diff options
author | Martin Aeschlimann | 2006-01-29 22:11:47 +0000 |
---|---|---|
committer | Martin Aeschlimann | 2006-01-29 22:11:47 +0000 |
commit | e1b034b769699f23e8dc54b36123c2d6d85c9fd9 (patch) | |
tree | b8bd0055685d1eef7300d7685ed09ce054849a2a | |
parent | 5f4eb5798f495065281cd1291605621f3d7f6cdf (diff) | |
download | eclipse.platform.text-e1b034b769699f23e8dc54b36123c2d6d85c9fd9.tar.gz eclipse.platform.text-e1b034b769699f23e8dc54b36123c2d6d85c9fd9.tar.xz eclipse.platform.text-e1b034b769699f23e8dc54b36123c2d6d85c9fd9.zip |
118200 Proposal for a new TextSearch UI
68 files changed, 8329 insertions, 246 deletions
diff --git a/org.eclipse.search/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.search/.settings/org.eclipse.jdt.core.prefs index 9c05f6773d2..7bb8267ac19 100644 --- a/org.eclipse.search/.settings/org.eclipse.jdt.core.prefs +++ b/org.eclipse.search/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,4 @@ -#Sun Oct 09 00:33:35 CEST 2005
+#Sun Jan 29 20:07:41 CET 2006
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
@@ -66,5 +66,249 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disa org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.3
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=20
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=66
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=0
+org.eclipse.jdt.core.formatter.blank_lines_after_package=0
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=0
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=0
+org.eclipse.jdt.core.formatter.blank_lines_before_method=0
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=0
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=0
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.format_comments=false
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=999
+org.eclipse.jdt.core.formatter.compact_else_if=false
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=999
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=2
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/org.eclipse.search/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.search/.settings/org.eclipse.jdt.ui.prefs index be033ab315d..06084349bb2 100644 --- a/org.eclipse.search/.settings/org.eclipse.jdt.ui.prefs +++ b/org.eclipse.search/.settings/org.eclipse.jdt.ui.prefs @@ -1,5 +1,7 @@ -#Tue Dec 21 12:50:24 CET 2004 +#Sun Jan 29 19:31:13 CET 2006 eclipse.preferences.version=1 -org.eclipse.jdt.ui.ondemandthreshold=99 +formatter_profile=_Search Code Style Conventions +formatter_settings_version=9 org.eclipse.jdt.ui.ignorelowercasenames=true org.eclipse.jdt.ui.importorder=java;javax;org.eclipse.core;org.eclipse.core.runtime;org.eclipse.core.resources;org.eclipse.swt;org.eclipse.jface;org.eclipse.jface.text;org.eclipse.ui;org.eclipse.ui.editors;org.eclipse.ui.workbench;org.eclipse.ui.workbench.texteditor;org.eclipseui.ide;org.eclipse.search.ui;org.eclipse.search.internal;org.eclipse.search2.internal; +org.eclipse.jdt.ui.ondemandthreshold=99 diff --git a/org.eclipse.search/META-INF/MANIFEST.MF b/org.eclipse.search/META-INF/MANIFEST.MF index 52c51c684ba..3d0c433807d 100644 --- a/org.eclipse.search/META-INF/MANIFEST.MF +++ b/org.eclipse.search/META-INF/MANIFEST.MF @@ -12,15 +12,18 @@ Export-Package: org.eclipse.search.core.text, org.eclipse.search.internal.ui.text;x-internal:=true, org.eclipse.search.internal.ui.util;x-internal:=true, org.eclipse.search.ui, + org.eclipse.search.ui.actions, org.eclipse.search.ui.text, org.eclipse.search2.internal.ui;x-internal:=true, org.eclipse.search2.internal.ui.basic.views;x-internal:=true, - org.eclipse.search2.internal.ui.text;x-internal:=true + org.eclipse.search2.internal.ui.text;x-internal:=true, + org.eclipse.search2.internal.ui.text2;x-internal:=true Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.resources, org.eclipse.ui, org.eclipse.ui.ide, org.eclipse.ui.workbench.texteditor, org.eclipse.jface.text, - org.eclipse.ui.editors + org.eclipse.ui.editors, + org.eclipse.ui.forms Eclipse-LazyStart: true diff --git a/org.eclipse.search/icons/full/dlcl16/filter_ps.gif b/org.eclipse.search/icons/full/dlcl16/filter_ps.gif Binary files differnew file mode 100644 index 00000000000..ba6d891495f --- /dev/null +++ b/org.eclipse.search/icons/full/dlcl16/filter_ps.gif diff --git a/org.eclipse.search/icons/full/elcl16/filter_ps.gif b/org.eclipse.search/icons/full/elcl16/filter_ps.gif Binary files differnew file mode 100644 index 00000000000..6fe6f0e10a1 --- /dev/null +++ b/org.eclipse.search/icons/full/elcl16/filter_ps.gif diff --git a/org.eclipse.search/icons/full/obj16/line_match.gif b/org.eclipse.search/icons/full/obj16/line_match.gif Binary files differnew file mode 100644 index 00000000000..cf62b63ae3e --- /dev/null +++ b/org.eclipse.search/icons/full/obj16/line_match.gif diff --git a/org.eclipse.search/new search/org/eclipse/search/core/text/AbstractTextFileScanner.java b/org.eclipse.search/new search/org/eclipse/search/core/text/AbstractTextFileScanner.java new file mode 100644 index 00000000000..24b82f3ca7c --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search/core/text/AbstractTextFileScanner.java @@ -0,0 +1,213 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search.core.text; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.eclipse.core.resources.IFile; + +/** + * Abstract base class for scanners supplied via the + * org.eclipse.search.textFileScanner extension point. + * It suffices to implement the scanFile() method. + */ +public abstract class AbstractTextFileScanner { + public final static int LOCATION_OTHER= 0; + public final static int LOCATION_STRING_LITERAL= 1; + public final static int LOCATION_COMMENT= 2; + public final static int LOCATION_IMPORT_OR_INCLUDE_STATEMENT= 3; + public final static int LOCATION_PREPROCESSOR_DIRECTIVE= 4; + public final static int LOCATION_FUNCTION= 5; + + /** + * LocationInfo objects are used to report information about matches. + */ + public final static class LineInformation { + private int fLineNumber; + private int fLineOffset; + private int fLineLength; + + public LineInformation(int lineNumber, int lineOffset, int lineLength) { + fLineNumber= lineNumber; + fLineOffset= lineOffset; + fLineLength= lineLength; + } + + /** + * @return the line number where the match starts in. + */ + public int getLineNumber() { + return fLineNumber; + } + + /** + * Returns the total length of the lines containing the match. This also includes + * the characters of the line terminator. + * @return the length of the lines containing the match. + * */ + public int getLineLength() { + return fLineLength; + } + + /** + * The character offset of the beginning of the line where the match starts. + * */ + public int getLineOffset() { + return fLineOffset; + } + } + + private static class Location { + public Location(int offset, int length, int kind) { + fOffset= offset; + fLength= length; + fKind= kind; + } + private int fOffset; + private int fLength; + private int fKind; + } + + private ArrayList fLocations= new ArrayList(); + private int[] fLineOffsets= null; + private int fLineCount; + private IFile fFile; + private int fFileLength; + + /** + * Clears any data cached by the scanner. + * Implementors may override this method but must call super.reset(); + */ + public void reset() { + fFile= null; + fLocations.clear(); + fLineOffsets= null; + fLineCount= 0; + } + + /** + * Called whenever information about a new file is requested. Implementors must + * scan the file and report lines and locations with addLineOffset() and addLocation(). + * @param matchAccess provides access to the file to be scanned. + */ + abstract protected void scanFile(TextSearchMatchAccess matchAccess); + + private void checkScanFile(TextSearchMatchAccess match) { + if (!match.getFile().equals(fFile)) { + reset(); + scanFile(match); + + // trim line count + if (fLineCount != 0) { + int[] offsets= new int[fLineCount]; + System.arraycopy(fLineOffsets, 0, offsets, 0, fLineCount); + fLineOffsets= offsets; + } + fFile= match.getFile(); + fFileLength= match.getFileContentLength(); + } + } + + /** + * Adds the offset of another line to the list of offsets. + * Call this method for every line when scanning a file. The first offset that has to + * be reported is always 0. + */ + final protected void addLineOffset(int offset) { + if (fLineCount == 0) { + fLineOffsets= new int[1024]; + } else + if (fLineCount == fLineOffsets.length) { + int[] newOffsets= new int[fLineOffsets.length * 2]; + System.arraycopy(fLineOffsets, 0, newOffsets, 0, fLineCount); + fLineOffsets= newOffsets; + } + fLineOffsets[fLineCount++]= offset; + } + + /** + * Adds the location to the list of offsets. + * Call this method for every location when scanning a file. + */ + final protected void addLocation(int offset, int length, int kind) { + fLocations.add(new Location(offset, length, kind)); + } + + /** + * Returns information about the lines containing the match provided. + * @param match access to the match. + * @return information about the provided match. + */ + public LineInformation getLineInformation(TextSearchMatchAccess match) { + // check if we need to scan another file + checkScanFile(match); + return getLineInformation(match.getMatchOffset(), match.getMatchLength()); + } + + private LineInformation getLineInformation(int offset, int length) { + if (fLineOffsets != null) { + final int lineIdx= getLineIndexForOffset(offset); + final int lineOffset= fLineOffsets[lineIdx]; + + int endLineIdx= getLineIndexForOffset(offset + length - 1); + int lineLength; + if (endLineIdx < fLineOffsets.length - 1) { + lineLength= fLineOffsets[endLineIdx + 1] - lineOffset; + } else { + lineLength= fFileLength - lineOffset; + } + return new LineInformation(lineIdx + 1, lineOffset, lineLength); + } + return new LineInformation(0, 0, 0); + } + + private int getLineIndexForOffset(int offset) { + int lineIdx= Arrays.binarySearch(fLineOffsets, offset); + if (lineIdx < 0) { + lineIdx= Math.max(0, -lineIdx - 2); + } + return lineIdx; + } + + /** + * Returns the kind of location the given match starts in. + * @param match access to the match. + * @return one of LOCATION_... + */ + public int getLocationKind(TextSearchMatchAccess match) { + checkScanFile(match); + return getLocationKind(match.getMatchOffset()); + } + + private int getLocationKind(int offset) { + int low= 0; + int high= fLocations.size() - 1; + + while (low <= high) { + int mid= (low + high) / 2; + Location loc= (Location) fLocations.get(mid); + int locOffset= loc.fOffset; + if (offset >= locOffset) { + if (offset < locOffset + loc.fLength) { + return loc.fKind; + } + // offset is larger + low= mid + 1; + } else { + // offset is smaller + high= mid - 1; + } + } + return 0; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search/core/text/TextSearchEngine.java b/org.eclipse.search/new search/org/eclipse/search/core/text/TextSearchEngine.java index 66ecd561062..4c10b7890b5 100644 --- a/org.eclipse.search/new search/org/eclipse/search/core/text/TextSearchEngine.java +++ b/org.eclipse.search/new search/org/eclipse/search/core/text/TextSearchEngine.java @@ -11,13 +11,14 @@ package org.eclipse.search.core.text; +import java.util.Comparator; import java.util.regex.Pattern; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; - import org.eclipse.search.internal.core.text.TextSearchVisitor; +import org.eclipse.search.internal.ui.SearchPlugin; /** * A {@link TextSearchEngine} searches the content of a workspace file resources @@ -37,8 +38,7 @@ public abstract class TextSearchEngine { * @return the created {@link TextSearchEngine}. */ public static TextSearchEngine create() { - // TODO: An future extension point will allow to contribute a new text search engine - return createDefault(); + return SearchPlugin.getDefault().getTextSearchEngineRegistry().getPreferred(); } /** @@ -50,10 +50,12 @@ public abstract class TextSearchEngine { public static TextSearchEngine createDefault() { return new TextSearchEngine() { public IStatus search(TextSearchScope scope, TextSearchRequestor requestor, Pattern searchPattern, IProgressMonitor monitor) { - return TextSearchVisitor.search(scope, requestor, searchPattern, monitor); + return new TextSearchVisitor(requestor, searchPattern, monitor).search(scope, getSearchOrderHint()); } }; } + + private Comparator fSearchOrderHint; /** * Uses a given search pattern to find matches in the content of a workspace file resource. If the file is open in an editor, the @@ -66,5 +68,28 @@ public abstract class TextSearchEngine { * @return the status containing information about problems in resources searched. */ public abstract IStatus search(TextSearchScope scope, TextSearchRequestor requestor, Pattern searchPattern, IProgressMonitor monitor); - + + /** + * Sets a comparator to be used by the search engine to order the files before searching them. + * The passed comparator will be used with instances of type {@link org.eclipse.core.resources.IFile}. + * The comparator on serves as a hint: The search engine is free to ignore the comparator and + * search the files in any order. + * + * @param comparator a comparator that is capable of comparing instances of type {@link org.eclipse.core.resources.IFile} + * or <code>null</code> not not provide a hint for the search order. + */ + public void setSearchOrderHint(Comparator comparator) { + fSearchOrderHint= comparator; + } + + /** + * Returns the comparator provided to give a hint of the order the search result should be provided. <code>null</code> + * is returned if no such order has been configured with {@link #setSearchOrderHint(Comparator)}. + * + * @return the comparator that can be used to order the files before searching, or + * <code>null</code> if no order hint has been configured. + */ + protected Comparator getSearchOrderHint() { + return fSearchOrderHint; + } } diff --git a/org.eclipse.search/new search/org/eclipse/search/ui/actions/TextSearchGroup.java b/org.eclipse.search/new search/org/eclipse/search/ui/actions/TextSearchGroup.java new file mode 100644 index 00000000000..79bec523702 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search/ui/actions/TextSearchGroup.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search.ui.actions; + +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; + +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.actions.ActionGroup; +import org.eclipse.ui.texteditor.ITextEditorActionConstants; + +import org.eclipse.search.ui.IContextMenuConstants; + +import org.eclipse.search2.internal.ui.SearchMessages; +import org.eclipse.search2.internal.ui.text2.FindInFileActionDelegate; +import org.eclipse.search2.internal.ui.text2.FindInProjectActionDelegate; +import org.eclipse.search2.internal.ui.text2.FindInRecentScopeActionDelegate; +import org.eclipse.search2.internal.ui.text2.FindInWorkingSetActionDelegate; +import org.eclipse.search2.internal.ui.text2.FindInWorkspaceActionDelegate; + +/** + * Action group that adds a sub-menu with text search actions to a context menu. + * to a context menu. + * + * @since 3.2 + */ +public class TextSearchGroup extends ActionGroup { + private String fAppendToGroup= ITextEditorActionConstants.GROUP_FIND; + private String fMenuText= SearchMessages.TextSearchGroup_submenu_text; + + private FindInRecentScopeActionDelegate[] fActions; + + /** + * Constructs a TextSearchGroup for adding actions to the context menu + * of the editor provided. The editor will be accessed for the purpose of + * determining the search string. + */ + public TextSearchGroup(IEditorPart editor) { + createActions(editor); + } + + /** + * Changes the text that is used for the submenu. The default is + * "Find Text". + */ + public void setMenuText(String text) { + fMenuText= text; + } + + /** + * Changes the group where the submenu is appended to. The default is + * ITextEditorActionConstants.GROUP_FIND. + */ + public void setAppendToGroup(String groupID) { + fAppendToGroup= groupID; + } + + private void createActions(IEditorPart editor) { + fActions= new FindInRecentScopeActionDelegate[] {new FindInRecentScopeActionDelegate(), new FindInWorkspaceActionDelegate(), new FindInProjectActionDelegate(), new FindInFileActionDelegate(), new FindInWorkingSetActionDelegate()}; + for (int i= 0; i < fActions.length; i++) { + FindInRecentScopeActionDelegate action= fActions[i]; + action.setActiveEditor(action, editor); + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.actions.ActionGroup#fillContextMenu(org.eclipse.jface.action.IMenuManager) + */ + public void fillContextMenu(IMenuManager menu) { + MenuManager textSearchMM= new MenuManager(fMenuText, IContextMenuConstants.GROUP_SEARCH); + textSearchMM.add(fActions[0]); + textSearchMM.add(new Separator()); + for (int i= 1; i < fActions.length; i++) { + textSearchMM.add(fActions[i]); + } + + menu.appendToGroup(fAppendToGroup, textSearchMM); + } + +} diff --git a/org.eclipse.search/new search/org/eclipse/search/ui/text/AbstractTextSearchViewPage.java b/org.eclipse.search/new search/org/eclipse/search/ui/text/AbstractTextSearchViewPage.java index e14796a4141..2b5831259b7 100644 --- a/org.eclipse.search/new search/org/eclipse/search/ui/text/AbstractTextSearchViewPage.java +++ b/org.eclipse.search/new search/org/eclipse/search/ui/text/AbstractTextSearchViewPage.java @@ -135,6 +135,14 @@ public abstract class AbstractTextSearchViewPage extends Page implements ISearch } else { fIsUIUpdateScheduled= false; turnOnDecoration(); + updateBusyLabel(); + if (fScheduleEnsureSelection) { + fScheduleEnsureSelection= false; + AbstractTextSearchResult result = getInput(); + if (result != null && fViewer.getSelection().isEmpty()) { + navigateNext(true); + } + } } fViewPart.updateLabel(); return Status.OK_STATUS; @@ -179,7 +187,8 @@ public abstract class AbstractTextSearchViewPage extends Page implements ISearch } - private transient boolean fIsUIUpdateScheduled= false; + private volatile boolean fIsUIUpdateScheduled= false; + private volatile boolean fScheduleEnsureSelection= false; private static final String KEY_LAYOUT = "org.eclipse.search.resultpage.layout"; //$NON-NLS-1$ /** @@ -516,25 +525,19 @@ public abstract class AbstractTextSearchViewPage extends Page implements ISearch } public void queryFinished(final ISearchQuery query) { - final Runnable runnable2 = new Runnable() { - public void run() { - updateBusyLabel(); - AbstractTextSearchResult result = getInput(); - - if (result == null || !result.getQuery().equals(query)) { - return; - } - - if (fViewer.getSelection().isEmpty()) { - navigateNext(true); - } - } - }; - asyncExec(runnable2); + // handle the end of the query in the UIUpdateJob, as ui updates + // may not be finished here. + postEnsureSelection(); } }; } + protected void postEnsureSelection() { + fScheduleEnsureSelection= true; + scheduleUIUpdate(); + } + + private void updateBusyLabel() { AbstractTextSearchResult result = getInput(); boolean shouldShowBusy = result != null && NewSearchUI.isQueryRunning(result.getQuery()) && result.getMatchCount() == 0; @@ -812,10 +815,11 @@ public abstract class AbstractTextSearchViewPage extends Page implements ISearch Match nextMatch = getCurrentMatch(); if (nextMatch == null) { navigateNext(false); - fCurrentMatchIndex = getInput().getMatchCount(getFirstSelectedElement()) - 1; + fCurrentMatchIndex = getDisplayedMatchCount(getFirstSelectedElement()) - 1; } showCurrentMatch(activateEditor); } + private void navigateNext(boolean forward) { INavigate navigator = null; if (fViewer instanceof TableViewer) { diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/SearchMessages.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/SearchMessages.java index 6b6ca8e4e25..5dde62d0c44 100644 --- a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/SearchMessages.java +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/SearchMessages.java @@ -19,6 +19,10 @@ public final class SearchMessages extends NLS { private SearchMessages() { // Do not instantiate } + + static { + NLS.initializeMessages(BUNDLE_NAME, SearchMessages.class); + } public static String AbstractTextSearchViewPage_update_job_name; public static String RemoveSelectedMatchesAction_label; @@ -79,14 +83,94 @@ public final class SearchMessages extends NLS { public static String AnnotationHighlighter_error_badLocation; public static String AnnotationHighlighter_error_noDocument; public static String EditorAccessHighlighter_error_badLocation; - - static { - NLS.initializeMessages(BUNDLE_NAME, SearchMessages.class); - } - public static String SearchHistoryDropDownAction_showemptyview_title; public static String SearchHistoryDropDownAction_showemptyview_tooltip; public static String PinSearchViewAction_label; public static String PinSearchViewAction_tooltip; public static String SearchPageRegistry_error_creating_extensionpoint; + public static String RetrieverFindTab_search; + public static String RetrieverFindTab_caseSensitive; + public static String RetrieverFindTab_regularExpression; + public static String RetrieverFindTab_wholeWord; + public static String RetrieverFindTab_searchScope; + public static String RetrieverFindTab_choose; + public static String RetrieverFindTab_filePatterns; + public static String RetrieverFindTab_Error_emptySearchString; + public static String RetrieverFindTab_Error_invalidRegex; + public static String RetrieverFindTab_Question_regexMatchesEmptyString; + public static String RetrieverQuery_label; + public static String RetrieverResult_label; + public static String RetrieverResult_noInput_label; + public static String FilePatternSelectionDialog_title; + public static String FilePatternSelectionDialog_message; + public static String FilePatternSelectionDialog_selectAll; + public static String FilePatternSelectionDialog_deselectAll; + public static String WorkspaceScopeDescription_label; + public static String RetrieverFilterTab_LocationFilter_text; + public static String RetrieverFilterTab_Comment_text; + public static String RetrieverFilterTab_Import_text; + public static String RetrieverFilterTab_Preprocessor_text; + public static String RetrieverFilterTab_String_text; + public static String RetrieverFilterTab_OtherLocation_text; + public static String RetrieverFilterTab_TextFilter_text; + public static String RetrieverFilterTab_HideMatching_text; + public static String WindowWorkingSetScopeDescription_label; + public static String RetrieverReplaceTab_ReplaceWith_label; + public static String RetrieverReplaceTab_Find_text; + public static String RetrieverReplaceTab_ReplaceFind_text; + public static String RetrieverReplaceTab_RestoreFind_text; + public static String RetrieverReplaceTab_Replace_text; + public static String RetrieverReplaceTab_ReplaceAll_text; + public static String RetrieverReplaceTab_RestoreAll_text; + public static String RetrieverReplaceTab_Preview_label; + public static String RetrieverReplaceTab_Restore_text; + public static String RetrieverReplaceTab_ReplaceWith_text; + public static String RetrieverLabelProvider_FilterHidesMatches_label; + public static String RetrieverFilterTab_FunctionBody_text; + public static String RetrieverPage_FindTab_text; + public static String RetrieverPage_FilterTab_text; + public static String RetrieverPage_ReplaceTab_text; + public static String RetrieverPage_EnableFilter_text; + public static String RetrieverPage_EnableFilter_tooltip; + public static String RetrieverPage_LoadQuery_text; + public static String RetrieverPage_LoadQuery_tooltip; + public static String RetrieverPage_SaveQuery_text; + public static String RetrieverPage_SaveQuery_tooltip; + public static String RetrieverPage_CreateWorkingSet_text; + public static String RetrieverPage_CreateWorkingSet_tooltip; + public static String RetrieverPage_CaseSensitiveFilePatterns_text; + public static String RetrieverPage_error_noResourcesForWorkingSet; + public static String RetrieverPage_CreateWorkingsetDialog_title; + public static String RetrieverPage_CreateWorkingSetDialog_description; + public static String RetrieverPage_question_overwriteWorkingSet; + public static String RetrieverPage_error_cannotLoadQuery; + public static String RetrieverPage_error_cannotStoreQuery; + public static String RetrieverPage_ErrorDialog_title; + public static String RetrieverPage_QuestionDialog_title; + public static String RetrieverPage_InformationDialog_title; + public static String RetrieverPage_ConsiderDerived_text; + public static String ReplaceOperation_error_cannotLocateMatch; + public static String ReplaceOperation_error_operationFailed; + public static String ReplaceOperation_task_performChanges; + public static String ReplaceOperation_error_didNotSucceedForAllMatches; + public static String ReplaceOperation_error_multipleErrors; + public static String ReplaceOperation_error_whileRefreshing; + public static String ReplaceOperation_error_whileValidateEdit; + public static String ReplaceOperation_error_allFilesReadOnly; + public static String ReplaceOperation_question_continueWithReadOnly_singular; + public static String ReplaceOperation_question_continueWithReadOnly_plural; + public static String ReplaceOperation_error_cannotComputeReplacement; + public static String ReplaceOperation_error_cannotLocateMatchAt; + public static String RetrieverReplaceTab_ReplaceSelected_text; + public static String RetrieverReplaceTab_RestoreSelected_text; + public static String TextFileScannerRegistry_error_instanciateScanner; + public static String CurrentFileScopeDescription_label; + public static String CurrentProjectScopeDescription_label; + public static String TextSearchGroup_submenu_text; + public static String FindInWorkspaceActionDelegate_text; + public static String FindInRecentScopeActionDelegate_text; + public static String FindInProjectActionDelegate_text; + public static String FindInWorkingSetActionDelegate_text; + public static String FindInFileActionDelegate_text; + }
\ No newline at end of file diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/SearchMessages.properties b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/SearchMessages.properties index 94564d08dc3..a71f940061d 100644 --- a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/SearchMessages.properties +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/SearchMessages.properties @@ -72,3 +72,87 @@ SearchHistoryDropDownAction_showemptyview_tooltip=Shows new {0} result SearchPageRegistry_error_creating_extensionpoint=Search result page creation failed PinSearchViewAction_label=Pi&n Search View PinSearchViewAction_tooltip=Pi&n the Search View +FilePatternSelectionDialog_deselectAll=Deselect All +FilePatternSelectionDialog_message=Select patterns for the files to be searched: +FindInWorkspaceActionDelegate_text=Workspace +FindInWorkingSetActionDelegate_text=Working Set... +FindInProjectActionDelegate_text=Project +FindInFileActionDelegate_text=File +FindInRecentScopeActionDelegate_text=Recent Scope +FilePatternSelectionDialog_selectAll=Select All +FilePatternSelectionDialog_title=Select File Patterns +RetrieverFilterTab_Comment_text=Comment +RetrieverFilterTab_FunctionBody_text=Function +RetrieverFilterTab_HideMatching_text=Hide matching +RetrieverFilterTab_Import_text=Import/Include +RetrieverFilterTab_LocationFilter_text=Restrict by location: +RetrieverFilterTab_OtherLocation_text=Any other +RetrieverFilterTab_Preprocessor_text=Preprocessor +RetrieverFilterTab_String_text=String +RetrieverFilterTab_TextFilter_text=Text filter: +RetrieverFindTab_caseSensitive=Case sensitive +RetrieverFindTab_choose=Choose... +RetrieverFindTab_Error_emptySearchString=Search string must not be empty. +ReplaceOperation_error_cannotLocateMatch=The match cannot be located +ReplaceOperation_error_whileValidateEdit=An error occurred while ensuring that files are writable +RetrieverFindTab_Error_invalidRegex=Invalid regular expression: +RetrieverFindTab_filePatterns=File patterns: +RetrieverFindTab_Question_regexMatchesEmptyString=The regular expression matches even an empty string, do you want to proceed? +ReplaceOperation_error_didNotSucceedForAllMatches=The operation did not succeed for all of the matches +RetrieverFindTab_regularExpression=Regular expression +RetrieverFindTab_search=Search +RetrieverFindTab_searchScope=Search scope: +RetrieverFindTab_wholeWord=Whole word +RetrieverLabelProvider_FilterHidesMatches_label=Filter hides {0} matches +ReplaceOperation_error_cannotComputeReplacement=Cannot compute replacement for match in {0} at line {1} +RetrieverPage_CaseSensitiveFilePatterns_text=Case Sensitive File Patterns +RetrieverPage_ConsiderDerived_text=Consider Derived Resources +RetrieverPage_CreateWorkingSet_text=Create Working Set... +RetrieverPage_CreateWorkingSet_tooltip=Create a working set off the search result +ReplaceOperation_error_operationFailed=The operation failed +ReplaceOperation_error_whileRefreshing=An error occurred while refreshing resources +RetrieverPage_CreateWorkingSetDialog_description=Specify a name for the working set: +RetrieverPage_CreateWorkingsetDialog_title=Create Working Set +RetrieverPage_EnableFilter_text=Enable Filter +RetrieverPage_EnableFilter_tooltip=Enables the filter for the current search result. +RetrieverPage_error_cannotLoadQuery=Cannot load query\! +RetrieverPage_error_cannotStoreQuery=Cannot store query\! +RetrieverPage_error_noResourcesForWorkingSet=There is no search result for creating a working set\! +RetrieverPage_ErrorDialog_title=Input Error +RetrieverPage_FilterTab_text=Filter +RetrieverPage_FindTab_text=Find +RetrieverPage_InformationDialog_title=Information +RetrieverPage_LoadQuery_text=Load Query... +RetrieverPage_LoadQuery_tooltip=Load a query +RetrieverPage_question_overwriteWorkingSet=Working set exists, do you want to overwrite it? +ReplaceOperation_error_cannotLocateMatchAt=Cannot locate match in {0} at line {1} +RetrieverPage_QuestionDialog_title=Question +RetrieverPage_ReplaceTab_text=Replace +RetrieverPage_SaveQuery_text=Save Query... +RetrieverPage_SaveQuery_tooltip=Save a query +RetrieverQuery_label=Retriever Query +RetrieverReplaceTab_Find_text=Find +RetrieverReplaceTab_Preview_label=Preview of replacement: +RetrieverReplaceTab_Replace_text=Replace +RetrieverReplaceTab_ReplaceAll_text=Replace All +RetrieverReplaceTab_ReplaceFind_text=Replace/Find +RetrieverReplaceTab_ReplaceWith_label=Replace with: +RetrieverReplaceTab_ReplaceSelected_text=Replace Selected +ReplaceOperation_error_multipleErrors=Multiple errors have occurred +RetrieverReplaceTab_ReplaceWith_text=Replace with ''{0}'' +RetrieverReplaceTab_Restore_text=Restore +RetrieverReplaceTab_RestoreAll_text=Restore All +RetrieverReplaceTab_RestoreFind_text=Restore/Find +RetrieverReplaceTab_RestoreSelected_text=Restore Selected +ReplaceOperation_task_performChanges=Performing changes +RetrieverResult_label=''{0}'' - {1} match(es) in {2} +RetrieverResult_noInput_label=Empty Text Search +WindowWorkingSetScopeDescription_label=Window working set +WorkspaceScopeDescription_label=Workspace +ReplaceOperation_error_allFilesReadOnly=Cannot apply changes, all files are read-only. +ReplaceOperation_question_continueWithReadOnly_singular=There is {0} read-only file, do you want to perform the rest of the changes? +ReplaceOperation_question_continueWithReadOnly_plural=There are {0} read-only files, do you want to perform the rest of the changes? +TextFileScannerRegistry_error_instanciateScanner=Cannot instantiate text file scanner +CurrentFileScopeDescription_label=Current file +CurrentProjectScopeDescription_label=Current project +TextSearchGroup_submenu_text=Find Text diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/CurrentFileScopeDescription.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/CurrentFileScopeDescription.java new file mode 100644 index 00000000000..c33da45da4a --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/CurrentFileScopeDescription.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.Properties; + +import org.eclipse.core.resources.IResource; + +import org.eclipse.jface.dialogs.IDialogSettings; + +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IWorkbenchPage; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class CurrentFileScopeDescription implements IScopeDescription { + + private static final IResource[] EMPTY_ARRAY= new IResource[0]; + + public CurrentFileScopeDescription() { + } + + public IResource[] getRoots(IWorkbenchPage page) { + IEditorPart editor= page.getActiveEditor(); + if (editor != null) { + IEditorInput ei= editor.getEditorInput(); + if (ei instanceof IFileEditorInput) { + IFileEditorInput fi= (IFileEditorInput) ei; + return new IResource[] {fi.getFile()}; + } + } + return EMPTY_ARRAY; + } + + public void store(IDialogSettings section) { + } + public void restore(IDialogSettings section) { + } + + public void store(Properties props, String prefix) { + } + public void restore(Properties props, String prefix) { + } + + public String getLabel() { + return SearchMessages.CurrentFileScopeDescription_label; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/CurrentProjectScopeDescription.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/CurrentProjectScopeDescription.java new file mode 100644 index 00000000000..673822171c9 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/CurrentProjectScopeDescription.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.Properties; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; + +import org.eclipse.jface.dialogs.IDialogSettings; + +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IWorkbenchPage; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class CurrentProjectScopeDescription implements IScopeDescription { + + private static final IResource[] EMPTY_ARRAY= new IResource[0]; + + public static IProject getCurrentProject(IWorkbenchPage page) { + IEditorPart editor= page.getActiveEditor(); + if (editor != null) { + IEditorInput ei= editor.getEditorInput(); + if (ei instanceof IFileEditorInput) { + IFileEditorInput fi= (IFileEditorInput) ei; + return fi.getFile().getProject(); + } + } + return null; + } + + public CurrentProjectScopeDescription() { + } + + public IResource[] getRoots(IWorkbenchPage page) { + IProject prj= getCurrentProject(page); + if (prj != null) { + return new IResource[] {prj}; + } + return EMPTY_ARRAY; + } + + public void store(IDialogSettings section) { + } + public void restore(IDialogSettings section) { + } + + public void store(Properties props, String prefix) { + } + public void restore(Properties props, String prefix) { + } + + public String getLabel() { + return SearchMessages.CurrentProjectScopeDescription_label; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/EditorDescriptorLabelProvider.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/EditorDescriptorLabelProvider.java new file mode 100644 index 00000000000..cfc38f0b833 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/EditorDescriptorLabelProvider.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.IEditorDescriptor; + +/** + * @author markus.schorn@windriver.com + */ +public class EditorDescriptorLabelProvider extends LabelProvider { + public final static EditorDescriptorLabelProvider INSTANCE= new EditorDescriptorLabelProvider(); + + private List imagesToDispose= new ArrayList(); + + private EditorDescriptorLabelProvider() { + super(); + } + + public void dispose() { + super.dispose(); + for (Iterator e= imagesToDispose.iterator(); e.hasNext();) { + ((Image) e.next()).dispose(); + } + imagesToDispose.clear(); + } + + public Image getColumnImage(Object element, int row) { + return getImage(element); + } + + public String getColumnText(Object element, int row) { + return getText(element); + } + + public Image getImage(Object element) { + if (element instanceof Map.Entry) { + Entry e= (Entry) element; + if (e.getValue() instanceof IEditorDescriptor) { + Image image= ((IEditorDescriptor) e.getValue()).getImageDescriptor().createImage(); + imagesToDispose.add(image); + return image; + } + } + return null; + } + + public String getText(Object element) { + if (element instanceof Map.Entry) { + Entry e= (Entry) element; + return e.getKey().toString(); + } + return null; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FilePatternSelectionDialog.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FilePatternSelectionDialog.java new file mode 100644 index 00000000000..da5dcaf2dd7 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FilePatternSelectionDialog.java @@ -0,0 +1,333 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.TreeMap; +import java.util.Map.Entry; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CheckboxTableViewer; + +import org.eclipse.ui.IEditorDescriptor; +import org.eclipse.ui.IEditorRegistry; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.SelectionDialog; + +import org.eclipse.search2.internal.ui.SearchMessages; + + +/** + * @author markus.schorn@windriver.com + */ +public class FilePatternSelectionDialog extends SelectionDialog { + static final String FILE_PATTERN_SEPERATOR= ","; //$NON-NLS-1$ + private final static int SIZING_SELECTION_WIDGET_HEIGHT= 250; + private final static int SIZING_SELECTION_WIDGET_WIDTH= 300; + + private String fInitialSelection; + private CheckboxTableViewer fListViewer; + private String fResult; + private Object[] fInput; + + + /** + * Creates a type selection dialog using the supplied entries. Set the + * initial selections to those whose extensions match the preselections. + */ + public FilePatternSelectionDialog(Shell parentShell, String string) { + super(parentShell); + setTitle(SearchMessages.FilePatternSelectionDialog_title); + fInitialSelection= string; + setMessage(SearchMessages.FilePatternSelectionDialog_message); + setShellStyle(getShellStyle() | SWT.RESIZE); + } + + /* + * (non-Javadoc) Method declared on Dialog. + */ + protected Control createDialogArea(Composite parent) { + // page group + Composite composite= (Composite) super.createDialogArea(parent); + createMessageArea(composite); + + fListViewer= CheckboxTableViewer.newCheckList(composite, SWT.BORDER); + GridData data= new GridData(GridData.FILL_BOTH); + data.heightHint= SIZING_SELECTION_WIDGET_HEIGHT; + data.widthHint= SIZING_SELECTION_WIDGET_WIDTH; + fListViewer.getTable().setLayoutData(data); + + fListViewer.setLabelProvider(EditorDescriptorLabelProvider.INSTANCE); + fListViewer.setContentProvider(new ArrayContentProvider()); + + addSelectionButtons(composite); + initializeViewer(fInitialSelection); + + applyDialogFont(composite); + return composite; + } + + /** + * Add the selection and deselection buttons to the dialog. + */ + private void addSelectionButtons(Composite composite) { + Composite buttonComposite= new Composite(composite, SWT.RIGHT); + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + buttonComposite.setLayout(layout); + GridData data= new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.GRAB_HORIZONTAL); + data.grabExcessHorizontalSpace= true; + composite.setData(data); + + Button selectButton= createButton(buttonComposite, IDialogConstants.SELECT_ALL_ID, SearchMessages.FilePatternSelectionDialog_selectAll, false); + + SelectionListener listener= new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + getListViewer().setAllChecked(true); + } + }; + selectButton.addSelectionListener(listener); + + Button deselectButton= createButton(buttonComposite, IDialogConstants.DESELECT_ALL_ID, SearchMessages.FilePatternSelectionDialog_deselectAll, false); + + listener= new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + getListViewer().setAllChecked(false); + + } + }; + deselectButton.addSelectionListener(listener); + } + + /* + * (non-Javadoc) Method declared in Window. + */ + protected void configureShell(Shell shell) { + super.configureShell(shell); + // IWorkbenchHelpSystem help= PlatformUI.getWorkbench().getHelpSystem(); + // help.setHelp(shell, IContextIDs.DIALOG_selectSymbol); + } + + /** + * Initializes this dialog's viewer after it has been laid out. + */ + private void initializeViewer(String initialSelection) { + IContentTypeManager ctm= Platform.getContentTypeManager(); + IContentType[] cts= ctm.getAllContentTypes(); + IContentType txtCt= ctm.getContentType(IContentTypeManager.CT_TEXT); + + HashMap editorToExtensions= new HashMap(); + for (int i= 0; i < cts.length; i++) { + IContentType ct= cts[i]; + if (ct.isKindOf(txtCt)) { + String[] exts= ct.getFileSpecs(IContentType.FILE_EXTENSION_SPEC); + String[] files= ct.getFileSpecs(IContentType.FILE_NAME_SPEC); + if (files.length > 30) { // ignore the c++ headers + files= new String[0]; + } + if (exts.length > 0 || files.length > 0) { + IEditorDescriptor editorDescriptor= searchForEditor(exts, files, ct); + HashSet patterns= (HashSet) editorToExtensions.get(editorDescriptor); + if (patterns == null) { + patterns= new HashSet(); + editorToExtensions.put(editorDescriptor, patterns); + } + + if (exts.length > 0) { + for (int j= 0; j < exts.length; j++) { + patterns.add("*." + exts[j]); //$NON-NLS-1$ + } + } + if (files.length > 0) { + for (int j= 0; j < files.length; j++) { + String file= files[j]; + int idx= file.lastIndexOf('.'); + if (idx >= 0) { + patterns.add("*" + file.substring(idx)); //$NON-NLS-1$ + } else { + patterns.add(file); + } + } + } + } + } + } + + // remove all subsets + HashMap oldMap= editorToExtensions; + editorToExtensions= new HashMap(); + for (Iterator iter= oldMap.entrySet().iterator(); iter.hasNext();) { + boolean ignore= false; + Entry entry= (Entry) iter.next(); + HashSet patterns= (HashSet) entry.getValue(); + for (Iterator iter2= editorToExtensions.values().iterator(); iter2.hasNext();) { + HashSet patterns2= (HashSet) iter2.next(); + if (patterns.size() <= patterns2.size()) { + if (patterns2.containsAll(patterns)) { + ignore= true; + } + } else { + if (patterns.containsAll(patterns2)) { + iter2.remove(); + } + } + } + if (!ignore) { + editorToExtensions.put(entry.getKey(), patterns); + } + } + + HashSet initialPatterns= new HashSet(); + HashSet remainingPatterns= new HashSet(); + if (initialPatterns != null) { + List helper= Arrays.asList(initialSelection.split(FILE_PATTERN_SEPERATOR)); + for (Iterator iter= helper.iterator(); iter.hasNext();) { + String element= (String) iter.next(); + element= element.trim(); + if (element.length() > 0) { + initialPatterns.add(element); + remainingPatterns.add(element); + } + } + } + final Comparator stringComparator= new Comparator() { + public int compare(Object arg0, Object arg1) { + String s1= (String) arg0; + String s2= (String) arg1; + int cmp= s1.compareToIgnoreCase(s2); + if (cmp == 0) { + cmp= -s1.compareTo(s2); + } + return cmp; + } + }; + TreeMap filePatterns= new TreeMap(stringComparator); + List checkmark= new ArrayList(); + for (Iterator iter= editorToExtensions.entrySet().iterator(); iter.hasNext();) { + Entry entry= (Entry) iter.next(); + Collection extensions= (Collection) entry.getValue(); + Object editor= entry.getKey(); + filePatterns.put(combineExtensions(extensions, stringComparator), editor); + if (initialPatterns.containsAll(extensions)) { + checkmark.add(editor); + remainingPatterns.removeAll(extensions); + } + } + + if (!remainingPatterns.isEmpty()) { + filePatterns.put(combineExtensions(remainingPatterns, stringComparator), null); + checkmark.add(null); + } + + fInput= filePatterns.entrySet().toArray(); + fListViewer.setInput(fInput); + for (int i= 0; i < fInput.length; i++) { + Entry element= (Entry) fInput[i]; + if (checkmark.contains(element.getValue())) { + fListViewer.setChecked(element, true); + } + } + } + + private IEditorDescriptor searchForEditor(String[] exts, String[] files, IContentType ct) { + IEditorRegistry reg= PlatformUI.getWorkbench().getEditorRegistry(); + + // try the extensions first + for (int i= 0; i < exts.length; i++) { + String ext= exts[i]; + String sample= "file." + ext; //$NON-NLS-1$ + IEditorDescriptor ed= reg.getDefaultEditor(sample, ct); + if (ed != null) { + return ed; + } + } + // next try files + for (int i= 0; i < files.length; i++) { + String file= files[i]; + IEditorDescriptor ed= reg.getDefaultEditor(file, ct); + if (ed != null) { + return ed; + } + } + + // give up + return null; + } + + private String combineExtensions(Collection input, Comparator comp) { + ArrayList extensions= new ArrayList(); + extensions.addAll(input); + Collections.sort(extensions, comp); + String last= null; + boolean needSep= false; + StringBuffer pattern= new StringBuffer(); + for (Iterator iterator= extensions.iterator(); iterator.hasNext();) { + String extension= (String) iterator.next(); + if (!extension.equals(last)) { + if (needSep) { + pattern.append(FILE_PATTERN_SEPERATOR); + } + needSep= true; + pattern.append(extension); + last= extension; + } + } + return pattern.toString(); + } + + protected void okPressed() { + // Get the input children. + List list= new ArrayList(); + for (int i= 0; i < fInput.length; ++i) { + Entry element= (Entry) fInput[i]; + if (fListViewer.getChecked(element)) { + String pattern= (String) element.getKey(); + list.addAll(Arrays.asList(pattern.split(FILE_PATTERN_SEPERATOR))); + } + } + setResult(list); + fResult= combineExtensions(list, String.CASE_INSENSITIVE_ORDER); + super.okPressed(); + } + + protected CheckboxTableViewer getListViewer() { + return fListViewer; + } + + public String getFilePatterns() { + return fResult; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FilterMatchEvent.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FilterMatchEvent.java new file mode 100644 index 00000000000..be0aac709bd --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FilterMatchEvent.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.search.ui.ISearchResult; +import org.eclipse.search.ui.text.Match; +import org.eclipse.search.ui.text.MatchEvent; + +public class FilterMatchEvent extends MatchEvent { + private static final long serialVersionUID= -4394594389515651137L; + public static final int FILTER_CHANGED= 3; + + public FilterMatchEvent(ISearchResult searchResult) { + super(searchResult); + setKind(FILTER_CHANGED); + } + + public void setMatches(Match[] matches) { + super.setMatches(matches); + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInFileActionDelegate.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInFileActionDelegate.java new file mode 100644 index 00000000000..318b2ae163c --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInFileActionDelegate.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.search2.internal.ui.SearchMessages; + + +public class FindInFileActionDelegate extends FindInRecentScopeActionDelegate { + + public FindInFileActionDelegate() { + super(SearchMessages.FindInFileActionDelegate_text); + } + + protected boolean modifyQuery(RetrieverQuery query) { + if (super.modifyQuery(query)) { + query.setSearchScope(new CurrentFileScopeDescription()); + return true; + } + return false; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInProjectActionDelegate.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInProjectActionDelegate.java new file mode 100644 index 00000000000..2c4f7d0a2b2 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInProjectActionDelegate.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class FindInProjectActionDelegate extends FindInRecentScopeActionDelegate { + + public FindInProjectActionDelegate() { + super(SearchMessages.FindInProjectActionDelegate_text); + } + + protected boolean modifyQuery(RetrieverQuery query) { + if (super.modifyQuery(query)) { + query.setSearchScope(new CurrentProjectScopeDescription()); + return true; + } + return false; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInRecentScopeActionDelegate.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInRecentScopeActionDelegate.java new file mode 100644 index 00000000000..b468fcb2de6 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInRecentScopeActionDelegate.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; + +import org.eclipse.ui.IEditorActionDelegate; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.texteditor.ITextEditor; + +import org.eclipse.search2.internal.ui.SearchMessages; + + +/** + * @author markus.schorn@windriver.com + */ +public class FindInRecentScopeActionDelegate extends RetrieverAction implements IWorkbenchWindowActionDelegate, IEditorActionDelegate { + private IWorkbenchWindow fWindow; + + public FindInRecentScopeActionDelegate() { + this(SearchMessages.FindInRecentScopeActionDelegate_text); + } + + public FindInRecentScopeActionDelegate(String text) { + setText(text); + } + + // IWorkbenchWindowActionDelegate + public void dispose() { + fWindow= null; + } + + // IWorkbenchWindowActionDelegate + public void init(IWorkbenchWindow window) { + fWindow= window; + } + + // IEditorActionDelegate + public void setActiveEditor(IAction action, IEditorPart targetEditor) { + if (targetEditor instanceof ITextEditor) { + fWindow= targetEditor.getSite().getWorkbenchWindow(); + } else { + fWindow= null; + } + } + + // IActionDelegate + public void selectionChanged(IAction action, ISelection selection) { + } + + // IActionDelegate + final public void run(IAction action) { + run(); + } + + // RetrieverAction + protected IWorkbenchPage getWorkbenchPage() { + if (fWindow != null) { + return fWindow.getActivePage(); + } + return null; + } + + protected boolean modifyQuery(RetrieverQuery query) { + IWorkbenchPage page= getWorkbenchPage(); + String searchFor= null; + if (page != null) { + searchFor= extractSearchTextFromSelection(page.getSelection()); + } + if (searchFor == null || searchFor.length() == 0) { + searchFor= extractSearchTextFromEditor(page.getActiveEditor()); + } + query.setSearchString(searchFor); + return true; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInWorkingSetActionDelegate.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInWorkingSetActionDelegate.java new file mode 100644 index 00000000000..bcf711d37a2 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInWorkingSetActionDelegate.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.ui.IWorkbenchPage; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class FindInWorkingSetActionDelegate extends FindInRecentScopeActionDelegate { + + public FindInWorkingSetActionDelegate() { + super(SearchMessages.FindInWorkingSetActionDelegate_text); + } + + protected boolean modifyQuery(RetrieverQuery query) { + if (super.modifyQuery(query)) { + IWorkbenchPage page= getWorkbenchPage(); + if (page != null) { + IScopeDescription scope= WorkingSetScopeDescription.createWithDialog(page, query.getScopeDescription()); + if (scope != null) { + query.setSearchScope(scope); + return true; + } + } + } + return false; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInWorkspaceActionDelegate.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInWorkspaceActionDelegate.java new file mode 100644 index 00000000000..1744de33db7 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/FindInWorkspaceActionDelegate.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class FindInWorkspaceActionDelegate extends FindInRecentScopeActionDelegate { + + public FindInWorkspaceActionDelegate() { + super(SearchMessages.FindInWorkspaceActionDelegate_text); + } + + protected boolean modifyQuery(RetrieverQuery query) { + if (super.modifyQuery(query)) { + query.setSearchScope(new WorkspaceScopeDescription()); + return true; + } + return false; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/IRetrieverKeys.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/IRetrieverKeys.java new file mode 100644 index 00000000000..5f9b449f4ba --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/IRetrieverKeys.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.search.core.text.AbstractTextFileScanner; + +interface IRetrieverKeys { + final String KEY_EXT_COMBO_CONTENT= ".combo"; //$NON-NLS-1$ + + final String KEY_SPLITTER_W1= "splitter.w1"; //$NON-NLS-1$ + final String KEY_SPLITTER_W2= "splitter.w2"; //$NON-NLS-1$ + + final String KEY_USE_FLAT_LAYOUT= "flat-layout"; //$NON-NLS-1$ + + final String KEY_CASE_SENSITIVE_SEARCH= "case-sensitive"; //$NON-NLS-1$ + final String KEY_REGULAR_EXPRESSION_SEARCH= "regular-expression"; //$NON-NLS-1$ + final String KEY_WHOLE_WORD= "whole-word"; //$NON-NLS-1$ + final String KEY_SEARCH_STRINGS= "search-string"; //$NON-NLS-1$ + + final String KEY_SEARCH_SCOPE= "search-scope"; //$NON-NLS-1$ + final String KEY_SCOPE_HISTORY= "scope-history"; //$NON-NLS-1$ + final String KEY_SCOPE_DESCRIPTOR_CLASS= "scope-descriptor-class"; //$NON-NLS-1$ + final String KEY_FILE_PATTERNS= "file-patterns"; //$NON-NLS-1$ + final String KEY_CONSIDER_DERIVED_RESOURCES= "consider-derived"; //$NON-NLS-1$ + final String KEY_USE_CASE_SENSITIVE_FILE_PATTERNS= "case-sensitive-file-patterns"; //$NON-NLS-1$ + + final String KEY_ENABLE_FILTER= "filter-action"; //$NON-NLS-1$ + final String KEY_ENABLE_LOCATION_FILTER= "use-location-filter"; //$NON-NLS-1$ + final String KEY_COMMENT_FILTER= "filter-comment"; //$NON-NLS-1$ + final String KEY_STRING_FILTER= "filter-string"; //$NON-NLS-1$ + final String KEY_INCLUDE_FILTER= "filter-include"; //$NON-NLS-1$ + final String KEY_PREP_FILTER= "filter-prep"; //$NON-NLS-1$ + final String KEY_FUNCTION_FILTER= "filter-function"; //$NON-NLS-1$ + final String KEY_ELSEWHERE_FILTER= "filter-elsewhere"; //$NON-NLS-1$ + + final String KEY_ENABLE_TEXT_FILTER= "use-filter-pattern"; //$NON-NLS-1$ + final String KEY_FILTER_PATTERNS= "filter-pattern"; //$NON-NLS-1$ + final String KEY_REGULAR_EXPRESSION_FILTER= "filter-regexp"; //$NON-NLS-1$ + final String KEY_INVERT_FILTER= "filter-invert"; //$NON-NLS-1$ + + final String KEY_REPLACEMENT_STRING= "replacement-string"; //$NON-NLS-1$ + + final int VISIBLE_ITEMS_IN_COMBO= 8; + + final int MAX_FILTER_PATTERNS= 8; + final int MAX_SEARCH_STRINGS= 8; + final int MAX_FILE_PATTERNS= 8; + final int MAX_SCOPES= 8; + final int MAX_REPLACEMENT_STRINGS= 8; + + final int MAX_COMBINED_LINE_LENGTH= 1024 * 8; + + final String SECTION_SCOPE= "scope"; //$NON-NLS-1$ + + final int ALL_LOCATIONS= (1 << AbstractTextFileScanner.LOCATION_OTHER) | (1 << AbstractTextFileScanner.LOCATION_COMMENT) | (1 << AbstractTextFileScanner.LOCATION_FUNCTION) | (1 << AbstractTextFileScanner.LOCATION_IMPORT_OR_INCLUDE_STATEMENT) | (1 << AbstractTextFileScanner.LOCATION_PREPROCESSOR_DIRECTIVE) | (1 << AbstractTextFileScanner.LOCATION_STRING_LITERAL); + +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/IScopeDescription.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/IScopeDescription.java new file mode 100644 index 00000000000..7fda6263c3a --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/IScopeDescription.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.Properties; + +import org.eclipse.core.resources.IResource; + +import org.eclipse.jface.dialogs.IDialogSettings; + +import org.eclipse.ui.IWorkbenchPage; + +/** + * Interface to handle various search scopes in the UI. + */ +public interface IScopeDescription { + + public String getLabel(); + + public IResource[] getRoots(IWorkbenchPage page); + + public void restore(IDialogSettings section); + + public void restore(Properties props, String keyPrefix); + + public void store(IDialogSettings section); + + public void store(Properties props, String keyPrefix); + +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/JavaScanner.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/JavaScanner.java new file mode 100644 index 00000000000..25abd4dc7d7 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/JavaScanner.java @@ -0,0 +1,219 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.search.core.text.AbstractTextFileScanner; +import org.eclipse.search.core.text.TextSearchMatchAccess; + +/** + * Scanner for java files, contributed via the org.eclipse.search.textFileScanner + * extension-point. + * Detects comments, string literals and import statements. + */ +public class JavaScanner extends AbstractTextFileScanner { + + private static final char[] IMPORT_CHARS= "import".toCharArray(); //$NON-NLS-1$ + private TextSearchMatchAccess fMatchAccess; + private int fOffset; + private int fLength; + + public JavaScanner() { + } + + protected void scanFile(TextSearchMatchAccess matchAccess) { + fMatchAccess= matchAccess; + fOffset= -1; + fLength= matchAccess.getFileContentLength(); + doScanFile(); + fMatchAccess= null; + } + + private void doScanFile() { + addLineOffset(0); + int c= nextChar(); + int offset; + while (c != -1) { + switch (c) { + case '"': + offset= fOffset; + c= matchStringLiteral(); + addLocation(offset, fOffset - offset, LOCATION_STRING_LITERAL); + break; + + case 'L': + if (peekChar() == '"') { + offset= fOffset; + nextChar(); + c= matchStringLiteral(); + addLocation(offset, fOffset - offset, LOCATION_STRING_LITERAL); + } else { + c= matchKeywordOrIdentifier((char) c); + } + break; + + case '\'': + c= matchCharacterLiteral(); + break; + + case '/': + offset= fOffset; + c= nextChar(); + switch (c) { + case '/': + c= matchSinglelineComment(); + addLocation(offset, fOffset - offset, LOCATION_COMMENT); + break; + + case '*': + c= matchMultilineComment(); + addLocation(offset, fOffset - offset, LOCATION_COMMENT); + break; + } + break; + + default: + if (Character.isJavaIdentifierStart((char) c)) { + c= matchKeywordOrIdentifier((char) c); + } else { + c= nextChar(); + } + break; + } + } + } + + private int matchMultilineComment() { + int c= nextChar(); + while (c != -1) { + if (c == '*') { + c= nextChar(); + if (c == '/') { + return nextChar(); + } + } else { + c= nextChar(); + } + } + return c; + } + + private int matchSinglelineComment() { + int c; + do { + c= nextChar(); + } while (c != '\n' && c != '\r' && c != -1); + if (c == '\r' && peekChar() == '\n') { + nextChar(); + } + return nextChar(); + } + + private int matchKeywordOrIdentifier(int c) { + int start= fOffset; + int importIdx= 0; + boolean isImport= c == IMPORT_CHARS[importIdx++]; + while (true) { + c= nextChar(); + if (c != -1 && Character.isJavaIdentifierPart((char) c)) { + if (isImport) { + if (importIdx == IMPORT_CHARS.length) { + isImport= false; + } else { + isImport= IMPORT_CHARS[importIdx++] == c; + } + } + } else { + break; + } + } + if (isImport) { + c= matchEndOfImport(c); + addLocation(start, fOffset - start, LOCATION_IMPORT_OR_INCLUDE_STATEMENT); + return c; + } + return c; + } + + private int matchEndOfImport(int c) { + while (c != ';' && c != -1) { + c= nextChar(); + } + return nextChar(); + } + + private int matchCharacterLiteral() { + boolean escaped= false; + while (true) { + switch (nextChar()) { + case -1: + return -1; + case '\\': + escaped= !escaped; + break; + case '\'': + case '\n': + case '\r': + if (!escaped) { + return nextChar(); + } + escaped= false; + break; + } + } + } + + private int matchStringLiteral() { + boolean escaped= false; + while (true) { + switch (nextChar()) { + case -1: + return -1; + case '\\': + escaped= !escaped; + break; + case '"': + case '\n': + case '\r': + if (!escaped) { + return nextChar(); + } + escaped= false; + break; + } + } + } + + private int peekChar() { + int offset= fOffset + 1; + if (offset >= fLength) { + return -1; + } + return fMatchAccess.getFileContentChar(offset); + } + + private int nextChar() { + if (++fOffset >= fLength) { + fOffset= fLength; + return -1; + } + char c= fMatchAccess.getFileContentChar(fOffset); + if (c == '\n') { + addLineOffset(fOffset + 1); + } else + if (c == '\r') { + if (peekChar() != '\n') { + addLineOffset(fOffset + 1); + } + } + return c; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/LineNumberScanner.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/LineNumberScanner.java new file mode 100644 index 00000000000..e47809356fb --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/LineNumberScanner.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.search.core.text.AbstractTextFileScanner; +import org.eclipse.search.core.text.TextSearchMatchAccess; + +/** + * The minimal scanner that figures out the line-numbers only. + */ +public class LineNumberScanner extends AbstractTextFileScanner { + public void scanFile(TextSearchMatchAccess matchAccess) { + int length= matchAccess.getFileContentLength(); + addLineOffset(0); + + boolean r= false; + for (int i= 0; i < length; i++) { + switch (matchAccess.getFileContentChar(i)) { + case '\r': + if (r) { + addLineOffset(i); + } + r= true; + break; + + case '\n': + addLineOffset(i + 1); + r= false; + break; + + default: + if (r) { + addLineOffset(i); + r= false; + } + } + } + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/ReplaceAction.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/ReplaceAction.java new file mode 100644 index 00000000000..49b97faef33 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/ReplaceAction.java @@ -0,0 +1,553 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.lang.reflect.InvocationTargetException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import org.eclipse.core.filebuffers.FileBuffers; +import org.eclipse.core.filebuffers.ITextFileBuffer; +import org.eclipse.core.filebuffers.ITextFileBufferManager; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.jobs.ISchedulingRule; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; + +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; + +import org.eclipse.ui.PlatformUI; + +import org.eclipse.search.internal.ui.SearchPlugin; +import org.eclipse.search.internal.ui.text.SearchAgainConfirmationDialog; + +import org.eclipse.search2.internal.ui.InternalSearchUI; +import org.eclipse.search2.internal.ui.Messages; +import org.eclipse.search2.internal.ui.SearchMessages; +import org.eclipse.search2.internal.ui.text.PositionTracker; + +/** + * Class to carry out replacement opertions. An instance may only be used once. + */ +public class ReplaceAction extends Action { + private RetrieverPage fView; + private Shell fShell; + private RetrieverResult fSearchResult; + private String fDialogTitle; + private boolean fSuccess; + private Pattern fPattern; + private String fReplacement; + private boolean fReplace; + private RetrieverMatch fMatch; + private HashSet fFileSet; + private Map fLineMap; + + /** + * Constructor to replace all matches + */ + public ReplaceAction(RetrieverPage retriever, String action, boolean replace) { + init(retriever, action, replace); + setupReplaceAll(); + } + + /** + * Constructor to replace a selection of matches + */ + public ReplaceAction(RetrieverPage retriever, String action, boolean replace, IStructuredSelection sel) { + init(retriever, action, replace); + setupReplaceSelection(sel); + } + + /** + * Constructor to replace a single match + */ + public ReplaceAction(RetrieverPage retriever, String action, boolean replace, RetrieverMatch match) { + init(retriever, action, replace); + fMatch= match; + } + + private void init(RetrieverPage retriever, String action, boolean replace) { + fView= retriever; + fSearchResult= (RetrieverResult) fView.getInput(); + fShell= fView.getSite().getShell(); + fDialogTitle= action; + fReplace= replace; + setText(action); + } + + private void setupReplaceAll() { + fFileSet= new HashSet(); + fLineMap= Collections.EMPTY_MAP; + Object[] lines= fSearchResult.getElements(); + for (int i= 0; i < lines.length; i++) { + RetrieverLine line= (RetrieverLine) lines[i]; + if (needsReplacement(line)) { + fFileSet.add(line.getParent()); + } + } + setEnabled(!fFileSet.isEmpty()); + } + + private boolean needsReplacement(RetrieverLine line) { + if (!line.isFiltered()) { + RetrieverMatch[] matches= line.getMatches(false); + for (int j= 0; j < matches.length; j++) { + RetrieverMatch match= matches[j]; + if (!match.isFiltered() && match.isReplaced() != fReplace) { + return true; + } + } + } + return false; + } + + private void setupReplaceSelection(IStructuredSelection sel) { + // collect resources and lines of selection + HashMap selectedResources= new HashMap(); + HashSet selectedLines= new HashSet(); + fFileSet= new HashSet(); + fLineMap= new HashMap(); + for (Iterator iter= sel.iterator(); iter.hasNext();) { + Object element= iter.next(); + if (element instanceof IResource) { + selectedResources.put(element, Boolean.TRUE); + } else + if (element instanceof RetrieverLine) { + selectedLines.add(element); + } + } + + Object[] allLines= fSearchResult.getElements(); + for (int i= 0; i < allLines.length; i++) { + RetrieverLine line= (RetrieverLine) allLines[i]; + if (needsReplacement(line)) { + IFile file= line.getParent(); + if (containsFile(selectedResources, file)) { + fFileSet.add(file); + } else + if (selectedLines.contains(line)) { + fFileSet.add(file); + addToLineMap(file, line); + } + } + } + setEnabled(!fFileSet.isEmpty()); + } + + private void addToLineMap(IFile file, RetrieverLine line) { + ArrayList lines= (ArrayList) fLineMap.get(file); + if (lines == null) { + lines= new ArrayList(); + fLineMap.put(file, lines); + } + lines.add(line); + } + + private boolean containsFile(HashMap resources, IFile file) { + return containsResource(resources, file).booleanValue(); + } + + private Boolean containsResource(HashMap resources, IResource res) { + Boolean result= (Boolean) resources.get(res); + if (result == null) { + IResource parent= res.getParent(); + result= parent == null ? Boolean.FALSE : containsResource(resources, parent); + resources.put(res, result); + } + return result; + } + + public void setReplacement(Pattern pattern, String replacement) { + fPattern= pattern; + fReplacement= replacement; + } + + public void run() { + fSuccess= false; + if (fSearchResult == null) { + return; + } + if (fReplace && (fPattern == null || fReplacement == null)) { + return; + } + + IWorkspace workspace= ResourcesPlugin.getWorkspace(); + ISchedulingRule rule= workspace.getRuleFactory().modifyRule(workspace.getRoot()); + + IRunnableWithProgress runnable= new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + fSuccess= doPerformReplace(monitor); + } + }; + + try { + PlatformUI.getWorkbench().getProgressService().runInUI(fView.getSite().getWorkbenchWindow(), runnable, rule); + } catch (InvocationTargetException e) { + SearchPlugin.log(e); + } catch (InterruptedException e) { + } + } + + protected boolean doPerformReplace(IProgressMonitor monitor) { + if (fMatch != null) { + return doPerformSingleReplace(monitor); + } else + if (fFileSet != null && fLineMap != null) { + return doPerformMultiReplace(monitor); + } + return false; + } + + private boolean doPerformSingleReplace(IProgressMonitor monitor) { + RetrieverMatch match= fMatch; + RetrieverLine line= match.getLine(); + IFile file= line.getParent(); + HashSet searchedAgain= new HashSet(); + if (!makeCommitable(Collections.singleton(file), searchedAgain)) { + return false; + } + if (searchedAgain.contains(file)) { + match= mapMatch(match); + } + if (match == null) { + MessageDialog.openError(fShell, fDialogTitle, SearchMessages.ReplaceOperation_error_cannotLocateMatch); + return false; + } + + ArrayList failures= new ArrayList(); + line= match.getLine(); + replaceInFile(monitor, line.getParent(), new RetrieverMatch[] {match}, failures); + if (!failures.isEmpty()) { + ErrorDialog.openError(fShell, fDialogTitle, SearchMessages.ReplaceOperation_error_operationFailed, (IStatus) failures.get(0)); + return false; + } + fView.getTreeViewer().refresh(line); + return true; + } + + private boolean doPerformMultiReplace(IProgressMonitor monitor) { + HashSet searchedAgain= new HashSet(); + if (!makeCommitable(fFileSet, searchedAgain)) { + return false; + } + + for (Iterator iter= searchedAgain.iterator(); iter.hasNext();) { + IFile file= (IFile) iter.next(); + ArrayList lines= (ArrayList) fLineMap.get(file); + if (lines != null) { + mapLines(file, lines); + } + } + + ArrayList failures= new ArrayList(); + monitor.beginTask(SearchMessages.ReplaceOperation_task_performChanges, fFileSet.size()); + try { + for (Iterator iter= fFileSet.iterator(); iter.hasNext();) { + IFile file= (IFile) iter.next(); + List lines= (List) fLineMap.get(file); + if (lines == null) { + lines= Arrays.asList(fSearchResult.getLinesForFile(file, false)); + } + ArrayList matches= new ArrayList(lines.size()); + for (Iterator iterator= lines.iterator(); iterator.hasNext();) { + RetrieverLine line= (RetrieverLine) iterator.next(); + if (line != null) { + matches.addAll(Arrays.asList(line.getDisplayedMatches())); + } + } + + replaceInFile(new SubProgressMonitor(monitor, 1), file, (RetrieverMatch[]) matches.toArray(new RetrieverMatch[matches.size()]), failures); + if (monitor.isCanceled()) { + return false; + } + } + } finally { + monitor.done(); + } + if (!failures.isEmpty()) { + handleFailures((IStatus[]) failures.toArray(new IStatus[failures.size()])); + return false; + } + + fView.getTreeViewer().refresh(); + return true; + } + + private void mapLines(IFile file, ArrayList lines) { + RetrieverLine[] newLines= fSearchResult.getLinesForFile(file, false); + for (int i= 0; i < lines.size(); i++) { + RetrieverLine line= (RetrieverLine) lines.get(i); + lines.set(i, findBestLine(line, newLines)); + } + } + + private RetrieverMatch mapMatch(RetrieverMatch match) { + RetrieverLine line= match.getLine(); + RetrieverLine[] newLines= fSearchResult.getLinesForFile(line.getParent(), false); + + RetrieverMatch bestMatch= null; + RetrieverLine bestLine= findBestLine(line, newLines); + if (bestLine != null) { + int col= match.getLineOffset(); + int nearest= Integer.MAX_VALUE; + RetrieverMatch[] candidates= bestLine.getDisplayedMatches(); + for (int i= 0; i < candidates.length; i++) { + RetrieverMatch candidate= candidates[i]; + if (!candidate.isFiltered() && candidate.getOriginal().equals(match.getOriginal())) { + int dist= Math.abs(candidate.getLineOffset() - col); + if (dist < nearest) { + dist= nearest; + bestMatch= candidate; + } + } + } + } + return bestMatch; + } + + private RetrieverLine findBestLine(RetrieverLine line, RetrieverLine[] newLines) { + // find the best line + String lineData= line.getLine().trim(); + int lineNumber= line.getLineNumber(); + int nearest= Integer.MAX_VALUE; + RetrieverLine best= null; + for (int i= 0; i < newLines.length; i++) { + RetrieverLine test= newLines[i]; + if (lineData.equals(test.getLine().trim())) { + int dist= Math.abs(test.getLineNumber() - lineNumber); + if (dist < nearest) { + dist= nearest; + best= test; + } + } + } + return best; + } + + private boolean handleFailures(IStatus[] stati) { + if (stati.length == 0) { + return true; + } + + String message= Messages.format(SearchMessages.ReplaceOperation_error_didNotSucceedForAllMatches, fDialogTitle); + if (stati.length == 1) { + ErrorDialog.openError(fShell, fDialogTitle, message, stati[0]); + } else { + MultiStatus mstatus= new MultiStatus(SearchPlugin.getID(), SearchPlugin.INTERNAL_ERROR, stati, SearchMessages.ReplaceOperation_error_multipleErrors, null); + ErrorDialog.openError(fShell, fDialogTitle, message, mstatus); + } + return false; + } + + private boolean makeCommitable(Collection files, HashSet searchedAgain) { + if (files.isEmpty()) { + return true; + } + + HashSet readOnly= new HashSet(); + for (Iterator iter= files.iterator(); iter.hasNext();) { + IFile file= (IFile) iter.next(); + if (!file.isSynchronized(IResource.DEPTH_ZERO)) { + if (!refreshFile(file)) { + return false; + } + searchedAgain.add(file); + } + if (file.isReadOnly()) { + readOnly.add(file); + } + } + + // try to make files writable + if (!validateEdit(readOnly)) { + return false; + } + + // check files if they are still read-only + int readOnlyCount= 0; + for (Iterator iter= readOnly.iterator(); iter.hasNext();) { + IFile rf= (IFile) iter.next(); + if (rf.isReadOnly()) { + searchedAgain.remove(rf); + readOnlyCount++; + } else { + searchedAgain.add(rf); + } + } + + // continue with all writable files? + if (!confirmParialReplacement(files.size(), readOnlyCount)) { + return false; + } + + if (!searchAgain(searchedAgain)) { + return false; + } + + return true; + } + + private boolean searchAgain(HashSet outdated) { + // don't attempt to research on a restore operation! + if (outdated.isEmpty() || !fReplace) { + return true; + } + SearchAgainConfirmationDialog dialog= new SearchAgainConfirmationDialog(fShell, (ILabelProvider) fView.getTreeViewer().getLabelProvider(), Collections.EMPTY_LIST, new ArrayList(outdated)); + if (dialog.open() != IDialogConstants.OK_ID) { + return false; + } + + fSearchResult.searchAgain(outdated); + return true; + } + + private boolean refreshFile(IFile file) { + try { + file.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor()); + } catch (CoreException e) { + ErrorDialog.openError(fShell, fDialogTitle, SearchMessages.ReplaceOperation_error_whileRefreshing, e.getStatus()); + return false; + } + return true; + } + + private boolean validateEdit(HashSet readOnly) { + if (!readOnly.isEmpty()) { + IStatus s= ResourcesPlugin.getWorkspace().validateEdit((IFile[]) readOnly.toArray(new IFile[readOnly.size()]), fShell); + if (s.getSeverity() != IStatus.OK) { + if (s.getSeverity() != IStatus.CANCEL && s.getCode() != IResourceStatus.READ_ONLY_LOCAL) { + ErrorDialog.openError(fShell, fDialogTitle, SearchMessages.ReplaceOperation_error_whileValidateEdit, s); + } + return false; + } + } + return true; + } + + private boolean confirmParialReplacement(int writableFiles, int readOnlyFiles) { + if (readOnlyFiles == 0) { + return true; + } + if (writableFiles == 0) { + MessageDialog.openError(fShell, fDialogTitle, SearchMessages.ReplaceOperation_error_allFilesReadOnly); + return false; + } + + String key= readOnlyFiles == 1 ? SearchMessages.ReplaceOperation_question_continueWithReadOnly_singular : SearchMessages.ReplaceOperation_question_continueWithReadOnly_plural; + + return MessageDialog.openQuestion(fShell, fDialogTitle, MessageFormat.format(key, new Object[] {new Integer(readOnlyFiles)})); + } + + private void replaceInFile(IProgressMonitor monitor, IFile file, RetrieverMatch[] matches, Collection failures) { + try { + if (file.isReadOnly()) { + return; + } + int ticks= 3; + monitor.beginTask(SearchMessages.ReplaceOperation_task_performChanges, ticks); + ITextFileBufferManager bm= FileBuffers.getTextFileBufferManager(); + try { + ticks--; + bm.connect(file.getFullPath(), new SubProgressMonitor(monitor, 1)); + if (monitor.isCanceled()) { + return; + } + ITextFileBuffer fb= bm.getTextFileBuffer(file.getFullPath()); + boolean wasDirty= fb.isDirty(); + IDocument doc= fb.getDocument(); + PositionTracker tracker= InternalSearchUI.getInstance().getPositionTracker(); + for (int i= 0; i < matches.length; i++) { + RetrieverMatch match= matches[i]; + if (!match.isFiltered() && (match.isReplaced() != fReplace)) { + int offset= match.getOffset(); + int length= match.getLength(); + Position currentPosition= tracker.getCurrentPosition(match); + if (currentPosition != null) { + offset= currentPosition.offset; + length= currentPosition.length; + } + String currentText= null; + try { + currentText= doc.get(offset, length); + } catch (BadLocationException e) { + } + if (currentText == null || !currentText.equals(match.getCurrentText())) { + failures.add(createErrorStatus(Messages.format(SearchMessages.ReplaceOperation_error_cannotLocateMatchAt, new Object[] {file.getFullPath(), new Integer(match.getLine().getLineNumber())}))); + } else { + String newText= fReplace ? match.computeReplacement(fPattern, fReplacement) : match.getOriginal(); + if (newText == null) { + failures.add(createErrorStatus(Messages.format(SearchMessages.ReplaceOperation_error_cannotComputeReplacement, new Object[] {file.getFullPath(), new Integer(match.getLine().getLineNumber())}))); + } else { + try { + doc.replace(offset, length, newText); + match.setReplacement(fReplace ? newText : null); + } catch (BadLocationException e) { + failures.add(createErrorStatus(Messages.format(SearchMessages.ReplaceOperation_error_cannotLocateMatchAt, new Object[] {file, new Integer(match.getLine().getLineNumber())}))); + } + } + } + } + } + if (!wasDirty) { + ticks--; + fb.commit(new SubProgressMonitor(monitor, 1), true); + } + } finally { + bm.disconnect(file.getFullPath(), new SubProgressMonitor(monitor, ticks)); + } + } catch (CoreException e) { + failures.add(e.getStatus()); + } finally { + monitor.done(); + } + } + + private Status createErrorStatus(String message) { + return new Status(IStatus.ERROR, SearchPlugin.getID(), SearchPlugin.INTERNAL_ERROR, message, null); + } + + public boolean wasSuccessful() { + return fSuccess; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverAction.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverAction.java new file mode 100644 index 00000000000..27e237b15c4 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverAction.java @@ -0,0 +1,195 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.TextSelection; + +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.texteditor.ITextEditor; + +import org.eclipse.search.ui.NewSearchUI; + +import org.eclipse.search2.internal.ui.InternalSearchUI; +import org.eclipse.search2.internal.ui.SearchView; + +abstract public class RetrieverAction extends Action { + public RetrieverAction() { + } + + public void run() { + IWorkbenchPage page= getWorkbenchPage(); + if (page == null) { + return; + } + + RetrieverQuery query= new RetrieverQuery(page); + RetrieverPage.initializeQuery(query); + if (modifyQuery(query)) { + String searchPattern= query.getSearchText(); + if (searchPattern == null || searchPattern.length() == 0) { + SearchView view= (SearchView) InternalSearchUI.getInstance().getSearchViewManager().activateSearchView(true); + view.showEmptySearchPage(RetrieverPage.ID); + } else { + NewSearchUI.runQueryInBackground(query); + } + } + } + + abstract protected boolean modifyQuery(RetrieverQuery query); + abstract protected IWorkbenchPage getWorkbenchPage(); + + final protected String extractSearchTextFromEditor(IEditorPart editor) { + if (editor != null) { + ITextSelection selection= null; + ISelectionProvider provider= editor.getEditorSite().getSelectionProvider(); + if (provider != null) { + ISelection s= provider.getSelection(); + if (s instanceof ITextSelection) { + selection= (ITextSelection) s; + } + } + + if (selection != null) { + if (selection.getLength() == 0) { + ITextEditor txtEditor= getTextEditor(editor); + if (txtEditor != null) { + IDocument document= txtEditor.getDocumentProvider().getDocument(txtEditor.getEditorInput()); + selection= expandSelection(selection, document, null); + } + } + + if (selection.getLength() > 0) { + return trimSearchString(selection.getText()); + } + } + } + return null; + } + + final protected String extractSearchTextFromSelection(ISelection sel) { + if (sel instanceof ITextSelection) { + return trimSearchString(((ITextSelection) sel).getText()); + } + return null; + } + + private String trimSearchString(String text) { + int idx= text.indexOf('\n'); + int idx2= text.indexOf('\r'); + if (idx2 >= 0 && idx2 < idx) { + idx= idx2; + } + if (idx >= 0) { + text= text.substring(0, idx); + } + return text.trim(); + } + + private ITextEditor getTextEditor(IEditorPart editor) { + if (editor instanceof ITextEditor) { + return (ITextEditor) editor; + } else + if (editor instanceof FormEditor) { + FormEditor me= (FormEditor) editor; + editor= me.getActiveEditor(); + if (editor instanceof ITextEditor) { + return (ITextEditor) editor; + } + } + return null; + } + + private ITextSelection expandSelection(ITextSelection sel, IDocument document, String stopChars) { + int offset= sel.getOffset(); + int length= sel.getLength(); + + // in case the length is zero we have to decide whether to go + // left or right. + if (length == 0) { + // try right + char chr= 0; + char chl= 0; + try { + chr= document.getChar(offset); + } catch (BadLocationException e2) { + } + try { + chl= document.getChar(offset - 1); + } catch (BadLocationException e2) { + } + + if (isPartOfIdentifier(chr)) { + length= 1; + } else + if (isPartOfIdentifier(chl)) { + offset--; + length= 1; + } else + if (stopChars != null && stopChars.indexOf(chr) == -1) { + length= 1; + } else + if (stopChars != null && stopChars.indexOf(chl) == -1) { + offset--; + length= 1; + } else { + return sel; + } + } + + int a= offset + length - 1; + int z= a; + + // move z one behind last character. + try { + char ch= document.getChar(z); + while (isValidChar(stopChars, ch)) { + ch= document.getChar(++z); + } + } catch (BadLocationException e2) { + } + // move a one before the first character + try { + char ch= document.getChar(a); + while (isValidChar(stopChars, ch)) { + ch= document.getChar(--a); + } + } catch (BadLocationException e2) { + } + + if (a == z) { + offset= a; + length= 0; + } else { + offset= a + 1; + length= z - a - 1; + } + return new TextSelection(document, offset, length); + } + + private boolean isValidChar(String stopChars, char ch) { + return stopChars == null ? isPartOfIdentifier(ch) : stopChars.indexOf(ch) == -1; + } + + private boolean isPartOfIdentifier(char ch) { + return Character.isLetterOrDigit(ch) || ch == '_'; + } + +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverContentProvider.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverContentProvider.java new file mode 100644 index 00000000000..889e2ee5148 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverContentProvider.java @@ -0,0 +1,302 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.Viewer; + +import org.eclipse.search.ui.text.AbstractTextSearchResult; + +import org.eclipse.search.internal.ui.text.IFileSearchContentProvider; + +public class RetrieverContentProvider implements ITreeContentProvider, IFileSearchContentProvider { + private static final Object[] EMPTY_ARR= new Object[0]; + private RetrieverResult fResult; + private RetrieverTreeViewer fTreeViewer; + private Map fChildrenMap; + private int[] fMatchCount; + private HashSet fAutoExpand= new HashSet(); + private boolean fFlatLayout; + + public RetrieverContentProvider(RetrieverTreeViewer viewer, boolean flatLayout) { + fTreeViewer= viewer; + fFlatLayout= flatLayout; + } + + public Object getParent(Object element) { + if (element instanceof RetrieverLine) { + return ((RetrieverLine) element).getParent(); + } + if (element instanceof IProject) { + return null; + } + if (element instanceof IResource) { + IResource resource= (IResource) element; + return fFlatLayout ? null : resource.getParent(); + } + return null; + } + + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + public void dispose() { + // nothing to do + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + if (newInput instanceof AbstractTextSearchResult) { + initialize((AbstractTextSearchResult) newInput); + } + } + + + protected synchronized void initialize(AbstractTextSearchResult result) { + fResult= (RetrieverResult) result; + fChildrenMap= new HashMap(); + fAutoExpand.clear(); + fMatchCount= null; + if (result != null) { + Object[] elements= result.getElements(); + for (int i= 0; i < elements.length; i++) { + Object element= elements[i]; + if (fResult.getDisplayedMatchCount(element) > 0) { + insert(element, false, null, null); + } + } + updateFilterItem(false, null, null); + } + } + + protected void insert(Object child, boolean refreshViewer, HashSet refreshElems, HashMap insertElems) { + Object parent= getParent(child); + Object dummyParent= parent; + if (parent == null) { + dummyParent= fResult; + } + + // add child to our childmap + if (insertInMap(dummyParent, child, fChildrenMap)) { + if (refreshViewer) { + insertInMap(dummyParent, child, insertElems); + } + if (parent != null) { + insert(parent, refreshViewer, refreshElems, insertElems); + } + } + } + + /** + * returns true if the child was added. + */ + private boolean insertInMap(Object parent, Object child, Map map) { + Set children= (Set) map.get(parent); + if (children == null) { + children= new HashSet(); + map.put(parent, children); + } + return children.add(child); + } + + protected void remove(Object element, boolean refreshViewer, HashSet refreshElems) { + // precondition here: fResult.getMatchCount(child) <= 0 + + if (hasChildren(element)) { + if (refreshViewer) { + refreshElems.add(element); + } + } else { + fChildrenMap.remove(element); + Object parent= getParent(element); + if (parent != null) { + if (removeFromSiblings(element, parent)) { + remove(parent, refreshViewer, refreshElems); + } + } else { + if (removeFromSiblings(element, fResult)) { + if (refreshViewer) { + refreshElems.add(fResult); + } + } + } + } + } + + private boolean removeFromSiblings(Object element, Object parent) { + Set siblings= (Set) fChildrenMap.get(parent); + if (siblings != null) { + return siblings.remove(element); + } + return false; + } + + public Object[] getChildren(Object parentElement) { + Set children= (Set) fChildrenMap.get(parentElement); + if (children == null) + return EMPTY_ARR; + return children.toArray(); + } + + public boolean hasChildren(Object element) { + return getChildren(element).length > 0; + } + + public synchronized void elementsChanged(final Object[] updatedElements) { + if (updatedElements.length == 0) { + return; + } + Runnable r= new Runnable() { + public void run() { + handeElementsChanged(updatedElements); + } + }; + fTreeViewer.preservingSelection(r); + } + + private void handeElementsChanged(final Object[] updatedElements) { + final HashSet refreshElems= new HashSet(); + final HashMap insertElems= new HashMap(); + updateFilterItem(true, refreshElems, insertElems); + for (int i= 0; i < updatedElements.length; i++) { + Object updatedElem= updatedElements[i]; + if (fResult.getDisplayedMatchCount(updatedElem) > 0) { + insert(updatedElem, true, refreshElems, insertElems); + } else { + remove(updatedElem, true, refreshElems); + } + } + if (refreshElems.contains(fResult)) { + fTreeViewer.refresh(); + } else { + for (Iterator iter= refreshElems.iterator(); iter.hasNext();) { + Object elem= iter.next(); + Object parent= getParent(elem); + if (!containsElemOrAParent(refreshElems, parent)) { + fTreeViewer.refresh(elem); + } + } + } + + Object[] insertParents= insertElems.keySet().toArray(); + for (int i= 0; i < insertParents.length; i++) { + Object element= insertParents[i]; + insertInView(element, refreshElems, insertElems); + } + } + + private void updateFilterItem(boolean updateViewer, final HashSet refreshElems, final HashMap insertElems) { + if (fResult != null) { + int[] matchCount= fResult.getDetailedMatchCount(); + if (matchCount[0] == matchCount[1]) { + if (fMatchCount != null) { + remove(fMatchCount, updateViewer, refreshElems); + fMatchCount= null; + } + } else { + if (fMatchCount != null) { + fMatchCount[0]= matchCount[0]; + fMatchCount[1]= matchCount[1]; + refreshElems.add(fMatchCount); + } else { + fMatchCount= matchCount; + insert(fMatchCount, updateViewer, refreshElems, insertElems); + } + } + } + } + + private boolean insertInView(Object element, HashSet refreshElems, HashMap insertElems) { + Object parent= getParent(element); + if (parent == null) { + parent= fResult; + } + Collection children= (Collection) insertElems.remove(element); + if (children == null) { + return !containsElemOrAParent(refreshElems, element); + } + + boolean needToInsert= true; + if (element != fResult) { + needToInsert= insertInView(parent, refreshElems, insertElems); + } + if (needToInsert) { + needToInsert= !refreshElems.contains(element); + } + if (needToInsert) { + fTreeViewer.add(element, children.toArray()); + } + if (fAutoExpand.contains(element)) { + fTreeViewer.setExpandedState(element, true); + } + return needToInsert; + } + + private boolean containsElemOrAParent(final HashSet set, Object elem) { + while (elem != null) { + if (set.contains(elem)) { + return true; + } + elem= getParent(elem); + } + return set.contains(fResult); + } + + public void clear() { + initialize(fResult); + fTreeViewer.refresh(); + } + + public AbstractTextSearchResult getResult() { + return fResult; + } + + public void onExpansionStateChange(Object element, boolean expanded) { + if (!expanded) { + fAutoExpand.remove(element); + } else { + fAutoExpand.add(element); + } + } + + public void setLayout(boolean flat) { + if (flat != fFlatLayout) { + fFlatLayout= flat; + initialize(fResult); + } + } + + // this works around the fact that expansion change is not reported when + // the selection is set via next/previous. + public void onSelectionChanged(SelectionChangedEvent event) { + IStructuredSelection sel= (IStructuredSelection) event.getSelection(); + Object element= sel.getFirstElement(); + if (element != null) { + element= getParent(element); + while (element != null && fAutoExpand.add(element)) { + element= getParent(element); + } + } + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverFilter.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverFilter.java new file mode 100644 index 00000000000..b34fab5ec63 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverFilter.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.regex.Pattern; + +import org.eclipse.search.internal.core.text.PatternConstructor; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class RetrieverFilter { + private static String sLastCauseForError; + private Pattern fFilterPattern; + private String fFilterText; + private int fAcceptedLocations; + private boolean fIsRegex; + private boolean fHideMatching; + private int fOriginatorsHash; + + public RetrieverFilter(RetrieverPage page, int acceptedLocations, String filterText, boolean isRegex, boolean hideMatching, int originatorsHash) { + + fOriginatorsHash= originatorsHash; + fFilterPattern= null; + fFilterText= null; + if (filterText != null) { + if (filterText.length() != 0) { + try { + fFilterPattern= PatternConstructor.createPattern(filterText, isRegex, false, false, false); + fFilterText= filterText; + } catch (Exception e) { + if (page != null && !filterText.equals(sLastCauseForError)) { + page.showError(SearchMessages.RetrieverFindTab_Error_invalidRegex + e.getMessage()); + } + } + sLastCauseForError= filterText; + } + } + fAcceptedLocations= acceptedLocations; + fIsRegex= isRegex; + fHideMatching= hideMatching; + } + + public RetrieverFilter() { + fAcceptedLocations= IRetrieverKeys.ALL_LOCATIONS; + } + + public int getOriginatorsHash() { + return fOriginatorsHash; + } + + public boolean getHideMatching() { + return fHideMatching; + } + + public int getAcceptedLocations() { + return fAcceptedLocations; + } + + public Pattern getPattern() { + return fFilterPattern; + } + + public boolean getIsRegex() { + return fIsRegex; + } + + public String getFilterString() { + return fFilterText; + } + +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverFilterTab.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverFilterTab.java new file mode 100644 index 00000000000..b801e12f19e --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverFilterTab.java @@ -0,0 +1,428 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.Properties; +import java.util.regex.Pattern; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; + +import org.eclipse.search.core.text.AbstractTextFileScanner; + +import org.eclipse.search2.internal.ui.SearchMessages; + +/** + * @author markus.schorn@windriver.com + */ +public class RetrieverFilterTab implements IRetrieverKeys { + private RetrieverPage fView; + + private boolean fEnable; + private boolean fEnableLocation; + private boolean fEnableString; + + private Button fUseLocationFilter; + private Button fCommentFilter; + private Button fStringFilter; + private Button fIncludeFilter; + private Button fPrepFilter; + private Button fFunctionFilter; + private Button fOtherFilter; + + private Button fUseStringFilter; + private Combo fFilterString; + private Button fHideMatching; + private Button fRegularExpressionFilter; + + private Control[][] fEnableDisable; + + + RetrieverFilterTab(RetrieverPage view) { + fView= view; + } + + public void createControl(Composite parent) { + int indent= 15; + GridData gd; + GridLayout gl; + + Composite outer= new Composite(parent, SWT.NONE); + outer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + outer.setLayout(gl= new GridLayout(1, false)); + gl.marginHeight= gl.marginWidth= 0; + gl.verticalSpacing= 2; + + fUseLocationFilter= new Button(outer, SWT.CHECK); + fUseLocationFilter.setText(SearchMessages.RetrieverFilterTab_LocationFilter_text); + fUseLocationFilter.setLayoutData(new GridData()); + + // location group + Composite locationGroup= new Composite(outer, SWT.NONE); + locationGroup.setLayoutData(gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + gd.horizontalIndent= indent; + + locationGroup.setLayout(gl= new GridLayout(3, false)); + gl.marginWidth= 0; + gl.marginHeight= 0; + gl.verticalSpacing= 0; + + // line 3, 4 + fCommentFilter= new Button(locationGroup, SWT.CHECK); + fCommentFilter.setText(SearchMessages.RetrieverFilterTab_Comment_text); + + fIncludeFilter= new Button(locationGroup, SWT.CHECK); + fIncludeFilter.setText(SearchMessages.RetrieverFilterTab_Import_text); + + if (TextFileScannerRegistry.getInstance().hasPreprocessorSupport()) { + fPrepFilter= new Button(locationGroup, SWT.CHECK); + fPrepFilter.setText(SearchMessages.RetrieverFilterTab_Preprocessor_text); + } else { + new Label(locationGroup, SWT.NONE); + } + + fStringFilter= new Button(locationGroup, SWT.CHECK); + fStringFilter.setText(SearchMessages.RetrieverFilterTab_String_text); + + if (TextFileScannerRegistry.getInstance().hasFunctionSupport()) { + fFunctionFilter= new Button(locationGroup, SWT.CHECK); + fFunctionFilter.setText(SearchMessages.RetrieverFilterTab_FunctionBody_text); + } + + fOtherFilter= new Button(locationGroup, SWT.CHECK); + fOtherFilter.setText(SearchMessages.RetrieverFilterTab_OtherLocation_text); + + // a bit of space before next line + Label separator2= new Label(outer, SWT.SEPARATOR | SWT.HORIZONTAL); + separator2.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + new Label(outer, SWT.NONE).setLayoutData(gd= new GridData()); + gd.heightHint= 5; + + // text filter + Composite indepAlign= new Composite(outer, SWT.NONE); + indepAlign.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + indepAlign.setLayout(gl= new GridLayout(2, false)); + gl.marginHeight= gl.marginWidth= 0; + + fUseStringFilter= new Button(indepAlign, SWT.CHECK); + fUseStringFilter.setLayoutData(new GridData()); + fUseStringFilter.setText(SearchMessages.RetrieverFilterTab_TextFilter_text); + + fFilterString= new Combo(indepAlign, SWT.NONE); + fFilterString.setVisibleItemCount(VISIBLE_ITEMS_IN_COMBO); + fFilterString.setLayoutData(gd= new GridData(GridData.FILL_HORIZONTAL)); + gd.widthHint= 20; + + indepAlign= new Composite(outer, SWT.NONE); + indepAlign.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); + indepAlign.setLayout(gl= new GridLayout(2, false)); + gl.marginHeight= gl.marginWidth= 0; + + fRegularExpressionFilter= new Button(indepAlign, SWT.CHECK); + fRegularExpressionFilter.setText(SearchMessages.RetrieverFindTab_regularExpression); + + fHideMatching= new Button(indepAlign, SWT.CHECK); + fHideMatching.setText(SearchMessages.RetrieverFilterTab_HideMatching_text); + + fEnableDisable= new Control[][] { {fCommentFilter, fStringFilter, fIncludeFilter, fPrepFilter, fFunctionFilter, fOtherFilter}, {fFilterString, fHideMatching, fRegularExpressionFilter}}; + } + + void createListeners() { + SelectionListener s= new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onEnableFilter(); + } + }; + fUseLocationFilter.addSelectionListener(s); + fUseStringFilter.addSelectionListener(s); + fFilterString.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + } + + public void keyReleased(KeyEvent e) { + if ((e.character == SWT.LF || e.character == SWT.CR)) { + onFilter(); + selectStringFilter(); + } + } + }); + fFilterString.addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { + } + + public void focusLost(FocusEvent e) { + onFilter(); + } + }); + + SelectionListener onFilter= new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onFilter(); + } + }; + fHideMatching.addSelectionListener(onFilter); + fRegularExpressionFilter.addSelectionListener(onFilter); + fStringFilter.addSelectionListener(onFilter); + fCommentFilter.addSelectionListener(onFilter); + fIncludeFilter.addSelectionListener(onFilter); + if (fPrepFilter != null) { + fPrepFilter.addSelectionListener(onFilter); + } + if (fFunctionFilter != null) { + fFunctionFilter.addSelectionListener(onFilter); + } + fOtherFilter.addSelectionListener(onFilter); + } + + protected void onEnableFilter() { + boolean el= fUseLocationFilter.getSelection(); + boolean es= fUseStringFilter.getSelection(); + fEnable= el || es; + if (fEnable) { + fEnableLocation= el; + fEnableString= es; + } + // reroute through the enable filter on the view + fView.onEnableToolbarFilter(fEnable); + } + + protected void onFilter() { + storeValues(); + fView.onFilterTabChanged(); + } + + public RetrieverFilter getFilter() { + if (fEnable) { + return new RetrieverFilter(fView, getAcceptedLocations(), getFilterText(), fRegularExpressionFilter.getSelection(), fHideMatching.getSelection(), hashCode()); + } + return new RetrieverFilter(); + } + + private int getAcceptedLocations() { + int acceptLocations= ALL_LOCATIONS; + if (fUseLocationFilter.getSelection()) { + acceptLocations= 0; + if (fStringFilter.getSelection()) { + acceptLocations|= (1 << AbstractTextFileScanner.LOCATION_STRING_LITERAL); + } + if (fCommentFilter.getSelection()) { + acceptLocations|= (1 << AbstractTextFileScanner.LOCATION_COMMENT); + } + if (fIncludeFilter.getSelection()) { + acceptLocations|= (1 << AbstractTextFileScanner.LOCATION_IMPORT_OR_INCLUDE_STATEMENT); + } + if (fPrepFilter == null || fPrepFilter.getSelection()) { + acceptLocations|= (1 << AbstractTextFileScanner.LOCATION_PREPROCESSOR_DIRECTIVE); + } + if (fFunctionFilter == null || fFunctionFilter.getSelection()) { + acceptLocations|= (1 << AbstractTextFileScanner.LOCATION_FUNCTION); + } + if (fOtherFilter.getSelection()) { + acceptLocations|= (1 << AbstractTextFileScanner.LOCATION_OTHER); + } + } + return acceptLocations; + } + + private String getFilterText() { + return fUseStringFilter.getSelection() ? fFilterString.getText() : null; + } + + + void storeValues() { + fView.storeValue(fEnableString, KEY_ENABLE_TEXT_FILTER); + fView.storeValue(fEnableLocation, KEY_ENABLE_LOCATION_FILTER); + fView.storeComboContent(fFilterString, KEY_FILTER_PATTERNS, MAX_FILTER_PATTERNS); + fView.storeButton(fHideMatching, KEY_INVERT_FILTER); + fView.storeButton(fRegularExpressionFilter, KEY_REGULAR_EXPRESSION_FILTER); + fView.storeButton(fCommentFilter, KEY_COMMENT_FILTER); + fView.storeButton(fStringFilter, KEY_STRING_FILTER); + fView.storeButton(fIncludeFilter, KEY_INCLUDE_FILTER); + fView.storeButton(fPrepFilter, KEY_PREP_FILTER); + fView.storeButton(fFunctionFilter, KEY_FUNCTION_FILTER); + fView.storeButton(fOtherFilter, KEY_ELSEWHERE_FILTER); + } + + /** + * called when the view is created + */ + void restoreValues(boolean filterEnabled) { + fEnable= filterEnabled; + fEnableLocation= fView.restoreValue(KEY_ENABLE_LOCATION_FILTER, true); + fEnableString= fView.restoreValue(KEY_ENABLE_TEXT_FILTER, false); + fUseLocationFilter.setSelection(fEnable && fEnableLocation); + fUseStringFilter.setSelection(fEnable && fEnableString); + fView.restoreCombo(fFilterString, KEY_FILTER_PATTERNS, ""); //$NON-NLS-1$ + fView.restoreButton(fHideMatching, KEY_INVERT_FILTER, false); + fView.restoreButton(fRegularExpressionFilter, KEY_REGULAR_EXPRESSION_FILTER, false); + fView.restoreButton(fCommentFilter, KEY_COMMENT_FILTER, true); + fView.restoreButton(fStringFilter, KEY_STRING_FILTER, true); + fView.restoreButton(fIncludeFilter, KEY_INCLUDE_FILTER, true); + fView.restoreButton(fPrepFilter, KEY_PREP_FILTER, true); + fView.restoreButton(fFunctionFilter, KEY_FUNCTION_FILTER, true); + fView.restoreButton(fOtherFilter, KEY_ELSEWHERE_FILTER, true); + updateEnablement(); + } + + private void updateEnablement() { + enableAll(fEnableDisable[0], fEnable && fEnableLocation); + enableAll(fEnableDisable[1], fEnable && fEnableString); + } + + private void enableAll(Control[] controls, boolean enable) { + for (int i= 0; i < controls.length; i++) { + Control control= controls[i]; + if (control != null) { + control.setEnabled(enable); + } + } + } + + public void onEnableToolbarFilter(boolean enable) { + fEnable= enable; + fUseLocationFilter.setSelection(fEnable && fEnableLocation); + fUseStringFilter.setSelection(fEnable && fEnableString); + updateEnablement(); + selectStringFilter(); + } + + public void onSelected() { + selectStringFilter(); + } + + private void selectStringFilter() { + if (fFilterString.isEnabled()) { + fFilterString.setFocus(); + fFilterString.setSelection(new Point(0, fFilterString.getText().length())); + } + } + + public void getProperties(Properties props) { + if (fEnable) { + props.setProperty(KEY_ENABLE_FILTER, String.valueOf(true)); + getProperty(props, KEY_COMMENT_FILTER, fCommentFilter); + getProperty(props, KEY_ELSEWHERE_FILTER, fOtherFilter); + getProperty(props, KEY_FILTER_PATTERNS, fFilterString); + getProperty(props, KEY_FUNCTION_FILTER, fFunctionFilter); + getProperty(props, KEY_INCLUDE_FILTER, fIncludeFilter); + getProperty(props, KEY_INVERT_FILTER, fHideMatching); + getProperty(props, KEY_PREP_FILTER, fPrepFilter); + getProperty(props, KEY_REGULAR_EXPRESSION_FILTER, fRegularExpressionFilter); + getProperty(props, KEY_STRING_FILTER, fStringFilter); + } + } + + private void getProperty(Properties props, String key, Button button) { + if (button != null) { + props.setProperty(key, String.valueOf(button.getSelection())); + } + } + + private void getProperty(Properties props, String key, Combo text) { + props.setProperty(key, text.getText()); + } + + public void setProperties(Properties props) { + if (Boolean.valueOf(props.getProperty(KEY_ENABLE_FILTER)).booleanValue()) { + fEnable= true; + setProperty(props, KEY_COMMENT_FILTER, fCommentFilter); + setProperty(props, KEY_INCLUDE_FILTER, fIncludeFilter); + setProperty(props, KEY_PREP_FILTER, fPrepFilter); + setProperty(props, KEY_STRING_FILTER, fStringFilter); + setProperty(props, KEY_FUNCTION_FILTER, fFunctionFilter); + setProperty(props, KEY_ELSEWHERE_FILTER, fOtherFilter); + setProperty(props, KEY_FILTER_PATTERNS, fFilterString); + setProperty(props, KEY_INVERT_FILTER, fHideMatching); + setProperty(props, KEY_REGULAR_EXPRESSION_FILTER, fRegularExpressionFilter); + } else { + fEnable= false; + } + + updateEnablement(); + } + + private void setProperty(Properties props, String key, Combo combo) { + String property= props.getProperty(key); + if (property != null) { + combo.setText(property); + } + } + + private void setProperty(Properties props, String key, Button button) { + if (button != null) { + String property= props.getProperty(key); + if (property != null) { + button.setSelection(Boolean.valueOf(property).booleanValue()); + } + } + } + + public boolean restoreFromResult(RetrieverFilter filter) { + // this came right back to me, so ignore it. + if (filter.getOriginatorsHash() == hashCode()) { + return fEnable; + } + int loc= filter.getAcceptedLocations(); + Pattern pattern= filter.getPattern(); + boolean el= (loc != ALL_LOCATIONS); + boolean es= (pattern != null); + + fEnable= el || es; + if (fEnable) { + fEnableLocation= el; + fEnableString= es; + } else { + el= es= false; + } + + fUseLocationFilter.setSelection(el); + fUseStringFilter.setSelection(es); + + if (el) { + setButton(fCommentFilter, loc, AbstractTextFileScanner.LOCATION_COMMENT); + setButton(fStringFilter, loc, AbstractTextFileScanner.LOCATION_STRING_LITERAL); + setButton(fIncludeFilter, loc, AbstractTextFileScanner.LOCATION_IMPORT_OR_INCLUDE_STATEMENT); + setButton(fPrepFilter, loc, AbstractTextFileScanner.LOCATION_PREPROCESSOR_DIRECTIVE); + setButton(fFunctionFilter, loc, AbstractTextFileScanner.LOCATION_FUNCTION); + setButton(fOtherFilter, loc, AbstractTextFileScanner.LOCATION_OTHER); + } + if (es) { + fEnableString= true; + fUseStringFilter.setSelection(true); + fFilterString.setText(filter.getFilterString()); + fRegularExpressionFilter.setSelection(filter.getIsRegex()); + fHideMatching.setSelection(filter.getHideMatching()); + } + updateEnablement(); + return fEnable; + } + + private void setButton(Button button, int allowedLoc, int loc) { + if (button != null) { + button.setSelection((allowedLoc & (1 << loc)) != 0); + } + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverFindTab.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverFindTab.java new file mode 100644 index 00000000000..c4ca3405eab --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverFindTab.java @@ -0,0 +1,429 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Pattern; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; + +import org.eclipse.jface.window.Window; + +import org.eclipse.search.ui.NewSearchUI; + +import org.eclipse.search.internal.ui.util.SWTUtil; + +import org.eclipse.search2.internal.ui.SearchMessages; + +/** + * @author markus.schorn@windriver.com + */ +public class RetrieverFindTab implements IRetrieverKeys { + private RetrieverPage fView; + private Combo fWorkingSetCombo; + private Button fChooseWorkingSetButton; + private Combo fSearchString; + private Button fCaseSensitive; + private Button fRegularExpression; + private Button fWholeWord; + private Button fSearchButton; + private Combo fFilePatterns; + private Button fFilePatternButton; + private Control[] fEnableDisable; + private Map fScopeMap= new HashMap(); + private int fPermanentScopeCount; + + RetrieverFindTab(RetrieverPage view) { + fView= view; + } + + public void createControl(Composite group) { + GridData gd; + GridLayout gl; + group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + group.setLayout(new GridLayout(3, false)); + + fSearchString= new Combo(group, SWT.NONE); + fSearchString.setLayoutData(gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + fSearchString.setVisibleItemCount(VISIBLE_ITEMS_IN_COMBO); + gd.horizontalSpan= 2; + gd.widthHint= 20; // spr 112201 + + fSearchButton= new Button(group, SWT.PUSH); + fSearchButton.setText(SearchMessages.RetrieverFindTab_search); + fSearchButton.setLayoutData(gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + gd.horizontalSpan= 1; + SWTUtil.setButtonDimensionHint(fSearchButton); + + Composite comp= new Composite(group, SWT.NONE); + comp.setLayoutData(gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + gd.horizontalSpan= 3; + comp.setLayout(gl= new GridLayout(3, false)); + gl.marginHeight= gl.marginWidth= 0; + + fCaseSensitive= new Button(comp, SWT.CHECK); + fCaseSensitive.setText(SearchMessages.RetrieverFindTab_caseSensitive); + + fRegularExpression= new Button(comp, SWT.CHECK); + fRegularExpression.setText(SearchMessages.RetrieverFindTab_regularExpression); + + fWholeWord= new Button(comp, SWT.CHECK); + fWholeWord.setText(SearchMessages.RetrieverFindTab_wholeWord); + + Label separator= new Label(group, SWT.SEPARATOR | SWT.HORIZONTAL); + separator.setLayoutData(gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + gd.horizontalSpan= 3; + new Label(group, SWT.NONE).setLayoutData(gd= new GridData()); + gd.horizontalSpan= 3; + gd.heightHint= 0; + + Label scopeLabel= new Label(group, SWT.NONE); + scopeLabel.setText(SearchMessages.RetrieverFindTab_searchScope); + + fWorkingSetCombo= new Combo(group, SWT.BORDER | SWT.READ_ONLY); + fWorkingSetCombo.setVisibleItemCount(VISIBLE_ITEMS_IN_COMBO); + fWorkingSetCombo.setLayoutData(gd= new GridData(GridData.FILL_HORIZONTAL)); + gd.widthHint= 20; + + fChooseWorkingSetButton= new Button(group, SWT.PUSH); + fChooseWorkingSetButton.setText(SearchMessages.RetrieverFindTab_choose); + fChooseWorkingSetButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + SWTUtil.setButtonDimensionHint(fChooseWorkingSetButton); + + Label filePatternLabel= new Label(group, SWT.NONE); + filePatternLabel.setText(SearchMessages.RetrieverFindTab_filePatterns); + + fFilePatterns= new Combo(group, SWT.NONE); + fFilePatterns.setVisibleItemCount(VISIBLE_ITEMS_IN_COMBO); + fFilePatterns.setLayoutData(gd= new GridData(GridData.FILL_HORIZONTAL)); + gd.widthHint= 20; + + fFilePatternButton= new Button(group, SWT.PUSH); + fFilePatternButton.setText(SearchMessages.RetrieverFindTab_choose); + fFilePatternButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + SWTUtil.setButtonDimensionHint(fFilePatternButton); + + fEnableDisable= new Control[] {fSearchString, fSearchButton, fCaseSensitive, fRegularExpression, fWholeWord, scopeLabel, fWorkingSetCombo, fChooseWorkingSetButton, filePatternLabel, fFilePatterns, fFilePatternButton}; + + setupScopeCombo(); + } + + // overrider + public void setFocus() { + fSearchString.setSelection(new Point(0, fSearchString.getText().length())); + fSearchString.setFocus(); + } + + public void dispose() { + } + + void storeValues() { + IScopeDescription scope= getSearchScope(); + fView.storeComboContent(fFilePatterns, KEY_FILE_PATTERNS, MAX_FILE_PATTERNS); + fView.storeComboContent(fSearchString, KEY_SEARCH_STRINGS, MAX_SEARCH_STRINGS); + fView.storeButton(fCaseSensitive, KEY_CASE_SENSITIVE_SEARCH); + fView.storeButton(fRegularExpression, KEY_REGULAR_EXPRESSION_SEARCH); + fView.storeButton(fWholeWord, KEY_WHOLE_WORD); + storeScopeCombo(); + + RetrieverPage.sLastFilePatterns= fFilePatterns.getText(); + RetrieverPage.sLastSearchPattern= fSearchString.getText(); + RetrieverPage.sLastIsCaseSensitive= fCaseSensitive.getSelection(); + RetrieverPage.sLastIsRegularExpression= fRegularExpression.getSelection(); + RetrieverPage.sLastIsWholeWord= fWholeWord.getSelection(); + RetrieverPage.sLastScope= scope; + } + + private void storeScopeCombo() { + String[] names= fWorkingSetCombo.getItems(); + fView.storeValue(names, KEY_SCOPE_HISTORY); + for (int i= fPermanentScopeCount; i < names.length; i++) { + String name= names[i]; + IScopeDescription scope= (IScopeDescription) fScopeMap.get(name); + if (scope != null) { + fView.storeScope(scope, KEY_SCOPE_HISTORY + "-" + name); //$NON-NLS-1$ + } + } + IScopeDescription scope= getSearchScope(); + fView.storeScope(scope, KEY_SEARCH_SCOPE); + } + + void restoreValues() { + fView.restoreCombo(fFilePatterns, KEY_FILE_PATTERNS, "*.c,*.ci,*.h,*.java"); //$NON-NLS-1$ + fView.restoreCombo(fSearchString, KEY_SEARCH_STRINGS, null); + fView.restoreButton(fCaseSensitive, KEY_CASE_SENSITIVE_SEARCH, true); + fView.restoreButton(fRegularExpression, KEY_REGULAR_EXPRESSION_SEARCH, false); + fView.restoreButton(fWholeWord, KEY_WHOLE_WORD, true); + fFilePatterns.clearSelection(); + setupScopeCombo(); + } + + private void setupScopeCombo() { + fWorkingSetCombo.removeAll(); + fPermanentScopeCount= 4; + addScopeToCombo(new WorkspaceScopeDescription(), false); + addScopeToCombo(new CurrentProjectScopeDescription(), false); + addScopeToCombo(new CurrentFileScopeDescription(), false); + addScopeToCombo(new WindowWorkingSetScopeDescription(), false); + + String[] names= fView.restoreValue(KEY_SCOPE_HISTORY, null); + if (names != null) { + for (int i= names.length - 1; i >= 0; i--) { + String name= names[i]; + IScopeDescription scope= fView.restoreScope(KEY_SCOPE_HISTORY + "-" + name); //$NON-NLS-1$ + if (scope != null) { + addScopeToCombo(scope, false); + } + } + } + IScopeDescription scope= fView.restoreScope(KEY_SEARCH_SCOPE); + addScopeToCombo(scope, false); + } + + void createListeners() { + fSearchButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onSearch(); + } + }); + fSearchString.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + } + + public void keyReleased(KeyEvent e) { + String text= fSearchString.getText(); + if ((e.character == SWT.LF || e.character == SWT.CR) && text.length() > 0) { + onSearch(); + } + RetrieverPage.sLastSearchPattern= text; + } + }); + fChooseWorkingSetButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onChooseButtonSelectWorkingSet(); + } + }); + fFilePatternButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onChooseButtonSelectFilePatterns(); + } + }); + fSearchString.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + RetrieverPage.sLastSearchPattern= fSearchString.getText(); + } + }); + fCaseSensitive.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + RetrieverPage.sLastIsCaseSensitive= fCaseSensitive.getSelection(); + } + }); + fRegularExpression.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + RetrieverPage.sLastIsRegularExpression= fRegularExpression.getSelection(); + } + }); + fWholeWord.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + RetrieverPage.sLastIsWholeWord= fWholeWord.getSelection(); + } + }); + fFilePatterns.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + RetrieverPage.sLastFilePatterns= fFilePatterns.getText(); + } + }); + fWorkingSetCombo.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + RetrieverPage.sLastScope= getSearchScope(); + } + }); + } + + protected void onSearch() { + // first do a few checks! + String searchText= fSearchString.getText(); + if (searchText.length() == 0) { + fView.showError(SearchMessages.RetrieverFindTab_Error_emptySearchString); + return; + } + if (fRegularExpression.getSelection()) { + Pattern pattern= null; + try { + pattern= Pattern.compile(searchText); + } catch (Exception e) { + fView.showError(SearchMessages.RetrieverFindTab_Error_invalidRegex + e.getMessage()); + return; + } + + if (pattern.matcher("").find()) { //$NON-NLS-1$ + boolean cont= fView.showQuestion(SearchMessages.RetrieverFindTab_Question_regexMatchesEmptyString); + if (!cont) { + return; + } + } + } + + fView.storeValues(); + RetrieverQuery query= new RetrieverQuery(fView.getSite().getPage()); + query.setSearchString(RetrieverPage.sLastSearchPattern); + query.setIsCaseSensitive(RetrieverPage.sLastIsCaseSensitive); + query.setIsRegularExpression(RetrieverPage.sLastIsRegularExpression); + query.setIsWholeWord(RetrieverPage.sLastIsWholeWord); + query.setSearchScope(RetrieverPage.sLastScope, RetrieverPage.sLastConsiderDerivedResources); + query.setFilePatterns(RetrieverPage.sLastFilePatterns, RetrieverPage.sLastUseCaseSensitiveFilePatterns); + query.setSearchOrder(fView.getPreferredSearchOrder()); + + RetrieverResult result= (RetrieverResult) query.getSearchResult(); + fView.initFilter(result); + fView.storeValues(); + NewSearchUI.runQueryInBackground(query, fView.getViewPart()); + } + + private IScopeDescription getSearchScope() { + String scopeLabel= fWorkingSetCombo.getText(); + IScopeDescription result= (IScopeDescription) fScopeMap.get(scopeLabel); + return result == null ? new WorkspaceScopeDescription() : result; + } + + protected void onChooseButtonSelectWorkingSet() { + IScopeDescription scope= getSearchScope(); + IScopeDescription use= WorkingSetScopeDescription.createWithDialog(fView.getSite().getPage(), scope); + if (use != null) { + addScopeToCombo(use, false); + } + } + + protected void onChooseButtonSelectFilePatterns() { + FilePatternSelectionDialog dlg= new FilePatternSelectionDialog(fView.getSite().getShell(), fFilePatterns.getText()); + if (dlg.open() == Window.OK) { + setCombo(fFilePatterns, dlg.getFilePatterns(), 0, MAX_FILE_PATTERNS, false); + } + } + + void updateEnablement(boolean searchInProgress) { + for (int i= 0; i < fEnableDisable.length; i++) { + fEnableDisable[i].setEnabled(!searchInProgress); + } + } + + public void onSelected() { + setFocus(); + } + + public void storeValues(Properties props) { + props.setProperty(KEY_FILE_PATTERNS, fFilePatterns.getText()); + props.setProperty(KEY_SEARCH_STRINGS, fSearchString.getText()); + storeButton(props, KEY_CASE_SENSITIVE_SEARCH, fCaseSensitive); + storeButton(props, KEY_REGULAR_EXPRESSION_SEARCH, fRegularExpression); + storeButton(props, KEY_WHOLE_WORD, fWholeWord); + storeScope(props, getSearchScope()); + } + + private void storeScope(Properties props, IScopeDescription searchScope) { + props.setProperty(KEY_SCOPE_DESCRIPTOR_CLASS, searchScope.getClass().getName()); + searchScope.store(props, KEY_SEARCH_SCOPE); + } + + private void storeButton(Properties props, String key, Button button) { + props.setProperty(key, String.valueOf(button.getSelection())); + } + + public void restoreValues(Properties props) { + restoreComboText(props, KEY_FILE_PATTERNS, fFilePatterns); + restoreComboText(props, KEY_SEARCH_STRINGS, fSearchString); + restoreButton(props, KEY_CASE_SENSITIVE_SEARCH, fCaseSensitive); + restoreButton(props, KEY_REGULAR_EXPRESSION_SEARCH, fRegularExpression); + restoreButton(props, KEY_WHOLE_WORD, fWholeWord); + + IScopeDescription scope= restoreScope(props); + addScopeToCombo(scope, false); + } + + private IScopeDescription restoreScope(Properties props) { + IScopeDescription scope= null; + try { + String scopeDescClass= props.getProperty(KEY_SCOPE_DESCRIPTOR_CLASS); + scope= (IScopeDescription) Class.forName(scopeDescClass).newInstance(); + scope.restore(props, KEY_SEARCH_SCOPE); + } catch (Exception e) { + scope= new WorkspaceScopeDescription(); + } + return scope; + } + + private void restoreComboText(Properties props, String key, Combo combo) { + String property= props.getProperty(key); + if (property != null) { + combo.setText(property); + } + } + + private void restoreButton(Properties props, String key, Button button) { + String property= props.getProperty(key); + if (property != null) { + button.setSelection(Boolean.valueOf(property).booleanValue()); + } + } + + public void restoreFromQuery(RetrieverQuery rq) { + fCaseSensitive.setSelection(rq.isCaseSensitive()); + fRegularExpression.setSelection(rq.isRegularExpression()); + fWholeWord.setSelection(rq.isWholeWord()); + + String searchFor= rq.getSearchText(); + if (searchFor != null && searchFor.length() > 0) { + setCombo(fSearchString, rq.getSearchText(), 0, MAX_SEARCH_STRINGS, true); + } + setCombo(fFilePatterns, rq.getFilePatterns(), 0, MAX_FILE_PATTERNS, true); + addScopeToCombo(rq.getScopeDescription(), true); + } + + private void addScopeToCombo(IScopeDescription scope, boolean moveExisting) { + String scopeLabel= scope.getLabel(); + fScopeMap.put(scopeLabel, scope); + setCombo(fWorkingSetCombo, scope.getLabel(), fPermanentScopeCount, MAX_SCOPES, moveExisting); + RetrieverPage.sLastScope= scope; + } + + private void setCombo(Combo combo, String value, int insertPos, int maxItems, boolean moveExisting) { + int idx= combo.indexOf(value); + if (idx < 0) { + insertPos= Math.min(combo.getItemCount(), insertPos); + combo.add(value, insertPos); + int itemCount= combo.getItemCount(); + if (itemCount > maxItems) { + combo.remove(maxItems, itemCount - 1); + } + idx= insertPos; + } else + if (moveExisting && idx > insertPos) { + combo.remove(idx); + combo.add(value, insertPos); + } + combo.setText(value); + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverLabelProvider.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverLabelProvider.java new file mode 100644 index 00000000000..008d80531ea --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverLabelProvider.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.text.MessageFormat; + +import org.eclipse.core.resources.IFile; + +import org.eclipse.swt.graphics.Image; + +import org.eclipse.search.ui.text.AbstractTextSearchViewPage; + +import org.eclipse.search.internal.ui.SearchPluginImages; +import org.eclipse.search.internal.ui.text.FileLabelProvider; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class RetrieverLabelProvider extends FileLabelProvider { + private boolean fAppendContainer= false; + + public RetrieverLabelProvider(AbstractTextSearchViewPage page, int orderFlag) { + super(page, orderFlag); + } + + public void setAppendFileContainer(boolean val) { + fAppendContainer= val; + } + + public Image getImage(Object element) { + if (element instanceof RetrieverLine) { + return SearchPluginImages.get(SearchPluginImages.IMG_OBJ_TEXT_SEARCH_LINE); + } + return super.getImage(element); + } + + public String getText(Object element) { + if (element instanceof RetrieverLine) { + RetrieverLine line= (RetrieverLine) element; + StringBuffer buf= new StringBuffer(); + buf.append(String.valueOf(line.getLineNumber())); + buf.append(": "); //$NON-NLS-1$ + buf.append(convertChars(line.getString())); + return buf.toString(); + } + if (element instanceof int[]) { + int[] matchCount= (int[]) element; + Integer hidden= new Integer(matchCount[0] - matchCount[1]); + return MessageFormat.format(SearchMessages.RetrieverLabelProvider_FilterHidesMatches_label, new Object[] {hidden}); + } + if (fAppendContainer && element instanceof IFile) { + IFile file= (IFile) element; + StringBuffer buf= new StringBuffer(); + buf.append(file.getName()); + buf.append(" - "); //$NON-NLS-1$ + buf.append(file.getParent().getFullPath().toString()); + return buf.toString(); + } + return super.getText(element); + } + + static String convertChars(CharSequence input) { + StringBuffer result= new StringBuffer(); + for (int i= 0; i < input.length(); i++) { + char c= input.charAt(i); + switch (c) { + case '\r': + result.append("\\r");break; //$NON-NLS-1$ + case '\n': + result.append("\\n");break; //$NON-NLS-1$ + case '\t': + result.append(" ");break; //$NON-NLS-1$ + default: + result.append(c); + break; + } + } + return result.toString(); + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverLine.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverLine.java new file mode 100644 index 00000000000..c04eb10878b --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverLine.java @@ -0,0 +1,282 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.runtime.IAdaptable; + +import org.eclipse.core.resources.IFile; + + +/** + * @author markus.schorn@windriver.com + */ +public class RetrieverLine implements IAdaptable { + private static final RetrieverMatch[] EMPTY_ARRAY= new RetrieverMatch[0]; + private static final int HIGH_BIT= 1 << 31; + + private IFile fParent; + private int fLineNumber; + private String fLineData; + private RetrieverMatch[] fMatches; + + public RetrieverLine(IFile parent, int lineNumber) { + fParent= parent; + fLineNumber= lineNumber; + fMatches= null; + setIsFiltered(false); + } + public int getLineNumber() { + return fLineNumber & ~HIGH_BIT; + } + public void setData(String line) { + fLineData= line; + } + + synchronized public void addMatch(RetrieverMatch match) { + if (fMatches == null) { + fMatches= new RetrieverMatch[] {match}; + } else { + RetrieverMatch[] newMatches= new RetrieverMatch[fMatches.length + 1]; + System.arraycopy(fMatches, 0, newMatches, 0, fMatches.length); + newMatches[fMatches.length]= match; + fMatches= newMatches; + } + } + + synchronized public void filter(Pattern regex, boolean hideMatching, int acceptLocations, Collection changedMatches) { + boolean lineWasFiltered= isFiltered(); + boolean lineIsFiltered= regex != null && regex.matcher(fLineData).find() == hideMatching; + for (int i= 0; i < fMatches.length; i++) { + RetrieverMatch match= fMatches[i]; + boolean wasFiltered= lineWasFiltered || match.isFiltered(); + boolean doFilter= lineIsFiltered || ((match.getKind() & acceptLocations) == 0); + if (wasFiltered != doFilter) { + if (changedMatches != null) { + changedMatches.add(match); + } + match.setFiltered(doFilter); + } + } + setIsFiltered(lineIsFiltered); + } + + private void setIsFiltered(boolean value) { + if (value) { + fLineNumber|= HIGH_BIT; + } else { + fLineNumber&= ~HIGH_BIT; + } + } + public String getLine() { + return fLineData; + } + + public RetrieverMatch[] getMatches(boolean copy) { + return copy ? (RetrieverMatch[]) fMatches.clone() : fMatches; + } + + public IFile getParent() { + return fParent; + } + + synchronized public void addMatchCount(int[] count) { + count[0]+= fMatches.length; + if (!isFiltered()) { + for (int i= 0; i < fMatches.length; i++) { + if (!fMatches[i].isFiltered()) { + count[1]++; + } + } + } + } + + public int getLength() { + return fLineData.length(); + } + + public String getString() { + return getPreString(null); + } + + synchronized public String getPreString(RetrieverMatch match) { + StringBuffer pre= new StringBuffer(); + int offset= 0; + int lineLength= fLineData.length(); + for (int i= 0; i < fMatches.length; i++) { + RetrieverMatch m= fMatches[i]; + if (m == match) { + break; + } + if (m.isReplaced()) { + int start= m.getLineOffset(); + if (start >= lineLength) { + break; + } + pre.append(fLineData.substring(offset, start)); + pre.append(m.getReplacement()); + offset= start + m.getOriginalLength(); + if (offset >= lineLength) { + break; + } + } + if (m == match) { + break; + } + } + if (offset < lineLength) { + int end= match == null ? lineLength : Math.min(match.getLineOffset(), lineLength); + pre.append(fLineData.substring(offset, end)); + } + return pre.toString(); + } + + synchronized public String computeReplacement(RetrieverMatch match, Pattern p, String replacement) { + if (match.getLineOffset() + match.getOriginalLength() > fLineData.length()) { + return null; + } + RetrieverMatch prev= null; + for (int i= 0; i < fMatches.length; i++) { + RetrieverMatch m= fMatches[i]; + if (m == match) { + break; + } + prev= m; + } + // find a good point to start the find + int offsetInLine= prev == null ? 0 : prev.getLineOffset() + prev.getOriginalLength(); + Matcher matcher= p.matcher(fLineData); + if (matcher.find(offsetInLine)) { + int shouldStart= match.getLineOffset(); + if (shouldStart == matcher.start()) { + StringBuffer help= new StringBuffer(); + try { + matcher.appendReplacement(help, replacement); + } catch (Exception e) { + return replacement.replaceAll("\\\\\\\\", "\\\\"); //$NON-NLS-1$//$NON-NLS-2$ + } + return help.substring(shouldStart); + } + } + return null; + } + + synchronized public String getPostString(RetrieverMatch match) { + StringBuffer post= new StringBuffer(); + int offset= 0; + int lineLength= fLineData.length(); + for (int i= 0; i < fMatches.length; i++) { + RetrieverMatch m= fMatches[i]; + if (m == match) { + offset= match.getLineOffset() + match.getOriginalLength(); + } else + if (offset > 0) { + if (m.isReplaced()) { + int start= m.getLineOffset(); + if (start >= lineLength) { + break; + } + post.append(fLineData.substring(offset, start)); + post.append(m.getReplacement()); + offset= start + m.getOriginalLength(); + if (offset >= lineLength) { + break; + } + } + } + } + if (offset < lineLength) { + post.append(fLineData.substring(offset, lineLength)); + } + return post.toString(); + } + + public void setParent(IFile file) { + fParent= file; + } + + synchronized public boolean checkState(boolean replace) { + for (int i= 0; i < fMatches.length; i++) { + RetrieverMatch match= fMatches[i]; + if (!match.isFiltered() && replace != match.isReplaced()) { + return true; + } + } + return false; + } + + synchronized public void remove(Set matchset) { + ArrayList matches= new ArrayList(); + for (int i= 0; i < fMatches.length; i++) { + Object m= fMatches[i]; + if (!matchset.contains(m)) { + matches.add(m); + } + } + fMatches= (RetrieverMatch[]) matches.toArray(new RetrieverMatch[matches.size()]); + } + + synchronized public int getDisplayedMatchCount() { + int result= 0; + if (!isFiltered()) { + for (int i= 0; i < fMatches.length; i++) { + if (!fMatches[i].isFiltered()) { + result++; + } + } + } + return result; + } + + synchronized public RetrieverMatch[] getDisplayedMatches() { + int count= getDisplayedMatchCount(); + if (count == 0) { + return EMPTY_ARRAY; + } + if (count == fMatches.length) { + return fMatches; + } + RetrieverMatch[] result= new RetrieverMatch[count]; + int j= 0; + for (int i= 0; i < fMatches.length; i++) { + RetrieverMatch match= fMatches[i]; + if (!match.isFiltered()) { + result[j++]= match; + } + } + return result; + } + + public boolean isFiltered() { + return (fLineNumber & HIGH_BIT) != 0; + } + + public int getMatchCount() { + return 0; + } + + public String substring(int begin, int end) { + return fLineData.substring(begin, end); + } + + public Object getAdapter(Class adapter) { + /* if (adapter.isAssignableFrom(IFile.class)) { + return getParent(); + }*/ + return null; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverMatch.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverMatch.java new file mode 100644 index 00000000000..e7c4201b748 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverMatch.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.regex.Pattern; + +import org.eclipse.search.ui.text.Match; + +public class RetrieverMatch extends Match { + private int fKind; + private int fLineOffset; + private String fReplacement; + private String fOriginal; + + public RetrieverMatch(RetrieverLine line, String original, int offset, int length, int lineOffset, int kind) { + super(line, offset, length); + fOriginal= original; + fReplacement= null; + fLineOffset= lineOffset; + fKind= kind; + } + + public int getKind() { + return fKind; + } + + public void setReplacement(String replacement) { + fReplacement= replacement; + } + + public boolean isReplaced() { + return fReplacement != null; + } + + public String getReplacement() { + return fReplacement; + } + + public String getOriginal() { + return fOriginal; + } + + public boolean filter(Pattern filterExpr, boolean hideMatching, int filterOptions, boolean invertOptions) { + boolean filtered= false; + if (((fKind & filterOptions) == 0) == invertOptions) { + filtered= true; + } + setFiltered(filtered); + return filtered; + } + + public int getLineOffset() { + return fLineOffset; + } + + public String getCurrentText() { + return fReplacement != null ? fReplacement : fOriginal; + } + + public String computeReplacement(Pattern pattern, String replacement) { + return getLine().computeReplacement(this, pattern, replacement); + } + + public RetrieverLine getLine() { + return (RetrieverLine) getElement(); + } + + public int getOriginalLength() { + return fOriginal.length(); + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverPage.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverPage.java new file mode 100644 index 00000000000..e4a6dd74f9f --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverPage.java @@ -0,0 +1,1031 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Properties; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.custom.ViewForm; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.util.DelegatingDragAdapter; +import org.eclipse.jface.viewers.DecoratingLabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeViewerListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TreeExpansionEvent; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.window.Window; + +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.IWorkingSetManager; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.ActionContext; +import org.eclipse.ui.actions.ActionGroup; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.part.IPageSite; +import org.eclipse.ui.part.ResourceTransfer; +import org.eclipse.ui.texteditor.ITextEditor; + +import org.eclipse.search.ui.IContextMenuConstants; +import org.eclipse.search.ui.IQueryListener; +import org.eclipse.search.ui.ISearchQuery; +import org.eclipse.search.ui.ISearchResult; +import org.eclipse.search.ui.ISearchResultViewPart; +import org.eclipse.search.ui.NewSearchUI; +import org.eclipse.search.ui.SearchResultEvent; +import org.eclipse.search.ui.text.AbstractTextSearchResult; +import org.eclipse.search.ui.text.AbstractTextSearchViewPage; +import org.eclipse.search.ui.text.Match; + +import org.eclipse.search.internal.ui.SearchPlugin; +import org.eclipse.search.internal.ui.SearchPluginImages; +import org.eclipse.search.internal.ui.text.EditorOpener; +import org.eclipse.search.internal.ui.text.FileLabelProvider; +import org.eclipse.search.internal.ui.text.NewTextSearchActionGroup; +import org.eclipse.search.internal.ui.text.ResourceTransferDragAdapter; + +import org.eclipse.search2.internal.ui.SearchMessages; +import org.eclipse.search2.internal.ui.basic.views.SetLayoutAction; + +/** + * @author markus.schorn@windriver.com + */ +public class RetrieverPage extends AbstractTextSearchViewPage implements IQueryListener, IRetrieverKeys { + + public static final String ID= "org.eclipse.search.text.RetrieverPage"; //$NON-NLS-1$ + private static final String QUERY_EXTENSION= ".query"; //$NON-NLS-1$ + + private static final Collator COLLATOR= Collator.getInstance(); + private static final Comparator FLAT_SORTER= new Comparator() { + public int compare(Object o1, Object o2) { + return compareResources((IResource) o1, (IResource) o2); + } + private int compareResources(IResource r1, IResource r2) { + if (r1 == r2) + return 0; + if (r1 == null) + return -1; + if (r2 == null) + return 1; + + int cmp= COLLATOR.compare(r1.getName(), r2.getName()); + if (cmp == 0) { + cmp= compare(r1.getParent(), r2.getParent()); + } + return cmp; + } + }; + private static final Comparator HIERARCHICAL_SORTER= new Comparator() { + public int compare(Object o1, Object o2) { + return compareFiles((IFile) o1, (IFile) o2); + } + private int compareFiles(IFile r1, IFile r2) { + if (r1 == r2) + return 0; + if (r1 == null) + return -1; + if (r2 == null) + return 1; + + int cmp= compareParentPaths(r1.getParent().getFullPath(), r2.getParent().getFullPath()); + if (cmp == 0) { // in same folder + cmp= COLLATOR.compare(r1.getName(), r2.getName()); + } + return cmp; + } + private int compareParentPaths(IPath p1, IPath p2) { + // compare fragment by fragment to avoid new string creation + int p1len= p1.segmentCount(); + int p2len= p2.segmentCount(); + for (int i= 0; i < p1len; i++) { + if (i >= p2len) { + return 1; // second is shorter, sort it first + } + int cmp= COLLATOR.compare(p1.segment(i), p2.segment(i)); + if (cmp != 0) { + return cmp; + } + } + if (p1len == p2len) { + return 0; + } + return -1; // first is shorter, sort it first + } + }; + + static String sLastSearchPattern; + static boolean sLastIsCaseSensitive; + static boolean sLastIsRegularExpression; + static boolean sLastIsWholeWord; + static boolean sLastConsiderDerivedResources; + static boolean sLastUseCaseSensitiveFilePatterns; + static boolean sLastUseFlatLayout; + static IScopeDescription sLastScope; + static String sLastFilePatterns; + + private RetrieverFindTab fSearchControl= new RetrieverFindTab(this); + private RetrieverFilterTab fFilterControl= new RetrieverFilterTab(this); + private RetrieverReplaceTab fReplaceControl= new RetrieverReplaceTab(this); + + private IDialogSettings fDialogSettings; + private boolean fSearchInProgress= false; + + private SashForm fSplitter; + private ViewForm fResultForm; + private ViewForm fInputForm; + private TabFolder fTabFolder; + + private SetLayoutAction fFlatAction; + private SetLayoutAction fHierarchicalAction; + + private Action fEnableFilter; + private Action fUseCaseSensitiveFilePatterns; + private Action fConsiderDerivedResources; + private RetrieverContentProvider fContentProvider; + private EditorOpener fEditorOpener= new EditorOpener(); + private Action fLoadAction; + private Action fStoreAction; + private Action fCreateWSAction; + private ActionGroup fActionGroup; + + private RetrieverViewerSorter fSorter; + + private boolean fUseFlatLayout; + + private RetrieverLabelProvider fLabelProvider; + private ISearchResultViewPart fViewPart; + private RetrieverFilter fRecentFilter; + + public RetrieverPage() { + super(FLAG_LAYOUT_TREE); + } + + // overrider + public void createControl(Composite parent) { + IDialogSettings ds= SearchPlugin.getDefault().getDialogSettings(); + fDialogSettings= ds.getSection(getClass().getName()); + if (fDialogSettings == null) { + fDialogSettings= ds.addNewSection(getClass().getName()); + } + restoreCurrentLayout(); + + fSplitter= new SashForm(parent, SWT.HORIZONTAL); + fSplitter.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + fResultForm= new ViewForm(fSplitter, SWT.NONE); + super.createControl(fResultForm); + fResultForm.setContent(super.getControl()); + + fInputForm= new ViewForm(fSplitter, SWT.NONE); + fInputForm.setContent(createInputControl(fInputForm)); + + fSplitter.setWeights(new int[] {60, 40}); + + + createListeners(); + + // IWorkbenchHelpSystem help= PlatformUI.getWorkbench().getHelpSystem(); + // help.setHelp(fSplitter, ISYContextIDs.VIEW_textSearch); + + restoreValues(); + } + + public Control getControl() { + return fSplitter; + } + + public void init(IPageSite pageSite) { + super.init(pageSite); + + createActions(); + IActionBars actionBars= pageSite.getActionBars(); + IMenuManager mm= actionBars.getMenuManager(); + mm.appendToGroup(IContextMenuConstants.GROUP_NEW, fLoadAction); + mm.appendToGroup(IContextMenuConstants.GROUP_NEW, fStoreAction); + mm.appendToGroup(IContextMenuConstants.GROUP_SHOW, fEnableFilter); + mm.appendToGroup(IContextMenuConstants.GROUP_SHOW, fCreateWSAction); + mm.appendToGroup(IContextMenuConstants.GROUP_SEARCH, fUseCaseSensitiveFilePatterns); + mm.appendToGroup(IContextMenuConstants.GROUP_SEARCH, fConsiderDerivedResources); + mm.appendToGroup(IContextMenuConstants.GROUP_VIEWER_SETUP, fFlatAction); + mm.appendToGroup(IContextMenuConstants.GROUP_VIEWER_SETUP, fHierarchicalAction); + + actionBars.updateActionBars(); + } + + protected void fillToolbar(IToolBarManager tbm) { + super.fillToolbar(tbm); + tbm.appendToGroup(IContextMenuConstants.GROUP_SHOW, fEnableFilter); + } + + public void setViewPart(ISearchResultViewPart part) { + super.setViewPart(part); + fViewPart= part; + fActionGroup= new NewTextSearchActionGroup(part); + } + + public void dispose() { + fActionGroup.dispose(); + NewSearchUI.removeQueryListener(this); + fSearchControl.dispose(); + fFilterControl= null; + super.dispose(); + } + + public void setLayout(int layout) { + boolean flat= ((layout & FLAG_LAYOUT_FLAT) != 0); + if (fUseFlatLayout != flat) { + onChangeLayout(flat); + } + } + + protected void fillContextMenu(IMenuManager mgr) { + super.fillContextMenu(mgr); + IStructuredSelection sel= (IStructuredSelection) getTreeViewer().getSelection(); + if (sel.getFirstElement() instanceof IFile) { + fActionGroup.setContext(new ActionContext(sel)); + fActionGroup.fillContextMenu(mgr); + } + if (!fSearchInProgress) { + fReplaceControl.fillContextMenu(mgr); + } + } + + // overrider + public void setFocus() { + fSearchControl.setFocus(); + } + + public int getDisplayedMatchCount(Object element) { + if (element instanceof RetrieverLine) { + return ((RetrieverLine) element).getDisplayedMatchCount(); + } + return 0; + } + + public Match[] getDisplayedMatches(Object element) { + if (element instanceof RetrieverLine) { + return ((RetrieverLine) element).getDisplayedMatches(); + } + return EMPTY_MATCH_ARRAY; + } + + + private Control createInputControl(Composite parent) { + fTabFolder= new TabFolder(parent, SWT.NONE); + fTabFolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + fTabFolder.setLayout(new GridLayout(1, false)); + + // search tab + ScrolledComposite sc= createScrolledComposite(fTabFolder); + fSearchControl.createControl((Composite) sc.getContent()); + setMinSize(sc); + createTabItem(fTabFolder, sc, SearchMessages.RetrieverPage_FindTab_text); + + // filter tab + sc= createScrolledComposite(fTabFolder); + fFilterControl.createControl((Composite) sc.getContent()); + setMinSize(sc); + createTabItem(fTabFolder, sc, SearchMessages.RetrieverPage_FilterTab_text); + + // replace tab + sc= createScrolledComposite(fTabFolder); + fReplaceControl.createControl((Composite) sc.getContent()); + setMinSize(sc); + createTabItem(fTabFolder, sc, SearchMessages.RetrieverPage_ReplaceTab_text); + + return fTabFolder; + } + + private void setMinSize(ScrolledComposite sc) { + sc.setMinSize(sc.getContent().computeSize(SWT.DEFAULT, SWT.DEFAULT)); + } + + private void createTabItem(TabFolder folder, Control content, String text) { + TabItem tabItem= new TabItem(folder, SWT.NONE); + tabItem.setText(text); + tabItem.setControl(content); + } + + private ScrolledComposite createScrolledComposite(Composite parent) { + ScrolledComposite sc= new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL); + sc.setLayoutData(new GridData(GridData.FILL_BOTH)); + sc.setLayout(new GridLayout(1, true)); + sc.setExpandHorizontal(true); + sc.setExpandVertical(true); + + Composite comp= new Composite(sc, SWT.NONE); + sc.setContent(comp); + comp.setLayoutData(new GridData(GridData.FILL_BOTH)); + comp.setLayout(new GridLayout(1, true)); + return sc; + } + + private void createListeners() { + fTabFolder.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onTabChanged(); + } + }); + + fSearchControl.createListeners(); + fFilterControl.createListeners(); + fReplaceControl.createListeners(getViewer()); + + NewSearchUI.addQueryListener(this); + } + + private void createActions() { + fReplaceControl.createActions(); + + fFlatAction= new SetLayoutAction(this, SearchMessages.AbstractTextSearchViewPage_flat_layout_label, SearchMessages.AbstractTextSearchViewPage_flat_layout_tooltip, FLAG_LAYOUT_FLAT); + fHierarchicalAction= new SetLayoutAction(this, SearchMessages.AbstractTextSearchViewPage_hierarchical_layout_label, SearchMessages.AbstractTextSearchViewPage_hierarchical_layout_tooltip, FLAG_LAYOUT_TREE); + SearchPluginImages.setImageDescriptors(fFlatAction, SearchPluginImages.T_LCL, SearchPluginImages.IMG_LCL_SEARCH_FLAT_LAYOUT); + SearchPluginImages.setImageDescriptors(fHierarchicalAction, SearchPluginImages.T_LCL, SearchPluginImages.IMG_LCL_SEARCH_HIERARCHICAL_LAYOUT); + + fEnableFilter= new Action(SearchMessages.RetrieverPage_EnableFilter_text, IAction.AS_CHECK_BOX) { + public void run() { + onEnableToolbarFilter(fEnableFilter.isChecked()); + } + }; + fEnableFilter.setToolTipText(SearchMessages.RetrieverPage_EnableFilter_tooltip); + SearchPluginImages.setImageDescriptors(fEnableFilter, SearchPluginImages.T_LCL, SearchPluginImages.IMG_LCL_SEARCH_FILTER); + + fLoadAction= new Action() { + public void run() { + onLoad(); + } + }; + fLoadAction.setText(SearchMessages.RetrieverPage_LoadQuery_text); + fLoadAction.setToolTipText(SearchMessages.RetrieverPage_LoadQuery_tooltip); + + fStoreAction= new Action() { + public void run() { + onStore(); + } + }; + fStoreAction.setText(SearchMessages.RetrieverPage_SaveQuery_text); + fStoreAction.setToolTipText(SearchMessages.RetrieverPage_SaveQuery_tooltip); + + fCreateWSAction= new Action() { + public void run() { + onCreateWorkingSet(); + } + }; + fCreateWSAction.setText(SearchMessages.RetrieverPage_CreateWorkingSet_text); + fCreateWSAction.setToolTipText(SearchMessages.RetrieverPage_CreateWorkingSet_tooltip); + + + fUseCaseSensitiveFilePatterns= new Action() { + public void run() { + onUseCaseSensitiveFilePatterns(); + } + }; + fUseCaseSensitiveFilePatterns.setText(SearchMessages.RetrieverPage_CaseSensitiveFilePatterns_text); + + fConsiderDerivedResources= new Action() { + public void run() { + onConsiderDerivedResources(); + } + }; + fConsiderDerivedResources.setText(SearchMessages.RetrieverPage_ConsiderDerived_text); + } + + protected void onConsiderDerivedResources() { + sLastConsiderDerivedResources= fConsiderDerivedResources.isChecked(); + } + + protected void onUseCaseSensitiveFilePatterns() { + sLastUseCaseSensitiveFilePatterns= fUseCaseSensitiveFilePatterns.isChecked(); + } + + private void onChangeLayout(boolean flat) { + fUseFlatLayout= flat; + fLabelProvider.setAppendFileContainer(flat); + fContentProvider.setLayout(flat); + getViewer().refresh(); + storeValues(); + } + + + protected void onCreateWorkingSet() { + Object[] lines= null; + String searchString= null; + AbstractTextSearchResult input= getInput(); + if (input != null) { + lines= input.getElements(); + RetrieverQuery q= (RetrieverQuery) input.getQuery(); + if (q != null) { + searchString= q.getSearchText(); + } + } + if (lines == null || searchString == null || lines.length < 1) { + showError(SearchMessages.RetrieverPage_error_noResourcesForWorkingSet); + return; + } + InputDialog dlg= new InputDialog(getSite().getShell(), SearchMessages.RetrieverPage_CreateWorkingsetDialog_title, SearchMessages.RetrieverPage_CreateWorkingSetDialog_description, "contains-" + searchString, null); //$NON-NLS-1$ + if (dlg.open() == Window.OK) { + String name= dlg.getValue(); + IWorkingSetManager wsm= PlatformUI.getWorkbench().getWorkingSetManager(); + IWorkingSet ws= wsm.getWorkingSet(name); + if (ws != null) { + if (!showQuestion(SearchMessages.RetrieverPage_question_overwriteWorkingSet)) { + onCreateWorkingSet(); + return; + } + } + HashSet fileset= new HashSet(); + for (int i= 0; i < lines.length; i++) { + RetrieverLine line= (RetrieverLine) lines[i]; + fileset.add(line.getParent()); + } + IFile[] files= (IFile[]) fileset.toArray(new IFile[fileset.size()]); + if (ws == null) { + ws= wsm.createWorkingSet(name, files); + ws.setId("org.eclipse.ui.resourceWorkingSetPage"); //$NON-NLS-1$ + wsm.addWorkingSet(ws); + } else { + ws.setElements(files); + } + wsm.addRecentWorkingSet(ws); + } + } + + protected void onLoad() { + FileDialog dlg= new FileDialog(getSite().getShell(), SWT.OPEN); + dlg.setFilterPath(SearchPlugin.getDefault().getStateLocation().toOSString()); + dlg.setFilterExtensions(new String[] {"*" + QUERY_EXTENSION}); //$NON-NLS-1$ + String path= dlg.open(); + if (path != null) { + InputStream in; + Properties props= new Properties(); + try { + in= new FileInputStream(path); + props.load(in); + fSearchControl.restoreValues(props); + fFilterControl.setProperties(props); + fReplaceControl.setProperties(props); + } catch (IOException e) { + handleError(SearchMessages.RetrieverPage_error_cannotLoadQuery, e, true); + } + storeValues(); + onFilterTabChanged(); + } + } + + protected void onStore() { + Properties props= new Properties(); + fSearchControl.storeValues(props); + fFilterControl.getProperties(props); + fReplaceControl.getProperties(props); + + FileDialog dlg= new FileDialog(getSite().getShell(), SWT.SAVE); + dlg.setFilterPath(SearchPlugin.getDefault().getStateLocation().toOSString()); + dlg.setFilterExtensions(new String[] {"*" + QUERY_EXTENSION}); //$NON-NLS-1$ + String path= dlg.open(); + if (path != null) { + if (!path.endsWith(QUERY_EXTENSION)) { + path+= QUERY_EXTENSION; + } + OutputStream out; + try { + out= new FileOutputStream(path); + props.store(out, "Query for retriever"); //$NON-NLS-1$ + } catch (IOException e) { + handleError(SearchMessages.RetrieverPage_error_cannotStoreQuery, e, true); + } + } + } + + + protected void onTabChanged() { + int idx= fTabFolder.getSelectionIndex(); + switch (idx) { + case 0: + fSearchControl.onSelected(); + break; + case 1: + fFilterControl.onSelected(); + break; + case 2: + fReplaceControl.onSelected(); + break; + } + } + + // called by the filter tab + public void onFilterTabChanged() { + RetrieverResult r= (RetrieverResult) getInput(); + if (r != null) { + r.filter(fFilterControl.getFilter()); + } + postEnsureSelection(); + } + + public void onEnableToolbarFilter(boolean enable) { + fEnableFilter.setChecked(enable); + fFilterControl.onEnableToolbarFilter(enable); + onFilterTabChanged(); + storeValues(); + if (enable) { + fTabFolder.setSelection(1); + fFilterControl.onSelected(); + } + } + + void showError(String errorTxt) { + MessageDialog.openError(getSite().getShell(), SearchMessages.RetrieverPage_ErrorDialog_title, errorTxt); + } + + boolean showQuestion(String qtext) { + return MessageDialog.openQuestion(getSite().getShell(), SearchMessages.RetrieverPage_QuestionDialog_title, qtext); + } + + void showInformation(String itext) { + MessageDialog.openInformation(getSite().getShell(), SearchMessages.RetrieverPage_InformationDialog_title, itext); + } + + void storeValues() { + int[] weights= fSplitter.getWeights(); + fDialogSettings.put(KEY_SPLITTER_W1, weights[0]); + fDialogSettings.put(KEY_SPLITTER_W2, weights[1]); + fDialogSettings.put(KEY_ENABLE_FILTER, fEnableFilter.isChecked()); + fDialogSettings.put(KEY_CONSIDER_DERIVED_RESOURCES, fConsiderDerivedResources.isChecked()); + fDialogSettings.put(KEY_USE_CASE_SENSITIVE_FILE_PATTERNS, fUseCaseSensitiveFilePatterns.isChecked()); + fDialogSettings.put(KEY_USE_FLAT_LAYOUT, fUseFlatLayout); + sLastUseFlatLayout= fUseFlatLayout; + sLastConsiderDerivedResources= fConsiderDerivedResources.isChecked(); + sLastUseCaseSensitiveFilePatterns= fUseCaseSensitiveFilePatterns.isChecked(); + + fSearchControl.storeValues(); + fFilterControl.storeValues(); + fReplaceControl.storeValues(); + } + + private void restoreCurrentLayout() { + if (fDialogSettings.get(KEY_USE_FLAT_LAYOUT) == null) { + fUseFlatLayout= true; + } else { + fUseFlatLayout= fDialogSettings.getBoolean(KEY_USE_FLAT_LAYOUT); + } + } + + private void restoreValues() { + int[] weights= new int[] {0, 0}; + try { + weights[0]= fDialogSettings.getInt(KEY_SPLITTER_W1); + weights[1]= fDialogSettings.getInt(KEY_SPLITTER_W2); + fSplitter.setWeights(weights); + } catch (Exception e) { + } + restoreAction(fEnableFilter, KEY_ENABLE_FILTER, false); + restoreAction(fUseCaseSensitiveFilePatterns, KEY_USE_CASE_SENSITIVE_FILE_PATTERNS, false); + restoreAction(fConsiderDerivedResources, KEY_CONSIDER_DERIVED_RESOURCES, false); + fSearchControl.restoreValues(); + fFilterControl.restoreValues(fEnableFilter.isChecked()); + fReplaceControl.restoreValues(); + fFlatAction.setChecked(fUseFlatLayout); + fHierarchicalAction.setChecked(!fUseFlatLayout); + } + + + void storeButton(Button button, String key) { + if (button != null) { + fDialogSettings.put(key, button.getSelection()); + } + } + + void storeValue(boolean val, String key) { + fDialogSettings.put(key, val); + } + + public void storeValue(String[] val, String key) { + fDialogSettings.put(key, val); + } + + void storeComboContent(Combo combo, String key, int maxItems) { + String ckey= key + KEY_EXT_COMBO_CONTENT; + String[] stored= fDialogSettings.getArray(ckey); + if (stored == null) { + stored= new String[0]; + } + + // copy elements + String text= combo.getText(); + ArrayList newElems= new ArrayList(); + if (text.length() > 0) { + newElems.add(text); + } + + for (int i= 0; i < stored.length && newElems.size() < maxItems; i++) { + String elem= stored[i]; + if (!text.equals(elem)) { + newElems.add(elem); + } + } + + String[] save= (String[]) newElems.toArray(new String[newElems.size()]); + fDialogSettings.put(ckey, save); + fDialogSettings.put(key, text); + + // redo the combo + combo.removeAll(); + combo.setItems(save); + combo.setText(text); + } + + void storeScope(IScopeDescription scope, String key) { + IDialogSettings ds= fDialogSettings.addNewSection(key); + ds.put(KEY_SCOPE_DESCRIPTOR_CLASS, scope.getClass().getName()); + scope.store(ds); + } + + boolean restoreValue(String key, boolean defaultValue) { + if (fDialogSettings.get(key) != null) { + defaultValue= fDialogSettings.getBoolean(key); + } + return defaultValue; + } + + public String[] restoreValue(String key, String[] defaultValue) { + String[] result= fDialogSettings.getArray(key); + return result == null ? defaultValue : result; + } + + + void restoreButton(Button button, String key, boolean defaultValue) { + if (button != null) { + if (fDialogSettings.get(key) != null) { + defaultValue= fDialogSettings.getBoolean(key); + } + button.setSelection(defaultValue); + } + } + + void restoreAction(Action button, String key, boolean defaultValue) { + if (fDialogSettings.get(key) != null) { + defaultValue= fDialogSettings.getBoolean(key); + } + button.setChecked(defaultValue); + } + + void restoreCombo(Combo combo, String key, String def) { + String ckey= key + KEY_EXT_COMBO_CONTENT; + String[] stored= fDialogSettings.getArray(ckey); + if (stored != null && stored.length > 0) { + combo.setItems(stored); + } + String text= fDialogSettings.get(key); + if (text == null) { + text= def; + } + if (text != null && text.length() > 0) { + combo.setText(text); + } + } + + public IScopeDescription restoreScope(String key) { + return getScope(fDialogSettings, key); + } + + IStructuredSelection getSelection() { + return (IStructuredSelection) getViewer().getSelection(); + } + + void handleError(String emsg, Exception e, boolean show) { + if (show) { + showError(emsg); + } else { + SearchPlugin.log(new Status(IStatus.ERROR, NewSearchUI.PLUGIN_ID, SearchPlugin.INTERNAL_ERROR, emsg, e)); + } + } + + protected void elementsChanged(Object[] objects) { + if (fContentProvider != null) + fContentProvider.elementsChanged(objects); + } + + protected void clear() { + if (fContentProvider != null) + fContentProvider.clear(); + } + + protected void configureTableViewer(TableViewer viewer) { + } + + protected TreeViewer createTreeViewer(Composite parent) { + return new RetrieverTreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + } + + protected void configureTreeViewer(TreeViewer viewer) { + viewer.setUseHashlookup(true); + fLabelProvider= new RetrieverLabelProvider(this, FileLabelProvider.SHOW_LABEL); + fLabelProvider.setAppendFileContainer(fUseFlatLayout); + viewer.setLabelProvider(new DecoratingLabelProvider(fLabelProvider, PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator())); + fContentProvider= new RetrieverContentProvider((RetrieverTreeViewer) viewer, fUseFlatLayout); + viewer.setContentProvider(fContentProvider); + fSorter= new RetrieverViewerSorter(fLabelProvider); + viewer.setSorter(fSorter); + viewer.addTreeListener(new ITreeViewerListener() { + public void treeCollapsed(TreeExpansionEvent event) { + fContentProvider.onExpansionStateChange(event.getElement(), false); + } + public void treeExpanded(TreeExpansionEvent event) { + fContentProvider.onExpansionStateChange(event.getElement(), true); + } + }); + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + fContentProvider.onSelectionChanged(event); + } + }); + + addDragAdapters(viewer); + } + + public TreeViewer getTreeViewer() { + return (TreeViewer) getViewer(); + } + + public ISearchResultViewPart getViewPart() { + return fViewPart; + } + + synchronized public void setInput(ISearchResult result, Object viewState) { + fSearchInProgress= false; + if (result != null) { + ISearchQuery query= result.getQuery(); + if (query instanceof RetrieverQuery) { + RetrieverQuery rq= (RetrieverQuery) query; + restoreFromQuery(rq); + fSearchInProgress= NewSearchUI.isQueryRunning(query); + } + } + super.setInput(result, viewState); + updateEnablementOnTabs(); + setFocus(); + } + + private void restoreFromQuery(RetrieverQuery rq) { + fConsiderDerivedResources.setChecked(rq.getConsiderDerivedResources()); + fUseCaseSensitiveFilePatterns.setChecked(rq.getUseCaseSensitiveFilePatterns()); + fSearchControl.restoreFromQuery(rq); + initFilter((RetrieverResult) rq.getSearchResult()); + fReplaceControl.setPattern(rq.createSearchPattern()); + String searchText= rq.getSearchText(); + if (searchText == null || searchText.length() == 0) { + fTabFolder.setSelection(0); + } + } + + private void updateEnablementOnTabs() { + fSearchControl.updateEnablement(fSearchInProgress); + fReplaceControl.updateEnablement(fSearchInProgress); + } + + private void addDragAdapters(StructuredViewer viewer) { + Transfer[] transfers= new Transfer[] {ResourceTransfer.getInstance()}; + int ops= DND.DROP_COPY | DND.DROP_LINK; + + DelegatingDragAdapter adapter= new DelegatingDragAdapter(); + adapter.addDragSourceListener(new ResourceTransferDragAdapter(viewer)); + + viewer.addDragSupport(ops, transfers, adapter); + } + + protected void showMatch(Match match, int offset, int length, boolean activate) throws PartInitException { + AbstractTextSearchResult result= getInput(); + if (result != null) { + IFile file= result.getFileMatchAdapter().getFile(match.getElement()); + IEditorPart editor= fEditorOpener.open(file, activate); + if (offset != 0 && length != 0) { + if (editor instanceof ITextEditor) { + ITextEditor textEditor= (ITextEditor) editor; + textEditor.selectAndReveal(offset, length); + } else + if (editor != null) { + showWithMarker(editor, file, offset, length); + } + } + } + fReplaceControl.updatePreview(null); + } + + private void showWithMarker(IEditorPart editor, IFile file, int offset, int length) throws PartInitException { + IMarker marker= null; + try { + marker= file.createMarker(NewSearchUI.SEARCH_MARKER); + HashMap attributes= new HashMap(4); + attributes.put(IMarker.CHAR_START, new Integer(offset)); + attributes.put(IMarker.CHAR_END, new Integer(offset + length)); + marker.setAttributes(attributes); + IDE.gotoMarker(editor, marker); + } catch (CoreException e) { + throw new PartInitException(org.eclipse.search.internal.ui.SearchMessages.FileSearchPage_error_marker, e); + } finally { + if (marker != null) + try { + marker.delete(); + } catch (CoreException e) { + // ignore + } + } + } + + public void queryAdded(ISearchQuery query) { + } + + public void queryRemoved(ISearchQuery query) { + } + + synchronized public void queryStarting(ISearchQuery query) { + AbstractTextSearchResult result= getInput(); + if (result != null && result.getQuery() == query) { + fSearchInProgress= true; + asyncUpdateEnablement(); + } + } + + synchronized public void queryFinished(ISearchQuery query) { + AbstractTextSearchResult result= getInput(); + if (result != null && result.getQuery() == query) { + fSearchInProgress= false; + asyncUpdateEnablement(); + } + } + + private void asyncUpdateEnablement() { + asyncExec(new Runnable() { + public void run() { + if (fFilterControl != null) { + updateEnablementOnTabs(); + } + } + }); + } + + private void asyncExec(Runnable runnable) { + Display display= getSite().getShell().getDisplay(); + if (display != null) { + display.asyncExec(runnable); + } + } + + public static IDialogSettings createSection(IDialogSettings ds, String name) { + IDialogSettings result= ds.getSection(name); + if (result == null) { + result= ds.addNewSection(name); + } + return result; + } + + public static void initializeQuery(RetrieverQuery query) { + if (sLastSearchPattern == null) { + initializeLastQuery(); + } + query.setSearchString(sLastSearchPattern); + query.setIsCaseSensitive(sLastIsCaseSensitive); + query.setIsRegularExpression(sLastIsRegularExpression); + query.setIsWholeWord(sLastIsWholeWord); + query.setSearchScope(sLastScope, sLastConsiderDerivedResources); + query.setFilePatterns(sLastFilePatterns, sLastUseCaseSensitiveFilePatterns); + query.setSearchOrder(sLastUseFlatLayout ? FLAT_SORTER : HIERARCHICAL_SORTER); + } + + + private static void initializeLastQuery() { + IDialogSettings ds= SearchPlugin.getDefault().getDialogSettings(); + ds= createSection(ds, RetrieverPage.class.getName()); + + sLastSearchPattern= getValue(ds, KEY_SEARCH_STRINGS, null); + sLastIsCaseSensitive= getValue(ds, KEY_CASE_SENSITIVE_SEARCH, false); + sLastIsRegularExpression= getValue(ds, KEY_REGULAR_EXPRESSION_SEARCH, false); + sLastIsWholeWord= getValue(ds, KEY_WHOLE_WORD, true); + sLastConsiderDerivedResources= getValue(ds, KEY_CONSIDER_DERIVED_RESOURCES, false); + sLastFilePatterns= getValue(ds, KEY_FILE_PATTERNS, "*.c,*.cpp,*.h,*.java"); //$NON-NLS-1$ + sLastUseCaseSensitiveFilePatterns= getValue(ds, KEY_USE_CASE_SENSITIVE_FILE_PATTERNS, false); + sLastUseFlatLayout= getValue(ds, KEY_USE_FLAT_LAYOUT, false); + sLastScope= getScope(ds, KEY_SEARCH_SCOPE); + } + + private static String getValue(IDialogSettings ds, String key, String def) { + String result= ds.get(key); + return result == null ? def : result; + } + + private static boolean getValue(IDialogSettings ds, String key, boolean def) { + String result= ds.get(key); + return result == null ? def : ds.getBoolean(key); + } + + private static IScopeDescription getScope(IDialogSettings ds, String key) { + ds= ds.getSection(key); + if (ds != null) { + String scopeDescClass= getValue(ds, KEY_SCOPE_DESCRIPTOR_CLASS, WorkspaceScopeDescription.class.getName()); + try { + IScopeDescription result= (IScopeDescription) Class.forName(scopeDescClass).newInstance(); + result.restore(ds); + return result; + } catch (Exception e) { + e.printStackTrace(); + } + } + return new WorkspaceScopeDescription(); + } + + public void initFilter(RetrieverResult result) { + RetrieverFilter filter= result.getFilter(); + if (filter == null) { + result.filter(fFilterControl.getFilter()); + } else { + fRecentFilter= filter; + handleNewFilterFromResult(); + } + + } + + private void handleNewFilterFromResult() { + fEnableFilter.setChecked(fFilterControl.restoreFromResult(fRecentFilter)); + } + + /* (non-Javadoc) + * @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#handleSearchResultChanged(org.eclipse.search.ui.SearchResultEvent) + */ + protected void handleSearchResultChanged(SearchResultEvent e) { + super.handleSearchResultChanged(e); + if (e instanceof FilterMatchEvent) { + RetrieverFilter filter= ((RetrieverResult) e.getSearchResult()).getFilter(); + if (filter != fRecentFilter) { + fRecentFilter= filter; + asyncExec(new Runnable() { + public void run() { + // make sure we are not disposed + if (fFilterControl != null) { + handleNewFilterFromResult(); + } + } + }); + } + } + } + + public Comparator getPreferredSearchOrder() { + return fUseFlatLayout ? FLAT_SORTER : HIERARCHICAL_SORTER; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverQuery.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverQuery.java new file mode 100644 index 00000000000..7c40e82b194 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverQuery.java @@ -0,0 +1,330 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.regex.Pattern; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; + +import org.eclipse.ui.IWorkbenchPage; + +import org.eclipse.search.ui.ISearchQuery; +import org.eclipse.search.ui.ISearchResult; + +import org.eclipse.search.core.text.AbstractTextFileScanner; +import org.eclipse.search.core.text.TextSearchEngine; +import org.eclipse.search.core.text.TextSearchMatchAccess; +import org.eclipse.search.core.text.TextSearchRequestor; +import org.eclipse.search.core.text.TextSearchScope; +import org.eclipse.search.core.text.AbstractTextFileScanner.LineInformation; + +import org.eclipse.search.internal.core.text.PatternConstructor; +import org.eclipse.search.internal.ui.text.SearchResultUpdater; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class RetrieverQuery implements ISearchQuery, IRetrieverKeys { + private String fSearchPattern= ""; //$NON-NLS-1$ + private boolean fIsCaseSensitive; + private boolean fIsRegularExpression; + private boolean fIsWholeWord; + private boolean fConsiderDerivedResources; + private boolean fUseCaseSensitiveFilePatterns; + private IScopeDescription fScope; + private String[] fFilePatterns; + private RetrieverLine fCurrentLine; + private int fCurrentLineOffset; + private RetrieverResult fResult; + private ArrayList fLinesOfCurrentFile; + private IWorkbenchPage fWorkbenchPage; + private AbstractTextFileScanner fScanner; + private Comparator fSearchOrder; + + + public RetrieverQuery(IWorkbenchPage page) { + fWorkbenchPage= page; + } + + public void setSearchString(String searchFor) { + fSearchPattern= searchFor == null ? "" : searchFor; //$NON-NLS-1$ + } + public void setIsCaseSensitive(boolean isCaseSensitive) { + fIsCaseSensitive= isCaseSensitive; + } + public void setIsRegularExpression(boolean isRegularExpression) { + fIsRegularExpression= isRegularExpression; + } + public void setIsWholeWord(boolean isWholeWord) { + fIsWholeWord= isWholeWord; + } + + public void setSearchScope(IScopeDescription scope) { + fScope= scope; + } + + public void setSearchScope(IScopeDescription scope, boolean considerDerived) { + fScope= scope; + fConsiderDerivedResources= considerDerived; + } + + public void setFilePatterns(String filePatterns, boolean caseSensitive) { + fFilePatterns= filePatterns.split(FilePatternSelectionDialog.FILE_PATTERN_SEPERATOR); + fUseCaseSensitiveFilePatterns= caseSensitive; + } + + public void setFilePatterns(String[] fileNamePatterns) { + fFilePatterns= (String[]) fileNamePatterns.clone(); + } + + public String getLabel() { + return SearchMessages.RetrieverQuery_label; + } + + public boolean canRerun() { + return true; + } + + public boolean canRunInBackground() { + return true; + } + + public ISearchResult getSearchResult() { + if (fResult == null) { + fResult= new RetrieverResult(this); + new SearchResultUpdater(fResult); + } + return fResult; + } + + public IStatus run(IProgressMonitor monitor) throws OperationCanceledException { + if (fSearchPattern.length() == 0) { + return Status.OK_STATUS; + } + if (fResult != null) { + fResult.removeAll(); + fResult.setComplete(false); + } + + TextSearchScope scope= createSearchScope(fWorkbenchPage); + return performSearch(monitor, scope); + } + + private IStatus performSearch(IProgressMonitor monitor, TextSearchScope scope) { + TextSearchEngine engine= TextSearchEngine.create(); + engine.setSearchOrderHint(fSearchOrder); + TextSearchRequestor requestor= createRequestor(); + Pattern searchPattern= createSearchPattern(); + + if (fResult != null) { + fResult.setComplete(false); + } + + IStatus status= engine.search(scope, requestor, searchPattern, monitor); + return status; + } + + Pattern createSearchPattern() { + return PatternConstructor.createPattern(fSearchPattern, fIsRegularExpression, false, fIsCaseSensitive, fIsWholeWord); + } + + private TextSearchScope createSearchScope(IWorkbenchPage page) { + RetrieverSearchScope scope= new RetrieverSearchScope(fScope.getRoots(page), fFilePatterns, fUseCaseSensitiveFilePatterns); + scope.setVisitDerived(fConsiderDerivedResources); + return scope; + } + + private TextSearchRequestor createRequestor() { + return new TextSearchRequestor() { + public boolean acceptFile(IFile file) throws CoreException { + onAcceptFile(file); + return true; + } + public boolean acceptPatternMatch(TextSearchMatchAccess matchAccess) throws CoreException { + onAcceptPatternMatch(matchAccess); + return true; + } + public void beginReporting() { + onBeginReporting(); + } + public void endReporting() { + onEndReporting(); + } + }; + } + + protected void onBeginReporting() { + fLinesOfCurrentFile= new ArrayList(); + getSearchResult(); + fScanner= null; + fCurrentLine= null; + } + + protected void onAcceptFile(IFile file) { + flushMatches(); + if (fScanner != null) { + fScanner.reset(); + } + fScanner= null; + fCurrentLine= null; + } + + protected void onAcceptPatternMatch(TextSearchMatchAccess matchAccess) { + if (fScanner == null) { + fScanner= selectScanner(matchAccess); + } + int offset= matchAccess.getMatchOffset(); + int length= matchAccess.getMatchLength(); + int kind= fScanner.getLocationKind(matchAccess); + int shiftedkind= 1; + if (kind >= 0 && kind < 32) { + shiftedkind= 1 << kind; + } + setupCurrentLine(matchAccess); + int column= offset - fCurrentLineOffset; + int endcolumn= column + length; + String original= null; + if (fCurrentLine.getLength() >= endcolumn) { + original= fCurrentLine.substring(column, endcolumn); + } else { + StringBuffer match= new StringBuffer(length); + int end= offset + length; + for (int i= offset; i < end; i++) { + match.append(matchAccess.getFileContentChar(i)); + } + original= match.toString(); + } + RetrieverMatch match= new RetrieverMatch(fCurrentLine, original, offset, length, column, shiftedkind); + fCurrentLine.addMatch(match); + } + + protected void onEndReporting() { + fResult.setComplete(true); + flushMatches(); + if (fScanner != null) { + fScanner.reset(); + } + fScanner= null; + fCurrentLine= null; + fLinesOfCurrentFile= null; + } + + private void setupCurrentLine(TextSearchMatchAccess match) { + LineInformation info= fScanner.getLineInformation(match); + int lineNumber= info.getLineNumber(); + if (fCurrentLine == null || fCurrentLine.getLineNumber() != lineNumber) { + fCurrentLineOffset= info.getLineOffset(); + final int lineLength= Math.min(info.getLineLength(), MAX_COMBINED_LINE_LENGTH); + final int lineEndOffset= fCurrentLineOffset + lineLength; + final int matchEndOffset= match.getMatchOffset() + match.getMatchLength(); + + StringBuffer lineData= new StringBuffer(lineLength); + for (int i= fCurrentLineOffset; i < lineEndOffset; i++) { + lineData.append(match.getFileContentChar(i)); + } + + // check the last two characters separately + if (lineEndOffset > matchEndOffset && lineLength > 0) { + char last= lineData.charAt(lineLength - 1); + if (last == '\n') { + if (lineEndOffset > matchEndOffset + 1 && lineLength > 1 && lineData.charAt(lineLength - 2) == '\r') { + lineData.setLength(lineLength - 2); + } else { + lineData.setLength(lineLength - 1); + } + } else + if (last == '\r') { + lineData.setLength(lineLength - 1); + } + } + + fCurrentLine= new RetrieverLine(match.getFile(), lineNumber); + fCurrentLine.setData(lineData.toString()); + fLinesOfCurrentFile.add(fCurrentLine); + } + } + + private void flushMatches() { + if (!fLinesOfCurrentFile.isEmpty()) { + fResult.setLinesForFile(fCurrentLine.getParent(), fLinesOfCurrentFile); + fLinesOfCurrentFile.clear(); + fCurrentLine= null; + } + } + + private AbstractTextFileScanner selectScanner(TextSearchMatchAccess matchAccess) { + AbstractTextFileScanner scanner= TextFileScannerRegistry.getInstance().findScanner(matchAccess.getFile()); + if (scanner == null) { + scanner= TextFileScannerRegistry.getInstance().getLineNumberScanner(); + } + return scanner; + } + + + public IScopeDescription getScopeDescription() { + return fScope; + } + + public boolean isCaseSensitive() { + return fIsCaseSensitive; + } + + public boolean isRegularExpression() { + return fIsRegularExpression; + } + + public boolean isWholeWord() { + return fIsWholeWord; + } + + public String getSearchText() { + return fSearchPattern; + } + + public boolean getUseCaseSensitiveFilePatterns() { + return fUseCaseSensitiveFilePatterns; + } + + public String getFilePatterns() { + StringBuffer buffer= new StringBuffer(); + for (int i= 0; i < fFilePatterns.length; i++) { + if (i > 0) { + buffer.append(FilePatternSelectionDialog.FILE_PATTERN_SEPERATOR); + } + buffer.append(fFilePatterns[i]); + } + + return buffer.toString(); + } + + public boolean getConsiderDerivedResources() { + return fConsiderDerivedResources; + } + + public void searchAgain(Collection outdated, IProgressMonitor monitor) { + TextSearchScope scope= new RetrieverSearchScope((IResource[]) outdated.toArray(new IResource[outdated.size()]), new String[] {"*"}, true); //$NON-NLS-1$ + performSearch(monitor, scope); + } + + public void setSearchOrder(Comparator searchOrder) { + fSearchOrder= searchOrder; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverReplaceTab.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverReplaceTab.java new file mode 100644 index 00000000000..8e06c9ce7de --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverReplaceTab.java @@ -0,0 +1,470 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.search2.internal.ui.text2; + +import java.util.Properties; +import java.util.regex.Pattern; + +import org.eclipse.core.filebuffers.FileBuffers; +import org.eclipse.core.filebuffers.ITextFileBuffer; + +import org.eclipse.core.runtime.IPath; + +import org.eclipse.core.resources.IFile; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.Viewer; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; + +import org.eclipse.search.ui.IContextMenuConstants; + +import org.eclipse.search.internal.ui.util.SWTUtil; + +import org.eclipse.search2.internal.ui.InternalSearchUI; +import org.eclipse.search2.internal.ui.SearchMessages; + +/** + * @author markus.schorn@windriver.com + */ +public class RetrieverReplaceTab implements IRetrieverKeys { + private RetrieverPage fView; + + private Combo fReplacementCombo; + private Button fNextButton; + private Button fReplaceNextButton; + private Button fRestoreNextButton; + private Button fReplaceRestoreButton; + private Button fReplaceAllButton; + private Button fRestoreAllButton; + private Text fPreviewLine; + private Pattern fSearchPattern; + private boolean fSearchInProgress; + + private RetrieverMatch fMatchOfPreview; + + + public RetrieverReplaceTab(RetrieverPage view) { + fView= view; + } + + public void createControl(Composite parent) { + GridLayout gl; + GridData gd; + + Composite group= new Composite(parent, SWT.NONE); + group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + group.setLayout(gl= new GridLayout(2, false)); + gl.marginHeight= gl.marginWidth= 0; + + // line 1 + Label l= new Label(group, SWT.NONE); + l.setText(SearchMessages.RetrieverReplaceTab_ReplaceWith_label); + + fReplacementCombo= new Combo(group, SWT.NONE); + fReplacementCombo.setVisibleItemCount(VISIBLE_ITEMS_IN_COMBO); + fReplacementCombo.setLayoutData(gd= new GridData(GridData.FILL_HORIZONTAL)); + gd.widthHint= 20; + + // line 2 + group= new Composite(parent, SWT.NONE); + group.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); + group.setLayout(gl= new GridLayout(1, true)); + gl.marginHeight= gl.marginWidth= 0; + + Composite lg= new Composite(group, SWT.NONE); + lg.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + lg.setLayout(gl= new GridLayout(3, true)); + gl.marginHeight= gl.marginWidth= 0; + gl.verticalSpacing= gl.horizontalSpacing= 2; + + fNextButton= new Button(lg, SWT.NONE); + fNextButton.setText(SearchMessages.RetrieverReplaceTab_Find_text); + fNextButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + SWTUtil.setButtonDimensionHint(fNextButton); + + fReplaceNextButton= new Button(lg, SWT.NONE); + fReplaceNextButton.setText(SearchMessages.RetrieverReplaceTab_ReplaceFind_text); + fReplaceNextButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + SWTUtil.setButtonDimensionHint(fReplaceNextButton); + + fRestoreNextButton= new Button(lg, SWT.NONE); + fRestoreNextButton.setText(SearchMessages.RetrieverReplaceTab_RestoreFind_text); + fRestoreNextButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + SWTUtil.setButtonDimensionHint(fRestoreNextButton); + + fReplaceRestoreButton= new Button(lg, SWT.NONE); + fReplaceRestoreButton.setText(SearchMessages.RetrieverReplaceTab_Replace_text); + fReplaceRestoreButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + SWTUtil.setButtonDimensionHint(fReplaceRestoreButton); + + fReplaceAllButton= new Button(lg, SWT.NONE); + fReplaceAllButton.setText(SearchMessages.RetrieverReplaceTab_ReplaceAll_text); + fReplaceAllButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + SWTUtil.setButtonDimensionHint(fReplaceAllButton); + + fRestoreAllButton= new Button(lg, SWT.NONE); + fRestoreAllButton.setText(SearchMessages.RetrieverReplaceTab_RestoreAll_text); + fRestoreAllButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + SWTUtil.setButtonDimensionHint(fRestoreAllButton); + + // line 4 + group= new Composite(parent, SWT.NONE); + group.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + group.setLayout(gl= new GridLayout(1, true)); + gl.marginHeight= gl.marginWidth= 0; + gl.verticalSpacing= 2; + + l= new Label(group, SWT.NONE); + l.setText(SearchMessages.RetrieverReplaceTab_Preview_label); + + fPreviewLine= new Text(group, SWT.READ_ONLY | SWT.BORDER); + fPreviewLine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + } + + void createListeners(Viewer resultViewer) { + resultViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + onSelectionChanged((IStructuredSelection) event.getSelection()); + } + }); + + fReplacementCombo.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + } + public void keyReleased(KeyEvent e) { + onReplacementChange(); + } + }); + fReplacementCombo.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onReplacementChange(); + } + }); + fNextButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + fView.gotoNextMatch(); + } + }); + fReplaceRestoreButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + if (fMatchOfPreview != null) { + onReplace(!fMatchOfPreview.isReplaced(), false, fReplaceRestoreButton.getText()); + } + } + }); + fReplaceNextButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onReplace(true, true, fReplaceNextButton.getText()); + } + }); + fRestoreNextButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onReplace(false, true, fRestoreNextButton.getText()); + } + }); + fReplaceAllButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onReplaceAll(true, fReplaceAllButton.getText()); + } + }); + fRestoreAllButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + onReplaceAll(false, fRestoreAllButton.getText()); + } + }); + } + + void createActions() { + } + + protected void onReplacementChange() { + updatePreview(fView.getSelection()); + } + + protected void updatePreview(ISelection sel) { + fMatchOfPreview= (RetrieverMatch) fView.getCurrentMatch(); + if (fMatchOfPreview == null) { + fMatchOfPreview= getMatchOfSelection(sel); + } + String preview= null; + if (fMatchOfPreview != null) { + preview= computePreview(fMatchOfPreview); + } + if (preview == null) { + preview= ""; //$NON-NLS-1$ + } + fPreviewLine.setText(preview); + } + + private RetrieverMatch getMatchOfSelection(ISelection sel) { + if (sel instanceof IStructuredSelection) { + Object element= ((IStructuredSelection) sel).getFirstElement(); + if (element instanceof RetrieverLine) { + RetrieverMatch[] matches= ((RetrieverLine) element).getDisplayedMatches(); + if (matches.length > 0) { + return matches[0]; + } + } + } + return null; + } + + protected void onSelectionChanged(IStructuredSelection sel) { + // compute preview + updatePreview(sel); + + if (fSearchInProgress) { + fReplaceRestoreButton.setEnabled(false); + fReplaceNextButton.setEnabled(false); + fRestoreNextButton.setEnabled(false); + fReplaceAllButton.setEnabled(false); + fRestoreAllButton.setEnabled(false); + return; + } + + if (fMatchOfPreview != null) { + boolean replaced= fMatchOfPreview.isReplaced(); + fReplaceRestoreButton.setEnabled(true); + fReplaceRestoreButton.setText(replaced ? SearchMessages.RetrieverReplaceTab_Restore_text : SearchMessages.RetrieverReplaceTab_Replace_text); + fReplaceNextButton.setEnabled(!replaced); + fRestoreNextButton.setEnabled(replaced); + } + fReplaceAllButton.setEnabled(true); + fRestoreAllButton.setEnabled(true); + + } + + private String computePreview(RetrieverMatch match) { + RetrieverLine line= match.getLine(); + IFile file= line.getParent(); + IDocument doc= null; + if (file != null) { + IPath path= file.getFullPath(); + ITextFileBuffer txfbuf= FileBuffers.getTextFileBufferManager().getTextFileBuffer(path); + if (txfbuf != null) { + doc= txfbuf.getDocument(); + } + } + + String pre, post; + if (doc != null) { + int offset1= match.getOffset(); + int offset2= offset1 + match.getLength(); + Position pos= InternalSearchUI.getInstance().getPositionTracker().getCurrentPosition(match); + if (pos != null) { + offset1= pos.offset; + offset2= offset1 + pos.length; + } + if (0 > offset1 || offset1 > offset2 || offset2 > doc.getLength()) { + return null; + } + String matchstr; + try { + int offset0= offset1; + int min= Math.max(0, offset1 - 1024); + while (offset0 > min) { + char c= doc.getChar(offset0 - 1); + if (c == '\n' || c == '\r') { + break; + } + offset0--; + } + int offset3= offset2; + int max= Math.min(doc.getLength(), offset2 + 1024); + while (offset3 < max) { + char c= doc.getChar(offset3); + if (c == '\n' || c == '\r') { + break; + } + offset3++; + } + // don't accept trailing \r + if (offset3 > offset2 && doc.getChar(offset3 - 1) == '\r') { + offset3--; + } + pre= doc.get(offset0, offset1 - offset0); + matchstr= doc.get(offset1, offset2 - offset1); + post= doc.get(offset2, offset3 - offset2); + } catch (BadLocationException e) { + return null; + } + if (!matchstr.equals(match.getCurrentText())) { + return null; + } + } else { + pre= line.getPreString(match); + post= line.getPostString(match); + } + + StringBuffer result= new StringBuffer(); + result.append(pre); + if (match.isReplaced()) { + result.append(match.getOriginal()); + } else { + String unescapedReplacement= getUnescapedReplacementString(); + String replacement= match.computeReplacement(fSearchPattern, unescapedReplacement); + if (replacement == null) { + return null; + } + result.append(replacement); + } + result.append(post); + return RetrieverLabelProvider.convertChars(result); + } + + private String getUnescapedReplacementString() { + return unescapeWhitespace(fReplacementCombo.getText()); + } + + private String unescapeWhitespace(String input) { + StringBuffer result= new StringBuffer(input.length()); + int i= 0; + while (i < input.length() - 1) { + char c= input.charAt(i); + i++; + if (c == '\\') { + c= input.charAt(i); + i++; + switch (c) { + case 't': + result.append('\t'); + break; + case 'r': + result.append('\r'); + break; + case 'n': + result.append('\n'); + break; + case '\\': + result.append('\\'); + result.append('\\'); + break; + default: + result.append('\\'); + result.append(c); + break; + } + } else { + result.append(c); + } + } + if (i < input.length()) { + result.append(input.charAt(i)); + } + + return result.toString(); + } + + protected void onReplace(boolean replace, boolean moveOn, String actionLabel) { + storeValues(); + if (fMatchOfPreview != null) { + ReplaceAction op= new ReplaceAction(fView, actionLabel, replace, fMatchOfPreview); + op.setReplacement(fSearchPattern, getUnescapedReplacementString()); + op.run(); + if (fView.getCurrentMatch() == null) { + fView.gotoNextMatch(); + } + if (moveOn && op.wasSuccessful()) { + fView.gotoNextMatch(); + } else { + onSelectionChanged(fView.getSelection()); + } + } + } + + protected void onReplaceAll(boolean replace, String actionLabel) { + storeValues(); + ReplaceAction op= new ReplaceAction(fView, actionLabel, replace); + op.setReplacement(fSearchPattern, getUnescapedReplacementString()); + op.run(); + } + + void storeValues() { + fView.storeComboContent(fReplacementCombo, KEY_REPLACEMENT_STRING, MAX_REPLACEMENT_STRINGS); + } + + void restoreValues() { + fView.restoreCombo(fReplacementCombo, KEY_REPLACEMENT_STRING, ""); //$NON-NLS-1$ + updateEnablement(true); + } + + public void setPattern(Pattern pattern) { + fSearchPattern= pattern; + } + + public void updateEnablement(boolean searchInProgress) { + if (fSearchInProgress != searchInProgress) { + fSearchInProgress= searchInProgress; + onSelectionChanged(fView.getSelection()); + } + } + + public void onSelected() { + fReplacementCombo.setFocus(); + } + + public void getProperties(Properties props) { + props.setProperty(KEY_REPLACEMENT_STRING, fReplacementCombo.getText()); + } + + public void setProperties(Properties props) { + String property= props.getProperty(KEY_REPLACEMENT_STRING); + if (property != null) { + fReplacementCombo.setText(property); + onReplacementChange(); + } + } + + public void fillContextMenu(IMenuManager mgr) { + IStructuredSelection sel= (IStructuredSelection) fView.getTreeViewer().getSelection(); + String replacement= getUnescapedReplacementString(); + if (sel != null && !sel.isEmpty()) { + ReplaceAction replaceAction= new ReplaceAction(fView, SearchMessages.RetrieverReplaceTab_ReplaceSelected_text, true, sel); + if (replaceAction.isEnabled()) { + replaceAction.setReplacement(fSearchPattern, replacement); + mgr.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, replaceAction); + } + ReplaceAction restoreAction= new ReplaceAction(fView, SearchMessages.RetrieverReplaceTab_RestoreSelected_text, false, sel); + if (restoreAction.isEnabled()) { + mgr.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, restoreAction); + } + } + ReplaceAction replaceAction= new ReplaceAction(fView, SearchMessages.RetrieverReplaceTab_ReplaceAll_text, true); + if (replaceAction.isEnabled()) { + replaceAction.setReplacement(fSearchPattern, replacement); + mgr.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, replaceAction); + } + ReplaceAction restoreAction= new ReplaceAction(fView, SearchMessages.RetrieverReplaceTab_RestoreAll_text, false); + if (restoreAction.isEnabled()) { + mgr.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, restoreAction); + } + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverResult.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverResult.java new file mode 100644 index 00000000000..8ad2adfa6f0 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverResult.java @@ -0,0 +1,292 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Pattern; + +import org.eclipse.core.runtime.NullProgressMonitor; + +import org.eclipse.core.resources.IFile; + +import org.eclipse.jface.resource.ImageDescriptor; + +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; + +import org.eclipse.search.ui.ISearchQuery; +import org.eclipse.search.ui.ISearchResult; +import org.eclipse.search.ui.SearchResultEvent; +import org.eclipse.search.ui.text.AbstractTextSearchResult; +import org.eclipse.search.ui.text.IEditorMatchAdapter; +import org.eclipse.search.ui.text.IFileMatchAdapter; +import org.eclipse.search.ui.text.Match; + +import org.eclipse.search.internal.ui.SearchPluginImages; + +import org.eclipse.search2.internal.ui.SearchMessages; + +/** + * @author markus.schorn@windriver.com + */ +class RetrieverResult extends AbstractTextSearchResult implements ISearchResult, IEditorMatchAdapter, IFileMatchAdapter, IRetrieverKeys { + private static final RetrieverMatch[] EMPTY_ARRAY= new RetrieverMatch[0]; + + private Pattern fFilterExpr; + private boolean fFilterHideMatching; + private int fAcceptLocations= 0; + private RetrieverQuery fQuery; + private boolean fIsComplete; + + private HashMap fFilesToLines= new HashMap(); + private FilterMatchEvent fFilterEvent= new FilterMatchEvent(this); + + private RetrieverFilter fFilter; + + public RetrieverResult(RetrieverQuery query) { + fQuery= query; + } + + public void filter(RetrieverFilter filter) { + fFilter= filter; + boolean hideMatches= filter.getHideMatching(); + int acceptLocations= filter.getAcceptedLocations(); + Pattern filterPattern= filter.getPattern(); + // check if filter has changed at all + if (fFilterHideMatching == hideMatches && acceptLocations == fAcceptLocations) { + if (filterPattern == fFilterExpr || (filterPattern != null && filterPattern.equals(fFilterExpr))) { + return; + } + } + + fFilterExpr= filterPattern; + fFilterHideMatching= hideMatches; + fAcceptLocations= acceptLocations; + + ArrayList changedMatches= new ArrayList(); + Object[] lines= getElements(); + for (int i= 0; i < lines.length; i++) { + RetrieverLine line= (RetrieverLine) lines[i]; + line.filter(fFilterExpr, fFilterHideMatching, fAcceptLocations, changedMatches); + } + synchronized (fFilterEvent) { + if (!changedMatches.isEmpty()) { + fireChange(getFilterSearchResultEvent(changedMatches)); + } + } + } + + private SearchResultEvent getFilterSearchResultEvent(ArrayList matches) { + Match[] matchArray= (Match[]) matches.toArray(new Match[matches.size()]); + fFilterEvent.setMatches(matchArray); + return fFilterEvent; + } + + public boolean hasFilter() { + return fFilterExpr != null || fAcceptLocations == ALL_LOCATIONS; + } + + public IEditorMatchAdapter getEditorMatchAdapter() { + return this; + } + + public IFileMatchAdapter getFileMatchAdapter() { + return this; + } + + public String getLabel() { + String pattern= fQuery.getSearchText(); + String scope= fQuery.getScopeDescription().getLabel(); + int matchCount= getMatchCount(); + + if (pattern.length() == 0) { + return SearchMessages.RetrieverResult_noInput_label; + } + return MessageFormat.format(SearchMessages.RetrieverResult_label, new Object[] {pattern, new Integer(matchCount), scope}); + } + + public String getTooltip() { + return getLabel(); + } + + public ImageDescriptor getImageDescriptor() { + return SearchPluginImages.DESC_OBJ_TSEARCH_DPDN; + } + + public ISearchQuery getQuery() { + return fQuery; + } + + public Match[] computeContainedMatches(AbstractTextSearchResult result, IFile file) { + return collectMatches(getLinesForFile(file, false)); + } + + public RetrieverLine[] getLinesForFile(IFile file, boolean copy) { + RetrieverLine[] lines= null; + synchronized (fFilesToLines) { + lines= (RetrieverLine[]) fFilesToLines.get(file); + } + return (copy && lines != null) ? (RetrieverLine[]) lines.clone() : lines; + } + + public IFile getFile(Object element) { + if (element instanceof IFile) { + return (IFile) element; + } else + if (element instanceof RetrieverLine) { + RetrieverLine line= (RetrieverLine) element; + return line.getParent(); + } + return null; + } + + public boolean isShownInEditor(Match match, IEditorPart editor) { + IEditorInput ei= editor.getEditorInput(); + if (ei instanceof IFileEditorInput) { + IFileEditorInput fi= (IFileEditorInput) ei; + Object line= match.getElement(); + if (line instanceof RetrieverLine) { + return ((RetrieverLine) line).getParent().equals(fi.getFile()); + } + } + return false; + } + + public Match[] computeContainedMatches(AbstractTextSearchResult result, IEditorPart editor) { + IEditorInput ei= editor.getEditorInput(); + if (ei instanceof IFileEditorInput) { + IFileEditorInput fi= (IFileEditorInput) ei; + return computeContainedMatches(result, fi.getFile()); + } + return EMPTY_ARRAY; + } + + public void setLinesForFile(IFile file, List lines) { + RetrieverLine[] newLines= (RetrieverLine[]) lines.toArray(new RetrieverLine[lines.size()]); + RetrieverMatch[] oldMatches= collectMatches(getLinesForFile(file, false)); + synchronized (fFilesToLines) { + fFilesToLines.remove(file); + } + if (oldMatches.length > 0) { + removeMatches(oldMatches); + } + if (newLines.length > 0) { + ArrayList matches= new ArrayList(newLines.length); + for (Iterator iter= lines.iterator(); iter.hasNext();) { + RetrieverLine line= (RetrieverLine) iter.next(); + line.filter(fFilterExpr, fFilterHideMatching, fAcceptLocations, null); + RetrieverMatch[] m= line.getMatches(false); + matches.addAll(Arrays.asList(m)); + } + if (!matches.isEmpty()) { + synchronized (fFilesToLines) { + fFilesToLines.put(file, newLines); + } + addMatches((Match[]) matches.toArray(new Match[matches.size()])); + } + } + } + + private RetrieverMatch[] collectMatches(RetrieverLine[] lines) { + if (lines == null || lines.length == 0) { + return EMPTY_ARRAY; + } + ArrayList matches= new ArrayList(lines.length); + for (int i= 0; i < lines.length; i++) { + RetrieverLine line= lines[i]; + matches.addAll(Arrays.asList(line.getMatches(false))); + } + return (RetrieverMatch[]) matches.toArray(new RetrieverMatch[matches.size()]); + } + + public void removeAll() { + synchronized (fFilesToLines) { + fFilesToLines.clear(); + } + super.removeAll(); + } + + public void removeMatch(Match match) { + ((RetrieverLine) match.getElement()).remove(Collections.singleton(match)); + super.removeMatch(match); + } + + public void removeMatches(Match[] matches) { + HashSet matchset= new HashSet(); + matchset.addAll(Arrays.asList(matches)); + HashSet lines= new HashSet(); + for (int i= 0; i < matches.length; i++) { + RetrieverMatch match= (RetrieverMatch) matches[i]; + lines.add(match.getElement()); + } + for (Iterator iter= lines.iterator(); iter.hasNext();) { + RetrieverLine line= (RetrieverLine) iter.next(); + line.remove(matchset); + } + super.removeMatches(matches); + } + + public int getMatchCount(Object element) { + if (element instanceof RetrieverLine) { + return ((RetrieverLine) element).getMatchCount(); + } + return 0; + } + + public int getDisplayedMatchCount(Object element) { + if (element instanceof RetrieverLine) { + return ((RetrieverLine) element).getDisplayedMatchCount(); + } + return 0; + } + + public boolean isComplete() { + return fIsComplete; + } + + public void setComplete(boolean isComplete) { + fIsComplete= isComplete; + } + + public int[] getDetailedMatchCount() { + int[] result= new int[] {0, 0}; + synchronized (fFilesToLines) { + for (Iterator iter= fFilesToLines.values().iterator(); iter.hasNext();) { + RetrieverLine[] lines= (RetrieverLine[]) iter.next(); + for (int i= 0; i < lines.length; i++) { + RetrieverLine line= lines[i]; + line.addMatchCount(result); + } + } + } + return result; + } + + public void searchAgain(Collection outdated) { + if (fQuery != null) { + fQuery.searchAgain(outdated, new NullProgressMonitor()); + } + } + + public RetrieverFilter getFilter() { + return fFilter; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverSearchScope.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverSearchScope.java new file mode 100644 index 00000000000..cc6e6d836ec --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverSearchScope.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceProxy; + +import org.eclipse.search.internal.core.text.PatternConstructor; + +import org.eclipse.search.core.text.TextSearchScope; + +public class RetrieverSearchScope extends TextSearchScope { + private boolean fIsCaseSensitive= false; + private boolean fVisitDerived= false; + + private IResource[] fRoots; + private HashSet fFileExtensions= new HashSet(); + private ArrayList fFileMatchers= new ArrayList(); + + + /** + * Creates a search scope for resources below a root matching one of the + * given file patterns. + * + * @param root + * the subtree of resources to be considered + * @param filePatterns + * an array of eclipse style patterns + * @param isCaseSensitive + * flag that indicates whether the file patterns are case + * sensitive or not. + */ + public RetrieverSearchScope(IResource root, String[] filePatterns, boolean isCaseSensitive) { + this(new IResource[] {root}, filePatterns, isCaseSensitive); + } + + /** + * Creates a search scope for resources below several roots matching one of + * the given file patterns. + * + * @param roots + * the subtree of resources to be considered + * @param filePatterns + * an array of eclipse style patterns + * @param isCaseSensitive + * flag that indicates whether the file patterns are case + * sensitive or not. + */ + public RetrieverSearchScope(IResource[] roots, String[] filePatterns, boolean isCaseSensitive) { + fIsCaseSensitive= isCaseSensitive; // do this before compiling the patterns! + compileFilePatterns(filePatterns); + + ArrayList openRoots= new ArrayList(); + for (int i= 0; i < roots.length; i++) { + IResource root= roots[i]; + if (root.getProject().isOpen()) { + openRoots.add(root); + } + } + fRoots= (IResource[]) openRoots.toArray(new IResource[openRoots.size()]); + } + + private void compileFilePatterns(String[] filePatterns) { + fFileMatchers.clear(); + fFileExtensions.clear(); + if (filePatterns != null) { + for (int i= 0; i < filePatterns.length; i++) { + compileFilePattern(filePatterns[i], fFileExtensions, fFileMatchers); + } + } + } + + private void compileFilePattern(String pattern, HashSet extensions, ArrayList matchers) { + pattern= pattern.trim(); + int pos= pattern.lastIndexOf('*'); + if (pos == 0) { + pos= pattern.lastIndexOf('.'); + if (pos == 1) { + String suffix= pattern.substring(2); + String literal= PatternConstructor.appendAsRegEx(false, suffix, new StringBuffer()).toString(); + String strMatcher= PatternConstructor.appendAsRegEx(true, suffix, new StringBuffer()).toString(); + if (literal.equals(strMatcher)) { + if (!fIsCaseSensitive) { + suffix= suffix.toUpperCase(); + } + extensions.add(suffix); + return; + } + } + } + Pattern regex= PatternConstructor.createPattern(pattern, false, true, fIsCaseSensitive, false); + matchers.add(regex.matcher("")); //$NON-NLS-1$ + } + + public boolean contains(IResourceProxy proxy) { + if (!fVisitDerived && proxy.isDerived()) { + return false; // all resources in a derived folder are considered to be derived, see bug 103576 + } + + switch (proxy.getType()) { + case IResource.PROJECT: + return ((IProject) proxy.requestResource()).isOpen(); + + case IResource.FILE: + return containsFile(proxy); + } + return true; + } + + private boolean containsFile(IResourceProxy proxy) { + String name= proxy.getName(); + int iDot= name.lastIndexOf('.'); + String ext= null; + if (iDot >= 0) { + ext= name.substring(iDot + 1); + if (!fIsCaseSensitive) { + ext= ext.toUpperCase(); + } + if (fFileExtensions.contains(ext)) { + return true; + } + } + for (int i= 0; i < fFileMatchers.size(); i++) { + Matcher m= (Matcher) fFileMatchers.get(i); + m.reset(name); + if (m.matches()) { + return true; + } + } + return false; + } + + public void setVisitDerived(boolean visitDerived) { + fVisitDerived= visitDerived; + } + + public IResource[] getRoots() { + return fRoots; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverTreeViewer.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverTreeViewer.java new file mode 100644 index 00000000000..334258251a9 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverTreeViewer.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import org.eclipse.swt.widgets.Composite; + +import org.eclipse.jface.viewers.TreeViewer; + +class RetrieverTreeViewer extends TreeViewer { + private boolean fPreservingSelection= false; + + public RetrieverTreeViewer(Composite parent, int options) { + super(parent, options); + } + + public void preservingSelection(Runnable updateCode) { + if (!fPreservingSelection) { + fPreservingSelection= true; + try { + super.preservingSelection(updateCode); + } finally { + fPreservingSelection= false; + } + } else { + updateCode.run(); + } + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverViewerSorter.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverViewerSorter.java new file mode 100644 index 00000000000..d1399babfb5 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/RetrieverViewerSorter.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.text.Collator; +import java.util.Arrays; +import java.util.Comparator; + +import org.eclipse.core.resources.IResource; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; + +public class RetrieverViewerSorter extends ViewerSorter { + private final ILabelProvider fLabelProvider; + + public RetrieverViewerSorter(ILabelProvider labelProvider) { + super(null); // lazy initialization + fLabelProvider= labelProvider; + } + + public int compare(Viewer viewer, Object e1, Object e2) { + if (e1 instanceof RetrieverLine && e2 instanceof RetrieverLine) { + return ((RetrieverLine) e1).getLineNumber() - ((RetrieverLine) e2).getLineNumber(); + } + + int diff= category(e1) - category(e2); + if (diff != 0) { + return diff; + } + + String name1= fLabelProvider.getText(e1); + String name2= fLabelProvider.getText(e2); + if (name1 == null) + name1= "";//$NON-NLS-1$ + if (name2 == null) + name2= "";//$NON-NLS-1$ + return getCollator().compare(name1, name2); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerSorter#getCollator() + */ + public final Collator getCollator() { + if (collator == null) { + collator= Collator.getInstance(); + } + return collator; + } + + public int category(Object element) { + if (element instanceof IResource) { + return -((IResource) element).getType(); + } + return 0; + } + + public void sort(Viewer viewer, Object[] elements) { + if (elements.length > 0) { + Object o= elements[0]; + if (o instanceof RetrieverLine) { + sortLines(viewer, elements); + return; + } + super.sort(viewer, elements); + } + } + + private void sortLines(Viewer viewer, Object[] elements) { + Arrays.sort(elements, new Comparator() { + public int compare(Object a, Object b) { + RetrieverLine l1= (RetrieverLine) a; + RetrieverLine l2= (RetrieverLine) b; + return l1.getLineNumber() - l2.getLineNumber(); + } + }); + } + + +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/TextFileScannerRegistry.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/TextFileScannerRegistry.java new file mode 100644 index 00000000000..84d844c8f90 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/TextFileScannerRegistry.java @@ -0,0 +1,303 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; + +import org.eclipse.jface.util.SafeRunnable; + +import org.eclipse.search.core.text.AbstractTextFileScanner; + +import org.eclipse.search.internal.ui.SearchPlugin; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class TextFileScannerRegistry { + private static final String ID_TEXT_FILE_SCANNER= "org.eclipse.search.textFileScanner"; //$NON-NLS-1$ + + private static final String ATTRIBUTE_SEPARATOR= ","; //$NON-NLS-1$ + private static final String ATTRIBUTE_FILE_EXTENSIONS= "fileExtensions"; //$NON-NLS-1$ + private static final String ATTRIBUTE_CONTENT_TYPE_IDS= "contentTypeIDs"; //$NON-NLS-1$ + private static final String ATTRIBUTE_COMMENT_SUPPORT= "supportsComments"; //$NON-NLS-1$ + private static final String ATTRIBUTE_STRING_SUPPORT= "supportsStrings"; //$NON-NLS-1$ + private static final String ATTRIBUTE_INCLUDE_SUPPORT= "supportsIncludes"; //$NON-NLS-1$ + private static final String ATTRIBUTE_PREPROCESSOR_SUPPORT= "supportsPreprocessor"; //$NON-NLS-1$ + private static final String ATTRIBUTE_FUNCTION_SUPPORT= "supportsFunctions"; //$NON-NLS-1$ + private static final String ATTRIBUTE_CLASS= "class"; //$NON-NLS-1$ + private static final String SCANNER_NODE_NAME= "textFileScanner"; //$NON-NLS-1$ + private static final ScannerProxyChain NULL_CHAIN= new ScannerProxyChain(); + + private static TextFileScannerRegistry sInstance= null; + + public static TextFileScannerRegistry getInstance() { + if (sInstance == null) { + sInstance= new TextFileScannerRegistry(); + } + return sInstance; + } + + private static class ScannerProxyChain { + private ArrayList fProxies= new ArrayList(); + private AbstractTextFileScanner fScanner= null; + public void sort() { + Collections.sort(fProxies); + } + public void add(ScannerProxy proxy) { + fProxies.add(proxy); + } + public AbstractTextFileScanner getScanner() { + return fScanner; + } + public AbstractTextFileScanner computeScanner() { + if (fScanner == null) { + for (Iterator iter= fProxies.iterator(); fScanner == null && iter.hasNext();) { + ScannerProxy proxy= (ScannerProxy) iter.next(); + if (proxy.isDisabled()) { + iter.remove(); + } else { + fScanner= proxy.createScanner(); + } + } + } + return fScanner; + } + } + + private static class ScannerProxy implements Comparable { + public static final ScannerProxy NULL_PROXY= new ScannerProxy(null, 0); + private IConfigurationElement fConfigElem; + private int fPriority; + private boolean fIsDisabled= false; + + public ScannerProxy(IConfigurationElement elem, int locationSupport) { + fConfigElem= elem; + fPriority= getPriority(locationSupport); + + } + + public AbstractTextFileScanner createScanner() { + final AbstractTextFileScanner[] holder= {null}; + ISafeRunnable code= new SafeRunnable(SearchMessages.TextFileScannerRegistry_error_instanciateScanner) { + public void run() throws Exception { + holder[0]= (AbstractTextFileScanner) fConfigElem.createExecutableExtension(ATTRIBUTE_CLASS); + } + public void handleException(Throwable e) { + disable(); + } + }; + Platform.run(code); + return holder[0]; + } + + public int getPriority(int locations) { + int priority= 0; + if (supportsLocation(locations, AbstractTextFileScanner.LOCATION_COMMENT)) { + priority+= 3; + } + if (supportsLocation(locations, AbstractTextFileScanner.LOCATION_STRING_LITERAL)) { + priority+= 3; + } + if (supportsLocation(locations, AbstractTextFileScanner.LOCATION_PREPROCESSOR_DIRECTIVE)) { + priority+= 1; + } + if (supportsLocation(locations, AbstractTextFileScanner.LOCATION_IMPORT_OR_INCLUDE_STATEMENT)) { + priority+= 2; + } + if (supportsLocation(locations, AbstractTextFileScanner.LOCATION_FUNCTION)) { + priority+= 1; + } + return priority; + } + + public int compareTo(Object o) { + return -(fPriority - ((ScannerProxy) o).fPriority); + } + + public boolean isDisabled() { + return fIsDisabled; + } + + public void disable() { + fIsDisabled= true; + } + } + + private HashMap fContentTypeMap= new HashMap(); + private HashMap fExtensionsMap= new HashMap(); + private AbstractTextFileScanner fLineNumberScanner= new LineNumberScanner(); + private int fAvailableLocations; + + private TextFileScannerRegistry() { + registerExtensions(); + } + + private void registerExtensions() { + fAvailableLocations= 0; + IExtensionPoint ep= Platform.getExtensionRegistry().getExtensionPoint(ID_TEXT_FILE_SCANNER); + if (ep != null) { + IExtension[] extensions= ep.getExtensions(); + if (extensions != null) { + for (int i= 0; i < extensions.length; i++) { + IConfigurationElement[] elems= extensions[i].getConfigurationElements(); + if (elems != null) { + for (int j= 0; j < elems.length; j++) { + IConfigurationElement elem= elems[j]; + if (SCANNER_NODE_NAME.equals(elem.getName())) { + String contentTypeIDs= elem.getAttribute(ATTRIBUTE_CONTENT_TYPE_IDS); + String fileExtensions= elem.getAttribute(ATTRIBUTE_FILE_EXTENSIONS); + int locationSupport= getLocationSupport(elem); + fAvailableLocations|= locationSupport; + ScannerProxy proxy= new ScannerProxy(elem, locationSupport); + registerProxy(contentTypeIDs, proxy, fContentTypeMap); + registerProxy(fileExtensions, proxy, fExtensionsMap); + } + } + } + } + } + } + sortProxyChains(fContentTypeMap.values()); + sortProxyChains(fExtensionsMap.values()); + } + + private void sortProxyChains(Collection chains) { + for (Iterator iter= chains.iterator(); iter.hasNext();) { + ScannerProxyChain chain= (ScannerProxyChain) iter.next(); + chain.sort(); + } + } + + private int getLocationSupport(IConfigurationElement elem) { + int result= 0; + result|= hasSupport(elem, ATTRIBUTE_COMMENT_SUPPORT, 1 << AbstractTextFileScanner.LOCATION_COMMENT); + result|= hasSupport(elem, ATTRIBUTE_STRING_SUPPORT, 1 << AbstractTextFileScanner.LOCATION_STRING_LITERAL); + result|= hasSupport(elem, ATTRIBUTE_INCLUDE_SUPPORT, 1 << AbstractTextFileScanner.LOCATION_IMPORT_OR_INCLUDE_STATEMENT); + result|= hasSupport(elem, ATTRIBUTE_PREPROCESSOR_SUPPORT, 1 << AbstractTextFileScanner.LOCATION_PREPROCESSOR_DIRECTIVE); + result|= hasSupport(elem, ATTRIBUTE_FUNCTION_SUPPORT, 1 << AbstractTextFileScanner.LOCATION_FUNCTION); + return result; + } + + private int hasSupport(IConfigurationElement elem, String attrib, int value) { + String aval= elem.getAttribute(attrib); + if (aval != null && Boolean.valueOf(aval).booleanValue()) { + return value; + } + return 0; + } + + private void registerProxy(String idList, ScannerProxy proxy, HashMap map) { + if (idList != null) { + String[] ids= idList.split(ATTRIBUTE_SEPARATOR); + for (int k= 0; k < ids.length; k++) { + String id= ids[k].trim(); + if (id.length() > 0) { + ScannerProxyChain chain= (ScannerProxyChain) map.get(id); + if (chain == null) { + chain= new ScannerProxyChain(); + map.put(id, chain); + } + chain.add(proxy); + } + } + } + } + + public AbstractTextFileScanner findScanner(IFile file) { + ScannerProxyChain chain= NULL_CHAIN; + if (file != null) { + // first try to find a scanner with the content type + IProject prj= file.getProject(); + IContentType ct; + try { + ct= prj.getContentTypeMatcher().findContentTypeFor(file.getName()); + if (ct != null) { + chain= findScanner(ct); + } + } catch (CoreException e) { + SearchPlugin.log(e.getStatus()); + } + + // try to find scanner by file extension + if (chain == NULL_CHAIN) { + chain= findScanner(file.getName()); + } + } + return chain.getScanner(); + } + + private ScannerProxyChain findScanner(IContentType ct) { + String id= ct.getId(); + ScannerProxyChain chain= (ScannerProxyChain) fContentTypeMap.get(id); + if (chain != null) { + if (chain == NULL_CHAIN || chain.computeScanner() != null) { + return chain; + } + } + + // no cached element + ct= ct.getBaseType(); + chain= ct == null ? NULL_CHAIN : findScanner(ct); + + fContentTypeMap.put(id, chain); + return chain; + } + + private ScannerProxyChain findScanner(String name) { + int idx= 0; + while (true) { + ScannerProxyChain chain= (ScannerProxyChain) fExtensionsMap.get(name); + if (chain != null) { + if (chain.computeScanner() != null) { + return chain; + } + fExtensionsMap.remove(name); + } + + idx= name.indexOf('.', 1); + if (idx < 0) { + return NULL_CHAIN; + } + name= name.substring(idx); + } + } + + public AbstractTextFileScanner getLineNumberScanner() { + return fLineNumberScanner; + } + + private static boolean supportsLocation(int locations, int location) { + return (locations & (1 << location)) != 0; + } + + public boolean hasPreprocessorSupport() { + return supportsLocation(fAvailableLocations, AbstractTextFileScanner.LOCATION_PREPROCESSOR_DIRECTIVE); + } + + public boolean hasFunctionSupport() { + return supportsLocation(fAvailableLocations, AbstractTextFileScanner.LOCATION_FUNCTION); + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/WindowWorkingSetScopeDescription.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/WindowWorkingSetScopeDescription.java new file mode 100644 index 00000000000..d93a6779d23 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/WindowWorkingSetScopeDescription.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.Properties; + +import org.eclipse.core.resources.IResource; + +import org.eclipse.jface.dialogs.IDialogSettings; + +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkingSet; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class WindowWorkingSetScopeDescription extends WorkingSetScopeDescription { + + public WindowWorkingSetScopeDescription() { + setLabel(SearchMessages.WindowWorkingSetScopeDescription_label); + } + + public IResource[] getRoots(IWorkbenchPage page) { + IWorkingSet ws= page.getAggregateWorkingSet(); + return getRootsFromWorkingSet(ws); + } + + public void store(IDialogSettings section) { + } + public void restore(IDialogSettings section) { + } + + public void store(Properties props, String prefix) { + } + public void restore(Properties props, String prefix) { + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/WorkingSetScopeDescription.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/WorkingSetScopeDescription.java new file mode 100644 index 00000000000..c1d3c43b0cb --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/WorkingSetScopeDescription.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Properties; + +import org.eclipse.core.runtime.IAdaptable; + +import org.eclipse.core.resources.IResource; + +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.window.Window; + +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.IWorkingSetManager; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.IWorkingSetSelectionDialog; + +public class WorkingSetScopeDescription implements IScopeDescription { + private static final String KEY_WORKING_SET_NAME= "workingset-name"; //$NON-NLS-1$ + private static final String KEY_LABEL= "workingset-label"; //$NON-NLS-1$ + private static final IResource[] EMPTY_ARRAY= new IResource[0]; + private String fWorkingSetName; + private String fLabel; + + public WorkingSetScopeDescription() { + } + + public WorkingSetScopeDescription(IWorkingSet set) { + fWorkingSetName= set.getName(); + fLabel= set.getLabel(); + // try to change the label + if (set.isAggregateWorkingSet()) { + computeLabel(); + } + } + + private void computeLabel() { + if (fWorkingSetName.startsWith("Aggregate:") && //$NON-NLS-1$ + fWorkingSetName.charAt(fWorkingSetName.length() - 1) == ':') { + fLabel= fWorkingSetName.substring(10, fWorkingSetName.length() - 1).replace(':', '+'); + } + } + + public String getLabel() { + return fLabel; + } + + protected void setLabel(String label) { + fLabel= label; + } + + public IResource[] getRoots(IWorkbenchPage page) { + IWorkingSetManager workingSetManager= PlatformUI.getWorkbench().getWorkingSetManager(); + IWorkingSet ws= workingSetManager.getWorkingSet(fWorkingSetName); + + return getRootsFromWorkingSet(ws); + } + + protected IResource[] getRootsFromWorkingSet(IWorkingSet ws) { + if (ws == null) { + return EMPTY_ARRAY; + } + + HashSet resources= new HashSet(); + getResources(ws.getElements(), resources); + + // remove duplicates + for (Iterator iter= resources.iterator(); iter.hasNext();) { + IResource r= (IResource) iter.next(); + IResource parent= r.getParent(); + while (parent != null) { + if (resources.contains(parent)) { + iter.remove(); + parent= null; + } else { + parent= parent.getParent(); + } + } + } + return (IResource[]) resources.toArray(new IResource[resources.size()]); + } + + public String getWorkingSetName() { + return fWorkingSetName; + } + + private void getResources(IAdaptable[] elements, Collection target) { + for (int i= 0; i < elements.length; i++) { + IAdaptable adaptable= elements[i]; + IResource r= (IResource) adaptable.getAdapter(IResource.class); + if (r != null) { + target.add(r); + } + } + } + + public void restore(IDialogSettings section) { + fWorkingSetName= section.get(KEY_WORKING_SET_NAME); + fLabel= section.get(KEY_LABEL); + if (fLabel == null) { + fLabel= fWorkingSetName; + } + } + + public void store(IDialogSettings section) { + section.put(KEY_WORKING_SET_NAME, fWorkingSetName); + section.put(KEY_LABEL, fLabel); + } + + public void store(Properties props, String prefix) { + props.put(prefix + KEY_WORKING_SET_NAME, fWorkingSetName); + props.put(prefix + KEY_LABEL, fLabel); + } + + public void restore(Properties props, String prefix) { + fWorkingSetName= (String) props.get(prefix + KEY_WORKING_SET_NAME); + fLabel= (String) props.get(prefix + KEY_LABEL); + if (fLabel == null) { + fLabel= fWorkingSetName; + } + } + + public static IScopeDescription createWithDialog(IWorkbenchPage page, IScopeDescription scope) { + if (page == null) { + return null; + } + IWorkingSetManager manager= PlatformUI.getWorkbench().getWorkingSetManager(); + IWorkingSetSelectionDialog dialog= manager.createWorkingSetSelectionDialog(page.getWorkbenchWindow().getShell(), false); + + IScopeDescription result= null; + if (scope instanceof WindowWorkingSetScopeDescription) { + dialog.setSelection(new IWorkingSet[] {page.getAggregateWorkingSet()}); + } else + if (scope instanceof WorkingSetScopeDescription) { + WorkingSetScopeDescription wsetscope= (WorkingSetScopeDescription) scope; + String name= wsetscope.getWorkingSetName(); + IWorkingSet ws= manager.getWorkingSet(name); + if (ws != null) { + dialog.setSelection(new IWorkingSet[] {ws}); + } + } + + if (dialog.open() == Window.OK) { + IWorkingSet[] wsarray= dialog.getSelection(); + if (wsarray != null && wsarray.length > 0) { + IWorkingSet ws= wsarray[0]; + if (ws == page.getAggregateWorkingSet()) { + result= new WindowWorkingSetScopeDescription(); + } else { + result= new WorkingSetScopeDescription(ws); + manager.addRecentWorkingSet(ws); + } + } else { + result= new WorkspaceScopeDescription(); + } + } + return result; + } +} diff --git a/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/WorkspaceScopeDescription.java b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/WorkspaceScopeDescription.java new file mode 100644 index 00000000000..0d54867acd5 --- /dev/null +++ b/org.eclipse.search/new search/org/eclipse/search2/internal/ui/text2/WorkspaceScopeDescription.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search2.internal.ui.text2; + +import java.util.Properties; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; + +import org.eclipse.jface.dialogs.IDialogSettings; + +import org.eclipse.ui.IWorkbenchPage; + +import org.eclipse.search2.internal.ui.SearchMessages; + +public class WorkspaceScopeDescription implements IScopeDescription { + public static final String LABEL= SearchMessages.WorkspaceScopeDescription_label; + + public WorkspaceScopeDescription() { + } + + public String getLabel() { + return LABEL; + } + + public IResource[] getRoots(IWorkbenchPage page) { + return ResourcesPlugin.getWorkspace().getRoot().getProjects(); + } + + public void restore(IDialogSettings section) { + } + + public void store(IDialogSettings section) { + } + + public void store(Properties props, String prefix) { + } + + public void restore(Properties props, String prefix) { + } +} diff --git a/org.eclipse.search/plugin.properties b/org.eclipse.search/plugin.properties index a653d7b4b21..523348c7ad1 100644 --- a/org.eclipse.search/plugin.properties +++ b/org.eclipse.search/plugin.properties @@ -27,6 +27,35 @@ openFileSearchPageAction.label= &File... openSearchDialogAction.label= Se&arch... openSearchDialogAction.tooltip= Search +textSearchSubMenu.label= Te&xt + +action.performTextSearch.label= &Recent Scope +action.performTextSearch.tooltip= Search for Text in Recent Search Scope +command.performTextSearch.name= Find Text in Recent Scope +command.performTextSearch.description= Searches the files in the recent search scope for specific text. + +action.performTextSearchWorkspace.label= &Workspace +action.performTextSearchWorkspace.tooltip= Search for Text in Workspace +command.performTextSearchWorkspace.name= Find Text in Workspace +command.performTextSearchWorkspace.description= Searches the files in the workspace for specific text. + +action.performTextSearchProject.label= &Project +action.performTextSearchProject.tooltip= Search for Text in Project +command.performTextSearchProject.name= Find Text in Project +command.performTextSearchProject.description= Searches the files in the project for specific text. + +action.performTextSearchFile.label= &File +action.performTextSearchFile.tooltip= Search for Text in File +command.performTextSearchFile.name= Find Text in File +command.performTextSearchFile.description= Searches the files in the file for specific text. + +action.performTextSearchWorkingSet.label= Working &Set... +action.performTextSearchWorkingSet.tooltip= Search for Text in a Working Set +command.performTextSearchWorkingSet.name= Find Text in Working Set +command.performTextSearchWorkingSet.description= Searches the files in the working set for specific text. + +RetrieverPage.label= Text Search + fileSearch= File Search searchResultViewName= Classic Search newSearchResultViewName= Search diff --git a/org.eclipse.search/plugin.xml b/org.eclipse.search/plugin.xml index ac66fdd349f..560138fe097 100644 --- a/org.eclipse.search/plugin.xml +++ b/org.eclipse.search/plugin.xml @@ -11,6 +11,8 @@ <extension-point name="%searchPages" id="searchPages" schema="schema/searchPages.exsd"/> <extension-point name="%searchResultSorters" id="searchResultSorters" schema="schema/searchResultSorters.exsd"/> <extension-point name="%searchResultViewPages" id="searchResultViewPages" schema="schema/searchResultViewPages.exsd"/> + <extension-point name="%textFileScanner" id="textFileScanner" schema="schema/textFileScanner.exsd"/> + <extension-point id="textSearchEngine" name="%textSearchEngine" schema="schema/textSearchEngine.exsd"/> <!-- Extensions --> @@ -93,6 +95,37 @@ name="%ViewCommand.searchView.name" description="%ViewCommand.searchView.description" /> + + <command + categoryId="org.eclipse.search.ui.category.search" + description="%command.performTextSearch.description" + id="org.eclipse.search.ui.performTextSearch" + name="%command.performTextSearch.name"/> + <command + categoryId="org.eclipse.search.ui.category.search" + id="org.eclipse.search.ui.performTextSearchWorkingSet" + name="%command.performTextSearchWorkingSet.name" + description="%command.performTextSearchWorkingSet.description" + /> + <command + categoryId="org.eclipse.search.ui.category.search" + id="org.eclipse.search.ui.performTextSearchWorkspace" + name="%command.performTextSearchWorkspace.name" + description="%command.performTextSearchWorkspace.description" + /> + <command + categoryId="org.eclipse.search.ui.category.search" + id="org.eclipse.search.ui.performTextSearchProject" + name="%command.performTextSearchProject.name" + description="%command.performTextSearchProject.description" + /> + <command + categoryId="org.eclipse.search.ui.category.search" + id="org.eclipse.search.ui.performTextSearchFile" + name="%command.performTextSearchFile.name" + description="%command.performTextSearchFile.description" + /> + </extension> <extension point="org.eclipse.ui.bindings"> @@ -119,6 +152,18 @@ commandId="org.eclipse.search.ui.views.SearchView" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" /> + <key + contextId="org.eclipse.ui.globalScope" + sequence="Ctrl+2" + commandId="org.eclipse.search.ui.performTextSearch" + schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" + /> + <key + contextId="org.eclipse.jdt.ui.javaEditorScope" + sequence="Ctrl+2 2" + commandId="org.eclipse.search.ui.performTextSearch" + schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" + /> </extension> <!-- action sets --> @@ -160,9 +205,57 @@ icon="$nl$/icons/full/etool16/search.gif" helpContextId="open_search_dialog_action_context" class="org.eclipse.search.internal.ui.OpenSearchDialogAction"/> + + <action id="org.eclipse.search.TextSearchWorkingSet" + definitionId="org.eclipse.search.ui.performTextSearchWorkingSet" + menubarPath="org.eclipse.search.menu/textSearchSubMenu/group1" + style="push" + label="%action.performTextSearchWorkingSet.label" + tooltip= "%action.performTextSearchWorkingSet.tooltip" + class="org.eclipse.search2.internal.ui.text2.FindInWorkingSetActionDelegate"/> + + <!-- Various actions for the text search in a sub menu --> + <menu id="textSearchSubMenu" + label="%textSearchSubMenu.label" + path="org.eclipse.search.menu/contextMenuActionsGroup"> + <separator name="group0"/> + <separator name="group1"/> + </menu> + <action id="org.eclipse.search.TextSearchFile" + definitionId="org.eclipse.search.ui.performTextSearchFile" + menubarPath="org.eclipse.search.menu/textSearchSubMenu/group1" + style="push" + label="%action.performTextSearchFile.label" + tooltip= "%action.performTextSearchFile.tooltip" + class="org.eclipse.search2.internal.ui.text2.FindInFileActionDelegate"/> + + <action id="org.eclipse.search.TextSearchProject" + definitionId="org.eclipse.search.ui.performTextSearchProject" + menubarPath="org.eclipse.search.menu/textSearchSubMenu/group1" + style="push" + label="%action.performTextSearchProject.label" + tooltip= "%action.performTextSearchProject.tooltip" + class="org.eclipse.search2.internal.ui.text2.FindInProjectActionDelegate"/> + + <action id="org.eclipse.search.TextSearchWorkspace" + definitionId="org.eclipse.search.ui.performTextSearchWorkspace" + menubarPath="org.eclipse.search.menu/textSearchSubMenu/group1" + style="push" + label="%action.performTextSearchWorkspace.label" + tooltip= "%action.performTextSearchWorkspace.tooltip" + class="org.eclipse.search2.internal.ui.text2.FindInWorkspaceActionDelegate"/> + + <action + class="org.eclipse.search2.internal.ui.text2.FindInRecentScopeActionDelegate" + definitionId="org.eclipse.search.ui.performTextSearch" + id="org.eclipse.search.TextSearch" + label="%action.performTextSearch.label" + menubarPath="org.eclipse.search.menu/textSearchSubMenu/group0" + style="push" + tooltip="%action.performTextSearch.tooltip"/> </actionSet> </extension> - + <extension point="org.eclipse.ui.views"> <view id="org.eclipse.search.SearchResultView" @@ -190,6 +283,14 @@ searchResultClass="org.eclipse.search.internal.ui.text.FileSearchResult" class="org.eclipse.search.internal.ui.text.FileSearchPage"> </viewPage> + <viewPage + class="org.eclipse.search2.internal.ui.text2.RetrieverPage" + emptyPageUseful="true" + icon="icons/full/obj16/tsearch_dpdn_obj.gif" + id="org.eclipse.search.text.RetrieverPage" + label="%RetrieverPage.label" + searchResultClass="org.eclipse.search2.internal.ui.text2.RetrieverResult"> + </viewPage> </extension> <extension point="org.eclipse.search.searchPages"> @@ -283,9 +384,21 @@ <factory class="org.eclipse.search.internal.ui.SearchResultViewEntryAdapterFactory" adaptableType="org.eclipse.search.ui.ISearchResultViewEntry"> - <adapter type="org.eclipse.core.resources.IResource"/> - <adapter type="org.eclipse.core.resources.IMarker"/> + <adapter type="org.eclipse.core.resources.IResource"/> + <adapter type="org.eclipse.core.resources.IMarker"/> </factory> - </extension> - + </extension> + <extension + id="java-scanner" + point="org.eclipse.search.textFileScanner"> + <textFileScanner + class="org.eclipse.search2.internal.ui.text2.JavaScanner" + contentTypeIDs="org.eclipse.jdt.core.javaSource" + fileExtensions=".java" + supportsComments="true" + supportsFunctions="false" + supportsIncludes="true" + supportsPreprocessor="false" + supportsStrings="true"/> + </extension> </plugin>
\ No newline at end of file diff --git a/org.eclipse.search/schema/textFileScanner.exsd b/org.eclipse.search/schema/textFileScanner.exsd new file mode 100644 index 00000000000..a870008d5c0 --- /dev/null +++ b/org.eclipse.search/schema/textFileScanner.exsd @@ -0,0 +1,162 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.search"> +<annotation> + <appInfo> + <meta.schema plugin="org.eclipse.search" id="textFileScanner" name="Text File Scanner"/> + </appInfo> + <documentation> + The extension point allows to register a scanner that categorizes text-matches. + </documentation> + </annotation> + + <element name="extension"> + <complexType> + <sequence> + <element ref="textFileScanner" minOccurs="1" maxOccurs="unbounded"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + </complexType> + </element> + + <element name="textFileScanner"> + <complexType> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + Class of the scanner that will be created, must extend org.eclipse.search.core.text.AbstractTextFileScanner. + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn="org.eclipse.search.core.text.AbstractTextFileScanner"/> + </appInfo> + </annotation> + </attribute> + <attribute name="fileExtensions" type="string"> + <annotation> + <documentation> + Comma separated list of file-extensions for which the scanner shall be applied. E.g. '.c,.h,.cpp'. In case an extension does not start with a dot, a match against the complete file-name will be attempted. E.g. 'Makefile,.mk' + </documentation> + </annotation> + </attribute> + <attribute name="contentTypeIDs" type="string"> + <annotation> + <documentation> + A comma-separated list of content type ids for which the supplied scanner shall be used. E.g.: 'org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cppSource' + </documentation> + </annotation> + </attribute> + <attribute name="supportsComments" type="boolean"> + <annotation> + <documentation> + True, if the scanner can detect comments. False, otherwise. + </documentation> + </annotation> + </attribute> + <attribute name="supportsStrings" type="boolean"> + <annotation> + <documentation> + True, if the scanner can detect string literals False, otherwise. + </documentation> + </annotation> + </attribute> + <attribute name="supportsIncludes" type="boolean"> + <annotation> + <documentation> + True, if the scanner can detect include or import statements. False, otherwise. + </documentation> + </annotation> + </attribute> + <attribute name="supportsPreprocessor" type="boolean"> + <annotation> + <documentation> + True, if the scanner can detect preprocessor directives. False, otherwise. + </documentation> + </annotation> + </attribute> + <attribute name="supportsFunctions" type="boolean"> + <annotation> + <documentation> + True, if the scanner can detect function bodies. False, otherwise. + </documentation> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + 3.2 + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="examples"/> + </appInfo> + <documentation> + As an example, here is the markup for the java scanner. + +<p> +<pre> +<extension id="JavaScanner" + point="org.eclipse.search.textFileScanner"> + <textFileScanner + class="org.eclipse.search2.internal.ui.text2.JavaScanner" + contentTypeIDs="org.eclipse.jdt.core.javaSource" + fileExtensions=".java" + supportsComments="true" + supportsStrings="true" + supportsIncludes="true"/> +</extension> +</pre> +</p> + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="apiInfo"/> + </appInfo> + <documentation> + The contributed class must implement <code>org.eclipse.search.core.text.AbstractTextFileScanner</code> + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="implementation"/> + </appInfo> + <documentation> + The search plugin provides both a scanner for java-files and for c/c++-files. + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="copyright"/> + </appInfo> + <documentation> + Copyright (c) 2006 Wind River Systems and others. + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a> + </documentation> + </annotation> + +</schema> diff --git a/org.eclipse.search/schema/textSearchEngine.exsd b/org.eclipse.search/schema/textSearchEngine.exsd new file mode 100644 index 00000000000..00a8f984e70 --- /dev/null +++ b/org.eclipse.search/schema/textSearchEngine.exsd @@ -0,0 +1,134 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.search"> +<annotation> + <appInfo> + <meta.schema plugin="org.eclipse.search" id="textSearchEngine" name="Text Search Engine"/> + </appInfo> + <documentation> + The extension point allows to register a text search engine that is used to search for text in files of the workspace. + </documentation> + </annotation> + + <element name="extension"> + <complexType> + <sequence> + <element ref="textSearchEngine" minOccurs="1" maxOccurs="unbounded"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="textSearchEngine"> + <complexType> + <attribute name="id" type="string" use="required"> + <annotation> + <documentation> + Used to distinguish different search engines. + </documentation> + </annotation> + </attribute> + <attribute name="label" type="string" use="required"> + <annotation> + <documentation> + Used when search engine is presented in UI. + </documentation> + </annotation> + </attribute> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + The class implementing org.eclipse.search.core.text.TextSearchEngine. + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn="org.eclipse.search.core.text.TextSearchEngine"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + 3.2 + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="examples"/> + </appInfo> + <documentation> + As an example, here is the markup for suppling a search engine + +<p> +<pre> +<extension id="MyEngine" + point="org.eclipse.search.textSearchEngine"> + <textFileScanner + id="com.windriver.textSearchEngine" + label="Wind River Search" + class="com.windriver.text.SearchEngine" /> +</extension> +</pre> +</p> + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="apiInfo"/> + </appInfo> + <documentation> + The contributed class must implement <code>org.eclipse.search.core.text.TextSearchEngine</code> + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="implementation"/> + </appInfo> + <documentation> + + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="copyright"/> + </appInfo> + <documentation> + Copyright (c) 2006 Wind River Systems and others. + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a> + </documentation> + </annotation> + +</schema> diff --git a/org.eclipse.search/search/org/eclipse/search/internal/core/text/FileNamePatternSearchScope.java b/org.eclipse.search/search/org/eclipse/search/internal/core/text/FileNamePatternSearchScope.java index d03a728e658..95889e06ccd 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/core/text/FileNamePatternSearchScope.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/core/text/FileNamePatternSearchScope.java @@ -147,7 +147,7 @@ public class FileNamePatternSearchScope extends TextSearchScope { pattern= Pattern.compile(".*"); //$NON-NLS-1$ } else { String[] patternStrings= (String[]) fFileNamePatterns.toArray(new String[fFileNamePatterns.size()]); - pattern= PatternConstructor.createPattern(patternStrings, IS_CASE_SENSITIVE_FILESYSTEM, false); + pattern= PatternConstructor.createPattern(patternStrings, IS_CASE_SENSITIVE_FILESYSTEM); } fFileNameMatcher= pattern.matcher(""); //$NON-NLS-1$ } diff --git a/org.eclipse.search/search/org/eclipse/search/internal/core/text/AmountOfWorkCalculator.java b/org.eclipse.search/search/org/eclipse/search/internal/core/text/FilesOfScopeCalculator.java index 4edc3687261..b07fb5e4651 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/core/text/AmountOfWorkCalculator.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/core/text/FilesOfScopeCalculator.java @@ -10,46 +10,53 @@ *******************************************************************************/ package org.eclipse.search.internal.core.text; +import java.util.ArrayList; + import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceProxyVisitor; import org.eclipse.search.core.text.TextSearchScope; -/** - * The visitor that does the actual work. - */ -public class AmountOfWorkCalculator implements IResourceProxyVisitor { - +public class FilesOfScopeCalculator implements IResourceProxyVisitor { + private final TextSearchScope fScope; - - private int fFileCount; + private final MultiStatus fStatus; + private ArrayList fFiles; - public AmountOfWorkCalculator(TextSearchScope scope) { + public FilesOfScopeCalculator(TextSearchScope scope, MultiStatus status) { fScope= scope; + fStatus= status; } - + public boolean visit(IResourceProxy proxy) { boolean inScope= fScope.contains(proxy); - + if (inScope && proxy.getType() == IResource.FILE) { - fFileCount++; + fFiles.add(proxy.requestResource()); } return inScope; } - - public int process() { - fFileCount= 0; - IResource[] roots= fScope.getRoots(); - for (int i= 0; i < roots.length; i++) { - try { - roots[i].accept(this, 0); - } catch (CoreException ex) { - // ignore + + public IFile[] process() { + fFiles= new ArrayList(); + try { + IResource[] roots= fScope.getRoots(); + for (int i= 0; i < roots.length; i++) { + try { + roots[i].accept(this, 0); + } catch (CoreException ex) { + // report and ignore + fStatus.add(ex.getStatus()); + } } + return (IFile[]) fFiles.toArray(new IFile[fFiles.size()]); + } finally { + fFiles= null; } - return fFileCount; } } diff --git a/org.eclipse.search/search/org/eclipse/search/internal/core/text/PatternConstructor.java b/org.eclipse.search/search/org/eclipse/search/internal/core/text/PatternConstructor.java index 7d4a2f8f036..e5d176fe690 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/core/text/PatternConstructor.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/core/text/PatternConstructor.java @@ -22,108 +22,145 @@ public class PatternConstructor { private PatternConstructor() { // don't instantiate } + + public static Pattern createPattern(String pattern, boolean isCaseSensitive, boolean isRegex) throws PatternSyntaxException { + return createPattern(pattern, isRegex, true, isCaseSensitive, false); + } /** * Creates a pattern element from the pattern string which is either a reg-ex expression or in our old * 'StringMatcher' format. * @param pattern The search pattern + * @param isRegex <code>true</code> if the passed string already is a reg-ex pattern + * @param isStringMatcher <code>true</code> if the passed string is in the StringMatcher format. * @param isCaseSensitive Set to <code>true</code> to create a case insensitive pattern - * @param isRegexSearch <code>true</code> if the passed string already is a reg-ex pattern + * @param isWholeWord <code>true</code> to create a pattern that requires a word boundary at the beginning and the end. * @return The created pattern * @throws PatternSyntaxException */ - public static Pattern createPattern(String pattern, boolean isCaseSensitive, boolean isRegexSearch) throws PatternSyntaxException { - if (!isRegexSearch) { - pattern= asRegEx(pattern, new StringBuffer()).toString(); + public static Pattern createPattern(String pattern, boolean isRegex, boolean isStringMatcher, boolean isCaseSensitive, boolean isWholeWord) throws PatternSyntaxException { + if (isRegex) { + if (isWholeWord) { + StringBuffer buffer= new StringBuffer(pattern.length() + 10); + buffer.append("\\b(?:").append(pattern).append(")\\b"); //$NON-NLS-1$ //$NON-NLS-2$ + pattern= buffer.toString(); + } + } else { + int len= pattern.length(); + StringBuffer buffer= new StringBuffer(len + 10); + // don't add a word boundary if the search text does not start with + // a word char. (this works around a user input error). + if (isWholeWord && len > 0 && isWordChar(pattern.charAt(0))) { + buffer.append("\\b"); //$NON-NLS-1$ + } + appendAsRegEx(isStringMatcher, pattern, buffer); + if (isWholeWord && len > 0 && isWordChar(pattern.charAt(len - 1))) { + buffer.append("\\b"); //$NON-NLS-1$ + } + pattern= buffer.toString(); } - - if (!isCaseSensitive) - return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.MULTILINE); - - return Pattern.compile(pattern, Pattern.MULTILINE); + + int regexOptions= Pattern.MULTILINE; + if (!isCaseSensitive) { + regexOptions|= Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; + } + return Pattern.compile(pattern, regexOptions); } - /** - * Creates a pattern element from the pattern string which is either a reg-ex expression or in our old + private static boolean isWordChar(char c) { + return Character.isLetterOrDigit(c); + } + + /** + * Creates a pattern element from an array of patterns in the old * 'StringMatcher' format. * @param patterns The search patterns * @param isCaseSensitive Set to <code>true</code> to create a case insensitive pattern - * @param isRegexSearch <code>true</code> if the passed string already is a reg-ex pattern * @return The created pattern * @throws PatternSyntaxException */ - public static Pattern createPattern(String[] patterns, boolean isCaseSensitive, boolean isRegexSearch) throws PatternSyntaxException { + public static Pattern createPattern(String[] patterns, boolean isCaseSensitive) throws PatternSyntaxException { StringBuffer pattern= new StringBuffer(); for (int i= 0; i < patterns.length; i++) { if (i > 0) { + // note that this works only as we know that the operands of the + // or expression will be simple and need no brackets. pattern.append('|'); } - if (isRegexSearch) { - pattern.append(patterns[i]); - } else { - asRegEx(patterns[i], pattern); - } + appendAsRegEx(true, patterns[i], pattern); } - return createPattern(pattern.toString(), isCaseSensitive, true); + return createPattern(pattern.toString(), true, true, isCaseSensitive, false); } - /** - * Translates a StringMatcher pattern (using '*' and '?') to a regex pattern string - * @param stringMatcherPattern a pattern using '*' and '?' - */ - private static StringBuffer asRegEx(String stringMatcherPattern, StringBuffer out) { - boolean escaped= false; - boolean quoting= false; - - int i= 0; - while (i < stringMatcherPattern.length()) { - char ch= stringMatcherPattern.charAt(i++); - - if (ch == '*' && !escaped) { - if (quoting) { - out.append("\\E"); //$NON-NLS-1$ - quoting= false; - } - out.append(".*"); //$NON-NLS-1$ - escaped= false; - continue; - } else if (ch == '?' && !escaped) { - if (quoting) { - out.append("\\E"); //$NON-NLS-1$ - quoting= false; - } - out.append("."); //$NON-NLS-1$ - escaped= false; - continue; - } else if (ch == '\\' && !escaped) { - escaped= true; - continue; - - } else if (ch == '\\' && escaped) { - escaped= false; - if (quoting) { - out.append("\\E"); //$NON-NLS-1$ - quoting= false; - } - out.append("\\\\"); //$NON-NLS-1$ - continue; - } - - if (!quoting) { - out.append("\\Q"); //$NON-NLS-1$ - quoting= true; - } - if (escaped && ch != '*' && ch != '?' && ch != '\\') - out.append('\\'); - out.append(ch); - escaped= ch == '\\'; - - } - if (quoting) - out.append("\\E"); //$NON-NLS-1$ - - return out; - } - + public static StringBuffer appendAsRegEx(boolean isStringMatcher, String pattern, StringBuffer buffer) { + boolean isEscaped= false; + for (int i = 0; i < pattern.length(); i++) { + char c = pattern.charAt(i); + switch(c) { + // the backslash + case '\\': + // the backslash is escape char in string matcher + if (isStringMatcher && !isEscaped) { + isEscaped= true; + } + else { + buffer.append("\\\\"); //$NON-NLS-1$ + isEscaped= false; + } + break; + // characters that need to be escaped in the regex. + case '(': + case ')': + case '{': + case '}': + case '.': + case '[': + case ']': + case '$': + case '^': + case '+': + case '|': + if (isEscaped) { + buffer.append("\\\\"); //$NON-NLS-1$ + isEscaped= false; + } + buffer.append('\\'); + buffer.append(c); + break; + case '?': + if (isStringMatcher && !isEscaped) { + buffer.append('.'); + } + else { + buffer.append('\\'); + buffer.append(c); + isEscaped= false; + } + break; + case '*': + if (isStringMatcher && !isEscaped) { + buffer.append(".*"); //$NON-NLS-1$ + } + else { + buffer.append('\\'); + buffer.append(c); + isEscaped= false; + } + break; + default: + if (isEscaped) { + buffer.append("\\\\"); //$NON-NLS-1$ + isEscaped= false; + } + buffer.append(c); + break; + } + } + if (isEscaped) { + buffer.append("\\\\"); //$NON-NLS-1$ + isEscaped= false; + } + return buffer; + } } diff --git a/org.eclipse.search/search/org/eclipse/search/internal/core/text/TextSearchEngineRegistry.java b/org.eclipse.search/search/org/eclipse/search/internal/core/text/TextSearchEngineRegistry.java new file mode 100644 index 00000000000..c5a6606e632 --- /dev/null +++ b/org.eclipse.search/search/org/eclipse/search/internal/core/text/TextSearchEngineRegistry.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.search.internal.core.text; + +import java.util.ArrayList; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Preferences; + +import org.eclipse.jface.util.SafeRunnable; + +import org.eclipse.search.core.text.TextSearchEngine; + +import org.eclipse.search.internal.ui.SearchMessages; +import org.eclipse.search.internal.ui.SearchPlugin; +import org.eclipse.search.internal.ui.SearchPreferencePage; + + +public class TextSearchEngineRegistry { + + private static final String ENGINE_NODE_NAME= "textSearchEngine"; //$NON-NLS-1$ + private static final String ATTRIB_ID= "id"; //$NON-NLS-1$ + private static final String ATTRIB_LABEL= "label"; //$NON-NLS-1$ + private static final String ATTRIB_CLASS= "class"; //$NON-NLS-1$ + + private TextSearchEngine fPreferredEngine; + private String fPreferredEngineId; + + public TextSearchEngineRegistry() { + fPreferredEngineId= null; // only null when not initialized + fPreferredEngine= null; + } + + public TextSearchEngine getPreferred() { + String preferredId= getPreferredEngineID(); + if (!preferredId.equals(fPreferredEngineId)) { + updateEngine(preferredId); + } + return fPreferredEngine; + } + + private void updateEngine(String preferredId) { + if (preferredId.length() != 0) { // empty string: default engine + TextSearchEngine engine= createFromExtension(preferredId); + if (engine != null) { + fPreferredEngineId= preferredId; + fPreferredEngine= engine; + return; + } + // creation failed, clear preference + setPreferredEngineID(""); // set to default //$NON-NLS-1$ + } + fPreferredEngineId= ""; //$NON-NLS-1$ + fPreferredEngine= TextSearchEngine.createDefault(); + } + + private String getPreferredEngineID() { + Preferences prefs= SearchPlugin.getDefault().getPluginPreferences(); + String preferedEngine= prefs.getString(SearchPreferencePage.TEXT_SEARCH_ENGINE); + return preferedEngine; + } + + private void setPreferredEngineID(String id) { + Preferences prefs= SearchPlugin.getDefault().getPluginPreferences(); + prefs.setValue(SearchPreferencePage.TEXT_SEARCH_ENGINE, id); + } + + private TextSearchEngine createFromExtension(final String id) { + final TextSearchEngine[] res= new TextSearchEngine[] { null }; + + SafeRunnable safe= new SafeRunnable() { + public void run() throws Exception { + IConfigurationElement[] extensions= Platform.getExtensionRegistry().getConfigurationElementsFor(ENGINE_NODE_NAME); + for (int i= 0; i < extensions.length; i++) { + IConfigurationElement curr= extensions[i]; + if (id.equals(curr.getAttribute(ATTRIB_ID))) { + res[0]= (TextSearchEngine) curr.createExecutableExtension(ATTRIB_CLASS); + return; + } + } + } + public void handleException(Throwable e) { + SearchPlugin.log(e); + } + }; + Platform.run(safe); + return res[0]; + } + + public String[][] getAvailableEngines() { + ArrayList res= new ArrayList(); + res.add(new String[] { SearchMessages.TextSearchEngineRegistry_defaulttextsearch_label, "" }); //$NON-NLS-1$ + + IConfigurationElement[] extensions= Platform.getExtensionRegistry().getConfigurationElementsFor(ENGINE_NODE_NAME); + for (int i= 0; i < extensions.length; i++) { + IConfigurationElement elem= extensions[i]; + res.add(new String[] { elem.getAttribute(ATTRIB_LABEL), elem.getAttribute(ATTRIB_ID) }); + } + return (String[][]) res.toArray(new String[res.size()][]); + } +} diff --git a/org.eclipse.search/search/org/eclipse/search/internal/core/text/TextSearchVisitor.java b/org.eclipse.search/search/org/eclipse/search/internal/core/text/TextSearchVisitor.java index cbc237ec383..079311e68da 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/core/text/TextSearchVisitor.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/core/text/TextSearchVisitor.java @@ -13,6 +13,8 @@ package org.eclipse.search.internal.core.text; import java.io.IOException; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; +import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; @@ -32,9 +34,6 @@ import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceProxy; -import org.eclipse.core.resources.IResourceProxyVisitor; import org.eclipse.jface.text.IDocument; @@ -60,7 +59,7 @@ import org.eclipse.search.internal.ui.SearchPlugin; /** * The visitor that does the actual work. */ -public class TextSearchVisitor implements IResourceProxyVisitor { +public class TextSearchVisitor { public static class ReusableMatchAccess extends TextSearchMatchAccess { @@ -102,7 +101,6 @@ public class TextSearchVisitor implements IResourceProxyVisitor { } - private final TextSearchScope fScope; private final TextSearchRequestor fCollector; private final Matcher fMatcher; @@ -120,33 +118,45 @@ public class TextSearchVisitor implements IResourceProxyVisitor { private final ReusableMatchAccess fMatchAccess; - public TextSearchVisitor(TextSearchScope scope, TextSearchRequestor collector, Pattern searchPattern, int fileCount, IProgressMonitor monitor) { - fScope= scope; + public TextSearchVisitor(TextSearchRequestor collector, Pattern searchPattern, IProgressMonitor monitor) { fCollector= collector; - fProgressMonitor= monitor; + fProgressMonitor= monitor == null ? new NullProgressMonitor() : monitor; fStatus= new MultiStatus(NewSearchUI.PLUGIN_ID, IStatus.OK, SearchMessages.TextSearchEngine_statusMessage, null); fMatcher= searchPattern.pattern().length() == 0 ? null : searchPattern.matcher(new String()); - fNumberOfScannedFiles= 0; - fNumberOfFilesToScan= fileCount; - fFileCharSequenceProvider= new FileCharSequenceProvider(); fMatchAccess= new ReusableMatchAccess(); } - public void process() { + public IStatus search(TextSearchScope scope, Comparator searchOrder) { + IFile[] files= new FilesOfScopeCalculator(scope, fStatus).process(); + fNumberOfScannedFiles= 0; + fNumberOfFilesToScan= files.length; + try { + fProgressMonitor.beginTask("", fNumberOfFilesToScan); //$NON-NLS-1$ + if (fNumberOfFilesToScan > 0) { + Integer[] args= new Integer[] {new Integer(1), new Integer(fNumberOfFilesToScan)}; + fProgressMonitor.setTaskName(Messages.format(SearchMessages.TextSearchEngine_scanning, args)); + } + fCollector.beginReporting(); + processFiles(files, searchOrder); + return fStatus; + } finally { + fProgressMonitor.done(); + fCollector.endReporting(); + } + + } + + private void processFiles(IFile[] files, Comparator searchOrder) { fDocumentsInEditors= evalNonFileBufferDocuments(); - - IResource[] roots= fScope.getRoots(); - for (int i= 0; i < roots.length; i++) { - try { - roots[i].accept(this, 0); - } catch (CoreException ex) { - fStatus.add(ex.getStatus()); - } + if (searchOrder != null) { + Arrays.sort(files, searchOrder); + } + for (int i= 0; i < files.length; i++) { + processFile(files[i]); } - fDocumentsInEditors= null; } @@ -197,23 +207,12 @@ public class TextSearchVisitor implements IResourceProxyVisitor { } } - public boolean visit(IResourceProxy proxy) { - if (!fScope.contains(proxy)) { - return false; - } - if (proxy.getType() != IResource.FILE) { - return true; - } + public void processFile(IFile file) { try { - IFile file= (IFile) proxy.requestResource(); - - boolean res= fCollector.acceptFile(file); - res= res || fCollector.acceptFile(proxy); //call for compatibility, remove before M5 - if (!res || fMatcher == null) { - return false; - } - - + if (!fCollector.acceptFile(file) || fMatcher == null) { + return; + } + IDocument document= getOpenDocument(file); if (document != null) { @@ -236,29 +235,24 @@ public class TextSearchVisitor implements IResourceProxyVisitor { } } } catch (UnsupportedCharsetException e) { - IFile file= (IFile) proxy.requestResource(); String[] args= { getCharSetName(file), file.getFullPath().makeRelative().toString()}; String message= Messages.format(SearchMessages.TextSearchVisitor_unsupportedcharset, args); fStatus.add(new Status(IStatus.ERROR, NewSearchUI.PLUGIN_ID, Platform.PLUGIN_ERROR, message, e)); } catch (IllegalCharsetNameException e) { - IFile file= (IFile) proxy.requestResource(); String[] args= { getCharSetName(file), file.getFullPath().makeRelative().toString()}; String message= Messages.format(SearchMessages.TextSearchVisitor_illegalcharset, args); fStatus.add(new Status(IStatus.ERROR, NewSearchUI.PLUGIN_ID, Platform.PLUGIN_ERROR, message, e)); } catch (IOException e) { - IFile file= (IFile) proxy.requestResource(); String[] args= { getExceptionMessage(e), file.getFullPath().makeRelative().toString()}; String message= Messages.format(SearchMessages.TextSearchVisitor_error, args); fStatus.add(new Status(IStatus.ERROR, NewSearchUI.PLUGIN_ID, Platform.PLUGIN_ERROR, message, e)); } catch (CoreException e) { - IFile file= (IFile) proxy.requestResource(); String[] args= { getExceptionMessage(e), file.getFullPath().makeRelative().toString()}; String message= Messages.format(SearchMessages.TextSearchVisitor_error, args); fStatus.add(new Status(IStatus.ERROR, NewSearchUI.PLUGIN_ID, Platform.PLUGIN_ERROR, message, e)); } finally { updateProgressMonitor(); } - return false; // finish, files don't have children } private void locateMatches(IFile file, CharSequence searchInput) throws CoreException { @@ -327,30 +321,5 @@ public class TextSearchVisitor implements IResourceProxyVisitor { if (fProgressMonitor.isCanceled()) throw new OperationCanceledException(SearchMessages.TextSearchVisitor_canceled); } - - - public static IStatus search(TextSearchScope scope, TextSearchRequestor collector, Pattern searchPattern, IProgressMonitor monitor) { - if (monitor == null) { - monitor= new NullProgressMonitor(); - } - - int amountOfWork= new AmountOfWorkCalculator(scope).process(); - try { - monitor.beginTask("", amountOfWork); //$NON-NLS-1$ - if (amountOfWork > 0) { - Integer[] args= new Integer[] {new Integer(1), new Integer(amountOfWork)}; - monitor.setTaskName(Messages.format(SearchMessages.TextSearchEngine_scanning, args)); - } - collector.beginReporting(); - TextSearchVisitor visitor= new TextSearchVisitor(scope, collector, searchPattern, amountOfWork, monitor); - visitor.process(); - return visitor.getStatus(); - } finally { - monitor.done(); - collector.endReporting(); - } - - } - } diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchMessages.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchMessages.java index 1bee616e20e..bd874b0726c 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchMessages.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchMessages.java @@ -198,4 +198,6 @@ public final class SearchMessages extends NLS { } public static String ReplaceDialog2_nomatches_error; + public static String SearchPreferencePage_textSearchEngine; + public static String TextSearchEngineRegistry_defaulttextsearch_label; }
\ No newline at end of file diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchMessages.properties b/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchMessages.properties index 5de161b9e5b..74c0c2b126e 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchMessages.properties +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchMessages.properties @@ -113,6 +113,7 @@ PreviousSearchesDialog_message= &Select one of the previous searches TextSearchPage_replace_searchproblems_title=Replace TextSearchPage_replace_searchproblems_message=Problems occurred while searching. The affected files will be skipped. +TextSearchEngineRegistry_defaulttextsearch_label=Default Text Search FileSearchQuery_label=File Search @@ -178,6 +179,7 @@ SearchPreferencePage_limit_label=&Limit table size for file search results to: SearchPreferencePage_limit_error=Table size must be an integer greater than 0 SearchPreferencePage_bringToFront= &Bring Search view to front after search SearchPreferencePage_defaultPerspective= Default &perspective for the Search view: +SearchPreferencePage_textSearchEngine=Text Search Engine to be used: SearchPreferencePage_defaultPerspective_none= None SearchPreferencePage_ignorePotentialMatches= &Ignore potential matches diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPlugin.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPlugin.java index eacd17035ec..9499dcf5c40 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPlugin.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPlugin.java @@ -43,6 +43,7 @@ import org.eclipse.ui.plugin.AbstractUIPlugin; import org.eclipse.search.ui.IContextMenuConstants; import org.eclipse.search.ui.NewSearchUI; +import org.eclipse.search.internal.core.text.TextSearchEngineRegistry; import org.eclipse.search.internal.ui.util.ExceptionHandler; import org.eclipse.search2.internal.ui.InternalSearchUI; @@ -68,15 +69,18 @@ public class SearchPlugin extends AbstractUIPlugin { public static final int INTERNAL_ERROR= 1; private static SearchPlugin fgSearchPlugin; + private List fPageDescriptors; private List fSorterDescriptors; + private TextSearchEngineRegistry fTextSearchEngineRegistry; public SearchPlugin() { super(); Assert.isTrue(fgSearchPlugin == null); fgSearchPlugin= this; + fTextSearchEngineRegistry= null; } /** @@ -287,7 +291,15 @@ public class SearchPlugin extends AbstractUIPlugin { fSorterDescriptors= createSorterDescriptors(elements); } return fSorterDescriptors; - } + } + + + public TextSearchEngineRegistry getTextSearchEngineRegistry() { + if (fTextSearchEngineRegistry == null) { + fTextSearchEngineRegistry= new TextSearchEngineRegistry(); + } + return fTextSearchEngineRegistry; + } /** * Creates all necessary sorter description nodes. diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPluginImages.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPluginImages.java index 69aafd6d6a2..3f19118fae6 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPluginImages.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPluginImages.java @@ -61,15 +61,17 @@ public class SearchPluginImages { public static final String IMG_LCL_SEARCH_CANCEL= NAME_PREFIX + "stop.gif"; //$NON-NLS-1$ public static final String IMG_LCL_SEARCH_COLLAPSE_ALL= NAME_PREFIX + "collapseall.gif"; //$NON-NLS-1$ public static final String IMG_LCL_SEARCH_EXPAND_ALL= NAME_PREFIX + "expandall.gif"; //$NON-NLS-1$ - + public static final String IMG_LCL_SEARCH_FILTER= NAME_PREFIX + "filter_ps.gif"; //$NON-NLS-1$ public static final String IMG_VIEW_SEARCHRES= NAME_PREFIX + "searchres.gif"; //$NON-NLS-1$ public static final String IMG_OBJ_TSEARCH_DPDN= NAME_PREFIX + "tsearch_dpdn_obj.gif"; //$NON-NLS-1$ public static final String IMG_OBJ_SEARCHMARKER= NAME_PREFIX + "searchm_obj.gif"; //$NON-NLS-1$ + public static final String IMG_OBJ_TEXT_SEARCH_LINE= NAME_PREFIX + "line_match.gif"; //$NON-NLS-1$ // Define images public static final ImageDescriptor DESC_OBJ_TSEARCH_DPDN= createManaged(T_OBJ, IMG_OBJ_TSEARCH_DPDN); public static final ImageDescriptor DESC_OBJ_SEARCHMARKER= createManaged(T_OBJ, IMG_OBJ_SEARCHMARKER); + public static final ImageDescriptor DESC_OBJ_TEXT_SEARCH_LINE= createManaged(T_OBJ, IMG_OBJ_TEXT_SEARCH_LINE); public static final ImageDescriptor DESC_VIEW_SEARCHRES= createManaged(T_EVIEW, IMG_VIEW_SEARCHRES); public static Image get(String key) { @@ -81,7 +83,7 @@ public class SearchPluginImages { PLUGIN_REGISTRY.put(name, result); return result; } - + /* * Creates an image descriptor for the given prefix and name in the Search plugin bundle. The path can * contain variables like $NL$. diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPreferencePage.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPreferencePage.java index 432016ca6df..3e973cea09a 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPreferencePage.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/SearchPreferencePage.java @@ -20,6 +20,8 @@ import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.util.PropertyChangeEvent; + +import org.eclipse.search.internal.core.text.TextSearchEngineRegistry; import org.eclipse.search.internal.ui.util.ComboFieldEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; @@ -52,6 +54,7 @@ public class SearchPreferencePage extends FieldEditorPreferencePage implements I public static final String BRING_VIEW_TO_FRONT= "org.eclipse.search.bringToFront"; //$NON-NLS-1$ public static final String LIMIT_TABLE_TO= "org.eclipse.search.limitTableTo"; //$NON-NLS-1$ public static final String LIMIT_TABLE= "org.eclipse.search.limitTable"; //$NON-NLS-1$ + public static final String TEXT_SEARCH_ENGINE = "org.eclipse.search.textSearchEngine"; //$NON-NLS-1$ private ColorFieldEditor fColorEditor; private BooleanFieldEditor fEmphasizedCheckbox; @@ -91,6 +94,7 @@ public class SearchPreferencePage extends FieldEditorPreferencePage implements I store.setDefault(DEFAULT_PERSPECTIVE, NO_DEFAULT_PERSPECTIVE); store.setDefault(LIMIT_TABLE_TO, 200); store.setDefault(LIMIT_TABLE, false); + store.setDefault(TEXT_SEARCH_ENGINE, ""); //default search engine is empty string //$NON-NLS-1$ } @@ -146,6 +150,18 @@ public class SearchPreferencePage extends FieldEditorPreferencePage implements I perspectiveNamesAndIds, getFieldEditorParent()); addField(comboEditor); + + // in case we have a contributed engine, let the user choose. + TextSearchEngineRegistry reg= SearchPlugin.getDefault().getTextSearchEngineRegistry(); + String[][] engineNamesAndIds= reg.getAvailableEngines(); + if (engineNamesAndIds.length > 1) { + comboEditor= new ComboFieldEditor( + TEXT_SEARCH_ENGINE, + SearchMessages.SearchPreferencePage_textSearchEngine, + engineNamesAndIds, + getFieldEditorParent()); + addField(comboEditor); + } } private void createTableLimit() { diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/EditorOpener.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/EditorOpener.java index 216a9e8d254..b8e5e3b7fa9 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/EditorOpener.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/EditorOpener.java @@ -11,9 +11,7 @@ package org.eclipse.search.internal.ui.text; import org.eclipse.core.resources.IFile; -import org.eclipse.search.internal.ui.SearchPlugin; -import org.eclipse.search.ui.NewSearchUI; -import org.eclipse.search.ui.text.Match; + import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorReference; @@ -25,23 +23,26 @@ import org.eclipse.ui.PartInitException; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.part.FileEditorInput; +import org.eclipse.search.ui.NewSearchUI; + +import org.eclipse.search.internal.ui.SearchPlugin; + public class EditorOpener { private IEditorPart fEditor; - IEditorPart open(Match match, boolean activate) throws PartInitException { + public IEditorPart open(IFile file, boolean activate) throws PartInitException { IWorkbenchPage wbPage= SearchPlugin.getActivePage(); if (NewSearchUI.reuseEditor()) - return showWithReuse(match, wbPage, activate); - return showWithoutReuse(match, wbPage, activate); + return showWithReuse(file, wbPage, activate); + return showWithoutReuse(file, wbPage, activate); } - private IEditorPart showWithoutReuse(Match match, IWorkbenchPage wbPage, boolean activate) throws PartInitException { - return IDE.openEditor(wbPage, (IFile) match.getElement(), activate); + private IEditorPart showWithoutReuse(IFile file, IWorkbenchPage wbPage, boolean activate) throws PartInitException { + return IDE.openEditor(wbPage, file, activate); } - private IEditorPart showWithReuse(Match match, IWorkbenchPage wbPage, boolean activate) throws PartInitException { - IFile file= (IFile) match.getElement(); + private IEditorPart showWithReuse(IFile file, IWorkbenchPage wbPage, boolean activate) throws PartInitException { String editorID= getEditorID(file); return showInEditor(wbPage, file, editorID, activate); } diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchPage.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchPage.java index f0f5aef62cf..003a6483835 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchPage.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchPage.java @@ -165,7 +165,7 @@ public class FileSearchPage extends AbstractTextSearchViewPage implements IAdapt protected void showMatch(Match match, int offset, int length, boolean activate) throws PartInitException { IFile file= (IFile) match.getElement(); - IEditorPart editor= fEditorOpener.open(match, activate); + IEditorPart editor= fEditorOpener.open(file, activate); if (offset != 0 && length != 0) { if (editor instanceof ITextEditor) { ITextEditor textEditor= (ITextEditor) editor; diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchQuery.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchQuery.java index 1123460410d..19a14044703 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchQuery.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/FileSearchQuery.java @@ -135,7 +135,7 @@ public class FileSearchQuery implements ISearchQuery { if (searchString.trim().equals(String.valueOf('*'))) { searchString= new String(); } - return PatternConstructor.createPattern(searchString, isCaseSensitive(), isRegexSearch()); + return PatternConstructor.createPattern(searchString, isRegexSearch(), true, isCaseSensitive(), false); } diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/NewTextSearchActionGroup.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/NewTextSearchActionGroup.java index d3f9381dfe7..b50c7b14f5e 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/NewTextSearchActionGroup.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/NewTextSearchActionGroup.java @@ -42,7 +42,7 @@ import org.eclipse.search.ui.IContextMenuConstants; * * @since 2.1 */ -class NewTextSearchActionGroup extends ActionGroup { +public class NewTextSearchActionGroup extends ActionGroup { private ISelectionProvider fSelectionProvider; private IWorkbenchPage fPage; diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/ReplaceDialog2.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/ReplaceDialog2.java index 1a45f3310aa..bad36bc50fe 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/ReplaceDialog2.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/ReplaceDialog2.java @@ -510,7 +510,7 @@ class ReplaceDialog2 extends ExtendedDialogWindow { } private Pattern createReplacePattern(FileSearchQuery query) { - return PatternConstructor.createPattern(query.getSearchString(), query.isCaseSensitive(), true); + return PatternConstructor.createPattern(query.getSearchString(), true, true, query.isCaseSensitive(), false); } private String computeReplacementString(Pattern pattern, String originalText, String replacementText) { diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/SearchResultUpdater.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/SearchResultUpdater.java index 669793adc7e..9eea60e8347 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/SearchResultUpdater.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/SearchResultUpdater.java @@ -20,16 +20,18 @@ import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.search.internal.ui.SearchPlugin; import org.eclipse.search.ui.IQueryListener; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.search.ui.NewSearchUI; +import org.eclipse.search.ui.text.AbstractTextSearchResult; import org.eclipse.search.ui.text.Match; +import org.eclipse.search.internal.ui.SearchPlugin; + public class SearchResultUpdater implements IResourceChangeListener, IQueryListener { - FileSearchResult fResult; + private AbstractTextSearchResult fResult; - public SearchResultUpdater(FileSearchResult result) { + public SearchResultUpdater(AbstractTextSearchResult result) { fResult= result; NewSearchUI.addQueryListener(this); ResourcesPlugin.getWorkspace().addResourceChangeListener(this); @@ -63,7 +65,7 @@ public class SearchResultUpdater implements IResourceChangeListener, IQueryListe } }); } catch (CoreException e) { - SearchPlugin.getDefault().getLog().log(e.getStatus()); + SearchPlugin.log(e); } } diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/TextSearchPage.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/TextSearchPage.java index 996e8b98e63..2b076688bd5 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/text/TextSearchPage.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/text/TextSearchPage.java @@ -56,6 +56,7 @@ import org.eclipse.jface.text.ITextSelection; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorRegistry; import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; @@ -70,6 +71,7 @@ import org.eclipse.search.ui.ISearchResultViewPart; import org.eclipse.search.ui.NewSearchUI; import org.eclipse.search.internal.core.text.FileNamePatternSearchScope; +import org.eclipse.search.internal.core.text.PatternConstructor; import org.eclipse.search.internal.ui.ISearchHelpContextIds; import org.eclipse.search.internal.ui.Messages; import org.eclipse.search.internal.ui.ScopePart; @@ -78,9 +80,17 @@ import org.eclipse.search.internal.ui.SearchPlugin; import org.eclipse.search.internal.ui.util.FileTypeEditor; import org.eclipse.search.internal.ui.util.SWTUtil; +import org.eclipse.search2.internal.ui.text2.CurrentProjectScopeDescription; +import org.eclipse.search2.internal.ui.text2.IScopeDescription; +import org.eclipse.search2.internal.ui.text2.RetrieverQuery; +import org.eclipse.search2.internal.ui.text2.WindowWorkingSetScopeDescription; +import org.eclipse.search2.internal.ui.text2.WorkingSetScopeDescription; +import org.eclipse.search2.internal.ui.text2.WorkspaceScopeDescription; + public class TextSearchPage extends DialogPage implements ISearchPage, IReplacePage { - private static final int HISTORY_SIZE= 12; + private static final String TMP_WORKING_SET_NAME = "tmp_for_search"; + private static final int HISTORY_SIZE= 12; public static final String EXTENSION_POINT_ID= "org.eclipse.search.internal.ui.text.TextSearchPage"; //$NON-NLS-1$ // Dialog store id constants @@ -99,7 +109,7 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP private boolean fSearchDerived; private Combo fPattern; - private Button fIgnoreCase; + private Button fIsCaseSensitiveCheckbox; private Combo fExtensions; private Button fIsRegExCheckbox; private CLabel fStatusLabel; @@ -109,18 +119,23 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP private FileTypeEditor fFileTypeEditor; private ContentAssistHandler fReplaceContentAssistHandler; + + // mstodo remove before release + private Button fUseNewTextUICheckbox; + private boolean fUseNewTextUI; + private static final String STORE_USE_NEW_TEXT_UI = "use-new-text-ui"; private static class SearchPatternData { - public final boolean ignoreCase; + public final boolean isCaseSensitive; public final boolean isRegExSearch; public final String textPattern; public final String[] fileNamePatterns; public final int scope; public final IWorkingSet[] workingSets; - public SearchPatternData(String textPattern, boolean ignoreCase, boolean isRegExSearch, String[] fileNamePatterns, int scope, IWorkingSet[] workingSets) { + public SearchPatternData(String textPattern, boolean isCaseSensitive, boolean isRegExSearch, String[] fileNamePatterns, int scope, IWorkingSet[] workingSets) { Assert.isNotNull(fileNamePatterns); - this.ignoreCase= ignoreCase; + this.isCaseSensitive= isCaseSensitive; this.isRegExSearch= isRegExSearch; this.textPattern= textPattern; this.fileNamePatterns= fileNamePatterns; @@ -129,7 +144,7 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP } public void store(IDialogSettings settings) { - settings.put("ignoreCase", ignoreCase); //$NON-NLS-1$ + settings.put("ignoreCase", !isCaseSensitive); //$NON-NLS-1$ settings.put("isRegExSearch", isRegExSearch); //$NON-NLS-1$ settings.put("textPattern", textPattern); //$NON-NLS-1$ settings.put("fileNamePatterns", fileNamePatterns); //$NON-NLS-1$ @@ -169,7 +184,7 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP boolean isRegExSearch= settings.getBoolean("isRegExSearch"); //$NON-NLS-1$ boolean ignoreCase= settings.getBoolean("ignoreCase"); //$NON-NLS-1$ - return new SearchPatternData(textPattern, ignoreCase, isRegExSearch, fileNamePatterns, scope, workingSets); + return new SearchPatternData(textPattern, !ignoreCase, isRegExSearch, fileNamePatterns, scope, workingSets); } catch (NumberFormatException e) { return null; } @@ -179,7 +194,12 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP //---- Action Handling ------------------------------------------------ public boolean performAction() { - NewSearchUI.runQueryInBackground(getSearchQuery()); + if (fUseNewTextUI) { + NewSearchUI.runQueryInBackground(getNewSearchQuery()); + } + else { + NewSearchUI.runQueryInBackground(getSearchQuery()); + } return true; } @@ -246,6 +266,56 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP return new FileSearchQuery(scope, getSearchOptions(), patternData.textPattern); } + private ISearchQuery getNewSearchQuery() { + // create query + RetrieverQuery query= new RetrieverQuery(getActivePage()); + + // extract data + SearchPatternData patternData= getPatternData(); + + // check if we have a string matcher pattern. + String pattern= patternData.textPattern; + boolean isRegex= patternData.isRegExSearch; + if (!isRegex) { + String literal= PatternConstructor.appendAsRegEx(false, pattern, new StringBuffer()).toString(); + String strMatcher= PatternConstructor.appendAsRegEx(true, pattern, new StringBuffer()).toString(); + if (!literal.equals(strMatcher)) { + isRegex= true; + pattern= strMatcher; + } + } + + // Setup search scope + IScopeDescription scope= null; + switch (getContainer().getSelectedScope()) { + case ISearchPageContainer.SELECTION_SCOPE: + scope= getSelectedResourcesScopeDescription(); + break; + case ISearchPageContainer.SELECTED_PROJECTS_SCOPE: + scope= getEnclosingProjectScopeDescription(); + break; + case ISearchPageContainer.WORKING_SET_SCOPE: + scope= getWorkingSetScopeDescription(); + break; + case ISearchPageContainer.WORKSPACE_SCOPE: + default: + scope= new WorkspaceScopeDescription(); + break; + } + + query.setSearchString(pattern); + query.setIsCaseSensitive(patternData.isCaseSensitive); + query.setIsRegularExpression(isRegex); + + query.setFilePatterns(patternData.fileNamePatterns); + query.setSearchScope(scope, fSearchDerived); + return query; + } + + private IWorkbenchPage getActivePage() { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + } + private String getPattern() { return fPattern.getText(); } @@ -272,7 +342,7 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP } match= new SearchPatternData( getPattern(), - ignoreCase(), + isCaseSensitive(), fIsRegExCheckbox.getSelection(), getExtensions(), getContainer().getSelectedScope(), @@ -303,7 +373,7 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP private String getSearchOptions() { StringBuffer result= new StringBuffer(); - if (!ignoreCase()) + if (!isCaseSensitive()) result.append('i'); if (fIsRegExSearch) @@ -316,8 +386,8 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP return fFileTypeEditor.getFileTypes(); } - private boolean ignoreCase() { - return fIgnoreCase.getSelection(); + private boolean isCaseSensitive() { + return fIsCaseSensitiveCheckbox.getSelection(); } /* @@ -424,16 +494,16 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP data.widthHint= convertWidthInCharsToPixels(50); fPattern.setLayoutData(data); - fIgnoreCase= new Button(group, SWT.CHECK); - fIgnoreCase.setText(SearchMessages.SearchPage_caseSensitive); - fIgnoreCase.setSelection(!fIsCaseSensitive); - fIgnoreCase.addSelectionListener(new SelectionAdapter() { + fIsCaseSensitiveCheckbox= new Button(group, SWT.CHECK); + fIsCaseSensitiveCheckbox.setText(SearchMessages.SearchPage_caseSensitive); + fIsCaseSensitiveCheckbox.setSelection(!fIsCaseSensitive); + fIsCaseSensitiveCheckbox.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { - fIsCaseSensitive= !fIgnoreCase.getSelection(); + fIsCaseSensitive= fIsCaseSensitiveCheckbox.getSelection(); } }); - fIgnoreCase.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); - fIgnoreCase.setFont(group.getFont()); + fIsCaseSensitiveCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); + fIsCaseSensitiveCheckbox.setFont(group.getFont()); // Text line which explains the special characters fStatusLabel= new CLabel(group, SWT.LEAD); @@ -468,7 +538,7 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP SearchPatternData patternData= (SearchPatternData) fPreviousSearchPatterns.get(selectionIndex); if (!fPattern.getText().equals(patternData.textPattern)) return; - fIgnoreCase.setSelection(patternData.ignoreCase); + fIsCaseSensitiveCheckbox.setSelection(patternData.isCaseSensitive); fIsRegExCheckbox.setSelection(patternData.isRegExSearch); fPattern.setText(patternData.textPattern); fFileTypeEditor.setFileTypes(patternData.fileNamePatterns); @@ -583,6 +653,18 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP }); fSearchDerivedCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); fSearchDerivedCheckbox.setFont(group.getFont()); + + fUseNewTextUICheckbox= new Button(group, SWT.CHECK); + fUseNewTextUICheckbox.setText("Work in progress: show search results in new Text Search UI"); + fUseNewTextUICheckbox.setSelection(fUseNewTextUI); + fUseNewTextUICheckbox.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + fUseNewTextUI= fUseNewTextUICheckbox.getSelection(); + writeConfiguration(); + } + }); + fUseNewTextUICheckbox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); + fUseNewTextUICheckbox.setFont(group.getFont()); } /** @@ -624,6 +706,52 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP return FileNamePatternSearchScope.newSearchScope(name, res, fSearchDerived); } + private IScopeDescription getEnclosingProjectScopeDescription() { + String[] enclosingProjectName= getContainer().getSelectedProjectNames(); + if (enclosingProjectName == null) { + return new WorkspaceScopeDescription(); + } + + IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); + IResource[] res= new IResource[enclosingProjectName.length]; + for (int i= 0; i < res.length; i++) { + res[i]= root.getProject(enclosingProjectName[i]); + } + if (res.length == 0) { + return new CurrentProjectScopeDescription(); + } + return getScopeDescription(res); + } + + private IScopeDescription getScopeDescription(IResource[] res) { + if (res.length == 1) { + if (res[0].equals(CurrentProjectScopeDescription.getCurrentProject(getActivePage()))) { + return new CurrentProjectScopeDescription(); + } + } + return new WorkingSetScopeDescription(createWorkingSet(res)); + } + + private IScopeDescription getWorkingSetScopeDescription() { + IWorkingSet[] wss= getContainer().getSelectedWorkingSets(); + if (wss.length == 0) { + return new WorkspaceScopeDescription(); + } + if (wss.length == 1) { + if (wss[0].equals(getActivePage().getAggregateWorkingSet())) { + return new WindowWorkingSetScopeDescription(); + } + return new WorkingSetScopeDescription(wss[0]); + } + IWorkingSetManager wm= PlatformUI.getWorkbench().getWorkingSetManager(); + StringBuffer id = new StringBuffer(); + id.append("Aggregate:"); //$NON-NLS-1$ + for (int i = 0; i < wss.length; i++) { + id.append(wss[i].getName()).append(':'); + } + return new WorkingSetScopeDescription(wm.createAggregateWorkingSet( + id.toString(), "Multiple Working Sets", wss)); //$NON-NLS-1$ + } private FileNamePatternSearchScope getSelectedResourcesScope() { HashSet resources= new HashSet(); @@ -656,9 +784,54 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP return FileNamePatternSearchScope.newSearchScope(SearchMessages.SelectionScope, arr, fSearchDerived); } + private IScopeDescription getSelectedResourcesScopeDescription() { + HashSet resources= new HashSet(); + ISelection selection= getSelection(); + if (selection instanceof IStructuredSelection && !selection.isEmpty()) { + Iterator iter= ((IStructuredSelection) selection).iterator(); + while (iter.hasNext()) { + Object curr= iter.next(); + if (curr instanceof IWorkingSet) { + IWorkingSet workingSet= (IWorkingSet) curr; + if (workingSet.isAggregateWorkingSet() && workingSet.isEmpty()) { + return new WorkspaceScopeDescription(); + } + IAdaptable[] elements= workingSet.getElements(); + for (int i= 0; i < elements.length; i++) { + IResource resource= (IResource)elements[i].getAdapter(IResource.class); + if (resource != null && resource.isAccessible()) { + resources.add(resource); + } + } + } else if (curr instanceof IAdaptable) { + IResource resource= (IResource) ((IAdaptable)curr).getAdapter(IResource.class); + if (resource != null && resource.isAccessible()) { + resources.add(resource); + } + } + } + } + return getScopeDescription((IResource[]) resources.toArray(new IResource[resources.size()])); + } + + private IWorkingSet createWorkingSet(IResource[] arr) { + IWorkingSetManager wsm= PlatformUI.getWorkbench().getWorkingSetManager(); + IWorkingSet ws= wsm.getWorkingSet(TMP_WORKING_SET_NAME); + if (ws == null) { + ws= wsm.createWorkingSet(TMP_WORKING_SET_NAME, arr); + ws.setId("org.eclipse.ui.resourceWorkingSetPage"); //$NON-NLS-1$ + wsm.addWorkingSet(ws); + } + else { + ws.setElements(arr); + } + return ws; + } + + //--------------- Configuration handling -------------- - /* (non-Javadoc) + /* (non-Javadoc) * @see org.eclipse.jface.dialogs.DialogPage#dispose() */ public void dispose() { @@ -684,6 +857,7 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP fIsCaseSensitive= s.getBoolean(STORE_CASE_SENSITIVE); fIsRegExSearch= s.getBoolean(STORE_IS_REG_EX_SEARCH); fSearchDerived= s.getBoolean(STORE_SEARCH_DERIVED); + fUseNewTextUI= s.getBoolean(STORE_USE_NEW_TEXT_UI); try { int historySize= s.getInt(STORE_HISTORY_SIZE); @@ -709,6 +883,7 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP s.put(STORE_CASE_SENSITIVE, fIsCaseSensitive); s.put(STORE_IS_REG_EX_SEARCH, fIsRegExSearch); s.put(STORE_SEARCH_DERIVED, fSearchDerived); + s.put(STORE_USE_NEW_TEXT_UI, fUseNewTextUI); int historySize= Math.min(fPreviousSearchPatterns.size(), HISTORY_SIZE); s.put(STORE_HISTORY_SIZE, historySize); diff --git a/org.eclipse.search/search/org/eclipse/search/internal/ui/util/ComboFieldEditor.java b/org.eclipse.search/search/org/eclipse/search/internal/ui/util/ComboFieldEditor.java index 6353789b13c..e5d1e03ddd2 100644 --- a/org.eclipse.search/search/org/eclipse/search/internal/ui/util/ComboFieldEditor.java +++ b/org.eclipse.search/search/org/eclipse/search/internal/ui/util/ComboFieldEditor.java @@ -79,7 +79,8 @@ public class ComboFieldEditor extends FieldEditor { protected void adjustForNumColumns(int numColumns) { Control control= getLabelControl(); if (control != null) { - ((GridData)control.getLayoutData()).horizontalSpan= numColumns; + ((GridData)control.getLayoutData()).horizontalSpan= numColumns-1; + numColumns=1; } ((GridData)fCombo.getLayoutData()).horizontalSpan= numColumns; } |