diff --git a/README.md b/README.md index c250a8e81..f8a5b8b7d 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,17 @@ -Kotlin for Eclipse -============== - -[![official JetBrains project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) - -Welcome to Kotlin for Eclipse project! Some handy links: - - * [Kotlin Site](http://kotlinlang.org/) - * [Getting Started Guide](http://kotlinlang.org/docs/tutorials/getting-started-eclipse.html) - * [Kotlin on Eclipse Marketplace](https://marketplace.eclipse.org/content/kotlin-plugin-eclipse) - * Issue Tracker: [File New Issue](https://youtrack.jetbrains.com/newIssue?project=KE&clearDraft=true), [All Open Issues](https://youtrack.jetbrains.com/issues/KE?q=%23Unresolved) - * [Kotlin Blog](http://blog.jetbrains.com/kotlin/) - * [Forum](https://discuss.kotlinlang.org/) - * [TeamCity CI build](https://teamcity.jetbrains.com/viewType.html?buildTypeId=Kotlin_EclipsePlugin) - * [Follow Kotlin on Twitter](https://twitter.com/kotlin) - -### Installation - -To give it a try you will need a clean installation of Eclipse Neon or newer. The Kotlin plugin is available from the Eclipse Marketplace. The easiest way to install the Kotlin plugin is to **drag-and-drop this button into a running Eclipse window**: - -Drag to your running Eclipse workspace to install Kotlin Plugin for Eclipse - -Alternatively, you can use *Help -> Eclipse Marketplace…* menu, or the following update site: - - https://dl.bintray.com/jetbrains/kotlin/eclipse-plugin/last/ - -### Building and Development - -*Eclipse IDE for Eclipse Committers* is the recommended way to build and develop the `kotlin-eclipse` project. Eclipse [Oxygen 4.7](https://www.eclipse.org/downloads/packages/eclipse-ide-eclipse-committers/oxygenr) is used so far. - -In order to start development in Eclipse: - - Install the [AspectJ Eclipse plug-in for Eclipse 4.7](http://www.eclipse.org/ajdt/downloads/index.php). To install AJDT 2.2.4 use the following update site: - - http://download.eclipse.org/tools/ajdt/47/dev/update - - - Since Kotlin plugin contains code written in Kotlin itself, you will also need a Kotlin plugin to build the project in Eclipse. To install the Kotlin Eclipse plugin use the following update site: - - https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_EclipsePlugin/bootstrap.tcbuildtag/ - - - Since Kotlin plugin uses weaving, you need to launch the project with weaving enabled. Installation of Equinox Weaving Launcher will add two additional launch configurations types for running plugin and for testing. To install the Equinox Weaving Launcher you can use the following update site: - - http://download.scala-ide.org/plugins/equinox-weaving-launcher/releases/site/ - - - Import plugin projects from the cloned repository into your workspace - - File -> Import -> Existing Projects into Workspace - - - Using the command line, run gradle build to download the Kotlin compiler. It will be used as a bundled compiler in built plugin and as a library during development. - - cd {repository}/kotlin-bundled-compiler - ./gradlew clean getBundled - or in Windows environment: - - cd {repository}\kotlin-bundled-compiler - gradlew.bat clean getBundled - - - Run another instance of Eclipse with the Kotlin plugin inside - - kotlin-eclipse-ui -> Run As -> Eclipse Weaving enabled Eclipse Application - -Building from the command line is also available (Note that Maven **3.0.5** is required): - - cd {repository} - mvn install - -### Eclipse update sites - -Latest stable release: - - https://dl.bintray.com/jetbrains/kotlin/eclipse-plugin/last/ - -Any previously released version (replace *:version* with the version number): - - https://dl.bintray.com/jetbrains/kotlin/eclipse-plugin/:version/ - -Nightly build: - - https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_EclipsePlugin/.lastSuccessful/ - -### Kotlin Eclipse Plugin Developer Documentation - -See basic developer documentation [here](https://github.com/JetBrains/kotlin-eclipse/blob/master/docs/dev-documentation.md) +Enhanced Kotlin for Eclipse +============== + +This plugin based on [JetBrains Kotlin plugin](https://github.com/JetBrains/kotlin-eclipse) and contains small enhancements. These enhancements mostly related to adaptations for latest versions ov Java, Eclipse and so on. + +Update sites description + +Update-site URL | Description +----------------|------------ +https://s3.eu-central-1.amazonaws.com/github.bvfalcon/kotlin-eclipse/eclipse-releases/2021-09/ | Last version Kotlin for Eclipse 2021-09 +https://s3.eu-central-1.amazonaws.com/github.bvfalcon/kotlin-eclipse/eclipse-releases/2021-06/ | Last version Kotlin for Eclipse 2021-06 +https://s3.eu-central-1.amazonaws.com/github.bvfalcon/kotlin-eclipse/eclipse-releases/2021-03/ | Last version Kotlin for Eclipse 2021-03 +https://s3.eu-central-1.amazonaws.com/github.bvfalcon/kotlin-eclipse/eclipse-releases/2020-12/ | Last version Kotlin for Eclipse 2020-12 +https://s3.eu-central-1.amazonaws.com/github.bvfalcon/kotlin-eclipse/eclipse-releases/2020-03/ | Last version Kotlin for Eclipse 2020-03 +https://s3.eu-central-1.amazonaws.com/github.bvfalcon/kotlin-eclipse/versions/0.8.20/ | Version 0.8.20 Kotlin for Eclipse 2020-03 + + diff --git a/kotlin-bundled-compiler/.classpath b/kotlin-bundled-compiler/.classpath deleted file mode 100644 index 80949bebc..000000000 --- a/kotlin-bundled-compiler/.classpath +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/kotlin-bundled-compiler/.project b/kotlin-bundled-compiler/.project deleted file mode 100644 index 002a00b34..000000000 --- a/kotlin-bundled-compiler/.project +++ /dev/null @@ -1,41 +0,0 @@ - - - kotlin-bundled-compiler - - - - - - org.jetbrains.kotlin.ui.kotlinBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.pde.PluginNature - org.jetbrains.kotlin.core.kotlinNature - - - - kotlin_bin - 2 - org.jetbrains.kotlin.core.filesystem:/kotlin-bundled-compiler/kotlin_bin - - - diff --git a/kotlin-bundled-compiler/.settings/org.eclipse.jdt.core.prefs b/kotlin-bundled-compiler/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 9a57a84d6..000000000 --- a/kotlin-bundled-compiler/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,297 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.kt -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 -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_annotation=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=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -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_method_declaration=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -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=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -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_lambda_body=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_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -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_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=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=80 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -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=true -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=false -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not 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_after_type_annotation=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_annotation_declaration=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_lambda_arrow=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_try=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=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=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=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_try=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=do not 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_lambda_arrow=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_try=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_parenthesized_expression_in_throw=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=do not 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_semicolon_in_try_resources=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=do not 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.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -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=120 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -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=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=false -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/kotlin-bundled-compiler/.settings/org.eclipse.jdt.ui.prefs b/kotlin-bundled-compiler/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index bddb247ef..000000000 --- a/kotlin-bundled-compiler/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,3 +0,0 @@ -eclipse.preferences.version=1 -formatter_profile=_Kotlin -formatter_settings_version=12 diff --git a/kotlin-bundled-compiler/META-INF/MANIFEST.MF b/kotlin-bundled-compiler/META-INF/MANIFEST.MF index c491979ba..4db053701 100644 --- a/kotlin-bundled-compiler/META-INF/MANIFEST.MF +++ b/kotlin-bundled-compiler/META-INF/MANIFEST.MF @@ -2,29 +2,44 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Bundled Kotlin Compiler Bundle-SymbolicName: org.jetbrains.kotlin.bundled-compiler;singleton:=true -Bundle-Version: 0.8.21.qualifier +Bundle-Version: 1.6.21.qualifier Bundle-Vendor: JetBrains Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: ., + lib/ide-common.jar, lib/kotlin-compiler.jar, - lib/intellij-core-analysis.jar, + lib/ide-dependencies.jar, lib/kotlin-stdlib.jar, lib/kotlin-plugin-parts.jar, lib/kotlin-script-runtime.jar, lib/kotlin-scripting-compiler.jar, + lib/kotlin-formatter.jar, + lib/kotlin-common.jar, + lib/kotlin-core.jar, + lib/kotlin-idea.jar, + lib/kotlin-j2k-old.jar, + lib/kotlin-j2k-new.jar, + lib/kotlin-j2k-idea.jar, + lib/kotlin-j2k-services.jar, + lib/kotlin-frontend-independent.jar, lib/kotlin-reflect.jar, ../kotlin-eclipse-ui-test/lib/gson-2.3.1.jar, - lib/ide-dependencies.jar, lib/annotations-13.0.jar, lib/kotlin-scripting-compiler-impl.jar, lib/kotlin-scripting-common.jar, lib/kotlin-scripting-jvm.jar, - lib/ide-common.jar -Export-Package: + lib/kotlinx-coroutines-core.jar, + lib/intellij-core-analysis-deprecated.jar +Export-Package: com.google.common.collect, com.intellij, + org.jetbrains.kotlin.idea.util.application, + org.jetbrains.kotlin.idea.caches.resolve, + org.jetbrains.kotlin.idea.core.util, + org.jetbrains.kotlin.nj2k, + org.jetbrains.kotlin.idea.j2k, + org.jetbrains.kotlin.nj2k.postProcessing, com.intellij.codeInsight, com.intellij.codeInsight.completion.scope, - com.intellij.codeInsight.daemon, com.intellij.codeInsight.folding, com.intellij.codeInsight.folding.impl, com.intellij.codeInsight.javadoc, @@ -37,7 +52,6 @@ Export-Package: com.intellij.ide, com.intellij.ide.highlighter, com.intellij.ide.plugins, - com.intellij.ide.plugins.cl, com.intellij.ide.util, com.intellij.injected.editor, com.intellij.lang, @@ -197,15 +211,18 @@ Export-Package: kotlin.reflect.full, kotlin.reflect.jvm.internal.impl.load.kotlin, kotlin.script.dependencies, + kotlin.script.experimental.annotations, kotlin.script.experimental.api, kotlin.script.experimental.dependencies, kotlin.script.experimental.host, kotlin.script.experimental.jvm, + kotlin.script.experimental.util, kotlin.script.extensions, kotlin.script.templates, kotlin.script.templates.standard, kotlin.sequences, kotlin.text, + kotlinx.coroutines, org.jetbrains.annotations, org.jetbrains.kotlin, org.jetbrains.kotlin.analyzer, @@ -259,6 +276,7 @@ Export-Package: org.jetbrains.kotlin.descriptors, org.jetbrains.kotlin.descriptors.annotations, org.jetbrains.kotlin.descriptors.impl, + org.jetbrains.kotlin.descriptors.java, org.jetbrains.kotlin.diagnostics, org.jetbrains.kotlin.diagnostics.rendering, org.jetbrains.kotlin.extensions, @@ -345,6 +363,7 @@ Export-Package: org.jetbrains.kotlin.resolve.lazy.data, org.jetbrains.kotlin.resolve.lazy.declarations, org.jetbrains.kotlin.resolve.lazy.descriptors, + org.jetbrains.kotlin.resolve.sam, org.jetbrains.kotlin.resolve.scopes, org.jetbrains.kotlin.resolve.scopes.receivers, org.jetbrains.kotlin.resolve.scopes.utils, diff --git a/kotlin-bundled-compiler/build.gradle.kts b/kotlin-bundled-compiler/build.gradle.kts index 0fdf0016c..cdd8a9d6b 100644 --- a/kotlin-bundled-compiler/build.gradle.kts +++ b/kotlin-bundled-compiler/build.gradle.kts @@ -1,7 +1,7 @@ import com.intellij.buildsupport.dependencies.PackageListFromSimpleFile +import com.intellij.buildsupport.resolve.http.HttpArtifact +import com.intellij.buildsupport.resolve.http.HttpArtifactsResolver import com.intellij.buildsupport.resolve.http.idea.IntellijIdeaArtifactsResolver -import com.intellij.buildsupport.resolve.tc.kotlin.CommonIDEArtifactsResolver -import com.intellij.buildsupport.resolve.tc.kotlin.KotlinCompilerTCArtifactsResolver import com.intellij.buildsupport.utils.FileUtils apply(plugin = "base") @@ -11,13 +11,16 @@ val teamcityBaseUrl ="https://teamcity.jetbrains.com" val ideaSdkUrl = "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/idea" // properties that might/should be modifiable -val kotlinCompilerTcBuildId: String = project.findProperty("kotlinCompilerTcBuildId") as String? ?: "3282462" -val kotlinCompilerVersion: String = project.findProperty("kotlinCompilerVersion") as String? ?: "1.4.0" -val kotlinxVersion: String = project.findProperty("kolinxVersion") as String? ?: "1.3.1" + +//val kotlinCompilerTcBuildId: String = project.findProperty("kotlinCompilerTcBuildId") as String? ?: "3546752" +val kotlinPluginUpdateId = project.findProperty("kotlinPluginUpdateId") as String? ?: "169248" // Kotlin Plugin 1.6.21 for Idea 2021.3 + +val kotlinCompilerVersion: String = project.findProperty("kotlinCompilerVersion") as String? ?: "1.6.21" +val kotlinxVersion: String = project.findProperty("kolinxVersion") as String? ?: "1.5.2" val tcArtifactsPath: String = project.findProperty("tcArtifactsPath") as String? ?: "" -val ideaVersion: String = project.findProperty("ideaVersion") as String? ?: "193.6494.35" -val kotlinIdeaCompatibleVersionMinor: String = project.findProperty("kotlinIdeaCompatibleVersionMinor") as String? ?: "2019.3" -val ignoreSources: Boolean = project.hasProperty("ignoreSources") +val ideaVersion: String = project.findProperty("ideaVersion") as String? ?: "213.5744.223" //Idea 2021.3 +val kotlinIdeaCompatibleVersionMinor: String = project.findProperty("kotlinIdeaCompatibleVersionMinor") as String? ?: "2021.3" +val ignoreSources: Boolean = true//project.hasProperty("ignoreSources") //directories val testDataDir = file("${projectDir.parentFile}/kotlin-eclipse-ui-test/common_testData") @@ -33,14 +36,21 @@ val libDir = if (teamCityWorkingDir != null) file("$teamCityWorkingDir/lib") els val localTCArtifacts: Boolean = tcArtifactsPath.isNotBlank() val downloadDir = if(localTCArtifacts) file(tcArtifactsPath) else file("$libDir/$downloadDirName") -val tcArtifactsResolver = KotlinCompilerTCArtifactsResolver(teamcityBaseUrl, +/*val tcArtifactsResolver = KotlinCompilerTCArtifactsResolver(teamcityBaseUrl, project.hasProperty("lastSuccessfulBuild"), kotlinCompilerTcBuildId, kotlinCompilerVersion, - kotlinIdeaCompatibleVersionMinor) + kotlinIdeaCompatibleVersionMinor)*/ + +HttpArtifactsResolver.getProxyProps()["https.proxyHost"] = project.findProperty("https.proxyHost") ?: System.getProperty("https.proxyHost") +HttpArtifactsResolver.getProxyProps()["https.proxyPort"] = project.findProperty("https.proxyPort") ?: System.getProperty("https.proxyPort") +HttpArtifactsResolver.getProxyProps()["https.proxyUser"] = project.findProperty("https.proxyUser") ?: System.getProperty("https.proxyUser") +HttpArtifactsResolver.getProxyProps()["https.proxyPassword"] = project.findProperty("https.proxyPassword") ?: System.getProperty("https.proxyPassword") val ideaArtifactsResolver = IntellijIdeaArtifactsResolver(ideaSdkUrl, ideaVersion) +val kotlinPluginArtifactsResolver = HttpArtifactsResolver("https://plugins.jetbrains.com") +val tempKotlinHttpArtifact = HttpArtifact("plugin/download?rel=true&updateId=$kotlinPluginUpdateId") tasks.withType { gradleVersion = "5.5.1" @@ -67,6 +77,12 @@ tasks.named("clean") { } } +val deleteLibrariesFromLibFolder by tasks.registering { + doFirst { + libDir.listFiles()?.filter { it.isFile }?.forEach { it.deleteRecursively() } + } +} + val downloadTestData by tasks.registering { val locallyDownloadedTestDataFile by extra { if(localTCArtifacts){ @@ -77,16 +93,15 @@ val downloadTestData by tasks.registering { } doLast { - if (!localTCArtifacts) { - tcArtifactsResolver.downloadTo(tcArtifactsResolver.KOTLIN_TEST_DATA_ZIP, locallyDownloadedTestDataFile) + //TODO can we get the test data from somewhere? + if (!localTCArtifacts && !locallyDownloadedTestDataFile.exists()) { + //tcArtifactsResolver.downloadTo(tcArtifactsResolver.KOTLIN_TEST_DATA_ZIP, locallyDownloadedTestDataFile) } - copy { + /*copy { from(zipTree(locallyDownloadedTestDataFile)) into(testDataDir) - } - - locallyDownloadedTestDataFile.delete() + }*/ } } @@ -96,14 +111,18 @@ val downloadTestFrameworkDependencies by tasks.registering(Copy::class) { } val downloadKotlinCompilerPluginAndExtractSelectedJars by tasks.registering { + dependsOn(deleteLibrariesFromLibFolder) + + val kotlinDownloadDir = file("$downloadDir/kotlin-$kotlinCompilerVersion/$kotlinIdeaCompatibleVersionMinor") val locallyDownloadedCompilerFile by extra { - file(downloadDir).listFiles()?.firstOrNull { it.name.startsWith("kotlin-plugin-") } - ?: file("$downloadDir/kotlin-plugin.zip") + file(kotlinDownloadDir).listFiles()?.firstOrNull { it.name.startsWith("kotlin-plugin-") } + ?: file("$kotlinDownloadDir/kotlin-plugin.zip") } doLast { - if (!localTCArtifacts) { - tcArtifactsResolver.downloadTo(tcArtifactsResolver.KOTLIN_PLUGIN_ZIP, locallyDownloadedCompilerFile) + if (!localTCArtifacts && !locallyDownloadedCompilerFile.exists()) { + kotlinPluginArtifactsResolver.downloadTo(tempKotlinHttpArtifact, locallyDownloadedCompilerFile) + //tcArtifactsResolver.downloadTo(tcArtifactsResolver.KOTLIN_PLUGIN_ZIP, locallyDownloadedCompilerFile) } copy { @@ -111,6 +130,15 @@ val downloadKotlinCompilerPluginAndExtractSelectedJars by tasks.registering { setIncludes(setOf("Kotlin/lib/kotlin-plugin.jar", "Kotlin/lib/ide-common.jar", + "Kotlin/lib/kotlin-core.jar", + "Kotlin/lib/kotlin-idea.jar", + "Kotlin/lib/kotlin-common.jar", + "Kotlin/lib/kotlin-j2k-old.jar", + "Kotlin/lib/kotlin-j2k-new.jar", + "Kotlin/lib/kotlin-j2k-idea.jar", + "Kotlin/lib/kotlin-j2k-services.jar", + "Kotlin/lib/kotlin-frontend-independent.jar", + "Kotlin/lib/kotlin-formatter.jar", "Kotlin/kotlinc/lib/kotlin-compiler.jar", "Kotlin/kotlinc/lib/kotlin-stdlib.jar", "Kotlin/kotlinc/lib/kotlin-reflect.jar", @@ -141,8 +169,8 @@ val extractPackagesFromPlugin by tasks.registering(Jar::class) { dependsOn(downloadKotlinCompilerPluginAndExtractSelectedJars) from(zipTree("$libDir/kotlin-plugin.jar")) - destinationDir = libDir - archiveName = "kotlin-plugin-parts.jar" + destinationDirectory.set(libDir) + archiveFileName.set("kotlin-plugin-parts.jar") include("**") exclude("com/intellij/util/**") @@ -152,15 +180,18 @@ val extractPackagesFromPlugin by tasks.registering(Jar::class) { } val downloadIntellijCoreAndExtractSelectedJars by tasks.registering { - val locallyDownloadedIntellijCoreFile by extra { file("$downloadDir/intellij-core.zip") } + dependsOn(deleteLibrariesFromLibFolder) + val ideaDownloadDir = file("$downloadDir/idea-$ideaVersion") + val locallyDownloadedIntellijCoreFile by extra { file("$ideaDownloadDir/intellij-core.zip") } doLast { - ideaArtifactsResolver.downloadTo(ideaArtifactsResolver.INTELLIJ_CORE_ZIP, locallyDownloadedIntellijCoreFile) - + if(!locallyDownloadedIntellijCoreFile.exists()) { + ideaArtifactsResolver.downloadTo(ideaArtifactsResolver.INTELLIJ_CORE_ZIP, locallyDownloadedIntellijCoreFile) + } copy { from(zipTree(locallyDownloadedIntellijCoreFile)) - setIncludes(setOf("intellij-core.jar", "intellij-core-analysis.jar")) + setIncludes(setOf("intellij-core.jar", "intellij-core-analysis-deprecated.jar")) includeEmptyDirs = false @@ -170,18 +201,21 @@ val downloadIntellijCoreAndExtractSelectedJars by tasks.registering { } val downloadIdeaDistributionZipAndExtractSelectedJars by tasks.registering { - val locallyDownloadedIdeaZipFile by extra { file("$downloadDir/ideaIC.zip") } - val chosenJars by extra { setOf("openapi", - "platform-util-ui", + dependsOn(deleteLibrariesFromLibFolder) + val ideaDownloadDir = file("$downloadDir/idea-$ideaVersion") + val locallyDownloadedIdeaZipFile by extra { file("$ideaDownloadDir/ideaIC.zip") } + val chosenJars by extra { setOf(//"openapi", + //"platform-util-ui", "util", "idea", - "trove4j", + //"trove4j", "platform-api", "platform-impl") } doLast { - ideaArtifactsResolver.downloadTo(ideaArtifactsResolver.IDEA_IC_ZIP, locallyDownloadedIdeaZipFile) - + if(!locallyDownloadedIdeaZipFile.exists()) { + ideaArtifactsResolver.downloadTo(ideaArtifactsResolver.IDEA_IC_ZIP, locallyDownloadedIdeaZipFile) + } copy { from(zipTree(locallyDownloadedIdeaZipFile)) @@ -204,7 +238,7 @@ val extractSelectedFilesFromIdeaJars by tasks.registering { val packages by extra { /*new PackageListFromManifest("META-INF/MANIFEST.MF"),*/ - PackageListFromSimpleFile("referencedPackages.txt").pathsToInclude + PackageListFromSimpleFile(file("referencedPackages.txt").path).pathsToInclude } val extractDir by extra { file("$downloadDir/dependencies") } @@ -228,8 +262,8 @@ val createIdeDependenciesJar by tasks.registering(Jar::class) { val extractDir: File by extractSelectedFilesFromIdeaJars.get().extra from(extractDir) - destinationDir = libDir - archiveName = "ide-dependencies.jar" + destinationDirectory.set(libDir) + archiveFileName.set("ide-dependencies.jar") manifest { attributes(mapOf("Built-By" to "JetBrains", @@ -254,8 +288,13 @@ val downloadIdeaAndKotlinCompilerSources by tasks.registering { val locallyDownloadedIdeaSourcesFile by extra { file("$downloadDir/idea-sdk-sources.jar") } doLast { - tcArtifactsResolver.downloadTo(tcArtifactsResolver.KOTLIN_COMPILER_SOURCES_JAR, locallyDownloadedKotlinCompilerSourcesFile) - ideaArtifactsResolver.downloadTo(ideaArtifactsResolver.IDEA_IC_SOURCES_JAR, locallyDownloadedIdeaSourcesFile) + if(!locallyDownloadedKotlinCompilerSourcesFile.exists()) { + //TODO can we get the sources from somewhere? + //tcArtifactsResolver.downloadTo(tcArtifactsResolver.KOTLIN_COMPILER_SOURCES_JAR, locallyDownloadedKotlinCompilerSourcesFile) + } + if(!locallyDownloadedIdeaSourcesFile.exists()) { + ideaArtifactsResolver.downloadTo(ideaArtifactsResolver.IDEA_IC_SOURCES_JAR, locallyDownloadedIdeaSourcesFile) + } } } @@ -268,20 +307,18 @@ val repackageIdeaAndKotlinCompilerSources by tasks.registering(Zip::class) { from(zipTree(locallyDownloadedKotlinCompilerSourcesFile)) from(zipTree(locallyDownloadedIdeaSourcesFile)) - destinationDir = libDir - archiveName = "kotlin-compiler-sources.jar" + destinationDirectory.set(libDir) + archiveFileName.set("kotlin-compiler-sources.jar") } val downloadBundled by tasks.registering { if (localTCArtifacts) { - dependsOn(downloadKotlinCompilerPluginAndExtractSelectedJars, - extractPackagesFromPlugin, + dependsOn(extractPackagesFromPlugin, downloadIntellijCoreAndExtractSelectedJars, createIdeDependenciesJar, downloadKotlinxLibraries) } else { - dependsOn(downloadKotlinCompilerPluginAndExtractSelectedJars, - extractPackagesFromPlugin, + dependsOn(extractPackagesFromPlugin, downloadIntellijCoreAndExtractSelectedJars, createIdeDependenciesJar, downloadKotlinxLibraries) diff --git a/kotlin-bundled-compiler/build.properties b/kotlin-bundled-compiler/build.properties index 1052121f8..3843203b4 100644 --- a/kotlin-bundled-compiler/build.properties +++ b/kotlin-bundled-compiler/build.properties @@ -35,8 +35,17 @@ bin.includes = META-INF/,\ lib/kotlin-scripting-jvm.jar,\ lib/kotlin-scripting-compiler-impl.jar,\ lib/kotlin-plugin-parts.jar,\ + lib/kotlin-formatter.jar,\ + lib/kotlin-common.jar,\ + lib/kotlin-idea.jar,\ + lib/kotlin-core.jar,\ + lib/kotlin-j2k-old.jar,\ + lib/kotlin-j2k-new.jar,\ + lib/kotlin-j2k-idea.jar,\ + lib/kotlin-j2k-services.jar,\ + lib/kotlin-frontend-independent.jar,\ lib/ide-common.jar,\ - lib/intellij-core-analysis.jar + lib/intellij-core-analysis-deprecated.jar src.includes = lib/ bin.excludes = lib/kotlin-compiler-sources.jar,\ lib/downloads/ diff --git a/kotlin-bundled-compiler/buildSrc/build.gradle b/kotlin-bundled-compiler/buildSrc/build.gradle index 2cb2b707b..eef3ad4cd 100644 --- a/kotlin-bundled-compiler/buildSrc/build.gradle +++ b/kotlin-bundled-compiler/buildSrc/build.gradle @@ -9,14 +9,14 @@ repositories { dependencies { - compile 'org.jetbrains.teamcity:teamcity-rest-client:1.5.0' + implementation 'org.jetbrains.teamcity:teamcity-rest-client:1.5.0' - testCompile('org.spockframework.spock:spock-core:spock-1.3') { + testImplementation('org.spockframework.spock:spock-core:spock-1.3') { exclude module : 'groovy-all' } - testCompile 'com.github.stefanbirkner:system-rules:1.19.0' - testCompile 'org.apache.commons:commons-lang3:3.8.1' + testImplementation 'com.github.stefanbirkner:system-rules:1.19.0' + testImplementation 'org.apache.commons:commons-lang3:3.8.1' } -test.enabled = false // otherwise integration tests will run always before the actual build \ No newline at end of file +test.enabled = false // otherwise integration tests will run always before the actual build diff --git a/kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/dependencies/PackageList.groovy b/kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/dependencies/PackageList.groovy index abef5442e..d50ec329e 100644 --- a/kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/dependencies/PackageList.groovy +++ b/kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/dependencies/PackageList.groovy @@ -2,7 +2,15 @@ package com.intellij.buildsupport.dependencies abstract class PackageList { List getPathsToInclude() { - packageNames.collect { it.replace('.', '/') + '/*.class'} + List tempList = [] + packageNames.forEach { + if(it.startsWith("custom:")) { + tempList.add(it.replace("custom:", "")) + } else { + tempList.add(it.replace('.', '/') + '/*.class') + } + } + return tempList } protected abstract List getPackageNames() diff --git a/kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/http/HttpArtifactsResolver.groovy b/kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/http/HttpArtifactsResolver.groovy index 36eac1980..8df349e85 100644 --- a/kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/http/HttpArtifactsResolver.groovy +++ b/kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/http/HttpArtifactsResolver.groovy @@ -5,11 +5,13 @@ import groovy.transform.TupleConstructor @TupleConstructor(includeFields = true) -abstract class HttpArtifactsResolver { +class HttpArtifactsResolver { // FIELDS ========================================================================================================= protected final String httpBaseUrl + static Map proxyProps = new HashMap<>() + // PUBLIC API ===================================================================================================== final void downloadTo(HttpArtifact httpArtifact, File outputFile) { @@ -23,8 +25,16 @@ abstract class HttpArtifactsResolver { private void downloadFileFromUrlInto(String fileURL, File destinationFile) { destinationFile.parentFile.mkdirs() - new AntBuilder().get(src: fileURL, - dest: destinationFile, - usetimestamp: true) + def ant = new AntBuilder() + if (!proxyProps.isEmpty() && proxyProps['https.proxyHost'] != null) { + if (proxyProps.get("https.proxyUser") == null) { + ant.setproxy(proxyHost: proxyProps['https.proxyHost'], proxyPort: proxyProps['https.proxyPort']) + } else { + ant.setproxy(proxyHost: proxyProps['https.proxyHost'], proxyPort: proxyProps['https.proxyPort'], proxyUser: proxyProps['https.proxyUser'], proxyPassword: proxyProps['https.proxyPassword']) + } + } + ant.get(src: fileURL, + dest: destinationFile, + usetimestamp: true) } } diff --git a/kotlin-bundled-compiler/gradle/wrapper/gradle-wrapper.properties b/kotlin-bundled-compiler/gradle/wrapper/gradle-wrapper.properties index 4b7e1f3d3..442d9132e 100644 --- a/kotlin-bundled-compiler/gradle/wrapper/gradle-wrapper.properties +++ b/kotlin-bundled-compiler/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kotlin-bundled-compiler/pom.xml b/kotlin-bundled-compiler/pom.xml index 51d81f683..d18b59f6d 100644 --- a/kotlin-bundled-compiler/pom.xml +++ b/kotlin-bundled-compiler/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.bundled-compiler @@ -22,7 +22,9 @@ org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} - + + 11 + compile @@ -33,6 +35,15 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 8 + 8 + + \ No newline at end of file diff --git a/kotlin-bundled-compiler/referencedPackages.txt b/kotlin-bundled-compiler/referencedPackages.txt index 2198c7da0..b4e156c48 100644 --- a/kotlin-bundled-compiler/referencedPackages.txt +++ b/kotlin-bundled-compiler/referencedPackages.txt @@ -2,6 +2,7 @@ com.intellij.psi.codeStyle com.intellij.psi.formatter +com.intellij.openapi.components com.intellij.openapi.options com.intellij.application.options com.intellij.application.options.codeStyle.properties @@ -10,8 +11,14 @@ com.intellij.formatting.engine com.intellij.util.containers gnu.trove com.intellij.openapi.util +com.intellij.openapi.util.text com.intellij.psi.codeStyle.arrangement com.intellij.configurationStore com.intellij.openapi.progress -com.intellij.openapi.util com.intellij.ui +com.intellij.util.text +custom:com/intellij/CodeStyleBundle.class +custom:com/intellij/DynamicBundle.class +custom:com/intellij/AbstractBundle.class +custom:messages/CodeStyleBundle.* +it.unimi.dsi.fastutil.objects \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinNullableNotNullManager.kt b/kotlin-bundled-compiler/src/com/intellij/codeInsight/KotlinNullableNotNullManager.kt similarity index 77% rename from kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinNullableNotNullManager.kt rename to kotlin-bundled-compiler/src/com/intellij/codeInsight/KotlinNullableNotNullManager.kt index 762508103..3f1d91297 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinNullableNotNullManager.kt +++ b/kotlin-bundled-compiler/src/com/intellij/codeInsight/KotlinNullableNotNullManager.kt @@ -14,14 +14,14 @@ * limitations under the License. * *******************************************************************************/ -package org.jetbrains.kotlin.core.model +package com.intellij.codeInsight -import com.intellij.codeInsight.NullabilityAnnotationInfo -import com.intellij.codeInsight.NullableNotNullManager import com.intellij.openapi.project.Project import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiElement import com.intellij.psi.PsiModifierListOwner +import org.jetbrains.annotations.Nullable + // Dummy implementation. Will be changed to something more useful, when KE-277 is fixed. class KotlinNullableNotNullManager(project: Project) : NullableNotNullManager(project) { @@ -41,13 +41,27 @@ class KotlinNullableNotNullManager(project: Project) : NullableNotNullManager(pr _nullables.addAll(annotations) } - override fun getDefaultNotNull(): String = "NotNull" - override fun getNotNulls(): List = _notNulls + override fun setDefaultNotNull(defaultNotNull: String) { + } + override fun getDefaultNullable(): String = "Nullable" - override fun setDefaultNotNull(defaultNotNull: String) { + override fun getDefaultNotNull(): String { + return "NotNullable" + } + + override fun getDefaultNullables(): MutableList { + return mutableListOf(defaultNullable) + } + + override fun getDefaultNotNulls(): MutableList { + return mutableListOf(defaultNotNull) + } + + override fun getAllDefaultAnnotations(): MutableList { + return (defaultNullables + defaultNotNulls).toMutableList() } override fun setNotNulls(vararg annotations: String) { @@ -73,5 +87,14 @@ class KotlinNullableNotNullManager(project: Project) : NullableNotNullManager(pr } ?: false } + @Nullable + override fun getNullityDefault( + container: PsiModifierListOwner, + placeTargetTypes: Array, + context: PsiElement, superPackage: Boolean + ): NullabilityAnnotationInfo? { + return null + } + override fun isNullable(owner: PsiModifierListOwner, checkBases: Boolean) = !isNotNull(owner, checkBases) } \ No newline at end of file diff --git a/kotlin-bundled-compiler/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/kotlin-bundled-compiler/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index 1c899848c..096b7ded0 100644 --- a/kotlin-bundled-compiler/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/kotlin-bundled-compiler/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -2,4 +2,8 @@ public class ReformatCodeProcessor { public static final String COMMAND_NAME = "dummy"; + + public static String getCommandName() { + return "Reformat Code"; + } } diff --git a/kotlin-bundled-compiler/src/com/intellij/openapi/util/text/StringUtil.java b/kotlin-bundled-compiler/src/com/intellij/openapi/util/text/StringUtil.java index 3a460bcb4..37fa79134 100644 --- a/kotlin-bundled-compiler/src/com/intellij/openapi/util/text/StringUtil.java +++ b/kotlin-bundled-compiler/src/com/intellij/openapi/util/text/StringUtil.java @@ -28,3015 +28,3020 @@ //TeamCity inherits StringUtil: do not add private constructors!!! @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass") public class StringUtil extends StringUtilRt { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.text.StringUtil"); + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.text.StringUtil"); - @SuppressWarnings("SpellCheckingInspection") private static final String VOWELS = "aeiouy"; - private static final Pattern EOL_SPLIT_KEEP_SEPARATORS = Pattern.compile("(?<=(\r\n|\n))|(?<=\r)(?=[^\n])"); - private static final Pattern EOL_SPLIT_PATTERN = Pattern.compile(" *(\r|\n|\r\n)+ *"); - private static final Pattern EOL_SPLIT_PATTERN_WITH_EMPTY = Pattern.compile(" *(\r|\n|\r\n) *"); - private static final Pattern EOL_SPLIT_DONT_TRIM_PATTERN = Pattern.compile("(\r|\n|\r\n)+"); + @SuppressWarnings("SpellCheckingInspection") private static final String VOWELS = "aeiouy"; + private static final Pattern EOL_SPLIT_KEEP_SEPARATORS = Pattern.compile("(?<=(\r\n|\n))|(?<=\r)(?=[^\n])"); + private static final Pattern EOL_SPLIT_PATTERN = Pattern.compile(" *(\r|\n|\r\n)+ *"); + private static final Pattern EOL_SPLIT_PATTERN_WITH_EMPTY = Pattern.compile(" *(\r|\n|\r\n) *"); + private static final Pattern EOL_SPLIT_DONT_TRIM_PATTERN = Pattern.compile("(\r|\n|\r\n)+"); - @NotNull - public static MergingCharSequence replaceSubSequence(@NotNull CharSequence charSeq, int start, int end, @NotNull CharSequence replacement) { - return new MergingCharSequence( - new MergingCharSequence(charSeq.subSequence(0, start), replacement), - charSeq.subSequence(end, charSeq.length())); - } + @NotNull + public static MergingCharSequence replaceSubSequence(@NotNull CharSequence charSeq, int start, int end, @NotNull CharSequence replacement) { + return new MergingCharSequence( + new MergingCharSequence(charSeq.subSequence(0, start), replacement), + charSeq.subSequence(end, charSeq.length())); + } + + @Contract(value = "null -> null; !null->!null", pure = true) + public static String internEmptyString(String s) { + return s == null ? null : (s.isEmpty() ? "" : s); + } + + private static class MyHtml2Text extends HTMLEditorKit.ParserCallback { + @NotNull private final StringBuilder myBuffer = new StringBuilder(); + private final boolean myIsSkipStyleTag; + + private boolean myIsStyleTagOpened; + + private MyHtml2Text(boolean isSkipStyleTag) { + myIsSkipStyleTag = isSkipStyleTag; + } + + public void parse(@NotNull Reader in) throws IOException { + myBuffer.setLength(0); + new ParserDelegator().parse(in, this, Boolean.TRUE); + } + + @Override + public void handleText(@NotNull char[] text, int pos) { + if (!myIsStyleTagOpened) { + myBuffer.append(text); + } + } + + @Override + public void handleStartTag(@NotNull HTML.Tag tag, MutableAttributeSet set, int i) { + if (myIsSkipStyleTag && "style".equals(tag.toString())) { + myIsStyleTagOpened = true; + } + handleTag(tag); + } + + @Override + public void handleEndTag(@NotNull HTML.Tag tag, int pos) { + if (myIsSkipStyleTag && "style".equals(tag.toString())) { + myIsStyleTagOpened = false; + } + } + + @Override + public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet set, int i) { + handleTag(tag); + } + + private void handleTag(@NotNull HTML.Tag tag) { + if (tag.breaksFlow() && myBuffer.length() > 0) { + myBuffer.append(SystemProperties.getLineSeparator()); + } + } + + @NotNull + public String getText() { + return myBuffer.toString(); + } + } + + private static final MyHtml2Text html2TextParser = new MyHtml2Text(false); + + public static final NotNullFunction QUOTER = new NotNullFunction() { + @Override + @NotNull + public String fun(String s) { + return "\"" + s + "\""; + } + }; + + public static final NotNullFunction SINGLE_QUOTER = new NotNullFunction() { + @Override + @NotNull + public String fun(String s) { + return "'" + s + "'"; + } + }; + + @NotNull + @Contract(pure = true) + public static List getWordsInStringLongestFirst(@NotNull String find) { + List words = getWordsIn(find); + // hope long words are rare + Collections.sort(words, new Comparator() { + @Override + public int compare(@NotNull final String o1, @NotNull final String o2) { + return o2.length() - o1.length(); + } + }); + return words; + } + + @NotNull + @Contract(pure = true) + public static String escapePattern(@NotNull final String text) { + return replace(replace(text, "'", "''"), "{", "'{'"); + } + + @NotNull + @Contract(pure = true) + public static Function createToStringFunction(@SuppressWarnings("unused") @NotNull Class cls) { + return new Function() { + @Override + public String fun(@NotNull T o) { + return o.toString(); + } + }; + } + + @NotNull + public static final Function TRIMMER = new Function() { + @Nullable + @Override + public String fun(@Nullable String s) { + return trim(s); + } + }; + + // Unlike String.replace(CharSequence,CharSequence) does not allocate intermediate objects on non-match + // TODO revise when JDK9 arrives - its String.replace(CharSequence, CharSequence) is more optimized + @NotNull + @Contract(pure = true) + public static String replace(@NotNull String text, @NotNull String oldS, @NotNull String newS) { + return replace(text, oldS, newS, false); + } + + @NotNull + @Contract(pure = true) + public static String replaceIgnoreCase(@NotNull String text, @NotNull String oldS, @NotNull String newS) { + return replace(text, oldS, newS, true); + } + + /** + * @deprecated Use {@link String#replace(char,char)} instead + */ + @NotNull + @Contract(pure = true) + @Deprecated + public static String replaceChar(@NotNull String buffer, char oldChar, char newChar) { + return buffer.replace(oldChar, newChar); + } + + @Contract(pure = true) + public static String replace(@NotNull final String text, @NotNull final String oldS, @NotNull final String newS, final boolean ignoreCase) { + if (text.length() < oldS.length()) return text; + + StringBuilder newText = null; + int i = 0; + + while (i < text.length()) { + final int index = ignoreCase? indexOfIgnoreCase(text, oldS, i) : text.indexOf(oldS, i); + if (index < 0) { + if (i == 0) { + return text; + } + + newText.append(text, i, text.length()); + break; + } + else { + if (newText == null) { + if (text.length() == oldS.length()) { + return newS; + } + newText = new StringBuilder(text.length() - i); + } + + newText.append(text, i, index); + newText.append(newS); + i = index + oldS.length(); + } + } + return newText != null ? newText.toString() : ""; + } + + @Contract(pure = true) + public static int indexOfIgnoreCase(@NotNull String where, @NotNull String what, int fromIndex) { + return indexOfIgnoreCase((CharSequence)where, what, fromIndex); + } + + /** + * Implementation copied from {@link String#indexOf(String, int)} except character comparisons made case insensitive + */ + @Contract(pure = true) + public static int indexOfIgnoreCase(@NotNull CharSequence where, @NotNull CharSequence what, int fromIndex) { + int targetCount = what.length(); + int sourceCount = where.length(); + + if (fromIndex >= sourceCount) { + return targetCount == 0 ? sourceCount : -1; + } + + if (fromIndex < 0) { + fromIndex = 0; + } + + if (targetCount == 0) { + return fromIndex; + } + + char first = what.charAt(0); + int max = sourceCount - targetCount; + + for (int i = fromIndex; i <= max; i++) { + /* Look for first character. */ + if (!charsEqualIgnoreCase(where.charAt(i), first)) { + //noinspection StatementWithEmptyBody,AssignmentToForLoopParameter + while (++i <= max && !charsEqualIgnoreCase(where.charAt(i), first)) ; + } + + /* Found first character, now look at the rest of v2 */ + if (i <= max) { + int j = i + 1; + int end = j + targetCount - 1; + //noinspection StatementWithEmptyBody + for (int k = 1; j < end && charsEqualIgnoreCase(where.charAt(j), what.charAt(k)); j++, k++) ; + + if (j == end) { + /* Found whole string. */ + return i; + } + } + } + + return -1; + } + + @Contract(pure = true) + public static int indexOfIgnoreCase(@NotNull String where, char what, int fromIndex) { + int sourceCount = where.length(); + for (int i = Math.max(fromIndex, 0); i < sourceCount; i++) { + if (charsEqualIgnoreCase(where.charAt(i), what)) { + return i; + } + } + + return -1; + } + + @Contract(pure = true) + public static int lastIndexOfIgnoreCase(@NotNull String where, char what, int fromIndex) { + for (int i = Math.min(fromIndex, where.length() - 1); i >= 0; i--) { + if (charsEqualIgnoreCase(where.charAt(i), what)) { + return i; + } + } + + return -1; + } + + @Contract(pure = true) + public static boolean containsIgnoreCase(@NotNull String where, @NotNull String what) { + return indexOfIgnoreCase(where, what, 0) >= 0; + } + + @Contract(pure = true) + public static boolean endsWithIgnoreCase(@NotNull String str, @NotNull String suffix) { + return StringUtilRt.endsWithIgnoreCase(str, suffix); + } + + @Contract(pure = true) + public static boolean startsWithIgnoreCase(@NotNull String str, @NotNull String prefix) { + return StringUtilRt.startsWithIgnoreCase(str, prefix); + } + + @Contract(pure = true) + @NotNull + public static String stripHtml(@NotNull String html, boolean convertBreaks) { + if (convertBreaks) { + html = html.replaceAll("
", "\n\n"); + } + + return html.replaceAll("<(.|\n)*?>", ""); + } + + @Contract(value = "null -> null; !null -> !null", pure = true) + public static String toLowerCase(@Nullable final String str) { + return str == null ? null : str.toLowerCase(); + } + + @NotNull + @Contract(pure = true) + public static String getPackageName(@NotNull String fqName) { + return getPackageName(fqName, '.'); + } + + /** + * Given a fqName returns the package name for the type or the containing type. + *

+ *

    + *
  • {@code java.lang.String} -> {@code java.lang}
  • + *
  • {@code java.util.Map.Entry} -> {@code java.util.Map}
  • + *
+ * + * @param fqName a fully qualified type name. Not supposed to contain any type arguments + * @param separator the separator to use. Typically '.' + * @return the package name of the type or the declarator of the type. The empty string if the given fqName is unqualified + */ + @NotNull + @Contract(pure = true) + public static String getPackageName(@NotNull String fqName, char separator) { + int lastPointIdx = fqName.lastIndexOf(separator); + if (lastPointIdx >= 0) { + return fqName.substring(0, lastPointIdx); + } + return ""; + } + + @Contract(pure = true) + public static int getLineBreakCount(@NotNull CharSequence text) { + int count = 0; + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + if (c == '\n') { + count++; + } + else if (c == '\r') { + if (i + 1 < text.length() && text.charAt(i + 1) == '\n') { + //noinspection AssignmentToForLoopParameter + i++; + } + count++; + } + } + return count; + } + + @Contract(pure = true) + public static boolean containsLineBreak(@NotNull CharSequence text) { + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + if (isLineBreak(c)) return true; + } + return false; + } + + @Contract(pure = true) + public static boolean isLineBreak(char c) { + return c == '\n' || c == '\r'; + } + + @NotNull + @Contract(pure = true) + public static String escapeLineBreak(@NotNull String text) { + StringBuilder buffer = new StringBuilder(text.length()); + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + switch (c) { + case '\n': + buffer.append("\\n"); + break; + case '\r': + buffer.append("\\r"); + break; + default: + buffer.append(c); + } + } + return buffer.toString(); + } + + @Contract(pure = true) + public static boolean endsWithLineBreak(@NotNull CharSequence text) { + int len = text.length(); + return len > 0 && isLineBreak(text.charAt(len - 1)); + } + + @Contract(pure = true) + public static int lineColToOffset(@NotNull CharSequence text, int line, int col) { + int curLine = 0; + int offset = 0; + while (line != curLine) { + if (offset == text.length()) return -1; + char c = text.charAt(offset); + if (c == '\n') { + curLine++; + } + else if (c == '\r') { + curLine++; + if (offset < text.length() - 1 && text.charAt(offset + 1) == '\n') { + offset++; + } + } + offset++; + } + return offset + col; + } + + @Contract(pure = true) + public static int offsetToLineNumber(@NotNull CharSequence text, int offset) { + LineColumn lineColumn = offsetToLineColumn(text, offset); + return lineColumn != null ? lineColumn.line : -1; + } + + @Contract(pure = true) + public static LineColumn offsetToLineColumn(@NotNull CharSequence text, int offset) { + int curLine = 0; + int curLineStart = 0; + int curOffset = 0; + while (curOffset < offset) { + if (curOffset == text.length()) return null; + char c = text.charAt(curOffset); + if (c == '\n') { + curLine++; + curLineStart = curOffset + 1; + } + else if (c == '\r') { + curLine++; + if (curOffset < text.length() - 1 && text.charAt(curOffset + 1) == '\n') { + curOffset++; + } + curLineStart = curOffset + 1; + } + curOffset++; + } + + return LineColumn.of(curLine, offset - curLineStart); + } + + /** + * Classic dynamic programming algorithm for string differences. + */ + @Contract(pure = true) + public static int difference(@NotNull String s1, @NotNull String s2) { + int[][] a = new int[s1.length()][s2.length()]; + + for (int i = 0; i < s1.length(); i++) { + a[i][0] = i; + } + + for (int j = 0; j < s2.length(); j++) { + a[0][j] = j; + } + + for (int i = 1; i < s1.length(); i++) { + for (int j = 1; j < s2.length(); j++) { + + a[i][j] = Math.min(Math.min(a[i - 1][j - 1] + (s1.charAt(i) == s2.charAt(j) ? 0 : 1), a[i - 1][j] + 1), a[i][j - 1] + 1); + } + } + + return a[s1.length() - 1][s2.length() - 1]; + } + + @NotNull + @Contract(pure = true) + public static String wordsToBeginFromUpperCase(@NotNull String s) { + return fixCapitalization(s, ourPrepositions, true); + } + + @NotNull + @Contract(pure = true) + public static String wordsToBeginFromLowerCase(@NotNull String s) { + return fixCapitalization(s, ourPrepositions, false); + } + + @NotNull + @Contract(pure = true) + public static String toTitleCase(@NotNull String s) { + return fixCapitalization(s, ArrayUtil.EMPTY_STRING_ARRAY, true); + } + + @NotNull + private static String fixCapitalization(@NotNull String s, @NotNull String[] prepositions, boolean title) { + StringBuilder buffer = null; + for (int i = 0; i < s.length(); i++) { + char prevChar = i == 0 ? ' ' : s.charAt(i - 1); + char currChar = s.charAt(i); + if (!Character.isLetterOrDigit(prevChar) && prevChar != '\'') { + if (Character.isLetterOrDigit(currChar)) { + if (title || Character.isUpperCase(currChar)) { + int j = i; + for (; j < s.length(); j++) { + if (!Character.isLetterOrDigit(s.charAt(j))) { + break; + } + } + if (!title && j > i + 1 && !Character.isLowerCase(s.charAt(i + 1))) { + // filter out abbreviations like I18n, SQL and CSS + continue; + } + if (!isPreposition(s, i, j - 1, prepositions)) { + if (buffer == null) { + buffer = new StringBuilder(s); + } + buffer.setCharAt(i, title ? toUpperCase(currChar) : toLowerCase(currChar)); + } + } + } + } + } + return buffer == null ? s : buffer.toString(); + } + + private static final String[] ourPrepositions = { + "a", "an", "and", "as", "at", "but", "by", "down", "for", "from", "if", "in", "into", "not", "of", "on", "onto", "or", "out", "over", + "per", "nor", "the", "to", "up", "upon", "via", "with" + }; + + @Contract(pure = true) + public static boolean isPreposition(@NotNull String s, int firstChar, int lastChar) { + return isPreposition(s, firstChar, lastChar, ourPrepositions); + } + + @Contract(pure = true) + public static boolean isPreposition(@NotNull String s, int firstChar, int lastChar, @NotNull String[] prepositions) { + for (String preposition : prepositions) { + boolean found = false; + if (lastChar - firstChar + 1 == preposition.length()) { + found = true; + for (int j = 0; j < preposition.length(); j++) { + if (toLowerCase(s.charAt(firstChar + j)) != preposition.charAt(j)) { + found = false; + } + } + } + if (found) { + return true; + } + } + return false; + } + + @NotNull + @Contract(pure = true) + public static NotNullFunction escaper(final boolean escapeSlash, @Nullable final String additionalChars) { + return new NotNullFunction() { + @NotNull + @Override + public String fun(@NotNull String dom) { + final StringBuilder builder = new StringBuilder(dom.length()); + escapeStringCharacters(dom.length(), dom, additionalChars, escapeSlash, builder); + return builder.toString(); + } + }; + } + + + public static void escapeStringCharacters(int length, @NotNull String str, @NotNull StringBuilder buffer) { + escapeStringCharacters(length, str, "\"", buffer); + } + + @NotNull + public static StringBuilder escapeStringCharacters(int length, + @NotNull String str, + @Nullable String additionalChars, + @NotNull StringBuilder buffer) { + return escapeStringCharacters(length, str, additionalChars, true, buffer); + } + + @NotNull + public static StringBuilder escapeStringCharacters(int length, + @NotNull String str, + @Nullable String additionalChars, + boolean escapeSlash, + @NotNull StringBuilder buffer) { + return escapeStringCharacters(length, str, additionalChars, escapeSlash, true, buffer); + } + + @NotNull + public static StringBuilder escapeStringCharacters(int length, + @NotNull String str, + @Nullable String additionalChars, + boolean escapeSlash, + boolean escapeUnicode, + @NotNull StringBuilder buffer) { + char prev = 0; + for (int idx = 0; idx < length; idx++) { + char ch = str.charAt(idx); + switch (ch) { + case '\b': + buffer.append("\\b"); + break; + + case '\t': + buffer.append("\\t"); + break; + + case '\n': + buffer.append("\\n"); + break; + + case '\f': + buffer.append("\\f"); + break; + + case '\r': + buffer.append("\\r"); + break; + + default: + if (escapeSlash && ch == '\\') { + buffer.append("\\\\"); + } + else if (additionalChars != null && additionalChars.indexOf(ch) > -1 && (escapeSlash || prev != '\\')) { + buffer.append("\\").append(ch); + } + else if (escapeUnicode && !isPrintableUnicode(ch)) { + CharSequence hexCode = toUpperCase(Integer.toHexString(ch)); + buffer.append("\\u"); + int paddingCount = 4 - hexCode.length(); + while (paddingCount-- > 0) { + buffer.append(0); + } + buffer.append(hexCode); + } + else { + buffer.append(ch); + } + } + prev = ch; + } + return buffer; + } + + @Contract(pure = true) + public static boolean isPrintableUnicode(char c) { + int t = Character.getType(c); + return t != Character.UNASSIGNED && t != Character.LINE_SEPARATOR && t != Character.PARAGRAPH_SEPARATOR && + t != Character.CONTROL && t != Character.FORMAT && t != Character.PRIVATE_USE && t != Character.SURROGATE; + } + + @NotNull + @Contract(pure = true) + public static String escapeStringCharacters(@NotNull String s) { + StringBuilder buffer = new StringBuilder(s.length()); + escapeStringCharacters(s.length(), s, "\"", buffer); + return buffer.toString(); + } + + @NotNull + @Contract(pure = true) + public static String escapeCharCharacters(@NotNull String s) { + StringBuilder buffer = new StringBuilder(s.length()); + escapeStringCharacters(s.length(), s, "\'", buffer); + return buffer.toString(); + } + + @NotNull + @Contract(pure = true) + public static String unescapeStringCharacters(@NotNull String s) { + StringBuilder buffer = new StringBuilder(s.length()); + unescapeStringCharacters(s.length(), s, buffer); + return buffer.toString(); + } + + private static boolean isQuoteAt(@NotNull String s, int ind) { + char ch = s.charAt(ind); + return ch == '\'' || ch == '\"'; + } + + @Contract(pure = true) + public static boolean isQuotedString(@NotNull String s) { + return StringUtilRt.isQuotedString(s); + } + + @NotNull + @Contract(pure = true) + public static String unquoteString(@NotNull String s) { + return StringUtilRt.unquoteString(s); + } + + private static void unescapeStringCharacters(int length, @NotNull String s, @NotNull StringBuilder buffer) { + boolean escaped = false; + for (int idx = 0; idx < length; idx++) { + char ch = s.charAt(idx); + if (!escaped) { + if (ch == '\\') { + escaped = true; + } + else { + buffer.append(ch); + } + } + else { + int octalEscapeMaxLength = 2; + switch (ch) { + case 'n': + buffer.append('\n'); + break; + + case 'r': + buffer.append('\r'); + break; + + case 'b': + buffer.append('\b'); + break; + + case 't': + buffer.append('\t'); + break; + + case 'f': + buffer.append('\f'); + break; + + case '\'': + buffer.append('\''); + break; + + case '\"': + buffer.append('\"'); + break; + + case '\\': + buffer.append('\\'); + break; + + case 'u': + if (idx + 4 < length) { + try { + int code = Integer.parseInt(s.substring(idx + 1, idx + 5), 16); + //noinspection AssignmentToForLoopParameter + idx += 4; + buffer.append((char)code); + } + catch (NumberFormatException e) { + buffer.append("\\u"); + } + } + else { + buffer.append("\\u"); + } + break; + + case '0': + case '1': + case '2': + case '3': + octalEscapeMaxLength = 3; + //noinspection fallthrough + case '4': + case '5': + case '6': + case '7': + int escapeEnd = idx + 1; + while (escapeEnd < length && escapeEnd < idx + octalEscapeMaxLength && isOctalDigit(s.charAt(escapeEnd))) escapeEnd++; + try { + buffer.append((char)Integer.parseInt(s.substring(idx, escapeEnd), 8)); + } + catch (NumberFormatException e) { + throw new RuntimeException("Couldn't parse " + s.substring(idx, escapeEnd), e); // shouldn't happen + } + //noinspection AssignmentToForLoopParameter + idx = escapeEnd - 1; + break; + + default: + buffer.append(ch); + break; + } + escaped = false; + } + } + + if (escaped) buffer.append('\\'); + } + +// @NotNull +// @Contract(pure = true) +// public static String pluralize(@NotNull String word) { +// String plural = Pluralizer.PLURALIZER.plural(word); +// if (plural != null) return plural; +// if (word.endsWith("s")) return Pluralizer.restoreCase(word, word + "es"); +// return Pluralizer.restoreCase(word, word + "s"); +// } + + @NotNull + @Contract(pure = true) + public static String capitalizeWords(@NotNull String text, + boolean allWords) { + return capitalizeWords(text, " \t\n\r\f", allWords, false); + } + + @NotNull + @Contract(pure = true) + public static String capitalizeWords(@NotNull String text, + @NotNull String tokenizerDelim, + boolean allWords, + boolean leaveOriginalDelims) { + final StringTokenizer tokenizer = new StringTokenizer(text, tokenizerDelim, leaveOriginalDelims); + final StringBuilder out = new StringBuilder(text.length()); + boolean toCapitalize = true; + while (tokenizer.hasMoreTokens()) { + final String word = tokenizer.nextToken(); + if (!leaveOriginalDelims && out.length() > 0) { + out.append(' '); + } + out.append(toCapitalize ? capitalize(word) : word); + if (!allWords) { + toCapitalize = false; + } + } + return out.toString(); + } + + @NotNull + @Contract(pure = true) + public static String decapitalize(@NotNull String s) { + return Introspector.decapitalize(s); + } + + @Contract(pure = true) + public static boolean isVowel(char c) { + return VOWELS.indexOf(c) >= 0; + } + + /** + * Capitalize the first letter of the sentence. + */ + @NotNull + @Contract(pure = true) + public static String capitalize(@NotNull String s) { + if (s.isEmpty()) return s; + if (s.length() == 1) return toUpperCase(s).toString(); + + // Optimization + if (Character.isUpperCase(s.charAt(0))) return s; + return toUpperCase(s.charAt(0)) + s.substring(1); + } + + @Contract(value = "null -> false", pure = true) + public static boolean isCapitalized(@Nullable String s) { + return s != null && !s.isEmpty() && Character.isUpperCase(s.charAt(0)); + } + + @NotNull + @Contract(pure = true) + public static String capitalizeWithJavaBeanConvention(@NotNull String s) { + if (s.length() > 1 && Character.isUpperCase(s.charAt(1))) { + return s; + } + return capitalize(s); + } + + @Contract(pure = true) + public static int stringHashCode(@NotNull CharSequence chars) { + if (chars instanceof String || chars instanceof CharSequenceWithStringHash) { + // we know for sure these classes have conformant (and maybe faster) hashCode() + return chars.hashCode(); + } + + return stringHashCode(chars, 0, chars.length()); + } + + @Contract(pure = true) + public static int stringHashCode(@NotNull CharSequence chars, int from, int to) { + int h = 0; + for (int off = from; off < to; off++) { + h = 31 * h + chars.charAt(off); + } + return h; + } + + @Contract(pure = true) + public static int stringHashCode(char[] chars, int from, int to) { + int h = 0; + for (int off = from; off < to; off++) { + h = 31 * h + chars[off]; + } + return h; + } + + @Contract(pure = true) + public static int stringHashCodeInsensitive(@NotNull char[] chars, int from, int to) { + int h = 0; + for (int off = from; off < to; off++) { + h = 31 * h + toLowerCase(chars[off]); + } + return h; + } + + @Contract(pure = true) + public static int stringHashCodeInsensitive(@NotNull CharSequence chars, int from, int to) { + int h = 0; + for (int off = from; off < to; off++) { + h = 31 * h + toLowerCase(chars.charAt(off)); + } + return h; + } + + @Contract(pure = true) + public static int stringHashCodeInsensitive(@NotNull CharSequence chars) { + return stringHashCodeInsensitive(chars, 0, chars.length()); + } + + @Contract(pure = true) + public static int stringHashCodeIgnoreWhitespaces(@NotNull char[] chars, int from, int to) { + int h = 0; + for (int off = from; off < to; off++) { + char c = chars[off]; + if (!isWhiteSpace(c)) { + h = 31 * h + c; + } + } + return h; + } + + @Contract(pure = true) + public static int stringHashCodeIgnoreWhitespaces(@NotNull CharSequence chars, int from, int to) { + int h = 0; + for (int off = from; off < to; off++) { + char c = chars.charAt(off); + if (!isWhiteSpace(c)) { + h = 31 * h + c; + } + } + return h; + } + + @Contract(pure = true) + public static int stringHashCodeIgnoreWhitespaces(@NotNull CharSequence chars) { + return stringHashCodeIgnoreWhitespaces(chars, 0, chars.length()); + } + + /** + * Equivalent to string.startsWith(prefixes[0] + prefixes[1] + ...) but avoids creating an object for concatenation. + */ + @Contract(pure = true) + public static boolean startsWithConcatenation(@NotNull String string, @NotNull String... prefixes) { + int offset = 0; + for (String prefix : prefixes) { + int prefixLen = prefix.length(); + if (!string.regionMatches(offset, prefix, 0, prefixLen)) { + return false; + } + offset += prefixLen; + } + return true; + } + + @Contract(value = "null -> null; !null -> !null", pure = true) + public static String trim(@Nullable String s) { + return s == null ? null : s.trim(); + } + + @NotNull + @Contract(pure = true) + public static String trimEnd(@NotNull String s, @NotNull String suffix) { + return trimEnd(s, suffix, false); + } + + @NotNull + @Contract(pure = true) + public static String trimEnd(@NotNull String s, @NotNull String suffix, boolean ignoreCase) { + boolean endsWith = ignoreCase ? endsWithIgnoreCase(s, suffix) : s.endsWith(suffix); + if (endsWith) { + return s.substring(0, s.length() - suffix.length()); + } + return s; + } + + @NotNull + @Contract(pure = true) + public static String trimEnd(@NotNull String s, char suffix) { + if (endsWithChar(s, suffix)) { + return s.substring(0, s.length() - 1); + } + return s; + } + + @NotNull + @Contract(pure = true) + public static String trimLog(@NotNull final String text, final int limit) { + if (limit > 5 && text.length() > limit) { + return text.substring(0, limit - 5) + " ...\n"; + } + return text; + } + + @NotNull + @Contract(pure = true) + public static String trimLeading(@NotNull String string) { + return trimLeading((CharSequence)string).toString(); + } + @NotNull + @Contract(pure = true) + public static CharSequence trimLeading(@NotNull CharSequence string) { + int index = 0; + while (index < string.length() && Character.isWhitespace(string.charAt(index))) index++; + return string.subSequence(index, string.length()); + } + + @NotNull + @Contract(pure = true) + public static String trimLeading(@NotNull String string, char symbol) { + int index = 0; + while (index < string.length() && string.charAt(index) == symbol) index++; + return string.substring(index); + } + + @NotNull + public static StringBuilder trimLeading(@NotNull StringBuilder builder, char symbol) { + int index = 0; + while (index < builder.length() && builder.charAt(index) == symbol) index++; + if (index > 0) builder.delete(0, index); + return builder; + } + + @NotNull + @Contract(pure = true) + public static String trimTrailing(@NotNull String string) { + return trimTrailing((CharSequence)string).toString(); + } + + @NotNull + @Contract(pure = true) + public static CharSequence trimTrailing(@NotNull CharSequence string) { + int index = string.length() - 1; + while (index >= 0 && Character.isWhitespace(string.charAt(index))) index--; + return string.subSequence(0, index + 1); + } + + @NotNull + @Contract(pure = true) + public static String trimTrailing(@NotNull String string, char symbol) { + int index = string.length() - 1; + while (index >= 0 && string.charAt(index) == symbol) index--; + return string.substring(0, index + 1); + } + + @NotNull + public static StringBuilder trimTrailing(@NotNull StringBuilder builder, char symbol) { + int index = builder.length() - 1; + while (index >= 0 && builder.charAt(index) == symbol) index--; + builder.setLength(index + 1); + return builder; + } + + @Contract(pure = true) + public static boolean startsWithChar(@Nullable CharSequence s, char prefix) { + return s != null && s.length() != 0 && s.charAt(0) == prefix; + } + + @Contract(pure = true) + public static boolean endsWithChar(@Nullable CharSequence s, char suffix) { + return StringUtilRt.endsWithChar(s, suffix); + } + + @NotNull + @Contract(pure = true) + public static String trimStart(@NotNull String s, @NotNull String prefix) { + if (s.startsWith(prefix)) { + return s.substring(prefix.length()); + } + return s; + } + + @NotNull + @Contract(pure = true) + public static String trimExtensions(@NotNull String name) { + int index = name.indexOf('.'); + return index < 0 ? name : name.substring(0, index); + } + +// @NotNull +// @Contract(pure = true) +// public static String pluralize(@NotNull String base, int count) { +// if (count == 1) return base; +// return pluralize(base); +// } + + public static void repeatSymbol(@NotNull Appendable buffer, char symbol, int times) { + assert times >= 0 : times; + try { + for (int i = 0; i < times; i++) { + buffer.append(symbol); + } + } + catch (IOException e) { + LOG.error(e); + } + } + + @Contract(pure = true) + public static String defaultIfEmpty(@Nullable String value, String defaultValue) { + return isEmpty(value) ? defaultValue : value; + } + + @Contract(value = "null -> false", pure = true) + public static boolean isNotEmpty(@Nullable String s) { + return !isEmpty(s); + } + + @Contract(value = "null -> true", pure = true) + public static boolean isEmpty(@Nullable String s) { + return s == null || s.isEmpty(); + } + + @Contract(value = "null -> true",pure = true) + public static boolean isEmpty(@Nullable CharSequence cs) { + return StringUtilRt.isEmpty(cs); + } + + @Contract(pure = true) + public static int length(@Nullable CharSequence cs) { + return cs == null ? 0 : cs.length(); + } + + @NotNull + @Contract(pure = true) + public static String notNullize(@Nullable String s) { + return StringUtilRt.notNullize(s); + } + + @NotNull + @Contract(pure = true) + public static String notNullize(@Nullable String s, @NotNull String defaultValue) { + return StringUtilRt.notNullize(s, defaultValue); + } + + @Nullable + @Contract(pure = true) + public static String nullize(@Nullable String s) { + return nullize(s, false); + } + + @Nullable + @Contract(pure = true) + public static String nullize(@Nullable String s, boolean nullizeSpaces) { + boolean empty = nullizeSpaces ? isEmptyOrSpaces(s) : isEmpty(s); + return empty ? null : s; + } + + @Contract(value = "null -> true",pure = true) + // we need to keep this method to preserve backward compatibility + public static boolean isEmptyOrSpaces(@Nullable String s) { + return isEmptyOrSpaces((CharSequence)s); + } + + @Contract(value = "null -> true", pure = true) + public static boolean isEmptyOrSpaces(@Nullable CharSequence s) { + return StringUtilRt.isEmptyOrSpaces(s); + } + + /** + * Allows to answer if given symbol is white space, tabulation or line feed. + * + * @param c symbol to check + * @return {@code true} if given symbol is white space, tabulation or line feed; {@code false} otherwise + */ + @Contract(pure = true) + public static boolean isWhiteSpace(char c) { + return c == '\n' || c == '\t' || c == ' '; + } + + @NotNull + @Contract(pure = true) + public static String getThrowableText(@NotNull Throwable aThrowable) { + return ExceptionUtil.getThrowableText(aThrowable); + } + + @NotNull + @Contract(pure = true) + public static String repeatSymbol(final char aChar, final int count) { + char[] buffer = new char[count]; + Arrays.fill(buffer, aChar); + return StringFactory.createShared(buffer); + } + + @NotNull + @Contract(pure = true) + public static String repeat(@NotNull String s, int count) { + assert count >= 0 : count; + StringBuilder sb = new StringBuilder(s.length() * count); + for (int i = 0; i < count; i++) { + sb.append(s); + } + return sb.toString(); + } + + @NotNull + @Contract(pure = true) + public static List split(@NotNull String s, @NotNull String separator) { + return split(s, separator, true); + } + @NotNull + @Contract(pure = true) + public static List split(@NotNull CharSequence s, @NotNull CharSequence separator) { + return split(s, separator, true, true); + } + + @NotNull + @Contract(pure = true) + public static List split(@NotNull String s, @NotNull String separator, boolean excludeSeparator) { + return split(s, separator, excludeSeparator, true); + } + + @NotNull + @Contract(pure = true) + @SuppressWarnings("unchecked") + public static List split(@NotNull String s, @NotNull String separator, boolean excludeSeparator, boolean excludeEmptyStrings) { + return (List)split((CharSequence)s, separator, excludeSeparator, excludeEmptyStrings); + } + + @NotNull + @Contract(pure = true) + public static List split(@NotNull CharSequence s, @NotNull CharSequence separator, boolean excludeSeparator, boolean excludeEmptyStrings) { + if (separator.length() == 0) { + return Collections.singletonList(s); + } + List result = new ArrayList(); + int pos = 0; + while (true) { + int index = indexOf(s, separator, pos); + if (index == -1) break; + final int nextPos = index + separator.length(); + CharSequence token = s.subSequence(pos, excludeSeparator ? index : nextPos); + if (token.length() != 0 || !excludeEmptyStrings) { + result.add(token); + } + pos = nextPos; + } + if (pos < s.length() || !excludeEmptyStrings && pos == s.length()) { + result.add(s.subSequence(pos, s.length())); + } + return result; + } + + @NotNull + @Contract(pure = true) + public static Iterable tokenize(@NotNull String s, @NotNull String separators) { + final com.intellij.util.text.StringTokenizer tokenizer = new com.intellij.util.text.StringTokenizer(s, separators); + return new Iterable() { + @NotNull + @Override + public Iterator iterator() { + return new Iterator() { + @Override + public boolean hasNext() { + return tokenizer.hasMoreTokens(); + } + + @Override + public String next() { + return tokenizer.nextToken(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + + @NotNull + @Contract(pure = true) + public static Iterable tokenize(@NotNull final StringTokenizer tokenizer) { + return new Iterable() { + @NotNull + @Override + public Iterator iterator() { + return new Iterator() { + @Override + public boolean hasNext() { + return tokenizer.hasMoreTokens(); + } + + @Override + public String next() { + return tokenizer.nextToken(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + + /** + * @return list containing all words in {@code text}, or {@link ContainerUtil#emptyList()} if there are none. + * The word here means the maximum sub-string consisting entirely of characters which are {@code Character.isJavaIdentifierPart(c)}. + */ + @NotNull + @Contract(pure = true) + public static List getWordsIn(@NotNull String text) { + List result = null; + int start = -1; + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + boolean isIdentifierPart = Character.isJavaIdentifierPart(c); + if (isIdentifierPart && start == -1) { + start = i; + } + if (isIdentifierPart && i == text.length() - 1) { + if (result == null) { + result = new SmartList(); + } + result.add(text.substring(start, i + 1)); + } + else if (!isIdentifierPart && start != -1) { + if (result == null) { + result = new SmartList(); + } + result.add(text.substring(start, i)); + start = -1; + } + } + if (result == null) { + return ContainerUtil.emptyList(); + } + return result; + } + + @NotNull + @Contract(pure = true) + public static List getWordIndicesIn(@NotNull String text) { + return getWordIndicesIn(text, null); + } + + /** + * @param text text to get word ranges in. + * @param separatorsSet if not null, only these characters will be considered as separators (i.e. not a part of word). + * Otherwise {@link Character#isJavaIdentifierPart(char)} will be used to determine whether a symbol is part of word. + * @return ranges ranges of words in passed text. + */ + @NotNull + @Contract(pure = true) + public static List getWordIndicesIn(@NotNull String text, @Nullable Set separatorsSet) { + List result = new SmartList(); + int start = -1; + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + boolean isIdentifierPart = separatorsSet == null ? Character.isJavaIdentifierPart(c) : !separatorsSet.contains(c); + if (isIdentifierPart && start == -1) { + start = i; + } + if (isIdentifierPart && i == text.length() - 1) { + result.add(new TextRange(start, i + 1)); + } + else if (!isIdentifierPart && start != -1) { + result.add(new TextRange(start, i)); + start = -1; + } + } + return result; + } + + @NotNull + @Contract(pure = true) + public static String join(@NotNull final String[] strings, @NotNull final String separator) { + return join(strings, 0, strings.length, separator); + } + + @NotNull + @Contract(pure = true) + public static String join(@NotNull final String[] strings, int startIndex, int endIndex, @NotNull final String separator) { + final StringBuilder result = new StringBuilder(); + for (int i = startIndex; i < endIndex; i++) { + if (i > startIndex) result.append(separator); + result.append(strings[i]); + } + return result.toString(); + } + + @NotNull + @Contract(pure = true) + public static String[] zip(@NotNull String[] strings1, @NotNull String[] strings2, String separator) { + if (strings1.length != strings2.length) throw new IllegalArgumentException(); + + String[] result = ArrayUtil.newStringArray(strings1.length); + for (int i = 0; i < result.length; i++) { + result[i] = strings1[i] + separator + strings2[i]; + } + + return result; + } + + @NotNull + @Contract(pure = true) + public static String[] surround(@NotNull String[] strings, @NotNull String prefix, @NotNull String suffix) { + String[] result = ArrayUtil.newStringArray(strings.length); + for (int i = 0; i < result.length; i++) { + result[i] = prefix + strings[i] + suffix; + } + return result; + } + + @NotNull + @Contract(pure = true) + public static String join(@NotNull T[] items, @NotNull Function f, @NotNull String separator) { + return join(Arrays.asList(items), f, separator); + } + + @NotNull + @Contract(pure = true) + public static String join(@NotNull Collection items, + @NotNull Function f, + @NotNull String separator) { + if (items.isEmpty()) return ""; + if (items.size() == 1) return notNullize(f.fun(items.iterator().next())); + return join((Iterable)items, f, separator); + } + + @Contract(pure = true) + public static String join(@NotNull Iterable items, @NotNull String separator) { + StringBuilder result = new StringBuilder(); + for (Object item : items) { + result.append(item).append(separator); + } + if (result.length() > 0) { + result.setLength(result.length() - separator.length()); + } + return result.toString(); + } + + @NotNull + @Contract(pure = true) + public static String join(@NotNull Iterable items, + @NotNull Function f, + @NotNull String separator) { + StringBuilder result = new StringBuilder(); + join(items, f, separator, result); + return result.toString(); + } + + public static void join(@NotNull Iterable items, + @NotNull Function f, + @NotNull String separator, + @NotNull StringBuilder result) { + boolean isFirst = true; + for (T item : items) { + String string = f.fun(item); + if (!isEmpty(string)) { + if (isFirst) { + isFirst = false; + } + else { + result.append(separator); + } + result.append(string); + } + } + } + + @NotNull + @Contract(pure = true) + public static String join(@NotNull Collection strings, @NotNull String separator) { + if (strings.size() <= 1) { + return notNullize(ContainerUtil.getFirstItem(strings)); + } + StringBuilder result = new StringBuilder(); + join(strings, separator, result); + return result.toString(); + } + + public static void join(@NotNull Collection strings, @NotNull String separator, @NotNull StringBuilder result) { + boolean isFirst = true; + for (String string : strings) { + if (string != null) { + if (isFirst) { + isFirst = false; + } + else { + result.append(separator); + } + result.append(string); + } + } + } + + @NotNull + @Contract(pure = true) + public static String join(@NotNull final int[] strings, @NotNull final String separator) { + final StringBuilder result = new StringBuilder(); + for (int i = 0; i < strings.length; i++) { + if (i > 0) result.append(separator); + result.append(strings[i]); + } + return result.toString(); + } + + @NotNull + @Contract(pure = true) + public static String join(@NotNull final String... strings) { + if (strings.length == 0) return ""; + + final StringBuilder builder = new StringBuilder(); + for (final String string : strings) { + builder.append(string); + } + return builder.toString(); + } + + /** + * Consider using {@link StringUtil#unquoteString(String)} instead. + * Note: this method has an odd behavior: + * Quotes are removed even if leading and trailing quotes are different or + * if there is only one quote (leading or trailing). + */ + @NotNull + @Contract(pure = true) + public static String stripQuotesAroundValue(@NotNull String text) { + final int len = text.length(); + if (len > 0) { + final int from = isQuoteAt(text, 0) ? 1 : 0; + final int to = len > 1 && isQuoteAt(text, len - 1) ? len - 1 : len; + if (from > 0 || to < len) { + return text.substring(from, to); + } + } + return text; + } + + /** Formats given duration as a sum of time units (example: {@code formatDuration(123456) = "2 m 3 s 456 ms"}). */ + @NotNull + @Contract(pure = true) + public static String formatDuration(long duration) { + return formatDuration(duration, " "); + } + + private static final String[] TIME_UNITS = {"ms", "s", "m", "h", "d", "mo", "yr", "c", "ml", "ep"}; + private static final long[] TIME_MULTIPLIERS = {1, 1000, 60, 60, 24, 30, 12, 100, 10, 10000}; + + /** Formats given duration as a sum of time units (example: {@code formatDuration(123456, "") = "2m 3s 456ms"}). */ + @NotNull + @Contract(pure = true) + public static String formatDuration(long duration, @NotNull String unitSeparator) { + String[] units = TIME_UNITS; + + StringBuilder sb = new StringBuilder(); + long count = duration; + int i = 1; + for (; i < units.length && count > 0; i++) { + long multiplier = TIME_MULTIPLIERS[i]; + if (count < multiplier) break; + long remainder = count % multiplier; + count /= multiplier; + if (remainder != 0 || sb.length() > 0) { + if (!units[i - 1].isEmpty()) { + sb.insert(0, units[i - 1]); + sb.insert(0, unitSeparator); + } + sb.insert(0, remainder).insert(0, " "); + } + else { + remainder = Math.round(remainder * 100 / (double)multiplier); + count += remainder / 100; + } + } + if (!units[i - 1].isEmpty()) { + sb.insert(0, units[i - 1]); + sb.insert(0, unitSeparator); + } + sb.insert(0, count); + return sb.toString(); + } + + @Contract(pure = true) + public static boolean containsAlphaCharacters(@NotNull String value) { + for (int i = 0; i < value.length(); i++) { + if (Character.isLetter(value.charAt(i))) return true; + } + return false; + } + + @Contract(pure = true) + public static boolean containsAnyChar(@NotNull final String value, @NotNull final String chars) { + return chars.length() > value.length() + ? containsAnyChar(value, chars, 0, value.length()) + : containsAnyChar(chars, value, 0, chars.length()); + } + + @Contract(pure = true) + public static boolean containsAnyChar(@NotNull final String value, + @NotNull final String chars, + final int start, final int end) { + for (int i = start; i < end; i++) { + if (chars.indexOf(value.charAt(i)) >= 0) { + return true; + } + } + + return false; + } + + @Contract(pure = true) + public static boolean containsChar(@NotNull final String value, final char ch) { + return value.indexOf(ch) >= 0; + } + + /** + * @deprecated use #capitalize(String) + */ + @Deprecated + @Contract(value = "null -> null; !null -> !null", pure = true) + public static String firstLetterToUpperCase(@Nullable final String displayString) { + if (displayString == null || displayString.isEmpty()) return displayString; + char firstChar = displayString.charAt(0); + char uppedFirstChar = toUpperCase(firstChar); + + if (uppedFirstChar == firstChar) return displayString; + + char[] buffer = displayString.toCharArray(); + buffer[0] = uppedFirstChar; + return StringFactory.createShared(buffer); + } + + /** + * Strip out all characters not accepted by given filter + * + * @param s e.g. "/n my string " + * @param filter e.g. {@link CharFilter#NOT_WHITESPACE_FILTER} + * @return stripped string e.g. "mystring" + */ + @NotNull + @Contract(pure = true) + public static String strip(@NotNull final String s, @NotNull final CharFilter filter) { + final StringBuilder result = new StringBuilder(s.length()); + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + if (filter.accept(ch)) { + result.append(ch); + } + } + return result.toString(); + } + + @NotNull + @Contract(pure = true) + public static List findMatches(@NotNull String s, @NotNull Pattern pattern) { + return findMatches(s, pattern, 1); + } + + @NotNull + @Contract(pure = true) + public static List findMatches(@NotNull String s, @NotNull Pattern pattern, int groupIndex) { + List result = new SmartList(); + Matcher m = pattern.matcher(s); + while (m.find()) { + String group = m.group(groupIndex); + if (group != null) { + result.add(group); + } + } + return result; + } + + /** + * Find position of the first character accepted by given filter. + * + * @param s the string to search + * @param filter search filter + * @return position of the first character accepted or -1 if not found + */ + @Contract(pure = true) + public static int findFirst(@NotNull final CharSequence s, @NotNull CharFilter filter) { + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + if (filter.accept(ch)) { + return i; + } + } + return -1; + } + + @NotNull + @Contract(pure = true) + public static String replaceSubstring(@NotNull String string, @NotNull TextRange range, @NotNull String replacement) { + return range.replace(string, replacement); + } + + @Contract(pure = true) + public static boolean startsWithWhitespace(@NotNull String text) { + return !text.isEmpty() && Character.isWhitespace(text.charAt(0)); + } + + @Contract(pure = true) + public static boolean isChar(CharSequence seq, int index, char c) { + return index >= 0 && index < seq.length() && seq.charAt(index) == c; + } + + @Contract(pure = true) + public static boolean startsWith(@NotNull CharSequence text, @NotNull CharSequence prefix) { + int l1 = text.length(); + int l2 = prefix.length(); + if (l1 < l2) return false; + + for (int i = 0; i < l2; i++) { + if (text.charAt(i) != prefix.charAt(i)) return false; + } + + return true; + } + + @Contract(pure = true) + public static boolean startsWith(@NotNull CharSequence text, int startIndex, @NotNull CharSequence prefix) { + int tl = text.length(); + if (startIndex < 0 || startIndex > tl) { + throw new IllegalArgumentException("Index is out of bounds: " + startIndex + ", length: " + tl); + } + int l1 = tl - startIndex; + int l2 = prefix.length(); + if (l1 < l2) return false; + + for (int i = 0; i < l2; i++) { + if (text.charAt(i + startIndex) != prefix.charAt(i)) return false; + } + + return true; + } + + @Contract(pure = true) + public static boolean endsWith(@NotNull CharSequence text, @NotNull CharSequence suffix) { + int l1 = text.length(); + int l2 = suffix.length(); + if (l1 < l2) return false; + + for (int i = l1 - 1; i >= l1 - l2; i--) { + if (text.charAt(i) != suffix.charAt(i + l2 - l1)) return false; + } + + return true; + } + + @NotNull + @Contract(pure = true) + public static String commonPrefix(@NotNull String s1, @NotNull String s2) { + return s1.substring(0, commonPrefixLength(s1, s2)); + } + + @Contract(pure = true) + public static int commonPrefixLength(@NotNull CharSequence s1, @NotNull CharSequence s2) { + return commonPrefixLength(s1, s2, false); + } + + @Contract(pure = true) + public static int commonPrefixLength(@NotNull CharSequence s1, @NotNull CharSequence s2, boolean ignoreCase) { + int i; + int minLength = Math.min(s1.length(), s2.length()); + for (i = 0; i < minLength; i++) { + if (!charsMatch(s1.charAt(i), s2.charAt(i), ignoreCase)) { + break; + } + } + return i; + } + + @NotNull + @Contract(pure = true) + public static String commonSuffix(@NotNull String s1, @NotNull String s2) { + return s1.substring(s1.length() - commonSuffixLength(s1, s2)); + } + + @Contract(pure = true) + public static int commonSuffixLength(@NotNull CharSequence s1, @NotNull CharSequence s2) { + int s1Length = s1.length(); + int s2Length = s2.length(); + if (s1Length == 0 || s2Length == 0) return 0; + int i; + for (i = 0; i < s1Length && i < s2Length; i++) { + if (s1.charAt(s1Length - i - 1) != s2.charAt(s2Length - i - 1)) { + break; + } + } + return i; + } + + /** + * Allows to answer if target symbol is contained at given char sequence at {@code [start; end)} interval. + * + * @param s target char sequence to check + * @param start start offset to use within the given char sequence (inclusive) + * @param end end offset to use within the given char sequence (exclusive) + * @param c target symbol to check + * @return {@code true} if given symbol is contained at the target range of the given char sequence; + * {@code false} otherwise + */ + @Contract(pure = true) + public static boolean contains(@NotNull CharSequence s, int start, int end, char c) { + return indexOf(s, c, start, end) >= 0; + } + + @Contract(pure = true) + public static boolean containsWhitespaces(@Nullable CharSequence s) { + if (s == null) return false; + + for (int i = 0; i < s.length(); i++) { + if (Character.isWhitespace(s.charAt(i))) return true; + } + return false; + } + + @Contract(pure = true) + public static int indexOf(@NotNull CharSequence s, char c) { + return indexOf(s, c, 0, s.length()); + } + + @Contract(pure = true) + public static int indexOf(@NotNull CharSequence s, char c, int start) { + return indexOf(s, c, start, s.length()); + } + + @Contract(pure = true) + public static int indexOf(@NotNull CharSequence s, char c, int start, int end) { + end = Math.min(end, s.length()); + for (int i = Math.max(start, 0); i < end; i++) { + if (s.charAt(i) == c) return i; + } + return -1; + } + + @Contract(pure = true) + public static boolean contains(@NotNull CharSequence sequence, @NotNull CharSequence infix) { + return indexOf(sequence, infix) >= 0; + } + + @Contract(pure = true) + public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix) { + return indexOf(sequence, infix, 0); + } + + @Contract(pure = true) + public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix, int start) { + return indexOf(sequence, infix, start, sequence.length()); + } + + @Contract(pure = true) + public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix, int start, int end) { + for (int i = start; i <= end - infix.length(); i++) { + if (startsWith(sequence, i, infix)) { + return i; + } + } + return -1; + } + + @Contract(pure = true) + public static int indexOf(@NotNull CharSequence s, char c, int start, int end, boolean caseSensitive) { + end = Math.min(end, s.length()); + for (int i = Math.max(start, 0); i < end; i++) { + if (charsMatch(s.charAt(i), c, !caseSensitive)) return i; + } + return -1; + } + + @Contract(pure = true) + public static int indexOf(@NotNull char[] s, char c, int start, int end, boolean caseSensitive) { + end = Math.min(end, s.length); + for (int i = Math.max(start, 0); i < end; i++) { + if (charsMatch(s[i], c, !caseSensitive)) return i; + } + return -1; + } + + @Contract(pure = true) + public static int indexOfSubstringEnd(@NotNull String text, @NotNull String subString) { + int i = text.indexOf(subString); + if (i == -1) return -1; + return i + subString.length(); + } + + @Contract(pure = true) + public static int indexOfAny(@NotNull final String s, @NotNull final String chars) { + return indexOfAny(s, chars, 0, s.length()); + } + + @Contract(pure = true) + public static int indexOfAny(@NotNull final CharSequence s, @NotNull final String chars) { + return indexOfAny(s, chars, 0, s.length()); + } + + @Contract(pure = true) + public static int indexOfAny(@NotNull final String s, @NotNull final String chars, final int start, final int end) { + return indexOfAny((CharSequence)s, chars, start, end); + } + + @Contract(pure = true) + public static int indexOfAny(@NotNull final CharSequence s, @NotNull final String chars, final int start, int end) { + end = Math.min(end, s.length()); + for (int i = Math.max(start, 0); i < end; i++) { + if (containsChar(chars, s.charAt(i))) return i; + } + return -1; + } + + @Contract(pure = true) + public static int lastIndexOfAny(@NotNull CharSequence s, @NotNull final String chars) { + for (int i = s.length() - 1; i >= 0; i--) { + if (containsChar(chars, s.charAt(i))) return i; + } + return -1; + } + + @Nullable + @Contract(pure = true) + public static String substringBefore(@NotNull String text, @NotNull String subString) { + int i = text.indexOf(subString); + if (i == -1) return null; + return text.substring(0, i); + } + + @NotNull + @Contract(pure = true) + public static String substringBeforeLast(@NotNull String text, @NotNull String subString) { + int i = text.lastIndexOf(subString); + if (i == -1) return text; + return text.substring(0, i); + } + + @Nullable + @Contract(pure = true) + public static String substringAfter(@NotNull String text, @NotNull String subString) { + int i = text.indexOf(subString); + if (i == -1) return null; + return text.substring(i + subString.length()); + } + + @Nullable + @Contract(pure = true) + public static String substringAfterLast(@NotNull String text, @NotNull String subString) { + int i = text.lastIndexOf(subString); + if (i == -1) return null; + return text.substring(i + subString.length()); + } + + /** + * Allows to retrieve index of last occurrence of the given symbols at {@code [start; end)} sub-sequence of the given text. + * + * @param s target text + * @param c target symbol which last occurrence we want to check + * @param start start offset of the target text (inclusive) + * @param end end offset of the target text (exclusive) + * @return index of the last occurrence of the given symbol at the target sub-sequence of the given text if any; + * {@code -1} otherwise + */ + @Contract(pure = true) + public static int lastIndexOf(@NotNull CharSequence s, char c, int start, int end) { + return StringUtilRt.lastIndexOf(s, c, start, end); + } + + @NotNull + @Contract(pure = true) + public static String first(@NotNull String text, final int maxLength, final boolean appendEllipsis) { + return text.length() > maxLength ? text.substring(0, maxLength) + (appendEllipsis ? "..." : "") : text; + } + + @NotNull + @Contract(pure = true) + public static CharSequence first(@NotNull CharSequence text, final int length, final boolean appendEllipsis) { + if (text.length() <= length) { + return text; + } + if (appendEllipsis) { + return text.subSequence(0, length) + "..."; + } + return text.subSequence(0, length); + } + + @NotNull + @Contract(pure = true) + public static CharSequence last(@NotNull CharSequence text, final int length, boolean prependEllipsis) { + if (text.length() <= length) { + return text; + } + if (prependEllipsis) { + return "..." + text.subSequence(text.length() - length, text.length()); + } + return text.subSequence(text.length() - length, text.length()); + } + + @NotNull + @Contract(pure = true) + public static String firstLast(@NotNull String text, int length) { + return text.length() > length + ? text.subSequence(0, length / 2) + "\u2026" + text.subSequence(text.length() - length / 2 - 1, text.length()) + : text; + } + + @NotNull + @Contract(pure = true) + public static String escapeChar(@NotNull final String str, final char character) { + return escapeChars(str, character); + } + + @NotNull + @Contract(pure = true) + public static String escapeChars(@NotNull final String str, final char... character) { + final StringBuilder buf = new StringBuilder(str); + for (char c : character) { + escapeChar(buf, c); + } + return buf.toString(); + } + + public static void escapeChar(@NotNull final StringBuilder buf, final char character) { + int idx = 0; + while ((idx = indexOf(buf, character, idx)) >= 0) { + buf.insert(idx, "\\"); + idx += 2; + } + } + + @NotNull + @Contract(pure = true) + public static String escapeQuotes(@NotNull final String str) { + return escapeChar(str, '"'); + } + + public static void escapeQuotes(@NotNull final StringBuilder buf) { + escapeChar(buf, '"'); + } + + @NotNull + @Contract(pure = true) + public static String escapeSlashes(@NotNull final String str) { + return escapeChar(str, '/'); + } + + @NotNull + @Contract(pure = true) + public static String escapeBackSlashes(@NotNull final String str) { + return escapeChar(str, '\\'); + } + + public static void escapeSlashes(@NotNull final StringBuilder buf) { + escapeChar(buf, '/'); + } + + @NotNull + @Contract(pure = true) + public static String unescapeSlashes(@NotNull final String str) { + final StringBuilder buf = new StringBuilder(str.length()); + unescapeChar(buf, str, '/'); + return buf.toString(); + } + + @NotNull + @Contract(pure = true) + public static String unescapeBackSlashes(@NotNull final String str) { + final StringBuilder buf = new StringBuilder(str.length()); + unescapeChar(buf, str, '\\'); + return buf.toString(); + } + + @NotNull + @Contract(pure = true) + public static String unescapeChar(@NotNull final String str, char unescapeChar) { + final StringBuilder buf = new StringBuilder(str.length()); + unescapeChar(buf, str, unescapeChar); + return buf.toString(); + } + + private static void unescapeChar(@NotNull StringBuilder buf, @NotNull String str, char unescapeChar) { + final int length = str.length(); + final int last = length - 1; + for (int i = 0; i < length; i++) { + char ch = str.charAt(i); + if (ch == '\\' && i != last) { + //noinspection AssignmentToForLoopParameter + i++; + ch = str.charAt(i); + if (ch != unescapeChar) buf.append('\\'); + } + + buf.append(ch); + } + } + + public static void quote(@NotNull final StringBuilder builder) { + quote(builder, '\"'); + } + + public static void quote(@NotNull final StringBuilder builder, final char quotingChar) { + builder.insert(0, quotingChar); + builder.append(quotingChar); + } + + @NotNull + @Contract(pure = true) + public static String wrapWithDoubleQuote(@NotNull String str) { + return '\"' + str + "\""; + } + + private static final List REPLACES_REFS = Arrays.asList("<", ">", "&", "'", """); + private static final List REPLACES_DISP = Arrays.asList("<", ">", "&", "'", "\""); + + /** + * @deprecated Use {@link #unescapeXmlEntities(String)} instead + */ + @Contract(value = "null -> null; !null -> !null",pure = true) + @Deprecated + public static String unescapeXml(@Nullable final String text) { + return text == null ? null : unescapeXmlEntities(text); + } + + /** + * @deprecated Use {@link #escapeXmlEntities(String)} instead + */ + @Contract(value = "null -> null; !null -> !null",pure = true) + @Deprecated + public static String escapeXml(@Nullable final String text) { + return text == null ? null : escapeXmlEntities(text); + } + + /** + * @return {@code text} with some standard XML entities replaced with corresponding characters, e.g. '{@code <}' replaced with '<' + */ + @NotNull + @Contract(pure = true) + public static String unescapeXmlEntities(@NotNull String text) { + return replace(text, REPLACES_REFS, REPLACES_DISP); + } + + /** + * @return {@code text} with some characters replaced with standard XML entities, e.g. '<' replaced with '{@code <}' + */ + @NotNull + @Contract(pure = true) + public static String escapeXmlEntities(@NotNull String text) { + return replace(text, REPLACES_DISP, REPLACES_REFS); + } + + @NotNull + public static String removeHtmlTags(@NotNull String htmlString) { + return removeHtmlTags(htmlString, false); + } + + @NotNull + public static String removeHtmlTags(@NotNull String htmlString, boolean isRemoveStyleTag) { + if (isEmpty(htmlString)) { + return ""; + } + + final MyHtml2Text parser = isRemoveStyleTag ? new MyHtml2Text(true) : html2TextParser; + try { + parser.parse(new StringReader(htmlString)); + } + catch (IOException e) { + LOG.error(e); + } + return parser.getText(); + } + + private static final List MN_QUOTED = Arrays.asList("&&", "__"); + private static final List MN_CHARS = Arrays.asList("&", "_"); + + @NotNull + @Contract(pure = true) + public static String escapeMnemonics(@NotNull String text) { + return replace(text, MN_CHARS, MN_QUOTED); + } + + @NotNull + @Contract(pure = true) + public static String htmlEmphasize(@NotNull String text) { + return "" + escapeXmlEntities(text) + ""; + } + + + @NotNull + @Contract(pure = true) + public static String escapeToRegexp(@NotNull String text) { + final StringBuilder result = new StringBuilder(text.length()); + return escapeToRegexp(text, result).toString(); + } + + @NotNull + public static StringBuilder escapeToRegexp(@NotNull CharSequence text, @NotNull StringBuilder builder) { + for (int i = 0; i < text.length(); i++) { + final char c = text.charAt(i); + if (c == ' ' || Character.isLetter(c) || Character.isDigit(c) || c == '_') { + builder.append(c); + } + else if (c == '\n') { + builder.append("\\n"); + } + else if (c == '\r') { + builder.append("\\r"); + } + else { + builder.append('\\').append(c); + } + } + + return builder; + } + + @Contract(pure = true) + public static boolean isEscapedBackslash(@NotNull char[] chars, int startOffset, int backslashOffset) { + if (chars[backslashOffset] != '\\') { + return true; + } + boolean escaped = false; + for (int i = startOffset; i < backslashOffset; i++) { + if (chars[i] == '\\') { + escaped = !escaped; + } + else { + escaped = false; + } + } + return escaped; + } + + @Contract(pure = true) + public static boolean isEscapedBackslash(@NotNull CharSequence text, int startOffset, int backslashOffset) { + if (text.charAt(backslashOffset) != '\\') { + return true; + } + boolean escaped = false; + for (int i = startOffset; i < backslashOffset; i++) { + if (text.charAt(i) == '\\') { + escaped = !escaped; + } + else { + escaped = false; + } + } + return escaped; + } + + /** + * @deprecated Use {@link #replace(String, List, List)} + */ + @Deprecated + @NotNull + @Contract(pure = true) + public static String replace(@NotNull String text, @NotNull String[] from, @NotNull String[] to) { + return replace(text, Arrays.asList(from), Arrays.asList(to)); + } + + @NotNull + @Contract(pure = true) + public static String replace(@NotNull String text, @NotNull List from, @NotNull List to) { + assert from.size() == to.size(); + StringBuilder result = null; + replace: + for (int i = 0; i < text.length(); i++) { + for (int j = 0; j < from.size(); j += 1) { + String toReplace = from.get(j); + String replaceWith = to.get(j); + + final int len = toReplace.length(); + if (text.regionMatches(i, toReplace, 0, len)) { + if (result == null) { + result = new StringBuilder(text.length()); + result.append(text, 0, i); + } + result.append(replaceWith); + //noinspection AssignmentToForLoopParameter + i += len - 1; + continue replace; + } + } + + if (result != null) { + result.append(text.charAt(i)); + } + } + return result == null ? text : result.toString(); + } + + @NotNull + @Contract(pure = true) + public static String[] filterEmptyStrings(@NotNull String[] strings) { + int emptyCount = 0; + for (String string : strings) { + if (string == null || string.isEmpty()) emptyCount++; + } + if (emptyCount == 0) return strings; + + String[] result = ArrayUtil.newStringArray(strings.length - emptyCount); + int count = 0; + for (String string : strings) { + if (string == null || string.isEmpty()) continue; + result[count++] = string; + } + + return result; + } + + @Contract(pure = true) + public static int countNewLines(@NotNull CharSequence text) { + return countChars(text, '\n'); + } + + @Contract(pure = true) + public static int countChars(@NotNull CharSequence text, char c) { + return countChars(text, c, 0, false); + } + + @Contract(pure = true) + public static int countChars(@NotNull CharSequence text, char c, int offset, boolean stopAtOtherChar) { + return countChars(text, c, offset, text.length(), stopAtOtherChar); + } + + @Contract(pure = true) + public static int countChars(@NotNull CharSequence text, char c, int start, int end, boolean stopAtOtherChar) { + boolean forward = start <= end; + start = forward ? Math.max(0, start) : Math.min(text.length(), start); + end = forward ? Math.min(text.length(), end) : Math.max(0, end); + int count = 0; + for (int i = forward ? start : start - 1; forward == i < end; i += forward ? 1 : -1) { + if (text.charAt(i) == c) { + count++; + } + else if (stopAtOtherChar) { + break; + } + } + return count; + } + + @NotNull + @Contract(pure = true) + public static String capitalsOnly(@NotNull String s) { + StringBuilder b = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + if (Character.isUpperCase(s.charAt(i))) { + b.append(s.charAt(i)); + } + } + + return b.toString(); + } + + /** + * @param args Strings to join. + * @return {@code null} if any of given Strings is {@code null}. + */ + @Nullable + @Contract(pure = true) + public static String joinOrNull(@NotNull String... args) { + StringBuilder r = new StringBuilder(); + for (String arg : args) { + if (arg == null) return null; + r.append(arg); + } + return r.toString(); + } + + @Nullable + @Contract(pure = true) + public static String getPropertyName(@NotNull String methodName) { + if (methodName.startsWith("get")) { + return Introspector.decapitalize(methodName.substring(3)); + } + if (methodName.startsWith("is")) { + return Introspector.decapitalize(methodName.substring(2)); + } + if (methodName.startsWith("set")) { + return Introspector.decapitalize(methodName.substring(3)); + } + return null; + } + + @Contract(pure = true) + public static boolean isJavaIdentifierStart(char c) { + return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || Character.isJavaIdentifierStart(c); + } + + @Contract(pure = true) + public static boolean isJavaIdentifierPart(char c) { + return c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || Character.isJavaIdentifierPart(c); + } + + @Contract(pure = true) + public static boolean isJavaIdentifier(@NotNull String text) { + int len = text.length(); + if (len == 0) return false; + + if (!isJavaIdentifierStart(text.charAt(0))) return false; + + for (int i = 1; i < len; i++) { + if (!isJavaIdentifierPart(text.charAt(i))) return false; + } + + return true; + } + + /** + * Escape property name or key in property file. Unicode characters are escaped as well. + * + * @param input an input to escape + * @param isKey if true, the rules for key escaping are applied. The leading space is escaped in that case. + * @return an escaped string + */ + @NotNull + @Contract(pure = true) + public static String escapeProperty(@NotNull String input, final boolean isKey) { + final StringBuilder escaped = new StringBuilder(input.length()); + for (int i = 0; i < input.length(); i++) { + final char ch = input.charAt(i); + switch (ch) { + case ' ': + if (isKey && i == 0) { + // only the leading space has to be escaped + escaped.append('\\'); + } + escaped.append(' '); + break; + case '\t': + escaped.append("\\t"); + break; + case '\r': + escaped.append("\\r"); + break; + case '\n': + escaped.append("\\n"); + break; + case '\f': + escaped.append("\\f"); + break; + case '\\': + case '#': + case '!': + case ':': + case '=': + escaped.append('\\'); + escaped.append(ch); + break; + default: + if (20 < ch && ch < 0x7F) { + escaped.append(ch); + } + else { + escaped.append("\\u"); + escaped.append(Character.forDigit((ch >> 12) & 0xF, 16)); + escaped.append(Character.forDigit((ch >> 8) & 0xF, 16)); + escaped.append(Character.forDigit((ch >> 4) & 0xF, 16)); + escaped.append(Character.forDigit((ch) & 0xF, 16)); + } + break; + } + } + return escaped.toString(); + } + + @NotNull + @Contract(pure = true) + public static String getQualifiedName(@Nullable String packageName, @NotNull String className) { + if (packageName == null || packageName.isEmpty()) { + return className; + } + return packageName + '.' + className; + } + + @Contract(pure = true) + public static int compareVersionNumbers(@Nullable String v1, @Nullable String v2) { + // todo duplicates com.intellij.util.text.VersionComparatorUtil.compare + // todo please refactor next time you make changes here + if (v1 == null && v2 == null) { + return 0; + } + if (v1 == null) { + return -1; + } + if (v2 == null) { + return 1; + } - private static class MyHtml2Text extends HTMLEditorKit.ParserCallback { - @NotNull private final StringBuilder myBuffer = new StringBuilder(); - private final boolean myIsSkipStyleTag; + String[] part1 = v1.split("[._\\-]"); + String[] part2 = v2.split("[._\\-]"); - private boolean myIsStyleTagOpened; + int idx = 0; + for (; idx < part1.length && idx < part2.length; idx++) { + String p1 = part1[idx]; + String p2 = part2[idx]; - private MyHtml2Text(boolean isSkipStyleTag) { - myIsSkipStyleTag = isSkipStyleTag; - } + int cmp; + if (p1.matches("\\d+") && p2.matches("\\d+")) { + cmp = new Integer(p1).compareTo(new Integer(p2)); + } + else { + cmp = part1[idx].compareTo(part2[idx]); + } + if (cmp != 0) return cmp; + } - public void parse(@NotNull Reader in) throws IOException { - myBuffer.setLength(0); - new ParserDelegator().parse(in, this, Boolean.TRUE); + if (part1.length != part2.length) { + boolean left = part1.length > idx; + String[] parts = left ? part1 : part2; + + for (; idx < parts.length; idx++) { + String p = parts[idx]; + int cmp; + if (p.matches("\\d+")) { + cmp = new Integer(p).compareTo(0); + } + else { + cmp = 1; + } + if (cmp != 0) return left ? cmp : -cmp; + } + } + return 0; + } + + @Contract(pure = true) + public static int getOccurrenceCount(@NotNull String text, final char c) { + int res = 0; + int i = 0; + while (i < text.length()) { + i = text.indexOf(c, i); + if (i >= 0) { + res++; + i++; + } + else { + break; + } + } + return res; + } + + @Contract(pure = true) + public static int getOccurrenceCount(@NotNull String text, @NotNull String s) { + int res = 0; + int i = 0; + while (i < text.length()) { + i = text.indexOf(s, i); + if (i >= 0) { + res++; + i++; + } + else { + break; + } + } + return res; + } + + @Contract(pure = true) + public static int getIgnoreCaseOccurrenceCount(@NotNull String text, @NotNull String s) { + int res = 0; + int i = 0; + while (i < text.length()) { + i = indexOfIgnoreCase(text, s, i); + if (i >= 0) { + res++; + i++; + } + else { + break; + } + } + return res; } - @Override - public void handleText(@NotNull char[] text, int pos) { - if (!myIsStyleTagOpened) { - myBuffer.append(text); - } + @NotNull + @Contract(pure = true) + public static String fixVariableNameDerivedFromPropertyName(@NotNull String name) { + if (isEmptyOrSpaces(name)) return name; + char c = name.charAt(0); + if (isVowel(c)) { + return "an" + Character.toUpperCase(c) + name.substring(1); + } + return "a" + Character.toUpperCase(c) + name.substring(1); } - @Override - public void handleStartTag(@NotNull HTML.Tag tag, MutableAttributeSet set, int i) { - if (myIsSkipStyleTag && "style".equals(tag.toString())) { - myIsStyleTagOpened = true; - } - handleTag(tag); - } + @NotNull + @Contract(pure = true) + public static String sanitizeJavaIdentifier(@NotNull String name) { + final StringBuilder result = new StringBuilder(name.length()); + + for (int i = 0; i < name.length(); i++) { + final char ch = name.charAt(i); + if (Character.isJavaIdentifierPart(ch)) { + if (result.length() == 0 && !Character.isJavaIdentifierStart(ch)) { + result.append("_"); + } + result.append(ch); + } + } - @Override - public void handleEndTag(@NotNull HTML.Tag tag, int pos) { - if (myIsSkipStyleTag && "style".equals(tag.toString())) { - myIsStyleTagOpened = false; - } + return result.toString(); } - @Override - public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet set, int i) { - handleTag(tag); - } + public static void assertValidSeparators(@NotNull CharSequence s) { + char[] chars = CharArrayUtil.fromSequenceWithoutCopying(s); + int slashRIndex = -1; - private void handleTag(@NotNull HTML.Tag tag) { - if (tag.breaksFlow() && myBuffer.length() > 0) { - myBuffer.append(SystemProperties.getLineSeparator()); - } + if (chars != null) { + for (int i = 0, len = s.length(); i < len; ++i) { + if (chars[i] == '\r') { + slashRIndex = i; + break; + } + } + } + else { + for (int i = 0, len = s.length(); i < len; i++) { + if (s.charAt(i) == '\r') { + slashRIndex = i; + break; + } + } + } + + if (slashRIndex != -1) { + String context = + String.valueOf(last(s.subSequence(0, slashRIndex), 10, true)) + first(s.subSequence(slashRIndex, s.length()), 10, true); + context = escapeStringCharacters(context); + throw new AssertionError("Wrong line separators: '" + context + "' at offset " + slashRIndex); + } } @NotNull - public String getText() { - return myBuffer.toString(); + @Contract(pure = true) + public static String tail(@NotNull String s, final int idx) { + return idx >= s.length() ? "" : s.substring(idx); } - } - private static final MyHtml2Text html2TextParser = new MyHtml2Text(false); + /** + * Splits string by lines. + * + * @param string String to split + * @return array of strings + */ + @NotNull + @Contract(pure = true) + public static String[] splitByLines(@NotNull String string) { + return splitByLines(string, true); + } + + /** + * Splits string by lines. If several line separators are in a row corresponding empty lines + * are also added to result if {@code excludeEmptyStrings} is {@code false}. + * + * @param string String to split + * @return array of strings + */ + @NotNull + @Contract(pure = true) + public static String[] splitByLines(@NotNull String string, boolean excludeEmptyStrings) { + return (excludeEmptyStrings ? EOL_SPLIT_PATTERN : EOL_SPLIT_PATTERN_WITH_EMPTY).split(string); + } - public static final NotNullFunction QUOTER = new NotNullFunction() { - @Override @NotNull - public String fun(String s) { - return "\"" + s + "\""; + @Contract(pure = true) + public static String[] splitByLinesDontTrim(@NotNull String string) { + return EOL_SPLIT_DONT_TRIM_PATTERN.split(string); + } + + /** + * Splits string by lines, keeping all line separators at the line ends and in the empty lines. + *
E.g. splitting text + *
+ * foo\r\n
+ * \n
+ * bar\n
+ * \r\n
+ * baz\r
+ * \r
+ *
+ * will return the following array: foo\r\n, \n, bar\n, \r\n, baz\r, \r + * + */ + @NotNull + @Contract(pure = true) + public static String[] splitByLinesKeepSeparators(@NotNull String string) { + return EOL_SPLIT_KEEP_SEPARATORS.split(string); } - }; - public static final NotNullFunction SINGLE_QUOTER = new NotNullFunction() { - @Override @NotNull - public String fun(String s) { - return "'" + s + "'"; + @Contract(pure = true) + public static List> getWordsWithOffset(@NotNull String s) { + List> res = ContainerUtil.newArrayList(); + s += " "; + StringBuilder name = new StringBuilder(); + int startInd = -1; + for (int i = 0; i < s.length(); i++) { + if (Character.isWhitespace(s.charAt(i))) { + if (name.length() > 0) { + res.add(Pair.create(name.toString(), startInd)); + name.setLength(0); + startInd = -1; + } + } + else { + if (startInd == -1) { + startInd = i; + } + name.append(s.charAt(i)); + } + } + return res; + } + + @Contract(pure = true) + public static int naturalCompare(@Nullable String string1, @Nullable String string2) { + return NaturalComparator.INSTANCE.compare(string1, string2); } - }; - @NotNull - @Contract(pure = true) - public static List getWordsInStringLongestFirst(@NotNull String find) { - List words = getWordsIn(find); - // hope long words are rare - Collections.sort(words, new Comparator() { - @Override - public int compare(@NotNull final String o1, @NotNull final String o2) { - return o2.length() - o1.length(); - } - }); - return words; - } + @Contract(pure = true) + public static boolean isDecimalDigit(char c) { + return c >= '0' && c <= '9'; + } - @NotNull - @Contract(pure = true) - public static String escapePattern(@NotNull final String text) { - return replace(replace(text, "'", "''"), "{", "'{'"); - } + @Contract("null -> false") + public static boolean isNotNegativeNumber(@Nullable CharSequence s) { + if (s == null) { + return false; + } + for (int i = 0; i < s.length(); i++) { + if (!isDecimalDigit(s.charAt(i))) { + return false; + } + } + return true; + } - @NotNull - @Contract(pure = true) - public static Function createToStringFunction(@SuppressWarnings("unused") @NotNull Class cls) { - return new Function() { - @Override - public String fun(@NotNull T o) { - return o.toString(); - } - }; - } + @Contract(pure = true) + public static int compare(@Nullable String s1, @Nullable String s2, boolean ignoreCase) { + //noinspection StringEquality + if (s1 == s2) return 0; + if (s1 == null) return -1; + if (s2 == null) return 1; + return ignoreCase ? s1.compareToIgnoreCase(s2) : s1.compareTo(s2); + } - @NotNull - public static final Function TRIMMER = new Function() { - @Nullable - @Override - public String fun(@Nullable String s) { - return trim(s); - } - }; - - // Unlike String.replace(CharSequence,CharSequence) does not allocate intermediate objects on non-match - // TODO revise when JDK9 arrives - its String.replace(CharSequence, CharSequence) is more optimized - @NotNull - @Contract(pure = true) - public static String replace(@NotNull String text, @NotNull String oldS, @NotNull String newS) { - return replace(text, oldS, newS, false); - } - - @NotNull - @Contract(pure = true) - public static String replaceIgnoreCase(@NotNull String text, @NotNull String oldS, @NotNull String newS) { - return replace(text, oldS, newS, true); - } - - /** - * @deprecated Use {@link String#replace(char,char)} instead - */ - @NotNull - @Contract(pure = true) - @Deprecated - public static String replaceChar(@NotNull String buffer, char oldChar, char newChar) { - return buffer.replace(oldChar, newChar); - } - - @Contract(pure = true) - public static String replace(@NotNull final String text, @NotNull final String oldS, @NotNull final String newS, final boolean ignoreCase) { - if (text.length() < oldS.length()) return text; - - StringBuilder newText = null; - int i = 0; - - while (i < text.length()) { - final int index = ignoreCase? indexOfIgnoreCase(text, oldS, i) : text.indexOf(oldS, i); - if (index < 0) { - if (i == 0) { - return text; - } - - newText.append(text, i, text.length()); - break; - } - else { - if (newText == null) { - if (text.length() == oldS.length()) { - return newS; - } - newText = new StringBuilder(text.length() - i); - } - - newText.append(text, i, index); - newText.append(newS); - i = index + oldS.length(); - } - } - return newText != null ? newText.toString() : ""; - } - - @Contract(pure = true) - public static int indexOfIgnoreCase(@NotNull String where, @NotNull String what, int fromIndex) { - return indexOfIgnoreCase((CharSequence)where, what, fromIndex); - } - - /** - * Implementation copied from {@link String#indexOf(String, int)} except character comparisons made case insensitive - */ - @Contract(pure = true) - public static int indexOfIgnoreCase(@NotNull CharSequence where, @NotNull CharSequence what, int fromIndex) { - int targetCount = what.length(); - int sourceCount = where.length(); - - if (fromIndex >= sourceCount) { - return targetCount == 0 ? sourceCount : -1; - } - - if (fromIndex < 0) { - fromIndex = 0; - } - - if (targetCount == 0) { - return fromIndex; - } - - char first = what.charAt(0); - int max = sourceCount - targetCount; - - for (int i = fromIndex; i <= max; i++) { - /* Look for first character. */ - if (!charsEqualIgnoreCase(where.charAt(i), first)) { - //noinspection StatementWithEmptyBody,AssignmentToForLoopParameter - while (++i <= max && !charsEqualIgnoreCase(where.charAt(i), first)) ; - } - - /* Found first character, now look at the rest of v2 */ - if (i <= max) { - int j = i + 1; - int end = j + targetCount - 1; - //noinspection StatementWithEmptyBody - for (int k = 1; j < end && charsEqualIgnoreCase(where.charAt(j), what.charAt(k)); j++, k++) ; - - if (j == end) { - /* Found whole string. */ - return i; - } - } - } - - return -1; - } - - @Contract(pure = true) - public static int indexOfIgnoreCase(@NotNull String where, char what, int fromIndex) { - int sourceCount = where.length(); - for (int i = Math.max(fromIndex, 0); i < sourceCount; i++) { - if (charsEqualIgnoreCase(where.charAt(i), what)) { - return i; - } + @Contract(pure = true) + public static int comparePairs(@Nullable String s1, @Nullable String t1, @Nullable String s2, @Nullable String t2, boolean ignoreCase) { + final int compare = compare(s1, s2, ignoreCase); + return compare != 0 ? compare : compare(t1, t2, ignoreCase); + } + + @Contract(pure = true) + public static int hashCode(@NotNull CharSequence s) { + return stringHashCode(s); } - return -1; - } + @Contract(pure = true) + public static boolean equals(@Nullable CharSequence s1, @Nullable CharSequence s2) { + if (s1 == null ^ s2 == null) { + return false; + } - @Contract(pure = true) - public static int lastIndexOfIgnoreCase(@NotNull String where, char what, int fromIndex) { - for (int i = Math.min(fromIndex, where.length() - 1); i >= 0; i--) { - if (charsEqualIgnoreCase(where.charAt(i), what)) { - return i; - } - } - - return -1; - } - - @Contract(pure = true) - public static boolean containsIgnoreCase(@NotNull String where, @NotNull String what) { - return indexOfIgnoreCase(where, what, 0) >= 0; - } - - @Contract(pure = true) - public static boolean endsWithIgnoreCase(@NotNull String str, @NotNull String suffix) { - return StringUtilRt.endsWithIgnoreCase(str, suffix); - } - - @Contract(pure = true) - public static boolean startsWithIgnoreCase(@NotNull String str, @NotNull String prefix) { - return StringUtilRt.startsWithIgnoreCase(str, prefix); - } - - @Contract(pure = true) - @NotNull - public static String stripHtml(@NotNull String html, boolean convertBreaks) { - if (convertBreaks) { - html = html.replaceAll("
", "\n\n"); - } - - return html.replaceAll("<(.|\n)*?>", ""); - } - - @Contract(value = "null -> null; !null -> !null", pure = true) - public static String toLowerCase(@Nullable final String str) { - return str == null ? null : str.toLowerCase(); - } - - @NotNull - @Contract(pure = true) - public static String getPackageName(@NotNull String fqName) { - return getPackageName(fqName, '.'); - } - - /** - * Given a fqName returns the package name for the type or the containing type. - *

- *

    - *
  • {@code java.lang.String} -> {@code java.lang}
  • - *
  • {@code java.util.Map.Entry} -> {@code java.util.Map}
  • - *
- * - * @param fqName a fully qualified type name. Not supposed to contain any type arguments - * @param separator the separator to use. Typically '.' - * @return the package name of the type or the declarator of the type. The empty string if the given fqName is unqualified - */ - @NotNull - @Contract(pure = true) - public static String getPackageName(@NotNull String fqName, char separator) { - int lastPointIdx = fqName.lastIndexOf(separator); - if (lastPointIdx >= 0) { - return fqName.substring(0, lastPointIdx); - } - return ""; - } - - @Contract(pure = true) - public static int getLineBreakCount(@NotNull CharSequence text) { - int count = 0; - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - if (c == '\n') { - count++; - } - else if (c == '\r') { - if (i + 1 < text.length() && text.charAt(i + 1) == '\n') { - //noinspection AssignmentToForLoopParameter - i++; - } - count++; - } - } - return count; - } - - @Contract(pure = true) - public static boolean containsLineBreak(@NotNull CharSequence text) { - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - if (isLineBreak(c)) return true; - } - return false; - } - - @Contract(pure = true) - public static boolean isLineBreak(char c) { - return c == '\n' || c == '\r'; - } - - @NotNull - @Contract(pure = true) - public static String escapeLineBreak(@NotNull String text) { - StringBuilder buffer = new StringBuilder(text.length()); - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - switch (c) { - case '\n': - buffer.append("\\n"); - break; - case '\r': - buffer.append("\\r"); - break; - default: - buffer.append(c); - } - } - return buffer.toString(); - } - - @Contract(pure = true) - public static boolean endsWithLineBreak(@NotNull CharSequence text) { - int len = text.length(); - return len > 0 && isLineBreak(text.charAt(len - 1)); - } - - @Contract(pure = true) - public static int lineColToOffset(@NotNull CharSequence text, int line, int col) { - int curLine = 0; - int offset = 0; - while (line != curLine) { - if (offset == text.length()) return -1; - char c = text.charAt(offset); - if (c == '\n') { - curLine++; - } - else if (c == '\r') { - curLine++; - if (offset < text.length() - 1 && text.charAt(offset + 1) == '\n') { - offset++; - } - } - offset++; - } - return offset + col; - } - - @Contract(pure = true) - public static int offsetToLineNumber(@NotNull CharSequence text, int offset) { - LineColumn lineColumn = offsetToLineColumn(text, offset); - return lineColumn != null ? lineColumn.line : -1; - } - - @Contract(pure = true) - public static LineColumn offsetToLineColumn(@NotNull CharSequence text, int offset) { - int curLine = 0; - int curLineStart = 0; - int curOffset = 0; - while (curOffset < offset) { - if (curOffset == text.length()) return null; - char c = text.charAt(curOffset); - if (c == '\n') { - curLine++; - curLineStart = curOffset + 1; - } - else if (c == '\r') { - curLine++; - if (curOffset < text.length() - 1 && text.charAt(curOffset + 1) == '\n') { - curOffset++; - } - curLineStart = curOffset + 1; - } - curOffset++; - } - - return LineColumn.of(curLine, offset - curLineStart); - } - - /** - * Classic dynamic programming algorithm for string differences. - */ - @Contract(pure = true) - public static int difference(@NotNull String s1, @NotNull String s2) { - int[][] a = new int[s1.length()][s2.length()]; - - for (int i = 0; i < s1.length(); i++) { - a[i][0] = i; - } - - for (int j = 0; j < s2.length(); j++) { - a[0][j] = j; - } - - for (int i = 1; i < s1.length(); i++) { - for (int j = 1; j < s2.length(); j++) { - - a[i][j] = Math.min(Math.min(a[i - 1][j - 1] + (s1.charAt(i) == s2.charAt(j) ? 0 : 1), a[i - 1][j] + 1), a[i][j - 1] + 1); - } - } - - return a[s1.length() - 1][s2.length() - 1]; - } - - @NotNull - @Contract(pure = true) - public static String wordsToBeginFromUpperCase(@NotNull String s) { - return fixCapitalization(s, ourPrepositions, true); - } - - @NotNull - @Contract(pure = true) - public static String wordsToBeginFromLowerCase(@NotNull String s) { - return fixCapitalization(s, ourPrepositions, false); - } - - @NotNull - @Contract(pure = true) - public static String toTitleCase(@NotNull String s) { - return fixCapitalization(s, ArrayUtil.EMPTY_STRING_ARRAY, true); - } - - @NotNull - private static String fixCapitalization(@NotNull String s, @NotNull String[] prepositions, boolean title) { - StringBuilder buffer = null; - for (int i = 0; i < s.length(); i++) { - char prevChar = i == 0 ? ' ' : s.charAt(i - 1); - char currChar = s.charAt(i); - if (!Character.isLetterOrDigit(prevChar) && prevChar != '\'') { - if (Character.isLetterOrDigit(currChar)) { - if (title || Character.isUpperCase(currChar)) { - int j = i; - for (; j < s.length(); j++) { - if (!Character.isLetterOrDigit(s.charAt(j))) { - break; - } - } - if (!title && j > i + 1 && !Character.isLowerCase(s.charAt(i + 1))) { - // filter out abbreviations like I18n, SQL and CSS - continue; - } - if (!isPreposition(s, i, j - 1, prepositions)) { - if (buffer == null) { - buffer = new StringBuilder(s); - } - buffer.setCharAt(i, title ? toUpperCase(currChar) : toLowerCase(currChar)); - } - } - } - } - } - return buffer == null ? s : buffer.toString(); - } - - private static final String[] ourPrepositions = { - "a", "an", "and", "as", "at", "but", "by", "down", "for", "from", "if", "in", "into", "not", "of", "on", "onto", "or", "out", "over", - "per", "nor", "the", "to", "up", "upon", "via", "with" - }; - - @Contract(pure = true) - public static boolean isPreposition(@NotNull String s, int firstChar, int lastChar) { - return isPreposition(s, firstChar, lastChar, ourPrepositions); - } - - @Contract(pure = true) - public static boolean isPreposition(@NotNull String s, int firstChar, int lastChar, @NotNull String[] prepositions) { - for (String preposition : prepositions) { - boolean found = false; - if (lastChar - firstChar + 1 == preposition.length()) { - found = true; - for (int j = 0; j < preposition.length(); j++) { - if (toLowerCase(s.charAt(firstChar + j)) != preposition.charAt(j)) { - found = false; - } - } - } - if (found) { + if (s1 == null) { + return true; + } + + if (s1.length() != s2.length()) { + return false; + } + for (int i = 0; i < s1.length(); i++) { + if (s1.charAt(i) != s2.charAt(i)) { + return false; + } + } return true; - } - } - return false; - } - - @NotNull - @Contract(pure = true) - public static NotNullFunction escaper(final boolean escapeSlash, @Nullable final String additionalChars) { - return new NotNullFunction() { - @NotNull - @Override - public String fun(@NotNull String dom) { - final StringBuilder builder = new StringBuilder(dom.length()); - escapeStringCharacters(dom.length(), dom, additionalChars, escapeSlash, builder); - return builder.toString(); - } - }; - } - - - public static void escapeStringCharacters(int length, @NotNull String str, @NotNull StringBuilder buffer) { - escapeStringCharacters(length, str, "\"", buffer); - } - - @NotNull - public static StringBuilder escapeStringCharacters(int length, - @NotNull String str, - @Nullable String additionalChars, - @NotNull StringBuilder buffer) { - return escapeStringCharacters(length, str, additionalChars, true, buffer); - } - - @NotNull - public static StringBuilder escapeStringCharacters(int length, - @NotNull String str, - @Nullable String additionalChars, - boolean escapeSlash, - @NotNull StringBuilder buffer) { - return escapeStringCharacters(length, str, additionalChars, escapeSlash, true, buffer); - } - - @NotNull - public static StringBuilder escapeStringCharacters(int length, - @NotNull String str, - @Nullable String additionalChars, - boolean escapeSlash, - boolean escapeUnicode, - @NotNull StringBuilder buffer) { - char prev = 0; - for (int idx = 0; idx < length; idx++) { - char ch = str.charAt(idx); - switch (ch) { - case '\b': - buffer.append("\\b"); - break; - - case '\t': - buffer.append("\\t"); - break; - - case '\n': - buffer.append("\\n"); - break; - - case '\f': - buffer.append("\\f"); - break; - - case '\r': - buffer.append("\\r"); - break; - - default: - if (escapeSlash && ch == '\\') { - buffer.append("\\\\"); - } - else if (additionalChars != null && additionalChars.indexOf(ch) > -1 && (escapeSlash || prev != '\\')) { - buffer.append("\\").append(ch); - } - else if (escapeUnicode && !isPrintableUnicode(ch)) { - CharSequence hexCode = toUpperCase(Integer.toHexString(ch)); - buffer.append("\\u"); - int paddingCount = 4 - hexCode.length(); - while (paddingCount-- > 0) { - buffer.append(0); - } - buffer.append(hexCode); - } - else { - buffer.append(ch); - } - } - prev = ch; - } - return buffer; - } - - @Contract(pure = true) - public static boolean isPrintableUnicode(char c) { - int t = Character.getType(c); - return t != Character.UNASSIGNED && t != Character.LINE_SEPARATOR && t != Character.PARAGRAPH_SEPARATOR && - t != Character.CONTROL && t != Character.FORMAT && t != Character.PRIVATE_USE && t != Character.SURROGATE; - } - - @NotNull - @Contract(pure = true) - public static String escapeStringCharacters(@NotNull String s) { - StringBuilder buffer = new StringBuilder(s.length()); - escapeStringCharacters(s.length(), s, "\"", buffer); - return buffer.toString(); - } - - @NotNull - @Contract(pure = true) - public static String escapeCharCharacters(@NotNull String s) { - StringBuilder buffer = new StringBuilder(s.length()); - escapeStringCharacters(s.length(), s, "\'", buffer); - return buffer.toString(); - } - - @NotNull - @Contract(pure = true) - public static String unescapeStringCharacters(@NotNull String s) { - StringBuilder buffer = new StringBuilder(s.length()); - unescapeStringCharacters(s.length(), s, buffer); - return buffer.toString(); - } - - private static boolean isQuoteAt(@NotNull String s, int ind) { - char ch = s.charAt(ind); - return ch == '\'' || ch == '\"'; - } - - @Contract(pure = true) - public static boolean isQuotedString(@NotNull String s) { - return StringUtilRt.isQuotedString(s); - } - - @NotNull - @Contract(pure = true) - public static String unquoteString(@NotNull String s) { - return StringUtilRt.unquoteString(s); - } - - private static void unescapeStringCharacters(int length, @NotNull String s, @NotNull StringBuilder buffer) { - boolean escaped = false; - for (int idx = 0; idx < length; idx++) { - char ch = s.charAt(idx); - if (!escaped) { - if (ch == '\\') { - escaped = true; + } + + @Contract(pure = true) + public static boolean equalsIgnoreCase(@Nullable CharSequence s1, @Nullable CharSequence s2) { + if (s1 == null ^ s2 == null) { + return false; } - else { - buffer.append(ch); - } - } - else { - int octalEscapeMaxLength = 2; - switch (ch) { - case 'n': - buffer.append('\n'); - break; - - case 'r': - buffer.append('\r'); - break; - - case 'b': - buffer.append('\b'); - break; - - case 't': - buffer.append('\t'); - break; - - case 'f': - buffer.append('\f'); - break; - - case '\'': - buffer.append('\''); - break; - - case '\"': - buffer.append('\"'); - break; - - case '\\': - buffer.append('\\'); - break; - - case 'u': - if (idx + 4 < length) { - try { - int code = Integer.parseInt(s.substring(idx + 1, idx + 5), 16); - //noinspection AssignmentToForLoopParameter - idx += 4; - buffer.append((char)code); - } - catch (NumberFormatException e) { - buffer.append("\\u"); - } + + if (s1 == null) { + return true; + } + + if (s1.length() != s2.length()) { + return false; + } + for (int i = 0; i < s1.length(); i++) { + if (!charsEqualIgnoreCase(s1.charAt(i), s2.charAt(i))) { + return false; } - else { - buffer.append("\\u"); + } + return true; + } + + @Contract(pure = true) + public static boolean equalsIgnoreWhitespaces(@Nullable CharSequence s1, @Nullable CharSequence s2) { + if (s1 == null ^ s2 == null) { + return false; + } + + if (s1 == null) { + return true; + } + + int len1 = s1.length(); + int len2 = s2.length(); + + int index1 = 0; + int index2 = 0; + while (index1 < len1 && index2 < len2) { + if (s1.charAt(index1) == s2.charAt(index2)) { + index1++; + index2++; + continue; } - break; - case '0': - case '1': - case '2': - case '3': - octalEscapeMaxLength = 3; - //noinspection fallthrough - case '4': - case '5': - case '6': - case '7': - int escapeEnd = idx + 1; - while (escapeEnd < length && escapeEnd < idx + octalEscapeMaxLength && isOctalDigit(s.charAt(escapeEnd))) escapeEnd++; - try { - buffer.append((char)Integer.parseInt(s.substring(idx, escapeEnd), 8)); + boolean skipped = false; + while (index1 != len1 && isWhiteSpace(s1.charAt(index1))) { + skipped = true; + index1++; } - catch (NumberFormatException e) { - throw new RuntimeException("Couldn't parse " + s.substring(idx, escapeEnd), e); // shouldn't happen + while (index2 != len2 && isWhiteSpace(s2.charAt(index2))) { + skipped = true; + index2++; } - //noinspection AssignmentToForLoopParameter - idx = escapeEnd - 1; - break; - default: - buffer.append(ch); - break; + if (!skipped) return false; } - escaped = false; - } - } - if (escaped) buffer.append('\\'); - } + for (; index1 != len1; index1++) { + if (!isWhiteSpace(s1.charAt(index1))) return false; + } + for (; index2 != len2; index2++) { + if (!isWhiteSpace(s2.charAt(index2))) return false; + } -// @NotNull -// @Contract(pure = true) -// public static String pluralize(@NotNull String word) { -// String plural = Pluralizer.PLURALIZER.plural(word); -// if (plural != null) return plural; -// if (word.endsWith("s")) return Pluralizer.restoreCase(word, word + "es"); -// return Pluralizer.restoreCase(word, word + "s"); -// } + return true; + } - @NotNull - @Contract(pure = true) - public static String capitalizeWords(@NotNull String text, - boolean allWords) { - return capitalizeWords(text, " \t\n\r\f", allWords, false); - } - - @NotNull - @Contract(pure = true) - public static String capitalizeWords(@NotNull String text, - @NotNull String tokenizerDelim, - boolean allWords, - boolean leaveOriginalDelims) { - final StringTokenizer tokenizer = new StringTokenizer(text, tokenizerDelim, leaveOriginalDelims); - final StringBuilder out = new StringBuilder(text.length()); - boolean toCapitalize = true; - while (tokenizer.hasMoreTokens()) { - final String word = tokenizer.nextToken(); - if (!leaveOriginalDelims && out.length() > 0) { - out.append(' '); - } - out.append(toCapitalize ? capitalize(word) : word); - if (!allWords) { - toCapitalize = false; - } - } - return out.toString(); - } - - @NotNull - @Contract(pure = true) - public static String decapitalize(@NotNull String s) { - return Introspector.decapitalize(s); - } - - @Contract(pure = true) - public static boolean isVowel(char c) { - return VOWELS.indexOf(c) >= 0; - } - - /** - * Capitalize the first letter of the sentence. - */ - @NotNull - @Contract(pure = true) - public static String capitalize(@NotNull String s) { - if (s.isEmpty()) return s; - if (s.length() == 1) return toUpperCase(s).toString(); - - // Optimization - if (Character.isUpperCase(s.charAt(0))) return s; - return toUpperCase(s.charAt(0)) + s.substring(1); - } - - @Contract(value = "null -> false", pure = true) - public static boolean isCapitalized(@Nullable String s) { - return s != null && !s.isEmpty() && Character.isUpperCase(s.charAt(0)); - } - - @NotNull - @Contract(pure = true) - public static String capitalizeWithJavaBeanConvention(@NotNull String s) { - if (s.length() > 1 && Character.isUpperCase(s.charAt(1))) { - return s; - } - return capitalize(s); - } - - @Contract(pure = true) - public static int stringHashCode(@NotNull CharSequence chars) { - if (chars instanceof String || chars instanceof CharSequenceWithStringHash) { - // we know for sure these classes have conformant (and maybe faster) hashCode() - return chars.hashCode(); - } - - return stringHashCode(chars, 0, chars.length()); - } - - @Contract(pure = true) - public static int stringHashCode(@NotNull CharSequence chars, int from, int to) { - int h = 0; - for (int off = from; off < to; off++) { - h = 31 * h + chars.charAt(off); - } - return h; - } - - @Contract(pure = true) - public static int stringHashCode(char[] chars, int from, int to) { - int h = 0; - for (int off = from; off < to; off++) { - h = 31 * h + chars[off]; - } - return h; - } - - @Contract(pure = true) - public static int stringHashCodeInsensitive(@NotNull char[] chars, int from, int to) { - int h = 0; - for (int off = from; off < to; off++) { - h = 31 * h + toLowerCase(chars[off]); - } - return h; - } - - @Contract(pure = true) - public static int stringHashCodeInsensitive(@NotNull CharSequence chars, int from, int to) { - int h = 0; - for (int off = from; off < to; off++) { - h = 31 * h + toLowerCase(chars.charAt(off)); - } - return h; - } - - @Contract(pure = true) - public static int stringHashCodeInsensitive(@NotNull CharSequence chars) { - return stringHashCodeInsensitive(chars, 0, chars.length()); - } - - @Contract(pure = true) - public static int stringHashCodeIgnoreWhitespaces(@NotNull char[] chars, int from, int to) { - int h = 0; - for (int off = from; off < to; off++) { - char c = chars[off]; - if (!isWhiteSpace(c)) { - h = 31 * h + c; - } - } - return h; - } - - @Contract(pure = true) - public static int stringHashCodeIgnoreWhitespaces(@NotNull CharSequence chars, int from, int to) { - int h = 0; - for (int off = from; off < to; off++) { - char c = chars.charAt(off); - if (!isWhiteSpace(c)) { - h = 31 * h + c; - } - } - return h; - } - - @Contract(pure = true) - public static int stringHashCodeIgnoreWhitespaces(@NotNull CharSequence chars) { - return stringHashCodeIgnoreWhitespaces(chars, 0, chars.length()); - } - - /** - * Equivalent to string.startsWith(prefixes[0] + prefixes[1] + ...) but avoids creating an object for concatenation. - */ - @Contract(pure = true) - public static boolean startsWithConcatenation(@NotNull String string, @NotNull String... prefixes) { - int offset = 0; - for (String prefix : prefixes) { - int prefixLen = prefix.length(); - if (!string.regionMatches(offset, prefix, 0, prefixLen)) { - return false; - } - offset += prefixLen; - } - return true; - } - - @Contract(value = "null -> null; !null -> !null", pure = true) - public static String trim(@Nullable String s) { - return s == null ? null : s.trim(); - } - - @NotNull - @Contract(pure = true) - public static String trimEnd(@NotNull String s, @NotNull String suffix) { - return trimEnd(s, suffix, false); - } - - @NotNull - @Contract(pure = true) - public static String trimEnd(@NotNull String s, @NotNull String suffix, boolean ignoreCase) { - boolean endsWith = ignoreCase ? endsWithIgnoreCase(s, suffix) : s.endsWith(suffix); - if (endsWith) { - return s.substring(0, s.length() - suffix.length()); - } - return s; - } - - @NotNull - @Contract(pure = true) - public static String trimEnd(@NotNull String s, char suffix) { - if (endsWithChar(s, suffix)) { - return s.substring(0, s.length() - 1); - } - return s; - } - - @NotNull - @Contract(pure = true) - public static String trimLog(@NotNull final String text, final int limit) { - if (limit > 5 && text.length() > limit) { - return text.substring(0, limit - 5) + " ...\n"; - } - return text; - } - - @NotNull - @Contract(pure = true) - public static String trimLeading(@NotNull String string) { - return trimLeading((CharSequence)string).toString(); - } - @NotNull - @Contract(pure = true) - public static CharSequence trimLeading(@NotNull CharSequence string) { - int index = 0; - while (index < string.length() && Character.isWhitespace(string.charAt(index))) index++; - return string.subSequence(index, string.length()); - } - - @NotNull - @Contract(pure = true) - public static String trimLeading(@NotNull String string, char symbol) { - int index = 0; - while (index < string.length() && string.charAt(index) == symbol) index++; - return string.substring(index); - } - - @NotNull - public static StringBuilder trimLeading(@NotNull StringBuilder builder, char symbol) { - int index = 0; - while (index < builder.length() && builder.charAt(index) == symbol) index++; - if (index > 0) builder.delete(0, index); - return builder; - } - - @NotNull - @Contract(pure = true) - public static String trimTrailing(@NotNull String string) { - return trimTrailing((CharSequence)string).toString(); - } - - @NotNull - @Contract(pure = true) - public static CharSequence trimTrailing(@NotNull CharSequence string) { - int index = string.length() - 1; - while (index >= 0 && Character.isWhitespace(string.charAt(index))) index--; - return string.subSequence(0, index + 1); - } - - @NotNull - @Contract(pure = true) - public static String trimTrailing(@NotNull String string, char symbol) { - int index = string.length() - 1; - while (index >= 0 && string.charAt(index) == symbol) index--; - return string.substring(0, index + 1); - } - - @NotNull - public static StringBuilder trimTrailing(@NotNull StringBuilder builder, char symbol) { - int index = builder.length() - 1; - while (index >= 0 && builder.charAt(index) == symbol) index--; - builder.setLength(index + 1); - return builder; - } - - @Contract(pure = true) - public static boolean startsWithChar(@Nullable CharSequence s, char prefix) { - return s != null && s.length() != 0 && s.charAt(0) == prefix; - } - - @Contract(pure = true) - public static boolean endsWithChar(@Nullable CharSequence s, char suffix) { - return StringUtilRt.endsWithChar(s, suffix); - } - - @NotNull - @Contract(pure = true) - public static String trimStart(@NotNull String s, @NotNull String prefix) { - if (s.startsWith(prefix)) { - return s.substring(prefix.length()); - } - return s; - } - - @NotNull - @Contract(pure = true) - public static String trimExtensions(@NotNull String name) { - int index = name.indexOf('.'); - return index < 0 ? name : name.substring(0, index); - } + @Contract(pure = true) + public static boolean equalsTrimWhitespaces(@NotNull CharSequence s1, @NotNull CharSequence s2) { + int start1 = 0; + int end1 = s1.length(); + int end2 = s2.length(); -// @NotNull -// @Contract(pure = true) -// public static String pluralize(@NotNull String base, int count) { -// if (count == 1) return base; -// return pluralize(base); -// } + while (start1 < end1) { + char c = s1.charAt(start1); + if (!isWhiteSpace(c)) break; + start1++; + } - public static void repeatSymbol(@NotNull Appendable buffer, char symbol, int times) { - assert times >= 0 : times; - try { - for (int i = 0; i < times; i++) { - buffer.append(symbol); - } - } - catch (IOException e) { - LOG.error(e); - } - } - - @Contract(pure = true) - public static String defaultIfEmpty(@Nullable String value, String defaultValue) { - return isEmpty(value) ? defaultValue : value; - } - - @Contract(value = "null -> false", pure = true) - public static boolean isNotEmpty(@Nullable String s) { - return !isEmpty(s); - } - - @Contract(value = "null -> true", pure = true) - public static boolean isEmpty(@Nullable String s) { - return s == null || s.isEmpty(); - } - - @Contract(value = "null -> true",pure = true) - public static boolean isEmpty(@Nullable CharSequence cs) { - return StringUtilRt.isEmpty(cs); - } - - @Contract(pure = true) - public static int length(@Nullable CharSequence cs) { - return cs == null ? 0 : cs.length(); - } - - @NotNull - @Contract(pure = true) - public static String notNullize(@Nullable String s) { - return StringUtilRt.notNullize(s); - } - - @NotNull - @Contract(pure = true) - public static String notNullize(@Nullable String s, @NotNull String defaultValue) { - return StringUtilRt.notNullize(s, defaultValue); - } - - @Nullable - @Contract(pure = true) - public static String nullize(@Nullable String s) { - return nullize(s, false); - } - - @Nullable - @Contract(pure = true) - public static String nullize(@Nullable String s, boolean nullizeSpaces) { - boolean empty = nullizeSpaces ? isEmptyOrSpaces(s) : isEmpty(s); - return empty ? null : s; - } - - @Contract(value = "null -> true",pure = true) - // we need to keep this method to preserve backward compatibility - public static boolean isEmptyOrSpaces(@Nullable String s) { - return isEmptyOrSpaces((CharSequence)s); - } - - @Contract(value = "null -> true", pure = true) - public static boolean isEmptyOrSpaces(@Nullable CharSequence s) { - return StringUtilRt.isEmptyOrSpaces(s); - } - - /** - * Allows to answer if given symbol is white space, tabulation or line feed. - * - * @param c symbol to check - * @return {@code true} if given symbol is white space, tabulation or line feed; {@code false} otherwise - */ - @Contract(pure = true) - public static boolean isWhiteSpace(char c) { - return c == '\n' || c == '\t' || c == ' '; - } - - @NotNull - @Contract(pure = true) - public static String getThrowableText(@NotNull Throwable aThrowable) { - return ExceptionUtil.getThrowableText(aThrowable); - } - - @NotNull - @Contract(pure = true) - public static String repeatSymbol(final char aChar, final int count) { - char[] buffer = new char[count]; - Arrays.fill(buffer, aChar); - return StringFactory.createShared(buffer); - } - - @NotNull - @Contract(pure = true) - public static String repeat(@NotNull String s, int count) { - assert count >= 0 : count; - StringBuilder sb = new StringBuilder(s.length() * count); - for (int i = 0; i < count; i++) { - sb.append(s); - } - return sb.toString(); - } - - @NotNull - @Contract(pure = true) - public static List split(@NotNull String s, @NotNull String separator) { - return split(s, separator, true); - } - @NotNull - @Contract(pure = true) - public static List split(@NotNull CharSequence s, @NotNull CharSequence separator) { - return split(s, separator, true, true); - } - - @NotNull - @Contract(pure = true) - public static List split(@NotNull String s, @NotNull String separator, boolean excludeSeparator) { - return split(s, separator, excludeSeparator, true); - } - - @NotNull - @Contract(pure = true) - @SuppressWarnings("unchecked") - public static List split(@NotNull String s, @NotNull String separator, boolean excludeSeparator, boolean excludeEmptyStrings) { - return (List)split((CharSequence)s, separator, excludeSeparator, excludeEmptyStrings); - } - - @NotNull - @Contract(pure = true) - public static List split(@NotNull CharSequence s, @NotNull CharSequence separator, boolean excludeSeparator, boolean excludeEmptyStrings) { - if (separator.length() == 0) { - return Collections.singletonList(s); - } - List result = new ArrayList(); - int pos = 0; - while (true) { - int index = indexOf(s, separator, pos); - if (index == -1) break; - final int nextPos = index + separator.length(); - CharSequence token = s.subSequence(pos, excludeSeparator ? index : nextPos); - if (token.length() != 0 || !excludeEmptyStrings) { - result.add(token); - } - pos = nextPos; - } - if (pos < s.length() || !excludeEmptyStrings && pos == s.length()) { - result.add(s.subSequence(pos, s.length())); - } - return result; - } - - @NotNull - @Contract(pure = true) - public static Iterable tokenize(@NotNull String s, @NotNull String separators) { - final com.intellij.util.text.StringTokenizer tokenizer = new com.intellij.util.text.StringTokenizer(s, separators); - return new Iterable() { - @NotNull - @Override - public Iterator iterator() { - return new Iterator() { - @Override - public boolean hasNext() { - return tokenizer.hasMoreTokens(); - } - - @Override - public String next() { - return tokenizer.nextToken(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - }; - } - - @NotNull - @Contract(pure = true) - public static Iterable tokenize(@NotNull final StringTokenizer tokenizer) { - return new Iterable() { - @NotNull - @Override - public Iterator iterator() { - return new Iterator() { - @Override - public boolean hasNext() { - return tokenizer.hasMoreTokens(); - } - - @Override - public String next() { - return tokenizer.nextToken(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - }; - } - - /** - * @return list containing all words in {@code text}, or {@link ContainerUtil#emptyList()} if there are none. - * The word here means the maximum sub-string consisting entirely of characters which are {@code Character.isJavaIdentifierPart(c)}. - */ - @NotNull - @Contract(pure = true) - public static List getWordsIn(@NotNull String text) { - List result = null; - int start = -1; - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - boolean isIdentifierPart = Character.isJavaIdentifierPart(c); - if (isIdentifierPart && start == -1) { - start = i; - } - if (isIdentifierPart && i == text.length() - 1) { - if (result == null) { - result = new SmartList(); + while (start1 < end1) { + char c = s1.charAt(end1 - 1); + if (!isWhiteSpace(c)) break; + end1--; } - result.add(text.substring(start, i + 1)); - } - else if (!isIdentifierPart && start != -1) { - if (result == null) { - result = new SmartList(); - } - result.add(text.substring(start, i)); - start = -1; - } - } - if (result == null) { - return ContainerUtil.emptyList(); - } - return result; - } - - @NotNull - @Contract(pure = true) - public static List getWordIndicesIn(@NotNull String text) { - return getWordIndicesIn(text, null); - } - - /** - * @param text text to get word ranges in. - * @param separatorsSet if not null, only these characters will be considered as separators (i.e. not a part of word). - * Otherwise {@link Character#isJavaIdentifierPart(char)} will be used to determine whether a symbol is part of word. - * @return ranges ranges of words in passed text. - */ - @NotNull - @Contract(pure = true) - public static List getWordIndicesIn(@NotNull String text, @Nullable Set separatorsSet) { - List result = new SmartList(); - int start = -1; - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - boolean isIdentifierPart = separatorsSet == null ? Character.isJavaIdentifierPart(c) : !separatorsSet.contains(c); - if (isIdentifierPart && start == -1) { - start = i; - } - if (isIdentifierPart && i == text.length() - 1) { - result.add(new TextRange(start, i + 1)); - } - else if (!isIdentifierPart && start != -1) { - result.add(new TextRange(start, i)); - start = -1; - } - } - return result; - } - - @NotNull - @Contract(pure = true) - public static String join(@NotNull final String[] strings, @NotNull final String separator) { - return join(strings, 0, strings.length, separator); - } - - @NotNull - @Contract(pure = true) - public static String join(@NotNull final String[] strings, int startIndex, int endIndex, @NotNull final String separator) { - final StringBuilder result = new StringBuilder(); - for (int i = startIndex; i < endIndex; i++) { - if (i > startIndex) result.append(separator); - result.append(strings[i]); - } - return result.toString(); - } - - @NotNull - @Contract(pure = true) - public static String[] zip(@NotNull String[] strings1, @NotNull String[] strings2, String separator) { - if (strings1.length != strings2.length) throw new IllegalArgumentException(); - - String[] result = ArrayUtil.newStringArray(strings1.length); - for (int i = 0; i < result.length; i++) { - result[i] = strings1[i] + separator + strings2[i]; - } - - return result; - } - - @NotNull - @Contract(pure = true) - public static String[] surround(@NotNull String[] strings, @NotNull String prefix, @NotNull String suffix) { - String[] result = ArrayUtil.newStringArray(strings.length); - for (int i = 0; i < result.length; i++) { - result[i] = prefix + strings[i] + suffix; - } - return result; - } - - @NotNull - @Contract(pure = true) - public static String join(@NotNull T[] items, @NotNull Function f, @NotNull String separator) { - return join(Arrays.asList(items), f, separator); - } - - @NotNull - @Contract(pure = true) - public static String join(@NotNull Collection items, - @NotNull Function f, - @NotNull String separator) { - if (items.isEmpty()) return ""; - if (items.size() == 1) return notNullize(f.fun(items.iterator().next())); - return join((Iterable)items, f, separator); - } - - @Contract(pure = true) - public static String join(@NotNull Iterable items, @NotNull String separator) { - StringBuilder result = new StringBuilder(); - for (Object item : items) { - result.append(item).append(separator); - } - if (result.length() > 0) { - result.setLength(result.length() - separator.length()); - } - return result.toString(); - } - - @NotNull - @Contract(pure = true) - public static String join(@NotNull Iterable items, - @NotNull Function f, - @NotNull String separator) { - StringBuilder result = new StringBuilder(); - join(items, f, separator, result); - return result.toString(); - } - - public static void join(@NotNull Iterable items, - @NotNull Function f, - @NotNull String separator, - @NotNull StringBuilder result) { - boolean isFirst = true; - for (T item : items) { - String string = f.fun(item); - if (!isEmpty(string)) { - if (isFirst) { - isFirst = false; + + int start2 = 0; + while (start2 < end2) { + char c = s2.charAt(start2); + if (!isWhiteSpace(c)) break; + start2++; } - else { - result.append(separator); + + while (start2 < end2) { + char c = s2.charAt(end2 - 1); + if (!isWhiteSpace(c)) break; + end2--; } - result.append(string); - } - } - } - @NotNull - @Contract(pure = true) - public static String join(@NotNull Collection strings, @NotNull String separator) { - if (strings.size() <= 1) { - return notNullize(ContainerUtil.getFirstItem(strings)); + CharSequence ts1 = new CharSequenceSubSequence(s1, start1, end1); + CharSequence ts2 = new CharSequenceSubSequence(s2, start2, end2); + + return equals(ts1, ts2); } - StringBuilder result = new StringBuilder(); - join(strings, separator, result); - return result.toString(); - } - public static void join(@NotNull Collection strings, @NotNull String separator, @NotNull StringBuilder result) { - boolean isFirst = true; - for (String string : strings) { - if (string != null) { - if (isFirst) { - isFirst = false; + /** + * Collapses all white-space (including new lines) between non-white-space characters to a single space character. + * Leading and trailing white space is removed. + */ + public static String collapseWhiteSpace(@NotNull CharSequence s) { + final StringBuilder result = new StringBuilder(); + boolean space = false; + for (int i = 0, length = s.length(); i < length; i++) { + final char ch = s.charAt(i); + if (isWhiteSpace(ch)) { + if (!space) space = true; + } + else { + if (space && result.length() > 0) result.append(' '); + result.append(ch); + space = false; + } } - else { - result.append(separator); - } - result.append(string); - } - } - } - - @NotNull - @Contract(pure = true) - public static String join(@NotNull final int[] strings, @NotNull final String separator) { - final StringBuilder result = new StringBuilder(); - for (int i = 0; i < strings.length; i++) { - if (i > 0) result.append(separator); - result.append(strings[i]); - } - return result.toString(); - } - - @NotNull - @Contract(pure = true) - public static String join(@NotNull final String... strings) { - if (strings.length == 0) return ""; - - final StringBuilder builder = new StringBuilder(); - for (final String string : strings) { - builder.append(string); - } - return builder.toString(); - } - - /** - * Consider using {@link StringUtil#unquoteString(String)} instead. - * Note: this method has an odd behavior: - * Quotes are removed even if leading and trailing quotes are different or - * if there is only one quote (leading or trailing). - */ - @NotNull - @Contract(pure = true) - public static String stripQuotesAroundValue(@NotNull String text) { - final int len = text.length(); - if (len > 0) { - final int from = isQuoteAt(text, 0) ? 1 : 0; - final int to = len > 1 && isQuoteAt(text, len - 1) ? len - 1 : len; - if (from > 0 || to < len) { - return text.substring(from, to); - } - } - return text; - } - - /** Formats given duration as a sum of time units (example: {@code formatDuration(123456) = "2 m 3 s 456 ms"}). */ - @NotNull - @Contract(pure = true) - public static String formatDuration(long duration) { - return formatDuration(duration, " "); - } - - private static final String[] TIME_UNITS = {"ms", "s", "m", "h", "d", "mo", "yr", "c", "ml", "ep"}; - private static final long[] TIME_MULTIPLIERS = {1, 1000, 60, 60, 24, 30, 12, 100, 10, 10000}; - - /** Formats given duration as a sum of time units (example: {@code formatDuration(123456, "") = "2m 3s 456ms"}). */ - @NotNull - @Contract(pure = true) - public static String formatDuration(long duration, @NotNull String unitSeparator) { - String[] units = TIME_UNITS; - - StringBuilder sb = new StringBuilder(); - long count = duration; - int i = 1; - for (; i < units.length && count > 0; i++) { - long multiplier = TIME_MULTIPLIERS[i]; - if (count < multiplier) break; - long remainder = count % multiplier; - count /= multiplier; - if (remainder != 0 || sb.length() > 0) { - if (!units[i - 1].isEmpty()) { - sb.insert(0, units[i - 1]); - sb.insert(0, unitSeparator); - } - sb.insert(0, remainder).insert(0, " "); - } - else { - remainder = Math.round(remainder * 100 / (double)multiplier); - count += remainder / 100; - } - } - if (!units[i - 1].isEmpty()) { - sb.insert(0, units[i - 1]); - sb.insert(0, unitSeparator); - } - sb.insert(0, count); - return sb.toString(); - } - - @Contract(pure = true) - public static boolean containsAlphaCharacters(@NotNull String value) { - for (int i = 0; i < value.length(); i++) { - if (Character.isLetter(value.charAt(i))) return true; - } - return false; - } - - @Contract(pure = true) - public static boolean containsAnyChar(@NotNull final String value, @NotNull final String chars) { - return chars.length() > value.length() - ? containsAnyChar(value, chars, 0, value.length()) - : containsAnyChar(chars, value, 0, chars.length()); - } - - @Contract(pure = true) - public static boolean containsAnyChar(@NotNull final String value, - @NotNull final String chars, - final int start, final int end) { - for (int i = start; i < end; i++) { - if (chars.indexOf(value.charAt(i)) >= 0) { - return true; - } - } - - return false; - } - - @Contract(pure = true) - public static boolean containsChar(@NotNull final String value, final char ch) { - return value.indexOf(ch) >= 0; - } - - /** - * @deprecated use #capitalize(String) - */ - @Deprecated - @Contract(value = "null -> null; !null -> !null", pure = true) - public static String firstLetterToUpperCase(@Nullable final String displayString) { - if (displayString == null || displayString.isEmpty()) return displayString; - char firstChar = displayString.charAt(0); - char uppedFirstChar = toUpperCase(firstChar); - - if (uppedFirstChar == firstChar) return displayString; - - char[] buffer = displayString.toCharArray(); - buffer[0] = uppedFirstChar; - return StringFactory.createShared(buffer); - } - - /** - * Strip out all characters not accepted by given filter - * - * @param s e.g. "/n my string " - * @param filter e.g. {@link CharFilter#NOT_WHITESPACE_FILTER} - * @return stripped string e.g. "mystring" - */ - @NotNull - @Contract(pure = true) - public static String strip(@NotNull final String s, @NotNull final CharFilter filter) { - final StringBuilder result = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) { - char ch = s.charAt(i); - if (filter.accept(ch)) { - result.append(ch); - } - } - return result.toString(); - } - - @NotNull - @Contract(pure = true) - public static List findMatches(@NotNull String s, @NotNull Pattern pattern) { - return findMatches(s, pattern, 1); - } - - @NotNull - @Contract(pure = true) - public static List findMatches(@NotNull String s, @NotNull Pattern pattern, int groupIndex) { - List result = new SmartList(); - Matcher m = pattern.matcher(s); - while (m.find()) { - String group = m.group(groupIndex); - if (group != null) { - result.add(group); - } - } - return result; - } - - /** - * Find position of the first character accepted by given filter. - * - * @param s the string to search - * @param filter search filter - * @return position of the first character accepted or -1 if not found - */ - @Contract(pure = true) - public static int findFirst(@NotNull final CharSequence s, @NotNull CharFilter filter) { - for (int i = 0; i < s.length(); i++) { - char ch = s.charAt(i); - if (filter.accept(ch)) { - return i; - } - } - return -1; - } - - @NotNull - @Contract(pure = true) - public static String replaceSubstring(@NotNull String string, @NotNull TextRange range, @NotNull String replacement) { - return range.replace(string, replacement); - } - - @Contract(pure = true) - public static boolean startsWithWhitespace(@NotNull String text) { - return !text.isEmpty() && Character.isWhitespace(text.charAt(0)); - } - - @Contract(pure = true) - public static boolean isChar(CharSequence seq, int index, char c) { - return index >= 0 && index < seq.length() && seq.charAt(index) == c; - } - - @Contract(pure = true) - public static boolean startsWith(@NotNull CharSequence text, @NotNull CharSequence prefix) { - int l1 = text.length(); - int l2 = prefix.length(); - if (l1 < l2) return false; - - for (int i = 0; i < l2; i++) { - if (text.charAt(i) != prefix.charAt(i)) return false; - } - - return true; - } - - @Contract(pure = true) - public static boolean startsWith(@NotNull CharSequence text, int startIndex, @NotNull CharSequence prefix) { - int tl = text.length(); - if (startIndex < 0 || startIndex > tl) { - throw new IllegalArgumentException("Index is out of bounds: " + startIndex + ", length: " + tl); - } - int l1 = tl - startIndex; - int l2 = prefix.length(); - if (l1 < l2) return false; - - for (int i = 0; i < l2; i++) { - if (text.charAt(i + startIndex) != prefix.charAt(i)) return false; - } - - return true; - } - - @Contract(pure = true) - public static boolean endsWith(@NotNull CharSequence text, @NotNull CharSequence suffix) { - int l1 = text.length(); - int l2 = suffix.length(); - if (l1 < l2) return false; - - for (int i = l1 - 1; i >= l1 - l2; i--) { - if (text.charAt(i) != suffix.charAt(i + l2 - l1)) return false; - } - - return true; - } - - @NotNull - @Contract(pure = true) - public static String commonPrefix(@NotNull String s1, @NotNull String s2) { - return s1.substring(0, commonPrefixLength(s1, s2)); - } - - @Contract(pure = true) - public static int commonPrefixLength(@NotNull CharSequence s1, @NotNull CharSequence s2) { - return commonPrefixLength(s1, s2, false); - } - - @Contract(pure = true) - public static int commonPrefixLength(@NotNull CharSequence s1, @NotNull CharSequence s2, boolean ignoreCase) { - int i; - int minLength = Math.min(s1.length(), s2.length()); - for (i = 0; i < minLength; i++) { - if (!charsMatch(s1.charAt(i), s2.charAt(i), ignoreCase)) { - break; - } - } - return i; - } - - @NotNull - @Contract(pure = true) - public static String commonSuffix(@NotNull String s1, @NotNull String s2) { - return s1.substring(s1.length() - commonSuffixLength(s1, s2)); - } - - @Contract(pure = true) - public static int commonSuffixLength(@NotNull CharSequence s1, @NotNull CharSequence s2) { - int s1Length = s1.length(); - int s2Length = s2.length(); - if (s1Length == 0 || s2Length == 0) return 0; - int i; - for (i = 0; i < s1Length && i < s2Length; i++) { - if (s1.charAt(s1Length - i - 1) != s2.charAt(s2Length - i - 1)) { - break; - } - } - return i; - } - - /** - * Allows to answer if target symbol is contained at given char sequence at {@code [start; end)} interval. - * - * @param s target char sequence to check - * @param start start offset to use within the given char sequence (inclusive) - * @param end end offset to use within the given char sequence (exclusive) - * @param c target symbol to check - * @return {@code true} if given symbol is contained at the target range of the given char sequence; - * {@code false} otherwise - */ - @Contract(pure = true) - public static boolean contains(@NotNull CharSequence s, int start, int end, char c) { - return indexOf(s, c, start, end) >= 0; - } - - @Contract(pure = true) - public static boolean containsWhitespaces(@Nullable CharSequence s) { - if (s == null) return false; - - for (int i = 0; i < s.length(); i++) { - if (Character.isWhitespace(s.charAt(i))) return true; - } - return false; - } - - @Contract(pure = true) - public static int indexOf(@NotNull CharSequence s, char c) { - return indexOf(s, c, 0, s.length()); - } - - @Contract(pure = true) - public static int indexOf(@NotNull CharSequence s, char c, int start) { - return indexOf(s, c, start, s.length()); - } - - @Contract(pure = true) - public static int indexOf(@NotNull CharSequence s, char c, int start, int end) { - end = Math.min(end, s.length()); - for (int i = Math.max(start, 0); i < end; i++) { - if (s.charAt(i) == c) return i; - } - return -1; - } - - @Contract(pure = true) - public static boolean contains(@NotNull CharSequence sequence, @NotNull CharSequence infix) { - return indexOf(sequence, infix) >= 0; - } - - @Contract(pure = true) - public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix) { - return indexOf(sequence, infix, 0); - } - - @Contract(pure = true) - public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix, int start) { - return indexOf(sequence, infix, start, sequence.length()); - } - - @Contract(pure = true) - public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix, int start, int end) { - for (int i = start; i <= end - infix.length(); i++) { - if (startsWith(sequence, i, infix)) { - return i; - } - } - return -1; - } - - @Contract(pure = true) - public static int indexOf(@NotNull CharSequence s, char c, int start, int end, boolean caseSensitive) { - end = Math.min(end, s.length()); - for (int i = Math.max(start, 0); i < end; i++) { - if (charsMatch(s.charAt(i), c, !caseSensitive)) return i; - } - return -1; - } - - @Contract(pure = true) - public static int indexOf(@NotNull char[] s, char c, int start, int end, boolean caseSensitive) { - end = Math.min(end, s.length); - for (int i = Math.max(start, 0); i < end; i++) { - if (charsMatch(s[i], c, !caseSensitive)) return i; - } - return -1; - } - - @Contract(pure = true) - public static int indexOfSubstringEnd(@NotNull String text, @NotNull String subString) { - int i = text.indexOf(subString); - if (i == -1) return -1; - return i + subString.length(); - } - - @Contract(pure = true) - public static int indexOfAny(@NotNull final String s, @NotNull final String chars) { - return indexOfAny(s, chars, 0, s.length()); - } - - @Contract(pure = true) - public static int indexOfAny(@NotNull final CharSequence s, @NotNull final String chars) { - return indexOfAny(s, chars, 0, s.length()); - } - - @Contract(pure = true) - public static int indexOfAny(@NotNull final String s, @NotNull final String chars, final int start, final int end) { - return indexOfAny((CharSequence)s, chars, start, end); - } - - @Contract(pure = true) - public static int indexOfAny(@NotNull final CharSequence s, @NotNull final String chars, final int start, int end) { - end = Math.min(end, s.length()); - for (int i = Math.max(start, 0); i < end; i++) { - if (containsChar(chars, s.charAt(i))) return i; - } - return -1; - } - - @Contract(pure = true) - public static int lastIndexOfAny(@NotNull CharSequence s, @NotNull final String chars) { - for (int i = s.length() - 1; i >= 0; i--) { - if (containsChar(chars, s.charAt(i))) return i; - } - return -1; - } - - @Nullable - @Contract(pure = true) - public static String substringBefore(@NotNull String text, @NotNull String subString) { - int i = text.indexOf(subString); - if (i == -1) return null; - return text.substring(0, i); - } - - @NotNull - @Contract(pure = true) - public static String substringBeforeLast(@NotNull String text, @NotNull String subString) { - int i = text.lastIndexOf(subString); - if (i == -1) return text; - return text.substring(0, i); - } - - @Nullable - @Contract(pure = true) - public static String substringAfter(@NotNull String text, @NotNull String subString) { - int i = text.indexOf(subString); - if (i == -1) return null; - return text.substring(i + subString.length()); - } - - @Nullable - @Contract(pure = true) - public static String substringAfterLast(@NotNull String text, @NotNull String subString) { - int i = text.lastIndexOf(subString); - if (i == -1) return null; - return text.substring(i + subString.length()); - } - - /** - * Allows to retrieve index of last occurrence of the given symbols at {@code [start; end)} sub-sequence of the given text. - * - * @param s target text - * @param c target symbol which last occurrence we want to check - * @param start start offset of the target text (inclusive) - * @param end end offset of the target text (exclusive) - * @return index of the last occurrence of the given symbol at the target sub-sequence of the given text if any; - * {@code -1} otherwise - */ - @Contract(pure = true) - public static int lastIndexOf(@NotNull CharSequence s, char c, int start, int end) { - return StringUtilRt.lastIndexOf(s, c, start, end); - } - - @NotNull - @Contract(pure = true) - public static String first(@NotNull String text, final int maxLength, final boolean appendEllipsis) { - return text.length() > maxLength ? text.substring(0, maxLength) + (appendEllipsis ? "..." : "") : text; - } - - @NotNull - @Contract(pure = true) - public static CharSequence first(@NotNull CharSequence text, final int length, final boolean appendEllipsis) { - if (text.length() <= length) { - return text; - } - if (appendEllipsis) { - return text.subSequence(0, length) + "..."; - } - return text.subSequence(0, length); - } - - @NotNull - @Contract(pure = true) - public static CharSequence last(@NotNull CharSequence text, final int length, boolean prependEllipsis) { - if (text.length() <= length) { - return text; - } - if (prependEllipsis) { - return "..." + text.subSequence(text.length() - length, text.length()); - } - return text.subSequence(text.length() - length, text.length()); - } - - @NotNull - @Contract(pure = true) - public static String firstLast(@NotNull String text, int length) { - return text.length() > length - ? text.subSequence(0, length / 2) + "\u2026" + text.subSequence(text.length() - length / 2 - 1, text.length()) - : text; - } - - @NotNull - @Contract(pure = true) - public static String escapeChar(@NotNull final String str, final char character) { - return escapeChars(str, character); - } - - @NotNull - @Contract(pure = true) - public static String escapeChars(@NotNull final String str, final char... character) { - final StringBuilder buf = new StringBuilder(str); - for (char c : character) { - escapeChar(buf, c); - } - return buf.toString(); - } - - public static void escapeChar(@NotNull final StringBuilder buf, final char character) { - int idx = 0; - while ((idx = indexOf(buf, character, idx)) >= 0) { - buf.insert(idx, "\\"); - idx += 2; - } - } - - @NotNull - @Contract(pure = true) - public static String escapeQuotes(@NotNull final String str) { - return escapeChar(str, '"'); - } - - public static void escapeQuotes(@NotNull final StringBuilder buf) { - escapeChar(buf, '"'); - } - - @NotNull - @Contract(pure = true) - public static String escapeSlashes(@NotNull final String str) { - return escapeChar(str, '/'); - } - - @NotNull - @Contract(pure = true) - public static String escapeBackSlashes(@NotNull final String str) { - return escapeChar(str, '\\'); - } - - public static void escapeSlashes(@NotNull final StringBuilder buf) { - escapeChar(buf, '/'); - } - - @NotNull - @Contract(pure = true) - public static String unescapeSlashes(@NotNull final String str) { - final StringBuilder buf = new StringBuilder(str.length()); - unescapeChar(buf, str, '/'); - return buf.toString(); - } - - @NotNull - @Contract(pure = true) - public static String unescapeBackSlashes(@NotNull final String str) { - final StringBuilder buf = new StringBuilder(str.length()); - unescapeChar(buf, str, '\\'); - return buf.toString(); - } - - @NotNull - @Contract(pure = true) - public static String unescapeChar(@NotNull final String str, char unescapeChar) { - final StringBuilder buf = new StringBuilder(str.length()); - unescapeChar(buf, str, unescapeChar); - return buf.toString(); - } - - private static void unescapeChar(@NotNull StringBuilder buf, @NotNull String str, char unescapeChar) { - final int length = str.length(); - final int last = length - 1; - for (int i = 0; i < length; i++) { - char ch = str.charAt(i); - if (ch == '\\' && i != last) { - //noinspection AssignmentToForLoopParameter - i++; - ch = str.charAt(i); - if (ch != unescapeChar) buf.append('\\'); - } - - buf.append(ch); - } - } - - public static void quote(@NotNull final StringBuilder builder) { - quote(builder, '\"'); - } - - public static void quote(@NotNull final StringBuilder builder, final char quotingChar) { - builder.insert(0, quotingChar); - builder.append(quotingChar); - } - - @NotNull - @Contract(pure = true) - public static String wrapWithDoubleQuote(@NotNull String str) { - return '\"' + str + "\""; - } - - private static final List REPLACES_REFS = Arrays.asList("<", ">", "&", "'", """); - private static final List REPLACES_DISP = Arrays.asList("<", ">", "&", "'", "\""); - - /** - * @deprecated Use {@link #unescapeXmlEntities(String)} instead - */ - @Contract(value = "null -> null; !null -> !null",pure = true) - @Deprecated - public static String unescapeXml(@Nullable final String text) { - return text == null ? null : unescapeXmlEntities(text); - } - - /** - * @deprecated Use {@link #escapeXmlEntities(String)} instead - */ - @Contract(value = "null -> null; !null -> !null",pure = true) - @Deprecated - public static String escapeXml(@Nullable final String text) { - return text == null ? null : escapeXmlEntities(text); - } - - /** - * @return {@code text} with some standard XML entities replaced with corresponding characters, e.g. '{@code <}' replaced with '<' - */ - @NotNull - @Contract(pure = true) - public static String unescapeXmlEntities(@NotNull String text) { - return replace(text, REPLACES_REFS, REPLACES_DISP); - } - - /** - * @return {@code text} with some characters replaced with standard XML entities, e.g. '<' replaced with '{@code <}' - */ - @NotNull - @Contract(pure = true) - public static String escapeXmlEntities(@NotNull String text) { - return replace(text, REPLACES_DISP, REPLACES_REFS); - } - - @NotNull - public static String removeHtmlTags(@NotNull String htmlString) { - return removeHtmlTags(htmlString, false); - } - - @NotNull - public static String removeHtmlTags(@NotNull String htmlString, boolean isRemoveStyleTag) { - if (isEmpty(htmlString)) { - return ""; - } - - final MyHtml2Text parser = isRemoveStyleTag ? new MyHtml2Text(true) : html2TextParser; - try { - parser.parse(new StringReader(htmlString)); - } - catch (IOException e) { - LOG.error(e); - } - return parser.getText(); - } - - private static final List MN_QUOTED = Arrays.asList("&&", "__"); - private static final List MN_CHARS = Arrays.asList("&", "_"); - - @NotNull - @Contract(pure = true) - public static String escapeMnemonics(@NotNull String text) { - return replace(text, MN_CHARS, MN_QUOTED); - } - - @NotNull - @Contract(pure = true) - public static String htmlEmphasize(@NotNull String text) { - return "" + escapeXmlEntities(text) + ""; - } - - - @NotNull - @Contract(pure = true) - public static String escapeToRegexp(@NotNull String text) { - final StringBuilder result = new StringBuilder(text.length()); - return escapeToRegexp(text, result).toString(); - } - - @NotNull - public static StringBuilder escapeToRegexp(@NotNull CharSequence text, @NotNull StringBuilder builder) { - for (int i = 0; i < text.length(); i++) { - final char c = text.charAt(i); - if (c == ' ' || Character.isLetter(c) || Character.isDigit(c) || c == '_') { - builder.append(c); - } - else if (c == '\n') { - builder.append("\\n"); - } - else if (c == '\r') { - builder.append("\\r"); - } - else { - builder.append('\\').append(c); - } - } - - return builder; - } - - @Contract(pure = true) - public static boolean isEscapedBackslash(@NotNull char[] chars, int startOffset, int backslashOffset) { - if (chars[backslashOffset] != '\\') { - return true; - } - boolean escaped = false; - for (int i = startOffset; i < backslashOffset; i++) { - if (chars[i] == '\\') { - escaped = !escaped; - } - else { - escaped = false; - } - } - return escaped; - } - - @Contract(pure = true) - public static boolean isEscapedBackslash(@NotNull CharSequence text, int startOffset, int backslashOffset) { - if (text.charAt(backslashOffset) != '\\') { - return true; - } - boolean escaped = false; - for (int i = startOffset; i < backslashOffset; i++) { - if (text.charAt(i) == '\\') { - escaped = !escaped; - } - else { - escaped = false; - } - } - return escaped; - } - - /** - * @deprecated Use {@link #replace(String, List, List)} - */ - @Deprecated - @NotNull - @Contract(pure = true) - public static String replace(@NotNull String text, @NotNull String[] from, @NotNull String[] to) { - return replace(text, Arrays.asList(from), Arrays.asList(to)); - } - - @NotNull - @Contract(pure = true) - public static String replace(@NotNull String text, @NotNull List from, @NotNull List to) { - assert from.size() == to.size(); - StringBuilder result = null; - replace: - for (int i = 0; i < text.length(); i++) { - for (int j = 0; j < from.size(); j += 1) { - String toReplace = from.get(j); - String replaceWith = to.get(j); - - final int len = toReplace.length(); - if (text.regionMatches(i, toReplace, 0, len)) { - if (result == null) { - result = new StringBuilder(text.length()); - result.append(text, 0, i); - } - result.append(replaceWith); - //noinspection AssignmentToForLoopParameter - i += len - 1; - continue replace; - } - } - - if (result != null) { - result.append(text.charAt(i)); - } - } - return result == null ? text : result.toString(); - } - - @NotNull - @Contract(pure = true) - public static String[] filterEmptyStrings(@NotNull String[] strings) { - int emptyCount = 0; - for (String string : strings) { - if (string == null || string.isEmpty()) emptyCount++; - } - if (emptyCount == 0) return strings; - - String[] result = ArrayUtil.newStringArray(strings.length - emptyCount); - int count = 0; - for (String string : strings) { - if (string == null || string.isEmpty()) continue; - result[count++] = string; - } - - return result; - } - - @Contract(pure = true) - public static int countNewLines(@NotNull CharSequence text) { - return countChars(text, '\n'); - } - - @Contract(pure = true) - public static int countChars(@NotNull CharSequence text, char c) { - return countChars(text, c, 0, false); - } - - @Contract(pure = true) - public static int countChars(@NotNull CharSequence text, char c, int offset, boolean stopAtOtherChar) { - return countChars(text, c, offset, text.length(), stopAtOtherChar); - } - - @Contract(pure = true) - public static int countChars(@NotNull CharSequence text, char c, int start, int end, boolean stopAtOtherChar) { - boolean forward = start <= end; - start = forward ? Math.max(0, start) : Math.min(text.length(), start); - end = forward ? Math.min(text.length(), end) : Math.max(0, end); - int count = 0; - for (int i = forward ? start : start - 1; forward == i < end; i += forward ? 1 : -1) { - if (text.charAt(i) == c) { - count++; - } - else if (stopAtOtherChar) { - break; - } - } - return count; - } - - @NotNull - @Contract(pure = true) - public static String capitalsOnly(@NotNull String s) { - StringBuilder b = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - if (Character.isUpperCase(s.charAt(i))) { - b.append(s.charAt(i)); - } - } - - return b.toString(); - } - - /** - * @param args Strings to join. - * @return {@code null} if any of given Strings is {@code null}. - */ - @Nullable - @Contract(pure = true) - public static String joinOrNull(@NotNull String... args) { - StringBuilder r = new StringBuilder(); - for (String arg : args) { - if (arg == null) return null; - r.append(arg); - } - return r.toString(); - } - - @Nullable - @Contract(pure = true) - public static String getPropertyName(@NotNull String methodName) { - if (methodName.startsWith("get")) { - return Introspector.decapitalize(methodName.substring(3)); - } - if (methodName.startsWith("is")) { - return Introspector.decapitalize(methodName.substring(2)); - } - if (methodName.startsWith("set")) { - return Introspector.decapitalize(methodName.substring(3)); - } - return null; - } - - @Contract(pure = true) - public static boolean isJavaIdentifierStart(char c) { - return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || Character.isJavaIdentifierStart(c); - } - - @Contract(pure = true) - public static boolean isJavaIdentifierPart(char c) { - return c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || Character.isJavaIdentifierPart(c); - } - - @Contract(pure = true) - public static boolean isJavaIdentifier(@NotNull String text) { - int len = text.length(); - if (len == 0) return false; - - if (!isJavaIdentifierStart(text.charAt(0))) return false; - - for (int i = 1; i < len; i++) { - if (!isJavaIdentifierPart(text.charAt(i))) return false; - } - - return true; - } - - /** - * Escape property name or key in property file. Unicode characters are escaped as well. - * - * @param input an input to escape - * @param isKey if true, the rules for key escaping are applied. The leading space is escaped in that case. - * @return an escaped string - */ - @NotNull - @Contract(pure = true) - public static String escapeProperty(@NotNull String input, final boolean isKey) { - final StringBuilder escaped = new StringBuilder(input.length()); - for (int i = 0; i < input.length(); i++) { - final char ch = input.charAt(i); - switch (ch) { - case ' ': - if (isKey && i == 0) { - // only the leading space has to be escaped - escaped.append('\\'); - } - escaped.append(' '); - break; - case '\t': - escaped.append("\\t"); - break; - case '\r': - escaped.append("\\r"); - break; - case '\n': - escaped.append("\\n"); - break; - case '\f': - escaped.append("\\f"); - break; - case '\\': - case '#': - case '!': - case ':': - case '=': - escaped.append('\\'); - escaped.append(ch); - break; - default: - if (20 < ch && ch < 0x7F) { - escaped.append(ch); - } - else { - escaped.append("\\u"); - escaped.append(Character.forDigit((ch >> 12) & 0xF, 16)); - escaped.append(Character.forDigit((ch >> 8) & 0xF, 16)); - escaped.append(Character.forDigit((ch >> 4) & 0xF, 16)); - escaped.append(Character.forDigit((ch) & 0xF, 16)); - } - break; - } - } - return escaped.toString(); - } - - @NotNull - @Contract(pure = true) - public static String getQualifiedName(@Nullable String packageName, @NotNull String className) { - if (packageName == null || packageName.isEmpty()) { - return className; - } - return packageName + '.' + className; - } - - @Contract(pure = true) - public static int compareVersionNumbers(@Nullable String v1, @Nullable String v2) { - // todo duplicates com.intellij.util.text.VersionComparatorUtil.compare - // todo please refactor next time you make changes here - if (v1 == null && v2 == null) { - return 0; - } - if (v1 == null) { - return -1; - } - if (v2 == null) { - return 1; - } - - String[] part1 = v1.split("[._\\-]"); - String[] part2 = v2.split("[._\\-]"); - - int idx = 0; - for (; idx < part1.length && idx < part2.length; idx++) { - String p1 = part1[idx]; - String p2 = part2[idx]; - - int cmp; - if (p1.matches("\\d+") && p2.matches("\\d+")) { - cmp = new Integer(p1).compareTo(new Integer(p2)); - } - else { - cmp = part1[idx].compareTo(part2[idx]); - } - if (cmp != 0) return cmp; - } - - if (part1.length != part2.length) { - boolean left = part1.length > idx; - String[] parts = left ? part1 : part2; - - for (; idx < parts.length; idx++) { - String p = parts[idx]; - int cmp; - if (p.matches("\\d+")) { - cmp = new Integer(p).compareTo(0); + return result.toString(); + } + + @Contract(pure = true) + public static boolean findIgnoreCase(@Nullable String toFind, @NotNull String... where) { + for (String string : where) { + if (equalsIgnoreCase(toFind, string)) return true; } - else { - cmp = 1; - } - if (cmp != 0) return left ? cmp : -cmp; - } - } - return 0; - } - - @Contract(pure = true) - public static int getOccurrenceCount(@NotNull String text, final char c) { - int res = 0; - int i = 0; - while (i < text.length()) { - i = text.indexOf(c, i); - if (i >= 0) { - res++; - i++; - } - else { - break; - } - } - return res; - } - - @Contract(pure = true) - public static int getOccurrenceCount(@NotNull String text, @NotNull String s) { - int res = 0; - int i = 0; - while (i < text.length()) { - i = text.indexOf(s, i); - if (i >= 0) { - res++; - i++; - } - else { - break; - } - } - return res; - } - - @Contract(pure = true) - public static int getIgnoreCaseOccurrenceCount(@NotNull String text, @NotNull String s) { - int res = 0; - int i = 0; - while (i < text.length()) { - i = indexOfIgnoreCase(text, s, i); - if (i >= 0) { - res++; - i++; - } - else { - break; - } - } - return res; - } - - @NotNull - @Contract(pure = true) - public static String fixVariableNameDerivedFromPropertyName(@NotNull String name) { - if (isEmptyOrSpaces(name)) return name; - char c = name.charAt(0); - if (isVowel(c)) { - return "an" + Character.toUpperCase(c) + name.substring(1); - } - return "a" + Character.toUpperCase(c) + name.substring(1); - } - - @NotNull - @Contract(pure = true) - public static String sanitizeJavaIdentifier(@NotNull String name) { - final StringBuilder result = new StringBuilder(name.length()); - - for (int i = 0; i < name.length(); i++) { - final char ch = name.charAt(i); - if (Character.isJavaIdentifierPart(ch)) { - if (result.length() == 0 && !Character.isJavaIdentifierStart(ch)) { - result.append("_"); - } - result.append(ch); - } - } - - return result.toString(); - } - - public static void assertValidSeparators(@NotNull CharSequence s) { - char[] chars = CharArrayUtil.fromSequenceWithoutCopying(s); - int slashRIndex = -1; - - if (chars != null) { - for (int i = 0, len = s.length(); i < len; ++i) { - if (chars[i] == '\r') { - slashRIndex = i; - break; - } - } - } - else { - for (int i = 0, len = s.length(); i < len; i++) { - if (s.charAt(i) == '\r') { - slashRIndex = i; - break; - } - } - } - - if (slashRIndex != -1) { - String context = - String.valueOf(last(s.subSequence(0, slashRIndex), 10, true)) + first(s.subSequence(slashRIndex, s.length()), 10, true); - context = escapeStringCharacters(context); - throw new AssertionError("Wrong line separators: '" + context + "' at offset " + slashRIndex); - } - } - - @NotNull - @Contract(pure = true) - public static String tail(@NotNull String s, final int idx) { - return idx >= s.length() ? "" : s.substring(idx); - } - - /** - * Splits string by lines. - * - * @param string String to split - * @return array of strings - */ - @NotNull - @Contract(pure = true) - public static String[] splitByLines(@NotNull String string) { - return splitByLines(string, true); - } - - /** - * Splits string by lines. If several line separators are in a row corresponding empty lines - * are also added to result if {@code excludeEmptyStrings} is {@code false}. - * - * @param string String to split - * @return array of strings - */ - @NotNull - @Contract(pure = true) - public static String[] splitByLines(@NotNull String string, boolean excludeEmptyStrings) { - return (excludeEmptyStrings ? EOL_SPLIT_PATTERN : EOL_SPLIT_PATTERN_WITH_EMPTY).split(string); - } - - @NotNull - @Contract(pure = true) - public static String[] splitByLinesDontTrim(@NotNull String string) { - return EOL_SPLIT_DONT_TRIM_PATTERN.split(string); - } - - /** - * Splits string by lines, keeping all line separators at the line ends and in the empty lines. - *
E.g. splitting text - *
- * foo\r\n
- * \n
- * bar\n
- * \r\n
- * baz\r
- * \r
- *
- * will return the following array: foo\r\n, \n, bar\n, \r\n, baz\r, \r - * - */ - @NotNull - @Contract(pure = true) - public static String[] splitByLinesKeepSeparators(@NotNull String string) { - return EOL_SPLIT_KEEP_SEPARATORS.split(string); - } - - @NotNull - @Contract(pure = true) - public static List> getWordsWithOffset(@NotNull String s) { - List> res = ContainerUtil.newArrayList(); - s += " "; - StringBuilder name = new StringBuilder(); - int startInd = -1; - for (int i = 0; i < s.length(); i++) { - if (Character.isWhitespace(s.charAt(i))) { - if (name.length() > 0) { - res.add(Pair.create(name.toString(), startInd)); - name.setLength(0); - startInd = -1; - } - } - else { - if (startInd == -1) { - startInd = i; - } - name.append(s.charAt(i)); - } - } - return res; - } - - @Contract(pure = true) - public static int naturalCompare(@Nullable String string1, @Nullable String string2) { - return NaturalComparator.INSTANCE.compare(string1, string2); - } - - @Contract(pure = true) - public static boolean isDecimalDigit(char c) { - return c >= '0' && c <= '9'; - } - - @Contract("null -> false") - public static boolean isNotNegativeNumber(@Nullable CharSequence s) { - if (s == null) { - return false; - } - for (int i = 0; i < s.length(); i++) { - if (!isDecimalDigit(s.charAt(i))) { return false; - } } - return true; - } - - @Contract(pure = true) - public static int compare(@Nullable String s1, @Nullable String s2, boolean ignoreCase) { - //noinspection StringEquality - if (s1 == s2) return 0; - if (s1 == null) return -1; - if (s2 == null) return 1; - return ignoreCase ? s1.compareToIgnoreCase(s2) : s1.compareTo(s2); - } - - @Contract(pure = true) - public static int comparePairs(@Nullable String s1, @Nullable String t1, @Nullable String s2, @Nullable String t2, boolean ignoreCase) { - final int compare = compare(s1, s2, ignoreCase); - return compare != 0 ? compare : compare(t1, t2, ignoreCase); - } - @Contract(pure = true) - public static int hashCode(@NotNull CharSequence s) { - return stringHashCode(s); - } - - @Contract(pure = true) - public static boolean equals(@Nullable CharSequence s1, @Nullable CharSequence s2) { - if (s1 == null ^ s2 == null) { - return false; + @Contract(pure = true) + public static int compare(char c1, char c2, boolean ignoreCase) { + // duplicating String.equalsIgnoreCase logic + int d = c1 - c2; + if (d == 0 || !ignoreCase) { + return d; + } + // If characters don't match but case may be ignored, + // try converting both characters to uppercase. + // If the results match, then the comparison scan should + // continue. + char u1 = StringUtilRt.toUpperCase(c1); + char u2 = StringUtilRt.toUpperCase(c2); + d = u1 - u2; + if (d != 0) { + // Unfortunately, conversion to uppercase does not work properly + // for the Georgian alphabet, which has strange rules about case + // conversion. So we need to make one last check before + // exiting. + d = StringUtilRt.toLowerCase(u1) - StringUtilRt.toLowerCase(u2); + } + return d; } - if (s1 == null) { - return true; + @Contract(pure = true) + public static boolean charsMatch(char c1, char c2, boolean ignoreCase) { + return compare(c1, c2, ignoreCase) == 0; } - if (s1.length() != s2.length()) { - return false; + @NotNull + @Contract(pure = true) + public static String formatLinks(@NotNull String message) { + Pattern linkPattern = Pattern.compile("http://[a-zA-Z0-9./\\-+]+"); + StringBuffer result = new StringBuffer(); + Matcher m = linkPattern.matcher(message); + while (m.find()) { + m.appendReplacement(result, "" + m.group() + ""); + } + m.appendTail(result); + return result.toString(); } - for (int i = 0; i < s1.length(); i++) { - if (s1.charAt(i) != s2.charAt(i)) { - return false; - } + + @Contract(pure = true) + public static boolean isHexDigit(char c) { + return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'; } - return true; - } - @Contract(pure = true) - public static boolean equalsIgnoreCase(@Nullable CharSequence s1, @Nullable CharSequence s2) { - if (s1 == null ^ s2 == null) { - return false; + @Contract(pure = true) + public static boolean isOctalDigit(char c) { + return '0' <= c && c <= '7'; } - if (s1 == null) { - return true; + @NotNull + @Contract(pure = true) + public static String shortenTextWithEllipsis(@NotNull final String text, final int maxLength, final int suffixLength) { + return shortenTextWithEllipsis(text, maxLength, suffixLength, false); } - if (s1.length() != s2.length()) { - return false; + @NotNull + @Contract(pure = true) + public static String trimMiddle(@NotNull String text, int maxLength) { + return shortenTextWithEllipsis(text, maxLength, maxLength >> 1, true); } - for (int i = 0; i < s1.length(); i++) { - if (!charsEqualIgnoreCase(s1.charAt(i), s2.charAt(i))) { - return false; - } + + @NotNull + @Contract(pure = true) + public static String shortenTextWithEllipsis(@NotNull final String text, + final int maxLength, + final int suffixLength, + @NotNull String symbol) { + final int textLength = text.length(); + if (textLength > maxLength) { + final int prefixLength = maxLength - suffixLength - symbol.length(); + assert prefixLength > 0; + return text.substring(0, prefixLength) + symbol + text.substring(textLength - suffixLength); + } + else { + return text; + } } - return true; - } - @Contract(pure = true) - public static boolean equalsIgnoreWhitespaces(@Nullable CharSequence s1, @Nullable CharSequence s2) { - if (s1 == null ^ s2 == null) { - return false; + @NotNull + @Contract(pure = true) + public static String shortenTextWithEllipsis(@NotNull final String text, + final int maxLength, + final int suffixLength, + boolean useEllipsisSymbol) { + String symbol = useEllipsisSymbol ? "\u2026" : "..."; + return shortenTextWithEllipsis(text, maxLength, suffixLength, symbol); } - if (s1 == null) { - return true; + @NotNull + @Contract(pure = true) + public static String shortenPathWithEllipsis(@NotNull final String path, final int maxLength, boolean useEllipsisSymbol) { + return shortenTextWithEllipsis(path, maxLength, (int)(maxLength * 0.7), useEllipsisSymbol); } - int len1 = s1.length(); - int len2 = s2.length(); + @NotNull + @Contract(pure = true) + public static String shortenPathWithEllipsis(@NotNull final String path, final int maxLength) { + return shortenPathWithEllipsis(path, maxLength, false); + } - int index1 = 0; - int index2 = 0; - while (index1 < len1 && index2 < len2) { - if (s1.charAt(index1) == s2.charAt(index2)) { - index1++; - index2++; - continue; - } + @Contract(pure = true) + public static boolean charsEqualIgnoreCase(char a, char b) { + return charsMatch(a, b, true); + } - boolean skipped = false; - while (index1 != len1 && isWhiteSpace(s1.charAt(index1))) { - skipped = true; - index1++; - } - while (index2 != len2 && isWhiteSpace(s2.charAt(index2))) { - skipped = true; - index2++; - } - - if (!skipped) return false; - } - - for (; index1 != len1; index1++) { - if (!isWhiteSpace(s1.charAt(index1))) return false; - } - for (; index2 != len2; index2++) { - if (!isWhiteSpace(s2.charAt(index2))) return false; - } - - return true; - } - - @Contract(pure = true) - public static boolean equalsTrimWhitespaces(@NotNull CharSequence s1, @NotNull CharSequence s2) { - int start1 = 0; - int end1 = s1.length(); - int end2 = s2.length(); - - while (start1 < end1) { - char c = s1.charAt(start1); - if (!isWhiteSpace(c)) break; - start1++; - } - - while (start1 < end1) { - char c = s1.charAt(end1 - 1); - if (!isWhiteSpace(c)) break; - end1--; - } - - int start2 = 0; - while (start2 < end2) { - char c = s2.charAt(start2); - if (!isWhiteSpace(c)) break; - start2++; - } - - while (start2 < end2) { - char c = s2.charAt(end2 - 1); - if (!isWhiteSpace(c)) break; - end2--; - } - - CharSequence ts1 = new CharSequenceSubSequence(s1, start1, end1); - CharSequence ts2 = new CharSequenceSubSequence(s2, start2, end2); - - return equals(ts1, ts2); - } - - /** - * Collapses all white-space (including new lines) between non-white-space characters to a single space character. - * Leading and trailing white space is removed. - */ - public static String collapseWhiteSpace(@NotNull CharSequence s) { - final StringBuilder result = new StringBuilder(); - boolean space = false; - for (int i = 0, length = s.length(); i < length; i++) { - final char ch = s.charAt(i); - if (isWhiteSpace(ch)) { - if (!space) space = true; - } - else { - if (space && result.length() > 0) result.append(' '); - result.append(ch); - space = false; - } - } - return result.toString(); - } - - @Contract(pure = true) - public static boolean findIgnoreCase(@Nullable String toFind, @NotNull String... where) { - for (String string : where) { - if (equalsIgnoreCase(toFind, string)) return true; - } - return false; - } - - @Contract(pure = true) - public static int compare(char c1, char c2, boolean ignoreCase) { - // duplicating String.equalsIgnoreCase logic - int d = c1 - c2; - if (d == 0 || !ignoreCase) { - return d; - } - // If characters don't match but case may be ignored, - // try converting both characters to uppercase. - // If the results match, then the comparison scan should - // continue. - char u1 = StringUtilRt.toUpperCase(c1); - char u2 = StringUtilRt.toUpperCase(c2); - d = u1 - u2; - if (d != 0) { - // Unfortunately, conversion to uppercase does not work properly - // for the Georgian alphabet, which has strange rules about case - // conversion. So we need to make one last check before - // exiting. - d = StringUtilRt.toLowerCase(u1) - StringUtilRt.toLowerCase(u2); - } - return d; - } - - @Contract(pure = true) - public static boolean charsMatch(char c1, char c2, boolean ignoreCase) { - return compare(c1, c2, ignoreCase) == 0; - } - - @NotNull - @Contract(pure = true) - public static String formatLinks(@NotNull String message) { - Pattern linkPattern = Pattern.compile("http://[a-zA-Z0-9./\\-+]+"); - StringBuffer result = new StringBuffer(); - Matcher m = linkPattern.matcher(message); - while (m.find()) { - m.appendReplacement(result, "" + m.group() + ""); - } - m.appendTail(result); - return result.toString(); - } - - @Contract(pure = true) - public static boolean isHexDigit(char c) { - return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'; - } - - @Contract(pure = true) - public static boolean isOctalDigit(char c) { - return '0' <= c && c <= '7'; - } - - @NotNull - @Contract(pure = true) - public static String shortenTextWithEllipsis(@NotNull final String text, final int maxLength, final int suffixLength) { - return shortenTextWithEllipsis(text, maxLength, suffixLength, false); - } - - @NotNull - @Contract(pure = true) - public static String trimMiddle(@NotNull String text, int maxLength) { - return shortenTextWithEllipsis(text, maxLength, maxLength >> 1, true); - } - - @NotNull - @Contract(pure = true) - public static String shortenTextWithEllipsis(@NotNull final String text, - final int maxLength, - final int suffixLength, - @NotNull String symbol) { - final int textLength = text.length(); - if (textLength > maxLength) { - final int prefixLength = maxLength - suffixLength - symbol.length(); - assert prefixLength > 0; - return text.substring(0, prefixLength) + symbol + text.substring(textLength - suffixLength); - } - else { - return text; - } - } - - @NotNull - @Contract(pure = true) - public static String shortenTextWithEllipsis(@NotNull final String text, - final int maxLength, - final int suffixLength, - boolean useEllipsisSymbol) { - String symbol = useEllipsisSymbol ? "\u2026" : "..."; - return shortenTextWithEllipsis(text, maxLength, suffixLength, symbol); - } - - @NotNull - @Contract(pure = true) - public static String shortenPathWithEllipsis(@NotNull final String path, final int maxLength, boolean useEllipsisSymbol) { - return shortenTextWithEllipsis(path, maxLength, (int)(maxLength * 0.7), useEllipsisSymbol); - } - - @NotNull - @Contract(pure = true) - public static String shortenPathWithEllipsis(@NotNull final String path, final int maxLength) { - return shortenPathWithEllipsis(path, maxLength, false); - } - - @Contract(pure = true) - public static boolean charsEqualIgnoreCase(char a, char b) { - return charsMatch(a, b, true); - } - - @Contract(pure = true) - public static char toUpperCase(char a) { - return StringUtilRt.toUpperCase(a); - } + @Contract(pure = true) + public static char toUpperCase(char a) { + return StringUtilRt.toUpperCase(a); + } @Contract(value = "null -> null; !null -> !null", pure = true) public static String toUpperCase(String a) { if (a == null) return null; - + StringBuilder answer = null; for (int i = 0; i < a.length(); i++) { char c = a.charAt(i); @@ -3050,300 +3055,300 @@ public static String toUpperCase(String a) { } } return answer == null ? a : answer.toString(); - } - - @Contract(pure = true) - public static char toLowerCase(final char a) { - return StringUtilRt.toLowerCase(a); - } - - @Contract(pure = true) - public static boolean isUpperCase(@NotNull CharSequence sequence) { - for (int i = 0; i < sequence.length(); i++) { - if (!Character.isUpperCase(sequence.charAt(i))) return false; - } - return true; - } - - @Nullable - public static LineSeparator detectSeparators(@NotNull CharSequence text) { - int index = indexOfAny(text, "\n\r"); - if (index == -1) return null; - LineSeparator lineSeparator = getLineSeparatorAt(text, index); - if (lineSeparator == null) { - throw new AssertionError(); - } - return lineSeparator; - } - - @Nullable - public static LineSeparator getLineSeparatorAt(@NotNull CharSequence text, int index) { - if (index < 0 || index >= text.length()) { - return null; - } - char ch = text.charAt(index); - if (ch == '\r') { - return index + 1 < text.length() && text.charAt(index + 1) == '\n' ? LineSeparator.CRLF : LineSeparator.CR; - } - return ch == '\n' ? LineSeparator.LF : null; - } - - @NotNull - @Contract(pure = true) - public static String convertLineSeparators(@NotNull String text) { - return StringUtilRt.convertLineSeparators(text); - } - - @NotNull - @Contract(pure = true) - public static String convertLineSeparators(@NotNull String text, boolean keepCarriageReturn) { - return StringUtilRt.convertLineSeparators(text, keepCarriageReturn); - } - - @NotNull - @Contract(pure = true) - public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator) { - return StringUtilRt.convertLineSeparators(text, newSeparator); - } - - @NotNull - public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator, @Nullable int[] offsetsToKeep) { - return StringUtilRt.convertLineSeparators(text, newSeparator, offsetsToKeep); - } - - @Contract(pure = true) - public static int parseInt(@Nullable String string, int defaultValue) { - return StringUtilRt.parseInt(string, defaultValue); - } - - @NotNull - @Contract(pure = true) - public static String getShortName(@NotNull String fqName) { - return StringUtilRt.getShortName(fqName); - } - - @NotNull - @Contract(pure = true) - public static String getShortName(@NotNull String fqName, char separator) { - return StringUtilRt.getShortName(fqName, separator); - } - - /** - * Equivalent for {@code getShortName(fqName).equals(shortName)}, but could be faster. - * - * @param fqName fully-qualified name (dot-separated) - * @param shortName a short name, must not contain dots - * @return true if specified short name is a short name of fully-qualified name - */ - public static boolean isShortNameOf(@NotNull String fqName, @NotNull String shortName) { - if (fqName.length() < shortName.length()) return false; - if (fqName.length() == shortName.length()) return fqName.equals(shortName); - int diff = fqName.length() - shortName.length(); - if (fqName.charAt(diff - 1) != '.') return false; - return fqName.regionMatches(diff, shortName, 0, shortName.length()); - } - - /** - * Strips class name from Object#toString if present. - * To be used as custom data type renderer for java.lang.Object. - * To activate just add {@code StringUtil.toShortString(this)} - * expression in Settings | Debugger | Data Views. - */ - @Contract("null->null;!null->!null") - @SuppressWarnings("UnusedDeclaration") - static String toShortString(@Nullable Object o) { - if (o == null) return null; - if (o instanceof CharSequence) return o.toString(); - String className = o.getClass().getName(); - String s = o.toString(); - if (!s.startsWith(className)) return s; - return s.length() > className.length() && !Character.isLetter(s.charAt(className.length())) ? - trimStart(s, className) : s; - } - - @NotNull - @Contract(pure = true) - public static CharSequence newBombedCharSequence(@NotNull CharSequence sequence, long delay) { - final long myTime = System.currentTimeMillis() + delay; - return new BombedCharSequence(sequence) { - @Override - protected void checkCanceled() { - long l = System.currentTimeMillis(); - if (l >= myTime) { - throw new ProcessCanceledException(); - } - } - }; - } - - public static boolean trimEnd(@NotNull StringBuilder buffer, @NotNull CharSequence end) { - if (endsWith(buffer, end)) { - buffer.delete(buffer.length() - end.length(), buffer.length()); - return true; - } - return false; - } - - /** - * Say smallPart = "op" and bigPart="open". Method returns true for "Ope" and false for "ops" - */ - @Contract(pure = true) - @SuppressWarnings("StringToUpperCaseOrToLowerCaseWithoutLocale") - public static boolean isBetween(@NotNull String string, @NotNull String smallPart, @NotNull String bigPart) { - final String s = string.toLowerCase(); - return s.startsWith(smallPart.toLowerCase()) && bigPart.toLowerCase().startsWith(s); - } - - /** - * Does the string have an uppercase character? - * @param s the string to test. - * @return true if the string has an uppercase character, false if not. - */ - public static boolean hasUpperCaseChar(String s) { - char[] chars = s.toCharArray(); - for (char c : chars) { - if (Character.isUpperCase(c)) { - return true; - } - } - return false; - } - - /** - * Does the string have a lowercase character? - * @param s the string to test. - * @return true if the string has a lowercase character, false if not. - */ - public static boolean hasLowerCaseChar(String s) { - char[] chars = s.toCharArray(); - for (char c : chars) { - if (Character.isLowerCase(c)) { - return true; - } - } - return false; - } - - private static final Pattern UNICODE_CHAR = Pattern.compile("\\\\u[0-9a-fA-F]{4}"); - - public static String replaceUnicodeEscapeSequences(String text) { - if (text == null) return null; - - final Matcher matcher = UNICODE_CHAR.matcher(text); - if (!matcher.find()) return text; // fast path - - matcher.reset(); - int lastEnd = 0; - final StringBuilder sb = new StringBuilder(text.length()); - while (matcher.find()) { - sb.append(text, lastEnd, matcher.start()); - final char c = (char)Integer.parseInt(matcher.group().substring(2), 16); - sb.append(c); - lastEnd = matcher.end(); - } - sb.append(text.substring(lastEnd)); - return sb.toString(); - } - - /** - * Expirable CharSequence. Very useful to control external library execution time, - * i.e. when java.util.regex.Pattern match goes out of control. - */ - public abstract static class BombedCharSequence implements CharSequence { - private final CharSequence delegate; - private int i; - private boolean myDefused; - - public BombedCharSequence(@NotNull CharSequence sequence) { - delegate = sequence; - } - - @Override - public int length() { - check(); - return delegate.length(); - } - - @Override - public char charAt(int i) { - check(); - return delegate.charAt(i); - } - - protected void check() { - if (myDefused) { - return; - } - if ((++i & 1023) == 0) { - checkCanceled(); - } - } - - public final void defuse() { - myDefused = true; - } - - @NotNull - @Override - public String toString() { - check(); - return delegate.toString(); - } - - protected abstract void checkCanceled(); - - @NotNull - @Override - public CharSequence subSequence(int i, int i1) { - check(); - return delegate.subSequence(i, i1); - } - } - - @Contract(pure = true) - @NotNull - public static String toHexString(@NotNull byte[] bytes) { - @SuppressWarnings("SpellCheckingInspection") String digits = "0123456789abcdef"; - StringBuilder sb = new StringBuilder(2 * bytes.length); - for (byte b : bytes) sb.append(digits.charAt((b >> 4) & 0xf)).append(digits.charAt(b & 0xf)); - return sb.toString(); - } - - @Contract(pure = true) - @NotNull - public static byte[] parseHexString(@NotNull String str) { - int len = str.length(); - if (len % 2 != 0) throw new IllegalArgumentException("Non-even-length: " + str); - byte[] bytes = new byte[len / 2]; - for (int i = 0; i < len; i += 2) { - bytes[i / 2] = (byte)((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16)); - } - return bytes; - } - - /** @deprecated use {@link #startsWithConcatenation(String, String...)} (to remove in IDEA 15) */ - @Deprecated - public static boolean startsWithConcatenationOf(@NotNull String string, @NotNull String firstPrefix, @NotNull String secondPrefix) { - return startsWithConcatenation(string, firstPrefix, secondPrefix); - } - - /** - * @return {@code true} if the passed string is not {@code null} and not empty - * and contains only latin upper- or lower-case characters and digits; {@code false} otherwise. - */ - @Contract(pure = true) - public static boolean isLatinAlphanumeric(@Nullable CharSequence str) { - if (isEmpty(str)) { - return false; - } - for (int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || Character.isDigit(c)) { - continue; - } - return false; - } - return true; - } - + } + + @Contract(pure = true) + public static char toLowerCase(final char a) { + return StringUtilRt.toLowerCase(a); + } + + @Contract(pure = true) + public static boolean isUpperCase(@NotNull CharSequence sequence) { + for (int i = 0; i < sequence.length(); i++) { + if (!Character.isUpperCase(sequence.charAt(i))) return false; + } + return true; + } + + @Nullable + public static LineSeparator detectSeparators(@NotNull CharSequence text) { + int index = indexOfAny(text, "\n\r"); + if (index == -1) return null; + LineSeparator lineSeparator = getLineSeparatorAt(text, index); + if (lineSeparator == null) { + throw new AssertionError(); + } + return lineSeparator; + } + + @Nullable + public static LineSeparator getLineSeparatorAt(@NotNull CharSequence text, int index) { + if (index < 0 || index >= text.length()) { + return null; + } + char ch = text.charAt(index); + if (ch == '\r') { + return index + 1 < text.length() && text.charAt(index + 1) == '\n' ? LineSeparator.CRLF : LineSeparator.CR; + } + return ch == '\n' ? LineSeparator.LF : null; + } + + @NotNull + @Contract(pure = true) + public static String convertLineSeparators(@NotNull String text) { + return StringUtilRt.convertLineSeparators(text); + } + + @NotNull + @Contract(pure = true) + public static String convertLineSeparators(@NotNull String text, boolean keepCarriageReturn) { + return StringUtilRt.convertLineSeparators(text, keepCarriageReturn); + } + + @NotNull + @Contract(pure = true) + public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator) { + return StringUtilRt.convertLineSeparators(text, newSeparator); + } + + @NotNull + public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator, @Nullable int[] offsetsToKeep) { + return StringUtilRt.convertLineSeparators(text, newSeparator, offsetsToKeep); + } + + @Contract(pure = true) + public static int parseInt(@Nullable String string, int defaultValue) { + return StringUtilRt.parseInt(string, defaultValue); + } + + @NotNull + @Contract(pure = true) + public static String getShortName(@NotNull String fqName) { + return StringUtilRt.getShortName(fqName); + } + + @NotNull + @Contract(pure = true) + public static String getShortName(@NotNull String fqName, char separator) { + return StringUtilRt.getShortName(fqName, separator); + } + + /** + * Equivalent for {@code getShortName(fqName).equals(shortName)}, but could be faster. + * + * @param fqName fully-qualified name (dot-separated) + * @param shortName a short name, must not contain dots + * @return true if specified short name is a short name of fully-qualified name + */ + public static boolean isShortNameOf(@NotNull String fqName, @NotNull String shortName) { + if (fqName.length() < shortName.length()) return false; + if (fqName.length() == shortName.length()) return fqName.equals(shortName); + int diff = fqName.length() - shortName.length(); + if (fqName.charAt(diff - 1) != '.') return false; + return fqName.regionMatches(diff, shortName, 0, shortName.length()); + } + + /** + * Strips class name from Object#toString if present. + * To be used as custom data type renderer for java.lang.Object. + * To activate just add {@code StringUtil.toShortString(this)} + * expression in Settings | Debugger | Data Views. + */ + @Contract("null->null;!null->!null") + @SuppressWarnings("UnusedDeclaration") + static String toShortString(@Nullable Object o) { + if (o == null) return null; + if (o instanceof CharSequence) return o.toString(); + String className = o.getClass().getName(); + String s = o.toString(); + if (!s.startsWith(className)) return s; + return s.length() > className.length() && !Character.isLetter(s.charAt(className.length())) ? + trimStart(s, className) : s; + } + + @NotNull + @Contract(pure = true) + public static CharSequence newBombedCharSequence(@NotNull CharSequence sequence, long delay) { + final long myTime = System.currentTimeMillis() + delay; + return new BombedCharSequence(sequence) { + @Override + protected void checkCanceled() { + long l = System.currentTimeMillis(); + if (l >= myTime) { + throw new ProcessCanceledException(); + } + } + }; + } + + public static boolean trimEnd(@NotNull StringBuilder buffer, @NotNull CharSequence end) { + if (endsWith(buffer, end)) { + buffer.delete(buffer.length() - end.length(), buffer.length()); + return true; + } + return false; + } + + /** + * Say smallPart = "op" and bigPart="open". Method returns true for "Ope" and false for "ops" + */ + @Contract(pure = true) + @SuppressWarnings("StringToUpperCaseOrToLowerCaseWithoutLocale") + public static boolean isBetween(@NotNull String string, @NotNull String smallPart, @NotNull String bigPart) { + final String s = string.toLowerCase(); + return s.startsWith(smallPart.toLowerCase()) && bigPart.toLowerCase().startsWith(s); + } + + /** + * Does the string have an uppercase character? + * @param s the string to test. + * @return true if the string has an uppercase character, false if not. + */ + public static boolean hasUpperCaseChar(String s) { + char[] chars = s.toCharArray(); + for (char c : chars) { + if (Character.isUpperCase(c)) { + return true; + } + } + return false; + } + + /** + * Does the string have a lowercase character? + * @param s the string to test. + * @return true if the string has a lowercase character, false if not. + */ + public static boolean hasLowerCaseChar(String s) { + char[] chars = s.toCharArray(); + for (char c : chars) { + if (Character.isLowerCase(c)) { + return true; + } + } + return false; + } + + private static final Pattern UNICODE_CHAR = Pattern.compile("\\\\u[0-9a-fA-F]{4}"); + + public static String replaceUnicodeEscapeSequences(String text) { + if (text == null) return null; + + final Matcher matcher = UNICODE_CHAR.matcher(text); + if (!matcher.find()) return text; // fast path + + matcher.reset(); + int lastEnd = 0; + final StringBuilder sb = new StringBuilder(text.length()); + while (matcher.find()) { + sb.append(text, lastEnd, matcher.start()); + final char c = (char)Integer.parseInt(matcher.group().substring(2), 16); + sb.append(c); + lastEnd = matcher.end(); + } + sb.append(text.substring(lastEnd)); + return sb.toString(); + } + + /** + * Expirable CharSequence. Very useful to control external library execution time, + * i.e. when java.util.regex.Pattern match goes out of control. + */ + public abstract static class BombedCharSequence implements CharSequence { + private final CharSequence delegate; + private int i; + private boolean myDefused; + + public BombedCharSequence(@NotNull CharSequence sequence) { + delegate = sequence; + } + + @Override + public int length() { + check(); + return delegate.length(); + } + + @Override + public char charAt(int i) { + check(); + return delegate.charAt(i); + } + + protected void check() { + if (myDefused) { + return; + } + if ((++i & 1023) == 0) { + checkCanceled(); + } + } + + public final void defuse() { + myDefused = true; + } + + @NotNull + @Override + public String toString() { + check(); + return delegate.toString(); + } + + protected abstract void checkCanceled(); + + @NotNull + @Override + public CharSequence subSequence(int i, int i1) { + check(); + return delegate.subSequence(i, i1); + } + } + + @Contract(pure = true) + @NotNull + public static String toHexString(@NotNull byte[] bytes) { + @SuppressWarnings("SpellCheckingInspection") String digits = "0123456789abcdef"; + StringBuilder sb = new StringBuilder(2 * bytes.length); + for (byte b : bytes) sb.append(digits.charAt((b >> 4) & 0xf)).append(digits.charAt(b & 0xf)); + return sb.toString(); + } + + @Contract(pure = true) + @NotNull + public static byte[] parseHexString(@NotNull String str) { + int len = str.length(); + if (len % 2 != 0) throw new IllegalArgumentException("Non-even-length: " + str); + byte[] bytes = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + bytes[i / 2] = (byte)((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16)); + } + return bytes; + } + + /** @deprecated use {@link #startsWithConcatenation(String, String...)} (to remove in IDEA 15) */ + @Deprecated + public static boolean startsWithConcatenationOf(@NotNull String string, @NotNull String firstPrefix, @NotNull String secondPrefix) { + return startsWithConcatenation(string, firstPrefix, secondPrefix); + } + + /** + * @return {@code true} if the passed string is not {@code null} and not empty + * and contains only latin upper- or lower-case characters and digits; {@code false} otherwise. + */ + @Contract(pure = true) + public static boolean isLatinAlphanumeric(@Nullable CharSequence str) { + if (isEmpty(str)) { + return false; + } + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || Character.isDigit(c)) { + continue; + } + return false; + } + return true; + } + } \ No newline at end of file diff --git a/kotlin-bundled-compiler/src/com/intellij/util/ObjectUtils.java b/kotlin-bundled-compiler/src/com/intellij/util/ObjectUtils.java deleted file mode 100644 index 1ba3d7102..000000000 --- a/kotlin-bundled-compiler/src/com/intellij/util/ObjectUtils.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package com.intellij.util; - -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.NotNullFactory; -import com.intellij.util.containers.Convertor; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.reflect.Proxy; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; - -/** - * @author peter - */ -public final class ObjectUtils { - private ObjectUtils() { - } - - /** - * @see NotNullizer - */ - public static final Object NULL = sentinel("ObjectUtils.NULL"); - - /** - * Creates a new object which could be used as sentinel value (special value to distinguish from any other object). It does not equal - * to any other object. Usually should be assigned to the static final field. - * - * @param name an object name, returned from {@link #toString()} to simplify the debugging or heap dump analysis - * (guaranteed to be stored as sentinel object field). If sentinel is assigned to the static final field, - * it's recommended to supply that field name (possibly qualified with the class name). - * @return a new sentinel object - */ - @NotNull - public static Object sentinel(@NotNull @NonNls String name) { - return new Sentinel(name); - } - - /** - * They promise in http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-February/051312.html that - * the object reference won't be removed by JIT and GC-ed until this call. - */ - public static void reachabilityFence(@SuppressWarnings("unused") Object o) {} - - private static final class Sentinel { - private final String myName; - - Sentinel(@NotNull String name) { - myName = name; - } - - @Override - public String toString() { - return myName; - } - } - - /** - * Creates an instance of class {@code ofInterface} with its {@link Object#toString()} method returning {@code name}. - * No other guarantees about return value behaviour. - * {@code ofInterface} must represent an interface class. - * Useful for stubs in generic code, e.g. for storing in {@code List} to represent empty special value. - */ - @NotNull - public static T sentinel(@NotNull final String name, @NotNull Class ofInterface) { - if (!ofInterface.isInterface()) { - throw new IllegalArgumentException("Expected interface but got: " + ofInterface); - } - // java.lang.reflect.Proxy.ProxyClassFactory fails if the class is not available via the classloader. - // We must use interface own classloader because classes from plugins are not available via ObjectUtils' classloader. - //noinspection unchecked - return (T)Proxy.newProxyInstance(ofInterface.getClassLoader(), new Class[]{ofInterface}, (__, method, args) -> { - if ("toString".equals(method.getName()) && args.length == 0) { - return name; - } - throw new AbstractMethodError(); - }); - } - - /** - * @deprecated Use {@link Objects#requireNonNull(Object)} - */ - @Deprecated - public static @NotNull T assertNotNull(@Nullable T t) { - return Objects.requireNonNull(t); - } - - public static void assertAllElementsNotNull(T [] array) { - for (int i = 0; i < array.length; i++) { - T t = array[i]; - if (t == null) { - throw new NullPointerException("Element [" + i + "] is null"); - } - } - } - - @Contract(value = "!null, _ -> !null; _, !null -> !null; null, null -> null", pure = true) - public static T chooseNotNull(@Nullable T t1, @Nullable T t2) { - return t1 == null? t2 : t1; - } - - @Contract(value = "!null, _ -> !null; _, !null -> !null; null, null -> null", pure = true) - public static T coalesce(@Nullable T t1, @Nullable T t2) { - return chooseNotNull(t1, t2); - } - - @Contract(value = "!null, _, _ -> !null; _, !null, _ -> !null; _, _, !null -> !null; null,null,null -> null", pure = true) - public static T coalesce(@Nullable T t1, @Nullable T t2, @Nullable T t3) { - return t1 != null ? t1 : t2 != null ? t2 : t3; - } - - @Nullable - public static T coalesce(@Nullable Iterable o) { - if (o == null) return null; - for (T t : o) { - if (t != null) return t; - } - return null; - } - - /** - * @deprecated Use {@link Objects#requireNonNull(Object)} - */ - @Deprecated - public static T notNull(@Nullable T value) { - return Objects.requireNonNull(value); - } - - @NotNull - @Contract(pure = true) - public static T notNull(@Nullable T value, @NotNull T defaultValue) { - return value == null ? defaultValue : value; - } - - @NotNull - public static T notNull(@Nullable T value, @NotNull NotNullFactory defaultValue) { - return value == null ? defaultValue.create() : value; - } - - @Contract(value = "null, _ -> null", pure = true) - @Nullable - public static T tryCast(@Nullable Object obj, @NotNull Class clazz) { - if (clazz.isInstance(obj)) { - return clazz.cast(obj); - } - return null; - } - - @Nullable - public static S doIfCast(@Nullable Object obj, @NotNull Class clazz, final Convertor convertor) { - if (clazz.isInstance(obj)) { - //noinspection unchecked - return convertor.convert((T)obj); - } - return null; - } - - @Contract("null, _ -> null") - @Nullable - public static S doIfNotNull(@Nullable T obj, @NotNull Function function) { - return obj == null ? null : function.fun(obj); - } - - public static void consumeIfNotNull(@Nullable T obj, @NotNull Consumer consumer) { - if (obj != null) { - consumer.consume(obj); - } - } - - public static void consumeIfCast(@Nullable Object obj, @NotNull Class clazz, final Consumer consumer) { - if (clazz.isInstance(obj)) { - //noinspection unchecked - consumer.consume((T)obj); - } - } - - @Nullable - @Contract("null, _ -> null") - public static T nullizeByCondition(@Nullable final T obj, @NotNull final Condition condition) { - if (condition.value(obj)) { - return null; - } - return obj; - } - - @Nullable - @Contract("null, _ -> null") - public static T nullizeIfDefaultValue(@Nullable T obj, @NotNull T defaultValue) { - if (obj == defaultValue) { - return null; - } - return obj; - } - - /** - * Performs binary search on the range [fromIndex, toIndex) - * @param indexComparator a comparator which receives a middle index and returns the result of comparision of the value at this index and the goal value - * (e.g 0 if found, -1 if the value[middleIndex] < goal, or 1 if value[middleIndex] > goal) - * @return index for which {@code indexComparator} returned 0 or {@code -insertionIndex-1} if wasn't found - * @see java.util.Arrays#binarySearch(Object[], Object, Comparator) - * @see java.util.Collections#binarySearch(List, Object, Comparator) - */ - public static int binarySearch(int fromIndex, int toIndex, @NotNull IntIntFunction indexComparator) { - int low = fromIndex; - int high = toIndex - 1; - while (low <= high) { - int mid = (low + high) >>> 1; - int cmp = indexComparator.fun(mid); - if (cmp < 0) low = mid + 1; - else if (cmp > 0) high = mid - 1; - else return mid; - } - return -(low + 1); - } -} diff --git a/kotlin-bundled-compiler/src/com/intellij/util/containers/ContainerUtil.java b/kotlin-bundled-compiler/src/com/intellij/util/containers/ContainerUtil.java deleted file mode 100644 index 01a7e69b3..000000000 --- a/kotlin-bundled-compiler/src/com/intellij/util/containers/ContainerUtil.java +++ /dev/null @@ -1,3014 +0,0 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package com.intellij.util.containers; - -import com.intellij.openapi.Disposable; -import com.intellij.openapi.util.*; -import com.intellij.util.*; -import gnu.trove.*; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.reflect.Array; -import java.util.HashMap; -import java.util.HashSet; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CopyOnWriteArrayList; - -@SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass"}) -public class ContainerUtil extends ContainerUtilRt { - private static final int INSERTION_SORT_THRESHOLD = 10; - - @NotNull - @Contract(pure=true) - public static T[] ar(@NotNull T... elements) { - return elements; - } - - @NotNull - @Contract(pure=true) - public static HashMap newHashMap() { - return ContainerUtilRt.newHashMap(); - } - - @NotNull - @Contract(pure=true) - public static HashMap newHashMap(@NotNull Map map) { - return ContainerUtilRt.newHashMap(map); - } - - @NotNull - @Contract(pure=true) - public static Map newHashMap(@NotNull Pair first, @NotNull Pair... entries) { - return ContainerUtilRt.newHashMap(first, entries); - } - - @NotNull - @Contract(pure=true) - public static Map newHashMap(@NotNull List keys, @NotNull List values) { - return ContainerUtilRt.newHashMap(keys, values); - } - - @NotNull - @Contract(pure=true) - public static TreeMap newTreeMap() { - return ContainerUtilRt.newTreeMap(); - } - - @NotNull - @Contract(pure=true) - public static TreeMap newTreeMap(@NotNull Map map) { - return ContainerUtilRt.newTreeMap(map); - } - - @NotNull - @Contract(pure=true) - public static LinkedHashMap newLinkedHashMap() { - return ContainerUtilRt.newLinkedHashMap(); - } - - @NotNull - @Contract(pure=true) - public static LinkedHashMap newLinkedHashMap(int capacity) { - return ContainerUtilRt.newLinkedHashMap(capacity); - } - - @NotNull - @Contract(pure=true) - public static LinkedHashMap newLinkedHashMap(@NotNull Map map) { - return ContainerUtilRt.newLinkedHashMap(map); - } - - @NotNull - @Contract(pure=true) - public static LinkedHashMap newLinkedHashMap(@NotNull Pair first, @NotNull Pair... entries) { - return ContainerUtilRt.newLinkedHashMap(first, entries); - } - - @NotNull - @Contract(pure=true) - public static THashMap newTroveMap() { - return new THashMap(); - } - - @NotNull - @Contract(pure=true) - public static THashMap newTroveMap(@NotNull TObjectHashingStrategy strategy) { - return new THashMap(strategy); - } - - @NotNull - @Contract(pure=true) - public static , V> EnumMap newEnumMap(@NotNull Class keyType) { - return new EnumMap(keyType); - } - - @SuppressWarnings("unchecked") - @NotNull - @Contract(pure=true) - public static TObjectHashingStrategy canonicalStrategy() { - return TObjectHashingStrategy.CANONICAL; - } - - @SuppressWarnings("unchecked") - @NotNull - @Contract(pure=true) - public static TObjectHashingStrategy identityStrategy() { - return TObjectHashingStrategy.IDENTITY; - } - - @NotNull - @Contract(pure=true) - public static IdentityHashMap newIdentityHashMap() { - return new IdentityHashMap(); - } - - @NotNull - @Contract(pure=true) - public static LinkedList newLinkedList() { - return ContainerUtilRt.newLinkedList(); - } - - @NotNull - @Contract(pure=true) - public static LinkedList newLinkedList(@NotNull T... elements) { - return ContainerUtilRt.newLinkedList(elements); - } - - @NotNull - @Contract(pure=true) - public static LinkedList newLinkedList(@NotNull Iterable elements) { - return ContainerUtilRt.newLinkedList(elements); - } - - @NotNull - @Contract(pure=true) - public static ArrayList newArrayList() { - return ContainerUtilRt.newArrayList(); - } - - @NotNull - @Contract(pure=true) - public static ArrayList newArrayList(@NotNull E... array) { - return ContainerUtilRt.newArrayList(array); - } - - @NotNull - @Contract(pure=true) - public static ArrayList newArrayList(@NotNull Iterable iterable) { - return ContainerUtilRt.newArrayList(iterable); - } - - @NotNull - @Contract(pure=true) - public static ArrayList newArrayListWithCapacity(int size) { - return ContainerUtilRt.newArrayListWithCapacity(size); - } - - @NotNull - @Contract(pure=true) - public static List newArrayList(@NotNull final T[] elements, final int start, final int end) { - if (start < 0 || start > end || end > elements.length) { - throw new IllegalArgumentException("start:" + start + " end:" + end + " length:" + elements.length); - } - - return new AbstractList() { - private final int size = end - start; - - @Override - public T get(final int index) { - if (index < 0 || index >= size) throw new IndexOutOfBoundsException("index:" + index + " size:" + size); - return elements[start + index]; - } - - @Override - public int size() { - return size; - } - }; - } - - @NotNull - @Contract(pure = true) - public static List newUnmodifiableList(List originalList) { - int size = originalList.size(); - if (size == 0) { - return emptyList(); - } - else if (size == 1) { - return Collections.singletonList(originalList.get(0)); - } - else { - return Collections.unmodifiableList(newArrayList(originalList)); - } - } - - @NotNull - @Contract(pure = true) - public static Collection unmodifiableOrEmptyCollection(@NotNull Collection original) { - int size = original.size(); - if (size == 0) { - return emptyList(); - } - if (size == 1) { - return Collections.singletonList(original.iterator().next()); - } - else { - return Collections.unmodifiableCollection(original); - } - } - - @NotNull - @Contract(pure = true) - public static List unmodifiableOrEmptyList(@NotNull List original) { - int size = original.size(); - if (size == 0) { - return emptyList(); - } - if (size == 1) { - return Collections.singletonList(original.iterator().next()); - } - else { - return Collections.unmodifiableList(original); - } - } - - @NotNull - @Contract(pure = true) - public static Set unmodifiableOrEmptySet(@NotNull Set original) { - int size = original.size(); - if (size == 0) { - return Collections.emptySet(); - } - if (size == 1) { - return Collections.singleton(original.iterator().next()); - } - else { - return Collections.unmodifiableSet(original); - } - } - - @NotNull - @Contract(pure = true) - public static Map unmodifiableOrEmptyMap(@NotNull Map original) { - int size = original.size(); - if (size == 0) { - return Collections.emptyMap(); - } - if (size == 1) { - Map.Entry entry = original.entrySet().iterator().next(); - return Collections.singletonMap(entry.getKey(), entry.getValue()); - } - else { - return Collections.unmodifiableMap(original); - } - } - - @NotNull - @Contract(pure=true) - public static List newSmartList() { - return new SmartList(); - } - - @NotNull - @Contract(pure=true) - public static List newSmartList(T element) { - return new SmartList(element); - } - - @NotNull - @Contract(pure=true) - public static List newSmartList(@NotNull T... elements) { - return new SmartList(elements); - } - - @NotNull - @Contract(pure=true) - public static HashSet newHashSet() { - return ContainerUtilRt.newHashSet(); - } - - @NotNull - @Contract(pure=true) - public static HashSet newHashSet(int initialCapacity) { - return ContainerUtilRt.newHashSet(initialCapacity); - } - - @NotNull - @Contract(pure=true) - public static HashSet newHashSet(@NotNull T... elements) { - return ContainerUtilRt.newHashSet(elements); - } - - @NotNull - @Contract(pure=true) - public static HashSet newHashSet(@NotNull Iterable iterable) { - return ContainerUtilRt.newHashSet(iterable); - } - - @NotNull - public static HashSet newHashSet(@NotNull Iterator iterator) { - return ContainerUtilRt.newHashSet(iterator); - } - - @NotNull - @Contract(pure=true) - public static Set newHashOrEmptySet(@Nullable Iterable iterable) { - boolean empty = iterable == null || iterable instanceof Collection && ((Collection)iterable).isEmpty(); - return empty ? Collections.emptySet() : ContainerUtilRt.newHashSet(iterable); - } - - @NotNull - @Contract(pure=true) - public static LinkedHashSet newLinkedHashSet() { - return ContainerUtilRt.newLinkedHashSet(); - } - - @NotNull - @Contract(pure=true) - public static LinkedHashSet newLinkedHashSet(@NotNull Iterable elements) { - return ContainerUtilRt.newLinkedHashSet(elements); - } - - @NotNull - @Contract(pure=true) - public static LinkedHashSet newLinkedHashSet(@NotNull T... elements) { - return ContainerUtilRt.newLinkedHashSet(elements); - } - - @NotNull - @Contract(pure=true) - public static THashSet newTroveSet() { - return new THashSet(); - } - - @NotNull - @Contract(pure=true) - public static THashSet newTroveSet(@NotNull TObjectHashingStrategy strategy) { - return new THashSet(strategy); - } - - @NotNull - @Contract(pure=true) - public static THashSet newTroveSet(@NotNull T... elements) { - return newTroveSet(Arrays.asList(elements)); - } - - @NotNull - @Contract(pure=true) - public static THashSet newTroveSet(@NotNull TObjectHashingStrategy strategy, @NotNull T... elements) { - return new THashSet(Arrays.asList(elements), strategy); - } - - @NotNull - @Contract(pure=true) - public static THashSet newTroveSet(@NotNull TObjectHashingStrategy strategy, @NotNull Collection elements) { - return new THashSet(elements, strategy); - } - - @NotNull - @Contract(pure=true) - public static THashSet newTroveSet(@NotNull Collection elements) { - return new THashSet(elements); - } - - @NotNull - @Contract(pure=true) - public static THashSet newIdentityTroveSet() { - return new THashSet(ContainerUtil.identityStrategy()); - } - - @NotNull - @Contract(pure=true) - public static THashSet newIdentityTroveSet(int initialCapacity) { - return new THashSet(initialCapacity, ContainerUtil.identityStrategy()); - } - @NotNull - @Contract(pure=true) - public static THashSet newIdentityTroveSet(@NotNull Collection collection) { - return new THashSet(collection, ContainerUtil.identityStrategy()); - } - - @NotNull - @Contract(pure=true) - public static THashMap newIdentityTroveMap() { - return new THashMap(ContainerUtil.identityStrategy()); - } - - @NotNull - @Contract(pure=true) - public static TreeSet newTreeSet() { - return ContainerUtilRt.newTreeSet(); - } - - @NotNull - @Contract(pure=true) - public static TreeSet newTreeSet(@NotNull Iterable elements) { - return ContainerUtilRt.newTreeSet(elements); - } - - @NotNull - @Contract(pure=true) - public static TreeSet newTreeSet(@NotNull T... elements) { - return ContainerUtilRt.newTreeSet(elements); - } - - @NotNull - @Contract(pure=true) - public static TreeSet newTreeSet(@Nullable Comparator comparator) { - return ContainerUtilRt.newTreeSet(comparator); - } - - @NotNull - @Contract(pure=true) - public static Set newConcurrentSet() { - return Collections.newSetFromMap(ContainerUtil.newConcurrentMap()); - } - - @NotNull - @Contract(pure=true) - public static ConcurrentMap newConcurrentMap() { - return new ConcurrentHashMap(); - } - - @Contract(pure=true) - public static ConcurrentMap newConcurrentMap(int initialCapacity) { - return new ConcurrentHashMap(initialCapacity); - } - - @Contract(pure=true) - public static ConcurrentMap newConcurrentMap(int initialCapacity, float loadFactor, int concurrencyLevel) { - return new ConcurrentHashMap(initialCapacity, loadFactor, concurrencyLevel); - } - - @NotNull - @Contract(pure=true) - public static List reverse(@NotNull final List elements) { - if (elements.isEmpty()) { - return ContainerUtilRt.emptyList(); - } - - return new AbstractList() { - @Override - public E get(int index) { - return elements.get(elements.size() - 1 - index); - } - - @Override - public int size() { - return elements.size(); - } - }; - } - - @NotNull - @Contract(pure=true) - public static Map union(@NotNull Map map, @NotNull Map map2) { - Map result = new THashMap(map.size() + map2.size()); - result.putAll(map); - result.putAll(map2); - return result; - } - - @NotNull - @Contract(pure=true) - public static Set union(@NotNull Set set, @NotNull Set set2) { - return union((Collection)set, set2); - } - - @NotNull - @Contract(pure=true) - public static Set union(@NotNull Collection set, @NotNull Collection set2) { - Set result = new THashSet(set.size() + set2.size()); - result.addAll(set); - result.addAll(set2); - return result; - } - - @NotNull - @Contract(pure=true) - public static Set immutableSet(@NotNull E... elements) { - switch (elements.length) { - case 0: - return Collections.emptySet(); - case 1: - return Collections.singleton(elements[0]); - default: - return Collections.unmodifiableSet(new THashSet(Arrays.asList(elements))); - } - } - - @NotNull - @Contract(pure=true) - public static ImmutableList immutableList(@NotNull E ... array) { - return new ImmutableListBackedByArray(array); - } - - @NotNull - @Contract(pure=true) - public static ImmutableList immutableSingletonList(final E element) { - return ImmutableList.singleton(element); - } - - @NotNull - @Contract(pure=true) - public static ImmutableList immutableList(@NotNull List list) { - return new ImmutableListBackedByList(list); - } - - @NotNull - @Contract(pure=true) - public static ImmutableMapBuilder immutableMapBuilder() { - return new ImmutableMapBuilder(); - } - - @NotNull - @Contract(pure = true) - public static MultiMap groupBy(@NotNull Iterable collection, @NotNull NullableFunction grouper) { - MultiMap result = MultiMap.createLinked(); - for (V data : collection) { - K key = grouper.fun(data); - if (key == null) { - continue; - } - result.putValue(key, data); - } - - if (!result.isEmpty() && result.keySet().iterator().next() instanceof Comparable) { - return new KeyOrderedMultiMap(result); - } - return result; - } - - @Contract(pure = true) - public static T getOrElse(@NotNull List elements, int i, T defaultValue) { - return elements.size() > i ? elements.get(i) : defaultValue; - } - - public static class ImmutableMapBuilder { - private final Map myMap = new THashMap(); - - public ImmutableMapBuilder put(K key, V value) { - myMap.put(key, value); - return this; - } - - @Contract(pure=true) - public Map build() { - return Collections.unmodifiableMap(myMap); - } - } - - private static class ImmutableListBackedByList extends ImmutableList { - private final List myStore; - - private ImmutableListBackedByList(@NotNull List list) { - myStore = list; - } - - @Override - public E get(int index) { - return myStore.get(index); - } - - @Override - public int size() { - return myStore.size(); - } - } - - private static class ImmutableListBackedByArray extends ImmutableList { - private final E[] myStore; - - private ImmutableListBackedByArray(@NotNull E[] array) { - myStore = array; - } - - @Override - public E get(int index) { - return myStore[index]; - } - - @Override - public int size() { - return myStore.length; - } - } - - @NotNull - @Contract(pure=true) - public static Map intersection(@NotNull Map map1, @NotNull Map map2) { - final Map res = newHashMap(); - final Set keys = newHashSet(); - keys.addAll(map1.keySet()); - keys.addAll(map2.keySet()); - for (K k : keys) { - V v1 = map1.get(k); - V v2 = map2.get(k); - if (v1 == v2 || v1 != null && v1.equals(v2)) { - res.put(k, v1); - } - } - return res; - } - - @NotNull - @Contract(pure=true) - public static Map> diff(@NotNull Map map1, @NotNull Map map2) { - final Map> res = newHashMap(); - final Set keys = newHashSet(); - keys.addAll(map1.keySet()); - keys.addAll(map2.keySet()); - for (K k : keys) { - V v1 = map1.get(k); - V v2 = map2.get(k); - if (!(v1 == v2 || v1 != null && v1.equals(v2))) { - res.put(k, Couple.of(v1, v2)); - } - } - return res; - } - - public static void processSortedListsInOrder(@NotNull List list1, - @NotNull List list2, - @NotNull Comparator comparator, - boolean mergeEqualItems, - @NotNull Consumer processor) { - int index1 = 0; - int index2 = 0; - while (index1 < list1.size() || index2 < list2.size()) { - T e; - if (index1 >= list1.size()) { - e = list2.get(index2++); - } - else if (index2 >= list2.size()) { - e = list1.get(index1++); - } - else { - T element1 = list1.get(index1); - T element2 = list2.get(index2); - int c = comparator.compare(element1, element2); - if (c == 0) { - index1++; - index2++; - if (mergeEqualItems) { - e = element1; - } - else { - processor.consume(element1); - e = element2; - } - } - else if (c < 0) { - e = element1; - index1++; - } - else { - e = element2; - index2++; - } - } - processor.consume(e); - } - } - - @NotNull - @Contract(pure=true) - public static List mergeSortedLists(@NotNull List list1, - @NotNull List list2, - @NotNull Comparator comparator, - boolean mergeEqualItems) { - final List result = new ArrayList(list1.size() + list2.size()); - processSortedListsInOrder(list1, list2, comparator, mergeEqualItems, new Consumer() { - @Override - public void consume(T t) { - result.add(t); - } - }); - return result; - } - - @NotNull - @Contract(pure=true) - public static List subList(@NotNull List list, int from) { - return list.subList(from, list.size()); - } - - public static void addAll(@NotNull Collection collection, @NotNull Iterable appendix) { - addAll(collection, appendix.iterator()); - } - - public static void addAll(@NotNull Collection collection, @NotNull Iterator iterator) { - while (iterator.hasNext()) { - T o = iterator.next(); - collection.add(o); - } - } - - /** - * Adds all not-null elements from the {@code elements}, ignoring nulls - */ - public static void addAllNotNull(@NotNull Collection collection, @NotNull Iterable elements) { - addAllNotNull(collection, elements.iterator()); - } - - /** - * Adds all not-null elements from the {@code elements}, ignoring nulls - */ - public static void addAllNotNull(@NotNull Collection collection, @NotNull Iterator elements) { - while (elements.hasNext()) { - T o = elements.next(); - if (o != null) { - collection.add(o); - } - } - } - - @NotNull - public static List collect(@NotNull Iterator iterator) { - if (!iterator.hasNext()) return emptyList(); - List list = new ArrayList(); - addAll(list, iterator); - return list; - } - - @NotNull - public static Set collectSet(@NotNull Iterator iterator) { - if (!iterator.hasNext()) return Collections.emptySet(); - Set hashSet = newHashSet(); - addAll(hashSet, iterator); - return hashSet; - } - - @NotNull - @Contract(pure = true) - public static Map newMapFromKeys(@NotNull Iterator keys, @NotNull Convertor valueConvertor) { - Map map = newHashMap(); - while (keys.hasNext()) { - K key = keys.next(); - map.put(key, valueConvertor.convert(key)); - } - return map; - } - - @NotNull - @Contract(pure = true) - public static Map newMapFromValues(@NotNull Iterator values, @NotNull Convertor keyConvertor) { - Map map = newHashMap(); - fillMapWithValues(map, values, keyConvertor); - return map; - } - - public static void fillMapWithValues(@NotNull Map map, - @NotNull Iterator values, - @NotNull Convertor keyConvertor) { - while (values.hasNext()) { - V value = values.next(); - map.put(keyConvertor.convert(value), value); - } - } - - @NotNull - @Contract(pure = true) - public static Map> classify(@NotNull Iterator iterator, @NotNull Convertor keyConvertor) { - Map> hashMap = new LinkedHashMap>(); - while (iterator.hasNext()) { - V value = iterator.next(); - final K key = keyConvertor.convert(value); - Set set = hashMap.get(key); - if (set == null) { - hashMap.put(key, set = new LinkedHashSet()); // ordered set!! - } - set.add(value); - } - return hashMap; - } - - @NotNull - @Contract(pure=true) - public static Iterator emptyIterator() { - return EmptyIterator.getInstance(); - } - - @NotNull - @Contract(pure=true) - public static Iterable emptyIterable() { - return EmptyIterable.getInstance(); - } - - @Nullable - @Contract(pure=true) - public static T find(@NotNull T[] array, @NotNull Condition condition) { - for (T element : array) { - if (condition.value(element)) return element; - } - return null; - } - - public static boolean process(@NotNull Iterable iterable, @NotNull Processor processor) { - for (final T t : iterable) { - if (!processor.process(t)) { - return false; - } - } - return true; - } - - public static boolean process(@NotNull List list, @NotNull Processor processor) { - //noinspection ForLoopReplaceableByForEach - for (int i = 0, size = list.size(); i < size; i++) { - T t = list.get(i); - if (!processor.process(t)) { - return false; - } - } - return true; - } - - public static boolean process(@NotNull T[] iterable, @NotNull Processor processor) { - for (final T t : iterable) { - if (!processor.process(t)) { - return false; - } - } - return true; - } - - public static boolean process(@NotNull Iterator iterator, @NotNull Processor processor) { - while (iterator.hasNext()) { - if (!processor.process(iterator.next())) { - return false; - } - } - return true; - } - - @Nullable - @Contract(pure=true) - public static V find(@NotNull Iterable iterable, @NotNull Condition condition) { - return ContainerUtilRt.find(iterable, condition); - } - - @Nullable - @Contract(pure=true) - public static T find(@NotNull Iterable iterable, @NotNull final T equalTo) { - return find(iterable, new Condition() { - @Override - public boolean value(final T object) { - return equalTo == object || equalTo.equals(object); - } - }); - } - - @Nullable - @Contract(pure=true) - public static T find(@NotNull Iterator iterator, @NotNull final T equalTo) { - return find(iterator, new Condition() { - @Override - public boolean value(final T object) { - return equalTo == object || equalTo.equals(object); - } - }); - } - - @Nullable - public static V find(@NotNull Iterator iterator, @NotNull Condition condition) { - return ContainerUtilRt.find(iterator, condition); - } - - @Nullable - @Contract(pure = true) - public static V findLast(@NotNull List list, @NotNull Condition condition) { - int index = lastIndexOf(list, condition); - if (index < 0) return null; - return list.get(index); - } - - @NotNull - @Contract(pure=true) - public static Map map2Map(@NotNull T[] collection, @NotNull Function> mapper) { - return map2Map(Arrays.asList(collection), mapper); - } - - @NotNull - @Contract(pure=true) - public static Map map2Map(@NotNull Collection collection, - @NotNull Function> mapper) { - final Map set = new THashMap(collection.size()); - for (T t : collection) { - Pair pair = mapper.fun(t); - set.put(pair.first, pair.second); - } - return set; - } - - @NotNull - @Contract(pure = true) - public static Map map2MapNotNull(@NotNull T[] collection, - @NotNull Function> mapper) { - return map2MapNotNull(Arrays.asList(collection), mapper); - } - - @NotNull - @Contract(pure = true) - public static Map map2MapNotNull(@NotNull Collection collection, - @NotNull Function> mapper) { - final Map set = new THashMap(collection.size()); - for (T t : collection) { - Pair pair = mapper.fun(t); - if (pair != null) { - set.put(pair.first, pair.second); - } - } - return set; - } - - @NotNull - @Contract(pure=true) - public static Map map2Map(@NotNull Collection> collection) { - final Map result = new THashMap(collection.size()); - for (Pair pair : collection) { - result.put(pair.first, pair.second); - } - return result; - } - - @NotNull - @Contract(pure=true) - public static Object[] map2Array(@NotNull T[] array, @NotNull Function mapper) { - return map2Array(array, Object.class, mapper); - } - - @NotNull - @Contract(pure=true) - public static Object[] map2Array(@NotNull Collection array, @NotNull Function mapper) { - return map2Array(array, Object.class, mapper); - } - - @NotNull - @Contract(pure=true) - public static V[] map2Array(@NotNull T[] array, @NotNull Class aClass, @NotNull Function mapper) { - return map2Array(Arrays.asList(array), aClass, mapper); - } - - @NotNull - @Contract(pure=true) - public static V[] map2Array(@NotNull Collection collection, @NotNull Class aClass, @NotNull Function mapper) { - final List list = map2List(collection, mapper); - @SuppressWarnings("unchecked") V[] array = (V[])Array.newInstance(aClass, list.size()); - return list.toArray(array); - } - - @NotNull - @Contract(pure=true) - public static V[] map2Array(@NotNull Collection collection, @NotNull V[] to, @NotNull Function mapper) { - return map2List(collection, mapper).toArray(to); - } - - @NotNull - @Contract(pure=true) - public static List filter(@NotNull T[] collection, @NotNull Condition condition) { - return findAll(collection, condition); - } - - @NotNull - @Contract(pure=true) - public static int[] filter(@NotNull int[] collection, @NotNull TIntProcedure condition) { - TIntArrayList result = new TIntArrayList(); - for (int t : collection) { - if (condition.execute(t)) { - result.add(t); - } - } - return result.isEmpty() ? ArrayUtil.EMPTY_INT_ARRAY : result.toNativeArray(); - } - - @NotNull - @Contract(pure=true) - public static List findAll(@NotNull T[] collection, @NotNull Condition condition) { - final List result = new SmartList(); - for (T t : collection) { - if (condition.value(t)) { - result.add(t); - } - } - return result; - } - - @NotNull - @Contract(pure=true) - public static List filter(@NotNull Collection collection, @NotNull Condition condition) { - return findAll(collection, condition); - } - - @NotNull - @Contract(pure = true) - public static Map filter(@NotNull Map map, @NotNull Condition keyFilter) { - Map result = newHashMap(); - for (Map.Entry entry : map.entrySet()) { - if (keyFilter.value(entry.getKey())) { - result.put(entry.getKey(), entry.getValue()); - } - } - return result; - } - - @NotNull - @Contract(pure=true) - public static List findAll(@NotNull Collection collection, @NotNull Condition condition) { - if (collection.isEmpty()) return emptyList(); - final List result = new SmartList(); - for (final T t : collection) { - if (condition.value(t)) { - result.add(t); - } - } - return result; - } - - @NotNull - @Contract(pure=true) - public static List skipNulls(@NotNull Collection collection) { - return findAll(collection, Condition.NOT_NULL); - } - - @NotNull - @Contract(pure=true) - public static List findAll(@NotNull T[] collection, @NotNull Class instanceOf) { - return findAll(Arrays.asList(collection), instanceOf); - } - - @NotNull - @Contract(pure=true) - public static V[] findAllAsArray(@NotNull T[] collection, @NotNull Class instanceOf) { - List list = findAll(Arrays.asList(collection), instanceOf); - @SuppressWarnings("unchecked") V[] array = (V[])Array.newInstance(instanceOf, list.size()); - return list.toArray(array); - } - - @NotNull - @Contract(pure=true) - public static V[] findAllAsArray(@NotNull Collection collection, @NotNull Class instanceOf) { - List list = findAll(collection, instanceOf); - @SuppressWarnings("unchecked") V[] array = (V[])Array.newInstance(instanceOf, list.size()); - return list.toArray(array); - } - - @NotNull - @Contract(pure=true) - public static T[] findAllAsArray(@NotNull T[] collection, @NotNull Condition instanceOf) { - List list = findAll(collection, instanceOf); - if (list.size() == collection.length) { - return collection; - } - @SuppressWarnings("unchecked") T[] array = (T[])Array.newInstance(collection.getClass().getComponentType(), list.size()); - return list.toArray(array); - } - - @NotNull - @Contract(pure=true) - public static List findAll(@NotNull Collection collection, @NotNull Class instanceOf) { - final List result = new SmartList(); - for (final T t : collection) { - if (instanceOf.isInstance(t)) { - @SuppressWarnings("unchecked") V v = (V)t; - result.add(v); - } - } - return result; - } - - public static boolean all(@NotNull Collection collection, @NotNull Condition condition) { - for (T t : collection) { - if (!condition.value(t)) { - return false; - } - } - return true; - } - - public static void removeDuplicates(@NotNull Collection collection) { - Set collected = newHashSet(); - for (Iterator iterator = collection.iterator(); iterator.hasNext();) { - T t = iterator.next(); - if (!collected.contains(t)) { - collected.add(t); - } - else { - iterator.remove(); - } - } - } - - @NotNull - @Contract(pure=true) - public static Map stringMap(@NotNull final String... keyValues) { - final Map result = newHashMap(); - for (int i = 0; i < keyValues.length - 1; i+=2) { - result.put(keyValues[i], keyValues[i+1]); - } - - return result; - } - - @NotNull - @Contract(pure=true) - public static Iterator iterate(@NotNull T[] array) { - return array.length == 0 ? EmptyIterator.getInstance() : Arrays.asList(array).iterator(); - } - - @NotNull - @Contract(pure=true) - public static Iterator iterate(@NotNull final Enumeration enumeration) { - return new Iterator() { - @Override - public boolean hasNext() { - return enumeration.hasMoreElements(); - } - - @Override - public T next() { - return enumeration.nextElement(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @NotNull - @Contract(pure=true) - public static Iterable iterate(@NotNull T[] arrays, @NotNull Condition condition) { - return iterate(Arrays.asList(arrays), condition); - } - - @NotNull - @Contract(pure=true) - public static Iterable iterate(@NotNull final Collection collection, @NotNull final Condition condition) { - if (collection.isEmpty()) return emptyIterable(); - return new Iterable() { - @NotNull - @Override - public Iterator iterator() { - return new Iterator() { - private final Iterator impl = collection.iterator(); - private T next = findNext(); - - @Override - public boolean hasNext() { - return next != null; - } - - @Override - public T next() { - T result = next; - next = findNext(); - return result; - } - - @Nullable - private T findNext() { - while (impl.hasNext()) { - T each = impl.next(); - if (condition.value(each)) { - return each; - } - } - return null; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - }; - } - - @NotNull - @Contract(pure=true) - public static Iterable iterateBackward(@NotNull final List list) { - return new Iterable() { - @NotNull - @Override - public Iterator iterator() { - return new Iterator() { - private final ListIterator it = list.listIterator(list.size()); - - @Override - public boolean hasNext() { - return it.hasPrevious(); - } - - @Override - public T next() { - return it.previous(); - } - - @Override - public void remove() { - it.remove(); - } - }; - } - }; - } - - @NotNull - @Contract(pure=true) - public static Iterable> zip(@NotNull final Iterable iterable1, @NotNull final Iterable iterable2) { - return new Iterable>() { - @NotNull - @Override - public Iterator> iterator() { - return new Iterator>() { - private final Iterator i1 = iterable1.iterator(); - private final Iterator i2 = iterable2.iterator(); - - @Override - public boolean hasNext() { - return i1.hasNext() && i2.hasNext(); - } - - @Override - public Pair next() { - return Pair.create(i1.next(), i2.next()); - } - - @Override - public void remove() { - i1.remove(); - i2.remove(); - } - }; - } - }; - } - - public static void swapElements(@NotNull List list, int index1, int index2) { - E e1 = list.get(index1); - E e2 = list.get(index2); - list.set(index1, e2); - list.set(index2, e1); - } - -// @NotNull -// public static List collect(@NotNull Iterator iterator, @NotNull FilteringIterator.InstanceOf instanceOf) { -// @SuppressWarnings("unchecked") List list = collect(FilteringIterator.create((Iterator)iterator, instanceOf)); -// return list; -// } - - public static void addAll(@NotNull Collection collection, @NotNull Enumeration enumeration) { - while (enumeration.hasMoreElements()) { - T element = enumeration.nextElement(); - collection.add(element); - } - } - - /** - * Add all supplied elements to the supplied collection and returns the modified collection. - * Unlike {@link Collections#addAll(Collection, Object[])} this method does not track whether collection - * was modified, so it could be marginally faster. - * - * @param collection collection to add elements to - * @param elements elements to add - * @param type of collection elements - * @param type of elements to add (subtype of collection elements) - * @param type of the collection - * @return the collection passed as first argument - */ - @SuppressWarnings({"UseBulkOperation", "ManualArrayToCollectionCopy"}) - @NotNull - public static > C addAll(@NotNull C collection, @NotNull A... elements) { - for (T element : elements) { - collection.add(element); - } - return collection; - } - - /** - * Adds all not-null elements from the {@code elements}, ignoring nulls - */ - @NotNull - public static > C addAllNotNull(@NotNull C collection, @NotNull A... elements) { - for (T element : elements) { - if (element != null) { - collection.add(element); - } - } - return collection; - } - - public static boolean removeAll(@NotNull Collection collection, @NotNull T... elements) { - boolean modified = false; - for (T element : elements) { - modified |= collection.remove(element); - } - return modified; - } - - // returns true if the collection was modified - public static boolean retainAll(@NotNull Collection collection, @NotNull Condition condition) { - boolean modified = false; - - for (Iterator iterator = collection.iterator(); iterator.hasNext(); ) { - T next = iterator.next(); - if (!condition.value(next)) { - iterator.remove(); - modified = true; - } - } - - return modified; - } - - @Contract(pure=true) - public static U findInstance(@NotNull Iterable iterable, @NotNull Class aClass) { - return findInstance(iterable.iterator(), aClass); - } - - public static U findInstance(@NotNull Iterator iterator, @NotNull Class aClass) { - //noinspection unchecked - return (U)find(iterator, FilteringIterator.instanceOf(aClass)); - } - - @Nullable - @Contract(pure=true) - public static U findInstance(@NotNull T[] array, @NotNull Class aClass) { - return findInstance(Arrays.asList(array), aClass); - } - - @NotNull - @Contract(pure=true) - public static List concat(@NotNull V[] array, @NotNull Function> fun) { - return concat(Arrays.asList(array), fun); - } - - /** - * @return read-only list consisting of the elements from the collections stored in list added together - */ - @NotNull - @Contract(pure=true) - public static List concat(@NotNull Iterable> list) { - List result = new ArrayList(); - for (final Collection ts : list) { - result.addAll(ts); - } - return result.isEmpty() ? Collections.emptyList() : result; - } - - @NotNull - @Contract(pure=true) - public static List append(@NotNull List list, @NotNull T... values) { - return concat(list, list(values)); - } - - /** - * prepend values in front of the list - * @return read-only list consisting of values and the elements from specified list - */ - @NotNull - @Contract(pure=true) - public static List prepend(@NotNull List list, @NotNull T... values) { - return concat(list(values), list); - } - - /** - * @return read-only list consisting of the two lists added together - */ - @NotNull - @Contract(pure=true) - public static List concat(@NotNull final List list1, @NotNull final List list2) { - if (list1.isEmpty() && list2.isEmpty()) { - return Collections.emptyList(); - } - if (list1.isEmpty()) { - //noinspection unchecked - return (List)list2; - } - if (list2.isEmpty()) { - //noinspection unchecked - return (List)list1; - } - - final int size1 = list1.size(); - final int size = size1 + list2.size(); - - return new AbstractList() { - @Override - public T get(int index) { - if (index < size1) { - return list1.get(index); - } - - return list2.get(index - size1); - } - - @Override - public int size() { - return size; - } - }; - } - - @SuppressWarnings({"unchecked"}) - @NotNull - @Contract(pure=true) - public static Iterable concat(@NotNull final Iterable... iterables) { - if (iterables.length == 0) return emptyIterable(); - if (iterables.length == 1) return (Iterable)iterables[0]; - return new Iterable() { - @NotNull - @Override - public Iterator iterator() { - Iterator[] iterators = new Iterator[iterables.length]; - for (int i = 0; i < iterables.length; i++) { - Iterable iterable = iterables[i]; - iterators[i] = iterable.iterator(); - } - return concatIterators(iterators); - } - }; - } - - @NotNull - @Contract(pure=true) - public static Iterator concatIterators(@NotNull Iterator... iterators) { - return new SequenceIterator(iterators); - } - -// @NotNull -// @Contract(pure=true) -// public static Iterator concatIterators(@NotNull Collection> iterators) { -// return new SequenceIterator(iterators); -// } - - @NotNull - @Contract(pure=true) - public static Iterable concat(@NotNull final T[]... iterables) { - return new Iterable() { - @NotNull - @Override - public Iterator iterator() { - Iterator[] iterators = new Iterator[iterables.length]; - for (int i = 0; i < iterables.length; i++) { - T[] iterable = iterables[i]; - iterators[i] = iterate(iterable); - } - @SuppressWarnings("unchecked") Iterator i = concatIterators(iterators); - return i; - } - }; - } - - /** - * @return read-only list consisting of the lists added together - */ - @NotNull - @Contract(pure=true) - public static List concat(@NotNull final List... lists) { - int size = 0; - for (List each : lists) { - size += each.size(); - } - if (size == 0) return emptyList(); - final int finalSize = size; - return new AbstractList() { - @Override - public T get(final int index) { - if (index >= 0 && index < finalSize) { - int from = 0; - for (List each : lists) { - if (from <= index && index < from + each.size()) { - return each.get(index - from); - } - from += each.size(); - } - if (from != finalSize) { - throw new ConcurrentModificationException("The list has changed. Its size was " + finalSize + "; now it's " + from); - } - } - throw new IndexOutOfBoundsException("index: " + index + "; size: " + size()); - } - - @Override - public int size() { - return finalSize; - } - }; - } - - /** - * @return read-only list consisting of the lists added together - */ - @NotNull - @Contract(pure=true) - public static List concat(@NotNull final List> lists) { - @SuppressWarnings("unchecked") List[] array = lists.toArray(new List[0]); - return concat(array); - } - - /** - * @return read-only list consisting of the lists (made by listGenerator) added together - */ - @NotNull - @Contract(pure=true) - public static List concat(@NotNull Iterable list, @NotNull Function> listGenerator) { - List result = new ArrayList(); - for (final V v : list) { - result.addAll(listGenerator.fun(v)); - } - return result.isEmpty() ? ContainerUtil.emptyList() : result; - } - - @Contract(pure=true) - public static boolean intersects(@NotNull Collection collection1, @NotNull Collection collection2) { - if (collection1.size() <= collection2.size()) { - for (T t : collection1) { - if (collection2.contains(t)) { - return true; - } - } - } - else { - for (T t : collection2) { - if (collection1.contains(t)) { - return true; - } - } - } - return false; - } - - /** - * @return read-only collection consisting of elements from both collections - */ - @NotNull - @Contract(pure=true) - public static Collection intersection(@NotNull Collection collection1, @NotNull Collection collection2) { - List result = new ArrayList(); - for (T t : collection1) { - if (collection2.contains(t)) { - result.add(t); - } - } - return result.isEmpty() ? ContainerUtil.emptyList() : result; - } - - @NotNull - @Contract(pure=true) - public static > EnumSet intersection(@NotNull EnumSet collection1, @NotNull EnumSet collection2) { - EnumSet result = EnumSet.copyOf(collection1); - result.retainAll(collection2); - return result; - } - - @Nullable - @Contract(pure=true) - public static T getFirstItem(@Nullable Collection items) { - return getFirstItem(items, null); - } - - @Nullable - @Contract(pure=true) - public static T getFirstItem(@Nullable List items) { - return items == null || items.isEmpty() ? null : items.get(0); - } - - @Contract(pure=true) - public static T getFirstItem(@Nullable final Collection items, @Nullable final T defaultResult) { - return items == null || items.isEmpty() ? defaultResult : items.iterator().next(); - } - - /** - * Returns the only item from the collection or null if collection is empty or contains more than one item - * - * @param items collection to get the item from - * @param type of collection element - * @return the only collection element or null - */ - @Nullable - @Contract(pure=true) - public static T getOnlyItem(@Nullable final Collection items) { - return getOnlyItem(items, null); - } - - @Contract(pure=true) - public static T getOnlyItem(@Nullable final Collection items, @Nullable final T defaultResult) { - return items == null || items.size() != 1 ? defaultResult : items.iterator().next(); - } - - /** - * The main difference from {@code subList} is that {@code getFirstItems} does not - * throw any exceptions, even if maxItems is greater than size of the list - * - * @param items list - * @param maxItems size of the result will be equal or less than {@code maxItems} - * @param type of list - * @return new list with no more than {@code maxItems} first elements - */ - @NotNull - @Contract(pure=true) - public static List getFirstItems(@NotNull final List items, int maxItems) { - return items.subList(0, Math.min(maxItems, items.size())); - } - - @Nullable - @Contract(pure=true) - public static T iterateAndGetLastItem(@NotNull Iterable items) { - Iterator itr = items.iterator(); - T res = null; - while (itr.hasNext()) { - res = itr.next(); - } - - return res; - } - - @NotNull - @Contract(pure=true) - public static Iterator mapIterator(@NotNull final Iterator iterator, @NotNull final Function mapper) { - return new Iterator() { - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public U next() { - return mapper.fun(iterator.next()); - } - - @Override - public void remove() { - iterator.remove(); - } - }; - } - - /** - * @return iterator with elements from the original {@param iterator} which are valid according to {@param filter} predicate. - */ - @NotNull - @Contract(pure=true) - public static Iterator filterIterator(@NotNull final Iterator iterator, @NotNull final Condition filter) { - return new Iterator() { - T next; - boolean hasNext; - { - findNext(); - } - @Override - public boolean hasNext() { - return hasNext; - } - - private void findNext() { - hasNext = false; - while (iterator.hasNext()) { - T t = iterator.next(); - if (filter.value(t)) { - next = t; - hasNext = true; - break; - } - } - } - - @Override - public T next() { - T result; - if (hasNext) { - result = next; - findNext(); - } - else { - throw new NoSuchElementException(); - } - return result; - } - - @Override - public void remove() { - iterator.remove(); - } - }; - } - - @Nullable - @Contract(pure=true) - public static > T getLastItem(@Nullable L list, @Nullable T def) { - return ContainerUtilRt.getLastItem(list, def); - } - - @Nullable - @Contract(pure=true) - public static > T getLastItem(@Nullable L list) { - return ContainerUtilRt.getLastItem(list); - } - - /** - * @return read-only collection consisting of elements from the 'from' collection which are absent from the 'what' collection - */ - @NotNull - @Contract(pure=true) - public static Collection subtract(@NotNull Collection from, @NotNull Collection what) { - final Set set = newHashSet(from); - set.removeAll(what); - return set.isEmpty() ? ContainerUtil.emptyList() : set; - } - - @NotNull - @Contract(pure=true) - public static T[] toArray(@Nullable Collection c, @NotNull ArrayFactory factory) { - return c != null ? c.toArray(factory.create(c.size())) : factory.create(0); - } - - @NotNull - @Contract(pure=true) - public static T[] toArray(@NotNull Collection c1, @NotNull Collection c2, @NotNull ArrayFactory factory) { - return ArrayUtil.mergeCollections(c1, c2, factory); - } - - @NotNull - @Contract(pure=true) - public static T[] mergeCollectionsToArray(@NotNull Collection c1, @NotNull Collection c2, @NotNull ArrayFactory factory) { - return ArrayUtil.mergeCollections(c1, c2, factory); - } - - public static > void sort(@NotNull List list) { - int size = list.size(); - - if (size < 2) return; - if (size == 2) { - T t0 = list.get(0); - T t1 = list.get(1); - - if (t0.compareTo(t1) > 0) { - list.set(0, t1); - list.set(1, t0); - } - } - else if (size < INSERTION_SORT_THRESHOLD) { - for (int i = 0; i < size; i++) { - for (int j = 0; j < i; j++) { - T ti = list.get(i); - T tj = list.get(j); - - if (ti.compareTo(tj) < 0) { - list.set(i, tj); - list.set(j, ti); - } - } - } - } - else { - Collections.sort(list); - } - } - - public static void sort(@NotNull List list, @NotNull Comparator comparator) { - int size = list.size(); - - if (size < 2) return; - if (size == 2) { - T t0 = list.get(0); - T t1 = list.get(1); - - if (comparator.compare(t0, t1) > 0) { - list.set(0, t1); - list.set(1, t0); - } - } - else if (size < INSERTION_SORT_THRESHOLD) { - for (int i = 0; i < size; i++) { - for (int j = 0; j < i; j++) { - T ti = list.get(i); - T tj = list.get(j); - - if (comparator.compare(ti, tj) < 0) { - list.set(i, tj); - list.set(j, ti); - } - } - } - } - else { - Collections.sort(list, comparator); - } - } - - public static > void sort(@NotNull T[] a) { - int size = a.length; - - if (size < 2) return; - if (size == 2) { - T t0 = a[0]; - T t1 = a[1]; - - if (t0.compareTo(t1) > 0) { - a[0] = t1; - a[1] = t0; - } - } - else if (size < INSERTION_SORT_THRESHOLD) { - for (int i = 0; i < size; i++) { - for (int j = 0; j < i; j++) { - T ti = a[i]; - T tj = a[j]; - - if (ti.compareTo(tj) < 0) { - a[i] = tj; - a[j] = ti; - } - } - } - } - else { - Arrays.sort(a); - } - } - - @NotNull - @Contract(pure=true) - public static List sorted(@NotNull Collection list, @NotNull Comparator comparator) { - return sorted((Iterable)list, comparator); - } - - @NotNull - @Contract(pure=true) - public static List sorted(@NotNull Iterable list, @NotNull Comparator comparator) { - List sorted = newArrayList(list); - sort(sorted, comparator); - return sorted; - } - - @NotNull - @Contract(pure=true) - public static > List sorted(@NotNull Collection list) { - return sorted(list, new Comparator() { - @Override - public int compare(T o1, T o2) { - return o1.compareTo(o2); - } - }); - } - - public static void sort(@NotNull T[] a, @NotNull Comparator comparator) { - int size = a.length; - - if (size < 2) return; - if (size == 2) { - T t0 = a[0]; - T t1 = a[1]; - - if (comparator.compare(t0, t1) > 0) { - a[0] = t1; - a[1] = t0; - } - } - else if (size < INSERTION_SORT_THRESHOLD) { - for (int i = 0; i < size; i++) { - for (int j = 0; j < i; j++) { - T ti = a[i]; - T tj = a[j]; - - if (comparator.compare(ti, tj) < 0) { - a[i] = tj; - a[j] = ti; - } - } - } - } - else { - Arrays.sort(a, comparator); - } - } - - /** - * @param iterable an input iterable to process - * @param mapping a side-effect free function which transforms iterable elements - * @return read-only list consisting of the elements from the iterable converted by mapping - */ - @NotNull - @Contract(pure=true) - public static List map(@NotNull Iterable iterable, @NotNull Function mapping) { - List result = new ArrayList(); - for (T t : iterable) { - result.add(mapping.fun(t)); - } - return result.isEmpty() ? ContainerUtil.emptyList() : result; - } - - /** - * @param collection an input collection to process - * @param mapping a side-effect free function which transforms iterable elements - * @return read-only list consisting of the elements from the input collection converted by mapping - */ - @NotNull - @Contract(pure=true) - public static List map(@NotNull Collection collection, @NotNull Function mapping) { - return ContainerUtilRt.map2List(collection, mapping); - } - - /** - * @param array an input array to process - * @param mapping a side-effect free function which transforms array elements - * @return read-only list consisting of the elements from the input array converted by mapping with nulls filtered out - */ - @NotNull - @Contract(pure=true) - public static List mapNotNull(@NotNull T[] array, @NotNull Function mapping) { - return mapNotNull(Arrays.asList(array), mapping); - } - - /** - * @param array an input array to process - * @param mapping a side-effect free function which transforms array elements - * @param emptyArray an empty array of desired result type (may be returned if the result is also empty) - * @return array consisting of the elements from the input array converted by mapping with nulls filtered out - */ - @NotNull - @Contract(pure=true) - public static V[] mapNotNull(@NotNull T[] array, @NotNull Function mapping, @NotNull V[] emptyArray) { - List result = new ArrayList(array.length); - for (T t : array) { - V v = mapping.fun(t); - if (v != null) { - result.add(v); - } - } - if (result.isEmpty()) { - assert emptyArray.length == 0 : "You must pass an empty array"; - return emptyArray; - } - return result.toArray(emptyArray); - } - - /** - * @param iterable an input iterable to process - * @param mapping a side-effect free function which transforms iterable elements - * @return read-only list consisting of the elements from the iterable converted by mapping with nulls filtered out - */ - @NotNull - @Contract(pure=true) - public static List mapNotNull(@NotNull Iterable iterable, @NotNull Function mapping) { - List result = new ArrayList(); - for (T t : iterable) { - final V o = mapping.fun(t); - if (o != null) { - result.add(o); - } - } - return result.isEmpty() ? ContainerUtil.emptyList() : result; - } - - /** - * @param collection an input collection to process - * @param mapping a side-effect free function which transforms collection elements - * @return read-only list consisting of the elements from the array converted by mapping with nulls filtered out - */ - @NotNull - @Contract(pure=true) - public static List mapNotNull(@NotNull Collection collection, @NotNull Function mapping) { - return ContainerUtilRt.mapNotNull(collection, mapping); - } - - /** - * @return read-only list consisting of the elements with nulls filtered out - */ - @NotNull - @Contract(pure=true) - public static List packNullables(@NotNull T... elements) { - List list = new ArrayList(); - for (T element : elements) { - addIfNotNull(list, element); - } - return list.isEmpty() ? ContainerUtil.emptyList() : list; - } - - /** - * @return read-only list consisting of the elements from the array converted by mapping - */ - @NotNull - @Contract(pure=true) - public static List map(@NotNull T[] array, @NotNull Function mapping) { - List result = new ArrayList(array.length); - for (T t : array) { - result.add(mapping.fun(t)); - } - return result.isEmpty() ? ContainerUtil.emptyList() : result; - } - - @NotNull - @Contract(pure=true) - public static V[] map(@NotNull T[] arr, @NotNull Function mapping, @NotNull V[] emptyArray) { - if (arr.length==0) { - assert emptyArray.length == 0 : "You must pass an empty array"; - return emptyArray; - } - - V[] result = emptyArray.length < arr.length ? Arrays.copyOf(emptyArray, arr.length) : emptyArray; - - for (int i = 0; i < arr.length; i++) { - result[i] = mapping.fun(arr[i]); - } - return result; - } - - @NotNull - @Contract(pure=true) - public static Set set(@NotNull T ... items) { - return newHashSet(items); - } - - public static void putIfAbsent(final K key, @Nullable V value, @NotNull final Map result) { - if (!result.containsKey(key)) { - result.put(key, value); - } - } - - public static void putIfNotNull(final K key, @Nullable V value, @NotNull final Map result) { - if (value != null) { - result.put(key, value); - } - } - - public static void putIfNotNull(final K key, @Nullable Collection value, @NotNull final MultiMap result) { - if (value != null) { - result.putValues(key, value); - } - } - - public static void putIfNotNull(final K key, @Nullable V value, @NotNull final MultiMap result) { - if (value != null) { - result.putValue(key, value); - } - } - - public static void add(final T element, @NotNull final Collection result, @NotNull final Disposable parentDisposable) { - if (result.add(element)) { - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - result.remove(element); - } - }); - } - } - - @NotNull - @Contract(pure=true) - public static List createMaybeSingletonList(@Nullable T element) { - return element == null ? ContainerUtil.emptyList() : Collections.singletonList(element); - } - - @NotNull - @Contract(pure=true) - public static Set createMaybeSingletonSet(@Nullable T element) { - return element == null ? Collections.emptySet() : Collections.singleton(element); - } - - @NotNull - public static V getOrCreate(@NotNull Map result, final T key, @NotNull V defaultValue) { - V value = result.get(key); - if (value == null) { - result.put(key, value = defaultValue); - } - return value; - } - - public static V getOrCreate(@NotNull Map result, final T key, @NotNull Factory factory) { - V value = result.get(key); - if (value == null) { - result.put(key, value = factory.create()); - } - return value; - } - - @NotNull - @Contract(pure=true) - public static V getOrElse(@NotNull Map result, final T key, @NotNull V defValue) { - V value = result.get(key); - return value == null ? defValue : value; - } - - @Contract(pure=true) - public static boolean and(@NotNull T[] iterable, @NotNull Condition condition) { - return and(Arrays.asList(iterable), condition); - } - - @Contract(pure=true) - public static boolean and(@NotNull Iterable iterable, @NotNull Condition condition) { - for (final T t : iterable) { - if (!condition.value(t)) return false; - } - return true; - } - - @Contract(pure=true) - public static boolean exists(@NotNull T[] array, @NotNull Condition condition) { - for (final T t : array) { - if (condition.value(t)) return true; - } - return false; - } - - @Contract(pure=true) - public static boolean exists(@NotNull Iterable iterable, @NotNull Condition condition) { - return or(iterable, condition); - } - - @Contract(pure=true) - public static boolean or(@NotNull T[] iterable, @NotNull Condition condition) { - return exists(iterable, condition); - } - - @Contract(pure=true) - public static boolean or(@NotNull Iterable iterable, @NotNull Condition condition) { - for (final T t : iterable) { - if (condition.value(t)) return true; - } - return false; - } - - @Contract(pure=true) - public static int count(@NotNull Iterable iterable, @NotNull Condition condition) { - int count = 0; - for (final T t : iterable) { - if (condition.value(t)) count++; - } - return count; - } - - @NotNull - @Contract(pure=true) - public static List unfold(@Nullable T t, @NotNull NullableFunction next) { - if (t == null) return emptyList(); - - List list = new ArrayList(); - while (t != null) { - list.add(t); - t = next.fun(t); - } - return list; - } - - @NotNull - @Contract(pure=true) - public static List dropTail(@NotNull List items) { - return items.subList(0, items.size() - 1); - } - - @NotNull - @Contract(pure=true) - public static List list(@NotNull T... items) { - return Arrays.asList(items); - } - - // Generalized Quick Sort. Does neither array.clone() nor list.toArray() - - public static void quickSort(@NotNull List list, @NotNull Comparator comparator) { - quickSort(list, comparator, 0, list.size()); - } - - private static void quickSort(@NotNull List x, @NotNull Comparator comparator, int off, int len) { - // Insertion sort on smallest arrays - if (len < 7) { - for (int i = off; i < len + off; i++) { - for (int j = i; j > off && comparator.compare(x.get(j), x.get(j - 1)) < 0; j--) { - swapElements(x, j, j - 1); - } - } - return; - } - - // Choose a partition element, v - int m = off + (len >> 1); // Small arrays, middle element - if (len > 7) { - int l = off; - int n = off + len - 1; - if (len > 40) { // Big arrays, pseudomedian of 9 - int s = len / 8; - l = med3(x, comparator, l, l + s, l + 2 * s); - m = med3(x, comparator, m - s, m, m + s); - n = med3(x, comparator, n - 2 * s, n - s, n); - } - m = med3(x, comparator, l, m, n); // Mid-size, med of 3 - } - T v = x.get(m); - - // Establish Invariant: v* (v)* v* - int a = off; - int b = a; - int c = off + len - 1; - int d = c; - while (true) { - while (b <= c && comparator.compare(x.get(b), v) <= 0) { - if (comparator.compare(x.get(b), v) == 0) { - swapElements(x, a++, b); - } - b++; - } - while (c >= b && comparator.compare(v, x.get(c)) <= 0) { - if (comparator.compare(x.get(c), v) == 0) { - swapElements(x, c, d--); - } - c--; - } - if (b > c) break; - swapElements(x, b++, c--); - } - - // Swap partition elements back to middle - int n = off + len; - int s = Math.min(a - off, b - a); - vecswap(x, off, b - s, s); - s = Math.min(d - c, n - d - 1); - vecswap(x, b, n - s, s); - - // Recursively sort non-partition-elements - if ((s = b - a) > 1) quickSort(x, comparator, off, s); - if ((s = d - c) > 1) quickSort(x, comparator, n - s, s); - } - - /* - * Returns the index of the median of the three indexed longs. - */ - private static int med3(@NotNull List x, Comparator comparator, int a, int b, int c) { - return comparator.compare(x.get(a), x.get(b)) < 0 ? comparator.compare(x.get(b), x.get(c)) < 0 - ? b - : comparator.compare(x.get(a), x.get(c)) < 0 ? c : a - : comparator.compare(x.get(c), x.get(b)) < 0 - ? b - : comparator.compare(x.get(c), x.get(a)) < 0 ? c : a; - } - - /* - * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)]. - */ - private static void vecswap(List x, int a, int b, int n) { - for (int i = 0; i < n; i++, a++, b++) { - swapElements(x, a, b); - } - } - - - /** - * @return read-only set consisting of the only element o - */ - @NotNull - @Contract(pure=true) - public static Set singleton(final T o, @NotNull final TObjectHashingStrategy strategy) { - return strategy == TObjectHashingStrategy.CANONICAL ? new SingletonSet(o) : SingletonSet.withCustomStrategy(o, strategy); - } - - /** - * @return read-only list consisting of the elements from all of the collections - */ - @NotNull - @Contract(pure=true) - public static List flatten(@NotNull Collection[] collections) { - return flatten(Arrays.asList(collections)); - } - - /** - * Processes the list, remove all duplicates and return the list with unique elements. - * @param list must be sorted (according to the comparator), all elements must be not-null - */ - @NotNull - public static List removeDuplicatesFromSorted(@NotNull List list, @NotNull Comparator comparator) { - T prev = null; - List result = null; - for (int i = 0; i < list.size(); i++) { - T t = list.get(i); - if (t == null) { - throw new IllegalArgumentException("get(" + i + ") = null"); - } - int cmp = prev == null ? -1 : comparator.compare(prev, t); - if (cmp < 0) { - if (result != null) result.add(t); - } - else if (cmp == 0) { - if (result == null) { - result = new ArrayList(list.size()); - result.addAll(list.subList(0, i)); - } - } - else { - throw new IllegalArgumentException("List must be sorted but get(" + (i - 1) + ")=" + list.get(i - 1) + " > get(" + i + ")=" + t); - } - prev = t; - } - return result == null ? list : result; - } - - /** - * @return read-only list consisting of the elements from all of the collections - */ - @NotNull - @Contract(pure=true) - public static List flatten(@NotNull Iterable> collections) { - List result = new ArrayList(); - for (Collection list : collections) { - result.addAll(list); - } - - return result.isEmpty() ? ContainerUtil.emptyList() : result; - } - - /** - * @return read-only list consisting of the elements from all of the collections - */ - @NotNull - @Contract(pure=true) - public static List flattenIterables(@NotNull Iterable> collections) { - List result = new ArrayList(); - for (Iterable list : collections) { - for (E e : list) { - result.add(e); - } - } - return result.isEmpty() ? ContainerUtil.emptyList() : result; - } - - @NotNull - public static V[] convert(@NotNull K[] from, @NotNull V[] to, @NotNull Function fun) { - if (to.length < from.length) { - @SuppressWarnings("unchecked") V[] array = (V[])Array.newInstance(to.getClass().getComponentType(), from.length); - to = array; - } - for (int i = 0; i < from.length; i++) { - to[i] = fun.fun(from[i]); - } - return to; - } - - @Contract(pure=true) - public static boolean containsIdentity(@NotNull Iterable list, T element) { - for (T t : list) { - if (t == element) { - return true; - } - } - return false; - } - - @Contract(pure=true) - public static int indexOfIdentity(@NotNull List list, T element) { - for (int i = 0, listSize = list.size(); i < listSize; i++) { - if (list.get(i) == element) { - return i; - } - } - return -1; - } - - @Contract(pure=true) - public static boolean equalsIdentity(@NotNull List list1, @NotNull List list2) { - int listSize = list1.size(); - if (list2.size() != listSize) { - return false; - } - - for (int i = 0; i < listSize; i++) { - if (list1.get(i) != list2.get(i)) { - return false; - } - } - return true; - } - - @Contract(pure=true) - public static int indexOf(@NotNull List list, @NotNull Condition condition) { - return ContainerUtilRt.indexOf(list, condition); - } - - @Contract(pure=true) - public static int lastIndexOf(@NotNull List list, @NotNull Condition condition) { - for (int i = list.size() - 1; i >= 0; i--) { - T t = list.get(i); - if (condition.value(t)) { - return i; - } - } - return -1; - } - - @Nullable - @Contract(pure = true) - public static U findLastInstance(@NotNull List list, @NotNull final Class clazz) { - int i = lastIndexOf(list, new Condition() { - @Override - public boolean value(T t) { - return clazz.isInstance(t); - } - }); - //noinspection unchecked - return i < 0 ? null : (U)list.get(i); - } - - @Contract(pure = true) - public static int lastIndexOfInstance(@NotNull List list, @NotNull final Class clazz) { - return lastIndexOf(list, new Condition() { - @Override - public boolean value(T t) { - return clazz.isInstance(t); - } - }); - } - - @NotNull - @Contract(pure=true) - public static Map reverseMap(@NotNull Map map) { - final Map result = newHashMap(); - for (Map.Entry entry : map.entrySet()) { - result.put(entry.getValue(), entry.getKey()); - } - return result; - } - - @Contract("null -> null; !null -> !null") - public static List trimToSize(@Nullable List list) { - if (list == null) return null; - if (list.isEmpty()) return emptyList(); - - if (list instanceof ArrayList) { - ((ArrayList)list).trimToSize(); - } - - return list; - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static Stack newStack() { - return ContainerUtilRt.newStack(); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static Stack newStack(@NotNull Collection initial) { - return ContainerUtilRt.newStack(initial); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static Stack newStack(@NotNull T... initial) { - return ContainerUtilRt.newStack(initial); - } - - @NotNull - @Contract(pure=true) - public static List emptyList() { - return ContainerUtilRt.emptyList(); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static CopyOnWriteArrayList createEmptyCOWList() { - // does not create garbage new Object[0] - return new CopyOnWriteArrayList(ContainerUtilRt.emptyList()); - } - - /** - * Creates List which is thread-safe to modify and iterate. - * It differs from the java.util.concurrent.CopyOnWriteArrayList in the following: - * - faster modification in the uncontended case - * - less memory - * - slower modification in highly contented case (which is the kind of situation you shouldn't use COWAL anyway) - * - * N.B. Avoid using {@code list.toArray(new T[list.size()])} on this list because it is inherently racey and - * therefore can return array with null elements at the end. - */ - @NotNull - @Contract(value = " -> new", pure = true) - public static List createLockFreeCopyOnWriteList() { - return createConcurrentList(); - } - -// @NotNull -// @Contract(value = "_ -> new", pure = true) -// public static List createLockFreeCopyOnWriteList(@NotNull Collection c) { -// return new LockFreeCopyOnWriteArrayList(c); -// } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentIntObjectMap createConcurrentIntObjectMap() { - return new ConcurrentIntObjectHashMap(); - } - -// @NotNull -// @Contract(value = "_,_,_ -> new", pure = true) -// public static ConcurrentIntObjectMap createConcurrentIntObjectMap(int initialCapacity, float loadFactor, int concurrencyLevel) { -// return new ConcurrentIntObjectHashMap(initialCapacity, loadFactor, concurrencyLevel); -// } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentIntObjectMap createConcurrentIntObjectSoftValueMap() { - return new ConcurrentIntKeySoftValueHashMap(); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentLongObjectMap createConcurrentLongObjectMap() { - return new ConcurrentLongObjectHashMap(); - } - -// @NotNull -// @Contract(value = "_ -> new", pure = true) -// public static ConcurrentLongObjectMap createConcurrentLongObjectMap(int initialCapacity) { -// return new ConcurrentLongObjectHashMap(initialCapacity); -// } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentMap createConcurrentWeakValueMap() { - return new ConcurrentWeakValueHashMap(); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentIntObjectMap createConcurrentIntObjectWeakValueMap() { - return new ConcurrentIntKeyWeakValueHashMap(); - } - - @NotNull - @Contract(value = "_,_,_,_ -> new", pure = true) - public static ConcurrentMap createConcurrentWeakKeySoftValueMap(int initialCapacity, - float loadFactor, - int concurrencyLevel, - @NotNull final TObjectHashingStrategy hashingStrategy) { - //noinspection deprecation - return new ConcurrentWeakKeySoftValueHashMap(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); - } - - @NotNull - @Contract(value = "_,_,_,_ -> new", pure = true) - public static ConcurrentMap createConcurrentSoftKeySoftValueMap(int initialCapacity, - float loadFactor, - int concurrencyLevel, - @NotNull final TObjectHashingStrategy hashingStrategy) { - return new ConcurrentSoftKeySoftValueHashMap(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentMap createConcurrentWeakKeySoftValueMap() { - return createConcurrentWeakKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors(), ContainerUtil.canonicalStrategy()); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentMap createConcurrentWeakKeyWeakValueMap() { - return createConcurrentWeakKeyWeakValueMap(ContainerUtil.canonicalStrategy()); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static ConcurrentMap createConcurrentWeakKeyWeakValueMap(@NotNull TObjectHashingStrategy strategy) { - return new ConcurrentWeakKeyWeakValueHashMap(100, 0.75f, Runtime.getRuntime().availableProcessors(), - strategy); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentMap createConcurrentSoftValueMap() { - return new ConcurrentSoftValueHashMap(); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentMap createConcurrentSoftMap() { - return new ConcurrentSoftHashMap(); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentMap createConcurrentWeakMap() { - //noinspection deprecation - return new ConcurrentWeakHashMap(0.75f); - } - -// @NotNull -// @Contract(value = "_,_,_,_ -> new", pure = true) -// public static ConcurrentMap createConcurrentSoftMap(int initialCapacity, -// float loadFactor, -// int concurrencyLevel, -// @NotNull TObjectHashingStrategy hashingStrategy) { -// return new ConcurrentSoftHashMap(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); -// } - - @NotNull - @Contract(value = "_,_,_,_ -> new", pure = true) - public static ConcurrentMap createConcurrentWeakMap(int initialCapacity, - float loadFactor, - int concurrencyLevel, - @NotNull TObjectHashingStrategy hashingStrategy) { - //noinspection deprecation - return new ConcurrentWeakHashMap(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); - } - -// @NotNull -// @Contract(value = "_ -> new", pure = true) -// public static ConcurrentMap createConcurrentWeakMap(@NotNull TObjectHashingStrategy hashingStrategy) { -// //noinspection deprecation -// return new ConcurrentWeakHashMap(hashingStrategy); -// } - - /** - * @see #createLockFreeCopyOnWriteList() - */ - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentList createConcurrentList() { - return new LockFreeCopyOnWriteArrayList(); - } - -// @NotNull -// @Contract(value = "_ -> new", pure = true) -// public static ConcurrentList createConcurrentList(@NotNull Collection collection) { -// return new LockFreeCopyOnWriteArrayList(collection); -// } - - /** - * @see #addIfNotNull(Collection, Object) instead - */ - @Deprecated - public static void addIfNotNull(@Nullable T element, @NotNull Collection result) { - addIfNotNull(result,element); - } - - public static void addIfNotNull(@NotNull Collection result, @Nullable T element) { - ContainerUtilRt.addIfNotNull(result, element); - } - - @NotNull - @Contract(pure=true) - public static List map2List(@NotNull T[] array, @NotNull Function mapper) { - return ContainerUtilRt.map2List(array, mapper); - } - - @NotNull - @Contract(pure=true) - public static List map2List(@NotNull Collection collection, @NotNull Function mapper) { - return ContainerUtilRt.map2List(collection, mapper); - } - - @NotNull - @Contract(pure=true) - public static List> map2List(@NotNull Map map) { - return ContainerUtilRt.map2List(map); - } - - @NotNull - @Contract(pure=true) - public static Set map2Set(@NotNull T[] collection, @NotNull Function mapper) { - return ContainerUtilRt.map2Set(collection, mapper); - } - - @NotNull - @Contract(pure=true) - public static Set map2Set(@NotNull Collection collection, @NotNull Function mapper) { - return ContainerUtilRt.map2Set(collection, mapper); - } - - @NotNull - @Contract(pure=true) - public static Set map2LinkedSet(@NotNull Collection collection, @NotNull Function mapper) { - if (collection.isEmpty()) return Collections.emptySet(); - Set set = new LinkedHashSet(collection.size()); - for (final T t : collection) { - set.add(mapper.fun(t)); - } - return set; - } - - @NotNull - @Contract(pure=true) - public static Set map2SetNotNull(@NotNull Collection collection, @NotNull Function mapper) { - if (collection.isEmpty()) return Collections.emptySet(); - Set set = new HashSet(collection.size()); - for (T t : collection) { - V value = mapper.fun(t); - if (value != null) { - set.add(value); - } - } - return set.isEmpty() ? Collections.emptySet() : set; - } - - /** - * @deprecated use {@link List#toArray(Object[])} instead - */ - @Deprecated - @NotNull - @Contract(pure=true) - public static T[] toArray(@NotNull List collection, @NotNull T[] array) { - return collection.toArray(array); - } - - /** - * @deprecated use {@link Collection#toArray(Object[])} instead - */ - @Deprecated - @NotNull - @Contract(pure=true) - public static T[] toArray(@NotNull Collection c, @NotNull T[] sample) { - return c.toArray(sample); - } - - @NotNull - public static T[] copyAndClear(@NotNull Collection collection, @NotNull ArrayFactory factory, boolean clear) { - int size = collection.size(); - T[] a = factory.create(size); - if (size > 0) { - a = collection.toArray(a); - if (clear) collection.clear(); - } - return a; - } - - @Contract("null -> null") - public static List copyList(@Nullable List list) { - if (list == null) { - return null; - } - else if (list == Collections.emptyList()) { - return Collections.emptyList(); - } - else if (list.size() == 1) { - return new SmartList(list.get(0)); - } - else if (list.isEmpty()) { - return new SmartList(); - } - else { - return new ArrayList(list); - } - } - - @NotNull - @Contract(pure=true) - public static Collection toCollection(@NotNull Iterable iterable) { - return iterable instanceof Collection ? (Collection)iterable : newArrayList(iterable); - } - - @NotNull - public static List toList(@NotNull Enumeration enumeration) { - if (!enumeration.hasMoreElements()) { - return Collections.emptyList(); - } - - List result = new SmartList(); - while (enumeration.hasMoreElements()) { - result.add(enumeration.nextElement()); - } - return result; - } - - @Contract(value = "null -> true", pure = true) - public static boolean isEmpty(@Nullable Collection collection) { - return ContainerUtilRt.isEmpty(collection); - } - - @Contract(value = "null -> true", pure = true) - public static boolean isEmpty(@Nullable Map map) { - return map == null || map.isEmpty(); - } - - @NotNull - @Contract(pure=true) - public static List notNullize(@Nullable List list) { - return list == null ? ContainerUtilRt.emptyList() : list; - } - - @NotNull - @Contract(pure=true) - public static Set notNullize(@Nullable Set set) { - return set == null ? Collections.emptySet() : set; - } - - @NotNull - @Contract(pure = true) - public static Map notNullize(@Nullable Map map) { - return map == null ? Collections.emptyMap() : map; - } - - @Contract(pure = true) - public static boolean startsWith(@NotNull List list, @NotNull List prefix) { - return list.size() >= prefix.size() && list.subList(0, prefix.size()).equals(prefix); - } - - @Nullable - @Contract(pure=true) - public static > C nullize(@Nullable C collection) { - return isEmpty(collection) ? null : collection; - } - - @Contract(pure=true) - public static > int compareLexicographically(@NotNull List o1, @NotNull List o2) { - for (int i = 0; i < Math.min(o1.size(), o2.size()); i++) { - int result = Comparing.compare(o1.get(i), o2.get(i)); - if (result != 0) { - return result; - } - } - return o1.size() < o2.size() ? -1 : o1.size() == o2.size() ? 0 : 1; - } - - @Contract(pure=true) - public static int compareLexicographically(@NotNull List o1, @NotNull List o2, @NotNull Comparator comparator) { - for (int i = 0; i < Math.min(o1.size(), o2.size()); i++) { - int result = comparator.compare(o1.get(i), o2.get(i)); - if (result != 0) { - return result; - } - } - return o1.size() < o2.size() ? -1 : o1.size() == o2.size() ? 0 : 1; - } - - /** - * Returns a String representation of the given map, by listing all key-value pairs contained in the map. - */ - @NotNull - @Contract(pure = true) - public static String toString(@NotNull Map map) { - StringBuilder sb = new StringBuilder("{"); - for (Iterator> iterator = map.entrySet().iterator(); iterator.hasNext(); ) { - Map.Entry entry = iterator.next(); - sb.append(entry.getKey()).append('=').append(entry.getValue()); - if (iterator.hasNext()) { - sb.append(", "); - } - } - sb.append('}'); - return sb.toString(); - } - - public static class KeyOrderedMultiMap extends MultiMap { - - public KeyOrderedMultiMap() { - } - - public KeyOrderedMultiMap(@NotNull MultiMap toCopy) { - super(toCopy); - } - - @NotNull - @Override - protected Map> createMap() { - return new TreeMap>(); - } - - @NotNull - @Override - protected Map> createMap(int initialCapacity, float loadFactor) { - return new TreeMap>(); - } - - @NotNull - public NavigableSet navigableKeySet() { - //noinspection unchecked - return ((TreeMap)myMap).navigableKeySet(); - } - } - - @Contract(value = " -> new", pure = true) - @NotNull - public static Map createWeakKeySoftValueMap() { - return new WeakKeySoftValueHashMap(); - } - - @Contract(value = " -> new", pure = true) - @NotNull - public static Map createWeakKeyWeakValueMap() { - //noinspection deprecation - return new WeakKeyWeakValueHashMap(); - } - - @Contract(value = " -> new", pure = true) - @NotNull - public static Map createSoftKeySoftValueMap() { - return new SoftKeySoftValueHashMap(); - } - - /** - * Hard keys soft values hash map. - * Null keys are NOT allowed - * Null values are allowed - */ - @Contract(value = " -> new", pure = true) - @NotNull - public static Map createSoftValueMap() { - //noinspection deprecation - return new SoftValueHashMap(ContainerUtil.canonicalStrategy()); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ConcurrentMap createConcurrentSoftKeySoftValueMap() { - return createConcurrentSoftKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors(), canonicalStrategy()); - } - - - /** - * Hard keys weak values hash map. - * Null keys are NOT allowed - * Null values are allowed - */ - @Contract(value = " -> new", pure = true) - @NotNull - public static Map createWeakValueMap() { - //noinspection deprecation - return new WeakValueHashMap(ContainerUtil.canonicalStrategy()); - } - - /** - * Soft keys hard values hash map. - * Null keys are NOT allowed - * Null values are allowed - */ - @Contract(value = " -> new", pure = true) - @NotNull - public static Map createSoftMap() { - //noinspection deprecation - return new SoftHashMap(4); - } - -// @Contract(value = "_ -> new", pure = true) -// @NotNull -// public static Map createSoftMap(@NotNull TObjectHashingStrategy strategy) { -// //noinspection deprecation -// return new SoftHashMap(strategy); -// } - - /** - * Weak keys hard values hash map. - * Null keys are NOT allowed - * Null values are allowed - */ - @Contract(value = " -> new", pure = true) - @NotNull - public static Map createWeakMap() { - return createWeakMap(4); - } - - @Contract(value = "_ -> new", pure = true) - @NotNull - public static Map createWeakMap(int initialCapacity) { - return createWeakMap(initialCapacity, 0.8f, ContainerUtil.canonicalStrategy()); - } - - @Contract(value = "_, _, _ -> new", pure = true) - @NotNull - public static Map createWeakMap(int initialCapacity, float loadFactor, @NotNull TObjectHashingStrategy strategy) { - //noinspection deprecation - return new WeakHashMap(initialCapacity, loadFactor, strategy); - } - - @Contract(value = " -> new", pure = true) - @NotNull - public static Set createWeakSet() { - return new WeakHashSet(); - } - - @Contract(value = " -> new", pure = true) - @NotNull - public static IntObjectMap createIntKeyWeakValueMap() { - return new IntKeyWeakValueHashMap(); - } - - @Contract(value = " -> new", pure = true) - @NotNull - public static ObjectIntMap createWeakKeyIntValueMap() { - return new WeakKeyIntValueHashMap(); - } - - - /** - * Create an immutable copy of the {@code list}. - * Modifications of the {@code list} have no effect on the returned copy. - */ - @SuppressWarnings("unchecked") - @Contract(value = "_ -> new", pure = true) - @NotNull - public static List freeze(@NotNull List list) { - if (list.isEmpty()) { - return Collections.emptyList(); - } - else if (list.size() == 1) { - return immutableSingletonList(list.get(0)); - } - else { - return immutableList((T[])list.toArray()); - } - } -} \ No newline at end of file diff --git a/kotlin-bundled-compiler/src/com/intellij/util/containers/ContainerUtilRt.java b/kotlin-bundled-compiler/src/com/intellij/util/containers/ContainerUtilRt.java deleted file mode 100644 index 55cedb0bd..000000000 --- a/kotlin-bundled-compiler/src/com/intellij/util/containers/ContainerUtilRt.java +++ /dev/null @@ -1,515 +0,0 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package com.intellij.util.containers; - -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Pair; -import com.intellij.util.ArrayUtilRt; -import com.intellij.util.Function; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.HashSet; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * Stripped-down version of {@code com.intellij.util.containers.ContainerUtil}. - * Intended to use by external (out-of-IDE-process) runners and helpers so it should not contain any library dependencies. - * - * @since 12.0 - */ -public class ContainerUtilRt { - @NotNull - @Contract(value = " -> new", pure = true) - public static HashMap newHashMap() { - return new java.util.HashMap(); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static HashMap newHashMap(@NotNull Map map) { - return new java.util.HashMap(map); - } - - @NotNull - @Contract(value = "_,_ -> new", pure = true) - public static Map newHashMap(@NotNull List keys, @NotNull List values) { - if (keys.size() != values.size()) { - throw new IllegalArgumentException(keys + " should have same length as " + values); - } - - Map map = newHashMap(keys.size()); - for (int i = 0; i < keys.size(); ++i) { - map.put(keys.get(i), values.get(i)); - } - return map; - } - - @NotNull - @Contract(value = "_,_ -> new", pure = true) - public static Map newHashMap(@NotNull Pair first, @NotNull Pair... entries) { - Map map = newHashMap(entries.length + 1); - map.put(first.getFirst(), first.getSecond()); - for (Pair entry : entries) { - map.put(entry.getFirst(), entry.getSecond()); - } - return map; - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static Map newHashMap(int initialCapacity) { - return new java.util.HashMap(initialCapacity); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static TreeMap newTreeMap() { - return new TreeMap(); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static TreeMap newTreeMap(@NotNull Map map) { - return new TreeMap(map); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static LinkedHashMap newLinkedHashMap() { - return new LinkedHashMap(); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static LinkedHashMap newLinkedHashMap(int capacity) { - return new LinkedHashMap(capacity); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static LinkedHashMap newLinkedHashMap(@NotNull Map map) { - return new LinkedHashMap(map); - } - - @NotNull - @Contract(value = "_,_ -> new", pure = true) - public static LinkedHashMap newLinkedHashMap(@NotNull Pair first, @NotNull Pair... entries) { - LinkedHashMap map = newLinkedHashMap(); - map.put(first.getFirst(), first.getSecond()); - for (Pair entry : entries) { - map.put(entry.getFirst(), entry.getSecond()); - } - return map; - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static LinkedList newLinkedList() { - return new LinkedList(); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static LinkedList newLinkedList(@NotNull T... elements) { - final LinkedList list = newLinkedList(); - Collections.addAll(list, elements); - return list; - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static LinkedList newLinkedList(@NotNull Iterable elements) { - return copy(ContainerUtilRt.newLinkedList(), elements); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static ArrayList newArrayList() { - return new ArrayList(); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static ArrayList newArrayList(@NotNull T... elements) { - ArrayList list = newArrayListWithCapacity(elements.length); - Collections.addAll(list, elements); - return list; - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static ArrayList newArrayList(@NotNull Iterable elements) { - if (elements instanceof Collection) { - @SuppressWarnings("unchecked") Collection collection = (Collection)elements; - return new ArrayList(collection); - } - return copy(ContainerUtilRt.newArrayList(), elements); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static ArrayList newArrayListWithCapacity(int size) { - return new ArrayList(size); - } - - @NotNull - private static > C copy(@NotNull C collection, @NotNull Iterable elements) { - for (T element : elements) { - collection.add(element); - } - return collection; - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static HashSet newHashSet() { - return new java.util.HashSet(); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static HashSet newHashSet(int initialCapacity) { - return new java.util.HashSet(initialCapacity); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static HashSet newHashSet(@NotNull T... elements) { - return new java.util.HashSet(Arrays.asList(elements)); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static HashSet newHashSet(@NotNull Iterable elements) { - if (elements instanceof Collection) { - @SuppressWarnings("unchecked") Collection collection = (Collection)elements; - return new java.util.HashSet(collection); - } - return newHashSet(elements.iterator()); - } - - @NotNull - public static HashSet newHashSet(@NotNull Iterator iterator) { - HashSet set = newHashSet(); - while (iterator.hasNext()) set.add(iterator.next()); - return set; - } - - @Contract(value = " -> new", pure = true) - @NotNull - public static LinkedHashSet newLinkedHashSet() { - return new LinkedHashSet(); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static LinkedHashSet newLinkedHashSet(@NotNull T... elements) { - return newLinkedHashSet(Arrays.asList(elements)); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static LinkedHashSet newLinkedHashSet(@NotNull Iterable elements) { - if (elements instanceof Collection) { - @SuppressWarnings("unchecked") Collection collection = (Collection)elements; - return new LinkedHashSet(collection); - } - return copy(ContainerUtilRt.newLinkedHashSet(), elements); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static TreeSet newTreeSet() { - return new TreeSet(); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static TreeSet newTreeSet(@NotNull T... elements) { - TreeSet set = newTreeSet(); - Collections.addAll(set, elements); - return set; - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static TreeSet newTreeSet(@NotNull Iterable elements) { - return copy(ContainerUtilRt.newTreeSet(), elements); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static TreeSet newTreeSet(@Nullable Comparator comparator) { - return new TreeSet(comparator); - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static Stack newStack() { - return new Stack(); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static Stack newStack(@NotNull Collection elements) { - return new Stack(elements); - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static Stack newStack(@NotNull T... initial) { - return new Stack(Arrays.asList(initial)); - } - - /** - * A variant of {@link Collections#emptyList()}, - * except that {@link #toArray()} here does not create garbage {@code new Object[0]} constantly. - */ - private static class EmptyList extends AbstractList implements RandomAccess, Serializable { - private static final long serialVersionUID = 1L; - - private static final EmptyList INSTANCE = new EmptyList(); - - @Override - public int size() { - return 0; - } - - @Override - public boolean contains(Object obj) { - return false; - } - - @Override - public T get(int index) { - throw new IndexOutOfBoundsException("Index: " + index); - } - - @NotNull - @Override - public Object[] toArray() { - return ArrayUtilRt.EMPTY_OBJECT_ARRAY; - } - - @NotNull - @Override - public E[] toArray(@NotNull E[] a) { - if (a.length != 0) { - a[0] = null; - } - return a; - } - - @NotNull - @Override - public Iterator iterator() { - return EmptyIterator.getInstance(); - } - - @NotNull - @Override - public ListIterator listIterator() { - return EmptyListIterator.getInstance(); - } - - @Override - public boolean containsAll(@NotNull Collection c) { - return c.isEmpty(); - } - - @Override - @Contract(pure = true) - public boolean isEmpty() { - return true; - } - - @Override - @Contract(pure = true) - public boolean equals(Object o) { - return o instanceof List && ((List)o).isEmpty(); - } - - @Override - public int hashCode() { - return 1; - } - } - - @NotNull - @Contract(pure=true) - public static List emptyList() { - //noinspection unchecked - return (List)EmptyList.INSTANCE; - } - - @NotNull - @Contract(value = " -> new", pure = true) - public static CopyOnWriteArrayList createEmptyCOWList() { - // does not create garbage new Object[0] - return new CopyOnWriteArrayList(ContainerUtilRt.emptyList()); - } - - /** - * @see #addIfNotNull(Collection, Object) - */ - @Deprecated - public static void addIfNotNull(@Nullable T element, @NotNull Collection result) { - if (element != null) { - result.add(element); - } - } - - public static void addIfNotNull(@NotNull Collection result, @Nullable T element) { - if (element != null) { - result.add(element); - } - } - - /** - * @return read-only list consisting of the elements from array converted by mapper - */ - @NotNull - @Contract(pure=true) - public static List map2List(@NotNull T[] array, @NotNull Function mapper) { - return map2List(Arrays.asList(array), mapper); - } - - /** - * @param collection an input collection to process - * @param mapping a side-effect free function which transforms collection elements - * @return read-only list consisting of the elements from the array converted by mapping with nulls filtered out - */ - @NotNull - @Contract(pure=true) - public static List mapNotNull(@NotNull Collection collection, @NotNull Function mapping) { - if (collection.isEmpty()) { - return emptyList(); - } - - List result = new ArrayList(collection.size()); - for (T t : collection) { - final V o = mapping.fun(t); - if (o != null) { - result.add(o); - } - } - return result.isEmpty() ? ContainerUtilRt.emptyList() : result; - } - - /** - * @return read-only list consisting of the elements from collection converted by mapper - */ - @NotNull - @Contract(pure=true) - public static List map2List(@NotNull Collection collection, @NotNull Function mapper) { - if (collection.isEmpty()) return emptyList(); - List list = new ArrayList(collection.size()); - for (final T t : collection) { - list.add(mapper.fun(t)); - } - return list; - } - - /** - * @return read-only list consisting key-value pairs of a map - */ - @NotNull - @Contract(pure=true) - public static List> map2List(@NotNull Map map) { - if (map.isEmpty()) return emptyList(); - final List> result = new ArrayList>(map.size()); - for (Map.Entry entry : map.entrySet()) { - result.add(Pair.create(entry.getKey(), entry.getValue())); - } - return result; - } - - /** - * @return read-only set consisting of the elements from collection converted by mapper - */ - @NotNull - @Contract(pure=true) - public static Set map2Set(@NotNull T[] collection, @NotNull Function mapper) { - return map2Set(Arrays.asList(collection), mapper); - } - - /** - * @return read-only set consisting of the elements from collection converted by mapper - */ - @NotNull - @Contract(pure=true) - public static Set map2Set(@NotNull Collection collection, @NotNull Function mapper) { - if (collection.isEmpty()) return Collections.emptySet(); - Set set = new HashSet(collection.size()); - for (final T t : collection) { - set.add(mapper.fun(t)); - } - return set; - } - - /** - * @deprecated use {@link List#toArray(Object[])} instead - */ - @Deprecated - @NotNull - public static T[] toArray(@NotNull List collection, @NotNull T[] array) { - return collection.toArray(array); - } - - /** - * @deprecated use {@link Collection#toArray(Object[])} instead - */ - @Deprecated - @NotNull - public static T[] toArray(@NotNull Collection c, @NotNull T[] sample) { - return c.toArray(sample); - } - - @Nullable - @Contract(pure=true) - public static > T getLastItem(@Nullable L list, @Nullable T def) { - return isEmpty(list) ? def : list.get(list.size() - 1); - } - - @Nullable - @Contract(pure=true) - public static > T getLastItem(@Nullable L list) { - return getLastItem(list, null); - } - - @Contract(value = "null -> true", pure = true) - public static boolean isEmpty(@Nullable Collection collection) { - return collection == null || collection.isEmpty(); - } - - @Nullable - @Contract(pure=true) - public static V find(@NotNull Iterable iterable, @NotNull Condition condition) { - return find(iterable.iterator(), condition); - } - - @Nullable - public static V find(@NotNull Iterator iterator, @NotNull Condition condition) { - while (iterator.hasNext()) { - V value = iterator.next(); - if (condition.value(value)) return value; - } - return null; - } - - @Contract(pure=true) - public static int indexOf(@NotNull List list, @NotNull Condition condition) { - for (int i = 0, listSize = list.size(); i < listSize; i++) { - T t = list.get(i); - if (condition.value(t)) { - return i; - } - } - return -1; - } - -} diff --git a/kotlin-bundled-compiler/src/com/intellij/util/containers/LinkedMultiMap.java b/kotlin-bundled-compiler/src/com/intellij/util/containers/LinkedMultiMap.java new file mode 100644 index 000000000..d3aad10fc --- /dev/null +++ b/kotlin-bundled-compiler/src/com/intellij/util/containers/LinkedMultiMap.java @@ -0,0 +1,5 @@ +package com.intellij.util.containers; + +@Deprecated +public class LinkedMultiMap extends MultiMap { +} \ No newline at end of file diff --git a/kotlin-bundled-compiler/src/com/intellij/util/containers/MultiMap.java b/kotlin-bundled-compiler/src/com/intellij/util/containers/MultiMap.java index a3d0060f0..528011d3e 100644 --- a/kotlin-bundled-compiler/src/com/intellij/util/containers/MultiMap.java +++ b/kotlin-bundled-compiler/src/com/intellij/util/containers/MultiMap.java @@ -9,8 +9,9 @@ import org.jetbrains.annotations.Nullable; import java.io.Serializable; -import java.util.*; import java.util.HashMap; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * Consider to use factory methods {@link #createLinked()}, {@link #createSet()}, {@link #createSmart()}, {@link #create(TObjectHashingStrategy)} instead of override. @@ -29,6 +30,10 @@ public MultiMap() { myMap = createMap(); } + public MultiMap(@NotNull Map> mapImpl) { + myMap = mapImpl; + } + public MultiMap(@NotNull MultiMap toCopy) { this(); putAllValues(toCopy); @@ -36,7 +41,7 @@ public MultiMap(@NotNull MultiMap toCopy) { @NotNull public MultiMap copy() { - return new MultiMap(this); + return new MultiMap<>(this); } public MultiMap(int initialCapacity, float loadFactor) { @@ -317,13 +322,23 @@ protected Map> createMap() { }; } + @NotNull + public static MultiMap createConcurrent() { + return new MultiMap(new ConcurrentHashMap<>()) { + @NotNull + protected Collection createCollection() { + return ContainerUtil.createLockFreeCopyOnWriteList(); + } + }; + } + @NotNull public static MultiMap createConcurrentSet() { return new ConcurrentMultiMap() { @NotNull @Override protected Collection createCollection() { - return ContainerUtil.newConcurrentSet(); + return Collections.newSetFromMap(new ConcurrentHashMap<>()); } @NotNull diff --git a/kotlin-bundled-compiler/src/com/intellij/util/containers/ObjectIntHashMap.java b/kotlin-bundled-compiler/src/com/intellij/util/containers/ObjectIntHashMap.java new file mode 100644 index 000000000..c0d47b902 --- /dev/null +++ b/kotlin-bundled-compiler/src/com/intellij/util/containers/ObjectIntHashMap.java @@ -0,0 +1,60 @@ +package com.intellij.util.containers; + +import gnu.trove.TObjectHashingStrategy; +import gnu.trove.TObjectIntHashMap; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Set; + +public class ObjectIntHashMap extends TObjectIntHashMap implements ObjectIntMap { + public ObjectIntHashMap(int initialCapacity) { + super(initialCapacity); + } + + public ObjectIntHashMap(@NotNull TObjectHashingStrategy strategy) { + super(strategy); + } + + public ObjectIntHashMap(int initialCapacity, @NotNull TObjectHashingStrategy strategy) { + super(initialCapacity, strategy); + } + + public ObjectIntHashMap() { + super(); + } + + public final int get(@NotNull K key) { + return this.get(key, -1); + } + + @Override + public @NotNull + Set keySet() { + return Collections.emptySet(); + } + + @NotNull + @Override + public int[] values() { + return Arrays.copyOf(_values, _values.length); + } + + @Override + public @NotNull + Iterable> entries() { + return Collections.emptySet(); + } + + public final int get(K key, int defaultValue) { + int index = this.index(key); + return index < 0 ? defaultValue : this._values[index]; + } + + public int put(K key, int value, int defaultValue) { + int index = this.index(key); + int prev = super.put(key, value); + return index >= 0 ? prev : defaultValue; + } +} \ No newline at end of file diff --git a/kotlin-bundled-compiler/src/it/unimi/dsi/fastutil/ints/IntOpenHashSet.java b/kotlin-bundled-compiler/src/it/unimi/dsi/fastutil/ints/IntOpenHashSet.java new file mode 100644 index 000000000..26ffe1364 --- /dev/null +++ b/kotlin-bundled-compiler/src/it/unimi/dsi/fastutil/ints/IntOpenHashSet.java @@ -0,0 +1,379 @@ +package it.unimi.dsi.fastutil.ints; + +import it.unimi.dsi.fastutil.Hash; +import it.unimi.dsi.fastutil.HashCommon; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.NoSuchElementException; + +public class IntOpenHashSet extends AbstractIntSet implements Hash, Serializable, Cloneable { + private static final long serialVersionUID = 0L; + protected transient int[] key; + protected transient int mask; + protected transient boolean containsNull; + protected transient int n; + protected transient int maxFill; + protected final transient int minN; + protected int size; + protected final float f; + + public IntOpenHashSet(int expected, float f) { + if (!(f <= 0.0F) && !(f >= 1.0F)) { + if (expected < 0) { + throw new IllegalArgumentException("The expected number of elements must be nonnegative"); + } else { + this.f = f; + this.minN = this.n = HashCommon.arraySize(expected, f); + this.mask = this.n - 1; + this.maxFill = HashCommon.maxFill(this.n, f); + this.key = new int[this.n + 1]; + } + } else { + throw new IllegalArgumentException("Load factor must be greater than 0 and smaller than 1"); + } + } + + public IntOpenHashSet(int expected) { + this(expected, 0.75F); + } + + public IntOpenHashSet() { + this(16, 0.75F); + } + + private int realSize() { + return this.containsNull ? this.size - 1 : this.size; + } + + private void ensureCapacity(int capacity) { + int needed = HashCommon.arraySize(capacity, this.f); + if (needed > this.n) { + this.rehash(needed); + } + + } + + private void tryCapacity(long capacity) { + int needed = (int)Math.min(1073741824L, Math.max(2L, HashCommon.nextPowerOfTwo((long)Math.ceil((double)((float)capacity / this.f))))); + if (needed > this.n) { + this.rehash(needed); + } + + } + + public boolean addAll(Collection c) { + if ((double)this.f <= 0.5D) { + this.ensureCapacity(c.size()); + } else { + this.tryCapacity((long)(this.size() + c.size())); + } + + return super.addAll(c); + } + + public boolean add(int k) { + if (k == 0) { + if (this.containsNull) { + return false; + } + + this.containsNull = true; + } else { + int[] key = this.key; + int pos; + int curr; + if ((curr = key[pos = HashCommon.mix(k) & this.mask]) != 0) { + if (curr == k) { + return false; + } + + while((curr = key[pos = pos + 1 & this.mask]) != 0) { + if (curr == k) { + return false; + } + } + } + + key[pos] = k; + } + + if (this.size++ >= this.maxFill) { + this.rehash(HashCommon.arraySize(this.size + 1, this.f)); + } + + return true; + } + + protected final void shiftKeys(int pos) { + int[] key = this.key; + + while(true) { + int last = pos; + pos = pos + 1 & this.mask; + + int curr; + while(true) { + if ((curr = key[pos]) == 0) { + key[last] = 0; + return; + } + + int slot = HashCommon.mix(curr) & this.mask; + if (last <= pos) { + if (last >= slot || slot > pos) { + break; + } + } else if (last >= slot && slot > pos) { + break; + } + + pos = pos + 1 & this.mask; + } + + key[last] = curr; + } + } + + private boolean removeEntry(int pos) { + --this.size; + this.shiftKeys(pos); + if (this.n > this.minN && this.size < this.maxFill / 4 && this.n > 16) { + this.rehash(this.n / 2); + } + + return true; + } + + private boolean removeNullEntry() { + this.containsNull = false; + this.key[this.n] = 0; + --this.size; + if (this.n > this.minN && this.size < this.maxFill / 4 && this.n > 16) { + this.rehash(this.n / 2); + } + + return true; + } + + public boolean remove(int k) { + if (k == 0) { + return this.containsNull ? this.removeNullEntry() : false; + } else { + int[] key = this.key; + int curr; + int pos; + if ((curr = key[pos = HashCommon.mix(k) & this.mask]) == 0) { + return false; + } else if (k == curr) { + return this.removeEntry(pos); + } else { + while((curr = key[pos = pos + 1 & this.mask]) != 0) { + if (k == curr) { + return this.removeEntry(pos); + } + } + + return false; + } + } + } + + public boolean contains(int k) { + if (k == 0) { + return this.containsNull; + } else { + int[] key = this.key; + int curr; + int pos; + if ((curr = key[pos = HashCommon.mix(k) & this.mask]) == 0) { + return false; + } else if (k == curr) { + return true; + } else { + while((curr = key[pos = pos + 1 & this.mask]) != 0) { + if (k == curr) { + return true; + } + } + + return false; + } + } + } + + public void clear() { + if (this.size != 0) { + this.size = 0; + this.containsNull = false; + Arrays.fill(this.key, 0); + } + } + + public int size() { + return this.size; + } + + public boolean isEmpty() { + return this.size == 0; + } + + public IntIterator iterator() { + return new IntOpenHashSet.SetIterator(); + } + + protected void rehash(int newN) { + int[] key = this.key; + int mask = newN - 1; + int[] newKey = new int[newN + 1]; + int i = this.n; + + int pos; + for(int var7 = this.realSize(); var7-- != 0; newKey[pos] = key[i]) { + do { + --i; + } while(key[i] == 0); + + if (newKey[pos = HashCommon.mix(key[i]) & mask] != 0) { + while(newKey[pos = pos + 1 & mask] != 0) { + } + } + } + + this.n = newN; + this.mask = mask; + this.maxFill = HashCommon.maxFill(this.n, this.f); + this.key = newKey; + } + + public IntOpenHashSet clone() { + IntOpenHashSet c; + try { + c = (IntOpenHashSet)super.clone(); + } catch (CloneNotSupportedException var3) { + throw new InternalError(); + } + + c.key = (int[])this.key.clone(); + c.containsNull = this.containsNull; + return c; + } + + public int hashCode() { + int h = 0; + int j = this.realSize(); + + for(int i = 0; j-- != 0; ++i) { + while(this.key[i] == 0) { + ++i; + } + + h += this.key[i]; + } + + return h; + } + + private class SetIterator implements IntIterator { + int pos; + int last; + int c; + boolean mustReturnNull; + IntArrayList wrapped; + + private SetIterator() { + this.pos = IntOpenHashSet.this.n; + this.last = -1; + this.c = IntOpenHashSet.this.size; + this.mustReturnNull = IntOpenHashSet.this.containsNull; + } + + public boolean hasNext() { + return this.c != 0; + } + + public int nextInt() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } else { + --this.c; + if (this.mustReturnNull) { + this.mustReturnNull = false; + this.last = IntOpenHashSet.this.n; + return IntOpenHashSet.this.key[IntOpenHashSet.this.n]; + } else { + int[] key = IntOpenHashSet.this.key; + + while(--this.pos >= 0) { + if (key[this.pos] != 0) { + return key[this.last = this.pos]; + } + } + + this.last = -2147483648; + return this.wrapped.getInt(-this.pos - 1); + } + } + } + + private final void shiftKeys(int pos) { + int[] key = IntOpenHashSet.this.key; + + while(true) { + int last = pos; + pos = pos + 1 & IntOpenHashSet.this.mask; + + int curr; + while(true) { + if ((curr = key[pos]) == 0) { + key[last] = 0; + return; + } + + int slot = HashCommon.mix(curr) & IntOpenHashSet.this.mask; + if (last <= pos) { + if (last >= slot || slot > pos) { + break; + } + } else if (last >= slot && slot > pos) { + break; + } + + pos = pos + 1 & IntOpenHashSet.this.mask; + } + + if (pos < last) { + if (this.wrapped == null) { + this.wrapped = new IntArrayList(2); + } + + this.wrapped.add(key[pos]); + } + + key[last] = curr; + } + } + + public void remove() { + if (this.last == -1) { + throw new IllegalStateException(); + } else { + if (this.last == IntOpenHashSet.this.n) { + IntOpenHashSet.this.containsNull = false; + IntOpenHashSet.this.key[IntOpenHashSet.this.n] = 0; + } else { + if (this.pos < 0) { + IntOpenHashSet.this.remove(this.wrapped.getInt(-this.pos - 1)); + this.last = -1; + return; + } + + this.shiftKeys(this.last); + } + + --IntOpenHashSet.this.size; + this.last = -1; + } + } + } +} \ No newline at end of file diff --git a/kotlin-eclipse-aspects/.classpath b/kotlin-eclipse-aspects/.classpath deleted file mode 100644 index 9fcfb446e..000000000 --- a/kotlin-eclipse-aspects/.classpath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/kotlin-eclipse-aspects/.project b/kotlin-eclipse-aspects/.project deleted file mode 100644 index 2ff8cf783..000000000 --- a/kotlin-eclipse-aspects/.project +++ /dev/null @@ -1,42 +0,0 @@ - - - kotlin-eclipse-aspects - - - - - - org.jetbrains.kotlin.ui.kotlinBuilder - - - - - org.eclipse.ajdt.core.ajbuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.ajdt.ui.ajnature - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - org.jetbrains.kotlin.core.kotlinNature - - - - kotlin_bin - 2 - org.jetbrains.kotlin.core.filesystem:/kotlin-eclipse-aspects/kotlin_bin - - - diff --git a/kotlin-eclipse-aspects/.settings/org.eclipse.ajdt.ui.prefs b/kotlin-eclipse-aspects/.settings/org.eclipse.ajdt.ui.prefs deleted file mode 100644 index 03202ef91..000000000 --- a/kotlin-eclipse-aspects/.settings/org.eclipse.ajdt.ui.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.ajdt.aopxml=/kotlin-eclipse-aspects/META-INF/aop.xml diff --git a/kotlin-eclipse-aspects/.settings/org.eclipse.jdt.core.prefs b/kotlin-eclipse-aspects/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 9a57a84d6..000000000 --- a/kotlin-eclipse-aspects/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,297 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.kt -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 -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_annotation=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=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -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_method_declaration=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -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=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -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_lambda_body=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_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -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_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=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=80 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -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=true -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=false -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not 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_after_type_annotation=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_annotation_declaration=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_lambda_arrow=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_try=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=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=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=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_try=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=do not 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_lambda_arrow=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_try=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_parenthesized_expression_in_throw=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=do not 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_semicolon_in_try_resources=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=do not 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.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -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=120 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -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=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=false -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/kotlin-eclipse-aspects/.settings/org.eclipse.jdt.ui.prefs b/kotlin-eclipse-aspects/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index bddb247ef..000000000 --- a/kotlin-eclipse-aspects/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,3 +0,0 @@ -eclipse.preferences.version=1 -formatter_profile=_Kotlin -formatter_settings_version=12 diff --git a/kotlin-eclipse-aspects/META-INF/MANIFEST.MF b/kotlin-eclipse-aspects/META-INF/MANIFEST.MF index 846e0a835..4d2cec58e 100644 --- a/kotlin-eclipse-aspects/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-aspects/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-aspects Bundle-SymbolicName: org.jetbrains.kotlin.aspects -Bundle-Version: 0.8.21.qualifier +Bundle-Version: 1.6.21.qualifier Bundle-Activator: org.jetbrains.kotlin.aspects.Activator Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, @@ -14,7 +14,8 @@ Require-Bundle: org.eclipse.ui, org.eclipse.ltk.core.refactoring, org.jetbrains.kotlin.ui, org.eclipse.debug.core, - org.eclipse.jdt.debug + org.eclipse.jdt.debug, + org.eclipse.jdt.core.manipulation Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Bundle-Vendor: JetBrains diff --git a/kotlin-eclipse-aspects/META-INF/aop.xml b/kotlin-eclipse-aspects/META-INF/aop.xml index cfee69108..3443af126 100644 --- a/kotlin-eclipse-aspects/META-INF/aop.xml +++ b/kotlin-eclipse-aspects/META-INF/aop.xml @@ -16,4 +16,7 @@ + + + \ No newline at end of file diff --git a/kotlin-eclipse-aspects/pom.xml b/kotlin-eclipse-aspects/pom.xml index 82f26fe46..39ec6720e 100644 --- a/kotlin-eclipse-aspects/pom.xml +++ b/kotlin-eclipse-aspects/pom.xml @@ -1,53 +1,53 @@ - 4.0.0 + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + 4.0.0 - - ../pom.xml - kotlin.eclipse - kotlin.eclipse.plugin - 0.8.21-SNAPSHOT - + + ../pom.xml + kotlin.eclipse + kotlin.eclipse.plugin + 1.6.21-SNAPSHOT + - org.jetbrains.kotlin.aspects - eclipse-plugin + org.jetbrains.kotlin.aspects + eclipse-plugin - - - - - org.eclipse.tycho - tycho-compiler-plugin - - - **/*.aj - - - - - - org.codehaus.mojo - aspectj-maven-plugin - - - process-sources - compile - - 1.8 - 1.8 - 1.8 - src - ignore - true - - - compile - - - - - - + + + + + org.eclipse.tycho + tycho-compiler-plugin + + + **/*.aj + + + + + org.codehaus.mojo + aspectj-maven-plugin + 1.14.0 + + + process-sources + compile + + 11 + 11 + 11 + src + ignore + true + + + compile + + + + + + \ No newline at end of file diff --git a/kotlin-eclipse-core/.classpath b/kotlin-eclipse-core/.classpath deleted file mode 100644 index cc0549d89..000000000 --- a/kotlin-eclipse-core/.classpath +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/kotlin-eclipse-core/.gitignore b/kotlin-eclipse-core/.gitignore deleted file mode 100644 index 5e56e040e..000000000 --- a/kotlin-eclipse-core/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin diff --git a/kotlin-eclipse-core/.project b/kotlin-eclipse-core/.project deleted file mode 100644 index ed9c7efaa..000000000 --- a/kotlin-eclipse-core/.project +++ /dev/null @@ -1,41 +0,0 @@ - - - kotlin-eclipse-core - - - - - - org.jetbrains.kotlin.ui.kotlinBuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - org.jetbrains.kotlin.core.kotlinNature - - - - kotlin_bin - 2 - org.jetbrains.kotlin.core.filesystem:/kotlin-eclipse-core/kotlin_bin - - - diff --git a/kotlin-eclipse-core/.settings/org.eclipse.jdt.core.prefs b/kotlin-eclipse-core/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index d2fd86c33..000000000 --- a/kotlin-eclipse-core/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,381 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.kt -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.jetbrains.annotations.NotNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.jetbrains.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=error -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=error -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 -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_annotation=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=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -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_method_declaration=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -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=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -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_lambda_body=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_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -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_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=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=80 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -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=true -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=false -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not 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_after_type_annotation=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_annotation_declaration=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_lambda_arrow=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_try=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=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=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=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_try=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=do not 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_lambda_arrow=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_try=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_parenthesized_expression_in_throw=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=do not 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_semicolon_in_try_resources=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=do not 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.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -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=120 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -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=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=false -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/kotlin-eclipse-core/.settings/org.eclipse.jdt.ui.prefs b/kotlin-eclipse-core/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index d1db68c03..000000000 --- a/kotlin-eclipse-core/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,56 +0,0 @@ -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -formatter_profile=_Kotlin -formatter_settings_version=12 -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=false -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=false -sp_cleanup.correct_indentation=false -sp_cleanup.format_source_code=false -sp_cleanup.format_source_code_changes_only=false -sp_cleanup.make_local_variable_final=false -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=true -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=true -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=false -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=false -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=false -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/kotlin-eclipse-core/META-INF/MANIFEST.MF b/kotlin-eclipse-core/META-INF/MANIFEST.MF index 63d3a54e5..6c0f41ddf 100644 --- a/kotlin-eclipse-core/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-core Bundle-SymbolicName: org.jetbrains.kotlin.core;singleton:=true -Bundle-Version: 0.8.21.qualifier +Bundle-Version: 1.6.21.qualifier Bundle-Activator: org.jetbrains.kotlin.core.Activator Bundle-Vendor: JetBrains Require-Bundle: org.jetbrains.kotlin.bundled-compiler, @@ -14,7 +14,15 @@ Require-Bundle: org.jetbrains.kotlin.bundled-compiler, org.eclipse.core.expressions, org.eclipse.jdt.junit Bundle-ActivationPolicy: lazy -Import-Package: org.eclipse.core.filesystem, +Import-Package: com.intellij.codeInsight, + com.intellij.openapi.components, + kotlin.script.experimental.annotations, + kotlin.script.experimental.api, + kotlin.script.experimental.dependencies, + kotlin.script.experimental.host, + kotlin.script.experimental.util, + kotlin.script.experimental.jvm, + org.eclipse.core.filesystem, org.eclipse.core.resources, org.eclipse.debug.internal.ui.viewers, org.eclipse.jdt.core, @@ -25,7 +33,8 @@ Import-Package: org.eclipse.core.filesystem, org.eclipse.jdt.internal.debug.core.breakpoints, org.eclipse.jdt.junit.launcher, org.eclipse.jdt.ui, - org.eclipse.jface.text + org.eclipse.jface.text, + org.jetbrains.kotlin.resolve.sam Export-Package: org.jetbrains.kotlin.core, org.jetbrains.kotlin.core.asJava, org.jetbrains.kotlin.core.builder, diff --git a/kotlin-eclipse-core/pom.xml b/kotlin-eclipse-core/pom.xml index b7d60acf2..775a4a54d 100644 --- a/kotlin-eclipse-core/pom.xml +++ b/kotlin-eclipse-core/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.core @@ -22,7 +22,9 @@ org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} - + + 11 + compile @@ -33,6 +35,15 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 8 + 8 + + diff --git a/kotlin-eclipse-core/preferences.ini b/kotlin-eclipse-core/preferences.ini index c71553e45..027eee32f 100644 --- a/kotlin-eclipse-core/preferences.ini +++ b/kotlin-eclipse-core/preferences.ini @@ -11,4 +11,4 @@ compilerPlugins/jpa/jarPath=$KOTLIN_HOME/lib/noarg-compiler-plugin.jar compilerPlugins/jpa/args=org.jetbrains.kotlin.noarg:preset=jpa compilerPlugins/sam-with-receiver/active=false compilerPlugins/sam-with-receiver/jarPath=$KOTLIN_HOME/lib/sam-with-receiver-compiler-plugin.jar -codeStyle/codeStyleId=KOTLIN_OLD_DEFAULTS +codeStyle/codeStyleId=KOTLIN_OFFICIAL diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/KotlinLightClassGeneration.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/KotlinLightClassGeneration.kt index b693894d0..72126b6fd 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/KotlinLightClassGeneration.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/KotlinLightClassGeneration.kt @@ -16,28 +16,26 @@ *******************************************************************************/ package org.jetbrains.kotlin.core.asJava -import org.eclipse.core.internal.jobs.JobStatus import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IProject -import org.eclipse.core.resources.WorkspaceJob -import org.eclipse.core.runtime.IProgressMonitor -import org.eclipse.core.runtime.IStatus import org.eclipse.core.runtime.Path import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.codegen.KotlinCodegenFacade import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.filesystem.KotlinLightClassManager import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.model.KotlinJavaManager +import org.jetbrains.kotlin.core.preferences.languageVersionSettings import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtCodeFragment import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtScript -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtCodeFragment object KotlinLightClassGeneration { @@ -55,13 +53,20 @@ object KotlinLightClassGeneration { eclipseProject: IProject, jetFiles: List, requestedClassName: String): GenerationState { + + val tempProps = KotlinEnvironment.getEnvironment(eclipseProject).compilerProperties + + val tempConfig = CompilerConfiguration().apply { + put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, tempProps.languageVersionSettings) + } + val state = GenerationState.Builder( KotlinEnvironment.getEnvironment(eclipseProject).project, LightClassBuilderFactory(), analysisResult.moduleDescriptor, analysisResult.bindingContext, jetFiles, - CompilerConfiguration.EMPTY) + tempConfig) .generateDeclaredClassFilter(object : GenerationState.GenerateClassFilter() { override fun shouldGenerateCodeFragment(script: KtCodeFragment): Boolean = false @@ -73,8 +78,8 @@ object KotlinLightClassGeneration { return checkByInternalName(internalName, requestedClassName) } - override fun shouldGeneratePackagePart(jetFile: KtFile): Boolean { - val internalName = JvmFileClassUtil.getFileClassInternalName(jetFile) + override fun shouldGeneratePackagePart(ktFile: KtFile): Boolean { + val internalName = JvmFileClassUtil.getFileClassInternalName(ktFile) return checkByInternalName(internalName, requestedClassName) } diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/LightClassBuilderFactory.java b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/LightClassBuilderFactory.java index 6e1d69928..5b871cd7b 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/LightClassBuilderFactory.java +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/LightClassBuilderFactory.java @@ -54,10 +54,10 @@ private void saveJvmSignature(@NotNull JvmDeclarationOrigin origin, @NotNull Str if (element != null) { Set> userData = element.getUserData(JVM_SIGNATURE); if (userData == null) { - userData = Collections.newSetFromMap(new ConcurrentHashMap, Boolean>()); + userData = Collections.newSetFromMap(new ConcurrentHashMap<>()); element.putUserData(JVM_SIGNATURE, userData); } - userData.add(new Pair(desc, name)); + userData.add(new Pair<>(desc, name)); } } }; @@ -77,4 +77,4 @@ public byte[] asBytes(ClassBuilder builder) { @Override public void close() { } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt index e21836971..a2e27fa45 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt @@ -16,6 +16,7 @@ *******************************************************************************/ package org.jetbrains.kotlin.core.builder +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtilRt @@ -33,21 +34,23 @@ import org.eclipse.jdt.core.IClasspathEntry import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.JavaCore import org.eclipse.jface.text.IDocument +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreApplicationEnvironment import org.jetbrains.kotlin.core.log.KotlinLogger -import org.jetbrains.kotlin.core.model.KotlinLightVirtualFile -import org.jetbrains.kotlin.core.model.KotlinNature -import org.jetbrains.kotlin.core.model.KotlinScriptEnvironment -import org.jetbrains.kotlin.core.model.getEnvironment +import org.jetbrains.kotlin.core.model.* import org.jetbrains.kotlin.core.utils.ProjectUtils +import org.jetbrains.kotlin.core.utils.asFile +import org.jetbrains.kotlin.core.utils.javaProject import org.jetbrains.kotlin.core.utils.sourceFolders import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider import java.io.File import java.util.Collections import java.util.HashSet import java.util.concurrent.ConcurrentHashMap +import kotlin.script.experimental.host.FileScriptSource interface PsiFilesStorage { fun getPsiFile(eclipseFile: IFile): KtFile @@ -81,8 +84,9 @@ private class ScriptsFilesStorage : PsiFilesStorage { return getPsiFile(file) } - override fun isApplicable(file: IFile): Boolean = file.fileExtension == "kts" - + override fun isApplicable(file: IFile): Boolean = + EclipseScriptDefinitionProvider.isScript(FileScriptSource(file.asFile)) + override fun removeFile(file: IFile) { cachedKtFiles.remove(file) } diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompiler.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompiler.kt index cdc60315f..f1a08a618 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompiler.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompiler.kt @@ -4,79 +4,85 @@ import com.intellij.openapi.util.Disposer import org.eclipse.jdt.core.IJavaProject import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.EXCEPTION +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.core.filesystem.KotlinLightClassManager.Companion.KOTLIN_TOUCHED_FILES_FILE_NAME import org.jetbrains.kotlin.core.launch.CompilerOutputData import org.jetbrains.kotlin.core.launch.CompilerOutputParser import org.jetbrains.kotlin.core.launch.KotlinCLICompiler import org.jetbrains.kotlin.core.model.KOTLIN_COMPILER_PATH import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.preferences.CompilerPlugin +import org.jetbrains.kotlin.core.utils.DependencyResolverException import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.incremental.makeIncrementally -import java.io.BufferedReader -import java.io.ByteArrayOutputStream -import java.io.File -import java.io.PrintStream -import java.io.Reader -import java.io.StringReader +import java.io.* object KotlinCompiler { private fun compileKotlinFiles( - javaProject: IJavaProject, - compilation: (IJavaProject, File, List) -> KotlinCompilerResult + javaProject: IJavaProject, + compilation: (IJavaProject, File, List) -> KotlinCompilerResult ): KotlinCompilerResult = - ProjectUtils.getSrcOutDirectories(javaProject) - .groupingBy { it.second }.fold(mutableListOf()) { list, key -> - list.apply { add(key.first) } - }.map { (out, sources) -> - compilation(javaProject, out, sources) - }.fold(KotlinCompilerResult(true, CompilerOutputData())) { previous, current -> - KotlinCompilerResult(previous.result and current.result, CompilerOutputData().apply { - previous.compilerOutput.list.union(current.compilerOutput.list).forEach { - add(it.messageSeverity, it.message, it.messageLocation) + ProjectUtils.getSrcOutDirectories(javaProject) + .groupingBy { it.second }.fold(mutableListOf()) { list, key -> + list.apply { add(key.first) } + }.onEach { (out) -> + val tempFile = File(out, KOTLIN_TOUCHED_FILES_FILE_NAME).takeIf { it.exists() } + tempFile?.readLines()?.map(::File)?.flatMap { tempFileToDelete -> + val tempName = tempFileToDelete.nameWithoutExtension + val tempFiles = tempFileToDelete.parentFile?.listFiles(FileFilter { it.name == "$tempName.class" || (it.name.startsWith("$tempName$") && it.name.endsWith(".class")) }) + tempFiles?.toList() ?: emptyList() + }?.distinct()?.forEach(File::delete) + tempFile?.delete() + out.walkTopDown().filter { it.extension == "kt" }.forEach { it.delete() } + }.map { (out, sources) -> + compilation(javaProject, out, sources) + }.fold(KotlinCompilerResult(true, CompilerOutputData())) { previous, current -> + KotlinCompilerResult(previous.result and current.result, CompilerOutputData().apply { + previous.compilerOutput.list.union(current.compilerOutput.list).forEach { + add(it.messageSeverity, it.message, it.messageLocation) + } + }) } - }) - } @JvmStatic fun compileKotlinFiles(javaProject: IJavaProject): KotlinCompilerResult = - compileKotlinFiles(javaProject) { project, path, sources -> - execKotlinCompiler(configureCompilerArguments(project, path.absolutePath, sources)) - } + compileKotlinFiles(javaProject) { project, path, sources -> + execKotlinCompiler(configureCompilerArguments(project, path.absolutePath, sources)) + } @JvmStatic fun compileIncrementallyFiles( - javaProject: IJavaProject + javaProject: IJavaProject ): KotlinCompilerResult = - compileKotlinFiles(javaProject) { project, path, sources -> - execIncrementalKotlinCompiler(project, path.absoluteFile, sources) - } + compileKotlinFiles(javaProject) { project, path, sources -> + execIncrementalKotlinCompiler(project, path.absoluteFile, sources) + } private fun execIncrementalKotlinCompiler( - javaProject: IJavaProject, - outputDir: File, - sourceDirs: List + javaProject: IJavaProject, + outputDir: File, + sourceDirs: List ): KotlinCompilerResult { val arguments = getCompilerArguments(javaProject, outputDir) val messageCollector = CompilerMessageCollector() - val disposable = Disposer.newDisposable() + val disposable = Disposer.newDisposable("Incremental compilation") val config = CompilerConfiguration().apply { put(JVMConfigurationKeys.NO_JDK, true) put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) put(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT, KOTLIN_COMPILER_PATH) } KotlinCoreEnvironment.getOrCreateApplicationEnvironmentForProduction(disposable, config) - var cacheDir = File("${outputDir.parentFile.absolutePath}/cache").also { it.mkdirs() } + val cacheDir = File("${outputDir.parentFile.absolutePath}/cache").also { it.mkdirs() } makeIncrementally(cacheDir, sourceDirs, arguments, messageCollector) return messageCollector.getCompilerResult() } @@ -88,7 +94,7 @@ object KotlinCompiler { private fun getCompilerArguments(javaProject: IJavaProject, outputDir: File) = K2JVMCompilerArguments().apply { val kotlinProperties = - KotlinEnvironment.getEnvironment(javaProject.project).compilerProperties + KotlinEnvironment.getEnvironment(javaProject.project).compilerProperties kotlinHome = ProjectUtils.ktHome destination = outputDir.absolutePath @@ -122,17 +128,20 @@ object KotlinCompiler { pluginClasspaths = pluginClasspathsList.toTypedArray() pluginOptions = pluginOptionsList.toTypedArray() - classpath = ProjectUtils.collectClasspathWithDependenciesForLaunch(javaProject, jdkUndefined) - .joinToString(separator = System.getProperty("path.separator")) { it.absolutePath } - + val tempFiles = try { + ProjectUtils.collectClasspathWithDependenciesForLaunch(javaProject, jdkUndefined) + } catch (e: DependencyResolverException) { + e.resolvedFiles + } + classpath = tempFiles.joinToString(separator = System.getProperty("path.separator")) { it.absolutePath } } private fun configureCompilerArguments( - javaProject: IJavaProject, outputDir: String, sourceDirs: List + javaProject: IJavaProject, outputDir: String, sourceDirs: List ): Array = with(mutableListOf()) { val kotlinProperties = - KotlinEnvironment.getEnvironment(javaProject.project).compilerProperties + KotlinEnvironment.getEnvironment(javaProject.project).compilerProperties add("-kotlin-home") add(ProjectUtils.ktHome) @@ -164,9 +173,14 @@ object KotlinCompiler { } add("-classpath") - ProjectUtils.collectClasspathWithDependenciesForLaunch(javaProject, jdkUndefined) - .joinToString(separator = System.getProperty("path.separator")) { it.absolutePath } - .let { add(it) } + + val tempFiles = try { + ProjectUtils.collectClasspathWithDependenciesForLaunch(javaProject, jdkUndefined) + } catch (e: DependencyResolverException) { + e.resolvedFiles + } + + add(tempFiles.joinToString(separator = System.getProperty("path.separator")) { it.absolutePath }) add("-d") add(outputDir) @@ -194,15 +208,17 @@ object KotlinCompiler { val compilerOutput = CompilerOutputData() override fun report( - severity: CompilerMessageSeverity, - message: String, - location: CompilerMessageSourceLocation? + severity: CompilerMessageSeverity, + message: String, + location: CompilerMessageSourceLocation? ) { hasErrors == hasErrors || severity.isError severities.add(severity) if (location != null) { val messageLocation = CompilerMessageLocation.create(location.path, location.line, location.column, location.lineContent) compilerOutput.add(severity, message, messageLocation) + } else { + compilerOutput.add(severity, message, null) } } @@ -213,7 +229,7 @@ object KotlinCompiler { } fun getCompilerResult(): KotlinCompilerResult = - KotlinCompilerResult(severities.firstOrNull { it == ERROR || it == EXCEPTION } == null, compilerOutput) + KotlinCompilerResult(severities.firstOrNull { it == ERROR || it == EXCEPTION } == null, compilerOutput) } private fun parseCompilerOutput(reader: Reader): KotlinCompilerResult { diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompilerUtils.java b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompilerUtils.java deleted file mode 100644 index 3286b9d2a..000000000 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompilerUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright 2010-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package org.jetbrains.kotlin.core.compiler; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.debug.core.DebugPlugin; -import org.eclipse.debug.core.IStatusHandler; -import org.eclipse.jdt.core.IJavaProject; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.core.Activator; -import org.jetbrains.kotlin.core.launch.CompilerOutputData; - -public class KotlinCompilerUtils { - - public static KotlinCompilerResult compileWholeProject(@NotNull IJavaProject javaProject) throws CoreException { - return KotlinCompiler.compileKotlinFiles(javaProject); - } - - public static KotlinCompilerResult compileProjectIncrementally(@NotNull IJavaProject javaProject) { - return KotlinCompiler.compileIncrementallyFiles(javaProject); - } - - public static void handleCompilerOutput(@NotNull CompilerOutputData compilerOutput) throws CoreException { - IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 1, "", null); - IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status); - - if (handler != null) { - handler.handleStatus(status, compilerOutput); - } - } -} diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompilerUtils.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompilerUtils.kt new file mode 100644 index 000000000..6c57deec4 --- /dev/null +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompilerUtils.kt @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.kotlin.core.compiler + +import org.jetbrains.kotlin.core.compiler.KotlinCompiler.compileKotlinFiles +import org.jetbrains.kotlin.core.compiler.KotlinCompiler.compileIncrementallyFiles +import org.eclipse.core.runtime.CoreException +import org.eclipse.jdt.core.IJavaProject +import org.eclipse.core.runtime.IStatus +import org.eclipse.core.runtime.Status +import org.eclipse.debug.core.IStatusHandler +import org.eclipse.debug.core.DebugPlugin +import org.jetbrains.kotlin.core.Activator +import org.jetbrains.kotlin.core.launch.CompilerOutputData + +object KotlinCompilerUtils { + + fun compileWholeProject(javaProject: IJavaProject): KotlinCompilerResult = compileKotlinFiles(javaProject) + + fun compileProjectIncrementally(javaProject: IJavaProject): KotlinCompilerResult = + compileIncrementallyFiles(javaProject) + + fun handleCompilerOutput(compilerOutput: CompilerOutputWithProject) { + val status: IStatus = Status(IStatus.ERROR, Activator.PLUGIN_ID, 1, "", null) + val handler = DebugPlugin.getDefault().getStatusHandler(status) + handler?.handleStatus(status, compilerOutput) + } + + data class CompilerOutputWithProject(val data: CompilerOutputData, val project: IJavaProject) +} \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinLightClassManager.java b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinLightClassManager.java deleted file mode 100644 index 5a599c8bb..000000000 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinLightClassManager.java +++ /dev/null @@ -1,307 +0,0 @@ -package org.jetbrains.kotlin.core.filesystem; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.eclipse.core.internal.jobs.JobStatus; -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.resources.WorkspaceJob; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; -import org.eclipse.jdt.internal.core.util.LRUCache; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.core.asJava.LightClassFile; -import org.jetbrains.kotlin.core.builder.KotlinPsiManager; -import org.jetbrains.kotlin.core.log.KotlinLogger; -import org.jetbrains.kotlin.core.model.KotlinEnvironment; -import org.jetbrains.kotlin.core.model.KotlinJavaManager; -import org.jetbrains.kotlin.core.utils.ProjectUtils; -import org.jetbrains.kotlin.fileClasses.FileClasses; -import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.psi.KtClassOrObject; -import org.jetbrains.kotlin.psi.KtFile; -import org.jetbrains.kotlin.psi.KtNamedFunction; -import org.jetbrains.kotlin.psi.KtProperty; -import org.jetbrains.kotlin.psi.KtSecondaryConstructor; -import org.jetbrains.kotlin.psi.KtVisitorVoid; - -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.util.PsiTreeUtil; - -public class KotlinLightClassManager { - private static final int LIGHT_CLASSES_CACHE_SIZE = 300; - - private static final String WORKSPACE_JOB_ID = "updateLightClassesJob"; - - private final LRUCache cachedLightClasses = new LRUCache(LIGHT_CLASSES_CACHE_SIZE); - - private final IProject project; - - private final ConcurrentMap> sourceFiles = new ConcurrentHashMap<>(); - - @NotNull - public static KotlinLightClassManager getInstance(@NotNull IProject project) { - Project ideaProject = KotlinEnvironment.Companion.getEnvironment(project).getProject(); - return ServiceManager.getService(ideaProject, KotlinLightClassManager.class); - } - - public KotlinLightClassManager(@NotNull IProject project) { - this.project = project; - } - - @Nullable - public synchronized byte[] getCachedLightClass(File file) { - Object lightClass = cachedLightClasses.get(file); - if (lightClass != null) return (byte[]) lightClass; - - return null; - } - - public synchronized void cacheLightClass(File file, @NotNull byte[] lightClass) { - cachedLightClasses.put(file, lightClass); - } - - public synchronized void removeLightClass(@NotNull File file) { - cachedLightClasses.flush(file); - } - - public void computeLightClassesSources() { - Map> newSourceFilesMap = new HashMap<>(); - for (IFile sourceFile : KotlinPsiManager.INSTANCE.getFilesByProject(project)) { - List lightClassesPaths = getLightClassesPaths(sourceFile); - - for (IPath path : lightClassesPaths) { - LightClassFile lightClassFile = new LightClassFile(project.getFile(path)); - - Set newSourceFiles = newSourceFilesMap.get(lightClassFile.asFile()); - if (newSourceFiles == null) { - newSourceFiles = new HashSet<>(); - newSourceFilesMap.put(lightClassFile.asFile(), newSourceFiles); - } - newSourceFiles.add(sourceFile); - } - } - - sourceFiles.clear(); - sourceFiles.putAll(newSourceFilesMap); - } - - public void updateLightClasses(@NotNull Set affectedFiles, Boolean resourceTreeBlocked) { - List toCreate = new ArrayList<>(); - List toRemove = new ArrayList<>(); - for (Map.Entry> entry : sourceFiles.entrySet()) { - IFile lightClassIFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(entry.getKey().getPath())); - if (lightClassIFile == null) continue; - - LightClassFile lightClassFile = new LightClassFile(lightClassIFile); - - if (!lightClassFile.exists()) { - toCreate.add(lightClassFile); - } - - for (IFile sourceFile : entry.getValue()) { - if (affectedFiles.contains(sourceFile)) { - toRemove.add(lightClassFile); - break; - } - } - } - if (resourceTreeBlocked) { - if (!toCreate.isEmpty() || !toRemove.isEmpty()) { - WorkspaceJob job = new WorkspaceJob(WORKSPACE_JOB_ID) { - @Override - public IStatus runInWorkspace(IProgressMonitor monitor) { - monitor.beginTask("Light class generation started", 0); - updateLightClasses(toCreate, toRemove); - monitor.done(); - return new JobStatus(0, this, "Light classes generation finished"); - } - }; - job.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().createRule( - project.getFolder(KotlinJavaManager.KOTLIN_BIN_FOLDER))); - job.schedule(); - } - } else { - updateLightClasses(toCreate, toRemove); - } - } - - private void updateLightClasses(List toCreate, List toRemove) { - for (LightClassFile lightClassFile: toCreate) { - createParentDirsFor(lightClassFile); - lightClassFile.createIfNotExists(); - } - for (LightClassFile lightClassFile: toRemove) { - removeLightClass(lightClassFile.asFile()); - lightClassFile.touchFile(); - } - cleanOutdatedLightClasses(project); - } - - public List getSourceFiles(@NotNull File file) { - if (sourceFiles.isEmpty()) { - computeLightClassesSources(); - } - - return getSourceKtFiles(file); - } - - @Nullable - public static String getInternalName(KtClassOrObject classOrObject) { - FqName fullFqName = classOrObject.getFqName(); - if (fullFqName == null) return null; - - KtClassOrObject topmostClassOrObject = PsiTreeUtil.getTopmostParentOfType(classOrObject, KtClassOrObject.class); - if (topmostClassOrObject == null) return makeInternalByToplevel(fullFqName); - - FqName topLevelFqName = topmostClassOrObject.getFqName(); - if (topLevelFqName == null) return null; - - String nestedPart = fullFqName.asString().substring(topLevelFqName.asString().length()).replaceAll("\\.", "\\$"); - - return makeInternalByToplevel(topLevelFqName) + nestedPart; - } - - private static String makeInternalByToplevel(FqName fqName) { - return fqName.asString().replaceAll("\\.", "/"); - } - - @NotNull - private List getSourceKtFiles(@NotNull File lightClass) { - Set sourceIOFiles = sourceFiles.get(lightClass); - if (sourceIOFiles != null) { - List jetSourceFiles = new ArrayList<>(); - for (IFile sourceFile : sourceIOFiles) { - KtFile jetFile = KotlinPsiManager.getKotlinParsedFile(sourceFile); - if (jetFile != null) { - jetSourceFiles.add(jetFile); - } - } - - return jetSourceFiles; - } - - return Collections.emptyList(); - } - - @NotNull - private List getLightClassesPaths(@NotNull IFile sourceFile) { - List lightClasses = new ArrayList(); - - KtFile ktFile = KotlinPsiManager.INSTANCE.getParsedFile(sourceFile); - for (KtClassOrObject classOrObject : findLightClasses(ktFile)) { - String internalName = getInternalName(classOrObject); - if (internalName != null) { - lightClasses.add(computePathByInternalName(internalName)); - } - } - - if (ktFile.hasTopLevelCallables()) { - String newFacadeInternalName = FileClasses.getFileClassInternalName( - NoResolveFileClassesProvider.INSTANCE, ktFile); - lightClasses.add(computePathByInternalName(newFacadeInternalName)); - } - - return lightClasses; - } - - private List findLightClasses(@NotNull KtFile ktFile) { - final ArrayList lightClasses = new ArrayList(); - ktFile.acceptChildren(new KtVisitorVoid() { - @Override - public void visitClassOrObject(@NotNull KtClassOrObject classOrObject) { - lightClasses.add(classOrObject); - super.visitClassOrObject(classOrObject); - } - - @Override - public void visitNamedFunction(@NotNull KtNamedFunction function) { - } - - @Override - public void visitSecondaryConstructor(@NotNull KtSecondaryConstructor constructor) { - } - - @Override - public void visitProperty(@NotNull KtProperty property) { - } - - @Override - public void visitElement(@Nullable PsiElement element) { - if (element != null) { - element.acceptChildren(this); - } - } - }); - return lightClasses; - } - - private IPath computePathByInternalName(String internalName) { - Path relativePath = new Path(internalName + ".class"); - return KotlinJavaManager.KOTLIN_BIN_FOLDER.append(relativePath); - } - - private void cleanOutdatedLightClasses(IProject project) { - ProjectUtils.cleanFolder(KotlinJavaManager.INSTANCE.getKotlinBinFolderFor(project), resource -> { - if (resource instanceof IFile) { - IFile eclipseFile = (IFile) resource; - LightClassFile lightClass = new LightClassFile(eclipseFile); - Set sources = sourceFiles.get(lightClass.asFile()); - - boolean dropLightClass = sources == null || sources.isEmpty(); - if (dropLightClass) { - removeLightClass(lightClass.asFile()); - } - - return dropLightClass; - } else if (resource instanceof IFolder) { - try { - return ((IFolder) resource).members().length == 0; - } catch (CoreException e) { - KotlinLogger.logAndThrow(e); - } - } - - return false; - }); - } - - private void createParentDirsFor(@NotNull LightClassFile lightClassFile) { - IFolder parent = (IFolder) lightClassFile.getResource().getParent(); - if (parent != null && !parent.exists()) { - createParentDirs(parent); - } - } - - private void createParentDirs(IFolder folder) { - IContainer parent = folder.getParent(); - if (!parent.exists()) { - createParentDirs((IFolder) parent); - } - - try { - folder.create(true, true, null); - } catch (CoreException e) { - KotlinLogger.logAndThrow(e); - } - } -} \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinLightClassManager.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinLightClassManager.kt new file mode 100644 index 000000000..7b8f1d56d --- /dev/null +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinLightClassManager.kt @@ -0,0 +1,261 @@ +package org.jetbrains.kotlin.core.filesystem + +import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil +import org.eclipse.core.internal.jobs.JobStatus +import org.eclipse.core.resources.* +import org.eclipse.core.runtime.* +import org.eclipse.jdt.core.JavaCore +import org.eclipse.jdt.internal.core.util.LRUCache +import org.jetbrains.kotlin.core.asJava.LightClassFile +import org.jetbrains.kotlin.core.builder.KotlinPsiManager.getFilesByProject +import org.jetbrains.kotlin.core.builder.KotlinPsiManager.getKotlinParsedFile +import org.jetbrains.kotlin.core.builder.KotlinPsiManager.getParsedFile +import org.jetbrains.kotlin.core.log.KotlinLogger.logAndThrow +import org.jetbrains.kotlin.core.model.KotlinEnvironment.Companion.getEnvironment +import org.jetbrains.kotlin.core.model.KotlinJavaManager +import org.jetbrains.kotlin.core.model.KotlinJavaManager.getKotlinBinFolderFor +import org.jetbrains.kotlin.core.utils.ProjectUtils.cleanFolder +import org.jetbrains.kotlin.core.utils.ProjectUtils.getAllOutputFolders +import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* +import java.io.File +import java.io.IOException +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentMap +import kotlin.text.Charsets.UTF_8 + +class KotlinLightClassManager(private val project: IProject) { + private val cachedLightClasses = LRUCache(LIGHT_CLASSES_CACHE_SIZE) + private val sourceFiles: ConcurrentMap> = ConcurrentHashMap() + + @Synchronized + fun getCachedLightClass(file: File): ByteArray? { + val lightClass: Any? = cachedLightClasses[file] + return if (lightClass != null) lightClass as ByteArray? else null + } + + @Synchronized + fun cacheLightClass(file: File, lightClass: ByteArray) { + cachedLightClasses.put(file, lightClass) + } + + @Synchronized + fun removeLightClass(file: File) { + cachedLightClasses.flush(file) + val tempFolders = getAllOutputFolders(JavaCore.create(project)) + val tempSegments = file.path.split("[/\\\\]".toRegex()).toTypedArray() + val tempRealPath = tempSegments.copyOfRange(3, tempSegments.size) + for (tempFolder in tempFolders) { + val tempRootFolder = tempFolder.location.toFile() + var tempCurrentFolder = tempRootFolder + for ((tempIndex, tempSegment) in tempRealPath.withIndex()) { + if (tempIndex == tempRealPath.lastIndex) { + val tempFile = File(tempCurrentFolder, tempSegment).takeIf { it.exists() } ?: break + val tempTouchedFilesFile = File(tempRootFolder, KOTLIN_TOUCHED_FILES_FILE_NAME) + try { + if (!tempTouchedFilesFile.exists()) tempTouchedFilesFile.createNewFile() + + val tempLines = tempTouchedFilesFile.readLines(UTF_8).toMutableSet() + tempLines.add(tempFile.absolutePath) + tempTouchedFilesFile.writeText(tempLines.joinToString("\n"), UTF_8) + } catch (e: IOException) { + e.printStackTrace() + } + } else { + tempCurrentFolder = File(tempCurrentFolder, tempSegment).takeIf { it.exists() } ?: break + } + } + } + } + + fun computeLightClassesSources() { + val newSourceFilesMap: MutableMap> = HashMap() + for (sourceFile in getFilesByProject(project)) { + val lightClassesPaths = getLightClassesPaths(sourceFile) + for (path in lightClassesPaths) { + val lightClassFile = LightClassFile(project.getFile(path)) + val newSourceFiles = newSourceFilesMap.computeIfAbsent(lightClassFile.asFile()) { HashSet() } + newSourceFiles.add(sourceFile) + } + } + sourceFiles.clear() + sourceFiles.putAll(newSourceFilesMap) + } + + fun updateLightClasses(affectedFiles: Set, resourceTreeBlocked: Boolean) { + val toCreate: MutableList = ArrayList() + val toRemove: MutableList = ArrayList() + for ((key, value) in sourceFiles) { + val lightClassIFile = ResourcesPlugin.getWorkspace().root.getFile(Path(key.path)) + ?: continue + val lightClassFile = LightClassFile(lightClassIFile) + if (!lightClassFile.exists()) { + toCreate.add(lightClassFile) + } + for (sourceFile in value) { + if (affectedFiles.contains(sourceFile)) { + toRemove.add(lightClassFile) + break + } + } + } + if (resourceTreeBlocked) { + if (toCreate.isNotEmpty() || toRemove.isNotEmpty()) { + val job: WorkspaceJob = object : WorkspaceJob(WORKSPACE_JOB_ID) { + override fun runInWorkspace(monitor: IProgressMonitor): IStatus { + monitor.beginTask("Light class generation started", 0) + updateLightClasses(toCreate, toRemove) + monitor.done() + return JobStatus(0, this, "Light classes generation finished") + } + } + job.rule = ResourcesPlugin.getWorkspace().ruleFactory.createRule( + project.getFolder(KotlinJavaManager.KOTLIN_BIN_FOLDER)) + job.schedule() + } + } else { + updateLightClasses(toCreate, toRemove) + } + } + + private fun updateLightClasses(toCreate: List, toRemove: List) { + for (lightClassFile in toCreate) { + createParentDirsFor(lightClassFile) + lightClassFile.createIfNotExists() + } + for (lightClassFile in toRemove) { + removeLightClass(lightClassFile.asFile()) + lightClassFile.touchFile() + } + cleanOutdatedLightClasses(project) + } + + fun getSourceFiles(file: File): List { + if (sourceFiles.isEmpty()) { + computeLightClassesSources() + } + return getSourceKtFiles(file) + } + + private fun getSourceKtFiles(lightClass: File): List { + val sourceIOFiles: Set? = sourceFiles[lightClass] + if (sourceIOFiles != null) { + val jetSourceFiles: MutableList = ArrayList() + for (sourceFile in sourceIOFiles) { + val jetFile = getKotlinParsedFile(sourceFile) + if (jetFile != null) { + jetSourceFiles.add(jetFile) + } + } + return jetSourceFiles + } + return emptyList() + } + + private fun getLightClassesPaths(sourceFile: IFile): List { + val lightClasses: MutableList = ArrayList() + val ktFile = getParsedFile(sourceFile) + for (classOrObject in findLightClasses(ktFile)) { + val internalName = getInternalName(classOrObject) + if (internalName != null) { + lightClasses.add(computePathByInternalName(internalName)) + } + } + if (ktFile.hasTopLevelCallables()) { + val newFacadeInternalName = JvmFileClassUtil.getFileClassInternalName(ktFile) + lightClasses.add(computePathByInternalName(newFacadeInternalName)) + } + return lightClasses + } + + private fun findLightClasses(ktFile: KtFile): List { + val lightClasses = ArrayList() + ktFile.acceptChildren(object : KtVisitorVoid() { + override fun visitClassOrObject(classOrObject: KtClassOrObject) { + lightClasses.add(classOrObject) + super.visitClassOrObject(classOrObject) + } + + override fun visitNamedFunction(function: KtNamedFunction) {} + override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor) {} + override fun visitProperty(property: KtProperty) {} + override fun visitElement(element: PsiElement) { + element.acceptChildren(this) + } + }) + return lightClasses + } + + private fun computePathByInternalName(internalName: String): IPath { + val relativePath = Path("$internalName.class") + return KotlinJavaManager.KOTLIN_BIN_FOLDER.append(relativePath) + } + + private fun cleanOutdatedLightClasses(project: IProject) { + cleanFolder(getKotlinBinFolderFor(project)) { resource: IResource? -> + if (resource is IFile) { + val lightClass = LightClassFile(resource) + val sources: Set? = sourceFiles[lightClass.asFile()] + val dropLightClass = sources == null || sources.isEmpty() + if (dropLightClass) { + removeLightClass(lightClass.asFile()) + } + return@cleanFolder dropLightClass + } else if (resource is IFolder) { + try { + return@cleanFolder resource.members().isEmpty() + } catch (e: CoreException) { + logAndThrow(e) + } + } + false + } + } + + private fun createParentDirsFor(lightClassFile: LightClassFile) { + val parent = lightClassFile.resource.parent as? IFolder + if (parent != null && !parent.exists()) { + createParentDirs(parent) + } + } + + private fun createParentDirs(folder: IFolder) { + val parent = folder.parent + if (!parent.exists()) { + createParentDirs(parent as IFolder) + } + try { + folder.create(true, true, null) + } catch (e: CoreException) { + logAndThrow(e) + } + } + + companion object { + const val KOTLIN_TOUCHED_FILES_FILE_NAME = "META-INF/kotlinTouchedFiles" + + private const val LIGHT_CLASSES_CACHE_SIZE = 300 + private const val WORKSPACE_JOB_ID = "updateLightClassesJob" + fun getInstance(project: IProject): KotlinLightClassManager { + val ideaProject: Project = getEnvironment(project).project + return ServiceManager.getService(ideaProject, KotlinLightClassManager::class.java) + } + + fun getInternalName(classOrObject: KtClassOrObject): String? { + val fullFqName = classOrObject.fqName ?: return null + val topmostClassOrObject = PsiTreeUtil.getTopmostParentOfType(classOrObject, KtClassOrObject::class.java) + ?: return makeInternalByToplevel(fullFqName) + val topLevelFqName = topmostClassOrObject.fqName ?: return null + val nestedPart = fullFqName.asString().substring(topLevelFqName.asString().length).replace("\\.".toRegex(), "\\$") + return makeInternalByToplevel(topLevelFqName) + nestedPart + } + + private fun makeInternalByToplevel(fqName: FqName): String { + return fqName.asString().replace("\\.".toRegex(), "/") + } + } +} \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/formatting/KotlinCodeStyleManager.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/formatting/KotlinCodeStyleManager.kt index 13ff68cc7..ce4a1e1fe 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/formatting/KotlinCodeStyleManager.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/formatting/KotlinCodeStyleManager.kt @@ -40,7 +40,7 @@ object KotlinCodeStyleManager { stylesCache.getOrPut(id) { CodeStyleSettings().also { it.settingsApplier() } } fun get(id: String): CodeStyleSettings? = stylesCache[id] ?: createStyleFromPredef(id) - + // Uses the same logic as ConcurrentHashMap.getOrPut() but due to possible nullability cannot be expressed by that method. private fun createStyleFromPredef(id: String): CodeStyleSettings? = predefinedStyles[id] ?.let { CodeStyleSettings().also(it::apply) } @@ -60,9 +60,9 @@ private val IProject.codeStyleSettings ?: KotlinCodeStyleProperties.workspaceInstance val IProject.codeStyle: CodeStyleSettings - get() = codeStyleSettings - .codeStyleId - ?.let { KotlinCodeStyleManager.get(it) } - ?: CodeStyleSettings() + get() { + val tempId = codeStyleSettings.codeStyleId ?: "KOTLIN_OFFICIAL" + return KotlinCodeStyleManager.get(tempId) ?: CodeStyleSettings() + } private val ExecutableExtensionPointDescriptor.nameInBuildsystem: String? by EPAttribute \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/CachedEnvironment.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/CachedEnvironment.kt index ab9d8d9a7..c81699e06 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/CachedEnvironment.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/CachedEnvironment.kt @@ -21,7 +21,7 @@ import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.impl.ZipHandler import java.util.concurrent.ConcurrentHashMap -class CachedEnvironment { +class CachedEnvironment { private val environmentLock = Any() private val environmentCache = ConcurrentHashMap() @@ -39,8 +39,15 @@ class CachedEnvironment { } fun removeEnvironment(resource: T) = synchronized(environmentLock) { - removeEnvironmentInternal(resource) - } + removeEnvironmentInternal(resource) + } + + + fun removeEnvironmentIf(check: (KotlinCommonEnvironment) -> Boolean): List { + val tempToRemove = environmentCache.filter { check(it.value) }.map { it.key } + tempToRemove.forEach(::removeEnvironmentInternal) + return tempToRemove + } fun removeAllEnvironments() = synchronized(environmentLock) { environmentCache.keys.toList().forEach { @@ -52,7 +59,7 @@ class CachedEnvironment { environmentCache.remove(resource)?.also { ideaProjectToEclipseResource.remove(it.project) - Disposer.dispose(it.kotlinCoreApplicationEnvironment.parentDisposable) + Disposer.dispose(it.projectEnvironment.parentDisposable) ZipHandler.clearFileAccessorCache() } } diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/DummyCodeStyleManager.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/DummyCodeStyleManager.kt index 3e0790d73..816d2d635 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/DummyCodeStyleManager.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/DummyCodeStyleManager.kt @@ -1,19 +1,20 @@ package org.jetbrains.kotlin.core.model -import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.lang.ASTNode -import com.intellij.openapi.project.Project -import com.intellij.psi.codeStyle.Indent -import com.intellij.openapi.fileTypes.FileType -import com.intellij.psi.PsiFile import com.intellij.openapi.editor.Document -import com.intellij.psi.PsiElement -import com.intellij.openapi.util.TextRange -import com.intellij.util.ThrowableRunnable +import com.intellij.openapi.fileTypes.FileType +import com.intellij.openapi.project.Project import com.intellij.openapi.util.Computable +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile import com.intellij.psi.codeStyle.ChangedRangesInfo +import com.intellij.psi.codeStyle.CodeStyleManager +import com.intellij.psi.codeStyle.Indent +import com.intellij.util.ThrowableRunnable -public class DummyCodeStyleManager : CodeStyleManager() { +@Suppress("DEPRECATION") +class DummyCodeStyleManager : CodeStyleManager() { override fun reformatTextWithContext(arg0: PsiFile, arg1: ChangedRangesInfo) { throw UnsupportedOperationException() } @@ -53,8 +54,8 @@ public class DummyCodeStyleManager : CodeStyleManager() { override fun reformat(element: PsiElement, canChangeWhiteSpacesOnly: Boolean): PsiElement { throw UnsupportedOperationException() } - - override fun reformatTextWithContext(arg0: PsiFile, arg1: MutableCollection) { + + override fun reformatTextWithContext(file: PsiFile, ranges: MutableCollection) { throw UnsupportedOperationException() } @@ -77,8 +78,8 @@ public class DummyCodeStyleManager : CodeStyleManager() { override fun isSequentialProcessingAllowed(): Boolean { throw UnsupportedOperationException() } - - override fun reformatText(file: PsiFile, ranges: MutableCollection) { + + override fun reformatText(p0: PsiFile, p1: MutableCollection) { throw UnsupportedOperationException() } @@ -86,9 +87,9 @@ public class DummyCodeStyleManager : CodeStyleManager() { throw UnsupportedOperationException() } - override fun reformatRange(element: PsiElement, startOffset: Int, endOffset: Int): PsiElement? = element + override fun reformatRange(element: PsiElement, startOffset: Int, endOffset: Int): PsiElement = element - override fun reformatRange(element: PsiElement, startOffset: Int, endOffset: Int, canChangeWhiteSpacesOnly: Boolean): PsiElement? = element + override fun reformatRange(element: PsiElement, startOffset: Int, endOffset: Int, canChangeWhiteSpacesOnly: Boolean): PsiElement = element override fun performActionWithFormatterDisabled(r: Runnable?) { throw UnsupportedOperationException() diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/EclipseKotlinModuleResolver.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/EclipseKotlinModuleResolver.kt index 11749ee6e..41d0f61d1 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/EclipseKotlinModuleResolver.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/EclipseKotlinModuleResolver.kt @@ -1,12 +1,10 @@ package org.jetbrains.kotlin.core.model import com.intellij.openapi.vfs.VirtualFile -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleFinder -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule -import com.intellij.psi.PsiJavaModule -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver +import org.jetbrains.kotlin.load.java.structure.JavaAnnotation +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver class EclipseKotlinJavaModuleResolver : JavaModuleResolver { override fun checkAccessibility( @@ -14,4 +12,6 @@ class EclipseKotlinJavaModuleResolver : JavaModuleResolver { referencedFile: VirtualFile, referencedPackage: FqName? ): JavaModuleResolver.AccessError? = null + + override fun getAnnotationsForModuleOwnerOfClass(classId: ClassId): List? = null } \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/EclipseScriptDefinitionProvider.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/EclipseScriptDefinitionProvider.kt index ce2f60c2c..c8cd81510 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/EclipseScriptDefinitionProvider.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/EclipseScriptDefinitionProvider.kt @@ -1,6 +1,5 @@ package org.jetbrains.kotlin.core.model -import org.eclipse.core.resources.IFile import org.eclipse.osgi.internal.loader.EquinoxClassLoader import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.script.ScriptTemplateContribution @@ -12,7 +11,10 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource import java.io.File +import java.net.URLClassLoader import kotlin.reflect.KClass +import kotlin.reflect.full.hasAnnotation +import kotlin.script.experimental.annotations.KotlinScript import kotlin.script.experimental.api.KotlinType import kotlin.script.experimental.api.SourceCode import kotlin.script.experimental.host.ScriptingHostConfiguration @@ -25,67 +27,94 @@ private const val EXTENSION_POINT_ID = "org.jetbrains.kotlin.core.scriptTemplate class EclipseScriptDefinitionProvider : ScriptDefinitionProvider { override fun getDefaultDefinition() = - scriptDefinitions.first { it.baseClassType == KotlinType(ProjectScriptTemplate::class) } + scriptDefinitions.first { it.baseClassType == KotlinType(ProjectScriptTemplate::class) } override fun findDefinition(script: SourceCode): ScriptDefinition? = - scriptDefinitions.first { it.isScript(script) } + scriptDefinitions.first { it.isScript(script) } override fun findScriptDefinition(fileName: String): KotlinScriptDefinition? = - scriptDefinitions.map { it.legacyDefinition }.first { it.isScript(fileName) } + scriptDefinitions.map { it.legacyDefinition }.first { it.isScript(fileName) } override fun getDefaultScriptDefinition() = - getDefaultDefinition().legacyDefinition + getDefaultDefinition().legacyDefinition override fun getKnownFilenameExtensions(): Sequence = - scriptDefinitions.map { it.fileExtension } + scriptDefinitions.map { it.fileExtension } - override fun isScript(script: SourceCode) = - scriptDefinitions.any { it.isScript(script) } + override fun isScript(script: SourceCode) = Companion.isScript(script) companion object { private val contributions: List by lazy { loadExecutableEP(EXTENSION_POINT_ID) - .mapNotNull { it.createProvider() } - .sortedByDescending { it.priority } - .map(::WrappedContribution) + .mapNotNull { it.createProvider() } + .sortedByDescending { it.priority } + .map(::WrappedContribution) } private val scriptDefinitions: Sequence - get() = contributions.asSequence().map { it.definition } + get() = contributions.asSequence().mapNotNull { it.definition } + + fun getContribution(script: SourceCode): ScriptTemplateContribution? = contributions.find { it.definition?.isScript(script) == true }?.contribution + + fun isScript(script: SourceCode) = scriptDefinitions.any { it.isScript(script) } fun getEnvironment(scriptFile: File) = - scriptFile.asResource - ?.let { KotlinPsiManager.getKotlinParsedFile(it) } - ?.let { KtFileScriptSource(it) } - ?.let { source -> - contributions.find { it.definition.isScript(source) } - ?.contribution?.scriptEnvironment(scriptFile) - ?: emptyMap() - } + scriptFile.asResource + ?.let { KotlinPsiManager.getKotlinParsedFile(it) } + ?.let { KtFileScriptSource(it) } + ?.let { source -> + contributions.find { it.definition?.isScript(source) == true } + ?.contribution?.scriptEnvironment(scriptFile) + ?: emptyMap() + } } } private class WrappedContribution(val contribution: ScriptTemplateContribution) { - val definition by lazy { - ScriptDefinition.FromLegacyTemplate( - hostConfiguration = ScriptingHostConfiguration { - getScriptingClass(JvmGetScriptingClass()) - configurationDependencies(JvmDependency(extractClasspath(contribution.template) + scriptingDependencies)) - }, - template = contribution.template - ) - } + + private var _definition: ScriptDefinition? = null + + val definition: ScriptDefinition? + get() { + return _definition ?: run { + try { + if (contribution.template.hasAnnotation()) { + ScriptDefinition.FromTemplate( + baseHostConfiguration = ScriptingHostConfiguration { + getScriptingClass(JvmGetScriptingClass()) + configurationDependencies(JvmDependency(extractClasspath(contribution.template) + scriptingDependencies)) + }, + template = contribution.template, + contextClass = contribution.template + ) + } else { + ScriptDefinition.FromLegacyTemplate( + hostConfiguration = ScriptingHostConfiguration { + getScriptingClass(JvmGetScriptingClass()) + configurationDependencies(JvmDependency(extractClasspath(contribution.template) + scriptingDependencies)) + }, + template = contribution.template + ) + } + } catch (e: Exception) { + null + } + }?.also { _definition = it } + } } // TODO: hack for now, will definitely need rethinking -private fun extractClasspath(kClass: KClass<*>): List = - (kClass.java.classLoader as? EquinoxClassLoader) - ?.classpathManager - ?.hostClasspathEntries - ?.map { entry -> entry.bundleFile.baseFile.resolve("bin") } - .orEmpty() +private fun extractClasspath(kClass: KClass<*>): List { + return when (val tempLoader = kClass.java.classLoader) { + is EquinoxClassLoader -> tempLoader.classpathManager + .hostClasspathEntries + .map { entry -> entry.bundleFile.baseFile.resolve("bin") } + is URLClassLoader -> tempLoader.urLs.mapNotNull { File(it.file).takeIf { it.exists() } } + else -> null + } ?: emptyList() +} private val scriptingDependencies: List by lazy { listOf("kotlin-scripting-jvm") - .map { File(ProjectUtils.buildLibPath(it)) } + .map { File(ProjectUtils.buildLibPath(it)) } } \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinCommonEnvironment.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinCommonEnvironment.kt index c17b6e063..2a5f2da73 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinCommonEnvironment.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinCommonEnvironment.kt @@ -14,12 +14,11 @@ * limitations under the License. * *******************************************************************************/ +@file:Suppress("DEPRECATION") + package org.jetbrains.kotlin.core.model -import com.intellij.codeInsight.ContainerProvider -import com.intellij.codeInsight.ExternalAnnotationsManager -import com.intellij.codeInsight.InferredAnnotationsManager -import com.intellij.codeInsight.NullableNotNullManager +import com.intellij.codeInsight.* import com.intellij.codeInsight.runner.JavaMainMethodProvider import com.intellij.core.CoreApplicationEnvironment import com.intellij.core.CoreJavaFileManager @@ -37,21 +36,20 @@ import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.extensions.ExtensionsArea import com.intellij.openapi.fileTypes.PlainTextFileType +import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.JavaModuleSystem import com.intellij.psi.PsiElementFinder import com.intellij.psi.PsiManager import com.intellij.psi.augment.PsiAugmentProvider -import com.intellij.psi.codeStyle.CodeStyleManager -import com.intellij.psi.codeStyle.CodeStyleSettingsProvider -import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider -import com.intellij.psi.compiled.ClassFileDecompilers +import com.intellij.psi.codeStyle.* import com.intellij.psi.impl.PsiElementFinderImpl import com.intellij.psi.impl.PsiTreeChangePreprocessor import com.intellij.psi.impl.compiled.ClsCustomNavigationPolicy import com.intellij.psi.impl.file.impl.JavaFileManager import org.eclipse.core.runtime.IPath +import org.eclipse.jdt.core.IJavaProject import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.finder.JavaElementFinder @@ -74,6 +72,9 @@ import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor import org.jetbrains.kotlin.idea.KotlinFileType +import org.jetbrains.kotlin.idea.j2k.J2KPostProcessingRegistrar +import org.jetbrains.kotlin.idea.j2k.J2KPostProcessingRegistrarImpl +import org.jetbrains.kotlin.idea.j2k.J2kPostProcessing import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager @@ -88,7 +89,6 @@ import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider import org.jetbrains.kotlin.scripting.extensions.ScriptingResolveExtension import java.io.File -import java.util.* import kotlin.reflect.KClass private fun setIdeaIoUseFallback() { @@ -97,31 +97,32 @@ private fun setIdeaIoUseFallback() { properties.setProperty("idea.io.use.nio2", java.lang.Boolean.TRUE.toString()) - if (!(SystemInfo.isJavaVersionAtLeast(1, 7, 0) && !"1.7.0-ea".equals(SystemInfo.JAVA_VERSION))) { + if (!(SystemInfo.isJavaVersionAtLeast(1, 7, 0) && "1.7.0-ea" != SystemInfo.JAVA_VERSION)) { properties.setProperty("idea.io.use.fallback", java.lang.Boolean.TRUE.toString()) } } } abstract class KotlinCommonEnvironment(disposable: Disposable) { - val kotlinCoreApplicationEnvironment: KotlinCoreApplicationEnvironment val project: MockProject - protected val projectEnvironment: JavaCoreProjectEnvironment + var hasError = false + + val projectEnvironment: JavaCoreProjectEnvironment private val roots = LinkedHashSet() val configuration = CompilerConfiguration() + abstract val javaProject: IJavaProject + init { setIdeaIoUseFallback() - kotlinCoreApplicationEnvironment = createKotlinCoreApplicationEnvironment(disposable) - projectEnvironment = object : JavaCoreProjectEnvironment(disposable, kotlinCoreApplicationEnvironment) { override fun preregisterServices() { - registerProjectExtensionPoints(Extensions.getArea(project)) + registerProjectExtensionPoints(project.extensionArea) CoreApplicationEnvironment.registerExtensionPoint( - Extensions.getArea(project), + project.extensionArea, JvmElementProvider.EP_NAME, JvmElementProvider::class.java ) @@ -161,14 +162,14 @@ abstract class KotlinCommonEnvironment(disposable: Disposable) { registerService(CodeAnalyzerInitializer::class.java, it) } - CliLightClassGenerationSupport(traceHolder).also { + CliLightClassGenerationSupport(traceHolder, project).also { registerService(LightClassGenerationSupport::class.java, it) registerService(CliLightClassGenerationSupport::class.java, it) } registerService(JavaModuleResolver::class.java, EclipseKotlinJavaModuleResolver()) - val area = Extensions.getArea(this) + val area = extensionArea val javaFileManager = ServiceManager.getService(this, JavaFileManager::class.java) (javaFileManager as KotlinCliJavaFileManagerImpl) .initialize( @@ -182,7 +183,7 @@ abstract class KotlinCommonEnvironment(disposable: Disposable) { val kotlinAsJavaSupport = CliKotlinAsJavaSupport(this, traceHolder) registerService(KotlinAsJavaSupport::class.java, kotlinAsJavaSupport) area.getExtensionPoint(PsiElementFinder.EP_NAME) - .registerExtension(JavaElementFinder(this, kotlinAsJavaSupport)) + .registerExtension(JavaElementFinder(this)) area.getExtensionPoint(SyntheticResolveExtension.extensionPointName) .registerExtension(ScriptingResolveExtension()) registerService(KotlinJavaPsiFacade::class.java, KotlinJavaPsiFacade(this)) @@ -236,6 +237,12 @@ abstract class KotlinCommonEnvironment(disposable: Disposable) { roots.add(JavaRoot(root, type)) } } + + companion object { + val kotlinCoreApplicationEnvironment: KotlinCoreApplicationEnvironment by lazy { + createKotlinCoreApplicationEnvironment(Disposer.newDisposable("Root Disposable")) + } + } } private fun createKotlinCoreApplicationEnvironment(disposable: Disposable): KotlinCoreApplicationEnvironment = @@ -250,6 +257,13 @@ private fun createKotlinCoreApplicationEnvironment(disposable: Disposable): Kotl application.registerService(Formatter::class.java, FormatterImpl()) application.registerService(KotlinBinaryClassCache::class.java, KotlinBinaryClassCache()) application.registerService(ScriptDefinitionProvider::class.java, EclipseScriptDefinitionProvider()) + application.registerService(J2KPostProcessingRegistrar::class.java, object : J2KPostProcessingRegistrar { + override val processings: Collection + get() = emptyList() + + override fun priority(processing: J2kPostProcessing): Int = 0 + }) + application.registerService(CodeStyleSettingsService::class.java, CodeStyleSettingsServiceImpl()) } private fun registerProjectExtensionPoints(area: ExtensionsArea) { @@ -258,6 +272,7 @@ private fun registerProjectExtensionPoints(area: ExtensionsArea) { registerExtensionPoint(area, SyntheticResolveExtension.extensionPointName, SyntheticResolveExtension::class) } +@Suppress("LocalVariableName") private fun registerApplicationExtensionPointsAndExtensionsFrom() { val EP_ERROR_MSGS = ExtensionPointName.create("org.jetbrains.defaultErrorMessages.extension") @@ -283,7 +298,8 @@ private fun registerApplicationExtensionPointsAndExtensionsFrom() { private fun registerAppExtensionPoints() { registerExtensionPointInRoot(ContainerProvider.EP_NAME, ContainerProvider::class) registerExtensionPointInRoot(ClsCustomNavigationPolicy.EP_NAME, ClsCustomNavigationPolicy::class) - registerExtensionPointInRoot(ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler::class) + //TODO + //registerExtensionPointInRoot(ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler::class) // For j2k converter registerExtensionPointInRoot(PsiAugmentProvider.EP_NAME, PsiAugmentProvider::class) diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt index 318947113..04d85ce01 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt @@ -18,8 +18,8 @@ package org.jetbrains.kotlin.core.model import com.intellij.core.CoreJavaFileManager import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.ServiceManager -import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.psi.PsiElementFinder @@ -57,6 +57,7 @@ import org.jetbrains.kotlin.core.preferences.CompilerPlugin import org.jetbrains.kotlin.core.preferences.KotlinBuildingProperties import org.jetbrains.kotlin.core.preferences.KotlinProperties import org.jetbrains.kotlin.core.resolve.lang.kotlin.EclipseVirtualFileFinderFactory +import org.jetbrains.kotlin.core.utils.DependencyResolverException import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.core.utils.asFile import org.jetbrains.kotlin.core.utils.buildLibPath @@ -65,23 +66,23 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.extensions.AnnotationBasedExtension import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor -import org.jetbrains.kotlin.resolve.sam.SamWithReceiverResolver import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.jvm.JvmPlatform import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.resolve.sam.SamWithReceiverResolver import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider import org.jetbrains.kotlin.scripting.definitions.annotationsForSamWithReceivers -import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource import java.io.File import java.net.URL import java.net.URLClassLoader import java.util.* import kotlin.script.experimental.api.ScriptCompilationConfiguration import kotlin.script.experimental.dependencies.ScriptDependencies +import kotlin.script.experimental.host.FileScriptSource val KOTLIN_COMPILER_PATH = ProjectUtils.buildLibPath("kotlin-compiler") @@ -118,10 +119,12 @@ class KotlinScriptEnvironment private constructor( ) : KotlinCommonEnvironment(disposable) { val definition: ScriptDefinition? = ScriptDefinitionProvider.getInstance(project) - ?.findDefinition(KtFileScriptSource(KotlinPsiManager.getParsedFile(eclipseFile))) + ?.findDefinition(FileScriptSource(eclipseFile.asFile)) val definitionClasspath: Collection = definition?.contextClassLoader?.let(::classpathFromClassloader).orEmpty() + override val javaProject: IJavaProject = JavaCore.create(eclipseFile.project) + init { configureClasspath() @@ -134,7 +137,7 @@ class KotlinScriptEnvironment private constructor( val index = JvmDependenciesIndexImpl(getRoots().toList()) - val area = Extensions.getArea(project) + val area = project.extensionArea with(area.getExtensionPoint(PsiElementFinder.EP_NAME)) { registerExtension(PsiElementFinderImpl(project, ServiceManager.getService(project, JavaFileManager::class.java))) } @@ -157,6 +160,9 @@ class KotlinScriptEnvironment private constructor( project.registerService(MetadataFinderFactory::class.java, finderFactory) project.registerService(VirtualFileFinderFactory::class.java, finderFactory) + project.registerService(FacadeCache::class.java, FacadeCache(project)) + project.registerService(KotlinLightClassManager::class.java, KotlinLightClassManager(javaProject.project)) + // definition?.dependencyResolver?.also { project.registerService(DependenciesResolver::class.java, it) } } @@ -171,7 +177,7 @@ class KotlinScriptEnvironment private constructor( checkIsScript(file) return cachedEnvironment.getOrCreateEnvironment(file) { - KotlinScriptEnvironment(it, null, Disposer.newDisposable()) + KotlinScriptEnvironment(it, null, Disposer.newDisposable("Scripting Env ${file.asFile.absolutePath}")) } } @@ -181,10 +187,19 @@ class KotlinScriptEnvironment private constructor( cachedEnvironment.removeEnvironment(file) } + fun removeAllEnvironments() { + cachedEnvironment.removeAllEnvironments() + } + + fun removeEnvironmentIf(check: (KotlinCommonEnvironment) -> Boolean) { + cachedEnvironment.removeEnvironmentIf(check) + } + @JvmStatic fun getEclipseFile(project: Project): IFile? = cachedEnvironment.getEclipseResource(project) - fun isScript(file: IFile): Boolean = file.fileExtension == "kts" + fun isScript(file: IFile): Boolean = + EclipseScriptDefinitionProvider.isScript(FileScriptSource(file.asFile)) private fun checkIsScript(file: IFile) { if (!isScript(file)) { @@ -194,8 +209,8 @@ class KotlinScriptEnvironment private constructor( fun updateDependencies(file: IFile, newDependencies: ScriptDependencies?) { cachedEnvironment.replaceEnvironment(file) { - KotlinScriptEnvironment(file, newDependencies, Disposer.newDisposable()) - .apply { addDependenciesToClasspath(newDependencies) } + KotlinScriptEnvironment(file, newDependencies, Disposer.newDisposable("Scripting Env ${file.asFile.absolutePath}")) + .apply { addDependenciesToClasspath(newDependencies) } } KotlinPsiManager.removeFile(file) } @@ -204,9 +219,17 @@ class KotlinScriptEnvironment private constructor( private fun configureClasspath() { addToClasspath(KOTLIN_RUNTIME_PATH.toFile()) addToClasspath(KOTLIN_SCRIPT_RUNTIME_PATH.toFile()) - addJREToClasspath() - definitionClasspath.forEach { addToClasspath(it) } + + if (!javaProject.exists()) return + + val tempFiles = try { + ProjectUtils.collectClasspathWithDependenciesForBuild(javaProject) + } catch (e: DependencyResolverException) { + hasError = true + e.resolvedFiles + } + tempFiles.forEach(::addToClasspath) } private fun addDependenciesToClasspath(dependencies: ScriptDependencies?) { @@ -254,7 +277,11 @@ private fun classpathFromClassloader(classLoader: ClassLoader): List { } is EquinoxClassLoader -> { classLoader.classpathManager.hostClasspathEntries.map { entry -> - entry.bundleFile.baseFile.resolve("bin") + if(entry.bundleFile.baseFile.isFile) { + entry.bundleFile.baseFile + } else { + entry.bundleFile.baseFile.resolve("bin") + } } } else -> { @@ -298,7 +325,7 @@ class SamWithReceiverResolverExtension( class KotlinEnvironment private constructor(val eclipseProject: IProject, disposable: Disposable) : KotlinCommonEnvironment(disposable) { - val javaProject = JavaCore.create(eclipseProject) + override val javaProject = JavaCore.create(eclipseProject) val projectCompilerProperties: KotlinProperties = KotlinProperties(ProjectScope(eclipseProject)) @@ -368,15 +395,20 @@ class KotlinEnvironment private constructor(val eclipseProject: IProject, dispos private fun configureClasspath(javaProject: IJavaProject) { if (!javaProject.exists()) return - for (file in ProjectUtils.collectClasspathWithDependenciesForBuild(javaProject)) { - addToClasspath(file) + val tempFiles = try { + ProjectUtils.collectClasspathWithDependenciesForBuild(javaProject) + } catch (e: DependencyResolverException) { + hasError = true + e.resolvedFiles + e.resolvedFiles } + tempFiles.forEach(::addToClasspath) } companion object { private val cachedEnvironment = CachedEnvironment() private val environmentCreation = { eclipseProject: IProject -> - KotlinEnvironment(eclipseProject, Disposer.newDisposable()) + KotlinEnvironment(eclipseProject, Disposer.newDisposable("Project Env ${eclipseProject.name}")) } @JvmStatic @@ -391,6 +423,17 @@ class KotlinEnvironment private constructor(val eclipseProject: IProject, dispos KotlinAnalysisProjectCache.resetCache(eclipseProject) } + fun removeEnvironmentIf(check: (KotlinCommonEnvironment) -> Boolean) { + val tempRemoved = cachedEnvironment.removeEnvironmentIf(check) + if(tempRemoved.isNotEmpty()) { + KotlinPsiManager.invalidateCachedProjectSourceFiles() + KotlinAnalysisFileCache.resetCache() + for (removedPrj in tempRemoved) { + KotlinAnalysisProjectCache.resetCache(removedPrj) + } + } + } + @JvmStatic fun removeAllEnvironments() { cachedEnvironment.removeAllEnvironments() diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinJavaManager.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinJavaManager.kt index af23d90b9..46688601b 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinJavaManager.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinJavaManager.kt @@ -16,77 +16,58 @@ *******************************************************************************/ package org.jetbrains.kotlin.core.model +import com.intellij.psi.util.PsiTreeUtil import org.eclipse.core.resources.IFolder import org.eclipse.core.resources.IProject import org.eclipse.core.runtime.Path -import org.eclipse.jdt.core.IJavaProject -import org.eclipse.jdt.core.IType -import org.eclipse.jdt.core.JavaModelException -import org.jetbrains.kotlin.core.filesystem.KotlinFileSystem -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.source.KotlinSourceElement -import org.jetbrains.kotlin.core.resolve.lang.java.resolver.EclipseJavaSourceElement -import org.eclipse.jdt.core.IJavaElement -import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.psi.KtDeclaration -import com.intellij.psi.PsiElement -import org.eclipse.jdt.core.IMethod -import org.jetbrains.kotlin.core.asJava.equalsJvmSignature -import org.jetbrains.kotlin.core.asJava.getTypeFqName +import org.eclipse.jdt.core.* import org.eclipse.jdt.core.dom.IBinding import org.eclipse.jdt.core.dom.IMethodBinding -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtSecondaryConstructor -import org.jetbrains.kotlin.psi.KtFunction -import org.jetbrains.kotlin.psi.KtPropertyAccessor -import org.eclipse.jdt.core.IMember -import org.jetbrains.kotlin.psi.KtProperty -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.psi.KtObjectDeclaration -import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.core.asJava.equalsJvmSignature +import org.jetbrains.kotlin.core.asJava.getTypeFqName import org.jetbrains.kotlin.core.builder.KotlinPsiManager -import org.jetbrains.kotlin.psi.KtPrimaryConstructor +import org.jetbrains.kotlin.core.filesystem.KotlinFileSystem import org.jetbrains.kotlin.core.log.KotlinLogger +import org.jetbrains.kotlin.core.resolve.lang.java.resolver.EclipseJavaSourceElement +import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.source.KotlinSourceElement -public object KotlinJavaManager { +object KotlinJavaManager { @JvmField - public val KOTLIN_BIN_FOLDER: Path = Path("kotlin_bin") + val KOTLIN_BIN_FOLDER: Path = Path("kotlin_bin") - public fun getKotlinBinFolderFor(project: IProject): IFolder = project.getFolder(KOTLIN_BIN_FOLDER) + fun getKotlinBinFolderFor(project: IProject): IFolder = project.getFolder(KOTLIN_BIN_FOLDER) - public fun findEclipseType(jetClass: KtClassOrObject, javaProject: IJavaProject): IType? { - return jetClass.getFqName().let { + fun findEclipseType(jetClass: KtClassOrObject, javaProject: IJavaProject): IType? { + return jetClass.fqName.let { if (it != null) javaProject.findType(it.asString()) else null } } - public fun findEclipseMembers(declaration: KtDeclaration, javaProject: IJavaProject, + fun findEclipseMembers(declaration: KtDeclaration, javaProject: IJavaProject, klass: Class): List { val containingElement = PsiTreeUtil.getParentOfType(declaration, KtClassOrObject::class.java, KtFile::class.java) val seekInParent: Boolean = containingElement is KtObjectDeclaration && containingElement.isCompanion() if (containingElement == null) return emptyList() - val declaringTypeFqName = getTypeFqName(containingElement) - if (declaringTypeFqName == null) return emptyList() - - val eclipseType = javaProject.findType(declaringTypeFqName.asString()) - if (eclipseType == null) return emptyList() - + val declaringTypeFqName = getTypeFqName(containingElement) ?: return emptyList() + + val eclipseType = javaProject.findType(declaringTypeFqName.asString()) ?: return emptyList() + val typeMembers = findMembersIn(eclipseType, declaration, klass) return if (seekInParent) { - val parentMembers = findMembersIn(eclipseType.getDeclaringType(), declaration, klass) + val parentMembers = findMembersIn(eclipseType.declaringType, declaration, klass) typeMembers + parentMembers } else { typeMembers } } - public fun hasLinkedKotlinBinFolder(project: IProject): Boolean { - val folder = project.getFolder(KotlinJavaManager.KOTLIN_BIN_FOLDER) - return folder.isLinked() && KotlinFileSystem.SCHEME == folder.getLocationURI().getScheme() + fun hasLinkedKotlinBinFolder(project: IProject): Boolean { + val folder = project.getFolder(KOTLIN_BIN_FOLDER) + return folder.isLinked && KotlinFileSystem.SCHEME == folder.locationURI.scheme } private fun findMembersIn(eclipseType: IType, declaration: KtDeclaration, klass: Class): List { @@ -95,14 +76,14 @@ public object KotlinJavaManager { return klass.isAssignableFrom(member.javaClass) && equalsJvmSignature(declaration, member) } - val methods = eclipseType.getMethods().filter { check(it) } - val fields = eclipseType.getFields().filter { check(it) } + val methods = eclipseType.methods.filter { check(it) } + val fields = eclipseType.fields.filter { check(it) } return methods + fields } } -public fun KtElement.toLightElements(): List { +fun KtElement.toLightElements(): List { val javaProject = KotlinPsiManager.getJavaProject(this) if (javaProject == null) { KotlinLogger.logWarning("Cannot resolve jetElement ($this) to light elements: there is no corresponding java project") @@ -119,28 +100,33 @@ public fun KtElement.toLightElements(): List { is KtSecondaryConstructor, is KtPrimaryConstructor, is KtPropertyAccessor -> KotlinJavaManager.findEclipseMembers(this as KtDeclaration, javaProject, IMethod::class.java) - is KtProperty -> KotlinJavaManager.findEclipseMembers(this, javaProject, IMember::class.java) + is KtProperty -> { + val list = KotlinJavaManager.findEclipseMembers(this, javaProject, IMember::class.java) + val getterList = getter?.toLightElements() ?: emptyList() + val setterList = setter?.toLightElements() ?: emptyList() + list + getterList + setterList + } else -> emptyList() } } -public fun SourceElement.toJavaElements(): List { +fun SourceElement.toJavaElements(): List { return when (this) { - is EclipseJavaSourceElement -> obtainJavaElement(this.getElementBinding())?.let(::listOf) ?: emptyList() - is KotlinSourceElement -> this.psi.toLightElements() - else -> emptyList() + is EclipseJavaSourceElement -> obtainJavaElement(elementBinding)?.let(::listOf) ?: emptyList() + is KotlinSourceElement -> psi.toLightElements() + else -> emptyList() } } -public fun sourceElementsToLightElements(sourceElements: List): List { +fun sourceElementsToLightElements(sourceElements: List): List { return sourceElements.flatMap { it.toJavaElements() } } private fun obtainJavaElement(binding: IBinding): IJavaElement? { - return if (binding is IMethodBinding && binding.isDefaultConstructor()) { - binding.getDeclaringClass().getJavaElement() + return if (binding is IMethodBinding && binding.isDefaultConstructor) { + binding.declaringClass.javaElement } else { - binding.getJavaElement() + binding.javaElement } } diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinPropertiesExtensions.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinPropertiesExtensions.kt index ff86a31be..401104baf 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinPropertiesExtensions.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinPropertiesExtensions.kt @@ -1,38 +1,48 @@ package org.jetbrains.kotlin.core.preferences -import org.jetbrains.kotlin.config.AnalysisFlag -import org.jetbrains.kotlin.config.JvmDefaultMode -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl -import org.jetbrains.kotlin.config.JvmAnalysisFlags -import org.jetbrains.kotlin.utils.ReportLevel -import org.jetbrains.kotlin.utils.Jsr305State +import org.jetbrains.kotlin.config.* -private enum class CompilerFlagsMapping(val flag: String) : (String) -> Pair, *>? { +private enum class CompilerFlagsMapping(val flag: String, vararg val alternativeFlags: String) : (List) -> Pair, *>? { JVM_DEFAULT("-Xjvm-default") { - override fun invoke(value: String) = - JvmDefaultMode.fromStringOrNull(value) + override fun invoke(value: List): Pair, JvmDefaultMode>? { + if (value.isEmpty()) return null + val tempSingle = value.single() + return JvmDefaultMode.fromStringOrNull(tempSingle) ?.let { JvmAnalysisFlags.jvmDefaultMode to it } + } }, - JSR_305("-Xjsr305") { - override fun invoke(value: String) = - when (ReportLevel.findByDescription(value)) { - ReportLevel.IGNORE -> Jsr305State.DISABLED - ReportLevel.WARN -> Jsr305State.DEFAULT - ReportLevel.STRICT -> Jsr305State.STRICT + OPT_IN("-opt-in", "-Xopt-in") { + override fun invoke(value: List): Pair, *>? { + if (value.isEmpty()) return null + return AnalysisFlags.optIn to value + } + }, + + USE_XR("-Xuse-ir") { + override fun invoke(value: List): Pair, *>? { + if (value.isEmpty()) return null + val tempSingle = value.single() + val tempUseIr = tempSingle.toBooleanStrictOrNull() + return when { + tempUseIr != null -> JvmAnalysisFlags.useIR to tempUseIr else -> null - }?.let { JvmAnalysisFlags.jsr305 to it } + } + } }; companion object { - fun flagByString(flag: String) = values().firstOrNull { it.flag == flag } + fun flagByString(flag: String) = values().firstOrNull { it.flag == flag || flag in it.alternativeFlags } } } private val KotlinProperties.analyzerCompilerFlags: Map, Any?> get() = compilerFlags?.split("\\s+".toRegex())?.mapNotNull { flagString -> flagString.split("=", limit = 2).takeIf { it.size == 2 } - }?.mapNotNull { (key, value) -> + }?.groupBy( { (key) -> + key + }, { (_, value) -> + value + })?.mapNotNull { (key, value) -> CompilerFlagsMapping.flagByString(key)?.invoke(value) }.orEmpty().toMap() diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/Preferences.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/Preferences.kt index dac57aeb5..78d68f2a9 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/Preferences.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/Preferences.kt @@ -108,7 +108,7 @@ abstract class Preferences(private val scope: IScopeContext, private val path: S in modifiedValues -> modifiedValues[key] in removedValues -> null else -> mainStore.getValue(key) - } ?: inheritedStores.firstNotNullResult { it.getValue(key) } + } ?: inheritedStores.firstNotNullOfOrNull { it.getValue(key) } // Does not save changes fun setValue(key: String, value: String) { diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/references/KotlinReference.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/references/KotlinReference.kt index b1248cb1f..782a6e02d 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/references/KotlinReference.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/references/KotlinReference.kt @@ -19,59 +19,94 @@ package org.jetbrains.kotlin.core.references import com.intellij.util.SmartList import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.calls.callUtil.getCall -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall +import org.jetbrains.kotlin.resolve.calls.util.getCall +import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addIfNotNull -import java.util.* -inline private fun ArrayList.register(e: KtElement, action: (T) -> KotlinReference) { +inline private fun ArrayList>.register( + e: KtElement, + action: (T) -> KotlinReference +) { if (e is T) this.add(action(e)) } -inline private fun ArrayList.registerMulti(e: KtElement, action: (T) -> List) { +inline private fun ArrayList>.registerMulti( + e: KtElement, + action: (T) -> List> +) { if (e is T) this.addAll(action(e)) } -public fun createReferences(element: KtReferenceExpression): List { - return arrayListOf().apply { - register(element, ::KotlinSimpleNameReference) - - register(element, ::KotlinInvokeFunctionReference) - - register(element, ::KotlinConstructorDelegationReference) - +public fun createReferences(element: KtElement): List> { + return arrayListOf>().apply { + register(element, ::KotlinSimpleNameReference) + + register(element, ::KotlinInvokeFunctionReference) + + register(element, ::KotlinConstructorDelegationReference) + registerMulti(element) { if (it.getReferencedNameElementType() != KtTokens.IDENTIFIER) return@registerMulti emptyList() - + when (it.readWriteAccess()) { ReferenceAccess.READ -> listOf(KotlinSyntheticPropertyAccessorReference.Getter(it)) ReferenceAccess.WRITE -> listOf(KotlinSyntheticPropertyAccessorReference.Setter(it)) ReferenceAccess.READ_WRITE -> listOf( - KotlinSyntheticPropertyAccessorReference.Getter(it), - KotlinSyntheticPropertyAccessorReference.Setter(it)) + KotlinSyntheticPropertyAccessorReference.Getter(it), + KotlinSyntheticPropertyAccessorReference.Setter(it) + ) } } + register(element, ::KotlinReferenceExpressionReference) + + register(element, ::KotlinKtPropertyDelegateReference) } } -public interface KotlinReference { - val expression: KtReferenceExpression - +public interface KotlinReference { + + val expression: KtElement + fun getTargetDescriptors(context: BindingContext): Collection val resolvesByNames: Collection } -open class KotlinSimpleNameReference(override val expression: KtSimpleNameExpression) : KotlinReference { - override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context) +class KotlinKtPropertyDelegateReference(override val expression: KtPropertyDelegate) : + KotlinReference { + + override fun getTargetDescriptors(context: BindingContext): Collection { + val tempProperty = expression.getParentOfType(false) ?: return emptyList() + val tempDescriptor = + tempProperty.resolveToDescriptorIfAny() as? VariableDescriptorWithAccessors ?: return emptyList() + val tempProviderDescriptor = context[BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, tempDescriptor]?.candidateDescriptor + val tempGetDescriptor = tempDescriptor.getter?.let { context[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, it]?.candidateDescriptor } + val tempSetDescriptor = tempDescriptor.setter?.let { context[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, it]?.candidateDescriptor } + + return listOfNotNull(tempProviderDescriptor, tempGetDescriptor, tempSetDescriptor) + } + + override val resolvesByNames: Collection + get() = emptyList() + +} + +open class KotlinSimpleNameReference(override val expression: KtSimpleNameExpression) : + KotlinReference { + override fun getTargetDescriptors(context: BindingContext): Collection { + return expression.getReferenceTargets(context) + } override val resolvesByNames: Collection get() { @@ -87,8 +122,7 @@ open class KotlinSimpleNameReference(override val expression: KtSimpleNameExpres return if (counterpart != null) { val counterpartName = OperatorConventions.getNameForOperationSymbol(counterpart, false, true)!! listOf(name, counterpartName) - } - else { + } else { listOf(name) } } @@ -98,7 +132,8 @@ open class KotlinSimpleNameReference(override val expression: KtSimpleNameExpres } } -public class KotlinInvokeFunctionReference(override val expression: KtCallExpression) : KotlinReference { +public class KotlinInvokeFunctionReference(override val expression: KtCallExpression) : + KotlinReference { override val resolvesByNames: Collection get() = listOf(OperatorNameConventions.INVOKE) @@ -113,12 +148,14 @@ public class KotlinInvokeFunctionReference(override val expression: KtCallExpres } } -sealed class KotlinSyntheticPropertyAccessorReference(override val expression: KtNameReferenceExpression, private val getter: Boolean) - : KotlinSimpleNameReference(expression) { +sealed class KotlinSyntheticPropertyAccessorReference( + expression: KtNameReferenceExpression, + private val getter: Boolean +) : KotlinSimpleNameReference(expression) { override fun getTargetDescriptors(context: BindingContext): Collection { val descriptors = super.getTargetDescriptors(context) if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList() - + val result = SmartList() for (descriptor in descriptors) { if (descriptor is SyntheticJavaPropertyDescriptor) { @@ -134,23 +171,35 @@ sealed class KotlinSyntheticPropertyAccessorReference(override val expression: K override val resolvesByNames: Collection get() = listOf(expression.getReferencedNameAsName()) - + class Getter(expression: KtNameReferenceExpression) : KotlinSyntheticPropertyAccessorReference(expression, true) class Setter(expression: KtNameReferenceExpression) : KotlinSyntheticPropertyAccessorReference(expression, false) } -public class KotlinConstructorDelegationReference(override val expression: KtConstructorDelegationReferenceExpression) : KotlinReference { +public class KotlinConstructorDelegationReference(override val expression: KtConstructorDelegationReferenceExpression) : + KotlinReference { override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context) override val resolvesByNames: Collection get() = emptyList() } +class KotlinReferenceExpressionReference(override val expression: KtReferenceExpression) : + KotlinReference { + override fun getTargetDescriptors(context: BindingContext): Collection { + return expression.getReferenceTargets(context) + } + + override val resolvesByNames: Collection + get() = emptyList() + +} + fun KtReferenceExpression.getReferenceTargets(context: BindingContext): Collection { val targetDescriptor = context[BindingContext.REFERENCE_TARGET, this] return if (targetDescriptor != null) { - listOf(targetDescriptor) - } else { - context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this].orEmpty() - } -} \ No newline at end of file + listOf(targetDescriptor) + } else { + context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this].orEmpty() + } +} diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/references/referenceUtils.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/references/referenceUtils.kt index 4116c949a..c0469445c 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/references/referenceUtils.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/references/referenceUtils.kt @@ -16,123 +16,106 @@ *******************************************************************************/ package org.jetbrains.kotlin.core.references -import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.core.resolve.EclipseDescriptorUtils -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.core.references.KotlinReference +import com.intellij.openapi.util.Key import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.psi.KtReferenceExpression import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.psi.KtElement -import org.eclipse.jdt.core.IJavaElement -import org.jetbrains.kotlin.core.resolve.lang.java.resolver.EclipseJavaSourceElement -import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.eclipse.jdt.core.IJavaProject -import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer -import org.jetbrains.kotlin.core.model.sourceElementsToLightElements import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.core.builder.KotlinPsiManager -import com.intellij.openapi.util.Key -import org.jetbrains.kotlin.psi.KtObjectDeclaration -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.core.model.toJavaElements -import org.jetbrains.kotlin.core.log.KotlinLogger -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtParenthesizedExpression -import org.jetbrains.kotlin.psi.KtAnnotatedExpression -import org.jetbrains.kotlin.psi.KtLabeledExpression -import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis -import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.types.expressions.OperatorConventions -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess -import org.jetbrains.kotlin.psi.KtUnaryExpression -import org.jetbrains.kotlin.utils.addToStdlib.constant +import org.jetbrains.kotlin.core.resolve.EclipseDescriptorUtils +import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer +import org.jetbrains.kotlin.core.utils.getBindingContext +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors +import org.jetbrains.kotlin.descriptors.accessors +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport -import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension -import org.jetbrains.kotlin.psi.KtNameReferenceExpression import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver -import org.jetbrains.kotlin.psi.KtThisExpression -import org.jetbrains.kotlin.psi.KtSuperExpression +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension +import org.jetbrains.kotlin.resolve.source.KotlinSourceElement +import org.jetbrains.kotlin.utils.addToStdlib.constant -public val FILE_PROJECT: Key = Key.create("FILE_PROJECT") +val FILE_PROJECT: Key = Key.create("FILE_PROJECT") -public fun List.resolveToSourceElements(): List { +fun List>.resolveToSourceElements(ktFile: KtFile): List { if (isEmpty()) return emptyList() - - val jetFile = first().expression.getContainingKtFile() - val javaProject = JavaCore.create(KotlinPsiManager.getEclipseFile(jetFile)?.getProject()) - ?: jetFile.getUserData(FILE_PROJECT) - if (javaProject == null) return emptyList() - return resolveToSourceElements( - KotlinAnalyzer.analyzeFile(jetFile).analysisResult.bindingContext, - javaProject) + val javaProject = JavaCore.create(KotlinPsiManager.getEclipseFile(ktFile)?.project) + ?: ktFile.getUserData(FILE_PROJECT) ?: return emptyList() + + return resolveToSourceElements(ktFile.getBindingContext(), javaProject) } -public fun List.resolveToSourceElements(context: BindingContext, javaProject: IJavaProject): List { +fun List>.resolveToSourceElements( + context: BindingContext, + javaProject: IJavaProject +): List { return flatMap { it.getTargetDescriptors(context) } - .flatMap { EclipseDescriptorUtils.descriptorToDeclarations(it, javaProject.project) } + .flatMap { EclipseDescriptorUtils.descriptorToDeclarations(it, javaProject.project) } } -public fun getReferenceExpression(element: PsiElement): KtReferenceExpression? { - return PsiTreeUtil.getNonStrictParentOfType(element, KtReferenceExpression::class.java) +fun getReferenceExpression(element: PsiElement): KtReferenceExpression? { + return PsiTreeUtil.getNonStrictParentOfType(element, KtReferenceExpression::class.java) } -public fun KtElement.resolveToSourceDeclaration(): List { - val jetElement = this - return when (jetElement) { - is KtDeclaration -> { - listOf(KotlinSourceElement(jetElement)) - } - +fun KtElement.resolveToSourceDeclaration(): List { + return when (val jetElement = this) { + is KtDeclaration -> listOf(KotlinSourceElement(jetElement)) else -> { // Try search declaration by reference - val referenceExpression = getReferenceExpression(jetElement) - if (referenceExpression == null) return emptyList() - + val referenceExpression = getReferenceExpression(jetElement) ?: jetElement val reference = createReferences(referenceExpression) - reference.resolveToSourceElements() - } + reference.resolveToSourceElements(jetElement.containingKtFile) + } } } -public enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) { +enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) { READ(true, false), WRITE(false, true), READ_WRITE(true, true) } -public fun KtExpression.readWriteAccess(): ReferenceAccess { +fun KtExpression.readWriteAccess(): ReferenceAccess { var expression = getQualifiedExpressionForSelectorOrThis() loop@ while (true) { - val parent = expression.parent - when (parent) { - is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression + when (val parent = expression.parent) { + is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = + parent as KtExpression else -> break@loop } } val assignment = expression.getAssignmentByLHS() if (assignment != null) { - when (assignment.operationToken) { - KtTokens.EQ -> return ReferenceAccess.WRITE - else -> return ReferenceAccess.READ_WRITE + return when (assignment.operationToken) { + KtTokens.EQ -> ReferenceAccess.WRITE + else -> ReferenceAccess.READ_WRITE } } - return if ((expression.parent as? KtUnaryExpression)?.operationToken in constant { setOf(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS) }) + return if ((expression.parent as? KtUnaryExpression)?.operationToken in constant { + setOf( + KtTokens.PLUSPLUS, + KtTokens.MINUSMINUS + ) + }) ReferenceAccess.READ_WRITE else ReferenceAccess.READ } // TODO: obtain this function from referenceUtil.kt (org.jetbrains.kotlin.idea.references) -fun KotlinReference.canBeResolvedViaImport(target: DeclarationDescriptor): Boolean { +fun KotlinReference<*>.canBeResolvedViaImport(target: DeclarationDescriptor): Boolean { if (!target.canBeReferencedViaImport()) return false if (target.isExtension) return true // assume that any type of reference can use imports when resolved to extension val referenceExpression = this.expression as? KtNameReferenceExpression ?: return false if (CallTypeAndReceiver.detect(referenceExpression).receiver != null) return false if (expression.parent is KtThisExpression || expression.parent is KtSuperExpression) return false // TODO: it's a bad design of PSI tree, we should change it return true -} \ No newline at end of file +} diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/BuiltInsReferenceResolver.java b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/BuiltInsReferenceResolver.java index d90fc9016..e8e6dcf58 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/BuiltInsReferenceResolver.java +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/BuiltInsReferenceResolver.java @@ -20,7 +20,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VfsBundle; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.psi.PsiDirectory; @@ -36,6 +35,7 @@ import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices; import org.jetbrains.kotlin.builtins.DefaultBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; +import org.jetbrains.kotlin.builtins.StandardNames; import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl; import org.jetbrains.kotlin.container.DslKt; import org.jetbrains.kotlin.container.StorageComponentContainer; @@ -61,10 +61,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; public class BuiltInsReferenceResolver { private static final String RUNTIME_SRC_DIR = "jar:file:"+ ProjectUtils.buildLibPath("kotlin-stdlib-sources")+ "!/kotlin"; @@ -93,12 +90,13 @@ private void initialize() { //if the sources are present, then the value cannot be null assert (jetBuiltInsFiles != null); - + + Map, Object> tempCapabilities = Collections.emptyMap(); MutableModuleContext newModuleContext = ContextKt.ContextForNewModule( ContextKt.ProjectContext(myProject, "Context for built-ins resolver module"), Name.special(""), DefaultBuiltIns.getInstance(), - null); + null, tempCapabilities); newModuleContext.setDependencies(newModuleContext.getModule()); StorageComponentContainer container = InjectionKt.createContainerForLazyResolve( @@ -115,7 +113,7 @@ private void initialize() { newModuleContext.initializeModuleContents(resolveSession.getPackageFragmentProvider()); PackageViewDescriptor packageView = newModuleContext.getModule().getPackage( - KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME); + StandardNames.BUILT_INS_PACKAGE_FQ_NAME); List fragments = packageView.getFragments(); moduleDescriptor = newModuleContext.getModule(); @@ -164,17 +162,19 @@ private String convertPathFromURL(URL url) { String protocol = url.getProtocol(); String path = url.getPath(); if (protocol.equals("jar")) { - if (StringUtil.startsWithConcatenation(path, "file", ":")) { + if (StringUtil.startsWith(path, "file:")) { try { URL subURL = new URL(path); path = subURL.getPath(); } catch (MalformedURLException e) { - throw new RuntimeException(VfsBundle.message("url.parse.unhandled.exception"), e); + //VfsBundle.message("url.parse.unhandled.exception") + throw new RuntimeException("Malformed URL!", e); } } else { - throw new RuntimeException(new IOException(VfsBundle.message("url.parse.error", url.toExternalForm()))); + throw new RuntimeException(new IOException("Url Parse Error" + url.toExternalForm())); + //VfsBundle.message("url.parse.error", url.toExternalForm()) } } if (SystemInfo.isWindows) { @@ -229,7 +229,7 @@ public DeclarationDescriptor findCurrentDescriptor(@NotNull DeclarationDescripto } if (originalDescriptor instanceof PackageFragmentDescriptor) { - return KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME.equals(((PackageFragmentDescriptor) originalDescriptor).getFqName()) + return StandardNames.BUILT_INS_PACKAGE_FQ_NAME.equals(((PackageFragmentDescriptor) originalDescriptor).getFqName()) ? builtinsPackageFragment : null; } diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseAnalyzerFacadeForJVM.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseAnalyzerFacadeForJVM.kt index e701a6dce..3fbab17a7 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseAnalyzerFacadeForJVM.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseAnalyzerFacadeForJVM.kt @@ -21,7 +21,6 @@ import com.intellij.psi.search.GlobalSearchScope import org.eclipse.core.runtime.Path import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.JavaCore -import org.eclipse.jdt.launching.JavaRuntime import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsPackageFragmentProvider @@ -37,10 +36,11 @@ import org.jetbrains.kotlin.context.MutableModuleContext import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.log.KotlinLogger +import org.jetbrains.kotlin.core.model.EclipseScriptDefinitionProvider import org.jetbrains.kotlin.core.model.KotlinCommonEnvironment import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.model.KotlinScriptEnvironment -import org.jetbrains.kotlin.core.script.EnvironmentProjectsManager +import org.jetbrains.kotlin.core.preferences.languageVersionSettings import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.core.utils.asResource import org.jetbrains.kotlin.descriptors.PackageFragmentProvider @@ -49,15 +49,28 @@ import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer -import org.jetbrains.kotlin.resolve.TopDownAnalysisMode +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension +import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformConfigurator import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer +import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo +import org.jetbrains.kotlin.resolve.lazy.data.KtScriptInfo +import org.jetbrains.kotlin.resolve.lazy.declarations.AbstractPsiBasedDeclarationProvider +import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource +import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration +import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.util.KotlinFrontEndException -import java.util.* +import kotlin.script.experimental.api.KotlinType +import kotlin.script.experimental.api.valueOrNull +import kotlin.script.experimental.util.PropertiesCollection data class AnalysisResultWithProvider(val analysisResult: AnalysisResult, val componentProvider: ComponentProvider?) { companion object { @@ -67,8 +80,8 @@ data class AnalysisResultWithProvider(val analysisResult: AnalysisResult, val co object EclipseAnalyzerFacadeForJVM { fun analyzeSources( - environment: KotlinEnvironment, - filesToAnalyze: Collection + environment: KotlinEnvironment, + filesToAnalyze: Collection ): AnalysisResultWithProvider { val filesSet = filesToAnalyze.toSet() if (filesSet.size != filesToAnalyze.size) { @@ -91,42 +104,124 @@ object EclipseAnalyzerFacadeForJVM { } fun analyzeScript( - environment: KotlinScriptEnvironment, - scriptFile: KtFile + environment: KotlinScriptEnvironment, + scriptFile: KtFile ): AnalysisResultWithProvider { - val javaProject = EnvironmentProjectsManager[scriptFile].apply { - val jvmLibraries = JavaRuntime.getDefaultVMInstall() - ?.let { JavaRuntime.getLibraryLocations(it) } - ?.map { JavaCore.newLibraryEntry(it.systemLibraryPath, null, null) } - .orEmpty() - - val userLibraries = (environment.dependencies - ?.classpath.orEmpty() + environment.definitionClasspath) - .map { JavaCore.newLibraryEntry(Path(it.absolutePath), null, null) } - .orEmpty() - .toSet() - - (jvmLibraries + userLibraries) - .toTypedArray() - .also { setRawClasspath(it, null) } - } - - val allFiles = LinkedHashSet().run { - add(scriptFile) - environment.dependencies?.sources?.toList() + //TODO actually take dependencies from script configuration! + val javaProject = environment.javaProject + + val tempOrigClasspath = javaProject.rawClasspath + + try { + val tempSourceCode = KtFileScriptSource(scriptFile) + val tempContribution = EclipseScriptDefinitionProvider.getContribution(tempSourceCode) + + val tempNewClasspath = tempContribution?.createClasspath(environment) ?: (tempOrigClasspath + environment.definitionClasspath.map { + JavaCore.newLibraryEntry(Path(it.absolutePath), null, null) + }).distinctBy { it.path }.toTypedArray() + + javaProject.setRawClasspath(tempNewClasspath, null) + + val allFiles = LinkedHashSet().run { + add(scriptFile) + environment.dependencies?.sources?.toList() .orEmpty() .mapNotNull { it.asResource } .mapNotNull { KotlinPsiManager.getKotlinParsedFile(it) } .toCollection(this) - } + } - return analyzeKotlin( + ProjectUtils.getSourceFilesWithDependencies(environment.javaProject).toCollection(allFiles) + + val tempRefinedConfig = environment.definition?.let { + refineScriptCompilationConfiguration(tempSourceCode, it, environment.project) + }?.valueOrNull()?.configuration + + + val tempDefaultImports = + tempRefinedConfig?.get(PropertiesCollection.Key("defaultImports", emptyList())) ?: emptyList() + val tempImports = ArrayList(tempDefaultImports) + + val analyzerService = object : PlatformDependentAnalyzerServices() { + + override val defaultLowPriorityImports: List = listOf(ImportPath.fromString("java.lang.*")) + + override val platformConfigurator: PlatformConfigurator = JvmPlatformConfigurator + + override fun computePlatformSpecificDefaultImports( + storageManager: StorageManager, + result: MutableList + ) { + result.add(ImportPath.fromString("kotlin.jvm.*")) + tempImports.map(ImportPath::fromString).toCollection(result) + + fun addAllClassifiersFromScope(scope: MemberScope) { + for (descriptor in scope.getContributedDescriptors( + DescriptorKindFilter.CLASSIFIERS, + MemberScope.ALL_NAME_FILTER + )) { + result.add(ImportPath(DescriptorUtils.getFqNameSafe(descriptor), false)) + } + } + + for (builtInPackage in JvmBuiltIns( + storageManager, + JvmBuiltIns.Kind.FROM_CLASS_LOADER + ).builtInPackagesImportedByDefault) { + addAllClassifiersFromScope(builtInPackage.memberScope) + } + } + } + + val tempProperties = + tempRefinedConfig?.get(PropertiesCollection.Key("providedProperties", emptyMap())) + + val declarationProviderFactory: (StorageManager) -> DeclarationProviderFactory = { storageManager -> + object : FileBasedDeclarationProviderFactory(storageManager, allFiles) { + + private val factory = KtPsiFactory(environment.project, true) + + override fun getClassMemberDeclarationProvider(classLikeInfo: KtClassLikeInfo): ClassMemberDeclarationProvider { + if (classLikeInfo is KtScriptInfo) { + return object : AbstractPsiBasedDeclarationProvider(storageManager), + ClassMemberDeclarationProvider { + override val ownerInfo: KtClassLikeInfo = classLikeInfo + + override fun doCreateIndex(index: Index) { + val tempProvidedProperties = tempProperties?.entries?.map { (key, value) -> + val isNullable = tempContribution?.isNullable(key, tempRefinedConfig) ?: true + val tempTypeName = value.fromClass?.qualifiedName ?: value.typeName + val tempText = + """ + /** Provided property '$key' of type: $tempTypeName */ + val $key: $tempTypeName${'$'}${if (isNullable) "? = null" else " = TODO()"}""".trimIndent() + factory.createProperty(tempText) + } ?: emptyList() + + val tempDeclarations = ownerInfo.declarations + + ownerInfo.primaryConstructorParameters + + tempProvidedProperties + + tempDeclarations.forEach(index::putToIndex) + } + } + } + return super.getClassMemberDeclarationProvider(classLikeInfo) + } + } + } + + return analyzeKotlin( filesToAnalyze = listOf(scriptFile), allFiles = allFiles, environment = environment, - javaProject = javaProject - ) - + javaProject = javaProject, + analyzerService = analyzerService, + providerFactoryCreator = declarationProviderFactory + ) + } finally { + javaProject.setRawClasspath(tempOrigClasspath, null) + } } private fun analyzeKotlin( @@ -134,22 +229,31 @@ object EclipseAnalyzerFacadeForJVM { allFiles: Collection, environment: KotlinCommonEnvironment, javaProject: IJavaProject?, - jvmTarget: JvmTarget = JvmTarget.DEFAULT + jvmTarget: JvmTarget = JvmTarget.DEFAULT, + analyzerService: PlatformDependentAnalyzerServices? = null, + providerFactoryCreator: (StorageManager) -> DeclarationProviderFactory = { storageManager -> + FileBasedDeclarationProviderFactory(storageManager, allFiles) + } + ): AnalysisResultWithProvider { val project = environment.project val moduleContext = createModuleContext(project, environment.configuration, true) val storageManager = moduleContext.storageManager val module = moduleContext.module - val providerFactory = FileBasedDeclarationProviderFactory(moduleContext.storageManager, allFiles) + val providerFactory = providerFactoryCreator(storageManager) val trace = CliBindingTrace() val sourceScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, filesToAnalyze) val moduleClassResolver = TopDownAnalyzerFacadeForJVM.SourceOrBinaryModuleClassResolver(sourceScope) - val languageVersionSettings = LanguageVersionSettingsImpl( - LanguageVersionSettingsImpl.DEFAULT.languageVersion, - LanguageVersionSettingsImpl.DEFAULT.apiVersion) + val languageVersionSettings = + javaProject?.project?.let { KotlinEnvironment.getEnvironment(it).compilerProperties.languageVersionSettings } + ?: LanguageVersionSettingsImpl( + LanguageVersionSettingsImpl.DEFAULT.languageVersion, + LanguageVersionSettingsImpl.DEFAULT.apiVersion + ) + val optionalBuiltInsModule = JvmBuiltIns(storageManager, JvmBuiltIns.Kind.FROM_CLASS_LOADER) .apply { initialize(module, true) } @@ -157,47 +261,60 @@ object EclipseAnalyzerFacadeForJVM { val dependencyModule = run { val dependenciesContext = ContextForNewModule( - moduleContext, Name.special(""), - module.builtIns, null + moduleContext, Name.special( + "" + ), + module.builtIns, null ) val dependencyScope = GlobalSearchScope.notScope(sourceScope) val dependenciesContainer = createContainerForTopDownAnalyzerForJvm( - dependenciesContext, - trace, - DeclarationProviderFactory.EMPTY, - dependencyScope, - LookupTracker.DO_NOTHING, - KotlinPackagePartProvider(environment), - jvmTarget, - languageVersionSettings, - moduleClassResolver, - javaProject) + dependenciesContext, + trace, + DeclarationProviderFactory.EMPTY, + dependencyScope, + LookupTracker.DO_NOTHING, + KotlinPackagePartProvider(environment), + jvmTarget, + languageVersionSettings, + moduleClassResolver, + javaProject, + environment.project.getService(JavaModuleResolver::class.java), + null + ) moduleClassResolver.compiledCodeResolver = dependenciesContainer.get() dependenciesContext.setDependencies(listOfNotNull(dependenciesContext.module, optionalBuiltInsModule)) dependenciesContext.initializeModuleContents( - CompositePackageFragmentProvider(listOf( - moduleClassResolver.compiledCodeResolver.packageFragmentProvider, - dependenciesContainer.get() - )) + CompositePackageFragmentProvider( + listOf( + moduleClassResolver.compiledCodeResolver.packageFragmentProvider, + dependenciesContainer.get() + ), "" + ) ) dependenciesContext.module } val container = createContainerForTopDownAnalyzerForJvm( - moduleContext, - trace, - providerFactory, - sourceScope, - LookupTracker.DO_NOTHING, - KotlinPackagePartProvider(environment), - jvmTarget, - languageVersionSettings, - moduleClassResolver, - javaProject).apply { + moduleContext, + trace, + providerFactory, + sourceScope, + LookupTracker.DO_NOTHING, + KotlinPackagePartProvider(environment), + jvmTarget, + languageVersionSettings, + moduleClassResolver, + javaProject, + environment.project.getService(JavaModuleResolver::class.java), + analyzerService + ).apply { initJvmBuiltInsForTopDownAnalysis() } @@ -211,16 +328,19 @@ object EclipseAnalyzerFacadeForJVM { } module.setDependencies( - listOfNotNull(module, dependencyModule, optionalBuiltInsModule), - setOf(dependencyModule) + listOfNotNull(module, dependencyModule, optionalBuiltInsModule), + setOf(dependencyModule) ) - module.initialize(CompositePackageFragmentProvider( + module.initialize( + CompositePackageFragmentProvider( listOf(container.get().packageFragmentProvider) + - additionalProviders - )) + additionalProviders, "" + ) + ) try { - container.get().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, filesToAnalyze) + container.get() + .analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, filesToAnalyze) } catch (e: KotlinFrontEndException) { // Editor will break if we do not catch this exception // and will not be able to save content without reopening it. @@ -229,8 +349,9 @@ object EclipseAnalyzerFacadeForJVM { } return AnalysisResultWithProvider( - AnalysisResult.success(trace.bindingContext, module), - container) + AnalysisResult.success(trace.bindingContext, module), + container + ) } private fun getPath(jetFile: KtFile): String? = jetFile.virtualFile?.path @@ -241,14 +362,19 @@ object EclipseAnalyzerFacadeForJVM { createBuiltInsFromModule: Boolean ): MutableModuleContext { val projectContext = ProjectContext(project, "context for project ${project.name}") - val builtIns = JvmBuiltIns(projectContext.storageManager, - if (createBuiltInsFromModule) JvmBuiltIns.Kind.FROM_DEPENDENCIES else JvmBuiltIns.Kind.FROM_CLASS_LOADER) + val builtIns = JvmBuiltIns( + projectContext.storageManager, + if (createBuiltInsFromModule) JvmBuiltIns.Kind.FROM_DEPENDENCIES else JvmBuiltIns.Kind.FROM_CLASS_LOADER + ) return ContextForNewModule( - projectContext, Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"), builtIns, null + projectContext, + Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"), + builtIns, + null ).apply { if (createBuiltInsFromModule) { builtIns.builtInsModule = module } } } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinCacheServiceImpl.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinCacheServiceImpl.kt index ed135eb2b..eb0c326f3 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinCacheServiceImpl.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinCacheServiceImpl.kt @@ -34,9 +34,16 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.analyzer.ResolverForProject +import org.jetbrains.kotlin.caches.resolve.PlatformAnalysisSettings +import org.jetbrains.kotlin.diagnostics.DiagnosticSink +import org.jetbrains.kotlin.idea.FrontendInternals -class KotlinCacheServiceImpl(val ideaProject: Project) : KotlinCacheService { - override fun getResolutionFacade(elements: List, platform: TargetPlatform): ResolutionFacade { +class KotlinCacheServiceImpl(private val ideaProject: Project) : KotlinCacheService { + + override fun getResolutionFacadeWithForcedPlatform( + elements: List, + platform: TargetPlatform + ): ResolutionFacade { return KotlinSimpleResolutionFacade(ideaProject, elements) } @@ -44,6 +51,13 @@ class KotlinCacheServiceImpl(val ideaProject: Project) : KotlinCacheService { throw UnsupportedOperationException() } + override fun getResolutionFacadeByModuleInfo( + moduleInfo: ModuleInfo, + settings: PlatformAnalysisSettings + ): ResolutionFacade? { + throw UnsupportedOperationException() + } + override fun getSuppressionCache(): KotlinSuppressCache { throw UnsupportedOperationException() } @@ -51,10 +65,14 @@ class KotlinCacheServiceImpl(val ideaProject: Project) : KotlinCacheService { override fun getResolutionFacade(elements: List): ResolutionFacade { return KotlinSimpleResolutionFacade(ideaProject, elements) } + + override fun getResolutionFacade(element: KtElement): ResolutionFacade = getResolutionFacade(listOf(element)) + override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? = null } +@OptIn(FrontendInternals::class) class KotlinSimpleResolutionFacade( override val project: Project, private val elements: List) : ResolutionFacade { @@ -71,35 +89,37 @@ class KotlinSimpleResolutionFacade( get() = throw UnsupportedOperationException() override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext { - val ktFile = element.getContainingKtFile() + val ktFile = element.containingKtFile return KotlinAnalysisFileCache.getAnalysisResult(ktFile).analysisResult.bindingContext } - + + override fun analyzeWithAllCompilerChecks( + elements: Collection, + callback: DiagnosticSink.DiagnosticsCallback? + ): AnalysisResult { + val ktFile = elements.first().containingKtFile + return KotlinAnalysisFileCache.getAnalysisResult(ktFile).analysisResult + } + override fun analyze(elements: Collection, bodyResolveMode: BodyResolveMode): BindingContext { if (elements.isEmpty()) { return BindingContext.EMPTY } - val ktFile = elements.first().getContainingKtFile() + val ktFile = elements.first().containingKtFile return KotlinAnalysisFileCache.getAnalysisResult(ktFile).analysisResult.bindingContext } - - override fun analyzeWithAllCompilerChecks(elements: Collection): AnalysisResult { - throw UnsupportedOperationException() - } - + override fun getFrontendService(element: PsiElement, serviceClass: Class): T { throw UnsupportedOperationException() } override fun getFrontendService(serviceClass: Class): T { - val files = elements.map { it.getContainingKtFile() }.toSet() + val files = elements.map { it.containingKtFile }.toSet() if (files.isEmpty()) throw IllegalStateException("Elements should not be empty") val componentProvider = KotlinAnalyzer.analyzeFiles(files).componentProvider - if (componentProvider == null) { - throw IllegalStateException("Trying to get service from non-initialized project") - } - + ?: throw IllegalStateException("Trying to get service from non-initialized project") + return componentProvider.getService(serviceClass) } diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinPackagePartProvider.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinPackagePartProvider.kt index cddf2f7c5..e6393866e 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinPackagePartProvider.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinPackagePartProvider.kt @@ -1,19 +1,19 @@ /******************************************************************************* -* Copyright 2000-2016 JetBrains s.r.o. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -*******************************************************************************/ + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *******************************************************************************/ package org.jetbrains.kotlin.core.resolve import com.intellij.openapi.vfs.VirtualFile @@ -25,22 +25,23 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping import org.jetbrains.kotlin.metadata.jvm.deserialization.PackageParts import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration -import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.serialization.deserialization.ClassData +import org.jetbrains.kotlin.utils.SmartList import java.io.EOFException +import java.io.FileNotFoundException public class KotlinPackagePartProvider(private val environment: KotlinCommonEnvironment) : PackagePartProvider { private data class ModuleMappingInfo(val root: VirtualFile, val mapping: ModuleMapping, val name: String) - + private val notLoadedRoots by lazy(LazyThreadSafetyMode.NONE) { - environment.getRoots() - .map { it.file } - .filter { it.findChild("META-INF") != null } - .toMutableList() + environment.getRoots() + .map { it.file } + .filter { it.findChild("META-INF") != null } + .toMutableList() } - + private val loadedModules: MutableList = SmartList() - + private val deserializationConfiguration = CompilerDeserializationConfiguration(LanguageVersionSettingsImpl.DEFAULT) override fun getAnnotationsOnBinaryModule(moduleName: String): List = @@ -93,8 +94,7 @@ public class KotlinPackagePartProvider(private val environment: KotlinCommonEnvi val relevantRoots = notLoadedRoots.filter { //filter all roots by package path existing - pathParts.fold(it) { - parent, part -> + pathParts.fold(it) { parent, part -> if (part.isEmpty()) parent else parent.findChild(part) ?: return@filter false } @@ -115,10 +115,12 @@ public class KotlinPackagePartProvider(private val environment: KotlinCommonEnvi ) { KotlinLogger.logWarning("Incompatible version for '$moduleFile': $it") } - } - catch (e: EOFException) { + } catch (e: EOFException) { throw RuntimeException("Error on reading package parts for '$packageFqName' package in '$moduleFile', " + - "roots: $notLoadedRoots", e) + "roots: $notLoadedRoots", e) + } catch (e: FileNotFoundException) { + notLoadedRoots.add(root) + continue } loadedModules.add(ModuleMappingInfo(root, mapping, moduleFile.nameWithoutExtension)) } diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinResolutionFacade.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinResolutionFacade.kt index 3515a60a8..2d811cad1 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinResolutionFacade.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinResolutionFacade.kt @@ -20,19 +20,22 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import org.eclipse.core.resources.IFile import org.jetbrains.kotlin.analyzer.AnalysisResult +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.analyzer.ResolverForProject import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.core.model.getEnvironment import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.diagnostics.DiagnosticSink +import org.jetbrains.kotlin.idea.FrontendInternals import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.analyzer.ModuleInfo -import org.jetbrains.kotlin.analyzer.ResolverForProject +@OptIn(FrontendInternals::class) public class KotlinResolutionFacade( val eclipseFile: IFile, val componentProvider: ComponentProvider, @@ -54,8 +57,10 @@ public class KotlinResolutionFacade( override fun analyze(elements: Collection, bodyResolveMode: BodyResolveMode): BindingContext { throw UnsupportedOperationException() } - - override fun analyzeWithAllCompilerChecks(elements: Collection): AnalysisResult { + + override fun analyzeWithAllCompilerChecks( + elements: Collection, callback: DiagnosticSink.DiagnosticsCallback? + ): AnalysisResult { throw UnsupportedOperationException() } diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/injection.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/injection.kt index f8d106eda..cffe1a792 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/injection.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/injection.kt @@ -23,7 +23,6 @@ import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsPackageFragmentProvider import org.jetbrains.kotlin.config.JvmAnalysisFlags import org.jetbrains.kotlin.config.JvmTarget -import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.container.StorageComponentContainer @@ -35,9 +34,11 @@ import org.jetbrains.kotlin.core.resolve.lang.java.resolver.EclipseJavaSourceEle import org.jetbrains.kotlin.core.resolve.lang.java.resolver.EclipseTraceBasedJavaResolverCache import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaPropertyInitializerEvaluator import org.jetbrains.kotlin.frontend.di.configureModule +import org.jetbrains.kotlin.incremental.InlineConstTrackerImpl import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.load.java.InternalFlexibleTypeTransformer import org.jetbrains.kotlin.load.java.JavaClassesTracker +import org.jetbrains.kotlin.load.java.JavaModuleAnnotationsProvider import org.jetbrains.kotlin.load.java.components.SignaturePropagatorImpl import org.jetbrains.kotlin.load.java.components.TraceBasedErrorReporter import org.jetbrains.kotlin.load.java.lazy.JavaResolverSettings @@ -48,8 +49,8 @@ import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver +import org.jetbrains.kotlin.resolve.jvm.SyntheticJavaPartsProvider import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices -import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory @@ -77,23 +78,25 @@ fun StorageComponentContainer.configureJavaTopDownAnalysis( } fun createContainerForLazyResolveWithJava( - moduleContext: ModuleContext, - bindingTrace: BindingTrace, - declarationProviderFactory: DeclarationProviderFactory, - moduleContentScope: GlobalSearchScope, - moduleClassResolver: ModuleClassResolver, - targetEnvironment: TargetEnvironment, - lookupTracker: LookupTracker, - packagePartProvider: PackagePartProvider, - jvmTarget: JvmTarget, - languageVersionSettings: LanguageVersionSettings, - javaProject: IJavaProject?, - useBuiltInsProvider: Boolean + moduleContext: ModuleContext, + bindingTrace: BindingTrace, + declarationProviderFactory: DeclarationProviderFactory, + moduleContentScope: GlobalSearchScope, + moduleClassResolver: ModuleClassResolver, + targetEnvironment: TargetEnvironment, + lookupTracker: LookupTracker, + packagePartProvider: PackagePartProvider, + jvmTarget: JvmTarget, + languageVersionSettings: LanguageVersionSettings, + javaProject: IJavaProject?, + useBuiltInsProvider: Boolean, + javaModuleAnnotationsProvider: JavaModuleAnnotationsProvider, + analyzerService: PlatformDependentAnalyzerServices? ): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatformAnalyzerServices) { configureModule( moduleContext, JvmPlatforms.jvmPlatformByTargetVersion(jvmTarget), - JvmPlatformAnalyzerServices, + analyzerService ?: JvmPlatformAnalyzerServices, bindingTrace, languageVersionSettings ) @@ -102,16 +105,21 @@ fun createContainerForLazyResolveWithJava( useImpl() useImpl() useImpl() + useImpl() + useInstance(SyntheticJavaPartsProvider.EMPTY) useInstance(packagePartProvider) useInstance(moduleClassResolver) + useInstance(javaModuleAnnotationsProvider) useInstance(declarationProviderFactory) javaProject?.let { useInstance(it) } - useInstance(languageVersionSettings.getFlag(JvmAnalysisFlags.jsr305)) + //TODO??? + useInstance(languageVersionSettings.getFlag(JvmAnalysisFlags.javaTypeEnhancementState)) if (useBuiltInsProvider) { - useInstance((moduleContext.module.builtIns as JvmBuiltIns).settings) + //TODO??? + useInstance((moduleContext.module.builtIns as JvmBuiltIns).customizer) useImpl() } @@ -119,10 +127,16 @@ fun createContainerForLazyResolveWithJava( targetEnvironment.configure(this) - useInstance(JavaResolverSettings.create( - isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))) + useInstance( + JavaResolverSettings.create( + //isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines), + correctNullabilityForNotNullTypeParameter = false, + typeEnhancementImprovementsInStrictMode = false, + ignoreNullabilityForErasedValueParameters = false + ) + ) }.apply { - get().initialize(bindingTrace, get()) + get().initialize(bindingTrace, get(),languageVersionSettings, jvmTarget) } fun createContainerForTopDownAnalyzerForJvm( @@ -135,11 +149,13 @@ fun createContainerForTopDownAnalyzerForJvm( jvmTarget: JvmTarget, languageVersionSettings: LanguageVersionSettings, moduleClassResolver: ModuleClassResolver, - javaProject: IJavaProject? + javaProject: IJavaProject?, + javaModuleAnnotationsProvider: JavaModuleAnnotationsProvider, + analyzerService: PlatformDependentAnalyzerServices? ): ComponentProvider = createContainerForLazyResolveWithJava( moduleContext, bindingTrace, declarationProviderFactory, moduleContentScope, moduleClassResolver, CompilerEnvironment, lookupTracker, packagePartProvider, jvmTarget, languageVersionSettings, javaProject, - useBuiltInsProvider = true + useBuiltInsProvider = true, javaModuleAnnotationsProvider, analyzerService ) // Copy functions from Dsl.kt as they were shrinked by proguard diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/EclipseJavaClassFinder.java b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/EclipseJavaClassFinder.java index a20fa4238..f348e0a13 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/EclipseJavaClassFinder.java +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/EclipseJavaClassFinder.java @@ -24,6 +24,8 @@ import org.eclipse.jdt.internal.core.NameLookup; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.config.JvmTarget; +import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.core.log.KotlinLogger; import org.jetbrains.kotlin.core.model.KotlinEnvironment; import org.jetbrains.kotlin.core.model.KotlinJavaManager; @@ -36,6 +38,7 @@ import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer; +import org.jetbrains.kotlin.resolve.jvm.JvmCodeAnalyzerInitializer; import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer; import java.util.Arrays; @@ -48,20 +51,23 @@ public class EclipseJavaClassFinder extends AbstractJavaClassFinder { public EclipseJavaClassFinder(@NotNull IJavaProject project) { javaProject = project; } - + @Override - public void initialize(@NotNull BindingTrace trace, @NotNull KotlinCodeAnalyzer codeAnalyzer) { + public void initialize(@NotNull BindingTrace trace, @NotNull KotlinCodeAnalyzer codeAnalyzer, @NotNull LanguageVersionSettings languageVersionSettings, @NotNull JvmTarget jvmTarget) { if (javaProject == null) { return; } - + MockProject ideaProject = KotlinEnvironment.Companion.getEnvironment(javaProject.getProject()).getProject(); - CodeAnalyzerInitializer.Companion.getInstance(ideaProject).initialize(trace, codeAnalyzer.getModuleDescriptor(), codeAnalyzer); + JvmCodeAnalyzerInitializer tempInitializer = (JvmCodeAnalyzerInitializer) CodeAnalyzerInitializer.Companion.getInstance(ideaProject); + //trace, codeAnalyzer.getModuleDescriptor(), codeAnalyzer, languageVersionSettings + tempInitializer.initialize(trace, codeAnalyzer.getModuleDescriptor(), codeAnalyzer, languageVersionSettings, jvmTarget); + //trace, codeAnalyzer.getModuleDescriptor(), codeAnalyzer } - @Override @Nullable - public JavaPackage findPackage(@NotNull FqName fqName) { + @Override + public JavaPackage findPackage(@NotNull FqName fqName, boolean b) { IPackageFragment[] packageFragments = findPackageFragments(javaProject, fqName.asString(), false, false); if (packageFragments != null && packageFragments.length > 0) { return new EclipseJavaPackage(Arrays.asList(packageFragments)); diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/resolver/EclipseTraceBasedJavaResolverCache.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/resolver/EclipseTraceBasedJavaResolverCache.kt index 8907ac588..31dc6be8d 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/resolver/EclipseTraceBasedJavaResolverCache.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/resolver/EclipseTraceBasedJavaResolverCache.kt @@ -21,10 +21,7 @@ import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.load.java.components.JavaResolverCache -import org.jetbrains.kotlin.load.java.structure.JavaClass -import org.jetbrains.kotlin.load.java.structure.JavaElement -import org.jetbrains.kotlin.load.java.structure.JavaField -import org.jetbrains.kotlin.load.java.structure.JavaMethod +import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.tail import org.jetbrains.kotlin.resolve.BindingContext @@ -33,25 +30,13 @@ import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils import javax.inject.Inject -class EclipseTraceBasedJavaResolverCache : JavaResolverCache { - private lateinit var trace: BindingTrace - private lateinit var resolveSession: ResolveSession - - @Inject - fun setTrace(trace: BindingTrace) { - this.trace = trace - } - - @Inject - fun setResolveSession(resolveSession: ResolveSession) { - this.resolveSession = resolveSession - } - +class EclipseTraceBasedJavaResolverCache(@Inject val trace: BindingTrace, @Inject val resolveSession: ResolveSession) : JavaResolverCache { + override fun getClassResolvedFromSource(fqName: FqName): ClassDescriptor? { return trace[BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, fqName.toUnsafe()] ?: findInPackageFragments(fqName) } - override fun recordMethod(method: JavaMethod, descriptor: SimpleFunctionDescriptor) { + override fun recordMethod(p0: JavaMember, p1: SimpleFunctionDescriptor) { } override fun recordConstructor(element: JavaElement, descriptor: ConstructorDescriptor) { diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaArrayType.java b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaArrayType.java deleted file mode 100644 index ac4ba406b..000000000 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaArrayType.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - *******************************************************************************/ -package org.jetbrains.kotlin.core.resolve.lang.java.structure; - -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.load.java.structure.JavaArrayType; -import org.jetbrains.kotlin.load.java.structure.JavaType; - -public class EclipseJavaArrayType extends EclipseJavaType implements JavaArrayType { - - public EclipseJavaArrayType(@NotNull ITypeBinding typeBinding) { - super(typeBinding); - } - - @Override - @NotNull - public JavaType getComponentType() { - return EclipseJavaType.create(getBinding().getComponentType()); - } - -} diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaArrayType.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaArrayType.kt new file mode 100644 index 000000000..c07b84343 --- /dev/null +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaArrayType.kt @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.jetbrains.kotlin.core.resolve.lang.java.structure + +import org.eclipse.jdt.core.dom.ITypeBinding +import org.jetbrains.kotlin.load.java.structure.JavaArrayType +import org.jetbrains.kotlin.load.java.structure.JavaType + +class EclipseJavaArrayType(typeBinding: ITypeBinding) : EclipseJavaType(typeBinding), JavaArrayType { + + override val componentType: JavaType get() = create(binding.componentType) +} diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaClass.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaClass.kt index 3ff857eb1..210303581 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaClass.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaClass.kt @@ -20,14 +20,7 @@ import org.eclipse.jdt.core.dom.ITypeBinding import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementFactory.classifierTypes import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementFactory.typeParameters import org.jetbrains.kotlin.descriptors.Visibility -import org.jetbrains.kotlin.load.java.structure.JavaAnnotation -import org.jetbrains.kotlin.load.java.structure.JavaClass -import org.jetbrains.kotlin.load.java.structure.JavaClassifierType -import org.jetbrains.kotlin.load.java.structure.JavaConstructor -import org.jetbrains.kotlin.load.java.structure.JavaField -import org.jetbrains.kotlin.load.java.structure.JavaMethod -import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter -import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind +import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames @@ -35,58 +28,66 @@ import java.lang.reflect.Modifier public class EclipseJavaClass(javaElement: ITypeBinding) : EclipseJavaClassifier(javaElement), JavaClass { override val name: Name = SpecialNames.safeIdentifier(binding.getName()) - + override val isAbstract: Boolean = Modifier.isAbstract(binding.getModifiers()) - + override val isStatic: Boolean = Modifier.isStatic(binding.getModifiers()) - + override val isFinal: Boolean = Modifier.isFinal(binding.getModifiers()) - + override val visibility: Visibility = EclipseJavaElementUtil.getVisibility(binding) - + override val typeParameters: List get() = typeParameters(binding.getTypeParameters()) - + override val innerClassNames: Collection get() = binding.declaredTypes.mapNotNull { it.name?.takeIf(Name::isValidIdentifier)?.let(Name::identifier) } - + override fun findInnerClass(name: Name): JavaClass? { return binding.declaredTypes.find { it.name == name.asString() }?.let(::EclipseJavaClass) } - + override val fqName: FqName? = binding.getQualifiedName()?.let { FqName(it) } - + override val isInterface: Boolean = binding.isInterface() - + override val isRecord: Boolean + get() = false //TODO + override val isSealed: Boolean + get() = false //TODO + override val isAnnotationType: Boolean = binding.isAnnotation() - + override val isEnum: Boolean = binding.isEnum() - - override val outerClass: JavaClass? + + override val outerClass: JavaClass? get() = binding.getDeclaringClass()?.let { EclipseJavaClass(it) } - - override val supertypes: Collection + override val permittedTypes: Collection + get() = emptyList() //TODO + override val recordComponents: Collection + get() = emptyList() // TODO + + override val supertypes: Collection get() = classifierTypes(EclipseJavaElementUtil.getSuperTypesWithObject(binding)) - - override val methods: Collection + + override val methods: Collection get() = binding.declaredMethods.filterNot { it.isConstructor() }.map(::EclipseJavaMethod) - + override val fields: Collection get() = binding.getDeclaredFields() - .filter { + .filter { val name = it.getName() name != null && Name.isValidIdentifier(name) } .map { EclipseJavaField(it) } - - override val constructors: Collection + + override val constructors: Collection get() = binding.declaredMethods.filter { it.isConstructor() }.map(::EclipseJavaConstructor) - + override val isDeprecatedInJavaDoc: Boolean = binding.isDeprecated - - override val annotations: Collection + + override val annotations: Collection get() = binding.annotations.map(::EclipseJavaAnnotation) - + override val lightClassOriginKind: LightClassOriginKind? get() = binding.javaElement.let { if (EclipseJavaElementUtil.isKotlinLightClass(it)) diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaElementUtil.java b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaElementUtil.java index 4ef0591c2..bd81ee450 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaElementUtil.java +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaElementUtil.java @@ -36,7 +36,7 @@ import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; -import org.eclipse.jdt.internal.core.AnnotationInfo; +import org.eclipse.jdt.internal.core.BinaryMethod; import org.eclipse.jdt.internal.core.BinaryType; import org.eclipse.jdt.internal.core.ClassFile; import org.jetbrains.annotations.NotNull; @@ -47,7 +47,7 @@ import org.jetbrains.kotlin.core.utils.ProjectUtils; import org.jetbrains.kotlin.descriptors.Visibilities; import org.jetbrains.kotlin.descriptors.Visibility; -import org.jetbrains.kotlin.load.java.JavaVisibilities; +import org.jetbrains.kotlin.descriptors.java.JavaVisibilities; import org.jetbrains.kotlin.load.java.structure.JavaAnnotation; import org.jetbrains.kotlin.load.java.structure.JavaValueParameter; import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache; @@ -70,14 +70,14 @@ public class EclipseJavaElementUtil { static Visibility getVisibility(@NotNull IBinding member) { int flags = member.getModifiers(); if (Modifier.isPublic(flags)) { - return Visibilities.PUBLIC; + return Visibilities.Public.INSTANCE; } else if (Modifier.isPrivate(flags)) { - return Visibilities.PRIVATE; + return Visibilities.Private.INSTANCE; } else if (Modifier.isProtected(flags)) { - return Flags.isStatic(flags) ? JavaVisibilities.PROTECTED_STATIC_VISIBILITY : JavaVisibilities.PROTECTED_AND_PACKAGE; + return Flags.isStatic(flags) ? JavaVisibilities.ProtectedAndPackage.INSTANCE : JavaVisibilities.ProtectedAndPackage.INSTANCE; } - return JavaVisibilities.PACKAGE_VISIBILITY; + return JavaVisibilities.PackageVisibility.INSTANCE; } private static List getSuperTypes(@NotNull ITypeBinding typeBinding) { @@ -209,6 +209,20 @@ public static boolean isFromKotlinBinFolder(@NotNull IResource resource) { return false; } + public static boolean isFromKotlinBinFolder(@NotNull IJavaElement element) { + IClassFile classFile; + if (element instanceof IClassFile) { + classFile = (IClassFile) element; + } else if (element instanceof BinaryType) { + classFile = ((BinaryType) element).getClassFile(); + } else if(element instanceof BinaryMethod) { + classFile = ((BinaryMethod) element).getClassFile(); + } else { + return false; + } + return classFile.getResource() == null || isFromKotlinBinFolder(classFile.getResource()); + } + public static boolean isKotlinBinaryElement(@NotNull IJavaElement element) { IClassFile classFile; if (element instanceof IClassFile) { diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseOptimizedJavaClass.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseOptimizedJavaClass.kt index 29b211812..28eef9edb 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseOptimizedJavaClass.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseOptimizedJavaClass.kt @@ -1,19 +1,12 @@ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.IType -import org.jetbrains.kotlin.load.java.structure.JavaAnnotation -import org.jetbrains.kotlin.load.java.structure.JavaClass -import org.jetbrains.kotlin.load.java.structure.JavaClassifierType -import org.jetbrains.kotlin.load.java.structure.JavaConstructor -import org.jetbrains.kotlin.load.java.structure.JavaField -import org.jetbrains.kotlin.load.java.structure.JavaMethod -import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter -import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.core.resolve.lang.java.EclipseJavaClassFinder +import org.jetbrains.kotlin.load.java.structure.* class EclipseOptimizedJavaClass(val eclipseClass: IType) : JavaClass { override val name: Name @@ -43,7 +36,13 @@ class EclipseOptimizedJavaClass(val eclipseClass: IType) : JavaClass { override val isInterface: Boolean get() = throw UnsupportedOperationException() - + + override val isRecord: Boolean + get() = throw UnsupportedOperationException() + + override val isSealed: Boolean + get() = throw UnsupportedOperationException() + override val lightClassOriginKind: LightClassOriginKind? get() = if (EclipseJavaElementUtil.isKotlinLightClass(eclipseClass)) LightClassOriginKind.SOURCE else null @@ -52,7 +51,13 @@ class EclipseOptimizedJavaClass(val eclipseClass: IType) : JavaClass { override val outerClass: JavaClass? get() = throw UnsupportedOperationException() - + + override val permittedTypes: Collection + get() = throw UnsupportedOperationException() + + override val recordComponents: Collection + get() = throw UnsupportedOperationException() + override val supertypes: Collection get() = throw UnsupportedOperationException() diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/kotlin/EclipseVirtualFileFinder.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/kotlin/EclipseVirtualFileFinder.kt index 7f3f64196..01eeea2ae 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/kotlin/EclipseVirtualFileFinder.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/kotlin/EclipseVirtualFileFinder.kt @@ -53,6 +53,8 @@ class EclipseVirtualFileFinder( classId.shortClassName.asString() + MetadataPackageFragment.DOT_METADATA_FILE_EXTENSION)?.inputStream } + override fun findSourceOrBinaryVirtualFile(classId: ClassId): VirtualFile? = findVirtualFileWithHeader(classId) + override fun hasMetadataPackage(fqName: FqName): Boolean { var found = false @@ -136,7 +138,7 @@ class EclipseVirtualFileFinder( class EclipseVirtualFileFinderFactory(private val project: IJavaProject) : VirtualFileFinderFactory { override fun create(_project: Project, module: ModuleDescriptor) = - VirtualFileFinderFactory.getInstance(_project).create(_project, module) + EclipseVirtualFileFinder(project, GlobalSearchScope.allScope(_project)) override fun create(scope: GlobalSearchScope): VirtualFileFinder = EclipseVirtualFileFinder(project, scope) } diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/ScriptTemplateContribution.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/ScriptTemplateContribution.kt index df1cb37d6..14531dbdf 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/ScriptTemplateContribution.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/ScriptTemplateContribution.kt @@ -1,14 +1,28 @@ package org.jetbrains.kotlin.core.script +import org.eclipse.jdt.core.IClasspathEntry +import org.jetbrains.kotlin.core.model.KotlinScriptEnvironment import java.io.File import kotlin.reflect.KClass +import kotlin.script.experimental.api.ScriptCompilationConfiguration abstract class ScriptTemplateContribution { open val priority = 0 protected abstract fun loadTemplate(): KClass<*> + open fun createClasspath(environment: KotlinScriptEnvironment): Array = environment.javaProject.rawClasspath + val template by lazy { loadTemplate() } + open fun isNullable(propName: String, compilationConfig: ScriptCompilationConfiguration): Boolean = true + open fun scriptEnvironment(script: File): Map = emptyMap() +} + +abstract class JavaScriptTemplateContribution : ScriptTemplateContribution() { + + abstract val javaClass: Class<*> + + override fun loadTemplate(): KClass<*> = javaClass.kotlin } \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/template/ProjectScriptTemplateContribution.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/template/ProjectScriptTemplateContribution.kt index 73130a849..ccf9ee850 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/template/ProjectScriptTemplateContribution.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/template/ProjectScriptTemplateContribution.kt @@ -17,15 +17,18 @@ package org.jetbrains.kotlin.core.script.template import org.eclipse.core.resources.IFile +import org.eclipse.core.runtime.Path +import org.eclipse.jdt.core.IClasspathEntry +import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.core.model.KotlinScriptEnvironment import org.jetbrains.kotlin.core.script.ScriptTemplateContribution -import org.jetbrains.kotlin.core.utils.ProjectUtils -import org.jetbrains.kotlin.core.utils.asResource -import org.jetbrains.kotlin.core.utils.isInClasspath -import org.jetbrains.kotlin.core.utils.javaProject +import org.jetbrains.kotlin.core.utils.* import java.io.File class ProjectScriptTemplateContribution : ScriptTemplateContribution() { + + override val priority: Int get() = Int.MAX_VALUE + override fun loadTemplate() = ProjectScriptTemplate::class override fun scriptEnvironment(script: File): Map { @@ -46,8 +49,17 @@ class ProjectScriptTemplateContribution : ScriptTemplateContribution() { val javaProject = file.javaProject ?: return emptyList() if (!file.isInClasspath) return emptyList() - val projectClasspath = ProjectUtils.collectClasspathWithDependenciesForLaunch(javaProject, false) + val projectClasspath = try { + ProjectUtils.collectClasspathWithDependenciesForLaunch(javaProject, false) + } catch (e: DependencyResolverException) { + e.resolvedFiles + } val outputFolders = ProjectUtils.getAllOutputFolders(javaProject).map { it.location.toFile() } return projectClasspath + outputFolders } + + override fun createClasspath(environment: KotlinScriptEnvironment): Array = + (environment.javaProject.rawClasspath + environment.definitionClasspath.map { + JavaCore.newLibraryEntry(Path(it.absolutePath), null, null) + }).distinctBy { it.path }.toTypedArray() } \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/DebugUtils.java b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/DebugUtils.java index 57622157b..ea45b74da 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/DebugUtils.java +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/DebugUtils.java @@ -1,5 +1,7 @@ package org.jetbrains.kotlin.core.utils; +import java.util.Optional; + import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IVariable; @@ -19,7 +21,7 @@ public static Boolean isVisible(IVariable variable) { public static Boolean hasKotlinSource(IStackFrame frame) throws DebugException { if (frame instanceof IJavaStackFrame) { IJavaStackFrame javaFrame = (IJavaStackFrame) frame; - return javaFrame.getSourceName().endsWith(".kt"); + return Optional.ofNullable(javaFrame.getSourceName()).map(s -> s.endsWith(".kt")).orElse(false); } else { return false; } diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/DependencyResolverException.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/DependencyResolverException.kt new file mode 100644 index 000000000..23fa559fe --- /dev/null +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/DependencyResolverException.kt @@ -0,0 +1,5 @@ +package org.jetbrains.kotlin.core.utils + +import java.io.File + +class DependencyResolverException(val resolvedFiles: List) : RuntimeException() \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/ProjectUtils.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/ProjectUtils.kt index 89bb4a7b2..0da697d66 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/ProjectUtils.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/ProjectUtils.kt @@ -18,7 +18,10 @@ package org.jetbrains.kotlin.core.utils import org.eclipse.core.resources.* import org.eclipse.core.runtime.* -import org.eclipse.jdt.core.* +import org.eclipse.jdt.core.IClasspathEntry +import org.eclipse.jdt.core.IJavaProject +import org.eclipse.jdt.core.JavaCore +import org.eclipse.jdt.core.JavaModelException import org.eclipse.jdt.launching.JavaRuntime import org.jetbrains.kotlin.core.KotlinClasspathContainer import org.jetbrains.kotlin.core.builder.KotlinPsiManager @@ -26,7 +29,6 @@ import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.core.model.KotlinNature import org.jetbrains.kotlin.psi.KtFile import java.io.File -import java.util.* object ProjectUtils { @@ -82,31 +84,45 @@ object ProjectUtils { @JvmStatic fun getAllOutputFolders(javaProject: IJavaProject): List = - javaProject.getResolvedClasspath(true) - .asSequence() - .filter { it.entryKind == IClasspathEntry.CPE_SOURCE } - .map { it.outputLocation } - .let { it + javaProject.outputLocation } - .filterNotNull() - .distinct() - .mapNotNull { ResourcesPlugin.getWorkspace().root.findMember(it) as? IFolder } - .filter { it.exists() } - .toList() - - fun getSourceFiles(project: IProject): List = - KotlinPsiManager.getFilesByProject(project) + javaProject.getResolvedClasspath(true) + .asSequence() + .filter { it.entryKind == IClasspathEntry.CPE_SOURCE } + .map { it.outputLocation } + .let { it + javaProject.outputLocation } + .filterNotNull() + .distinct() + .mapNotNull { ResourcesPlugin.getWorkspace().root.findMember(it) as? IFolder } + .filter { it.exists() } + .toList() + + fun getSourceFiles(project: IProject): List { + var tempFiles = KotlinPsiManager.getFilesByProject(project) + if (tempFiles.any { !it.asFile.exists() }) { + project.refreshLocal(IResource.DEPTH_INFINITE, NullProgressMonitor()) + } + tempFiles = KotlinPsiManager.getFilesByProject(project) + return tempFiles .map { KotlinPsiManager.getParsedFile(it) } + } fun getSourceFilesWithDependencies(javaProject: IJavaProject): List = - (getDependencyProjects(javaProject) + javaProject.project) + (listOf(javaProject).getDependencyProjects() + javaProject.project) .flatMap { getSourceFiles(it) } - fun getDependencyProjects(javaProject: IJavaProject): List = - javaProject.getResolvedClasspath(true) - .filter { it.entryKind == IClasspathEntry.CPE_PROJECT } - .map { ResourcesPlugin.getWorkspace().root.getProject(it.path.toPortableString()) } - .filter { it.isAccessible } - .flatMap { listOf(it) + getDependencyProjects(JavaCore.create(it)) } + fun getDependencyProjects(javaProject: IJavaProject) = listOf(javaProject).getDependencyProjects() + + tailrec fun Collection.getDependencyProjects(result: MutableSet = hashSetOf()): Set { + if (isEmpty()) return result + return flatMap { it.getResolvedClasspath(true).toList() } + .asSequence() + .filter { it.entryKind == IClasspathEntry.CPE_PROJECT } + .map { ResourcesPlugin.getWorkspace().root.getProject(it.path.toPortableString()) } + .filter { it.isAccessible } + .filter { result.add(it) } + .map { JavaCore.create(it) } + .toList() + .getDependencyProjects(result) + } fun collectClasspathWithDependenciesForBuild(javaProject: IJavaProject): List { return expandClasspath(javaProject, true, false) { true } @@ -115,23 +131,36 @@ object ProjectUtils { @JvmStatic fun collectClasspathWithDependenciesForLaunch(javaProject: IJavaProject, includeJRE: Boolean): List { val jreEntries = getJREClasspathElements(javaProject) - return expandClasspath(javaProject, true, true) { - entry -> entry.entryKind == IClasspathEntry.CPE_LIBRARY && (includeJRE || jreEntries.none { it.path == entry.path }) + return expandClasspath(javaProject, true, true) { entry -> + entry.entryKind == IClasspathEntry.CPE_LIBRARY && (includeJRE || jreEntries.none { it.path == entry.path }) } } private fun getJREClasspathElements(javaProject: IJavaProject): List = - JavaRuntime.resolveRuntimeClasspathEntry(JavaRuntime.computeJREEntry(javaProject), javaProject).map { it.classpathEntry } + JavaRuntime.resolveRuntimeClasspathEntry(JavaRuntime.computeJREEntry(javaProject), javaProject) + .map { it.classpathEntry } private fun expandClasspath( javaProject: IJavaProject, includeDependencies: Boolean, includeBinFolders: Boolean, entryPredicate: Function1 ): List { val orderedFiles = LinkedHashSet() + var wasError = false for (classpathEntry in javaProject.getResolvedClasspath(true)) { if (classpathEntry.entryKind == IClasspathEntry.CPE_PROJECT && includeDependencies) { - orderedFiles.addAll(expandDependentProjectClasspath(classpathEntry, includeBinFolders, entryPredicate)) + try { + orderedFiles.addAll( + expandDependentProjectClasspath( + classpathEntry, + includeBinFolders, + entryPredicate + ) + ) + } catch (e: DependencyResolverException) { + wasError = true + orderedFiles.addAll(e.resolvedFiles) + } } else { // Source folder or library if (entryPredicate.invoke(classpathEntry)) { orderedFiles.addAll(getFileByEntry(classpathEntry, javaProject)) @@ -139,6 +168,10 @@ object ProjectUtils { } } + if(wasError) { + throw DependencyResolverException(orderedFiles.toList()) + } + return orderedFiles.toList() } @@ -151,7 +184,6 @@ object ProjectUtils { ?.let { listOf(it) } ?: emptyList() - private fun expandDependentProjectClasspath( projectEntry: IClasspathEntry, includeBinFolders: Boolean, entryPredicate: Function1 @@ -161,36 +193,51 @@ object ProjectUtils { val javaProject = JavaCore.create(dependentProject) val orderedFiles = LinkedHashSet() + var wasError = false - for (classpathEntry in javaProject.getResolvedClasspath(true)) { - if (!(classpathEntry.isExported || classpathEntry.entryKind == IClasspathEntry.CPE_SOURCE)) { - continue - } + try { + for (classpathEntry in javaProject.getResolvedClasspath(true)) { + if (!(classpathEntry.isExported || classpathEntry.entryKind == IClasspathEntry.CPE_SOURCE)) { + continue + } - if (classpathEntry.entryKind == IClasspathEntry.CPE_PROJECT) { - orderedFiles.addAll(expandDependentProjectClasspath(classpathEntry, includeBinFolders, entryPredicate)) - } else { - if (entryPredicate.invoke(classpathEntry)) { - orderedFiles.addAll(getFileByEntry(classpathEntry, javaProject)) + if (classpathEntry.entryKind == IClasspathEntry.CPE_PROJECT) { + try { + orderedFiles.addAll( + expandDependentProjectClasspath( + classpathEntry, + includeBinFolders, + entryPredicate + ) + ) + } catch (e: DependencyResolverException) { + wasError = true + orderedFiles.addAll(e.resolvedFiles) + } + } else { + if (entryPredicate.invoke(classpathEntry)) { + orderedFiles.addAll(getFileByEntry(classpathEntry, javaProject)) + } } } + + + if (includeBinFolders) { + getAllOutputFolders(javaProject) + .map { it.location.toFile() } + .toCollection(orderedFiles) + } + } catch (e: JavaModelException) { + throw DependencyResolverException(emptyList()) } - if (includeBinFolders) { - getAllOutputFolders(javaProject) - .map { it.location.toFile() } - .toCollection(orderedFiles) + if(wasError) { + throw DependencyResolverException(orderedFiles.toList()) } return orderedFiles.toList() } - @JvmStatic - fun getSrcDirectories(javaProject: IJavaProject): List = - expandClasspath(javaProject, false, false) { entry -> - entry.entryKind == IClasspathEntry.CPE_SOURCE - } - @JvmStatic fun getSrcOutDirectories(javaProject: IJavaProject): List> { val projectOutput = javaProject.outputLocation @@ -276,7 +323,6 @@ object ProjectUtils { fun isGradleProject(project: IProject): Boolean = project.hasNature(GRADLE_NATURE_ID) - @JvmStatic fun buildLibPath(libName: String): String = ktHome + buildLibName(libName) diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/analyzeUtils.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/analyzeUtils.kt new file mode 100644 index 000000000..6cd507b62 --- /dev/null +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/analyzeUtils.kt @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *******************************************************************************/ + +package org.jetbrains.kotlin.core.utils + +import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.resolve.BindingContext + +fun KtElement.getBindingContext(): BindingContext = + containingKtFile.getBindingContext() + +fun KtFile.getBindingContext(): BindingContext = + KotlinAnalyzer.analyzeFile(this).analysisResult.bindingContext + +fun getModuleDescriptor(ktFile: KtFile): ModuleDescriptor = + KotlinAnalyzer.analyzeFile(ktFile).analysisResult.moduleDescriptor \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/importsUtils.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/importsUtils.kt index 4bed5b9d2..4f45b87b5 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/importsUtils.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/importsUtils.kt @@ -16,28 +16,42 @@ *******************************************************************************/ package org.jetbrains.kotlin.core.utils +import com.intellij.psi.PsiClass import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature.DefaultImportOfPackageKotlinComparisons import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.idea.util.ActionRunningMode import org.jetbrains.kotlin.idea.util.ImportDescriptorResult import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.ImportPath -import java.util.Comparator import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices -import org.jetbrains.kotlin.idea.util.ActionRunningMode class KotlinImportInserterHelper : ImportInsertHelper() { - override val importSortComparator: Comparator = object : Comparator { - override fun compare(o1: ImportPath?, o2: ImportPath?): Int { - return 0 - } + private val importSortComparator: Comparator = Comparator { _, _ -> 0 } + + override fun getImportSortComparator(contextFile: KtFile): Comparator { + return importSortComparator + } + + override fun importDescriptor( + element: KtElement, + descriptor: DeclarationDescriptor, + actionRunningMode: ActionRunningMode, + forceAllUnderImport: Boolean + ): ImportDescriptorResult { + throw UnsupportedOperationException() } - override fun importDescriptor(file: KtFile, descriptor: DeclarationDescriptor, actionRunningMode: ActionRunningMode, forceAllUnderImport: Boolean): ImportDescriptorResult { + override fun importPsiClass( + element: KtElement, + psiClass: PsiClass, + actionRunningMode: ActionRunningMode + ): ImportDescriptorResult { throw UnsupportedOperationException() } @@ -50,7 +64,7 @@ class KotlinImportInserterHelper : ImportInsertHelper() { return importPath.isImported(defaultImports) } - override fun mayImportOnShortenReferences(descriptor: DeclarationDescriptor): Boolean { + override fun mayImportOnShortenReferences(descriptor: DeclarationDescriptor, contextFile: KtFile): Boolean { return false } diff --git a/kotlin-eclipse-feature/.project b/kotlin-eclipse-feature/.project deleted file mode 100644 index 6201f504c..000000000 --- a/kotlin-eclipse-feature/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - kotlin-eclipse-feature - - - - - - org.eclipse.pde.FeatureBuilder - - - - - - org.eclipse.pde.FeatureNature - - diff --git a/kotlin-eclipse-feature/feature.xml b/kotlin-eclipse-feature/feature.xml index fd6f4135c..63f27b3ff 100644 --- a/kotlin-eclipse-feature/feature.xml +++ b/kotlin-eclipse-feature/feature.xml @@ -2,11 +2,11 @@ - Kotlin language support for Kotlin 1.4.0 + Kotlin language support for Kotlin 1.6.21 diff --git a/kotlin-eclipse-feature/pom.xml b/kotlin-eclipse-feature/pom.xml index 0127ecd22..cd78113a4 100644 --- a/kotlin-eclipse-feature/pom.xml +++ b/kotlin-eclipse-feature/pom.xml @@ -8,12 +8,11 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.feature - kotlin.eclipse - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT eclipse-feature \ No newline at end of file diff --git a/kotlin-eclipse-gradle-feature/feature.xml b/kotlin-eclipse-gradle-feature/feature.xml index f028dd6f8..041d5dac7 100644 --- a/kotlin-eclipse-gradle-feature/feature.xml +++ b/kotlin-eclipse-gradle-feature/feature.xml @@ -2,7 +2,7 @@ @@ -29,18 +29,4 @@ See the License for the specific language governing permissions and limitations under the License. - - - - diff --git a/kotlin-eclipse-gradle-feature/pom.xml b/kotlin-eclipse-gradle-feature/pom.xml index 2bb80325a..63eb76f95 100644 --- a/kotlin-eclipse-gradle-feature/pom.xml +++ b/kotlin-eclipse-gradle-feature/pom.xml @@ -8,12 +8,11 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.gradle.feature - kotlin.eclipse - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT eclipse-feature \ No newline at end of file diff --git a/kotlin-eclipse-gradle-model/META-INF/MANIFEST.MF b/kotlin-eclipse-gradle-model/META-INF/MANIFEST.MF index a7c5ba35d..98831c14c 100644 --- a/kotlin-eclipse-gradle-model/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-gradle-model/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-gradle-model Bundle-SymbolicName: org.jetbrains.kotlin.gradle.model;singleton:=true -Bundle-Version: 0.8.21.qualifier +Bundle-Version: 1.6.21.qualifier Bundle-Vendor: JetBrains Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy diff --git a/kotlin-eclipse-gradle-model/build.gradle b/kotlin-eclipse-gradle-model/build.gradle index 63d204c7d..620db4b5d 100644 --- a/kotlin-eclipse-gradle-model/build.gradle +++ b/kotlin-eclipse-gradle-model/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'org.jetbrains.kotlin.jvm' version '1.3.40' + id 'org.jetbrains.kotlin.jvm' version '1.6.0' } group 'kotlin-eclipse-plugin' @@ -18,10 +18,10 @@ sourceSets { } compileKotlin { - kotlinOptions.jvmTarget = "1.8" + kotlinOptions.jvmTarget = "11" } compileTestKotlin { - kotlinOptions.jvmTarget = "1.8" + kotlinOptions.jvmTarget = "11" } jar { diff --git a/kotlin-eclipse-gradle-model/pom.xml b/kotlin-eclipse-gradle-model/pom.xml index 7173e6920..1c375a4bd 100644 --- a/kotlin-eclipse-gradle-model/pom.xml +++ b/kotlin-eclipse-gradle-model/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.gradle.model @@ -22,7 +22,9 @@ org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} - + + 11 + compile diff --git a/kotlin-eclipse-gradle/META-INF/MANIFEST.MF b/kotlin-eclipse-gradle/META-INF/MANIFEST.MF index 5a3f8fa89..2cebba273 100644 --- a/kotlin-eclipse-gradle/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-gradle/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-gradle Bundle-SymbolicName: org.jetbrains.kotlin.gradle;singleton:=true -Bundle-Version: 0.8.21.qualifier +Bundle-Version: 1.6.21.qualifier Bundle-Activator: org.jetbrains.kotlin.gradle.Activator Bundle-Vendor: JetBrains Require-Bundle: org.jetbrains.kotlin.core, diff --git a/kotlin-eclipse-gradle/pom.xml b/kotlin-eclipse-gradle/pom.xml index f674a2077..2ebb45f03 100644 --- a/kotlin-eclipse-gradle/pom.xml +++ b/kotlin-eclipse-gradle/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.gradle @@ -22,7 +22,9 @@ org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} - + + 11 + compile diff --git a/kotlin-eclipse-maven/.classpath b/kotlin-eclipse-maven/.classpath deleted file mode 100644 index f98be78ce..000000000 --- a/kotlin-eclipse-maven/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/kotlin-eclipse-maven/.project b/kotlin-eclipse-maven/.project deleted file mode 100644 index 6e00215c3..000000000 --- a/kotlin-eclipse-maven/.project +++ /dev/null @@ -1,41 +0,0 @@ - - - kotlin-eclipse-maven - - - - - - org.jetbrains.kotlin.ui.kotlinBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - org.jetbrains.kotlin.core.kotlinNature - - - - kotlin_bin - 2 - org.jetbrains.kotlin.core.filesystem:/kotlin-eclipse-maven/kotlin_bin - - - diff --git a/kotlin-eclipse-maven/.settings/org.eclipse.jdt.core.prefs b/kotlin-eclipse-maven/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 9a57a84d6..000000000 --- a/kotlin-eclipse-maven/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,297 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.kt -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 -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_annotation=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=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -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_method_declaration=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -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=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -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_lambda_body=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_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -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_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=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=80 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -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=true -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=false -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not 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_after_type_annotation=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_annotation_declaration=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_lambda_arrow=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_try=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=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=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=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_try=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=do not 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_lambda_arrow=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_try=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_parenthesized_expression_in_throw=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=do not 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_semicolon_in_try_resources=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=do not 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.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -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=120 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -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=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=false -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/kotlin-eclipse-maven/.settings/org.eclipse.jdt.ui.prefs b/kotlin-eclipse-maven/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index bddb247ef..000000000 --- a/kotlin-eclipse-maven/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,3 +0,0 @@ -eclipse.preferences.version=1 -formatter_profile=_Kotlin -formatter_settings_version=12 diff --git a/kotlin-eclipse-maven/META-INF/MANIFEST.MF b/kotlin-eclipse-maven/META-INF/MANIFEST.MF index f3e6fd039..71284a9ed 100644 --- a/kotlin-eclipse-maven/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-maven/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-maven Bundle-SymbolicName: org.jetbrains.kotlin.maven;singleton:=true -Bundle-Version: 0.8.21.qualifier +Bundle-Version: 1.6.21.qualifier Bundle-Activator: org.jetbrains.kotlin.maven.Activator Bundle-Vendor: JetBrains Require-Bundle: org.eclipse.core.runtime, diff --git a/kotlin-eclipse-maven/pom.xml b/kotlin-eclipse-maven/pom.xml index f70f24bdb..d10519d49 100644 --- a/kotlin-eclipse-maven/pom.xml +++ b/kotlin-eclipse-maven/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.maven @@ -22,7 +22,9 @@ org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} - + + 11 + compile diff --git a/kotlin-eclipse-p2updatesite/.project b/kotlin-eclipse-p2updatesite/.project deleted file mode 100644 index e7625d985..000000000 --- a/kotlin-eclipse-p2updatesite/.project +++ /dev/null @@ -1,11 +0,0 @@ - - - kotlin-eclipse-p2updatesite - - - - - - - - diff --git a/kotlin-eclipse-p2updatesite/category.xml b/kotlin-eclipse-p2updatesite/category.xml index 86aa9992d..541d1bf35 100644 --- a/kotlin-eclipse-p2updatesite/category.xml +++ b/kotlin-eclipse-p2updatesite/category.xml @@ -1,9 +1,9 @@ - + - + diff --git a/kotlin-eclipse-p2updatesite/pom.xml b/kotlin-eclipse-p2updatesite/pom.xml index 5ce4d20f2..8e9c41908 100644 --- a/kotlin-eclipse-p2updatesite/pom.xml +++ b/kotlin-eclipse-p2updatesite/pom.xml @@ -8,12 +8,11 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.p2updatesite - kotlin.eclipse - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT eclipse-repository \ No newline at end of file diff --git a/kotlin-eclipse-policy/.project b/kotlin-eclipse-policy/.project deleted file mode 100644 index afb49a2a4..000000000 --- a/kotlin-eclipse-policy/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - kotlin-eclipse-policy - - - - - - org.eclipse.pde.FeatureBuilder - - - - - - org.eclipse.pde.FeatureNature - - diff --git a/kotlin-eclipse-policy/feature.xml b/kotlin-eclipse-policy/feature.xml index 836728c72..51cf3aaab 100644 --- a/kotlin-eclipse-policy/feature.xml +++ b/kotlin-eclipse-policy/feature.xml @@ -2,7 +2,7 @@ diff --git a/kotlin-eclipse-policy/pom.xml b/kotlin-eclipse-policy/pom.xml index a7cb0df2a..5e3aff0c8 100644 --- a/kotlin-eclipse-policy/pom.xml +++ b/kotlin-eclipse-policy/pom.xml @@ -8,12 +8,11 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.policy - kotlin.eclipse - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT eclipse-feature \ No newline at end of file diff --git a/kotlin-eclipse-test-framework/.classpath b/kotlin-eclipse-test-framework/.classpath deleted file mode 100644 index f98be78ce..000000000 --- a/kotlin-eclipse-test-framework/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/kotlin-eclipse-test-framework/.gitignore b/kotlin-eclipse-test-framework/.gitignore deleted file mode 100644 index 5e56e040e..000000000 --- a/kotlin-eclipse-test-framework/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin diff --git a/kotlin-eclipse-test-framework/.project b/kotlin-eclipse-test-framework/.project deleted file mode 100644 index f507c9f5e..000000000 --- a/kotlin-eclipse-test-framework/.project +++ /dev/null @@ -1,41 +0,0 @@ - - - kotlin-eclipse-test-framework - - - - - - org.jetbrains.kotlin.ui.kotlinBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - org.jetbrains.kotlin.core.kotlinNature - - - - kotlin_bin - 2 - org.jetbrains.kotlin.core.filesystem:/kotlin-eclipse-test-framework/kotlin_bin - - - diff --git a/kotlin-eclipse-test-framework/.settings/org.eclipse.jdt.core.prefs b/kotlin-eclipse-test-framework/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 1d31a3ec8..000000000 --- a/kotlin-eclipse-test-framework/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,381 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.kt -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.jetbrains.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.jetbrains.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=error -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=error -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 -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_annotation=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=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -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_method_declaration=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -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=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -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_lambda_body=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_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -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_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=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=80 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -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=true -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=false -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not 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_after_type_annotation=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_annotation_declaration=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_lambda_arrow=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_try=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=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=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=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_try=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=do not 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_lambda_arrow=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_try=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_parenthesized_expression_in_throw=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=do not 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_semicolon_in_try_resources=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=do not 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.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -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=120 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -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=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=false -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/kotlin-eclipse-test-framework/.settings/org.eclipse.jdt.ui.prefs b/kotlin-eclipse-test-framework/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index bddb247ef..000000000 --- a/kotlin-eclipse-test-framework/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,3 +0,0 @@ -eclipse.preferences.version=1 -formatter_profile=_Kotlin -formatter_settings_version=12 diff --git a/kotlin-eclipse-test-framework/META-INF/MANIFEST.MF b/kotlin-eclipse-test-framework/META-INF/MANIFEST.MF index 76e8b8c59..3adf09666 100644 --- a/kotlin-eclipse-test-framework/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-test-framework/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-testframework Bundle-SymbolicName: org.jetbrains.kotlin.testframework -Bundle-Version: 0.8.21.qualifier +Bundle-Version: 1.6.21.qualifier Bundle-Activator: org.jetbrains.kotlin.testframework.Activator Require-Bundle: org.jetbrains.kotlin.core, org.jetbrains.kotlin.ui, diff --git a/kotlin-eclipse-test-framework/pom.xml b/kotlin-eclipse-test-framework/pom.xml index b3872150d..275cd1863 100644 --- a/kotlin-eclipse-test-framework/pom.xml +++ b/kotlin-eclipse-test-framework/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.testframework @@ -22,7 +22,9 @@ org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} - + + 11 + compile @@ -33,6 +35,15 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 8 + 8 + + \ No newline at end of file diff --git a/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/editor/TextEditorTest.java b/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/editor/TextEditorTest.java index 731da6ce3..4ef566219 100644 --- a/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/editor/TextEditorTest.java +++ b/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/editor/TextEditorTest.java @@ -97,7 +97,7 @@ public void type(char c) { } public void runOpenDeclarationAction() { - ((KotlinEditor) editor).getJavaEditor().getAction(KotlinOpenDeclarationAction.Companion.getOPEN_EDITOR_TEXT()).run(); + ((KotlinEditor) editor).getJavaEditor().getAction(KotlinOpenDeclarationAction.OPEN_EDITOR_TEXT).run(); } public void runFormatAction() { diff --git a/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/InTextDirectivesUtils.java b/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/InTextDirectivesUtils.java index c0d9583d9..b8f794e01 100644 --- a/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/InTextDirectivesUtils.java +++ b/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/InTextDirectivesUtils.java @@ -9,6 +9,7 @@ import java.util.List; import com.intellij.openapi.util.text.StringUtil; +import kotlin.text.StringsKt; // Source code is taken from org.jetbrains.kotlin.InTextDirectivesUtils public class InTextDirectivesUtils { @@ -70,7 +71,7 @@ private static List cleanDirectivesFromComments(Collection prefi for (String prefix : prefixes) { if (prefix.startsWith("//")) { - resultPrefixes.add(StringUtil.trimStart(prefix, prefix.substring(0, 2)).trim()); + resultPrefixes.add(StringsKt.removePrefix(prefix, prefix.substring(0, 2)).trim()); } else { resultPrefixes.add(prefix.trim()); } diff --git a/kotlin-eclipse-ui-test/.classpath b/kotlin-eclipse-ui-test/.classpath deleted file mode 100644 index 6ee1ef490..000000000 --- a/kotlin-eclipse-ui-test/.classpath +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/kotlin-eclipse-ui-test/.gitignore b/kotlin-eclipse-ui-test/.gitignore deleted file mode 100644 index 5e56e040e..000000000 --- a/kotlin-eclipse-ui-test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin diff --git a/kotlin-eclipse-ui-test/.project b/kotlin-eclipse-ui-test/.project deleted file mode 100644 index c614587d1..000000000 --- a/kotlin-eclipse-ui-test/.project +++ /dev/null @@ -1,47 +0,0 @@ - - - kotlin-eclipse-ui-test - - - - - - org.jetbrains.kotlin.ui.kotlinBuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.api.tools.apiAnalysisBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - org.eclipse.pde.api.tools.apiAnalysisNature - org.jetbrains.kotlin.core.kotlinNature - - - - kotlin_bin - 2 - org.jetbrains.kotlin.core.filesystem:/kotlin-eclipse-ui-test/kotlin_bin - - - diff --git a/kotlin-eclipse-ui-test/.settings/org.eclipse.jdt.core.prefs b/kotlin-eclipse-ui-test/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index d67810695..000000000 --- a/kotlin-eclipse-ui-test/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,382 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.builder.invalidClasspath=ignore -org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.kt -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 -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_annotation=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=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -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_method_declaration=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -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=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -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_lambda_body=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_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -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_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=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=80 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -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=true -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=false -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not 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_after_type_annotation=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_annotation_declaration=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_lambda_arrow=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_try=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=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=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=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_try=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=do not 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_lambda_arrow=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_try=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_parenthesized_expression_in_throw=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=do not 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_semicolon_in_try_resources=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=do not 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.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -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=120 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -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=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=false -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/kotlin-eclipse-ui-test/.settings/org.eclipse.jdt.ui.prefs b/kotlin-eclipse-ui-test/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index bddb247ef..000000000 --- a/kotlin-eclipse-ui-test/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,3 +0,0 @@ -eclipse.preferences.version=1 -formatter_profile=_Kotlin -formatter_settings_version=12 diff --git a/kotlin-eclipse-ui-test/META-INF/MANIFEST.MF b/kotlin-eclipse-ui-test/META-INF/MANIFEST.MF index 5abe1198b..b24b6604d 100644 --- a/kotlin-eclipse-ui-test/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-ui-test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-ui-test Bundle-SymbolicName: org.jetbrains.kotlin.ui.tests;singleton:=true -Bundle-Version: 0.8.21.qualifier +Bundle-Version: 1.6.21.qualifier Bundle-Vendor: JetBrains Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: ., diff --git a/kotlin-eclipse-ui-test/pom.xml b/kotlin-eclipse-ui-test/pom.xml index 8266c06e3..780660735 100644 --- a/kotlin-eclipse-ui-test/pom.xml +++ b/kotlin-eclipse-ui-test/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.ui.tests @@ -17,7 +17,16 @@ - + + + + com.google.code.gson + gson + 2.8.2 + provided + + + @@ -36,9 +45,9 @@ - p2.osgi.bundle - org.eclipse.equinox.weaving.hook - ${weaving-hook.version} + org.eclipse.platform + org.eclipse.equinox.weaving.hook + ${weaving-hook.version} @@ -54,7 +63,9 @@ org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} - + + 11 + compile @@ -67,7 +78,7 @@ - + macosx-jvm-flags @@ -79,4 +90,4 @@ - \ No newline at end of file + diff --git a/kotlin-eclipse-ui/.classpath b/kotlin-eclipse-ui/.classpath deleted file mode 100644 index f98be78ce..000000000 --- a/kotlin-eclipse-ui/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/kotlin-eclipse-ui/.project b/kotlin-eclipse-ui/.project deleted file mode 100644 index 00014da9d..000000000 --- a/kotlin-eclipse-ui/.project +++ /dev/null @@ -1,41 +0,0 @@ - - - kotlin-eclipse-ui - - - - - - org.jetbrains.kotlin.ui.kotlinBuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - org.jetbrains.kotlin.core.kotlinNature - - - - kotlin_bin - 2 - org.jetbrains.kotlin.core.filesystem:/kotlin-eclipse-ui/kotlin_bin - - - diff --git a/kotlin-eclipse-ui/.settings/org.eclipse.jdt.core.prefs b/kotlin-eclipse-ui/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 24c2733a9..000000000 --- a/kotlin-eclipse-ui/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,381 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.kt -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.jetbrains.annotations.NotNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.jetbrains.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=error -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=error -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 -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_annotation=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=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -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_method_declaration=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 -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=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -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=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -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_lambda_body=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_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -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_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=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=80 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -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=true -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=false -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not 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_after_type_annotation=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_annotation_declaration=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_lambda_arrow=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_try=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=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=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=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_try=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=do not 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_lambda_arrow=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_try=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_parenthesized_expression_in_throw=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=do not 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_semicolon_in_try_resources=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=do not 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.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -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=120 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -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=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=false -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/kotlin-eclipse-ui/.settings/org.eclipse.jdt.ui.prefs b/kotlin-eclipse-ui/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index d1db68c03..000000000 --- a/kotlin-eclipse-ui/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,56 +0,0 @@ -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -formatter_profile=_Kotlin -formatter_settings_version=12 -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=false -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=false -sp_cleanup.correct_indentation=false -sp_cleanup.format_source_code=false -sp_cleanup.format_source_code_changes_only=false -sp_cleanup.make_local_variable_final=false -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=true -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=true -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=false -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=false -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=false -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/kotlin-eclipse-ui/META-INF/MANIFEST.MF b/kotlin-eclipse-ui/META-INF/MANIFEST.MF index 7c2261364..d396585ca 100644 --- a/kotlin-eclipse-ui/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-ui Bundle-SymbolicName: org.jetbrains.kotlin.ui;singleton:=true -Bundle-Version: 0.8.21.qualifier +Bundle-Version: 1.6.21.qualifier Bundle-Activator: org.jetbrains.kotlin.ui.Activator Bundle-Vendor: JetBrains Require-Bundle: org.eclipse.ui, @@ -25,11 +25,14 @@ Require-Bundle: org.eclipse.ui, org.eclipse.equinox.p2.core, org.eclipse.equinox.p2.metadata, org.eclipse.equinox.p2.engine, - org.eclipse.mylyn.commons.ui, org.eclipse.equinox.p2.director, org.eclipse.core.variables Bundle-ActivationPolicy: lazy -Import-Package: org.eclipse.core.expressions, +Import-Package: com.google.common.collect, + org.jetbrains.kotlin.nj2k, + org.jetbrains.kotlin.idea.j2k, + org.jetbrains.kotlin.nj2k.postProcessing, + org.eclipse.core.expressions, org.eclipse.core.resources, org.eclipse.jdt.core, org.eclipse.jdt.core.compiler, @@ -53,7 +56,8 @@ Import-Package: org.eclipse.core.expressions, org.eclipse.ui.texteditor.link, org.eclipse.ui.texteditor.templates, org.eclipse.ui.views.contentoutline, - org.eclipse.ui.wizards.newresource + org.eclipse.ui.wizards.newresource, + org.jetbrains.kotlin.idea.util Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: org.jetbrains.kotlin.eclipse.ui.utils, org.jetbrains.kotlin.ui, diff --git a/kotlin-eclipse-ui/plugin.xml b/kotlin-eclipse-ui/plugin.xml index d2dffc685..495b556bb 100644 --- a/kotlin-eclipse-ui/plugin.xml +++ b/kotlin-eclipse-ui/plugin.xml @@ -29,7 +29,7 @@ icon="icons/newfile_wiz.gif" id="org.jetbrains.kotlin.wizard" name="Kotlin File" - preferredPerspectives="org.jetbrains.kotlin.perspective" + preferredPerspectives="org.jetbrains.kotlin.perspective,org.eclipse.jdt.ui.JavaPerspective" project="false"> Create a new Kotlin file @@ -49,6 +49,20 @@ Create a new Kotlin class + + + Create a new Kotlin sealed class + + - Create a new Kotlin trait + Create a new Kotlin interface + + + + + Create a new Kotlin sealed interface + + + Create a new Kotlin data class + + + + + Create a new Kotlin annotation + + + + + + + + @@ -370,14 +442,29 @@ label="References"> + + + + + + @@ -600,8 +687,7 @@ class="org.jetbrains.kotlin.ui.editors.KotlinElementHyperlinkDetector" id="org.jetbrains.kotlin.ui.editors.KotlinElementHyperlinkDetector" name="KotlinElementHyperlinkDetector" - targetId="org.jetbrains.kotlin.ui.editors.kotlinCode"> - + targetId="org.jetbrains.kotlin.ui.editors.kotlinCode"/> diff --git a/kotlin-eclipse-ui/pom.xml b/kotlin-eclipse-ui/pom.xml index dd89bcbed..f7d9a3bab 100644 --- a/kotlin-eclipse-ui/pom.xml +++ b/kotlin-eclipse-ui/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.ui @@ -23,7 +23,7 @@ kotlin-maven-plugin ${kotlin.version} - 1.8 + 11 @@ -35,6 +35,15 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 8 + 8 + + \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/KotlinEclipseScope.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/KotlinEclipseScope.kt new file mode 100644 index 000000000..c4bb8430e --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/KotlinEclipseScope.kt @@ -0,0 +1,7 @@ +package org.jetbrains.kotlin.eclipse.ui.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob + +object KotlinEclipseScope : CoroutineScope by CoroutineScope(SupervisorJob() + Dispatchers.IO) diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/KotlinImageProvider.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/KotlinImageProvider.kt index a22e0a677..d17576d31 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/KotlinImageProvider.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/KotlinImageProvider.kt @@ -16,36 +16,28 @@ *******************************************************************************/ package org.jetbrains.kotlin.eclipse.ui.utils +import org.eclipse.jdt.ui.ISharedImages import org.eclipse.jdt.ui.JavaUI import org.eclipse.swt.graphics.Image -import org.eclipse.jdt.ui.ISharedImages -import org.jetbrains.kotlin.psi.KtVariableDeclaration -import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.descriptors.VariableDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.PackageViewDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.psi.KtVariableDeclaration -public object KotlinImageProvider { - public fun getImage(descriptor: DeclarationDescriptor): Image? { +object KotlinImageProvider { + fun getImage(descriptor: DeclarationDescriptor): Image? { return when(descriptor) { is ClassDescriptor, is TypeParameterDescriptor, is TypeAliasDescriptor -> getImageFromJavaUI(ISharedImages.IMG_OBJS_CLASS) is FunctionDescriptor -> getImageFromJavaUI(ISharedImages.IMG_OBJS_PUBLIC) is VariableDescriptor -> getImageFromJavaUI(ISharedImages.IMG_FIELD_PUBLIC) is PackageViewDescriptor -> getImageFromJavaUI(ISharedImages.IMG_OBJS_PACKAGE) - is PropertyDescriptor -> getImageFromJavaUI(ISharedImages.IMG_FIELD_PUBLIC) else -> null } } - public fun getImage(element: KtElement): Image? { + fun getImage(element: KtElement): Image? { return when(element) { is KtClassOrObject -> getImageFromJavaUI(ISharedImages.IMG_OBJS_CLASS) is KtFunction -> getImageFromJavaUI(ISharedImages.IMG_OBJS_PUBLIC) @@ -55,4 +47,4 @@ public object KotlinImageProvider { } private fun getImageFromJavaUI(imageName: String): Image = JavaUI.getSharedImages().getImage(imageName) -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/analyzeUtils.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/analyzeUtils.kt index a78eb6d39..45158e2ea 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/analyzeUtils.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/analyzeUtils.kt @@ -1,37 +1,8 @@ -/******************************************************************************* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - *******************************************************************************/ - package org.jetbrains.kotlin.eclipse.ui.utils -import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.ui.editors.KotlinEditor +import org.jetbrains.kotlin.core.utils.getBindingContext -fun getBindingContext(kotlinEditor: KotlinEditor): BindingContext? = - kotlinEditor.parsedFile?.let { getBindingContext(it) } - -fun getBindingContext(ktElement: KtElement): BindingContext? = - getBindingContext(ktElement.containingKtFile) - -fun getBindingContext(ktFile: KtFile): BindingContext? = - KotlinAnalyzer.analyzeFile(ktFile).analysisResult.bindingContext - -fun getModuleDescriptor(ktFile: KtFile): ModuleDescriptor = - KotlinAnalyzer.analyzeFile(ktFile).analysisResult.moduleDescriptor \ No newline at end of file +fun KotlinEditor.getBindingContext(): BindingContext? = + parsedFile?.getBindingContext() \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/KotlinAwarePackageExplorerLabelProvider.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/KotlinAwarePackageExplorerLabelProvider.kt index 44b05519c..5ec8a261e 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/KotlinAwarePackageExplorerLabelProvider.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/KotlinAwarePackageExplorerLabelProvider.kt @@ -6,6 +6,9 @@ import org.eclipse.jdt.internal.ui.packageview.PackageExplorerContentProvider import org.eclipse.jdt.internal.ui.packageview.PackageExplorerLabelProvider import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider import org.eclipse.swt.graphics.Image +import org.jetbrains.kotlin.core.model.EclipseScriptDefinitionProvider +import org.jetbrains.kotlin.core.utils.asFile +import kotlin.script.experimental.host.FileScriptSource /** * Modified version of [PackageExplorerLabelProvider] that returns correct images for packages @@ -18,7 +21,7 @@ import org.eclipse.swt.graphics.Image */ class KotlinAwarePackageExplorerLabelProvider(cp: PackageExplorerContentProvider) : PackageExplorerLabelProvider(cp) { - override fun getImage(element: Any?): Image { + override fun getImage(element: Any?): Image? { // Replace instances of IPackageFragment with instances of KotlinAwarePackageFragment return super.getImage(when (element) { is IPackageFragment -> KotlinAwarePackageFragment(element) @@ -35,7 +38,7 @@ class KotlinAwarePackageExplorerLabelProvider(cp: PackageExplorerContentProvider override fun hasChildren(): Boolean { return base.hasChildren() || base.nonJavaResources.any { obj -> - obj is IFile && (obj.name.endsWith(".kt") || obj.name.endsWith(".kts")) + obj is IFile && (obj.name.endsWith(".kt") || EclipseScriptDefinitionProvider.isScript(FileScriptSource(obj.asFile))) } } } diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/KotlinPluginUpdater.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/KotlinPluginUpdater.kt index 8dfa0f2d6..57d865803 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/KotlinPluginUpdater.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/KotlinPluginUpdater.kt @@ -16,42 +16,37 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui -import java.util.concurrent.TimeUnit +import com.intellij.openapi.util.SystemInfo import org.eclipse.core.runtime.IProgressMonitor +import org.eclipse.core.runtime.IStatus +import org.eclipse.core.runtime.NullProgressMonitor +import org.eclipse.core.runtime.jobs.IJobChangeEvent +import org.eclipse.core.runtime.jobs.JobChangeAdapter import org.eclipse.equinox.p2.metadata.IInstallableUnit +import org.eclipse.equinox.p2.metadata.Version import org.eclipse.equinox.p2.operations.OperationFactory -import org.eclipse.core.runtime.NullProgressMonitor -import java.net.URI +import org.eclipse.equinox.p2.operations.UpdateOperation import org.eclipse.jface.dialogs.MessageDialog -import org.eclipse.swt.widgets.Display -import org.eclipse.equinox.p2.operations.ProfileModificationJob -import org.eclipse.equinox.p2.operations.ProvisioningJob -import org.eclipse.mylyn.commons.ui.dialogs.AbstractNotificationPopup -import org.eclipse.swt.widgets.Composite -import org.eclipse.swt.layout.GridLayout -import org.eclipse.swt.widgets.Label +import org.eclipse.jface.notifications.AbstractNotificationPopup +import org.eclipse.jface.preference.IPreferenceStore import org.eclipse.swt.SWT -import org.eclipse.swt.layout.GridData -import org.eclipse.swt.widgets.Link import org.eclipse.swt.events.SelectionAdapter import org.eclipse.swt.events.SelectionEvent -import org.eclipse.equinox.p2.operations.UpdateOperation -import java.net.URL -import java.net.URLConnection -import java.net.HttpURLConnection +import org.eclipse.swt.layout.GridData +import org.eclipse.swt.layout.GridLayout +import org.eclipse.swt.widgets.Composite +import org.eclipse.swt.widgets.Display +import org.eclipse.swt.widgets.Label +import org.eclipse.swt.widgets.Link +import org.eclipse.ui.PlatformUI import org.jetbrains.kotlin.core.log.KotlinLogger -import com.intellij.openapi.util.SystemInfo -import java.net.URLEncoder -import org.eclipse.jface.preference.IPreferenceStore -import org.eclipse.equinox.p2.metadata.Version -import java.util.Random -import org.jetbrains.kotlin.core.model.runJob -import org.eclipse.core.runtime.IStatus -import org.eclipse.core.runtime.Status import java.io.IOException -import org.eclipse.core.runtime.jobs.JobChangeAdapter -import org.eclipse.core.runtime.jobs.IJobChangeEvent -import org.eclipse.ui.PlatformUI +import java.net.HttpURLConnection +import java.net.URI +import java.net.URL +import java.net.URLEncoder +import java.util.* +import java.util.concurrent.TimeUnit private sealed class PluginUpdateStatus() { object Update : PluginUpdateStatus() diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/ScriptClasspathUpdater.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/ScriptClasspathUpdater.kt index 828a772c9..9a8f12937 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/ScriptClasspathUpdater.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/ScriptClasspathUpdater.kt @@ -39,13 +39,16 @@ internal fun tryUpdateScriptClasspath(file: IFile) { val dependenciesProvider: DependenciesResolver? = ServiceManager.getService(environment.project, DependenciesResolver::class.java) runJob("Check script dependencies", Job.DECORATE, null, { - val contents = ScriptContentLoader(environment.project).getScriptContents( - environment.definition?.legacyDefinition!!, - environment.getVirtualFile(file.location)!! - ) + var newDependencies: DependenciesResolver.ResolveResult? = null + if(dependenciesProvider != null) { + val contents = ScriptContentLoader(environment.project).getScriptContents( + environment.definition?.legacyDefinition!!, + environment.getVirtualFile(file.location)!! + ) - val scriptEnvironment = EclipseScriptDefinitionProvider.getEnvironment(file.asFile).orEmpty() - val newDependencies = dependenciesProvider?.resolve(contents, scriptEnvironment) + val scriptEnvironment = EclipseScriptDefinitionProvider.getEnvironment(file.asFile).orEmpty() + newDependencies = dependenciesProvider.resolve(contents, scriptEnvironment) + } StatusWithDependencies(Status.OK_STATUS, newDependencies?.dependencies) }) { event -> val editor = findEditor(file) @@ -53,8 +56,11 @@ internal fun tryUpdateScriptClasspath(file: IFile) { val newDependencies = (statusWithDependencies as? StatusWithDependencies)?.dependencies if (file.isAccessible && editor != null) { editor.reconcile { - KotlinScriptEnvironment.updateDependencies(file, newDependencies) - KotlinAnalysisFileCache.resetCache() + val tempEnv = KotlinScriptEnvironment.getEnvironment(file) + if(tempEnv.dependencies != newDependencies) { + KotlinScriptEnvironment.updateDependencies(file, newDependencies) + KotlinAnalysisFileCache.resetCache() + } } } } diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/BaseKotlinBuilderElement.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/BaseKotlinBuilderElement.kt index 505709d79..7120a562e 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/BaseKotlinBuilderElement.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/BaseKotlinBuilderElement.kt @@ -4,14 +4,19 @@ import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IResourceDelta import org.eclipse.core.resources.ResourcesPlugin +import org.eclipse.core.runtime.Status +import org.eclipse.core.runtime.jobs.Job import org.eclipse.jdt.core.IJavaProject import org.eclipse.ui.PlatformUI import org.jetbrains.kotlin.core.asJava.KotlinLightClassGeneration import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.model.KotlinScriptEnvironment +import org.jetbrains.kotlin.core.model.runJob +import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics +import org.jetbrains.kotlin.ui.KotlinPluginUpdater import org.jetbrains.kotlin.ui.editors.KotlinFileEditor import org.jetbrains.kotlin.ui.editors.annotations.AnnotationManager import org.jetbrains.kotlin.ui.editors.annotations.DiagnosticAnnotation @@ -73,6 +78,51 @@ abstract class BaseKotlinBuilderElement { clearMarkersFromFiles(affectedFiles) addMarkersToProject(DiagnosticAnnotationUtil.INSTANCE.handleDiagnostics(diagnostics), affectedFiles) } + + protected fun postBuild(delta: IResourceDelta?, javaProject: IJavaProject) { + val allAffectedFiles = if (delta != null) getAllAffectedFiles(delta) else emptySet() + + if (allAffectedFiles.isNotEmpty()) { + if (isAllFilesApplicableForFilters(allAffectedFiles, javaProject)) { + return + } + } + + val kotlinAffectedFiles = + allAffectedFiles + .filterTo(hashSetOf()) { KotlinPsiManager.isKotlinSourceFile(it, javaProject) } + + val existingAffectedFiles = kotlinAffectedFiles.filter { it.exists() } + + commitFiles(existingAffectedFiles) + + KotlinLightClassGeneration.updateLightClasses(javaProject.project, kotlinAffectedFiles) + if (kotlinAffectedFiles.isNotEmpty()) { + + runJob("Checking for update", Job.DECORATE) { + KotlinPluginUpdater.kotlinFileEdited() + Status.OK_STATUS + } + } + + val ktFiles = existingAffectedFiles.map { KotlinPsiManager.getParsedFile(it) } + + val analysisResultWithProvider = if (ktFiles.isEmpty()) + KotlinAnalyzer.analyzeProject(javaProject.project) + else + KotlinAnalyzer.analyzeFiles(ktFiles) + + clearProblemAnnotationsFromOpenEditorsExcept(existingAffectedFiles) + updateLineMarkers(analysisResultWithProvider.analysisResult.bindingContext.diagnostics, existingAffectedFiles) + + runCancellableAnalysisFor(javaProject) { analysisResult -> + val projectFiles = KotlinPsiManager.getFilesByProject(javaProject.project) + updateLineMarkers( + analysisResult.bindingContext.diagnostics, + (projectFiles - existingAffectedFiles.toSet()).toList() + ) + } + } } private fun clearMarkersFromFiles(files: List) { diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/IncrementalKotlinBuilderElement.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/IncrementalKotlinBuilderElement.kt index 2e868e923..7bbb58cc1 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/IncrementalKotlinBuilderElement.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/IncrementalKotlinBuilderElement.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.core.compiler.KotlinCompilerUtils import org.jetbrains.kotlin.core.model.runJob import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer import org.jetbrains.kotlin.ui.KotlinPluginUpdater +import org.jetbrains.kotlin.ui.launch.removeKotlinConsoles class IncrementalKotlinBuilderElement : BaseKotlinBuilderElement() { @@ -25,51 +26,10 @@ class IncrementalKotlinBuilderElement : BaseKotlinBuilderElement() { return null } + removeKotlinConsoles(javaProject) compileKotlinFilesIncrementally(javaProject) - val allAffectedFiles = if (delta != null) getAllAffectedFiles(delta) else emptySet() - - if (allAffectedFiles.isNotEmpty()) { - if (isAllFilesApplicableForFilters(allAffectedFiles, javaProject)) { - return null - } - } - - val kotlinAffectedFiles = - allAffectedFiles - .filter { KotlinPsiManager.isKotlinSourceFile(it, javaProject) } - .toSet() - - val existingAffectedFiles = kotlinAffectedFiles.filter { it.exists() } - - commitFiles(existingAffectedFiles) - - KotlinLightClassGeneration.updateLightClasses(javaProject.project, kotlinAffectedFiles) - if (kotlinAffectedFiles.isNotEmpty()) { - - runJob("Checking for update", Job.DECORATE) { - KotlinPluginUpdater.kotlinFileEdited() - Status.OK_STATUS - } - } - - val ktFiles = existingAffectedFiles.map { KotlinPsiManager.getParsedFile(it) } - - val analysisResultWithProvider = if (ktFiles.isEmpty()) - KotlinAnalyzer.analyzeProject(project) - else - KotlinAnalyzer.analyzeFiles(ktFiles) - - clearProblemAnnotationsFromOpenEditorsExcept(existingAffectedFiles) - updateLineMarkers(analysisResultWithProvider.analysisResult.bindingContext.diagnostics, existingAffectedFiles) - - runCancellableAnalysisFor(javaProject) { analysisResult -> - val projectFiles = KotlinPsiManager.getFilesByProject(javaProject.project) - updateLineMarkers( - analysisResult.bindingContext.diagnostics, - (projectFiles - existingAffectedFiles).toList() - ) - } + postBuild(delta, javaProject) return null } @@ -77,7 +37,7 @@ class IncrementalKotlinBuilderElement : BaseKotlinBuilderElement() { private fun compileKotlinFilesIncrementally(javaProject: IJavaProject) { val compilerResult: KotlinCompilerResult = KotlinCompilerUtils.compileProjectIncrementally(javaProject) if (!compilerResult.compiledCorrectly()) { - KotlinCompilerUtils.handleCompilerOutput(compilerResult.compilerOutput) + KotlinCompilerUtils.handleCompilerOutput(KotlinCompilerUtils.CompilerOutputWithProject(compilerResult.compilerOutput, javaProject)) } } } \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/KotlinBuilderElement.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/KotlinBuilderElement.kt index 4818651a9..5b753c947 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/KotlinBuilderElement.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/KotlinBuilderElement.kt @@ -15,12 +15,14 @@ import org.jetbrains.kotlin.core.compiler.KotlinCompilerUtils import org.jetbrains.kotlin.core.model.runJob import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer import org.jetbrains.kotlin.ui.KotlinPluginUpdater +import org.jetbrains.kotlin.ui.launch.removeKotlinConsoles class KotlinBuilderElement : BaseKotlinBuilderElement() { override fun build(project: IProject, delta: IResourceDelta?, kind: Int): Array? { val javaProject = JavaCore.create(project) if (isBuildingForLaunch()) { + removeKotlinConsoles(javaProject) compileKotlinFiles(javaProject) return null } @@ -30,49 +32,7 @@ class KotlinBuilderElement : BaseKotlinBuilderElement() { return null } - val allAffectedFiles = if (delta != null) getAllAffectedFiles(delta) else emptySet() - - if (allAffectedFiles.isNotEmpty()) { - if (isAllFilesApplicableForFilters(allAffectedFiles, javaProject)) { - return null - } - } - - val kotlinAffectedFiles = - allAffectedFiles - .filter { KotlinPsiManager.isKotlinSourceFile(it, javaProject) } - .toSet() - - val existingAffectedFiles = kotlinAffectedFiles.filter { it.exists() } - - commitFiles(existingAffectedFiles) - - KotlinLightClassGeneration.updateLightClasses(javaProject.project, kotlinAffectedFiles) - if (kotlinAffectedFiles.isNotEmpty()) { - - runJob("Checking for update", Job.DECORATE) { - KotlinPluginUpdater.kotlinFileEdited() - Status.OK_STATUS - } - } - - val ktFiles = existingAffectedFiles.map { KotlinPsiManager.getParsedFile(it) } - - val analysisResultWithProvider = if (ktFiles.isEmpty()) - KotlinAnalyzer.analyzeProject(project) - else - KotlinAnalyzer.analyzeFiles(ktFiles) - - clearProblemAnnotationsFromOpenEditorsExcept(existingAffectedFiles) - updateLineMarkers(analysisResultWithProvider.analysisResult.bindingContext.diagnostics, existingAffectedFiles) - - runCancellableAnalysisFor(javaProject) { analysisResult -> - val projectFiles = KotlinPsiManager.getFilesByProject(javaProject.project) - updateLineMarkers( - analysisResult.bindingContext.diagnostics, - (projectFiles - existingAffectedFiles).toList() - ) - } + postBuild(delta, javaProject) return null } @@ -87,7 +47,7 @@ class KotlinBuilderElement : BaseKotlinBuilderElement() { private fun compileKotlinFiles(javaProject: IJavaProject) { val compilerResult: KotlinCompilerResult = KotlinCompilerUtils.compileWholeProject(javaProject) if (!compilerResult.compiledCorrectly()) { - KotlinCompilerUtils.handleCompilerOutput(compilerResult.compilerOutput) + KotlinCompilerUtils.handleCompilerOutput(KotlinCompilerUtils.CompilerOutputWithProject(compilerResult.compilerOutput, javaProject)) } } } \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/ResourceChangeListener.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/ResourceChangeListener.kt index c801eb3c7..faea7b6fe 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/ResourceChangeListener.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/ResourceChangeListener.kt @@ -1,65 +1,58 @@ /******************************************************************************* -* Copyright 2000-2015 JetBrains s.r.o. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -*******************************************************************************/ + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *******************************************************************************/ package org.jetbrains.kotlin.ui.builder -import org.eclipse.core.resources.IFile -import org.eclipse.core.resources.IProject -import org.eclipse.core.resources.IResource -import org.eclipse.core.resources.IResourceChangeEvent -import org.eclipse.core.resources.IResourceChangeListener -import org.eclipse.core.resources.IResourceDelta -import org.eclipse.core.resources.IResourceDeltaVisitor +import org.eclipse.core.resources.* +import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.core.builder.KotlinPsiManager -import org.jetbrains.kotlin.core.model.KotlinEnvironment -import org.jetbrains.kotlin.core.model.KotlinNature -import org.jetbrains.kotlin.core.model.setKotlinBuilderBeforeJavaBuilder +import org.jetbrains.kotlin.core.model.* +import org.jetbrains.kotlin.core.utils.ProjectUtils +import org.jetbrains.kotlin.core.utils.asFile +import kotlin.script.experimental.host.FileScriptSource -public class ResourceChangeListener : IResourceChangeListener { - override public fun resourceChanged(event: IResourceChangeEvent) { +class ResourceChangeListener : IResourceChangeListener { + override fun resourceChanged(event: IResourceChangeEvent) { val eventResource = event.resource if (eventResource != null) { val type = event.type if (type == IResourceChangeEvent.PRE_CLOSE || type == IResourceChangeEvent.PRE_DELETE) { updateManager(eventResource, IResourceDelta.REMOVED) } - + return } - - val delta = event.delta - if (delta != null) { - delta.accept(ProjectChangeListener()) - } + + event.delta?.accept(ProjectChangeListener()) } } class ProjectChangeListener : IResourceDeltaVisitor { - override public fun visit(delta: IResourceDelta) : Boolean { + override fun visit(delta: IResourceDelta): Boolean { val resource = delta.resource if ((delta.flags and IResourceDelta.OPEN) != 0) { if (resource is IProject && resource.isOpen) { return updateManager(resource, IResourceDelta.ADDED) } } - - if (delta.getKind() == IResourceDelta.CHANGED) { + + if (delta.kind == IResourceDelta.CHANGED) { return true } - + return updateManager(resource, delta.kind) } } @@ -67,30 +60,48 @@ class ProjectChangeListener : IResourceDeltaVisitor { private fun updateManager(resource: IResource, deltaKind: Int): Boolean { return when (resource) { is IFile -> { + //IF we got a source file we update the psi! if (KotlinPsiManager.isKotlinSourceFile(resource)) { KotlinPsiManager.updateProjectPsiSources(resource, deltaKind) } - + + //If we got a script file and it was deleted we remove the environment. + if(EclipseScriptDefinitionProvider.isScript(FileScriptSource(resource.asFile))) { + if(deltaKind == IResourceDelta.REMOVED) { + KotlinScriptEnvironment.removeKotlinEnvironment(resource) + } + } false } - + is IProject -> { - if (!resource.isAccessible || !KotlinNature.hasKotlinNature(resource)) { - return false - } - + //If we got a project removed we need to remove all environments that represent + //this project or dependet on that project. For simplicity we remove all environments for now. if (deltaKind == IResourceDelta.REMOVED) { KotlinPsiManager.removeProjectFromManager(resource) - KotlinEnvironment.removeEnvironment(resource) + KotlinEnvironment.removeEnvironmentIf { it: KotlinCommonEnvironment -> + val tempDepPrjs = ProjectUtils.getDependencyProjects(it.javaProject) + resource in tempDepPrjs + } + KotlinScriptEnvironment.removeEnvironmentIf { it: KotlinCommonEnvironment -> + val tempDepPrjs = ProjectUtils.getDependencyProjects(it.javaProject) + resource in tempDepPrjs + } } - - if (deltaKind == IResourceDelta.ADDED && KotlinNature.hasKotlinBuilder(resource)) { - setKotlinBuilderBeforeJavaBuilder(resource) + + //If a project was added we need to make sure the kotlin builder is invoked before the java builder. + //Also we need to refresh all environments that had errors before, as they could be resolved by the new project. + if (deltaKind == IResourceDelta.ADDED) { + if(KotlinNature.hasKotlinBuilder(resource)) { + setKotlinBuilderBeforeJavaBuilder(resource) + } + KotlinEnvironment.removeEnvironmentIf { it.hasError } + KotlinScriptEnvironment.removeEnvironmentIf { it.hasError } } - + false } - + else -> true // folder } } \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/findReferences/KotlinFindReferencesAction.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/findReferences/KotlinFindReferencesAction.kt index c4877eac3..e583156f3 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/findReferences/KotlinFindReferencesAction.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/findReferences/KotlinFindReferencesAction.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.ui.commands.findReferences import org.eclipse.core.commands.AbstractHandler import org.eclipse.core.commands.ExecutionEvent -import org.eclipse.core.resources.IFile import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.JavaCore import org.eclipse.jdt.core.search.IJavaSearchConstants @@ -45,14 +44,14 @@ abstract class KotlinFindReferencesHandler : AbstractHandler() { override fun execute(event: ExecutionEvent): Any? { val editor = HandlerUtil.getActiveEditor(event) if (editor !is KotlinCommonEditor) return null - - getAction(editor).run(editor.getViewer().getSelectionProvider().getSelection() as ITextSelection) - + + getAction(editor).run(editor.viewer.selectionProvider.selection as ITextSelection) + return null } - + abstract fun getAction(editor: KotlinCommonEditor): KotlinFindReferencesAction - + } class KotlinFindReferencesInProjectHandler : KotlinFindReferencesHandler() { @@ -61,83 +60,139 @@ class KotlinFindReferencesInProjectHandler : KotlinFindReferencesHandler() { } } + class KotlinFindReferencesInWorkspaceHandler : KotlinFindReferencesHandler() { override fun getAction(editor: KotlinCommonEditor): KotlinFindReferencesAction { return KotlinFindReferencesInWorkspaceAction(editor) } } -public class KotlinFindReferencesInProjectAction(editor: KotlinCommonEditor) : KotlinFindReferencesAction(editor) { +class KotlinFindImplementationsInWorkspaceHandler : KotlinFindReferencesHandler() { + + override fun getAction(editor: KotlinCommonEditor): KotlinFindReferencesAction { + return KotlinFindImplementationsInWorkspaceAction(editor) + } +} + +class KotlinFindImplementationsInProjectHandler : KotlinFindReferencesHandler() { + + override fun getAction(editor: KotlinCommonEditor): KotlinFindReferencesAction { + return KotlinFindImplementationsInProjectAction(editor) + } +} + +class KotlinFindImplementationsInProjectAction(editor: KotlinCommonEditor) : KotlinFindReferencesAction(editor) { + + init { + actionDefinitionId = IJavaEditorActionDefinitionIds.SEARCH_IMPLEMENTORS_IN_WORKSPACE + text = SearchMessages.Search_FindImplementorsAction_label + toolTipText = SearchMessages.Search_FindImplementorsAction_tooltip + imageDescriptor = JavaPluginImages.DESC_OBJS_SEARCH_REF + PlatformUI.getWorkbench().helpSystem.setHelp(this, IJavaHelpContextIds.FIND_IMPLEMENTORS_IN_WORKSPACE_ACTION) + } + + override fun createScopeQuerySpecification(jetElement: KtElement): QuerySpecification { + val factory = JavaSearchScopeFactory.getInstance() + return createQuerySpecification( + jetElement, + factory.createJavaProjectSearchScope(javaProject, false), + factory.getProjectScopeDescription(javaProject, false), + IMPLEMENTORS_LIMIT_TO + ) + } + + companion object { + const val IMPLEMENTORS_LIMIT_TO = 48 + } +} + +class KotlinFindImplementationsInWorkspaceAction(editor: KotlinCommonEditor) : KotlinFindReferencesAction(editor) { + + init { + actionDefinitionId = IJavaEditorActionDefinitionIds.SEARCH_IMPLEMENTORS_IN_WORKSPACE + text = SearchMessages.Search_FindImplementorsAction_label + toolTipText = SearchMessages.Search_FindImplementorsAction_tooltip + imageDescriptor = JavaPluginImages.DESC_OBJS_SEARCH_REF + PlatformUI.getWorkbench().helpSystem.setHelp(this, IJavaHelpContextIds.FIND_IMPLEMENTORS_IN_WORKSPACE_ACTION) + } + + override fun createScopeQuerySpecification(jetElement: KtElement): QuerySpecification { + val factory = JavaSearchScopeFactory.getInstance() + return createQuerySpecification( + jetElement, + factory.createWorkspaceScope(false), + factory.getWorkspaceScopeDescription(false), + KotlinFindImplementationsInProjectAction.IMPLEMENTORS_LIMIT_TO + ) + } +} + +class KotlinFindReferencesInProjectAction(editor: KotlinCommonEditor) : KotlinFindReferencesAction(editor) { init { - setActionDefinitionId(IJavaEditorActionDefinitionIds.SEARCH_REFERENCES_IN_PROJECT) - setText(SearchMessages.Search_FindReferencesInProjectAction_label) - setToolTipText(SearchMessages.Search_FindReferencesInProjectAction_tooltip) - setImageDescriptor(JavaPluginImages.DESC_OBJS_SEARCH_REF) - PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.FIND_REFERENCES_IN_PROJECT_ACTION) + actionDefinitionId = IJavaEditorActionDefinitionIds.SEARCH_REFERENCES_IN_PROJECT + text = SearchMessages.Search_FindReferencesInProjectAction_label + toolTipText = SearchMessages.Search_FindReferencesInProjectAction_tooltip + imageDescriptor = JavaPluginImages.DESC_OBJS_SEARCH_REF + PlatformUI.getWorkbench().helpSystem.setHelp(this, IJavaHelpContextIds.FIND_REFERENCES_IN_PROJECT_ACTION) } - + companion object { - val ACTION_ID = "SearchReferencesInProject" + const val ACTION_ID = "SearchReferencesInProject" } - + override fun createScopeQuerySpecification(jetElement: KtElement): QuerySpecification { val factory = JavaSearchScopeFactory.getInstance() return createQuerySpecification( - jetElement, - factory.createJavaProjectSearchScope(javaProject, false), - factory.getProjectScopeDescription(javaProject, false)) + jetElement, + factory.createJavaProjectSearchScope(javaProject, false), + factory.getProjectScopeDescription(javaProject, false) + ) } } -public class KotlinFindReferencesInWorkspaceAction(editor: KotlinCommonEditor) : KotlinFindReferencesAction(editor) { +class KotlinFindReferencesInWorkspaceAction(editor: KotlinCommonEditor) : KotlinFindReferencesAction(editor) { init { - setActionDefinitionId(IJavaEditorActionDefinitionIds.SEARCH_REFERENCES_IN_WORKSPACE) - setText(SearchMessages.Search_FindReferencesAction_label) - setToolTipText(SearchMessages.Search_FindReferencesAction_tooltip) - setImageDescriptor(JavaPluginImages.DESC_OBJS_SEARCH_REF) - PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.FIND_REFERENCES_IN_WORKSPACE_ACTION) + actionDefinitionId = IJavaEditorActionDefinitionIds.SEARCH_REFERENCES_IN_WORKSPACE + text = SearchMessages.Search_FindReferencesAction_label + toolTipText = SearchMessages.Search_FindReferencesAction_tooltip + imageDescriptor = JavaPluginImages.DESC_OBJS_SEARCH_REF + PlatformUI.getWorkbench().helpSystem.setHelp(this, IJavaHelpContextIds.FIND_REFERENCES_IN_WORKSPACE_ACTION) } - + companion object { - val ACTION_ID = "SearchReferencesInWorkspace" + const val ACTION_ID = "SearchReferencesInWorkspace" } - + override fun createScopeQuerySpecification(jetElement: KtElement): QuerySpecification { val factory = JavaSearchScopeFactory.getInstance() return createQuerySpecification( - jetElement, - factory.createWorkspaceScope(false), - factory.getWorkspaceScopeDescription(false)) + jetElement, + factory.createWorkspaceScope(false), + factory.getWorkspaceScopeDescription(false) + ) } } -abstract class KotlinFindReferencesAction(val editor: KotlinCommonEditor) : SelectionDispatchAction(editor.getSite()) { +abstract class KotlinFindReferencesAction(val editor: KotlinCommonEditor) : SelectionDispatchAction(editor.site) { var javaProject: IJavaProject by Delegates.notNull() - - override public fun run(selection: ITextSelection) { - val file = editor.eclipseFile - if (file == null) return - - javaProject = JavaCore.create(file.getProject()) - - val jetElement = EditorUtil.getJetElement(editor, selection.getOffset()) - if (jetElement == null) return - + + override fun run(selection: ITextSelection) { + val file = editor.eclipseFile ?: return + + javaProject = JavaCore.create(file.project) + + val jetElement = EditorUtil.getJetElement(editor, selection.offset) ?: return + val querySpecification = createScopeQuerySpecification(jetElement) val query = JavaSearchQuery(querySpecification) - + SearchUtil.runQueryInBackground(query) } - + abstract fun createScopeQuerySpecification(jetElement: KtElement): QuerySpecification - - private fun getFile(event: ExecutionEvent): IFile? { - val activeEditor = HandlerUtil.getActiveEditor(event) - return EditorUtil.getFile(activeEditor) - } } -fun createQuerySpecification(jetElement: KtElement, scope: IJavaSearchScope, description: String): QuerySpecification { +fun createQuerySpecification(jetElement: KtElement, scope: IJavaSearchScope, description: String, limitTo: Int = IJavaSearchConstants.REFERENCES): QuerySpecification { val sourceElements = jetElement.resolveToSourceDeclaration() - return KotlinJavaQuerySpecification(sourceElements, IJavaSearchConstants.REFERENCES, scope, description) -} \ No newline at end of file + return KotlinJavaQuerySpecification(sourceElements, limitTo, scope, description) +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/findReferences/querySpecifications.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/findReferences/querySpecifications.kt index a163f41fe..287c659e2 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/findReferences/querySpecifications.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/findReferences/querySpecifications.kt @@ -1,15 +1,14 @@ package org.jetbrains.kotlin.ui.commands.findReferences +import org.eclipse.core.resources.IFile +import org.eclipse.core.resources.ResourcesPlugin +import org.eclipse.core.runtime.IPath +import org.eclipse.jdt.core.IJavaElement import org.eclipse.jdt.core.search.IJavaSearchConstants -import org.eclipse.jdt.ui.search.PatternQuerySpecification import org.eclipse.jdt.core.search.IJavaSearchScope -import org.jetbrains.kotlin.psi.KtElement -import org.eclipse.jdt.core.IJavaElement -import org.eclipse.core.runtime.IPath -import org.eclipse.jdt.ui.search.ElementQuerySpecification -import org.eclipse.core.resources.ResourcesPlugin -import org.eclipse.core.resources.IFile +import org.eclipse.jdt.ui.search.PatternQuerySpecification import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.psi.KtElement interface KotlinAndJavaSearchable { val sourceElements: List @@ -29,7 +28,7 @@ class KotlinScopedQuerySpecification( override val sourceElements: List, override val searchScope: List, limitTo: Int, - description: String) : KotlinDummyQuerySpecification(EmptyJavaSearchScope, description, limitTo), + description: String) : KotlinDummyQuerySpecification(EmptyJavaSearchScope, description, limitTo), KotlinAndJavaSearchable, KotlinScoped class KotlinOnlyQuerySpecification( @@ -41,35 +40,37 @@ class KotlinOnlyQuerySpecification( // After passing this query specification to java, it will try to find some usages and to ensure that nothing will found // before KotlinQueryParticipant here is using dummy element '------------' abstract class KotlinDummyQuerySpecification( - searchScope: IJavaSearchScope, - description: String, - limitTo: Int = IJavaSearchConstants.REFERENCES) : PatternQuerySpecification( - "Kotlin Find References", - IJavaSearchConstants.CLASS, - true, - limitTo, - searchScope, - description) + searchScope: IJavaSearchScope, + description: String, + limitTo: Int = IJavaSearchConstants.REFERENCES +) : PatternQuerySpecification( + "Kotlin Find ${if (limitTo == IJavaSearchConstants.REFERENCES) "References" else if (limitTo == KotlinFindImplementationsInProjectAction.IMPLEMENTORS_LIMIT_TO) "Implementations" else "???"}", + IJavaSearchConstants.CLASS, + true, + limitTo, + searchScope, + description +) object EmptyJavaSearchScope : IJavaSearchScope { override fun setIncludesClasspaths(includesClasspaths: Boolean) { } - + override fun setIncludesBinaries(includesBinaries: Boolean) { } - + override fun enclosingProjectsAndJars(): Array { val base = ResourcesPlugin.getWorkspace().getRoot().getLocation() return ResourcesPlugin.getWorkspace().getRoot().getProjects() .map { it.getLocation().makeRelativeTo(base) } .toTypedArray() } - + override fun includesBinaries(): Boolean = false - + override fun includesClasspaths(): Boolean = false - + override fun encloses(resourcePath: String?): Boolean = false - + override fun encloses(element: IJavaElement?): Boolean = false -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/j2k/JavaToKotlinActionHandler.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/j2k/JavaToKotlinActionHandler.java index 3f8caacde..d7c634a46 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/j2k/JavaToKotlinActionHandler.java +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/j2k/JavaToKotlinActionHandler.java @@ -1,15 +1,9 @@ package org.jetbrains.kotlin.ui.commands.j2k; -import static org.eclipse.ui.ide.undo.WorkspaceUndoUtil.getUIInfoAdapter; - -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; @@ -17,14 +11,7 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; -import org.eclipse.jdt.core.IBuffer; -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.IPackageFragmentRoot; -import org.eclipse.jdt.core.ITypeRoot; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.*; import org.eclipse.jdt.internal.core.CompilationUnit; import org.eclipse.jdt.internal.core.DocumentAdapter; import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; @@ -57,10 +44,11 @@ import org.jetbrains.kotlin.ui.launch.KotlinRuntimeConfigurator; import org.jetbrains.kotlin.wizards.FileCreationOp; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.util.*; + +import static org.eclipse.ui.ide.undo.WorkspaceUndoUtil.getUIInfoAdapter; public class JavaToKotlinActionHandler extends AbstractHandler { @@ -170,7 +158,7 @@ private List collectCompilationUnits(@NotNull IPackageFragment private Pair> convertToKotlin(@NotNull Set compilationUnits, @NotNull Shell shell) { try { - List convertedFiles = new ArrayList(); + List convertedFiles = new ArrayList<>(); CompositeUndoableOperation compositeOperation = new CompositeUndoableOperation("Convert Java to Kotlin"); for (CompilationUnit compilationUnit : compilationUnits) { ConvertedKotlinData convertedFile = getConvertedFileData(compilationUnit, shell); @@ -194,10 +182,10 @@ private Pair> convertToKotlin(@NotNull Set PlatformUI.getWorkbench().getOperationSupport().getOperationHistory().execute( compositeOperation, null, getUIInfoAdapter(shell)); - return new Pair>(Status.OK_STATUS, convertedFiles); + return new Pair<>(Status.OK_STATUS, convertedFiles); } catch (ExecutionException e) { KotlinLogger.logError(e.getMessage(), null); - return new Pair>(new Status(IStatus.ERROR, Activator.Companion.getPLUGIN_ID(), e.getMessage()), Collections.emptyList()); + return new Pair<>(new Status(IStatus.ERROR, Activator.Companion.getPLUGIN_ID(), e.getMessage()), Collections.emptyList()); } } diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/debug/commands/KotlinStepIntoSelectionHandler.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/debug/commands/KotlinStepIntoSelectionHandler.kt index 372ca4895..78a93c467 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/debug/commands/KotlinStepIntoSelectionHandler.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/debug/commands/KotlinStepIntoSelectionHandler.kt @@ -41,10 +41,10 @@ import org.eclipse.debug.core.model.IThread import org.jetbrains.kotlin.core.log.KotlinLogger import org.eclipse.jdt.core.IType -public class KotlinStepIntoSelectionHandler : AbstractHandler() { +class KotlinStepIntoSelectionHandler : AbstractHandler() { override fun execute(event: ExecutionEvent): Any? { val editor = HandlerUtil.getActiveEditor(event) as KotlinFileEditor - val selection = editor.getEditorSite().getSelectionProvider().getSelection() + val selection = editor.editorSite.selectionProvider.selection if (selection is ITextSelection) { stepIntoSelection(editor, selection) } @@ -55,23 +55,20 @@ public class KotlinStepIntoSelectionHandler : AbstractHandler() { private fun stepIntoSelection(editor: KotlinFileEditor, selection: ITextSelection) { val frame = EvaluationContextManager.getEvaluationContext(editor) - if (frame == null || !frame.isSuspended()) return + if (frame == null || !frame.isSuspended) return - val psiElement = EditorUtil.getPsiElement(editor, selection.getOffset()) - if (psiElement == null) return - - val expression = getReferenceExpression(psiElement) - if (expression == null) return - - val sourceElements = createReferences(expression).resolveToSourceElements() + val psiElement = EditorUtil.getPsiElement(editor, selection.offset) ?: return + + val expression = getReferenceExpression(psiElement) ?: return + + val sourceElements = createReferences(expression).resolveToSourceElements(expression.containingKtFile) val javaElements = sourceElementsToLightElements(sourceElements) if (javaElements.size > 1) { KotlinLogger.logWarning("There are more than one java element for $sourceElements") return } - val element = javaElements.first() - val method = when (element) { + val method = when (val element = javaElements.first()) { is IMethod -> element is IType -> element.getMethod(element.elementName, emptyArray()) else -> null @@ -81,8 +78,8 @@ private fun stepIntoSelection(editor: KotlinFileEditor, selection: ITextSelectio } private fun stepIntoElement(method: IMethod, frame: IJavaStackFrame, selection: ITextSelection, editor: KotlinFileEditor) { - if (selection.getStartLine() + 1 == frame.getLineNumber()) { - val handler = StepIntoSelectionHandler(frame.getThread() as IJavaThread, frame, method) + if (selection.startLine + 1 == frame.lineNumber) { + val handler = StepIntoSelectionHandler(frame.thread as IJavaThread, frame, method) handler.step() } else { val refMethod = StepIntoSelectionUtils::class.java.getDeclaredMethod( @@ -92,7 +89,7 @@ private fun stepIntoElement(method: IMethod, frame: IJavaStackFrame, selection: ITextSelection::class.java, IThread::class.java, IMethod::class.java) - refMethod.setAccessible(true) - refMethod.invoke(null, editor, frame.getReceivingTypeName(), selection, frame.getThread(), method) + refMethod.isAccessible = true + refMethod.invoke(null, editor, frame.receivingTypeName, selection, frame.thread, method) } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/FileEditorConfiguration.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/FileEditorConfiguration.kt index 1bafbd6e5..addc38422 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/FileEditorConfiguration.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/FileEditorConfiguration.kt @@ -30,6 +30,7 @@ import org.eclipse.jface.text.reconciler.MonoReconciler import org.eclipse.jface.text.source.ISourceViewer import org.eclipse.swt.graphics.Color import org.jetbrains.kotlin.ui.editors.codeassist.KotlinCompletionProcessor +import org.jetbrains.kotlin.ui.editors.codeassist.KotlinContextInfoContentAssistProcessor class FileEditorConfiguration(colorManager: IColorManager, private val fileEditor: KotlinEditor, @@ -49,11 +50,13 @@ class FileEditorConfiguration(colorManager: IColorManager, override fun getAutoEditStrategies(sourceViewer: ISourceViewer, contentType: String) = arrayOf(KotlinAutoIndentStrategy(fileEditor)) - override fun getContentAssistant(sourceViewer: ISourceViewer): IContentAssistant? = ContentAssistant().apply { + override fun getContentAssistant(sourceViewer: ISourceViewer): IContentAssistant = ContentAssistant(true).apply { KotlinCompletionProcessor.createKotlinCompletionProcessors(fileEditor, this).forEach { addContentAssistProcessor(it, IDocument.DEFAULT_CONTENT_TYPE) } - + + addContentAssistProcessor(KotlinContextInfoContentAssistProcessor(fileEditor), IDocument.DEFAULT_CONTENT_TYPE) + val autoActivation = fPreferenceStore.getBoolean(PreferenceConstants.CODEASSIST_AUTOACTIVATION) enableAutoActivation(autoActivation) @@ -83,4 +86,4 @@ class FileEditorConfiguration(colorManager: IColorManager, fun getColor(store: IPreferenceStore, key: String, manager: IColorManager): Color { val rgb = PreferenceConverter.getColor(store, key) return manager.getColor(rgb) -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCommonEditor.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCommonEditor.kt index bfb8d2a0b..99f6e73cf 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCommonEditor.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCommonEditor.kt @@ -195,9 +195,9 @@ abstract class KotlinCommonEditor : CompilationUnitEditor(), KotlinEditor { override fun dispose() { colorManager.dispose() - if (kotlinSemanticHighlighter != null) { - kotlinReconcilingStrategy.removeListener(kotlinSemanticHighlighter!!) - kotlinSemanticHighlighter!!.uninstall() + kotlinSemanticHighlighter?.let { + kotlinReconcilingStrategy.removeListener(it) + it.uninstall() } kotlinReconcilingStrategy.removeListener(KotlinLineAnnotationsReconciler) diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCorrectionProcessor.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCorrectionProcessor.kt index d89fc07e5..ec13ed08d 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCorrectionProcessor.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCorrectionProcessor.kt @@ -27,9 +27,9 @@ import org.eclipse.swt.graphics.Image import org.eclipse.swt.graphics.Point import org.eclipse.ui.ide.IDE import org.eclipse.ui.texteditor.MarkerAnnotation +import org.jetbrains.kotlin.core.utils.getBindingContext import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.eclipse.ui.utils.LineEndUtil -import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.ui.editors.quickassist.KotlinQuickAssistProcessor import org.jetbrains.kotlin.ui.editors.quickfix.KotlinMarkerResolution import org.jetbrains.kotlin.ui.editors.quickfix.KotlinMarkerResolutionGenerator @@ -83,7 +83,7 @@ private class KotlinMarkerResolutionProposal( fun findDiagnosticsBy(invocationContext: IQuickAssistInvocationContext, editor: KotlinEditor): List { val offset = LineEndUtil.convertCrToDocumentOffset(editor.document, invocationContext.offset) return editor.parsedFile?.let { ktFile -> - getBindingContext(ktFile)?.diagnostics?.filter { + ktFile.getBindingContext().diagnostics.filter { val range = it.psiElement.textRange range.startOffset <= offset && offset <= range.endOffset } diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlink.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlink.java deleted file mode 100644 index 3f442c2be..000000000 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlink.java +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - *******************************************************************************/ -package org.jetbrains.kotlin.ui.editors; - -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.hyperlink.IHyperlink; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.ui.editors.navigation.KotlinOpenDeclarationAction; - -public class KotlinElementHyperlink implements IHyperlink { - - private static final String HYPERLINK_TEXT = "Open Kotlin Declaration"; - - private final KotlinOpenDeclarationAction openAction; - private final IRegion region; - - public KotlinElementHyperlink(@NotNull KotlinOpenDeclarationAction openAction, @NotNull IRegion region) { - this.openAction = openAction; - this.region = region; - } - - @Override - public IRegion getHyperlinkRegion() { - return region; - } - - @Override - public String getTypeLabel() { - return null; - } - - @Override - public String getHyperlinkText() { - return HYPERLINK_TEXT; - } - - @Override - public void open() { - openAction.run(); - } -} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlink.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlink.kt new file mode 100644 index 000000000..73ca168ca --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlink.kt @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.jetbrains.kotlin.ui.editors + +import org.eclipse.jface.text.IRegion +import org.eclipse.jface.text.hyperlink.IHyperlink +import org.jetbrains.kotlin.core.utils.getBindingContext +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.KtPropertyDelegate +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.ui.editors.codeassist.getParentOfType +import org.jetbrains.kotlin.ui.editors.navigation.KotlinOpenDeclarationAction +import org.jetbrains.kotlin.ui.editors.navigation.gotoElement + +class KTGenericHyperLink( + private val region: IRegion, + private val label: String, + private val editor: KotlinEditor, + private val targetDescriptor: DeclarationDescriptor, + private val fromElement: KtElement +) : + IHyperlink { + override fun getHyperlinkRegion(): IRegion = region + + override fun getTypeLabel(): String? = null + + override fun getHyperlinkText(): String = label + + override fun open() { + val tempPrj = editor.javaProject ?: return + gotoElement(targetDescriptor, fromElement, editor, tempPrj) + } + +} + +private const val HYPERLINK_TEXT = "Open Kotlin Declaration" diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlinkDetector.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlinkDetector.java deleted file mode 100644 index 7524d6742..000000000 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlinkDetector.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - *******************************************************************************/ -package org.jetbrains.kotlin.ui.editors; - -import org.eclipse.jdt.internal.ui.text.JavaWordFinder; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.ITextViewer; -import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector; -import org.eclipse.jface.text.hyperlink.IHyperlink; -import org.eclipse.ui.texteditor.ITextEditor; -import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil; -import org.jetbrains.kotlin.ui.editors.navigation.KotlinOpenDeclarationAction; - -public class KotlinElementHyperlinkDetector extends AbstractHyperlinkDetector { - - @Override - public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) { - ITextEditor textEditor = getAdapter(ITextEditor.class); - if (region == null || !(textEditor instanceof KotlinEditor)) { - return null; - } - KotlinEditor editor = (KotlinEditor) textEditor; - - IAction openAction = textEditor.getAction(KotlinOpenDeclarationAction.Companion.getOPEN_EDITOR_TEXT()); - if (!(openAction instanceof KotlinOpenDeclarationAction)) { - return null; - } - - int offset = region.getOffset(); - IRegion wordRegion = JavaWordFinder.findWord(textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput()), offset); - if (wordRegion == null || wordRegion.getLength() == 0) { - return null; - } - - if (EditorUtil.getReferenceExpression(editor, offset) == null) { - return null; - } - - return new IHyperlink[] { - new KotlinElementHyperlink((KotlinOpenDeclarationAction) openAction, wordRegion) - }; - } -} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlinkDetector.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlinkDetector.kt new file mode 100644 index 000000000..f6d275f34 --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinElementHyperlinkDetector.kt @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.jetbrains.kotlin.ui.editors + +import org.eclipse.jdt.internal.ui.text.JavaWordFinder +import org.eclipse.jface.text.IRegion +import org.eclipse.jface.text.ITextViewer +import org.eclipse.jface.text.Region +import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector +import org.eclipse.jface.text.hyperlink.IHyperlink +import org.eclipse.ui.texteditor.ITextEditor +import org.jetbrains.kotlin.core.references.createReferences +import org.jetbrains.kotlin.core.utils.getBindingContext +import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil +import org.jetbrains.kotlin.eclipse.ui.utils.LineEndUtil +import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtOperationReferenceExpression +import org.jetbrains.kotlin.psi.KtReferenceExpression +import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.ui.editors.navigation.KotlinOpenDeclarationAction + +@Suppress("unused") +class KotlinElementHyperlinkDetector : AbstractHyperlinkDetector() { + override fun detectHyperlinks( + textViewer: ITextViewer, + region: IRegion?, + canShowMultipleHyperlinks: Boolean + ): Array? { + val textEditor = getAdapter(ITextEditor::class.java) + if (region == null || textEditor !is KotlinEditor) return null + + val tempProject = textEditor.javaProject ?: return null + + val tempDocument = textEditor.documentProvider.getDocument(textEditor.editorInput) + + var wordRegion = JavaWordFinder.findWord(tempDocument, region.offset) + + var tempReferenceExpression: KtReferenceExpression? = null + if (wordRegion == null || wordRegion.length == 0) { + tempReferenceExpression = EditorUtil.getReferenceExpression(textEditor, region.offset) + if (tempReferenceExpression is KtOperationReferenceExpression) { + val tempOffset = + LineEndUtil.convertLfOffsetForMixedDocument(tempDocument, tempReferenceExpression.textOffset) + wordRegion = Region(tempOffset, tempReferenceExpression.textLength) + } else if (tempReferenceExpression is KtArrayAccessExpression) { + val tempOffset = + LineEndUtil.convertLfOffsetForMixedDocument(tempDocument, tempReferenceExpression.textOffset) + wordRegion = Region(tempOffset, tempReferenceExpression.textLength) + } else if (tempReferenceExpression is KtCallExpression) { + if (KotlinOpenDeclarationAction.getNavigationData(tempReferenceExpression, tempProject) != null) { + val tempOffset = + LineEndUtil.convertLfOffsetForMixedDocument(tempDocument, tempReferenceExpression.textOffset) + wordRegion = Region(tempOffset, tempReferenceExpression.textLength) + } + } + } + + val tempRenderer = DescriptorRenderer.SHORT_NAMES_IN_TYPES.withOptions { + modifiers = emptySet() + includeAdditionalModifiers = false + } + + val tempRef = tempReferenceExpression + ?: EditorUtil.getReferenceExpression(textEditor, region.offset) + ?: EditorUtil.getJetElement(textEditor, region.offset) + ?: return null + + val context = tempRef.getBindingContext() + val tempTargets = createReferences(tempRef) + .flatMap { it.getTargetDescriptors(context) } + + return tempTargets.map { + KTGenericHyperLink( + wordRegion, + tempRenderer.render(it), + textEditor, + it, + tempRef + ) + }.toTypedArray().takeIf { it.isNotEmpty() } + } +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/annotations/DiagnosticAnnotationUtil.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/annotations/DiagnosticAnnotationUtil.java index b64245594..8da29a55e 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/annotations/DiagnosticAnnotationUtil.java +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/annotations/DiagnosticAnnotationUtil.java @@ -16,13 +16,10 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui.editors.annotations; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiErrorElement; +import com.intellij.psi.PsiFile; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; @@ -49,10 +46,7 @@ import org.jetbrains.kotlin.resolve.AnalyzingUtils; import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiErrorElement; -import com.intellij.psi.PsiFile; +import java.util.*; public class DiagnosticAnnotationUtil { @@ -63,7 +57,7 @@ private DiagnosticAnnotationUtil() { @NotNull public Map> handleDiagnostics(@NotNull Diagnostics diagnostics) { - Map> annotations = new HashMap>(); + Map> annotations = new HashMap<>(); for (Diagnostic diagnostic : diagnostics) { if (diagnostic.getTextRanges().isEmpty()) { continue; @@ -78,13 +72,15 @@ public Map> handleDiagnostics(@NotNull Diagnos getFileForLocation(new Path(virtualFile.getPath())); if (!annotations.containsKey(curFile)) { - annotations.put(curFile, new ArrayList()); + annotations.put(curFile, new ArrayList<>()); } - + + if (curFile != null) { DiagnosticAnnotation annotation = createKotlinAnnotation(diagnostic, curFile); annotations.get(curFile).add(annotation); } - + } + return annotations; } @@ -101,7 +97,7 @@ public void addParsingDiagnosticAnnotations(@NotNull IFile file, @NotNull Map createParsingDiagnosticAnnotations(@NotNull IFile file) { KtFile jetFile = KotlinPsiManager.INSTANCE.getParsedFile(file); - List result = new ArrayList(); + List result = new ArrayList<>(); for (PsiErrorElement syntaxError : AnalyzingUtils.getSyntaxErrorRanges(jetFile)) { try { result.add(createKotlinAnnotation(syntaxError, file)); diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/CompletionElementType.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/CompletionElementType.kt new file mode 100644 index 000000000..a9e71093e --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/CompletionElementType.kt @@ -0,0 +1,34 @@ +package org.jetbrains.kotlin.ui.editors.codeassist + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension + +enum class CompletionElementType { + KFUNCTION_TOP, + KVARIABLE_TOP, + KFUNCTION_EXT, + KVARIABLE_EXT, + KFUNCTION, + KVARIABLE, + KCLASS_OBJECT, + UNKNOWN; + + companion object { + fun from(descriptor: DeclarationDescriptor) : CompletionElementType { + return when(descriptor) { + is ClassDescriptor, is TypeParameterDescriptor, is TypeAliasDescriptor -> KCLASS_OBJECT + is FunctionDescriptor -> when { + descriptor.isExtension -> KFUNCTION_EXT + descriptor.isTopLevelInPackage() -> KFUNCTION_TOP + else -> KFUNCTION + } + is VariableDescriptor -> when { + descriptor.isExtension -> KVARIABLE_EXT + descriptor.isTopLevelInPackage() -> KVARIABLE_TOP + else -> KVARIABLE + } + else -> UNKNOWN + } + } + } +} \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KeywordCompletion.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KeywordCompletion.kt index 2669e4688..cf8449cda 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KeywordCompletion.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KeywordCompletion.kt @@ -1,11 +1,7 @@ package org.jetbrains.kotlin.ui.editors.codeassist -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiComment -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiErrorElement -import com.intellij.psi.PsiWhiteSpace +import com.intellij.psi.* import com.intellij.psi.filters.ClassFilter import com.intellij.psi.filters.ElementFilter import com.intellij.psi.filters.NotFilter @@ -14,61 +10,24 @@ import com.intellij.psi.filters.position.PositionElementFilter import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.TokenSet import com.intellij.psi.util.PsiTreeUtil +import org.eclipse.jdt.core.IJavaProject +import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl +import org.jetbrains.kotlin.core.model.KotlinEnvironment +import org.jetbrains.kotlin.core.preferences.languageVersionSettings import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.ANNOTATION_CLASS -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.CLASS_ONLY -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.ENUM_CLASS -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.ENUM_ENTRY -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.FUNCTION -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.INTERFACE -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.MEMBER_FUNCTION -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.MEMBER_PROPERTY -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.OBJECT -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.PROPERTY -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.TOP_LEVEL_FUNCTION -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.TOP_LEVEL_PROPERTY -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.TYPE_PARAMETER -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.VALUE_PARAMETER +import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.* import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken -import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtBlockExpression -import org.jetbrains.kotlin.psi.KtCatchClause -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtClassBody -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtConstantExpression -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtDeclarationWithBody -import org.jetbrains.kotlin.psi.KtDeclarationWithInitializer -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtEnumEntry -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtLabeledExpression -import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry -import org.jetbrains.kotlin.psi.KtLoopExpression -import org.jetbrains.kotlin.psi.KtModifierList -import org.jetbrains.kotlin.psi.KtObjectDeclaration -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtPrimaryConstructor -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.KtPsiUtil -import org.jetbrains.kotlin.psi.KtTryExpression -import org.jetbrains.kotlin.psi.KtTypeParameter -import org.jetbrains.kotlin.psi.psiUtil.nextLeaf -import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf -import org.jetbrains.kotlin.psi.psiUtil.prevLeaf -import org.jetbrains.kotlin.psi.psiUtil.prevLeafs -import org.jetbrains.kotlin.psi.psiUtil.siblings +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.renderer.render -import org.jetbrains.kotlin.resolve.ModifierCheckerCore -import java.util.ArrayList -import com.intellij.psi.PsiFile -import org.jetbrains.kotlin.KtNodeTypes -import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl +import org.jetbrains.kotlin.resolve.deprecatedParentTargetMap +import org.jetbrains.kotlin.resolve.possibleParentTargetPredicateMap +import org.jetbrains.kotlin.resolve.possibleTargetMap open class KeywordLookupObject @@ -76,52 +35,55 @@ open class KeywordLookupObject object KeywordCompletion { private val ALL_KEYWORDS = (KEYWORDS.types + SOFT_KEYWORDS.types).map { it as KtKeywordToken } - private val KEYWORDS_TO_IGNORE_PREFIX = TokenSet.create(OVERRIDE_KEYWORD /* it's needed to complete overrides that should be work by member name too */) + private val KEYWORDS_TO_IGNORE_PREFIX = + TokenSet.create(OVERRIDE_KEYWORD /* it's needed to complete overrides that should be work by member name too */) private val COMPOUND_KEYWORDS = mapOf( - COMPANION_KEYWORD to OBJECT_KEYWORD, - ENUM_KEYWORD to CLASS_KEYWORD, - ANNOTATION_KEYWORD to CLASS_KEYWORD, - SEALED_KEYWORD to CLASS_KEYWORD, - LATEINIT_KEYWORD to VAR_KEYWORD + COMPANION_KEYWORD to OBJECT_KEYWORD, + ENUM_KEYWORD to CLASS_KEYWORD, + ANNOTATION_KEYWORD to CLASS_KEYWORD, + SEALED_KEYWORD to CLASS_KEYWORD, + LATEINIT_KEYWORD to VAR_KEYWORD ) private val KEYWORD_CONSTRUCTS = mapOf( - IF_KEYWORD to "fun foo() { if (caret)", - WHILE_KEYWORD to "fun foo() { while(caret)", - FOR_KEYWORD to "fun foo() { for(caret)", - TRY_KEYWORD to "fun foo() { try {\ncaret\n}", - CATCH_KEYWORD to "fun foo() { try {} catch (caret)", - FINALLY_KEYWORD to "fun foo() { try {\n}\nfinally{\ncaret\n}", - DO_KEYWORD to "fun foo() { do {\ncaret\n}", - INIT_KEYWORD to "class C { init {\ncaret\n}", - CONSTRUCTOR_KEYWORD to "class C { constructor(caret)", - COMPANION_KEYWORD to "class C { companion object {\ncaret\n}" + IF_KEYWORD to "fun foo() { if (caret)", + WHILE_KEYWORD to "fun foo() { while(caret)", + FOR_KEYWORD to "fun foo() { for(caret)", + TRY_KEYWORD to "fun foo() { try {\ncaret\n}", + CATCH_KEYWORD to "fun foo() { try {} catch (caret)", + FINALLY_KEYWORD to "fun foo() { try {\n}\nfinally{\ncaret\n}", + DO_KEYWORD to "fun foo() { do {\ncaret\n}", + INIT_KEYWORD to "class C { init {\ncaret\n}", + CONSTRUCTOR_KEYWORD to "class C { constructor(caret)", + COMPANION_KEYWORD to "class C { companion object {\ncaret\n}" ) - private val NO_SPACE_AFTER = listOf(THIS_KEYWORD, - SUPER_KEYWORD, - NULL_KEYWORD, - TRUE_KEYWORD, - FALSE_KEYWORD, - BREAK_KEYWORD, - CONTINUE_KEYWORD, - ELSE_KEYWORD, - WHEN_KEYWORD, - FILE_KEYWORD, - DYNAMIC_KEYWORD, - GET_KEYWORD, - SET_KEYWORD).map { it.value } + "companion object" - - fun complete(position: PsiElement, prefix: String, isJvmModule: Boolean, consumer: (String) -> Unit) { + private val NO_SPACE_AFTER = listOf( + THIS_KEYWORD, + SUPER_KEYWORD, + NULL_KEYWORD, + TRUE_KEYWORD, + FALSE_KEYWORD, + BREAK_KEYWORD, + CONTINUE_KEYWORD, + ELSE_KEYWORD, + WHEN_KEYWORD, + FILE_KEYWORD, + DYNAMIC_KEYWORD, + GET_KEYWORD, + SET_KEYWORD + ).map { it.value } + "companion object" + + fun complete(position: PsiElement, prefix: String, isJvmModule: Boolean, javaPrj: IJavaProject?, consumer: (String) -> Unit) { if (!GENERAL_FILTER.isAcceptable(position, position)) return - val parserFilter = buildFilter(position) + val parserFilter = buildFilter(position, javaPrj) for (keywordToken in ALL_KEYWORDS) { var keyword = keywordToken.value val nextKeyword = COMPOUND_KEYWORDS[keywordToken] - var applicableAsCompound = false + var applicableAsCompound = false if (nextKeyword != null) { fun PsiElement.isSpace() = this is PsiWhiteSpace && '\n' !in getText() @@ -154,20 +116,21 @@ object KeywordCompletion { } } - private val GENERAL_FILTER = NotFilter(OrFilter( + private val GENERAL_FILTER = NotFilter( + OrFilter( CommentFilter(), ParentFilter(ClassFilter(KtLiteralStringTemplateEntry::class.java)), ParentFilter(ClassFilter(KtConstantExpression::class.java)), LeftNeighbour(TextFilter(".")), LeftNeighbour(TextFilter("?.")) - )) + ) + ) private class CommentFilter() : ElementFilter { - override fun isAcceptable(element: Any?, context: PsiElement?) - = (element is PsiElement) && KtPsiUtil.isInComment(element) + override fun isAcceptable(element: Any?, context: PsiElement?) = + (element is PsiElement) && KtPsiUtil.isInComment(element) - override fun isClassAcceptable(hintClass: Class) - = true + override fun isClassAcceptable(hintClass: Class) = true } private class ParentFilter(filter: ElementFilter) : PositionElementFilter() { @@ -181,7 +144,7 @@ object KeywordCompletion { } } - private fun buildFilter(position: PsiElement): (KtKeywordToken) -> Boolean { + private fun buildFilter(position: PsiElement, javaPrj: IJavaProject?): (KtKeywordToken) -> Boolean { var parent = position.parent var prevParent = position while (parent != null) { @@ -190,25 +153,28 @@ object KeywordCompletion { var prefixText = "fun foo() { " if (prevParent is KtExpression) { // check that we are right after a try-expression without finally-block or after if-expression without else - val prevLeaf = prevParent.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment && it !is PsiErrorElement } + val prevLeaf = + prevParent.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment && it !is PsiErrorElement } if (prevLeaf != null) { - val isAfterThen = prevLeaf.goUpWhileIsLastChild().any { it.node.elementType == KtNodeTypes.THEN } + val isAfterThen = + prevLeaf.goUpWhileIsLastChild().any { it.node.elementType == KtNodeTypes.THEN } var isAfterTry = false var isAfterCatch = false - if (prevLeaf.node.elementType == KtTokens.RBRACE) { + if (prevLeaf.node.elementType == RBRACE) { val blockParent = (prevLeaf.parent as? KtBlockExpression)?.parent when (blockParent) { is KtTryExpression -> isAfterTry = true - is KtCatchClause -> { isAfterTry = true; isAfterCatch = true } + is KtCatchClause -> { + isAfterTry = true; isAfterCatch = true + } } } if (isAfterThen) { if (isAfterTry) { prefixText += "if (a)\n" - } - else { + } else { prefixText += "if (a) {}\n" } } @@ -220,18 +186,22 @@ object KeywordCompletion { } } - return buildFilterWithContext(prefixText, prevParent, position) - } - else { + return buildFilterWithContext(prefixText, prevParent, position, javaPrj) + } else { val lastExpression = prevParent - .siblings(forward = false, withItself = false) - .firstIsInstanceOrNull() + .siblings(forward = false, withItself = false) + .firstIsInstanceOrNull() if (lastExpression != null) { val contextAfterExpression = lastExpression - .siblings(forward = true, withItself = false) - .takeWhile { it != prevParent } - .joinToString { it.text } - return buildFilterWithContext(prefixText + "x" + contextAfterExpression, prevParent, position) + .siblings(forward = true, withItself = false) + .takeWhile { it != prevParent } + .joinToString { it.text } + return buildFilterWithContext( + prefixText + "x" + contextAfterExpression, + prevParent, + position, + javaPrj + ) } } } @@ -239,14 +209,14 @@ object KeywordCompletion { is KtDeclarationWithInitializer -> { val initializer = parent.initializer if (prevParent == initializer) { - return buildFilterWithContext("val v = ", initializer, position) + return buildFilterWithContext("val v = ", initializer, position, javaPrj) } } is KtParameter -> { val default = parent.defaultValue if (prevParent == default) { - return buildFilterWithContext("val v = ", default, position) + return buildFilterWithContext("val v = ", default, position, javaPrj) } } @@ -255,14 +225,13 @@ object KeywordCompletion { when (scope) { is KtClassOrObject -> { return if (parent is KtPrimaryConstructor) { - buildFilterWithReducedContext("class X ", parent, position) - } - else { - buildFilterWithReducedContext("class X { ", parent, position) + buildFilterWithReducedContext("class X ", parent, position, javaPrj) + } else { + buildFilterWithReducedContext("class X { ", parent, position, javaPrj) } } - is KtFile -> return buildFilterWithReducedContext("", parent, position) + is KtFile -> return buildFilterWithReducedContext("", parent, position, javaPrj) } } } @@ -272,7 +241,7 @@ object KeywordCompletion { parent = parent.parent } - return buildFilterWithReducedContext("", null, position) + return buildFilterWithReducedContext("", null, position, javaPrj) } private fun PsiElement.goUpWhileIsLastChild(): Sequence { @@ -286,25 +255,35 @@ object KeywordCompletion { } } - private fun buildFilterWithContext(prefixText: String, - contextElement: PsiElement, - position: PsiElement): (KtKeywordToken) -> Boolean { + private fun buildFilterWithContext( + prefixText: String, + contextElement: PsiElement, + position: PsiElement, + javaPrj: IJavaProject? + ): (KtKeywordToken) -> Boolean { val offset = position.getStartOffsetInAncestor(contextElement) val truncatedContext = contextElement.text!!.substring(0, offset) - return buildFilterByText(prefixText + truncatedContext, contextElement) + return buildFilterByText(prefixText + truncatedContext, contextElement, javaPrj) } - private fun buildFilterWithReducedContext(prefixText: String, - contextElement: PsiElement?, - position: PsiElement): (KtKeywordToken) -> Boolean { + private fun buildFilterWithReducedContext( + prefixText: String, + contextElement: PsiElement?, + position: PsiElement, + javaPrj: IJavaProject? + ): (KtKeywordToken) -> Boolean { val builder = StringBuilder() buildReducedContextBefore(builder, position, contextElement) - return buildFilterByText(prefixText + builder.toString(), position) + return buildFilterByText(prefixText + builder.toString(), position, javaPrj) } - private fun buildFilesWithKeywordApplication(keywordTokenType: KtKeywordToken, prefixText: String, psiFactory: KtPsiFactory): Sequence { + private fun buildFilesWithKeywordApplication( + keywordTokenType: KtKeywordToken, + prefixText: String, + psiFactory: KtPsiFactory + ): Sequence { return computeKeywordApplications(prefixText, keywordTokenType) - .map { application -> psiFactory.createFile(prefixText + application) } + .map { application -> psiFactory.createFile(prefixText + application) } } fun computeKeywordApplications(prefixText: String, keyword: KtKeywordToken): Sequence { @@ -319,7 +298,7 @@ object KeywordCompletion { } } - private fun buildFilterByText(prefixText: String, position: PsiElement): (KtKeywordToken) -> Boolean { + private fun buildFilterByText(prefixText: String, position: PsiElement, javaPrj: IJavaProject?): (KtKeywordToken) -> Boolean { val psiFactory = KtPsiFactory(position.project) fun isKeywordCorrectlyApplied(keywordTokenType: KtKeywordToken, file: KtFile): Boolean { val elementAt = file.findElementAt(prefixText.length)!! @@ -348,34 +327,58 @@ object KeywordCompletion { is KtEnumEntry -> listOf(ENUM_ENTRY) - is KtClassBody -> listOf(CLASS_ONLY, INTERFACE, OBJECT, ENUM_CLASS, ANNOTATION_CLASS, MEMBER_FUNCTION, MEMBER_PROPERTY, FUNCTION, PROPERTY) - - is KtFile -> listOf(CLASS_ONLY, INTERFACE, OBJECT, ENUM_CLASS, ANNOTATION_CLASS, TOP_LEVEL_FUNCTION, TOP_LEVEL_PROPERTY, FUNCTION, PROPERTY) + is KtClassBody -> listOf( + CLASS_ONLY, + INTERFACE, + OBJECT, + ENUM_CLASS, + ANNOTATION_CLASS, + MEMBER_FUNCTION, + MEMBER_PROPERTY, + FUNCTION, + PROPERTY + ) + + is KtFile -> listOf( + CLASS_ONLY, + INTERFACE, + OBJECT, + ENUM_CLASS, + ANNOTATION_CLASS, + TOP_LEVEL_FUNCTION, + TOP_LEVEL_PROPERTY, + FUNCTION, + PROPERTY + ) else -> null } - val modifierTargets = ModifierCheckerCore.possibleTargetMap[keywordTokenType] + val modifierTargets = possibleTargetMap[keywordTokenType] if (modifierTargets != null && possibleTargets != null && possibleTargets.none { it in modifierTargets }) return false val ownerDeclaration = container?.getParentOfType(strict = true) val parentTarget = when (ownerDeclaration) { - null -> KotlinTarget.FILE + null -> FILE is KtClass -> { when { - ownerDeclaration.isInterface() -> KotlinTarget.INTERFACE - ownerDeclaration.isEnum() -> KotlinTarget.ENUM_CLASS - ownerDeclaration.isAnnotation() -> KotlinTarget.ANNOTATION_CLASS - else -> KotlinTarget.CLASS_ONLY + ownerDeclaration.isInterface() -> INTERFACE + ownerDeclaration.isEnum() -> ENUM_CLASS + ownerDeclaration.isAnnotation() -> ANNOTATION_CLASS + else -> CLASS_ONLY } } - is KtObjectDeclaration -> if (ownerDeclaration.isObjectLiteral()) KotlinTarget.OBJECT_LITERAL else KotlinTarget.OBJECT + is KtObjectDeclaration -> if (ownerDeclaration.isObjectLiteral()) OBJECT_LITERAL else OBJECT else -> return true } - return ModifierCheckerCore.isPossibleParentTarget(keywordTokenType, parentTarget, LanguageVersionSettingsImpl.DEFAULT) + val tempLanguageVersionSettings = + javaPrj?.project?.let { KotlinEnvironment.getEnvironment(it).compilerProperties.languageVersionSettings } + ?: LanguageVersionSettingsImpl.DEFAULT + + return isPossibleParentTarget(keywordTokenType, parentTarget, tempLanguageVersionSettings) } } } @@ -386,6 +389,19 @@ object KeywordCompletion { } } + private fun isPossibleParentTarget( + modifier: KtModifierKeywordToken, + parentTarget: KotlinTarget, + languageVersionSettings: LanguageVersionSettings + ): Boolean { + val deprecatedTargets = deprecatedParentTargetMap[modifier] + if (deprecatedTargets != null) { + if (parentTarget in deprecatedTargets) return false + } + + return possibleParentTargetPredicateMap[modifier]?.isAllowed(parentTarget, languageVersionSettings) ?: true + } + private fun isErrorElementBefore(token: PsiElement): Boolean { for (leaf in token.prevLeafs) { if (leaf is PsiWhiteSpace || leaf is PsiComment) continue diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinCompletionProcessor.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinCompletionProcessor.kt index ea1c396bc..4f4f17f4b 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinCompletionProcessor.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinCompletionProcessor.kt @@ -1,19 +1,19 @@ /******************************************************************************* -* Copyright 2000-2014 JetBrains s.r.o. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -*******************************************************************************/ + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *******************************************************************************/ package org.jetbrains.kotlin.ui.editors.codeassist import com.intellij.psi.PsiElement @@ -26,17 +26,9 @@ import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider import org.eclipse.jface.text.IRegion import org.eclipse.jface.text.ITextViewer import org.eclipse.jface.text.Region -import org.eclipse.jface.text.contentassist.ContentAssistEvent -import org.eclipse.jface.text.contentassist.ContentAssistant -import org.eclipse.jface.text.contentassist.ICompletionListener -import org.eclipse.jface.text.contentassist.ICompletionProposal -import org.eclipse.jface.text.contentassist.ICompletionProposalSorter -import org.eclipse.jface.text.contentassist.IContentAssistProcessor -import org.eclipse.jface.text.contentassist.IContextInformation -import org.eclipse.jface.text.contentassist.IContextInformationValidator +import org.eclipse.jface.text.contentassist.* import org.eclipse.jface.text.templates.TemplateContext import org.eclipse.jface.text.templates.TemplateProposal -import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.eclipse.ui.utils.KotlinImageProvider import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver @@ -44,26 +36,35 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.renderer.DescriptorRenderer -import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.ui.editors.KotlinEditor import org.jetbrains.kotlin.ui.editors.completion.KotlinCompletionUtils import org.jetbrains.kotlin.ui.editors.templates.KotlinApplicableTemplateContext import org.jetbrains.kotlin.ui.editors.templates.KotlinDocumentTemplateContext import org.jetbrains.kotlin.ui.editors.templates.KotlinTemplateManager -import java.util.Comparator + +sealed class KotlinBasicCompletionProposal { + + abstract val descriptor: DeclarationDescriptor + + class Proposal(val proposal: KotlinCompletionProposal, override val descriptor: DeclarationDescriptor) : + KotlinBasicCompletionProposal() + + class Descriptor(override val descriptor: DeclarationDescriptor) : KotlinBasicCompletionProposal() +} abstract class KotlinCompletionProcessor( val editor: KotlinEditor, private val assistant: ContentAssistant?, - private val needSorting: Boolean) : IContentAssistProcessor, ICompletionListener { + private val needSorting: Boolean +) : IContentAssistProcessor, ICompletionListener { companion object { private val VALID_PROPOSALS_CHARS = charArrayOf() - private val VALID_INFO_CHARS = charArrayOf('(', ',') fun createKotlinCompletionProcessors( editor: KotlinEditor, assistant: ContentAssistant? = null, - needSorting: Boolean = false) = listOf( + needSorting: Boolean = false + ) = listOf( object : KotlinCompletionProcessor(editor, assistant, needSorting) { override fun computeProposals( identifierPart: String, @@ -88,7 +89,11 @@ abstract class KotlinCompletionProcessor( offset: Int ): List? = simpleNameExpression?.takeIf { identifierPart.isNotBlank() }?.let { - generateNonImportedCompletionProposals(identifierPart, simpleNameExpression, editor.javaProject!!) + generateNonImportedCompletionProposals( + identifierPart, + simpleNameExpression, + editor.javaProject!! + ) } }, object : KotlinCompletionProcessor(editor, assistant, needSorting) { @@ -117,31 +122,23 @@ abstract class KotlinCompletionProcessor( } ) } - - private val kotlinParameterValidator by lazy { - KotlinParameterListValidator(editor) - } - + override fun computeCompletionProposals(viewer: ITextViewer, offset: Int): Array { if (assistant != null) { configureContentAssistant(assistant) } - + val generatedProposals = generateCompletionProposals(viewer, offset).let { if (needSorting) sortProposals(it) else it } - + return generatedProposals.toTypedArray() } private fun sortProposals(proposals: List): List { - return proposals.sortedWith(object : Comparator { - override fun compare(o1: ICompletionProposal, o2: ICompletionProposal): Int { - return KotlinCompletionSorter.compare(o1, o2) - } - }) + return proposals.sortedWith(KotlinCompletionSorter::compare) } - + private fun configureContentAssistant(contentAssistant: ContentAssistant) { contentAssistant.setEmptyMessage("No Default Proposals") contentAssistant.setSorter(KotlinCompletionSorter) @@ -164,122 +161,150 @@ abstract class KotlinCompletionProcessor( ): List? protected fun generateNonImportedCompletionProposals( - identifierPart: String, - expression: KtSimpleNameExpression, - javaProject: IJavaProject): List { + identifierPart: String, + expression: KtSimpleNameExpression, + javaProject: IJavaProject + ): List { val file = editor.eclipseFile ?: return emptyList() val ktFile = editor.parsedFile ?: return emptyList() - return lookupNonImportedTypes(expression, identifierPart, ktFile, javaProject).map { + val tempTypeProposals = lookupNonImportedTypes(expression, identifierPart, ktFile, javaProject).map { val imageDescriptor = JavaElementImageProvider.getTypeImageDescriptor(false, false, it.modifiers, false) val image = JavaPlugin.getImageDescriptorRegistry().get(imageDescriptor) - KotlinImportCompletionProposal(it, image, file, identifierPart) + KotlinImportTypeCompletionProposal(it, image, file, identifierPart) } + + return tempTypeProposals } - protected fun generateBasicCompletionProposals(identifierPart: String, expression: KtSimpleNameExpression): Collection { - val file = editor.eclipseFile ?: - throw IllegalStateException("Failed to retrieve IFile from editor $editor") - + protected fun generateBasicCompletionProposals( + identifierPart: String, + expression: KtSimpleNameExpression + ): Collection { + val file = editor.eclipseFile ?: throw IllegalStateException("Failed to retrieve IFile from editor $editor") + val ktFile = editor.parsedFile ?: throw IllegalStateException("Failed to retrieve KTFile from editor $editor") + val nameFilter: (Name) -> Boolean = { name -> KotlinCompletionUtils.applicableNameFor(identifierPart, name) } - - return KotlinCompletionUtils.getReferenceVariants(expression, nameFilter, file, identifierPart) + + return KotlinCompletionUtils.getReferenceVariants( + expression, + nameFilter, + ktFile, + file, + identifierPart, + editor.javaProject!! + ) } - - protected fun collectCompletionProposals(descriptors: Collection, part: String): List { - return descriptors.map { descriptor -> - val completion = descriptor.name.identifier - val image = KotlinImageProvider.getImage(descriptor) - val presentableString = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(descriptor) - val containmentPresentableString = if (descriptor is ClassDescriptor) { - val fqName = DescriptorUtils.getFqName(descriptor) - if (fqName.isRoot) "" else fqName.parent().asString() - } else { - null + + protected fun collectCompletionProposals( + descriptors: Collection, + part: String + ): List { + return descriptors.map { basicDescriptor -> + when (basicDescriptor) { + is KotlinBasicCompletionProposal.Descriptor -> { + val descriptor = basicDescriptor.descriptor + val completion = descriptor.name.identifier + val image = KotlinImageProvider.getImage(descriptor) + + val tempRenderer = DescriptorRenderer.SHORT_NAMES_IN_TYPES.withOptions { + modifiers = emptySet() + includeAdditionalModifiers = false + } + + val presentableString = tempRenderer.render(descriptor) + val containmentPresentableString = null + + val proposal = KotlinCompletionProposal( + completion, + image, + presentableString, + containmentPresentableString, + null, + completion, + part, + CompletionElementType.from(descriptor) + ) + withKotlinInsertHandler(descriptor, proposal) + } + is KotlinBasicCompletionProposal.Proposal -> basicDescriptor.proposal } - - val proposal = KotlinCompletionProposal( - completion, - image, - presentableString, - containmentPresentableString, - null, - completion, - part) - - withKotlinInsertHandler(descriptor, proposal, part) } } - + protected fun generateTemplateProposals( - psiFile: PsiFile, viewer: ITextViewer, offset: Int, identifierPart: String): List { - - val contextTypeIds = KotlinApplicableTemplateContext.getApplicableContextTypeIds(viewer, psiFile, offset - identifierPart.length) + psiFile: PsiFile, viewer: ITextViewer, offset: Int, identifierPart: String + ): List { + + val contextTypeIds = + KotlinApplicableTemplateContext.getApplicableContextTypeIds(viewer, psiFile, offset - identifierPart.length) val region = Region(offset - identifierPart.length, identifierPart.length) - + val templateIcon = JavaPluginImages.get(JavaPluginImages.IMG_OBJS_TEMPLATE) val templates = KotlinApplicableTemplateContext.getTemplatesByContextTypeIds(contextTypeIds) - + return templates - .filter { it.name.startsWith(identifierPart) } - .map { - val templateContext = createTemplateContext(region, it.contextTypeId) - TemplateProposal(it, templateContext, region, templateIcon) - } - + .filter { it.name.startsWith(identifierPart) } + .map { + val templateContext = createTemplateContext(region, it.contextTypeId) + TemplateProposal(it, templateContext, region, templateIcon) + } + } - + private fun createTemplateContext(region: IRegion, contextTypeID: String): TemplateContext { return KotlinDocumentTemplateContext( - KotlinTemplateManager.INSTANCE.contextTypeRegistry.getContextType(contextTypeID), - editor, region.offset, region.length + KotlinTemplateManager.INSTANCE.contextTypeRegistry.getContextType(contextTypeID), + editor, region.offset, region.length ) } - - protected fun generateKeywordProposals(identifierPart: String, expression: PsiElement): List { - val callTypeAndReceiver = if (expression is KtSimpleNameExpression) CallTypeAndReceiver.detect(expression) else null - + + protected fun generateKeywordProposals( + identifierPart: String, + expression: PsiElement + ): List { + val callTypeAndReceiver = + if (expression is KtSimpleNameExpression) CallTypeAndReceiver.detect(expression) else null + return arrayListOf().apply { - KeywordCompletion.complete(expression, identifierPart, true) { keywordProposal -> + KeywordCompletion.complete(expression, identifierPart, true, editor.javaProject) { keywordProposal -> if (!KotlinCompletionUtils.applicableNameFor(identifierPart, keywordProposal)) return@complete - + when (keywordProposal) { "break", "continue" -> { if (expression is KtSimpleNameExpression) { addAll(breakOrContinueExpressionItems(expression, keywordProposal)) } - } - + } + "class" -> { if (callTypeAndReceiver !is CallTypeAndReceiver.CALLABLE_REFERENCE) { add(keywordProposal) } } - + "this", "return" -> { if (expression is KtExpression) { add(keywordProposal) } } - + else -> add(keywordProposal) } } }.map { KotlinKeywordCompletionProposal(it, identifierPart) } } - override fun computeContextInformation(viewer: ITextViewer?, offset: Int): Array { - return KotlinFunctionParameterInfoAssist.computeContextInformation(editor, offset) - } + override fun computeContextInformation(viewer: ITextViewer?, offset: Int): Array = emptyArray() override fun getCompletionProposalAutoActivationCharacters(): CharArray = VALID_PROPOSALS_CHARS - override fun getContextInformationAutoActivationCharacters(): CharArray = VALID_INFO_CHARS + override fun getContextInformationAutoActivationCharacters(): CharArray = charArrayOf() override fun getErrorMessage(): String? = "" - override fun getContextInformationValidator(): IContextInformationValidator = kotlinParameterValidator + override fun getContextInformationValidator() = null override fun assistSessionStarted(event: ContentAssistEvent?) { } @@ -287,26 +312,34 @@ abstract class KotlinCompletionProcessor( override fun assistSessionEnded(event: ContentAssistEvent?) { } - override fun selectionChanged(proposal: ICompletionProposal?, smartToggle: Boolean) { } + override fun selectionChanged(proposal: ICompletionProposal?, smartToggle: Boolean) {} } private object KotlinCompletionSorter : ICompletionProposalSorter { override fun compare(p1: ICompletionProposal, p2: ICompletionProposal): Int { - val relevance2 = p2.relevance() - val relevance1 = p1.relevance() - - return when { + + // simple and lazy hashing to make relevance more accurate. + val relevance2 = ((p2.relevance() * p2.typeRelevance()) + (p2.typeRelevance() / 2)) + val relevance1 = ((p1.relevance() * p1.typeRelevance()) + (p1.typeRelevance() / 2)) + return when { relevance2 > relevance1 -> 1 relevance2 < relevance1 -> -1 - else -> p1.sortString().compareTo(p2.sortString(), ignoreCase = true) - } + else -> p1.sortString().compareTo(p2.sortString(), ignoreCase = true) + } } - - private fun ICompletionProposal.sortString(): String { - return if (this is KotlinCompletionProposal) this.replacementString else this.displayString + + private fun ICompletionProposal.sortString(): String = + if (this is KotlinCompletionProposal) replacementString else displayString + + private fun ICompletionProposal.relevance(): Int = (this as? KotlinRelevanceCompletionProposal)?.getRelevance() ?: 0 + + private fun ICompletionProposal.typeRelevance(): Int { + return when (this) { + is KotlinKeywordCompletionProposal -> 0 + is KotlinImportTypeCompletionProposal -> 1 + is TemplateProposal -> 2 + is KotlinTypedCompletionProposal -> 3 + type.ordinal + else -> 4 + } } - - private fun ICompletionProposal.relevance(): Int { - return if (this is KotlinCompletionProposal) this.getRelevance() else 0 - } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinCompletionProposal.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinCompletionProposal.kt index 7df4f373a..65980dbbd 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinCompletionProposal.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinCompletionProposal.kt @@ -1,19 +1,19 @@ /******************************************************************************* -* Copyright 2000-2016 JetBrains s.r.o. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -*******************************************************************************/ + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *******************************************************************************/ package org.jetbrains.kotlin.ui.editors.codeassist import org.eclipse.core.resources.IFile @@ -31,36 +31,44 @@ import org.eclipse.swt.graphics.Image import org.eclipse.swt.graphics.Point import org.jetbrains.kotlin.builtins.isExtensionFunctionType import org.jetbrains.kotlin.builtins.isFunctionType -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.core.imports.FunctionCandidate +import org.jetbrains.kotlin.core.imports.TypeCandidate +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.calls.util.getValueParametersCountFromFunctionType +import org.jetbrains.kotlin.ui.editors.codeassist.CaretPosition.AFTER_BRACKETS +import org.jetbrains.kotlin.ui.editors.codeassist.CaretPosition.IN_BRACKETS import org.jetbrains.kotlin.ui.editors.completion.KotlinCompletionUtils import org.jetbrains.kotlin.ui.editors.quickfix.placeImports -import org.jetbrains.kotlin.core.imports.TypeCandidate -public fun withKotlinInsertHandler( - descriptor: DeclarationDescriptor, - proposal: KotlinCompletionProposal, - identifierPart: String): KotlinCompletionProposal { +fun withKotlinInsertHandler( + descriptor: DeclarationDescriptor, + proposal: KotlinCompletionProposal +): ICompletionProposal { return when (descriptor) { is FunctionDescriptor -> { - val parameters = descriptor.getValueParameters() + val parameters = descriptor.valueParameters when (parameters.size) { - 0 -> KotlinFunctionCompletionProposal(proposal, CaretPosition.AFTER_BRACKETS, false, identifierPart) + 0 -> KotlinFunctionCompletionProposal(proposal, AFTER_BRACKETS, false) 1 -> { - val parameterType = parameters.single().getType() + val parameter = parameters.single() + val parameterType = parameter.type if (parameterType.isFunctionType || parameterType.isExtensionFunctionType) { val parameterCount = getValueParametersCountFromFunctionType(parameterType) - if (parameterCount <= 1) { - // otherwise additional item with lambda template is to be added - return KotlinFunctionCompletionProposal(proposal, CaretPosition.IN_BRACKETS, true, identifierPart) + return if (parameterCount <= 1) { + KotlinFunctionCompletionProposal(proposal, IN_BRACKETS, true) + } else { + val tempParamNames = getLambdaParamNames(parameter) + KotlinFunctionCompletionProposal(proposal, IN_BRACKETS, true, tempParamNames) } } - KotlinFunctionCompletionProposal(proposal, CaretPosition.IN_BRACKETS, false, identifierPart) + KotlinFunctionCompletionProposal(proposal, IN_BRACKETS, false) } - else -> KotlinFunctionCompletionProposal(proposal, CaretPosition.IN_BRACKETS, false, identifierPart) + else -> KotlinFunctionCompletionProposal(proposal, IN_BRACKETS, false) } } @@ -68,6 +76,30 @@ public fun withKotlinInsertHandler( } } +private fun getLambdaParamNames(parameter: ValueParameterDescriptor): String { + val typeCharMap = mutableMapOf() + fun Char.nextParamName(): String { + val tempChar = lowercaseChar() + val tempCurrentNum = typeCharMap[tempChar] + return if (tempCurrentNum == null) { + typeCharMap[tempChar] = 2 + "$tempChar" + } else { + typeCharMap[tempChar] = tempCurrentNum + 1 + "$tempChar$tempCurrentNum" + } + } + + val tempParamNames = + parameter.type.arguments.dropLast(1).joinToString(", ", postfix = " -> ") { + val tempAnnotation = + it.type.annotations.findAnnotation(FqName(ParameterName::class.qualifiedName!!)) + tempAnnotation?.allValueArguments?.get(Name.identifier(ParameterName::name.name)) + ?.value?.toString() ?: it.type.toString().first().nextParamName() + } + return tempParamNames +} + fun getIdentifierInfo(document: IDocument, offset: Int): IdentifierInfo { val text = document.get() var identStartOffset = offset @@ -79,37 +111,45 @@ fun getIdentifierInfo(document: IDocument, offset: Int): IdentifierInfo { data class IdentifierInfo(val identifierPart: String, val identifierStart: Int) -open class KotlinCompletionProposal( - val replacementString: String, - val img: Image?, - val presentableString: String, - val containmentPresentableString: String? = null, - val information: IContextInformation? = null, - val additionalInfo: String? = null, - identifierPart: String) : ICompletionProposal, ICompletionProposalExtension2, ICompletionProposalExtension6 { - - var selectedOffset = -1 - - private @Volatile var identifierPart = identifierPart - - open fun getRelevance(): Int { +interface KotlinRelevanceCompletionProposal { + fun getRelevance(): Int +} + +interface KotlinTypedCompletionProposal { + + val type: CompletionElementType +} + +open class KotlinCompletionProposal constructor( + val replacementString: String, + private val img: Image?, + private val presentableString: String, + private val containmentPresentableString: String? = null, + private val information: IContextInformation? = null, + private val additionalInfo: String? = null, + @Volatile private var identifierPart: String, + override val type: CompletionElementType = CompletionElementType.UNKNOWN +) : ICompletionProposal, ICompletionProposalExtension2, ICompletionProposalExtension6, KotlinTypedCompletionProposal, KotlinRelevanceCompletionProposal { + + private var selectedOffset = -1 + override fun getRelevance(): Int { return computeCaseMatchingRelevance(identifierPart.toCharArray(), replacementString.toCharArray()) } - + override fun apply(viewer: ITextViewer, trigger: Char, stateMask: Int, offset: Int) { val document = viewer.document val (identifierPart, identifierStart) = getIdentifierInfo(document, offset) document.replace(identifierStart, offset - identifierStart, replacementString) - + selectedOffset = offset - identifierPart.length + replacementString.length } - + override fun validate(document: IDocument, offset: Int, event: DocumentEvent): Boolean { val identiferInfo = getIdentifierInfo(document, offset) identifierPart = identiferInfo.identifierPart return KotlinCompletionUtils.applicableNameFor(identiferInfo.identifierPart, replacementString) } - + override fun getSelection(document: IDocument): Point? = Point(selectedOffset, 0) override fun getAdditionalProposalInfo(): String? = additionalInfo @@ -119,60 +159,95 @@ open class KotlinCompletionProposal( override fun getImage(): Image? = img override fun getContextInformation(): IContextInformation? = information - + override fun getStyledDisplayString(): StyledString { return if (containmentPresentableString != null) { - createStyledString(getDisplayString(), containmentPresentableString) + createStyledString(displayString, containmentPresentableString) } else { - StyledString(getDisplayString()) + StyledString(displayString) } } - + override fun selected(viewer: ITextViewer?, smartToggle: Boolean) { } - + override fun unselected(viewer: ITextViewer?) { } - - override final fun apply(document: IDocument) { + + final override fun apply(document: IDocument) { // should not be called } } -class KotlinImportCompletionProposal(val typeName: TypeNameMatch, image: Image?, val file: IFile, identifierPart: String) : - KotlinCompletionProposal( - typeName.simpleTypeName, - image, - typeName.simpleTypeName, - typeName.packageName, - identifierPart = identifierPart) { +class KotlinImportTypeCompletionProposal( + private val typeName: TypeNameMatch, + image: Image?, + val file: IFile, + identifierPart: String +) : + KotlinCompletionProposal( + typeName.simpleTypeName, + image, + typeName.simpleTypeName, + typeName.fullyQualifiedName.removeSuffix(".${typeName.simpleTypeName}"), + identifierPart = identifierPart + ) { + + private var importShift = -1 - var importShift = -1 - override fun apply(viewer: ITextViewer, trigger: Char, stateMask: Int, offset: Int) { super.apply(viewer, trigger, stateMask, offset) importShift = placeImports(listOf(TypeCandidate(typeName)), file, viewer.document) } - + override fun getSelection(document: IDocument): Point? { val selection = super.getSelection(document) return if (importShift > 0 && selection != null) Point(selection.x + importShift, 0) else selection } - + override fun getRelevance(): Int { return -1 } } +class KotlinImportCallableCompletionProposal( + val descriptor: CallableDescriptor, + image: Image?, + val file: IFile, + identifierPart: String +) : + KotlinCompletionProposal( + "${descriptor.name.identifier}${if (descriptor is PropertyDescriptor) "" else "()"}", + image, + DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor), + null, + identifierPart = identifierPart + ) { + + private var importShift = -1 + + override fun apply(viewer: ITextViewer, trigger: Char, stateMask: Int, offset: Int) { + super.apply(viewer, trigger, stateMask, offset) + importShift = placeImports(listOf(FunctionCandidate(descriptor)), file, viewer.document) + } + + override fun getSelection(document: IDocument): Point? { + val selection = super.getSelection(document) + return if (importShift > 0 && selection != null) Point(selection.x + importShift, 0) else selection + } + + override fun getRelevance(): Int = -1 +} + class KotlinKeywordCompletionProposal(keyword: String, identifierPart: String) : - KotlinCompletionProposal(keyword, null, keyword, identifierPart = identifierPart) + KotlinCompletionProposal(keyword, null, keyword, identifierPart = identifierPart) private fun createStyledString(simpleName: String, containingDeclaration: String): StyledString { - return StyledString().apply { + return StyledString().apply { append(simpleName) if (containingDeclaration.isNotBlank()) { append(JavaElementLabels.CONCAT_STRING, StyledString.QUALIFIER_STYLER) append(containingDeclaration, StyledString.QUALIFIER_STYLER) } } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinContextInfoContentAssistProcessor.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinContextInfoContentAssistProcessor.kt new file mode 100644 index 000000000..0196815e8 --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinContextInfoContentAssistProcessor.kt @@ -0,0 +1,32 @@ +package org.jetbrains.kotlin.ui.editors.codeassist + +import org.eclipse.jface.text.ITextViewer +import org.eclipse.jface.text.contentassist.ICompletionProposal +import org.eclipse.jface.text.contentassist.IContentAssistProcessor +import org.eclipse.jface.text.contentassist.IContextInformation +import org.jetbrains.kotlin.ui.editors.KotlinEditor + +class KotlinContextInfoContentAssistProcessor(private val editor: KotlinEditor) : IContentAssistProcessor { + + private val kotlinParameterValidator by lazy { + KotlinParameterListValidator(editor) + } + + override fun computeCompletionProposals(p0: ITextViewer?, p1: Int): Array = emptyArray() + + override fun computeContextInformation(p0: ITextViewer?, offset: Int): Array { + return KotlinFunctionParameterInfoAssist.computeContextInformation(editor, offset) + } + + override fun getCompletionProposalAutoActivationCharacters() = charArrayOf() + + override fun getContextInformationAutoActivationCharacters() = VALID_INFO_CHARS + + override fun getErrorMessage() = "" + + override fun getContextInformationValidator() = kotlinParameterValidator + + companion object { + private val VALID_INFO_CHARS = charArrayOf('(', ',') + } +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinFunctionCompletionProposal.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinFunctionCompletionProposal.kt index a22d483ba..00bf17d64 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinFunctionCompletionProposal.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinFunctionCompletionProposal.kt @@ -1,118 +1,107 @@ /******************************************************************************* -* Copyright 2000-2016 JetBrains s.r.o. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -*******************************************************************************/ + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *******************************************************************************/ package org.jetbrains.kotlin.ui.editors.codeassist -import org.eclipse.jface.text.contentassist.ICompletionProposal -import org.eclipse.jface.text.contentassist.ICompletionProposalExtension import org.eclipse.jface.text.IDocument -import org.jetbrains.kotlin.eclipse.ui.utils.LineEndUtil -import com.intellij.psi.util.PsiTreeUtil -import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.ui.editors.KotlinFileEditor -import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2 import org.eclipse.jface.text.ITextViewer -import org.eclipse.jface.text.DocumentEvent -import org.eclipse.jface.text.TextSelection -import org.eclipse.jface.text.Position +import org.eclipse.jface.text.contentassist.ICompletionProposal +import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2 +import org.eclipse.jface.text.contentassist.ICompletionProposalExtension6 import org.eclipse.swt.graphics.Point -public enum class CaretPosition { +enum class CaretPosition { IN_BRACKETS, AFTER_BRACKETS } -public class KotlinFunctionCompletionProposal( - proposal: KotlinCompletionProposal, - val caretPosition: CaretPosition, - val hasLambda: Boolean, - identifierPart: String) : - KotlinCompletionProposal( - proposal.replacementString, - proposal.img, - proposal.presentableString, - identifierPart = identifierPart) { - +class KotlinFunctionCompletionProposal( + private val proposal: KotlinCompletionProposal, + private val caretPosition: CaretPosition, + private val hasLambda: Boolean, + private val lambdaParamNames: String = "" +) : ICompletionProposal by proposal, ICompletionProposalExtension2 by proposal, + ICompletionProposalExtension6 by proposal, KotlinTypedCompletionProposal by proposal, + KotlinRelevanceCompletionProposal by proposal { + init { if (caretPosition == CaretPosition.AFTER_BRACKETS && hasLambda) { throw IllegalArgumentException("CaretPosition.AFTER_BRACKETS with lambdaInfo != null combination is not supported") } } - + override fun apply(viewer: ITextViewer, trigger: Char, stateMask: Int, offset: Int) { - super.apply(viewer, trigger, stateMask, offset) - - addBrackets(viewer, trigger, super.getSelection(viewer.getDocument())!!.x) + proposal.apply(viewer, trigger, stateMask, offset) + + addBrackets(viewer, trigger, proposal.getSelection(viewer.document)!!.x) if (trigger == '.') { - val closeBracketOffset = viewer.getTextWidget().getCaretOffset() - viewer.getDocument().replace(closeBracketOffset, 0, trigger.toString()) - viewer.getTextWidget().setCaretOffset(closeBracketOffset + 1) + val closeBracketOffset = viewer.textWidget.caretOffset + viewer.document.replace(closeBracketOffset, 0, trigger.toString()) + viewer.textWidget.caretOffset = closeBracketOffset + 1 } } - + override fun getSelection(document: IDocument): Point? = null - - + + private fun addBrackets(viewer: ITextViewer, completionChar: Char, completionOffset: Int) { - val document = viewer.getDocument() + val document = viewer.document val braces = hasLambda && completionChar != '(' - + val openingBracket = if (braces) '{' else '(' val closingBracket = if (braces) '}' else ')' - + var openingBracketOffset = indexOfSkippingSpace(document, openingBracket, completionOffset) var inBracketsShift = 0 if (openingBracketOffset == -1) { if (braces) { - document.replace(completionOffset, 0, " { }") + document.replace(completionOffset, 0, " { $lambdaParamNames }") inBracketsShift = 1 - } - else { + } else { document.replace(completionOffset, 0, "()") } } - + openingBracketOffset = indexOfSkippingSpace(document, openingBracket, completionOffset) assert(openingBracketOffset != -1) { "If there wasn't open bracket it should already have been inserted" } - + val closeBracketOffset = indexOfSkippingSpace(document, closingBracket, openingBracketOffset + 1) - + if (shouldPlaceCaretInBrackets(completionChar) || closeBracketOffset == -1) { viewer.setSelectedRange(openingBracketOffset + 1 + inBracketsShift, 0) - } - else { + } else { viewer.setSelectedRange(closeBracketOffset + 1, 0) } } - - private fun indexOfSkippingSpace(document: IDocument, ch : Char, startIndex : Int) : Int { + + private fun indexOfSkippingSpace(document: IDocument, ch: Char, startIndex: Int): Int { val text = document.get() - for (i in startIndex..text.length - 1) { + for (i in startIndex until text.length) { val currentChar = text[i] if (ch == currentChar) return i if (currentChar != ' ' && currentChar != '\t') return -1 } return -1 } - + private fun shouldPlaceCaretInBrackets(completionChar: Char): Boolean { - return when { - completionChar == '.' -> false - completionChar == '(' -> true + return when (completionChar) { + '.' -> false + '(' -> true else -> caretPosition == CaretPosition.IN_BRACKETS } } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinFunctionParameterInfoAssist.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinFunctionParameterInfoAssist.kt index 31883c6bd..dd6502e17 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinFunctionParameterInfoAssist.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinFunctionParameterInfoAssist.kt @@ -16,53 +16,55 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui.editors.codeassist -import org.jetbrains.kotlin.ui.editors.KotlinEditor -import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.psi.KtValueArgumentList import org.eclipse.jface.text.contentassist.IContextInformation -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.psi.KtCallElement -import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression -import org.jetbrains.kotlin.ui.editors.completion.KotlinCompletionUtils -import org.jetbrains.kotlin.ui.editors.KotlinFileEditor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.eclipse.swt.graphics.Image -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.core.resolve.EclipseDescriptorUtils +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil import org.jetbrains.kotlin.eclipse.ui.utils.KotlinImageProvider import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtCallElement +import org.jetbrains.kotlin.psi.KtParameter +import org.jetbrains.kotlin.psi.KtSimpleNameExpression +import org.jetbrains.kotlin.psi.KtValueArgumentList +import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression +import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue -import org.jetbrains.kotlin.core.resolve.EclipseDescriptorUtils -import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.resolve.source.KotlinSourceElement -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.core.references.getReferenceExpression -import org.jetbrains.kotlin.core.references.createReferences import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.ui.editors.KotlinEditor +import org.jetbrains.kotlin.ui.editors.completion.KotlinCompletionUtils + +object KotlinFunctionParameterInfoAssist { + fun computeContextInformation(editor: KotlinEditor, offset: Int): Array { + val file = editor.eclipseFile ?: throw IllegalStateException("Failed to retrieve IFile from editor $editor") + val ktFile = editor.parsedFile ?: throw IllegalStateException("Failed to retrieve KTFile from editor $editor") + val javaProject = editor.javaProject ?: throw IllegalStateException("Failed to retrieve JavaProject from editor $editor") + + val expression = getCallSimpleNameExpression(editor, offset) ?: return emptyArray() -public object KotlinFunctionParameterInfoAssist { - public fun computeContextInformation(editor: KotlinEditor, offset: Int): Array { - val expression = getCallSimpleNameExpression(editor, offset) - if (expression == null) return emptyArray() - val referencedName = expression.getReferencedName() val nameFilter: (Name) -> Boolean = { name -> name.asString() == referencedName } - val variants = KotlinCompletionUtils.getReferenceVariants(expression, nameFilter, editor.eclipseFile!!, null) + val variants = KotlinCompletionUtils.getReferenceVariants( + expression, + nameFilter, + ktFile, + file, + referencedName, + javaProject + ) - return variants + return variants.map { it.descriptor } .flatMap { when (it) { is FunctionDescriptor -> listOf(it) - is ClassDescriptor -> it.getConstructors() + is ClassDescriptor -> it.constructors else -> emptyList() } } - .filter { it.getValueParameters().isNotEmpty() } + .filter { it.valueParameters.isNotEmpty() } .map { KotlinFunctionParameterContextInformation(it) } .toTypedArray() } @@ -70,19 +72,20 @@ public object KotlinFunctionParameterInfoAssist { fun getCallSimpleNameExpression(editor: KotlinEditor, offset: Int): KtSimpleNameExpression? { val psiElement = EditorUtil.getPsiElement(editor, offset) - val argumentList = PsiTreeUtil.getParentOfType(psiElement, KtValueArgumentList::class.java) - if (argumentList == null) return null - - val argumentListParent = argumentList.getParent() + val argumentList = PsiTreeUtil.getParentOfType(psiElement, KtValueArgumentList::class.java) ?: return null + + val argumentListParent = argumentList.parent return if (argumentListParent is KtCallElement) argumentListParent.getCallNameExpression() else null } -public class KotlinFunctionParameterContextInformation(descriptor: FunctionDescriptor) : IContextInformation { - val displayString = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(descriptor) - val renderedParameters = descriptor.getValueParameters().map { renderParameter(it) } - val informationString = renderedParameters.joinToString(", ") - val displayImage = KotlinImageProvider.getImage(descriptor) - val name = if (descriptor is ConstructorDescriptor) descriptor.getContainingDeclaration().getName() else descriptor.getName() +class KotlinFunctionParameterContextInformation(descriptor: FunctionDescriptor) : IContextInformation { + private val displayString = DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.withOptions { + this.withDefinedIn = false + }.render(descriptor) + val renderedParameters = descriptor.valueParameters.map { renderParameter(it) } + private val informationString = renderedParameters.joinToString(", ") + private val displayImage = KotlinImageProvider.getImage(descriptor) + val name = if (descriptor is ConstructorDescriptor) descriptor.containingDeclaration.name else descriptor.name override fun getContextDisplayString(): String = displayString @@ -94,7 +97,7 @@ public class KotlinFunctionParameterContextInformation(descriptor: FunctionDescr val result = StringBuilder() if (parameter.varargElementType != null) result.append("vararg ") - result.append(parameter.getName()) + result.append(parameter.name) .append(": ") .append(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(getActualParameterType(parameter))) @@ -111,7 +114,7 @@ public class KotlinFunctionParameterContextInformation(descriptor: FunctionDescr private fun getDefaultExpressionString(parameterDeclaration: SourceElement): String { val parameterText: String? = if (parameterDeclaration is KotlinSourceElement) { val parameter = parameterDeclaration.psi - (parameter as? KtParameter)?.getDefaultValue()?.getText() + (parameter as? KtParameter)?.defaultValue?.text } else { null } @@ -120,6 +123,6 @@ public class KotlinFunctionParameterContextInformation(descriptor: FunctionDescr } private fun getActualParameterType(descriptor: ValueParameterDescriptor): KotlinType { - return descriptor.varargElementType ?: descriptor.getType() + return descriptor.varargElementType ?: descriptor.type } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinParameterListValidator.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinParameterListValidator.kt index 009a415de..e9e140dde 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinParameterListValidator.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/KotlinParameterListValidator.kt @@ -32,39 +32,38 @@ import org.jetbrains.kotlin.psi.KtValueArgumentList import org.jetbrains.kotlin.ui.editors.KotlinEditor import kotlin.properties.Delegates -public class KotlinParameterListValidator(val editor: KotlinEditor) : IContextInformationValidator, - IContextInformationPresenter { +class KotlinParameterListValidator(val editor: KotlinEditor) : IContextInformationValidator, + IContextInformationPresenter { var info: KotlinFunctionParameterContextInformation by Delegates.notNull() var viewer: ITextViewer by Delegates.notNull() var position: Int by Delegates.notNull() var previousIndex: Int by Delegates.notNull() - + override fun install(info: IContextInformation, viewer: ITextViewer, offset: Int) { this.info = info as KotlinFunctionParameterContextInformation this.viewer = viewer this.position = offset this.previousIndex = -1 } - + override fun isContextInformationValid(offset: Int): Boolean { - if (info !is KotlinFunctionParameterContextInformation) return false EditorUtil.updatePsiFile(editor) - - val document = viewer.getDocument() + + val document = viewer.document val line = document.getLineInformationOfOffset(position) - - if (offset < line.getOffset()) return false - + + if (offset < line.offset) return false + val currentArgumentIndex = getCurrentArgumentIndex(offset) if (currentArgumentIndex == null || isIndexOutOfBound(currentArgumentIndex)) { return false } - + val expression = getCallSimpleNameExpression(editor, offset) - + return expression?.getReferencedName() == info.name.asString() } - + override fun updatePresentation(offset: Int, presentation: TextPresentation): Boolean { val currentArgumentIndex = getCurrentArgumentIndex(offset) if (currentArgumentIndex == null || previousIndex == currentArgumentIndex) { @@ -72,43 +71,44 @@ public class KotlinParameterListValidator(val editor: KotlinEditor) : IContextIn } presentation.clear() previousIndex = currentArgumentIndex - + if (isIndexOutOfBound(currentArgumentIndex)) return false - + val renderedParameter = info.renderedParameters[currentArgumentIndex] - - val displayString = info.getInformationDisplayString() + + val displayString = info.informationDisplayString val start = displayString.indexOf(renderedParameter) if (start >= 0) { presentation.addStyleRange(StyleRange(0, start, null, null, SWT.NORMAL)) - + val end = start + renderedParameter.length presentation.addStyleRange(StyleRange(start, end - start, null, null, SWT.BOLD)) presentation.addStyleRange(StyleRange(end, displayString.length - end, null, null, SWT.NORMAL)) - + return true } - + return true } - + private fun isIndexOutOfBound(index: Int): Boolean = info.renderedParameters.size <= index - -// Copied with some changes from JetFunctionParameterInfoHandler.java + + // Copied with some changes from JetFunctionParameterInfoHandler.java private fun getCurrentArgumentIndex(offset: Int): Int? { val psiElement = EditorUtil.getPsiElement(editor, offset) - val argumentList = PsiTreeUtil.getNonStrictParentOfType(psiElement, KtValueArgumentList::class.java) - if (argumentList == null) return null - + val argumentList = + PsiTreeUtil.getNonStrictParentOfType(psiElement, KtValueArgumentList::class.java) ?: return null + val offsetInPSI = LineEndUtil.convertCrToDocumentOffset(editor.document, offset) - var child = argumentList.getNode().getFirstChildNode() + var child = argumentList.node.firstChildNode var index = 0 - while (child != null && child.getStartOffset() < offsetInPSI) { - if (child.getElementType() == KtTokens.COMMA || - (child.getText() == "," && child is PsiErrorElement)) ++index - child = child.getTreeNext() + while (child != null && child.startOffset < offsetInPSI) { + if (child.elementType == KtTokens.COMMA || + (child.text == "," && child is PsiErrorElement) + ) ++index + child = child.treeNext } - + return index } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/VisibilityUtils.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/VisibilityUtils.kt index 01ffc1ae2..04188cbf0 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/VisibilityUtils.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/codeassist/VisibilityUtils.kt @@ -1,36 +1,19 @@ package org.jetbrains.kotlin.ui.editors.codeassist import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.resolve.BindingContext -import com.intellij.psi.PsiFile -import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.psi.KtClassBody -import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue -import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver -import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils -import org.jetbrains.kotlin.psi.KtQualifiedExpression -import org.jetbrains.kotlin.psi.KtImportDirective -import org.jetbrains.kotlin.psi.KtCallExpression -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.types.expressions.OperatorConventions -import org.jetbrains.kotlin.psi.KtUnaryExpression -import org.jetbrains.kotlin.psi.KtUserType -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy +import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.scopes.LexicalScope +import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver +import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy // from idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt but without the second parameter -public fun PsiElement.getResolutionScope(bindingContext: BindingContext): LexicalScope { +fun PsiElement.getResolutionScope(bindingContext: BindingContext): LexicalScope { for (parent in parentsWithSelf) { if (parent is KtElement) { val scope = bindingContext[BindingContext.LEXICAL_SCOPE, parent] @@ -48,12 +31,12 @@ public fun PsiElement.getResolutionScope(bindingContext: BindingContext): Lexica } //from idea/idea-core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt -public fun DeclarationDescriptorWithVisibility.isVisible( +fun DeclarationDescriptorWithVisibility.isVisible( from: DeclarationDescriptor, bindingContext: BindingContext? = null, element: KtSimpleNameExpression? = null ): Boolean { - if (Visibilities.isVisibleWithAnyReceiver(this, from)) return true + if (DescriptorVisibilities.isVisibleWithAnyReceiver(this, from, /*TODO true right?*/true)) return true if (bindingContext == null || element == null) return false @@ -61,18 +44,18 @@ public fun DeclarationDescriptorWithVisibility.isVisible( if (receiverExpression != null) { val receiverType = bindingContext.getType(receiverExpression) ?: return false val explicitReceiver = ExpressionReceiver.create(receiverExpression, receiverType, bindingContext) - return Visibilities.isVisible(explicitReceiver, this, from) + return DescriptorVisibilities.isVisible(explicitReceiver, this, from, /*TODO true right?*/true) } else { val resolutionScope = element.getResolutionScope(bindingContext) return resolutionScope.getImplicitReceiversHierarchy().any { - Visibilities.isVisible(it.value, this, from) + DescriptorVisibilities.isVisible(it.value, this, from, /*TODO true right?*/true) } } } //from idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt -public fun TypeParameterDescriptor.isVisible(where: DeclarationDescriptor?): Boolean { +fun TypeParameterDescriptor.isVisible(where: DeclarationDescriptor?): Boolean { val owner = getContainingDeclaration() var parent = where while (parent != null) { diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/completion/KotlinCompletionUtils.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/completion/KotlinCompletionUtils.kt index 501e57f94..52ae759e9 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/completion/KotlinCompletionUtils.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/completion/KotlinCompletionUtils.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.ui.editors.completion import com.intellij.openapi.util.text.StringUtilRt import com.intellij.psi.PsiElement import org.eclipse.core.resources.IFile +import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.search.SearchPattern import org.eclipse.jdt.internal.ui.JavaPlugin import org.eclipse.jdt.ui.PreferenceConstants @@ -37,6 +38,7 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.ui.editors.KotlinEditor +import org.jetbrains.kotlin.ui.editors.codeassist.KotlinBasicCompletionProposal import org.jetbrains.kotlin.ui.editors.codeassist.getResolutionScope import org.jetbrains.kotlin.ui.editors.codeassist.isVisible @@ -54,11 +56,13 @@ object KotlinCompletionUtils { } fun getReferenceVariants( - simpleNameExpression: KtSimpleNameExpression, - nameFilter: (Name) -> Boolean, - file: IFile, - identifierPart: String? - ): Collection { + simpleNameExpression: KtSimpleNameExpression, + nameFilter: (Name) -> Boolean, + ktFile: KtFile, + file: IFile, + identifierPart: String?, + javaProject: IJavaProject + ): Collection { val (analysisResult, container) = KotlinAnalyzer.analyzeFile(simpleNameExpression.containingKtFile) if (container == null) return emptyList() @@ -84,13 +88,13 @@ object KotlinCompletionUtils { val collectAll = (identifierPart == null || identifierPart.length > 2) || !KotlinScriptEnvironment.isScript(file) val kind = if (collectAll) DescriptorKindFilter.ALL else DescriptorKindFilter.CALLABLES - - return KotlinReferenceVariantsHelper ( - analysisResult.bindingContext, - KotlinResolutionFacade(file, container, analysisResult.moduleDescriptor), - analysisResult.moduleDescriptor, - visibilityFilter).getReferenceVariants( - simpleNameExpression, kind, nameFilter) + + return KotlinReferenceVariantsHelper( + analysisResult.bindingContext, + KotlinResolutionFacade(file, container, analysisResult.moduleDescriptor), + analysisResult.moduleDescriptor, + visibilityFilter + ).getReferenceVariants(simpleNameExpression, kind, nameFilter, javaProject, ktFile, file, identifierPart) } fun getPsiElement(editor: KotlinEditor, identOffset: Int): PsiElement? { @@ -110,4 +114,4 @@ object KotlinCompletionUtils { val offsetWithoutCR = LineEndUtil.convertCrToDocumentOffset(sourceCodeWithMarker, identOffset, editor.document) return jetFile.findElementAt(offsetWithoutCR) } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/completion/KotlinReferenceVariantsHelper.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/completion/KotlinReferenceVariantsHelper.kt index 19cd6e2b6..00bdefd16 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/completion/KotlinReferenceVariantsHelper.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/completion/KotlinReferenceVariantsHelper.kt @@ -1,25 +1,43 @@ package org.jetbrains.kotlin.ui.editors.completion import com.intellij.psi.PsiElement +import kotlinx.coroutines.* +import org.eclipse.core.resources.IFile +import org.eclipse.jdt.core.Flags +import org.eclipse.jdt.core.IJavaProject +import org.eclipse.jdt.core.JavaCore +import org.eclipse.jdt.core.search.* +import org.eclipse.jdt.internal.ui.search.JavaSearchScopeFactory import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.core.resolve.KotlinResolutionFacade +import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.eclipse.ui.utils.KotlinEclipseScope +import org.jetbrains.kotlin.eclipse.ui.utils.KotlinImageProvider +import org.jetbrains.kotlin.idea.FrontendInternals +import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.incremental.KotlinLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.load.kotlin.toSourceElement +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver +import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.scopes.* +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter.Companion.CALLABLES +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter.Companion.FUNCTIONS_MASK +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter.Companion.VARIABLES_MASK import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier import org.jetbrains.kotlin.resolve.scopes.utils.collectDescriptorsFiltered import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope @@ -27,7 +45,10 @@ import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.expressions.DoubleColonLHS +import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.isUnit +import org.jetbrains.kotlin.ui.editors.codeassist.KotlinBasicCompletionProposal +import org.jetbrains.kotlin.ui.editors.codeassist.KotlinImportCallableCompletionProposal import org.jetbrains.kotlin.ui.refactorings.extract.parentsWithSelf import java.util.* @@ -40,30 +61,41 @@ class KotlinReferenceVariantsHelper( fun getReferenceVariants( simpleNameExpression: KtSimpleNameExpression, kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean - ): Collection { + nameFilter: (Name) -> Boolean, + javaProject: IJavaProject, + ktFile: KtFile, + file: IFile, + identifierPart: String? + ): Collection { val callTypeAndReceiver = CallTypeAndReceiver.detect(simpleNameExpression) - var variants: Collection = - getReferenceVariants(simpleNameExpression, callTypeAndReceiver, kindFilter, nameFilter) - .filter { - !resolutionFacade.frontendService().isHiddenInResolution(it) && visibilityFilter( - it - ) - } - - ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, simpleNameExpression, callTypeAndReceiver) - ?.let { - variants = it.filter(variants) + var variants: Collection = + getReferenceVariants( + simpleNameExpression, + callTypeAndReceiver, + kindFilter, + nameFilter, + javaProject, + ktFile, + file, + identifierPart + ).filter { + !resolutionFacade.frontendService().isHiddenInResolution(it.descriptor) && + visibilityFilter(it.descriptor) } - if (kindFilter.kindMask.and(DescriptorKindFilter.FUNCTIONS_MASK) != 0) { - variants = filterOutJavaGettersAndSetters(variants) - } - if (kindFilter.kindMask.and(DescriptorKindFilter.VARIABLES_MASK) != 0) { - variants = excludeNonInitializedVariable(variants, simpleNameExpression) + val tempFilter = ShadowedDeclarationsFilter.create( + bindingContext, + resolutionFacade, + simpleNameExpression, + callTypeAndReceiver + ) + if (tempFilter != null) { + variants = variants.mapNotNull { + if (tempFilter.filter(listOf(it.descriptor)).isEmpty()) null else it + } } - return variants + return variants.filter { kindFilter.accepts(it.descriptor) } } private fun getVariantsForImportOrPackageDirective( @@ -109,8 +141,8 @@ class KotlinReferenceVariantsHelper( useReceiverType: KotlinType?, kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean - ): Collection { - val descriptors = LinkedHashSet() + ): Collection { + val descriptors = LinkedHashSet() val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade) @@ -142,7 +174,10 @@ class KotlinReferenceVariantsHelper( if (isStatic) { explicitReceiverTypes .mapNotNull { (it.constructor.declarationDescriptor as? ClassDescriptor)?.staticScope } - .flatMapTo(descriptors) { it.collectStaticMembers(resolutionFacade, kindFilter, nameFilter) } + .flatMapTo(descriptors) { scope -> + scope.collectStaticMembers(resolutionFacade, kindFilter, nameFilter) + .map { KotlinBasicCompletionProposal.Descriptor(it) } + } } } else { descriptors.addNonExtensionCallablesAndConstructors( @@ -158,8 +193,12 @@ class KotlinReferenceVariantsHelper( simpleNameExpression: KtSimpleNameExpression, callTypeAndReceiver: CallTypeAndReceiver<*, *>, kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean - ): Collection { + nameFilter: (Name) -> Boolean, + javaProject: IJavaProject, + ktFile: KtFile, + file: IFile, + identifierPart: String? + ): Collection { val callType = callTypeAndReceiver.callType @Suppress("NAME_SHADOWING") @@ -169,10 +208,12 @@ class KotlinReferenceVariantsHelper( when (callTypeAndReceiver) { is CallTypeAndReceiver.IMPORT_DIRECTIVE -> { return getVariantsForImportOrPackageDirective(callTypeAndReceiver.receiver, kindFilter, nameFilter) + .map { KotlinBasicCompletionProposal.Descriptor(it) } } is CallTypeAndReceiver.PACKAGE_DIRECTIVE -> { return getVariantsForImportOrPackageDirective(callTypeAndReceiver.receiver, kindFilter, nameFilter) + .map { KotlinBasicCompletionProposal.Descriptor(it) } } is CallTypeAndReceiver.TYPE -> { @@ -181,7 +222,7 @@ class KotlinReferenceVariantsHelper( simpleNameExpression, kindFilter, nameFilter - ) + ).map { KotlinBasicCompletionProposal.Descriptor(it) } } is CallTypeAndReceiver.ANNOTATION -> { @@ -190,7 +231,7 @@ class KotlinReferenceVariantsHelper( simpleNameExpression, kindFilter, nameFilter - ) + ).map { KotlinBasicCompletionProposal.Descriptor(it) } } is CallTypeAndReceiver.CALLABLE_REFERENCE -> { @@ -233,7 +274,7 @@ class KotlinReferenceVariantsHelper( ) }.toSet() - val descriptors = LinkedHashSet() + val descriptors = LinkedHashSet() val filterWithoutExtensions = kindFilter exclude DescriptorKindExclude.Extensions if (receiverExpression != null) { @@ -244,7 +285,7 @@ class KotlinReferenceVariantsHelper( resolutionFacade, filterWithoutExtensions, nameFilter - ) + ).map { KotlinBasicCompletionProposal.Descriptor(it) } ) } @@ -262,7 +303,12 @@ class KotlinReferenceVariantsHelper( resolutionScope, callType, kindFilter, - nameFilter + nameFilter, + javaProject, + ktFile, + file, + identifierPart, + false ) } else { descriptors.processAll( @@ -271,7 +317,12 @@ class KotlinReferenceVariantsHelper( resolutionScope, callType, kindFilter, - nameFilter + nameFilter, + javaProject, + ktFile, + file, + identifierPart, + true ) descriptors.addAll( @@ -279,50 +330,209 @@ class KotlinReferenceVariantsHelper( filterWithoutExtensions, nameFilter, changeNamesForAliased = true - ) + ).map { KotlinBasicCompletionProposal.Descriptor(it) } ) } if (callType == CallType.SUPER_MEMBERS) { // we need to unwrap fake overrides in case of "super." because ShadowedDeclarationsFilter does not work correctly - return descriptors.flatMapTo(LinkedHashSet()) { - if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) it.overriddenDescriptors else listOf( - it - ) - } + return descriptors.filterIsInstance() + .flatMapTo(LinkedHashSet()) { descriptor -> + if (descriptor.descriptor is CallableMemberDescriptor && descriptor.descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + descriptor.descriptor.overriddenDescriptors.map { KotlinBasicCompletionProposal.Descriptor(it) } + } else { + listOf(descriptor) + } + } } - return descriptors + return descriptors.distinctBy { (it.descriptor as? ImportedFromObjectCallableDescriptor<*>)?.callableFromObject ?: it.descriptor } } - private fun MutableSet.processAll( + private fun MutableSet.processAll( implicitReceiverTypes: Collection, receiverTypes: Collection, resolutionScope: LexicalScope, callType: CallType<*>, kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean + nameFilter: (Name) -> Boolean, + javaProject: IJavaProject, + ktFile: KtFile, + file: IFile, + identifierPart: String?, + allowNoReceiver: Boolean ) { - addNonExtensionMembers(receiverTypes, kindFilter, nameFilter, constructorFilter = { it.isInner }) - addMemberExtensions(implicitReceiverTypes, receiverTypes, callType, kindFilter, nameFilter) - addScopeAndSyntheticExtensions(resolutionScope, receiverTypes, callType, kindFilter, nameFilter) + runBlocking { + val tempJobs = mutableListOf() + tempJobs += KotlinEclipseScope.launch { + addNonExtensionMembers(receiverTypes, kindFilter, nameFilter, constructorFilter = { it.isInner }) + } + tempJobs += KotlinEclipseScope.launch { + addMemberExtensions(implicitReceiverTypes, receiverTypes, callType, kindFilter, nameFilter) + } + tempJobs += KotlinEclipseScope.launch { + addNotImportedTopLevelCallables( + receiverTypes, + kindFilter, + nameFilter, + javaProject, + ktFile, + file, + identifierPart, + allowNoReceiver + ) + println("Finished!") + } + tempJobs += KotlinEclipseScope.launch { + addScopeAndSyntheticExtensions(resolutionScope, receiverTypes, callType, kindFilter, nameFilter) + } + tempJobs.joinAll() + } } - private fun MutableSet.addMemberExtensions( + private suspend fun MutableSet.addNotImportedTopLevelCallables( + receiverTypes: Collection, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean, + javaProject: IJavaProject, + ktFile: KtFile, + file: IFile, + identifierPart: String?, + allowNoReceiver: Boolean + ) { + if (!identifierPart.isNullOrBlank()) { + val searchEngine = SearchEngine() + + val dependencyProjects = arrayListOf().apply { + addAll(ProjectUtils.getDependencyProjects(javaProject).map { JavaCore.create(it) }) + add(javaProject) + } + + val javaProjectSearchScope = + JavaSearchScopeFactory.getInstance().createJavaSearchScope(dependencyProjects.toTypedArray(), false) + + val tempClassNames = hashMapOf() + + val collector = object : MethodNameMatchRequestor() { + override fun acceptMethodNameMatch(match: MethodNameMatch) { + if (Flags.isPublic(match.modifiers)) { + tempClassNames[match.method.declaringType.getTypeQualifiedName('.')] = + match.method.declaringType.packageFragment.elementName + } + } + } + + searchEngine.searchAllMethodNames( + null, + SearchPattern.R_EXACT_MATCH, + null, + SearchPattern.R_EXACT_MATCH, + null, + SearchPattern.R_EXACT_MATCH, + identifierPart.toCharArray(), + SearchPattern.R_PREFIX_MATCH, + javaProjectSearchScope, + collector, + IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH, + null + ) + + val tempCapitalIdentifier = + identifierPart.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } + + searchEngine.searchAllMethodNames( + null, + SearchPattern.R_EXACT_MATCH, + null, + SearchPattern.R_EXACT_MATCH, + null, + SearchPattern.R_EXACT_MATCH, + "get$tempCapitalIdentifier".toCharArray(), + SearchPattern.R_PREFIX_MATCH, + javaProjectSearchScope, + collector, + IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH, + null + ) + + val tempPackages = mutableListOf() + + val tempClasses = tempClassNames.mapNotNull { (className, packageName) -> + val tempClassId = ClassId(FqName(packageName), FqName(className), false) + moduleDescriptor.findClassAcrossModuleDependencies(tempClassId) ?: run { + tempPackages.add(resolutionFacade.moduleDescriptor.getPackage(FqName(packageName))) + null + } + } + + val importsSet = ktFile.importDirectives + .mapNotNull { it.importedFqName?.asString() } + .toSet() + + val originPackage = ktFile.packageFqName.asString() + + fun MemberScope.filterByKindAndName() = getDescriptorsFiltered( + kindFilter.intersect(CALLABLES), + nameFilter + ).asSequence() + .filterIsInstance() + .filter { callDesc -> + val tempFuzzy = callDesc.fuzzyExtensionReceiverType() + //We need all where the receiver matches. + val anyReceiverMatch = tempFuzzy != null && receiverTypes.any { receiverType -> + tempFuzzy.checkIsSuperTypeOf(receiverType) != null + } + //Or all, where we have no receiver, it's ok to have no receiver and the containing class of the callable Descriptor is not in the list of receivers, as this would give us the same completion twice. + val isTopLevelOrObjectCallable = callDesc.isTopLevelInPackage() || (callDesc.containingDeclaration as? ClassDescriptor)?.let { containing -> + val tempContainingKotlinType = containing.classValueType + val tempIsObject = containing.kind == ClassKind.OBJECT + val tempContainingIsReceiver = tempContainingKotlinType != null && receiverTypes.any { receiver -> receiver.isSubtypeOf(tempContainingKotlinType) } + tempIsObject && !tempContainingIsReceiver + } == true + val noReceiverMatches = allowNoReceiver && tempFuzzy == null && isTopLevelOrObjectCallable + noReceiverMatches || anyReceiverMatch + } + .filter { callDesc -> + callDesc.importableFqName?.asString() !in importsSet && + callDesc.importableFqName?.parent()?.asString() != originPackage + }.toList() + + val tempDeferreds = + tempPackages.map { desc -> KotlinEclipseScope.async { desc.memberScope.filterByKindAndName() } } + + tempClasses.map { desc -> KotlinEclipseScope.async { desc.unsubstitutedMemberScope.filterByKindAndName() } } + + val tempDescriptors = tempDeferreds.awaitAll().flatten() + + tempDescriptors + .map { + KotlinBasicCompletionProposal.Proposal( + KotlinImportCallableCompletionProposal( + it, + KotlinImageProvider.getImage(it), + file, + identifierPart + ), it + ) + }.toCollection(this) + } + } + + private fun MutableSet.addMemberExtensions( dispatchReceiverTypes: Collection, extensionReceiverTypes: Collection, callType: CallType<*>, kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean + nameFilter: (Name) -> Boolean, ) { val memberFilter = kindFilter exclude DescriptorKindExclude.NonExtensions for (dispatchReceiverType in dispatchReceiverTypes) { for (member in dispatchReceiverType.memberScope.getDescriptorsFiltered(memberFilter, nameFilter)) { - addAll((member as CallableDescriptor).substituteExtensionIfCallable(extensionReceiverTypes, callType)) + addAll((member as CallableDescriptor).substituteExtensionIfCallable(extensionReceiverTypes, callType) + .map { KotlinBasicCompletionProposal.Descriptor(it) }) } } } - private fun MutableSet.addNonExtensionMembers( + private fun MutableSet.addNonExtensionMembers( receiverTypes: Collection, kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, @@ -344,19 +554,19 @@ class KotlinReferenceVariantsHelper( } } - private fun MutableSet.addNonExtensionCallablesAndConstructors( + private fun MutableSet.addNonExtensionCallablesAndConstructors( scope: HierarchicalScope, kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, constructorFilter: (ClassDescriptor) -> Boolean, classesOnly: Boolean ) { - var filterToUse = DescriptorKindFilter(kindFilter.kindMask and DescriptorKindFilter.CALLABLES.kindMask).exclude( + var filterToUse = DescriptorKindFilter(kindFilter.kindMask and CALLABLES.kindMask).exclude( DescriptorKindExclude.Extensions ) // should process classes if we need constructors - if (filterToUse.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) { + if (filterToUse.acceptsKinds(FUNCTIONS_MASK)) { filterToUse = filterToUse.withKinds(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS_MASK) } @@ -364,14 +574,15 @@ class KotlinReferenceVariantsHelper( if (descriptor is ClassDescriptor) { if (descriptor.modality == Modality.ABSTRACT || descriptor.modality == Modality.SEALED) continue if (!constructorFilter(descriptor)) continue - descriptor.constructors.filterTo(this) { kindFilter.accepts(it) } + descriptor.constructors.map { KotlinBasicCompletionProposal.Descriptor(it) } + .filterTo(this) { kindFilter.accepts(it.descriptor) } } else if (!classesOnly && kindFilter.accepts(descriptor)) { - this.add(descriptor) + this.add(KotlinBasicCompletionProposal.Descriptor(descriptor)) } } } - private fun MutableSet.addScopeAndSyntheticExtensions( + private fun MutableSet.addScopeAndSyntheticExtensions( scope: LexicalScope, receiverTypes: Collection, callType: CallType<*>, @@ -384,9 +595,11 @@ class KotlinReferenceVariantsHelper( fun process(extensionOrSyntheticMember: CallableDescriptor) { if (kindFilter.accepts(extensionOrSyntheticMember) && nameFilter(extensionOrSyntheticMember.name)) { if (extensionOrSyntheticMember.isExtension) { - addAll(extensionOrSyntheticMember.substituteExtensionIfCallable(receiverTypes, callType)) + addAll( + extensionOrSyntheticMember.substituteExtensionIfCallable(receiverTypes, callType) + .map { KotlinBasicCompletionProposal.Descriptor(it) }) } else { - add(extensionOrSyntheticMember) + add(KotlinBasicCompletionProposal.Descriptor(extensionOrSyntheticMember)) } } } @@ -400,7 +613,7 @@ class KotlinReferenceVariantsHelper( } val syntheticScopes = resolutionFacade.getFrontendService(SyntheticScopes::class.java) - if (kindFilter.acceptsKinds(DescriptorKindFilter.VARIABLES_MASK)) { + if (kindFilter.acceptsKinds(VARIABLES_MASK)) { val lookupLocation = (scope.ownerDescriptor.toSourceElement.getPsi() as? KtElement)?.let { KotlinLookupLocation(it) } ?: NoLookupLocation.FROM_IDE @@ -410,7 +623,7 @@ class KotlinReferenceVariantsHelper( } } - if (kindFilter.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) { + if (kindFilter.acceptsKinds(FUNCTIONS_MASK)) { for (syntheticMember in syntheticScopes.collectSyntheticMemberFunctions(receiverTypes)) { process(syntheticMember) } @@ -462,6 +675,7 @@ private fun MemberScope.collectStaticMembers( ) } +@OptIn(FrontendInternals::class) fun ResolutionScope.collectSyntheticStaticMembersAndConstructors( resolutionFacade: ResolutionFacade, kindFilter: DescriptorKindFilter, @@ -470,9 +684,11 @@ fun ResolutionScope.collectSyntheticStaticMembersAndConstructors( val syntheticScopes = resolutionFacade.getFrontendService(SyntheticScopes::class.java) val functionDescriptors = this.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS) val classifierDescriptors = this.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) - return (syntheticScopes.collectSyntheticStaticFunctions(functionDescriptors) + syntheticScopes.collectSyntheticConstructors(classifierDescriptors)) + return (syntheticScopes.collectSyntheticStaticFunctions(functionDescriptors) + syntheticScopes.collectSyntheticConstructors( + classifierDescriptors + )) .filter { kindFilter.accepts(it) && nameFilter(it.name) } } -private inline fun ResolutionFacade.frontendService(): T - = this.getFrontendService(T::class.java) +@OptIn(FrontendInternals::class) +private inline fun ResolutionFacade.frontendService(): T = this.getFrontendService(T::class.java) diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/highlighting/KotlinSemanticHighlightingVisitor.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/highlighting/KotlinSemanticHighlightingVisitor.kt index 79f2ea826..227ad9987 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/highlighting/KotlinSemanticHighlightingVisitor.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/highlighting/KotlinSemanticHighlightingVisitor.kt @@ -16,44 +16,20 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui.editors.highlighting -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.core.builder.KotlinPsiManager -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.core.model.KotlinAnalysisFileCache -import org.eclipse.jface.text.Position -import org.jetbrains.kotlin.psi.KtVisitorVoid +import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.psi.KtThisExpression -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.VariableDescriptor -import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightings -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import com.intellij.psi.util.PsiTreeUtil +import org.eclipse.jface.text.IDocument +import org.eclipse.jface.text.Position +import org.jetbrains.kotlin.core.model.KotlinAnalysisFileCache +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassKind.* import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import com.intellij.openapi.util.TextRange -import org.jetbrains.kotlin.ui.editors.KotlinFileEditor import org.jetbrains.kotlin.eclipse.ui.utils.LineEndUtil -import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.renderer.DescriptorRenderer -import org.eclipse.jface.text.IDocument -import org.eclipse.jdt.core.IJavaProject -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.psi.KtTypeParameter -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.descriptors.ClassKind.* -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtSuperExpression -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.psi.KtAnnotationEntry -import org.jetbrains.kotlin.psi.KtValueArgumentList +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorUtils public class KotlinSemanticHighlightingVisitor(val ktFile: KtFile, val document: IDocument) : KtVisitorVoid() { private lateinit var bindingContext: BindingContext @@ -90,7 +66,7 @@ public class KotlinSemanticHighlightingVisitor(val ktFile: KtFile, val document: if (target == null) return val smartCast = bindingContext.get(BindingContext.SMARTCAST, expression) - val typeName = smartCast?.defaultType?.let { DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it) } ?: null + val typeName = smartCast?.defaultType?.let { DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it) } when (target) { is TypeParameterDescriptor -> highlightTypeParameter(expression) @@ -219,8 +195,7 @@ public class KotlinSemanticHighlightingVisitor(val ktFile: KtFile, val document: } is ValueParameterDescriptor -> KotlinHighlightingAttributes.PARAMETER_VARIABLE - - else -> throw IllegalStateException("Cannot find highlight attributes for $descriptor") + else -> KotlinHighlightingAttributes.PARAMETER_VARIABLE } if (typeName != null) highlightSmartCast(element.getTextRange(), typeName) highlight(attributes, element.getTextRange()) @@ -235,4 +210,4 @@ sealed class HighlightPosition(offset: Int, length: Int) : Position(offset, leng class StyleAttributes(val styleAttributes: KotlinHighlightingAttributes, offset: Int, length: Int) : HighlightPosition(offset, length) class SmartCast(val typeName: String, offset: Int, length: Int) : HighlightPosition(offset, length) -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/hover/KotlinTextHover.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/hover/KotlinTextHover.kt index 020e8c95b..c6825c6fb 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/hover/KotlinTextHover.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/hover/KotlinTextHover.kt @@ -59,7 +59,7 @@ class KotlinTextHover(private val editor: KotlinEditor) : ITextHover, ITextHover override fun getHoverInfo2(textViewer: ITextViewer?, hoverRegion: IRegion): Any? = createHoverData(hoverRegion.offset)?.let { data -> - extensionsHovers.firstNotNullResult { hover -> + extensionsHovers.firstNotNullOfOrNull { hover -> hover.takeIf { it.isAvailable(data) }?.getHoverInfo(data)?.also { bestHover = hover } diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/navigation/KotlinOpenDeclarationAction.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/navigation/KotlinOpenDeclarationAction.kt index 763b65ea4..6b464c73f 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/navigation/KotlinOpenDeclarationAction.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/navigation/KotlinOpenDeclarationAction.kt @@ -1,58 +1,41 @@ /******************************************************************************* -* Copyright 2000-2016 JetBrains s.r.o. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -*******************************************************************************/ + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *******************************************************************************/ package org.jetbrains.kotlin.ui.editors.navigation -import org.jetbrains.kotlin.ui.editors.KotlinEditor -import org.eclipse.jdt.ui.actions.SelectionDispatchAction +import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.internal.ui.actions.ActionMessages import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds +import org.eclipse.jdt.ui.actions.SelectionDispatchAction import org.eclipse.jface.text.ITextSelection -import org.jetbrains.kotlin.psi.KtReferenceExpression -import org.eclipse.jdt.core.IJavaProject -import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer -import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.core.references.createReferences +import org.jetbrains.kotlin.core.utils.getBindingContext +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.ui.editors.KotlinEditor class KotlinOpenDeclarationAction(val editor: KotlinEditor) : SelectionDispatchAction(editor.javaEditor.site) { companion object { - val OPEN_EDITOR_TEXT = "OpenEditor" - } - - init { - setText(ActionMessages.OpenAction_declaration_label) - setActionDefinitionId(IJavaEditorActionDefinitionIds.OPEN_EDITOR) - } - - override fun run(selection: ITextSelection) { - val selectedExpression = EditorUtil.getReferenceExpression(editor, selection.offset) - val javaProject = editor.javaProject - if (selectedExpression == null || javaProject == null) return - - val data = getNavigationData(selectedExpression, javaProject) - if (data == null) return - - gotoElement(data.sourceElement, data.descriptor, selectedExpression, editor, javaProject) - } - - private fun getNavigationData(referenceExpression: KtReferenceExpression, javaProject: IJavaProject): NavigationData? { - val context = KotlinAnalyzer.analyzeFile(referenceExpression.getContainingKtFile()).analysisResult.bindingContext - return createReferences(referenceExpression) + const val OPEN_EDITOR_TEXT = "OpenEditor" + + fun getNavigationData(ktElement: KtElement, javaProject: IJavaProject): NavigationData? { + val context = ktElement.getBindingContext() + return createReferences(ktElement) .asSequence() .flatMap { it.getTargetDescriptors(context).asSequence() } .mapNotNull { descriptor -> @@ -60,7 +43,23 @@ class KotlinOpenDeclarationAction(val editor: KotlinEditor) : SelectionDispatchA if (elementWithSource != null) NavigationData(elementWithSource, descriptor) else null } .firstOrNull() + } + + data class NavigationData(val sourceElement: SourceElement, val descriptor: DeclarationDescriptor) + } + + init { + text = ActionMessages.OpenAction_declaration_label + actionDefinitionId = IJavaEditorActionDefinitionIds.OPEN_EDITOR + } + + override fun run(selection: ITextSelection) { + val selectedExpression = EditorUtil.getReferenceExpression(editor, selection.offset) ?: + EditorUtil.getJetElement(editor, selection.offset) ?: return + val javaProject = editor.javaProject ?: return + + val data = getNavigationData(selectedExpression, javaProject) ?: return + + gotoElement(data.sourceElement, data.descriptor, selectedExpression, editor, javaProject) } - - private data class NavigationData(val sourceElement: SourceElement, val descriptor: DeclarationDescriptor) -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/navigation/KotlinOpenSuperImplementationAction.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/navigation/KotlinOpenSuperImplementationAction.kt index bcbaecdf9..69c48bbeb 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/navigation/KotlinOpenSuperImplementationAction.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/navigation/KotlinOpenSuperImplementationAction.kt @@ -1,23 +1,25 @@ /******************************************************************************* -* Copyright 2000-2016 JetBrains s.r.o. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -*******************************************************************************/ + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *******************************************************************************/ package org.jetbrains.kotlin.ui.editors.navigation import com.intellij.psi.util.PsiTreeUtil +import org.eclipse.core.commands.AbstractHandler +import org.eclipse.core.commands.ExecutionEvent import org.eclipse.jdt.internal.ui.actions.ActionMessages import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds import org.eclipse.jdt.ui.actions.SelectionDispatchAction @@ -26,116 +28,147 @@ import org.eclipse.jface.viewers.ArrayContentProvider import org.eclipse.jface.window.Window import org.eclipse.ui.PlatformUI import org.eclipse.ui.dialogs.ListDialog +import org.eclipse.ui.handlers.HandlerUtil import org.jetbrains.kotlin.core.model.KotlinAnalysisFileCache import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.* import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.MemberDescriptor import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtObjectDeclaration -import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.stubs.KotlinStubWithFqName import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.ui.editors.KotlinCommonEditor import org.jetbrains.kotlin.ui.overrideImplement.KotlinCallableLabelProvider -import java.util.LinkedHashSet -public class KotlinOpenSuperImplementationAction(val editor: KotlinCommonEditor) : SelectionDispatchAction(editor.site) { +class KotlinOpenSuperImplementationActionHandler : AbstractHandler() { + override fun execute(event: ExecutionEvent): Any? { + val editor = HandlerUtil.getActiveEditor(event) + if (editor !is KotlinCommonEditor) return null + + KotlinOpenSuperImplementationAction(editor).run() + + return null + } +} + +class KotlinOpenAllSuperImplementationActionHandler : AbstractHandler() { + override fun execute(event: ExecutionEvent): Any? { + val editor = HandlerUtil.getActiveEditor(event) + if (editor !is KotlinCommonEditor) return null + + KotlinOpenSuperImplementationAction(editor, true).run() + + return null + } +} + +class KotlinOpenSuperImplementationAction( + private val editor: KotlinCommonEditor, + private val recursive: Boolean = false +) : SelectionDispatchAction(editor.site) { init { - setActionDefinitionId(IJavaEditorActionDefinitionIds.OPEN_SUPER_IMPLEMENTATION) - setText(ActionMessages.OpenSuperImplementationAction_label) - setDescription(ActionMessages.OpenSuperImplementationAction_description) + actionDefinitionId = IJavaEditorActionDefinitionIds.OPEN_SUPER_IMPLEMENTATION + text = ActionMessages.OpenSuperImplementationAction_label + description = ActionMessages.OpenSuperImplementationAction_description } - + companion object { - val ACTION_ID = "OpenSuperImplementation" + const val ACTION_ID = "OpenSuperImplementation" } - + override fun run(selection: ITextSelection) { val ktFile = editor.parsedFile val project = editor.javaProject if (ktFile == null || project == null) return - - val psiElement = EditorUtil.getPsiElement(editor, selection.offset) - if (psiElement == null) return - - val declaration: KtDeclaration? = PsiTreeUtil.getParentOfType(psiElement, + + val psiElement = EditorUtil.getPsiElement(editor, selection.offset) ?: return + + val declaration: KtTypeParameterListOwnerStub>> = + PsiTreeUtil.getParentOfType( + psiElement, KtNamedFunction::class.java, KtClass::class.java, KtProperty::class.java, - KtObjectDeclaration::class.java) - if (declaration == null) return - + KtObjectDeclaration::class.java + ) ?: return + val descriptor = resolveToDescriptor(declaration) if (descriptor !is DeclarationDescriptor) return - - val superDeclarations = findSuperDeclarations(descriptor) + + val superDeclarations = + if (recursive) findSuperDeclarationsRecursive(descriptor) else findSuperDeclarations(descriptor) if (superDeclarations.isEmpty()) return - - val superDeclaration = when { - superDeclarations.isEmpty() -> null - superDeclarations.size == 1 -> superDeclarations.first() + + val superDeclaration = when (superDeclarations.size) { + 1 -> superDeclarations.first() else -> chooseFromSelectionDialog(superDeclarations) - } - - if (superDeclaration == null) return - + } ?: return + gotoElement(superDeclaration, declaration, editor, project) } - + private fun chooseFromSelectionDialog(declarations: Set): MemberDescriptor? { - val shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell() + val shell = PlatformUI.getWorkbench().activeWorkbenchWindow.shell val dialog = ListDialog(shell) - + dialog.setTitle("Super Declarations") dialog.setMessage("Select a declaration to navigate") dialog.setContentProvider(ArrayContentProvider()) dialog.setLabelProvider(KotlinCallableLabelProvider()) - + dialog.setInput(declarations.toTypedArray()) - + if (dialog.open() == Window.CANCEL) { - return null; + return null } - - val result = dialog.getResult() + + val result = dialog.result if (result == null || result.size != 1) { return null } - + return result[0] as MemberDescriptor } - + private fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor? { - val context = KotlinAnalysisFileCache.getAnalysisResult(declaration.getContainingKtFile()).analysisResult.bindingContext + val context = + KotlinAnalysisFileCache.getAnalysisResult(declaration.containingKtFile).analysisResult.bindingContext return context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] } - + private fun findSuperDeclarations(descriptor: DeclarationDescriptor): Set { val superDescriptors = when (descriptor) { is ClassDescriptor -> { - descriptor.typeConstructor.supertypes.mapNotNull { + descriptor.typeConstructor.supertypes.mapNotNull { val declarationDescriptor = it.constructor.declarationDescriptor if (declarationDescriptor is ClassDescriptor) declarationDescriptor else null }.toSet() } - + is CallableMemberDescriptor -> descriptor.getDirectlyOverriddenDeclarations().toSet() - + else -> emptySet() } - + return superDescriptors } - fun D.getDirectlyOverriddenDeclarations(): Collection { + private fun findSuperDeclarationsRecursive(descriptor: DeclarationDescriptor): Set { + val tempResult = mutableSetOf() + var tempNewResults = setOf(descriptor) + while (tempNewResults.isNotEmpty()) { + val tempSuperResults = tempNewResults.flatMapTo(hashSetOf()) { findSuperDeclarations(it) } + tempSuperResults -= tempResult + tempResult += tempSuperResults + tempNewResults = tempSuperResults + } + return tempResult + } + + private fun D.getDirectlyOverriddenDeclarations(): Collection { val result = LinkedHashSet() for (overriddenDescriptor in overriddenDescriptors) { @Suppress("UNCHECKED_CAST") @@ -150,4 +183,4 @@ public class KotlinOpenSuperImplementationAction(val editor: KotlinCommonEditor) } return OverridingUtil.filterOutOverridden(result) } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/occurrences/KotlinMarkOccurrences.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/occurrences/KotlinMarkOccurrences.kt index 4604cb7bc..d841859d9 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/occurrences/KotlinMarkOccurrences.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/occurrences/KotlinMarkOccurrences.kt @@ -29,25 +29,24 @@ import org.eclipse.search.ui.text.Match import org.eclipse.ui.ISelectionListener import org.eclipse.ui.IWorkbenchPart import org.jetbrains.kotlin.core.builder.KotlinPsiManager +import org.jetbrains.kotlin.core.model.runJob import org.jetbrains.kotlin.core.references.resolveToSourceDeclaration import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil import org.jetbrains.kotlin.eclipse.ui.utils.getTextDocumentOffset -import org.jetbrains.kotlin.core.model.runJob import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.ui.commands.findReferences.KotlinScopedQuerySpecification import org.jetbrains.kotlin.ui.editors.KotlinCommonEditor import org.jetbrains.kotlin.ui.editors.KotlinEditor -import org.jetbrains.kotlin.ui.editors.KotlinFileEditor import org.jetbrains.kotlin.ui.editors.annotations.AnnotationManager import org.jetbrains.kotlin.ui.refactorings.rename.getLengthOfIdentifier import org.jetbrains.kotlin.ui.search.KotlinElementMatch import org.jetbrains.kotlin.ui.search.KotlinQueryParticipant import org.jetbrains.kotlin.ui.search.getContainingClassOrObjectForConstructor -public class KotlinMarkOccurrences(val kotlinEditor: KotlinCommonEditor) : ISelectionListener { +class KotlinMarkOccurrences(private val kotlinEditor: KotlinCommonEditor) : ISelectionListener { companion object { - private val ANNOTATION_TYPE = "org.eclipse.jdt.ui.occurrences" + private const val ANNOTATION_TYPE = "org.eclipse.jdt.ui.occurrences" } override fun selectionChanged(part: IWorkbenchPart, selection: ISelection) { @@ -58,16 +57,12 @@ public class KotlinMarkOccurrences(val kotlinEditor: KotlinCommonEditor) : ISele val file = part.eclipseFile if (file == null || !file.exists()) return@runJob Status.CANCEL_STATUS - val document = part.getDocumentSafely() - if (document == null) return@runJob Status.CANCEL_STATUS - + val document = part.getDocumentSafely() ?: return@runJob Status.CANCEL_STATUS + KotlinPsiManager.getKotlinFileIfExist(file, document.get()) - val ktElement = EditorUtil.getJetElement(part, selection.getOffset()) - if (ktElement == null) { - return@runJob Status.CANCEL_STATUS - } - + val ktElement = EditorUtil.getJetElement(part, selection.offset) ?: return@runJob Status.CANCEL_STATUS + val occurrences = findOccurrences(part, ktElement, file) updateOccurrences(part, occurrences) } @@ -88,25 +83,24 @@ public class KotlinMarkOccurrences(val kotlinEditor: KotlinCommonEditor) : ISele val searchingElements = getSearchingElements(sourceElements) val querySpecification = KotlinScopedQuerySpecification(searchingElements, listOf(file), - IJavaSearchConstants.ALL_OCCURRENCES, "Searching in ${file.getName()}") + IJavaSearchConstants.ALL_OCCURRENCES, "Searching in ${file.name}") val occurrences = arrayListOf() KotlinQueryParticipant().search({ occurrences.add(it) }, querySpecification, NullProgressMonitor()) - return occurrences.map { - if (it !is KotlinElementMatch) return@map null + return occurrences.mapNotNull { + if (it !is KotlinElementMatch) return@mapNotNull null val element = it.jetElement - val length = getLengthOfIdentifier(element) - if (length == null) return@map null - - val document = editor.getDocumentSafely() ?: return@map null + val length = getLengthOfIdentifier(element) ?: return@mapNotNull null + + val document = editor.getDocumentSafely() ?: return@mapNotNull null Position(element.getTextDocumentOffset(document), length) - }.filterNotNull() + } } private fun getSearchingElements(sourceElements: List): List { val classOrObjects = getContainingClassOrObjectForConstructor(sourceElements) - return if (classOrObjects.isNotEmpty()) classOrObjects else sourceElements + return classOrObjects.ifEmpty { sourceElements } } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/KotlinOrganizeImportsAction.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/KotlinOrganizeImportsAction.kt index 99a60a109..17c60e246 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/KotlinOrganizeImportsAction.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/KotlinOrganizeImportsAction.kt @@ -29,6 +29,7 @@ import org.eclipse.jface.window.Window import org.eclipse.swt.graphics.Image import org.eclipse.ui.ISharedImages import org.eclipse.ui.PlatformUI +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.formatting.codeStyle import org.jetbrains.kotlin.core.imports.* @@ -39,6 +40,9 @@ import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer import org.jetbrains.kotlin.core.resolve.KotlinResolutionFacade import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings +import org.jetbrains.kotlin.idea.core.formatter.KotlinPackageEntry +import org.jetbrains.kotlin.idea.core.formatter.KotlinPackageEntry.Companion.ALL_OTHER_ALIAS_IMPORTS_ENTRY +import org.jetbrains.kotlin.idea.core.formatter.KotlinPackageEntryTable import org.jetbrains.kotlin.idea.formatter.kotlinCustomSettings import org.jetbrains.kotlin.idea.imports.OptimizedImportsBuilder import org.jetbrains.kotlin.psi.KtFile @@ -65,7 +69,7 @@ class KotlinOrganizeImportsAction(private val editor: KotlinCommonEditor) : Sele } override fun run() { - val bindingContext = getBindingContext(editor) ?: return + val bindingContext = editor.getBindingContext() ?: return val ktFile = editor.parsedFile ?: return val file = editor.eclipseFile ?: return val (result, container) = KotlinAnalyzer.analyzeFile(ktFile) @@ -98,18 +102,21 @@ class KotlinOrganizeImportsAction(private val editor: KotlinCommonEditor) : Sele KotlinPsiManager.commitFile(file, editor.document) - optimizeImports() + optimizeImports(languageVersionSettings) } - private fun optimizeImports() { + private fun optimizeImports(languageVersionSettings: LanguageVersionSettings) { val ktFile = editor.parsedFile ?: return val file = editor.eclipseFile ?: return val importsData = collectDescriptorsToImport(ktFile) val kotlinCodeStyleSettings = file.project.codeStyle.kotlinCustomSettings - val optimizedImports = prepareOptimizedImports(ktFile, importsData, kotlinCodeStyleSettings) ?: return + val optimizedImports = prepareOptimizedImports(ktFile, importsData, kotlinCodeStyleSettings, languageVersionSettings) ?: return - replaceImports(optimizedImports.map { it.toString() }, file, editor.document) + replaceImports( + optimizedImports.sortedWith(ImportPathComparator(kotlinCodeStyleSettings.PACKAGES_IMPORT_LAYOUT)) + .map { it.toString() }, file, editor.document + ) } // null signalizes about cancelling operation @@ -137,7 +144,8 @@ class KotlinOrganizeImportsAction(private val editor: KotlinCommonEditor) : Sele fun prepareOptimizedImports( file: KtFile, importsData: OptimizedImportsBuilder.InputData, - settings: KotlinCodeStyleSettings + settings: KotlinCodeStyleSettings, + languageVersionSettings: LanguageVersionSettings ): List? = OptimizedImportsBuilder( file, @@ -145,7 +153,8 @@ fun prepareOptimizedImports( OptimizedImportsBuilder.Options( settings.NAME_COUNT_TO_USE_STAR_IMPORT, settings.NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS - ) { fqName -> fqName.asString() in settings.PACKAGES_TO_USE_STAR_IMPORTS } + ) { fqName -> fqName.asString() in settings.PACKAGES_TO_USE_STAR_IMPORTS }, + languageVersionSettings.apiVersion ).buildOptimizedImports() object ImportCandidatesLabelProvider : LabelProvider() { @@ -163,4 +172,59 @@ object ImportCandidatesLabelProvider : LabelProvider() { else -> element.toString() .also { KotlinLogger.logWarning("Unknown type of import candidate: $element") } } +} + +internal class ImportPathComparator(private val packageTable: KotlinPackageEntryTable) : Comparator { + + override fun compare(import1: ImportPath, import2: ImportPath): Int { + val ignoreAlias = import1.hasAlias() && import2.hasAlias() + + return compareValuesBy( + import1, + import2, + { import -> bestEntryMatchIndex(import, ignoreAlias) }, + { import -> import.toString() } + ) + } + + private fun bestEntryMatchIndex(path: ImportPath, ignoreAlias: Boolean): Int { + var bestEntryMatch: KotlinPackageEntry? = null + var bestIndex: Int = -1 + + for ((index, entry) in packageTable.getEntries().withIndex()) { + if (entry.isBetterMatchForPackageThan(bestEntryMatch, path, ignoreAlias)) { + bestEntryMatch = entry + bestIndex = index + } + } + + return bestIndex + } +} + +private fun KotlinPackageEntry.isBetterMatchForPackageThan(entry: KotlinPackageEntry?, path: ImportPath, ignoreAlias: Boolean): Boolean { + if (!matchesImportPath(path, ignoreAlias)) return false + if (entry == null) return true + + // Any matched package is better than ALL_OTHER_IMPORTS_ENTRY + if (this == KotlinPackageEntry.ALL_OTHER_IMPORTS_ENTRY) return false + if (entry == KotlinPackageEntry.ALL_OTHER_IMPORTS_ENTRY) return true + + if (entry.withSubpackages != withSubpackages) return !withSubpackages + + return entry.packageName.count { it == '.' } < packageName.count { it == '.' } +} + +/** + * In current implementation we assume that aliased import can be matched only by + * [ALL_OTHER_ALIAS_IMPORTS_ENTRY] which is always present. + */ +private fun KotlinPackageEntry.matchesImportPath(importPath: ImportPath, ignoreAlias: Boolean): Boolean { + if (!ignoreAlias && importPath.hasAlias()) { + return this == ALL_OTHER_ALIAS_IMPORTS_ENTRY + } + + if (this == KotlinPackageEntry.ALL_OTHER_IMPORTS_ENTRY) return true + + return matchesPackageName(importPath.pathStr) } \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/importsCollector.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/importsCollector.kt index 70bce899b..5fee80ef3 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/importsCollector.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/importsCollector.kt @@ -19,8 +19,8 @@ package org.jetbrains.kotlin.ui.editors.organizeImports import com.intellij.psi.PsiElement import org.jetbrains.kotlin.core.references.canBeResolvedViaImport import org.jetbrains.kotlin.core.references.createReferences +import org.jetbrains.kotlin.core.utils.getBindingContext import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.idea.imports.OptimizedImportsBuilder import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.incremental.components.NoLookupLocation @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope import org.jetbrains.kotlin.resolve.scopes.utils.* @@ -39,7 +40,8 @@ import kotlin.collections.LinkedHashSet fun collectDescriptorsToImport(file: KtFile): OptimizedImportsBuilder.InputData { val visitor = CollectUsedDescriptorsVisitor(file) file.accept(visitor) - return OptimizedImportsBuilder.InputData(visitor.descriptorsToImport, visitor.namesToImport, emptyList()) + val tempDescriptors = visitor.descriptorsToImport.mapTo(hashSetOf()) { OptimizedImportsBuilder.ImportableDescriptor(it, it.fqNameSafe) } + return OptimizedImportsBuilder.InputData(tempDescriptors, visitor.namesToImport, emptyList(), emptySet() /*TODO??*/) } private class CollectUsedDescriptorsVisitor(val file: KtFile) : KtVisitorVoid() { @@ -48,7 +50,7 @@ private class CollectUsedDescriptorsVisitor(val file: KtFile) : KtVisitorVoid() val descriptorsToImport = LinkedHashSet() val namesToImport = LinkedHashMap>() - private val bindingContext = getBindingContext(file)!! + private val bindingContext = file.getBindingContext() private val aliases: Map> = file.importDirectives .asSequence() diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinChangeReturnTypeProposal.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinChangeReturnTypeProposal.kt index 2efb15901..5b9ea8247 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinChangeReturnTypeProposal.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinChangeReturnTypeProposal.kt @@ -3,9 +3,9 @@ package org.jetbrains.kotlin.ui.editors.quickassist import com.intellij.psi.PsiElement import com.intellij.psi.util.PsiTreeUtil import org.eclipse.jface.text.IDocument +import org.jetbrains.kotlin.core.utils.getBindingContext import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.approximateWithResolvableType @@ -32,12 +32,12 @@ class KotlinChangeReturnTypeProposal(editor: KotlinEditor) : KotlinQuickAssistPr Errors.TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH) override fun apply(document: IDocument, psiElement: PsiElement) { - val oldTypeRef = function.getTypeReference() + val oldTypeRef = function.typeReference val renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS.renderType(type) if (oldTypeRef != null) { replace(oldTypeRef, renderedType) } else { - val anchor = function.getValueParameterList() + val anchor = function.valueParameterList if (anchor != null) { insertAfter(anchor, ": $renderedType") } @@ -45,7 +45,7 @@ class KotlinChangeReturnTypeProposal(editor: KotlinEditor) : KotlinQuickAssistPr } override fun getDisplayString(): String { - val functionName = function.getName() + val functionName = function.name val renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS.renderType(type) return if (functionName != null) { "Change '$functionName' function return type to '$renderedType'" @@ -55,24 +55,22 @@ class KotlinChangeReturnTypeProposal(editor: KotlinEditor) : KotlinQuickAssistPr } override fun isApplicable(psiElement: PsiElement): Boolean { - val bindingContext = getBindingContext() - if (bindingContext == null) return false - - val activeDiagnostic = getActiveDiagnostic(psiElement.textOffset, bindingContext.diagnostics) - if (activeDiagnostic == null) return false - + val bindingContext = getBindingContext() ?: return false + + val activeDiagnostic = getActiveDiagnostic(psiElement.textOffset, bindingContext.diagnostics) ?: return false + val expression = PsiTreeUtil.getNonStrictParentOfType(activeDiagnostic.psiElement, KtExpression::class.java) - if (expression == null) return false - + ?: return false + val expressionType = when (activeDiagnostic.factory) { Errors.TYPE_MISMATCH -> { val diagnosticWithParameters = Errors.TYPE_MISMATCH.cast(activeDiagnostic) - diagnosticWithParameters.getB() + diagnosticWithParameters.b } Errors.NULL_FOR_NONNULL_TYPE -> { val diagnosticWithParameters = Errors.NULL_FOR_NONNULL_TYPE.cast(activeDiagnostic) - val expectedType = diagnosticWithParameters.getA() + val expectedType = diagnosticWithParameters.a expectedType.makeNullable() } @@ -80,15 +78,13 @@ class KotlinChangeReturnTypeProposal(editor: KotlinEditor) : KotlinQuickAssistPr Errors.TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH -> { val diagnosticWithParameters = Errors.TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.cast(activeDiagnostic) - diagnosticWithParameters.getB() + diagnosticWithParameters.b } else -> null - } - - if (expressionType == null) return false - - val expressionParent = expression.getParent() + } ?: return false + + val expressionParent = expression.parent val ktFunction = if (expressionParent is KtReturnExpression) { expressionParent.getTargetFunction(bindingContext) } else { @@ -125,9 +121,8 @@ class KotlinChangeReturnTypeProposal(editor: KotlinEditor) : KotlinQuickAssistPr } private fun getBindingContext(): BindingContext? { - val ktFile = editor.parsedFile - if (ktFile == null) return null - - return getBindingContext(ktFile) + val ktFile = editor.parsedFile ?: return null + + return ktFile.getBindingContext() } } \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToBlockBodyAssistProposal.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToBlockBodyAssistProposal.kt index 957726c72..1c1317c51 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToBlockBodyAssistProposal.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToBlockBodyAssistProposal.kt @@ -23,6 +23,7 @@ import com.intellij.psi.util.PsiTreeUtil import org.eclipse.jface.text.IDocument import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.core.formatting.codeStyle +import org.jetbrains.kotlin.core.utils.getBindingContext import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.psi.KtBlockExpression @@ -47,7 +48,7 @@ class KotlinConvertToBlockBodyAssistProposal(editor: KotlinEditor) : KotlinQuick when (declaration) { is KtNamedFunction -> { - val bindingContext = getBindingContext(declaration) ?: return false; + val bindingContext = declaration.getBindingContext() val returnType: KotlinType = declaration.returnType(bindingContext) ?: return false // do not convert when type is implicit and unknown @@ -66,7 +67,7 @@ class KotlinConvertToBlockBodyAssistProposal(editor: KotlinEditor) : KotlinQuick override fun apply(document: IDocument, psiElement: PsiElement) { val declaration = PsiTreeUtil.getParentOfType(psiElement, KtDeclarationWithBody::class.java)!! - val context = getBindingContext(declaration)!! + val context = declaration.getBindingContext()!! val shouldSpecifyType = declaration is KtNamedFunction && !declaration.hasDeclaredReturnType() diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToExpressionBodyAssistProposal.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToExpressionBodyAssistProposal.kt index 8d4664054..15390ac0f 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToExpressionBodyAssistProposal.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToExpressionBodyAssistProposal.kt @@ -25,32 +25,21 @@ import org.eclipse.jface.text.TextUtilities import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.core.formatting.codeStyle -import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext +import org.jetbrains.kotlin.core.utils.getBindingContext import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtBlockExpression -import org.jetbrains.kotlin.psi.KtCallableDeclaration -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtDeclarationWithBody -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtFunctionLiteral -import org.jetbrains.kotlin.psi.KtLoopExpression -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtPropertyAccessor -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.KtReturnExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.ui.editors.KotlinEditor import org.jetbrains.kotlin.ui.editors.selection.handlers.siblings import org.jetbrains.kotlin.ui.formatter.formatCode -import org.jetbrains.kotlin.types.isError public class KotlinConvertToExpressionBodyAssistProposal(editor: KotlinEditor) : KotlinQuickAssistProposal(editor) { override fun isApplicable(psiElement: PsiElement): Boolean { val declaration = PsiTreeUtil.getParentOfType(psiElement, KtDeclarationWithBody::class.java) ?: return false - val context = getBindingContext(declaration.getContainingKtFile()) ?: return false + val context = declaration.getContainingKtFile().getBindingContext() ?: return false val value = calcValue(declaration, context) return value != null && !containsReturn(value) } diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinRemoveExplicitTypeAssistProposal.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinRemoveExplicitTypeAssistProposal.kt index 596420c7d..b6a3283ea 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinRemoveExplicitTypeAssistProposal.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinRemoveExplicitTypeAssistProposal.kt @@ -19,14 +19,8 @@ package org.jetbrains.kotlin.ui.editors.quickassist import com.intellij.psi.PsiElement import com.intellij.psi.util.PsiTreeUtil import org.eclipse.jface.text.IDocument -import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext -import org.jetbrains.kotlin.psi.KtCallableDeclaration -import org.jetbrains.kotlin.psi.KtCodeFragment -import org.jetbrains.kotlin.psi.KtDeclarationWithInitializer -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtTypeReference +import org.jetbrains.kotlin.core.utils.getBindingContext +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.ui.editors.KotlinEditor public class KotlinRemoveExplicitTypeAssistProposal(editor: KotlinEditor) : KotlinQuickAssistProposal(editor) { @@ -44,7 +38,7 @@ public class KotlinRemoveExplicitTypeAssistProposal(editor: KotlinEditor) : Kotl val initializer = (element as? KtDeclarationWithInitializer)?.getInitializer() if (initializer != null && initializer.getTextRange().containsOffset(caretOffset)) return false - val bindingContext = getBindingContext(element) + val bindingContext = element.getBindingContext() if (bindingContext == null) return false return when (element) { diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinSpecifyTypeAssistProposal.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinSpecifyTypeAssistProposal.kt index 23a35f1ba..71b873764 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinSpecifyTypeAssistProposal.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinSpecifyTypeAssistProposal.kt @@ -19,23 +19,15 @@ package org.jetbrains.kotlin.ui.editors.quickassist import com.intellij.psi.PsiElement import com.intellij.psi.util.PsiTreeUtil import org.eclipse.jface.text.IDocument +import org.jetbrains.kotlin.core.utils.getBindingContext import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.psi.KtCallableDeclaration -import org.jetbrains.kotlin.psi.KtCodeFragment -import org.jetbrains.kotlin.psi.KtConstructor -import org.jetbrains.kotlin.psi.KtDeclarationWithInitializer -import org.jetbrains.kotlin.psi.KtFunction -import org.jetbrains.kotlin.psi.KtFunctionLiteral -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.ui.editors.KotlinEditor import org.jetbrains.kotlin.types.isError +import org.jetbrains.kotlin.ui.editors.KotlinEditor public class KotlinSpecifyTypeAssistProposal(editor: KotlinEditor) : KotlinQuickAssistProposal(editor) { private var displayString: String? = null @@ -85,7 +77,7 @@ public class KotlinSpecifyTypeAssistProposal(editor: KotlinEditor) : KotlinQuick } private fun getTypeForDeclaration(declaration: KtCallableDeclaration): KotlinType { - val bindingContext = getBindingContext(declaration) + val bindingContext = declaration.getBindingContext() if (bindingContext == null) return ErrorUtils.createErrorType("null type") val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickfix/KotlinAddModifierResolution.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickfix/KotlinAddModifierResolution.kt index a868b2b1c..81331eb81 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickfix/KotlinAddModifierResolution.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickfix/KotlinAddModifierResolution.kt @@ -19,20 +19,20 @@ package org.jetbrains.kotlin.ui.editors.quickfix import com.intellij.psi.PsiComment import com.intellij.psi.PsiElement import com.intellij.psi.PsiNameIdentifierOwner - import com.intellij.psi.PsiWhiteSpace +import com.intellij.psi.tree.IElementType import com.intellij.psi.util.PsiTreeUtil import org.eclipse.core.resources.IFile import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility import org.eclipse.jface.text.IDocument import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.resolve.EclipseDescriptorUtils +import org.jetbrains.kotlin.core.utils.getBindingContext import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.DiagnosticWithParameters2 -import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens.* @@ -43,7 +43,6 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.ui.editors.KotlinEditor import org.jetbrains.kotlin.ui.editors.quickassist.insertBefore import org.jetbrains.kotlin.ui.editors.quickassist.replace -import com.intellij.psi.tree.IElementType fun DiagnosticFactory<*>.createAddModifierFix(modifier: KtModifierKeywordToken): KotlinDiagnosticQuickFix = createAddModifierFix(modifier, KtModifierListOwner::class.java) @@ -94,7 +93,7 @@ class KotlinMakeClassOpenQuickFix(private val diagnosticTrigger: DiagnosticFacto val ktFile = typeReference.containingKtFile - val bindingContext = getBindingContext(ktFile) ?: return emptyList() + val bindingContext = ktFile.getBindingContext() val type = bindingContext[BindingContext.TYPE, typeReference] ?: return emptyList() diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickfix/KotlinAutoImportQuickFix.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickfix/KotlinAutoImportQuickFix.kt index 5892dfc85..95759a159 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickfix/KotlinAutoImportQuickFix.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickfix/KotlinAutoImportQuickFix.kt @@ -34,10 +34,10 @@ import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.preferences.languageVersionSettings import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer import org.jetbrains.kotlin.core.resolve.KotlinResolutionFacade +import org.jetbrains.kotlin.core.utils.getBindingContext import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.eclipse.ui.utils.IndenterUtil -import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.eclipse.ui.utils.getEndLfOffset import org.jetbrains.kotlin.eclipse.ui.utils.getTextDocumentOffset import org.jetbrains.kotlin.psi.KtFile @@ -50,7 +50,7 @@ object KotlinAutoImportQuickFix : KotlinDiagnosticQuickFix { override fun getResolutions(diagnostic: Diagnostic): List { val ktFile = diagnostic.psiElement.containingFile as? KtFile ?: return emptyList() val file = KotlinPsiManager.getEclipseFile(ktFile) ?: return emptyList() - val bindingContext = getBindingContext(ktFile) ?: return emptyList() + val bindingContext = ktFile.getBindingContext() val (result, container) = KotlinAnalyzer.analyzeFile(ktFile) val resolutionFacade = container?.let { KotlinResolutionFacade(file, it, result.moduleDescriptor) } ?: return emptyList() diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/CompilerStatusHandler.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/CompilerStatusHandler.java deleted file mode 100644 index 4271a4d6f..000000000 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/CompilerStatusHandler.java +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - *******************************************************************************/ -package org.jetbrains.kotlin.ui.launch; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.debug.core.IStatusHandler; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.ui.console.ConsolePlugin; -import org.eclipse.ui.console.MessageConsole; -import org.eclipse.ui.console.MessageConsoleStream; -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation; -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity; -import org.jetbrains.kotlin.core.launch.CompilerOutputData; -import org.jetbrains.kotlin.core.launch.CompilerOutputElement; - -public class CompilerStatusHandler implements IStatusHandler { - - public static final String CONSOLE_NAME = "org.jetbrains.kotlin.ui.console"; - - private static final RGB CONSOLE_RED = new RGB(229, 43, 80); - private static final RGB CONSOLE_YELLOW = new RGB(218, 165, 32); - private static final RGB CONSOLE_BLACK = new RGB(0, 0, 0); - - @Override - public Object handleStatus(IStatus status, Object source) throws CoreException { - if (!(source instanceof CompilerOutputData)) { - return null; - } - - List outputDataList = ((CompilerOutputData) source).getList(); - - Map> sortedOutput = groupOutputByPath(outputDataList); - - MessageConsole msgConsole = KotlinConsoleKt.createCleanKotlinConsole(); - for (List outputList : sortedOutput.values()) { - printCompilerOutputList(outputList, msgConsole); - } - - if (status.getSeverity() == IStatus.ERROR) { - ConsolePlugin.getDefault().getConsoleManager().showConsoleView(msgConsole); - } - - return null; - } - - private void printCompilerOutputList(List outputList, MessageConsole msgConsole) { - - CompilerMessageLocation location = outputList.get(0).getMessageLocation(); - printlnToConsole(location != null ? location.getPath() : "No Location", CONSOLE_BLACK, msgConsole); - - for (CompilerOutputElement dataElement : outputList) { - RGB color = getColorByMessageSeverity(dataElement.getMessageSeverity()); - StringBuilder message = new StringBuilder(); - - message.append("\t"); - message.append(dataElement.getMessageSeverity().toString() + ": " + dataElement.getMessage()); - if (dataElement.getMessageLocation() != null) { - message.append(" (" + dataElement.getMessageLocation().getLine() + ", " + dataElement.getMessageLocation().getColumn() + ")"); - } - - printlnToConsole(message.toString(), color, msgConsole); - } - } - - private RGB getColorByMessageSeverity(CompilerMessageSeverity messageSeverity) { - RGB color = null; - switch (messageSeverity) { - case ERROR: - color = CONSOLE_RED; - break; - case WARNING: - color = CONSOLE_YELLOW; - break; - default: - color = CONSOLE_BLACK; - break; - } - - return color; - } - - private void printlnToConsole(String message, RGB color, MessageConsole msgConsole) { - MessageConsoleStream msgStream = msgConsole.newMessageStream(); - msgStream.setColor(new Color(null, color)); - - msgStream.println(message); - } - - private Map> groupOutputByPath(List outputData) { - Map> res = new HashMap>(); - String emptyPath = ""; - for (CompilerOutputElement dataElement : outputData) { - CompilerMessageLocation location = dataElement.getMessageLocation(); - String path = location != null ? location.getPath() : emptyPath; - if (!res.containsKey(path)) { - res.put(path, new ArrayList()); - } - - res.get(path).add(dataElement); - } - - return res; - } -} \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/CompilerStatusHandler.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/CompilerStatusHandler.kt new file mode 100644 index 000000000..f1d4b9d7a --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/CompilerStatusHandler.kt @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.jetbrains.kotlin.ui.launch + +import org.eclipse.core.runtime.CoreException +import org.eclipse.core.runtime.IStatus +import org.eclipse.debug.core.IStatusHandler +import org.eclipse.jdt.core.IJavaProject +import org.eclipse.swt.graphics.Color +import org.eclipse.swt.graphics.RGB +import org.eclipse.ui.console.ConsolePlugin +import org.eclipse.ui.console.MessageConsole +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.core.compiler.KotlinCompilerUtils +import org.jetbrains.kotlin.core.launch.CompilerOutputElement + +class CompilerStatusHandler : IStatusHandler { + + @Throws(CoreException::class) + override fun handleStatus(status: IStatus, source: Any): Any? { + if (source !is KotlinCompilerUtils.CompilerOutputWithProject) { + return null + } + val javaProject: IJavaProject = source.project + val outputDataList: List = source.data.list + val sortedOutput = groupOutputByPath(outputDataList) + val msgConsole = createCleanKotlinConsole(javaProject) + for (outputList in sortedOutput.values) { + printCompilerOutputList(outputList, msgConsole) + } + if (status.severity == IStatus.ERROR) { + ConsolePlugin.getDefault().consoleManager.showConsoleView(msgConsole) + } + return null + } + + private fun printCompilerOutputList(outputList: List, msgConsole: MessageConsole) { + val path = outputList[0].messageLocation?.path + msgConsole.println(path ?: "No Location", CONSOLE_BLACK) + for (dataElement in outputList) { + val color = dataElement.messageSeverity.color + val message = StringBuilder() + message.append("\t") + message.append(dataElement.messageSeverity.toString() + ": " + dataElement.message) + if (dataElement.messageLocation != null) { + message.append(" (" + dataElement.messageLocation.line + ", " + dataElement.messageLocation.column + ")") + } + msgConsole.println(message.toString(), color) + } + } + + private val CompilerMessageSeverity.color: RGB + get() = when (this) { + CompilerMessageSeverity.ERROR -> CONSOLE_RED + CompilerMessageSeverity.WARNING -> CONSOLE_YELLOW + else -> CONSOLE_BLACK + } + + private fun MessageConsole.println(message: String, color: RGB?) = newMessageStream().apply { + this.color = Color(null, color) + println(message) + } + + private fun groupOutputByPath(outputData: List): Map> { + val res: MutableMap> = HashMap() + val emptyPath = "" + for (dataElement in outputData) { + val path = dataElement.messageLocation?.path ?: emptyPath + if (!res.containsKey(path)) { + res[path] = ArrayList() + } + res[path]!!.add(dataElement) + } + return res + } + + companion object { + private val CONSOLE_RED = RGB(229, 43, 80) + private val CONSOLE_YELLOW = RGB(218, 165, 32) + private val CONSOLE_BLACK = RGB(0, 0, 0) + } +} \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinRuntimeConfigurator.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinRuntimeConfigurator.kt index 65826b918..dd5c5a389 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinRuntimeConfigurator.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinRuntimeConfigurator.kt @@ -17,7 +17,7 @@ package org.jetbrains.kotlin.ui.launch import org.eclipse.core.resources.IProject -import org.eclipse.mylyn.commons.ui.dialogs.AbstractNotificationPopup +import org.eclipse.jface.notifications.AbstractNotificationPopup import org.eclipse.swt.SWT import org.eclipse.swt.custom.StyleRange import org.eclipse.swt.custom.StyledText diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinScriptLaunchConfigurationTabGroup.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinScriptLaunchConfigurationTabGroup.kt index 212913987..723452aa4 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinScriptLaunchConfigurationTabGroup.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinScriptLaunchConfigurationTabGroup.kt @@ -2,10 +2,13 @@ package org.jetbrains.kotlin.ui.launch import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup import org.eclipse.debug.ui.ILaunchConfigurationDialog +import org.eclipse.debug.ui.CommonTab +import org.eclipse.debug.ui.ILaunchConfigurationTab import org.eclipse.jdt.debug.ui.launchConfigurations.JavaArgumentsTab class KotlinScriptLaunchConfigurationTabGroup : AbstractLaunchConfigurationTabGroup() { override fun createTabs(dialog: ILaunchConfigurationDialog, mode: String) { - setTabs(arrayOf(JavaArgumentsTab())) + val arr = arrayOf(CommonTab()) + setTabs(*arr) } } \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/kotlinConsole.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/kotlinConsole.kt index 10c1d3622..decb07cdb 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/kotlinConsole.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/kotlinConsole.kt @@ -16,24 +16,31 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui.launch +import org.eclipse.jdt.core.IJavaProject import org.eclipse.ui.console.ConsolePlugin -import org.eclipse.ui.console.IConsoleManager import org.eclipse.ui.console.MessageConsole private const val KOTLIN_CONSOLE_ID = "org.jetbrains.kotlin.ui.console" -fun createCleanKotlinConsole(): MessageConsole { - val consoleManager = ConsolePlugin.getDefault().getConsoleManager() - removeKotlinConsoles(consoleManager) - - val messageConsole = MessageConsole(KOTLIN_CONSOLE_ID, null) - consoleManager.addConsoles(arrayOf(messageConsole)) - +private val manager get() = ConsolePlugin.getDefault().consoleManager + +private val IJavaProject.consoleName get() = "$KOTLIN_CONSOLE_ID.${project.name}" + +fun createCleanKotlinConsole(javaProject: IJavaProject): MessageConsole { + removeKotlinConsoles(javaProject) + + return createNewKotlinConsole(javaProject) +} + +private fun createNewKotlinConsole(javaProject: IJavaProject): MessageConsole { + val messageConsole = MessageConsole(javaProject.consoleName, null) + manager.addConsoles(arrayOf(messageConsole)) + return messageConsole } -fun removeKotlinConsoles(manager: IConsoleManager) { +fun removeKotlinConsoles(javaProject: IJavaProject) { manager.removeConsoles(manager.consoles - .filter { it.name == KOTLIN_CONSOLE_ID } + .filter { it.name == javaProject.consoleName } .toTypedArray()) } \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/navigation/KotlinOpenEditor.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/navigation/KotlinOpenEditor.java index c3c02d09f..1ca747d95 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/navigation/KotlinOpenEditor.java +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/navigation/KotlinOpenEditor.java @@ -6,8 +6,10 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.ISourceReference; import org.eclipse.jdt.internal.core.BinaryType; import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; import org.eclipse.ui.IEditorPart; @@ -17,6 +19,7 @@ import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.core.builder.KotlinPsiManager; @@ -30,8 +33,11 @@ import org.jetbrains.kotlin.ui.editors.KotlinEditor; // Seeks Kotlin editor by IJavaElement +@SuppressWarnings("restriction") public class KotlinOpenEditor { - @Nullable + private static final String CLASS_WITHOUT_SOURCE = "*.class without source"; + + @Nullable public static IEditorPart openKotlinEditor(@NotNull IJavaElement element, boolean activate) { List sourceFiles = findSourceFiles(element); @@ -66,7 +72,7 @@ public static List findSourceFiles(@NotNull IJavaElement element) { } File lightClass = resource.getFullPath().toFile(); - List sourceFiles = KotlinLightClassManager + List sourceFiles = KotlinLightClassManager.Companion .getInstance(element.getJavaProject().getProject()).getSourceFiles(lightClass); KtFile navigationFile = KotlinOpenEditorUtilsKt.findNavigationFileFromSources(element, sourceFiles); @@ -112,7 +118,7 @@ public static IEditorPart openKotlinClassFileEditor(@NotNull IJavaElement elemen IWorkbenchPage page = win.getActivePage(); try { - IEditorPart reusedEditor = page.openEditor(editorInput, KotlinClassFileEditor.Companion.getEDITOR_ID(), activate); + IEditorPart reusedEditor = page.openEditor(editorInput, resolveEditorID((ISourceReference)element), activate); if (reusedEditor != null) { // the input is compared by a source path, but corresponding // classes may be different @@ -121,9 +127,17 @@ public static IEditorPart openKotlinClassFileEditor(@NotNull IJavaElement elemen page.reuseEditor((IReusableEditor) reusedEditor, editorInput); } return reusedEditor; - } catch (PartInitException e) { + } catch (CoreException e) { KotlinLogger.logAndThrow(e); } return null; } + + private static String resolveEditorID(@NotNull ISourceReference reference) throws CoreException { + // if no source let the java decompiler handle it. + if(reference.getSourceRange() != null && reference.getSourceRange().getLength() > 0) { + return KotlinClassFileEditor.Companion.getEDITOR_ID(); + } + return IDE.getEditorDescriptor(CLASS_WITHOUT_SOURCE, true, false).getId(); + } } diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/overrideImplement/KotlinOverrideMembersAction.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/overrideImplement/KotlinOverrideMembersAction.kt index d8d8e907c..cb7350991 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/overrideImplement/KotlinOverrideMembersAction.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/overrideImplement/KotlinOverrideMembersAction.kt @@ -25,11 +25,7 @@ import org.eclipse.jface.text.ITextSelection import org.eclipse.jface.window.Window import org.eclipse.ui.PlatformUI import org.eclipse.ui.dialogs.CheckedTreeSelectionDialog -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.ui.editors.KotlinCommonEditor @@ -113,7 +109,7 @@ public class KotlinOverrideMembersAction( if (member is CallableMemberDescriptor && (member.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE || member.kind == CallableMemberDescriptor.Kind.DELEGATION)) { val overridden = member.overriddenDescriptors - if (overridden.any { it.modality == Modality.FINAL || Visibilities.isPrivate(it.visibility.normalize()) }) continue + if (overridden.any { it.modality == Modality.FINAL || DescriptorVisibilities.isPrivate(it.visibility.normalize()) }) continue class Data( val realSuper: CallableMemberDescriptor, diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/extract/KotlinExtractVariableRefactoring.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/extract/KotlinExtractVariableRefactoring.kt index 2b99b80dc..f5e0fc31b 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/extract/KotlinExtractVariableRefactoring.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/extract/KotlinExtractVariableRefactoring.kt @@ -30,27 +30,15 @@ import org.eclipse.ltk.core.refactoring.Refactoring import org.eclipse.ltk.core.refactoring.RefactoringStatus import org.eclipse.ltk.core.refactoring.TextFileChange import org.eclipse.text.edits.ReplaceEdit +import org.jetbrains.kotlin.core.utils.getBindingContext import org.jetbrains.kotlin.eclipse.ui.utils.IndenterUtil import org.jetbrains.kotlin.eclipse.ui.utils.LineEndUtil -import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.eclipse.ui.utils.getOffsetByDocument import org.jetbrains.kotlin.eclipse.ui.utils.getTextDocumentOffset import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiUnifier import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtArrayAccessExpression -import org.jetbrains.kotlin.psi.KtBlockExpression -import org.jetbrains.kotlin.psi.KtBlockStringTemplateEntry -import org.jetbrains.kotlin.psi.KtClassBody -import org.jetbrains.kotlin.psi.KtContainerNode -import org.jetbrains.kotlin.psi.KtDeclarationWithBody -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtIfExpression -import org.jetbrains.kotlin.psi.KtLoopExpression -import org.jetbrains.kotlin.psi.KtStringTemplateEntryWithExpression -import org.jetbrains.kotlin.psi.KtWhenEntry +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.canPlaceAfterSimpleNameEntry import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement @@ -104,7 +92,7 @@ public class KotlinExtractVariableRefactoring(val selection: ITextSelection, val } val variableDeclarationText = "val $newName = ${expression.getText()}" - val bindingContext = getBindingContext(expression) ?: return emptyList() + val bindingContext = expression.getBindingContext() return createEdits( commonContainer, diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/KotlinRenameParticipant.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/KotlinRenameParticipant.kt index 4c74f0d34..d186de726 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/KotlinRenameParticipant.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/KotlinRenameParticipant.kt @@ -106,19 +106,15 @@ open class KotlinRenameParticipant : RenameParticipant() { val jetElement = match.jetElement - val eclipseFile = KotlinPsiManager.getEclipseFile(jetElement.getContainingKtFile()) - if (eclipseFile == null) return null - + val eclipseFile = KotlinPsiManager.getEclipseFile(jetElement.containingKtFile) ?: return null + val document = EditorUtil.getDocument(eclipseFile) // TODO: make workaround here later - val textLength = getLengthOfIdentifier(jetElement) - return if (textLength != null) { - FileEdit( - eclipseFile, - ReplaceEdit(jetElement.getTextDocumentOffset(document), textLength, newName)) - } else { - null - } + val textLength = getLengthOfIdentifier(jetElement) ?: return null + + return FileEdit( + eclipseFile, + ReplaceEdit(jetElement.getTextDocumentOffset(document), textLength, newName)) } private fun obtainOriginElement(javaElement: IJavaElement): IJavaElement { @@ -130,4 +126,4 @@ open class KotlinRenameParticipant : RenameParticipant() { } } -data class FileEdit(val file: IFile, val edit: TextEdit) \ No newline at end of file +data class FileEdit(val file: IFile, val edit: TextEdit) diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/lightEclipseElements.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/lightEclipseElements.kt index 40848d70d..00604b6b8 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/lightEclipseElements.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/lightEclipseElements.kt @@ -32,7 +32,9 @@ import org.eclipse.jdt.core.IImportDeclaration import org.eclipse.jdt.core.IInitializer import org.eclipse.jdt.core.IJavaElement import org.eclipse.jdt.core.IJavaModel +import org.eclipse.jdt.internal.core.JavaModel import org.eclipse.jdt.core.IJavaProject +import org.eclipse.jdt.internal.core.JavaProject import org.eclipse.jdt.core.IMethod import org.eclipse.jdt.core.IOpenable import org.eclipse.jdt.core.IPackageFragment @@ -79,7 +81,7 @@ class KotlinLightType(val originElement: IType) : override fun getNameRange(): ISourceRange = DUMMY_NAME_RANGE - override fun getPrimaryElement(): IJavaElement? = this + override fun getPrimaryElement(): JavaElement = this as JavaElement override fun isBinary(): Boolean = false @@ -281,9 +283,9 @@ class KotlinLightType(val originElement: IType) : override fun getSuperInterfaceNames(): Array? = originElement.getSuperInterfaceNames() - override fun getJavaModel(): IJavaModel? = originElement.getJavaModel() + override fun getJavaModel(): JavaModel = originElement.getJavaModel() as JavaModel - override fun getParent(): IJavaElement? = originElement.getParent() + override fun getParent(): JavaElement = originElement.getParent() as JavaElement override fun getChildren(): Array? = originElement.getChildren() @@ -311,7 +313,7 @@ class KotlinLightType(val originElement: IType) : return originElement.createMethod(contents, sibling, force, monitor) } - override fun getJavaProject(): IJavaProject? = originElement.getJavaProject() + override fun getJavaProject(): JavaProject = originElement.getJavaProject() as JavaProject override fun move(container: IJavaElement?, sibling: IJavaElement?, rename: String?, replace: Boolean, monitor: IProgressMonitor?) { originElement.move(container, sibling, rename, replace, monitor) diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/refactoringUtils.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/refactoringUtils.kt index 742572a86..5584ac2cb 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/refactoringUtils.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/refactorings/rename/refactoringUtils.kt @@ -22,8 +22,8 @@ import org.jetbrains.kotlin.psi.KtReferenceExpression fun getLengthOfIdentifier(jetElement: KtElement): Int? { return when (jetElement) { - is KtNamedDeclaration -> jetElement.getNameIdentifier()!!.getTextLength() + is KtNamedDeclaration -> jetElement.nameIdentifier!!.textLength is KtReferenceExpression -> jetElement.getTextLength() else -> null } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinElementMatchCreator.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinElementMatchCreator.kt new file mode 100644 index 000000000..f4340f5f1 --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinElementMatchCreator.kt @@ -0,0 +1,69 @@ +package org.jetbrains.kotlin.ui.search + +import com.intellij.psi.util.PsiTreeUtil +import org.eclipse.jdt.ui.search.QuerySpecification +import org.eclipse.search.ui.text.Match +import org.jetbrains.kotlin.core.utils.getBindingContext +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.resolve.calls.util.getCall +import org.jetbrains.kotlin.ui.commands.findReferences.KotlinFindImplementationsInProjectAction + +interface KotlinElementMatchCreator { + + fun createMatch(element: KtElement): Match? + + companion object { + fun getMatchCreator(querySpecification: QuerySpecification) = when (querySpecification.limitTo) { + KotlinFindImplementationsInProjectAction.IMPLEMENTORS_LIMIT_TO -> InheritorsSearchMatchCreator + else -> BasicSearchMatchCreator + } + } +} + +object InheritorsSearchMatchCreator : KotlinElementMatchCreator { + override fun createMatch(element: KtElement): Match? { + val (descriptor: DeclarationDescriptor?, nameIdentifier) = when (element) { + is KtNamedFunction -> element.resolveToDescriptorIfAny() to element.nameIdentifier + is KtClass -> element.resolveToDescriptorIfAny() to element.nameIdentifier + is KtProperty -> element.resolveToDescriptorIfAny() to element.nameIdentifier + is KtObjectDeclaration -> element.resolveToDescriptorIfAny() to element.nameIdentifier + else -> return null + } + val tempLabel = + descriptor?.let { DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(it) } ?: BasicSearchMatchCreator.render( + element + ) + + return KotlinElementMatch(element, tempLabel, nameIdentifier ?: element) + } + +} + +object BasicSearchMatchCreator : KotlinElementMatchCreator { + + override fun createMatch(element: KtElement): Match { + return KotlinElementMatch(element, render(element), element) + } + + fun render(element: KtElement): String { + val tempElement = element.getCall(element.getBindingContext())?.toString() ?: element.text + + val tempParentDescriptor = + PsiTreeUtil.getParentOfType(element, KtDeclaration::class.java)?.resolveToDescriptorIfAny() + + return buildString { + append(tempElement.lines().first()) + if (tempParentDescriptor != null) { + append(" in ") + append(DescriptorRenderer.SHORT_NAMES_IN_TYPES.withOptions { + modifiers = emptySet() + includeAdditionalModifiers = false + }.render(tempParentDescriptor)) + } + } + } + +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinQueryParticipant.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinQueryParticipant.kt index 3167e4e60..c261800d5 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinQueryParticipant.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinQueryParticipant.kt @@ -16,245 +16,352 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui.search +import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil import org.eclipse.core.resources.IFile +import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IResource -import org.eclipse.core.runtime.CoreException +import org.eclipse.core.runtime.IAdaptable import org.eclipse.core.runtime.IProgressMonitor +import org.eclipse.core.runtime.ISafeRunnable import org.eclipse.jdt.core.IJavaElement +import org.eclipse.jdt.core.IType +import org.eclipse.jdt.core.search.IJavaSearchScope +import org.eclipse.jdt.internal.core.JavaModel +import org.eclipse.jdt.internal.ui.search.AbstractJavaSearchResult +import org.eclipse.jdt.internal.ui.search.JavaSearchQuery import org.eclipse.jdt.ui.search.ElementQuerySpecification -import org.eclipse.jdt.ui.search.IMatchPresentation import org.eclipse.jdt.ui.search.IQueryParticipant import org.eclipse.jdt.ui.search.ISearchRequestor import org.eclipse.jdt.ui.search.QuerySpecification -import org.eclipse.search.internal.ui.text.FileSearchQuery +import org.eclipse.jface.resource.ImageDescriptor +import org.eclipse.jface.util.SafeRunnable +import org.eclipse.search.internal.ui.text.FileSearchResult import org.eclipse.search.ui.ISearchResult import org.eclipse.search.ui.text.FileTextSearchScope -import org.eclipse.core.resources.ResourcesPlugin +import org.eclipse.search.ui.text.Match +import org.eclipse.search.ui.text.TextSearchQueryProvider.TextSearchInput +import org.eclipse.search2.internal.ui.text2.DefaultTextSearchQueryProvider +import org.eclipse.ui.model.IWorkbenchAdapter import org.jetbrains.kotlin.core.builder.KotlinPsiManager -import com.intellij.psi.PsiElement -import org.eclipse.search.internal.ui.text.FileSearchResult -import org.jetbrains.kotlin.eclipse.ui.utils.findElementByDocumentOffset -import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil -import org.jetbrains.kotlin.core.references.getReferenceExpression +import org.jetbrains.kotlin.core.log.KotlinLogger +import org.jetbrains.kotlin.core.model.sourceElementsToLightElements import org.jetbrains.kotlin.core.references.resolveToSourceDeclaration -import java.util.ArrayList -import org.jetbrains.kotlin.core.references.KotlinReference -import org.jetbrains.kotlin.core.model.KotlinAnalysisProjectCache -import org.eclipse.search.ui.text.Match -import org.eclipse.jface.viewers.ILabelProvider -import org.jetbrains.kotlin.ui.editors.outline.PsiLabelProvider -import org.eclipse.jface.viewers.LabelProvider -import org.jetbrains.kotlin.psi.KtElement -import org.eclipse.jdt.internal.core.JavaModel -import org.eclipse.core.resources.IProject -import org.jetbrains.kotlin.core.references.createReferences -import org.eclipse.core.runtime.IAdaptable -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.core.asJava.getDeclaringTypeFqName -import org.eclipse.jdt.core.IJavaProject -import org.eclipse.jdt.core.IMethod -import org.eclipse.jdt.core.IMember -import org.eclipse.jdt.core.search.SearchPattern -import org.eclipse.jdt.core.IType -import org.eclipse.jdt.core.IField -import org.eclipse.jdt.core.JavaCore -import org.jetbrains.kotlin.resolve.source.KotlinSourceElement +import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.core.model.sourceElementsToLightElements -import org.eclipse.jface.util.SafeRunnable -import org.eclipse.core.runtime.ISafeRunnable -import org.jetbrains.kotlin.core.log.KotlinLogger -import org.eclipse.jdt.internal.ui.search.JavaSearchQuery -import org.eclipse.jdt.internal.ui.search.AbstractJavaSearchResult -import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression -import org.jetbrains.kotlin.core.model.KotlinAnalysisFileCache -import org.jetbrains.kotlin.ui.commands.findReferences.KotlinScopedQuerySpecification -import org.eclipse.jdt.core.search.IJavaSearchScope -import org.jetbrains.kotlin.ui.commands.findReferences.KotlinJavaQuerySpecification -import org.jetbrains.kotlin.ui.commands.findReferences.KotlinOnlyQuerySpecification -import org.jetbrains.kotlin.ui.commands.findReferences.KotlinAndJavaSearchable -import org.jetbrains.kotlin.ui.commands.findReferences.KotlinScoped -import org.jetbrains.kotlin.psi.KtConstructor -import org.eclipse.search2.internal.ui.text2.DefaultTextSearchQueryProvider -import org.eclipse.search.ui.text.TextSearchQueryProvider.TextSearchInput +import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil +import org.jetbrains.kotlin.eclipse.ui.utils.findElementByDocumentOffset +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny +import org.jetbrains.kotlin.lexer.KtSingleValueToken +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.resolve.source.KotlinSourceElement +import org.jetbrains.kotlin.types.expressions.OperatorConventions +import org.jetbrains.kotlin.ui.commands.findReferences.* + +class KotlinQueryParticipant : IQueryParticipant { + + private inner class DelegatedUniqueMatchSearchRequestor( + private val delegate: ISearchRequestor, + private val querySpecification: QuerySpecification + ) : ISearchRequestor { -public class KotlinQueryParticipant : IQueryParticipant { - override public fun search(requestor: ISearchRequestor, querySpecification: QuerySpecification, monitor: IProgressMonitor?) { + private val seenMatches: MutableSet = mutableSetOf() + override fun reportMatch(match: Match) { + val tempElement = match.element + if ((match is KotlinElementMatch && !seenMatches.add(match.jetElement)) || (tempElement is IJavaElement && !seenMatches.add(tempElement))) return + + delegate.reportMatch(match) + + if (querySpecification.limitTo == KotlinFindImplementationsInProjectAction.IMPLEMENTORS_LIMIT_TO && match is KotlinElementMatch && match.jetElement is KtClass) { + val tempNewSpec = KotlinOnlyQuerySpecification( + match.jetElement, + querySpecification.getFilesInScope(), + KotlinFindImplementationsInProjectAction.IMPLEMENTORS_LIMIT_TO, + querySpecification.scopeDescription + ) + search(this, tempNewSpec, null) + } + } + } + + override fun search( + requestor: ISearchRequestor, + querySpecification: QuerySpecification, + monitor: IProgressMonitor? + ) { SafeRunnable.run(object : ISafeRunnable { override fun run() { + val tempRequestor = + requestor as? DelegatedUniqueMatchSearchRequestor ?: DelegatedUniqueMatchSearchRequestor( + requestor, + querySpecification + ) val searchElements = getSearchElements(querySpecification) if (searchElements.isEmpty()) return - + if (querySpecification is KotlinAndJavaSearchable) { - runCompositeSearch(searchElements, requestor, querySpecification, monitor) + runCompositeSearch(searchElements, tempRequestor, querySpecification, monitor) return } - + val kotlinFiles = getKotlinFilesByScope(querySpecification) if (kotlinFiles.isEmpty()) return - + if (monitor?.isCanceled == true) return + if (searchElements.size > 1) { KotlinLogger.logWarning("There are more than one elements to search: $searchElements") } - + // We assume that there is only one search element, it could be IJavaElement or KtElement val searchElement = searchElements.first() - val searchResult = searchTextOccurrences(searchElement, kotlinFiles) - if (searchResult == null) return - - val elements = obtainElements(searchResult as FileSearchResult, kotlinFiles) + val searchResult = searchTextOccurrences(searchElement, kotlinFiles) ?: return + if (monitor?.isCanceled == true) return + + val elements = obtainElements(searchResult as FileSearchResult, kotlinFiles).flatMap { + val tempImportAlias = it.getParentOfType(false)?.alias + + if (tempImportAlias != null) { + val tempEclipseFile = KotlinPsiManager.getEclipseFile(tempImportAlias.containingKtFile)!! + val tempResult = searchTextOccurrences( + SearchElement.KotlinSearchElement(tempImportAlias), + listOf(tempEclipseFile) + ) + return@flatMap obtainElements(tempResult as FileSearchResult, listOf(tempEclipseFile)) + it + } + + listOf(it) + } + + if (monitor?.isCanceled == true) return val matchedReferences = resolveElementsAndMatch(elements, searchElement, querySpecification) - - matchedReferences.forEach { requestor.reportMatch(KotlinElementMatch(it)) } + if (monitor?.isCanceled == true) return + matchedReferences.forEach { ktElement -> + val tempCreator = KotlinElementMatchCreator.getMatchCreator(querySpecification) + tempCreator.createMatch(ktElement)?.let { tempRequestor.reportMatch(it) } + } } - + override fun handleException(exception: Throwable) { KotlinLogger.logError(exception) } }) } - - override public fun estimateTicks(specification: QuerySpecification): Int = 500 - - override public fun getUIParticipant() = KotlinReferenceMatchPresentation() - - private fun runCompositeSearch(elements: List, requestor: ISearchRequestor, originSpecification: QuerySpecification, - monitor: IProgressMonitor?) { - + + override fun estimateTicks(specification: QuerySpecification): Int = 500 + + override fun getUIParticipant() = KotlinReferenceMatchPresentation() + + private fun runCompositeSearch( + elements: List, requestor: ISearchRequestor, originSpecification: QuerySpecification, + monitor: IProgressMonitor? + ) { + + fun reportMatch(match: Match) { + val tempElement = match.element + if (tempElement is IJavaElement && EclipseJavaElementUtil.isFromKotlinBinFolder(tempElement)) { + return + } + requestor.reportMatch(match) + } + fun reportSearchResults(result: AbstractJavaSearchResult) { - for (searchElement in result.getElements()) { - result.getMatches(searchElement).forEach { requestor.reportMatch(it) } + for (searchElement in result.elements) { + result.getMatches(searchElement).forEach { match -> + reportMatch(match) + } } } - - val specifications = elements.map { searchElement -> + + val specifications = elements.map { searchElement -> when (searchElement) { - is SearchElement.JavaSearchElement -> + is SearchElement.JavaSearchElement -> ElementQuerySpecification( - searchElement.javaElement, - originSpecification.getLimitTo(), - originSpecification.getScope(), - originSpecification.getScopeDescription()) - - is SearchElement.KotlinSearchElement -> + searchElement.javaElement, + originSpecification.limitTo, + originSpecification.scope, + originSpecification.scopeDescription + ) + + is SearchElement.KotlinSearchElement -> KotlinOnlyQuerySpecification( searchElement.kotlinElement, - originSpecification.getFilesInScope(), - originSpecification.getLimitTo(), - originSpecification.getScopeDescription()) + originSpecification.getFilesInScope(), + originSpecification.limitTo, + originSpecification.scopeDescription + ) } } - - if (originSpecification is KotlinScoped) { - for (specification in specifications) { - KotlinQueryParticipant().search({ requestor.reportMatch(it) }, specification, monitor) - } - } else { - for (specification in specifications) { + + for (specification in specifications) { + if (specification is KotlinScoped) { + search(requestor, specification, monitor) + } else if (specification is ElementQuerySpecification && specification.limitTo == KotlinFindImplementationsInProjectAction.IMPLEMENTORS_LIMIT_TO && specification.element is IType) { + //We need this workaround to find java subclasses! + val tempElement = specification.element as IType + val tempSubTypes = tempElement.newTypeHierarchy(monitor).getAllSubtypes(tempElement) + for (tempMatch in tempSubTypes.map { Match(it, it.nameRange.offset, it.nameRange.length) }) { + reportMatch(tempMatch) + } + } else { val searchQuery = JavaSearchQuery(specification) searchQuery.run(monitor) - reportSearchResults(searchQuery.getSearchResult() as AbstractJavaSearchResult) + reportSearchResults(searchQuery.searchResult as AbstractJavaSearchResult) } } } - + sealed class SearchElement private constructor() { abstract fun getSearchText(): String? - + class JavaSearchElement(val javaElement: IJavaElement) : SearchElement() { - override fun getSearchText(): String = javaElement.getElementName() + override fun getSearchText(): String = javaElement.elementName } - + class KotlinSearchElement(val kotlinElement: KtElement) : SearchElement() { - override fun getSearchText(): String? = kotlinElement.getName() + override fun getSearchText(): String? = kotlinElement.name } } - - + + private fun getSearchElements(querySpecification: QuerySpecification): List { fun obtainSearchElements(sourceElements: List): List { val (javaElements, kotlinElements) = getJavaAndKotlinElements(sourceElements) - return javaElements.map { SearchElement.JavaSearchElement(it) } + - kotlinElements.map { SearchElement.KotlinSearchElement(it) } - + return javaElements.map { SearchElement.JavaSearchElement(it) } + + kotlinElements.map { SearchElement.KotlinSearchElement(it) } + } - + return when (querySpecification) { - is ElementQuerySpecification -> listOf(SearchElement.JavaSearchElement(querySpecification.getElement())) + is ElementQuerySpecification -> listOf(SearchElement.JavaSearchElement(querySpecification.element)) is KotlinOnlyQuerySpecification -> listOf(SearchElement.KotlinSearchElement(querySpecification.kotlinElement)) is KotlinAndJavaSearchable -> obtainSearchElements(querySpecification.sourceElements) else -> emptyList() } } - + private fun searchTextOccurrences(searchElement: SearchElement, filesScope: List): ISearchResult? { - val searchText = searchElement.getSearchText() - if (searchText == null) return null - + var searchText = searchElement.getSearchText() ?: return null + var asRegex = false + + if (searchElement is SearchElement.KotlinSearchElement) { + if (searchElement.kotlinElement is KtFunction) { + //Either it has an operator keyword directly, or it overrides something. In this case we could look in the overridden element, or we could just try to search for it! + if (searchElement.kotlinElement.hasModifier(KtTokens.OPERATOR_KEYWORD)) { + val pair = getSearchTextAsRegex(searchText) + asRegex = pair.first + searchText = pair.second + } else if (searchElement.kotlinElement.hasModifier(KtTokens.OVERRIDE_KEYWORD)) { + val tempDescriptor = searchElement.kotlinElement.resolveToDescriptorIfAny() as? FunctionDescriptor + if (tempDescriptor?.isOperator == true) { + val pair = getSearchTextAsRegex(searchText) + asRegex = pair.first + searchText = pair.second + } + } + } + } + val scope = FileTextSearchScope.newSearchScope(filesScope.toTypedArray(), null as Array?, false) - + val query = DefaultTextSearchQueryProvider().createQuery(object : TextSearchInput() { - override fun isWholeWordSearch(): Boolean = true - + override fun isWholeWordSearch(): Boolean = !asRegex + override fun getSearchText(): String = searchText - + override fun isCaseSensitiveSearch(): Boolean = true - - override fun isRegExSearch(): Boolean = false - + + override fun isRegExSearch(): Boolean = asRegex + override fun getScope(): FileTextSearchScope = scope }) - + query.run(null) - - return query.getSearchResult() + + return query.searchResult + } + + private fun getSearchTextAsRegex( + searchText: String + ): Pair { + val tempOperationSymbol = + (OperatorConventions.getOperationSymbolForName(Name.identifier(searchText)) as? KtSingleValueToken)?.value?.let { "\\Q$it\\E" } + ?: when (searchText) { + "get" -> "\\[.*?]" + "set" -> "\\[.*?]\\s*?=" + "invoke" -> "\\(.*?\\)" + "contains" -> "in|!in" + "getValue", "setValue", "provideDelegate" -> "by" + else -> null + } + if (tempOperationSymbol != null) { + return Pair(true, "(\\b$searchText\\b|$tempOperationSymbol)") + } + return Pair(false, searchText) } - - private fun resolveElementsAndMatch(elements: List, searchElement: SearchElement, - querySpecification: QuerySpecification): List { + + private fun resolveElementsAndMatch( + elements: List, searchElement: SearchElement, + querySpecification: QuerySpecification + ): List { val beforeResolveFilters = getBeforeResolveFilters(querySpecification) - val afterResolveFilters = getAfterResolveFilters() - + val afterResolveFilters = getAfterResolveFilters(querySpecification) + val mapper = SearchParentObjectMapper.getMapper(querySpecification) + // This is important for optimization: - // we will consequentially cache files one by one which are containing these references - val sortedByFileNameElements = elements.sortedBy { it.getContainingKtFile().getName() } - - return sortedByFileNameElements.filter { element -> - val beforeResolveCheck = beforeResolveFilters.all { it.isApplicable(element) } - if (!beforeResolveCheck) return@filter false - - val sourceElements = element.resolveToSourceDeclaration() - if (sourceElements.isEmpty()) return@filter false - + // we will consequentially cache files one by one which do contain these references + val sortedByFileNameElements = elements.sortedBy { it.containingKtFile.name } + + return sortedByFileNameElements.flatMap { element -> + val tempElement = findApplicableElement(element, beforeResolveFilters, mapper) ?: return@flatMap emptyList() + + val sourceElements = tempElement.resolveToSourceDeclaration() + if (sourceElements.isEmpty()) return@flatMap emptyList() + val additionalElements = getContainingClassOrObjectForConstructor(sourceElements) - - return@filter afterResolveFilters.all { it.isApplicable(sourceElements, searchElement) } || - afterResolveFilters.all { it.isApplicable(additionalElements, searchElement) } + + if (afterResolveFilters.all { it.isApplicable(sourceElements, searchElement) } || + afterResolveFilters.all { it.isApplicable(additionalElements, searchElement) }) { + return@flatMap listOf(tempElement) + } + emptyList() } } - + + private fun findApplicableElement( + element: KtElement, beforeResolveFilters: List, mapper: SearchParentObjectMapper + ): KtElement? { + if (beforeResolveFilters.all { it.isApplicable(element) }) return element + return mapper.map(element)?.takeIf { refExp -> + beforeResolveFilters.all { it.isApplicable(refExp) } + } + } + private fun obtainElements(searchResult: FileSearchResult, files: List): List { val elements = ArrayList() for (file in files) { val matches = searchResult.getMatches(file) val jetFile = KotlinPsiManager.getParsedFile(file) val document = EditorUtil.getDocument(file) - + matches - .map { - val element = jetFile.findElementByDocumentOffset(it.getOffset(), document) + .map { match -> + val element = jetFile.findElementByDocumentOffset(match.offset, document) element?.let { PsiTreeUtil.getNonStrictParentOfType(it, KtElement::class.java) } } .filterNotNullTo(elements) } - + return elements } - + private fun getKotlinFilesByScope(querySpecification: QuerySpecification): List { return when (querySpecification) { is ElementQuerySpecification, - is KotlinJavaQuerySpecification -> querySpecification.getScope().getKotlinFiles() + is KotlinJavaQuerySpecification -> querySpecification.scope.getKotlinFiles() is KotlinScoped -> querySpecification.searchScope else -> emptyList() } @@ -269,34 +376,30 @@ fun getContainingClassOrObjectForConstructor(sourceElements: List return@mapNotNull KotlinSourceElement(psi.getContainingClassOrObject()) } } - + null } } -fun getJavaAndKotlinElements(sourceElements: List): Pair, List> { +fun getJavaAndKotlinElements( + sourceElements: List +): Pair, List> { val javaElements = sourceElementsToLightElements(sourceElements) - - // Filter out Kotlin elements which have light elements because Javas search will call KotlinQueryParticipant - // to look up for these elements - val kotlinElements = sourceElementsToKotlinElements(sourceElements).filterNot { kotlinElement -> - javaElements.any { it.getElementName() == kotlinElement.getName() } - } - + val kotlinElements = sourceElementsToKotlinElements(sourceElements) return Pair(javaElements, kotlinElements) } private fun sourceElementsToKotlinElements(sourceElements: List): List { return sourceElements - .filterIsInstance(KotlinSourceElement::class.java) - .map { it.psi } + .filterIsInstance(KotlinSourceElement::class.java) + .map { it.psi } } fun IJavaSearchScope.getKotlinFiles(): List { return enclosingProjectsAndJars() - .map { JavaModel.getTarget(it, true) } - .filterIsInstance(IProject::class.java) - .flatMap { KotlinPsiManager.getFilesByProject(it) } + .map { JavaModel.getTarget(it, true) } + .filterIsInstance(IProject::class.java) + .flatMap { KotlinPsiManager.getFilesByProject(it) } } fun QuerySpecification.getFilesInScope(): List { @@ -306,16 +409,28 @@ fun QuerySpecification.getFilesInScope(): List { } } -public class KotlinElementMatch(val jetElement: KtElement) : Match(KotlinAdaptableElement(jetElement), jetElement.getTextOffset(), - jetElement.getTextOffset()) +class KotlinElementMatch(val jetElement: KtElement, val label: String, val identifier: PsiElement) : + Match(KotlinAdaptableElement(jetElement, label), identifier.textOffset, identifier.textLength) -class KotlinAdaptableElement(val jetElement: KtElement): IAdaptable { +class KotlinAdaptableElement(val jetElement: KtElement, val label: String) : IAdaptable { @Suppress("UNCHECKED_CAST") override fun getAdapter(adapter: Class?): T? { return when { IResource::class.java == adapter -> - KotlinPsiManager.getEclipseFile(jetElement.getContainingKtFile()) as T + KotlinPsiManager.getEclipseFile(jetElement.containingKtFile) as T + IWorkbenchAdapter::class.java == adapter -> + object : IWorkbenchAdapter { + override fun getChildren(p0: Any?): Array = emptyArray() + + override fun getImageDescriptor(p0: Any?): ImageDescriptor? = null + + override fun getLabel(p0: Any?): String = label + + override fun getParent(p0: Any?): Any? = + KotlinPsiManager.getEclipseFile(jetElement.containingKtFile) + + } as T else -> null } } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinReferenceMatchPresentation.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinReferenceMatchPresentation.kt index 10960a032..d4cbfa9d2 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinReferenceMatchPresentation.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/KotlinReferenceMatchPresentation.kt @@ -16,39 +16,22 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui.search +import com.intellij.psi.util.PsiTreeUtil import org.eclipse.jdt.ui.search.IMatchPresentation import org.eclipse.jface.viewers.ILabelProvider -import org.eclipse.search.ui.text.Match import org.eclipse.jface.viewers.LabelProvider -import org.jetbrains.kotlin.psi.KtReferenceExpression -import org.eclipse.swt.graphics.Image -import com.intellij.psi.util.PsiTreeUtil -import org.eclipse.jdt.ui.JavaUI -import org.eclipse.jdt.ui.ISharedImages -import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil -import org.jetbrains.kotlin.eclipse.ui.utils.getTextDocumentOffset import org.eclipse.search.internal.ui.text.EditorOpener -import org.eclipse.core.resources.ResourcesPlugin +import org.eclipse.search.ui.text.Match +import org.eclipse.swt.graphics.Image import org.eclipse.ui.PlatformUI +import org.jetbrains.kotlin.core.asJava.getTypeFqName import org.jetbrains.kotlin.core.builder.KotlinPsiManager -import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider -import org.eclipse.jface.viewers.StyledString -import org.eclipse.jface.viewers.ITreeContentProvider -import org.eclipse.jface.viewers.Viewer -import org.eclipse.jdt.ui.JavaElementLabels -import org.eclipse.jdt.internal.corext.util.Strings -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.ui.editors.completion.KotlinCompletionUtils -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil import org.jetbrains.kotlin.eclipse.ui.utils.KotlinImageProvider -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.core.asJava.getTypeFqName +import org.jetbrains.kotlin.eclipse.ui.utils.getTextDocumentOffset +import org.jetbrains.kotlin.psi.* -public class KotlinReferenceMatchPresentation : IMatchPresentation { +class KotlinReferenceMatchPresentation : IMatchPresentation { private val editorOpener = EditorOpener() override fun createLabelProvider(): ILabelProvider = KotlinReferenceLabelProvider() @@ -56,32 +39,31 @@ public class KotlinReferenceMatchPresentation : IMatchPresentation { override fun showMatch(match: Match, currentOffset: Int, currentLength: Int, activate: Boolean) { if (match !is KotlinElementMatch) return + val identifier = match.identifier val element = match.jetElement - val eclipseFile = KotlinPsiManager.getEclipseFile(element.getContainingKtFile()) + val eclipseFile = KotlinPsiManager.getEclipseFile(element.containingKtFile) if (eclipseFile != null) { val document = EditorUtil.getDocument(eclipseFile) editorOpener.openAndSelect( - PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), - eclipseFile, - element.getTextDocumentOffset(document), - element.getTextLength(), - activate) + PlatformUI.getWorkbench().activeWorkbenchWindow.activePage, + eclipseFile, + identifier.getTextDocumentOffset(document), + identifier.textLength, + activate + ) } } } -public class KotlinReferenceLabelProvider : LabelProvider() { +class KotlinReferenceLabelProvider : LabelProvider() { override fun getText(element: Any): String { if (element !is KotlinAdaptableElement) { throw IllegalArgumentException("KotlinReferenceLabelProvider asked for non-reference expression: $element") } - - val declaration = getContainingDeclaration(element.jetElement) - return when (declaration) { - is KtNamedDeclaration -> declaration.let { - with (it) { - getFqName()?.asString() ?: getNameAsSafeName().asString() - } + + return when (val declaration = getContainingDeclaration(element.jetElement)) { + is KtNamedDeclaration -> with (declaration) { + fqName?.asString() ?: nameAsSafeName.asString() } is KtFile -> getTypeFqName(declaration)?.asString() ?: "" else -> "" @@ -91,7 +73,7 @@ public class KotlinReferenceLabelProvider : LabelProvider() { override fun getImage(element: Any): Image? { val jetElement = (element as KotlinAdaptableElement).jetElement val containingDeclaration = getContainingDeclaration(jetElement) - return containingDeclaration?.let { KotlinImageProvider.getImage(it) } ?: null + return containingDeclaration?.let { KotlinImageProvider.getImage(it) } } private fun getContainingDeclaration(jetElement: KtElement): KtElement? { @@ -101,4 +83,4 @@ public class KotlinReferenceLabelProvider : LabelProvider() { KtClassOrObject::class.java, KtFile::class.java) } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/SearchParentObjectMapper.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/SearchParentObjectMapper.kt new file mode 100644 index 000000000..1940b7230 --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/SearchParentObjectMapper.kt @@ -0,0 +1,39 @@ +package org.jetbrains.kotlin.ui.search + +import org.eclipse.jdt.core.search.IJavaSearchConstants +import org.eclipse.jdt.ui.search.QuerySpecification +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypes +import org.jetbrains.kotlin.ui.commands.findReferences.KotlinFindImplementationsInProjectAction + +fun interface SearchParentObjectMapper { + + fun map(element: KtElement): KtElement? + + companion object { + fun getMapper(querySpecification: QuerySpecification): SearchParentObjectMapper = + when (querySpecification.limitTo) { + IJavaSearchConstants.REFERENCES -> ReferencesParentObjectMapper + KotlinFindImplementationsInProjectAction.IMPLEMENTORS_LIMIT_TO -> ImplementationsParentObjectMapper + else -> NO_MAPPING + } + + private val NO_MAPPING = SearchParentObjectMapper { null } + } +} + +object ReferencesParentObjectMapper : SearchParentObjectMapper { + override fun map(element: KtElement): KtElement? = element.getParentOfType(false) +} + +object ImplementationsParentObjectMapper : SearchParentObjectMapper { + override fun map(element: KtElement): KtElement? = + element.getParentOfTypes( + false, + KtClass::class.java, + KtObjectDeclaration::class.java, + KtProperty::class.java, + KtNamedFunction::class.java + ) +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/searchFilters.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/searchFilters.kt index dddacfacf..6842db603 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/searchFilters.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/search/searchFilters.kt @@ -20,14 +20,18 @@ import org.eclipse.jdt.core.IJavaElement import org.eclipse.jdt.core.IMethod import org.eclipse.jdt.core.search.IJavaSearchConstants import org.eclipse.jdt.ui.search.QuerySpecification -import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtReferenceExpression -import org.jetbrains.kotlin.psi.KtSimpleNameExpression +import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf +import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence +import org.jetbrains.kotlin.ui.commands.findReferences.KotlinFindImplementationsInProjectAction import org.jetbrains.kotlin.ui.search.KotlinQueryParticipant.SearchElement import org.jetbrains.kotlin.ui.search.KotlinQueryParticipant.SearchElement.JavaSearchElement import org.jetbrains.kotlin.ui.search.KotlinQueryParticipant.SearchElement.KotlinSearchElement +import org.jetbrains.kotlin.utils.findCurrentDescriptor interface SearchFilter { fun isApplicable(jetElement: KtElement): Boolean @@ -35,10 +39,13 @@ interface SearchFilter { interface SearchFilterAfterResolve { fun isApplicable(sourceElement: KtElement, originElement: KtElement): Boolean - + fun isApplicable(sourceElement: IJavaElement, originElement: IJavaElement): Boolean - - fun isApplicable(sourceElements: List, originElement: SearchElement): Boolean { + + fun isApplicable( + sourceElements: List, + originElement: SearchElement + ): Boolean { val (javaElements, kotlinElements) = getJavaAndKotlinElements(sourceElements) return when (originElement) { is JavaSearchElement -> javaElements.any { isApplicable(it, originElement.javaElement) } @@ -47,54 +54,107 @@ interface SearchFilterAfterResolve { } } -fun getBeforeResolveFilters(querySpecification: QuerySpecification): List { - val filters = arrayListOf() - if (querySpecification.getLimitTo() == IJavaSearchConstants.REFERENCES) { - filters.add(NonImportFilter()) - filters.add(ReferenceFilter()) +fun getBeforeResolveFilters(querySpecification: QuerySpecification): List = + when (querySpecification.limitTo) { + IJavaSearchConstants.REFERENCES -> listOf(NonImportFilter, ElementWithPossibleReferencesFilter) + KotlinFindImplementationsInProjectAction.IMPLEMENTORS_LIMIT_TO -> listOf( + NonImportFilter, + PossibleOverridingMemberFilter + ) + else -> emptyList() + } + +fun getAfterResolveFilters(querySpecification: QuerySpecification): List = + when (querySpecification.limitTo) { + KotlinFindImplementationsInProjectAction.IMPLEMENTORS_LIMIT_TO -> listOf(InheritorsFilter) + else -> listOf(ResolvedReferenceFilter) } - - return filters + +object ElementWithPossibleReferencesFilter : SearchFilter { + override fun isApplicable(jetElement: KtElement): Boolean = + jetElement is KtReferenceExpression || (jetElement is KtPropertyDelegate) } -fun getAfterResolveFilters(): List = listOf(ResolvedReferenceFilter()) +object PossibleOverridingMemberFilter : SearchFilter { -class ReferenceFilter : SearchFilter { - override fun isApplicable(jetElement: KtElement): Boolean = jetElement is KtReferenceExpression + override fun isApplicable(jetElement: KtElement): Boolean { + return jetElement is KtClass || jetElement is KtNamedFunction || jetElement is KtProperty || jetElement is KtObjectDeclaration + } } -class NonImportFilter : SearchFilter { +object NonImportFilter : SearchFilter { override fun isApplicable(jetElement: KtElement): Boolean { return jetElement !is KtSimpleNameExpression || !jetElement.isImportDirectiveExpression() } } -class ResolvedReferenceFilter : SearchFilterAfterResolve { +object InheritorsFilter : SearchFilterAfterResolve { override fun isApplicable(sourceElement: KtElement, originElement: KtElement): Boolean { - return sourceElement == originElement + if (originElement is KtClass && (sourceElement !is KtClass && sourceElement !is KtObjectDeclaration)) return false + if (originElement is KtProperty && sourceElement !is KtProperty) return false + if (originElement is KtNamedFunction && sourceElement !is KtNamedFunction) return false + + val (tempSourceModuleDescriptor, tempSourceDescriptor) = sourceElement.tryGetDescriptor() + val (_, tempOriginDescriptor) = originElement.tryGetDescriptor() + + if (tempSourceDescriptor == null || tempOriginDescriptor == null) return false + + val tempCurrentOriginDescriptor = + tempSourceModuleDescriptor.findCurrentDescriptor(tempOriginDescriptor) ?: return false + val tempCurrentSourceDescriptor = + tempSourceModuleDescriptor.findCurrentDescriptor(tempSourceDescriptor) ?: return false + + if (tempCurrentOriginDescriptor == tempCurrentSourceDescriptor) return false + + return if (tempCurrentSourceDescriptor is ClassDescriptor && tempCurrentOriginDescriptor is ClassDescriptor) { + return tempCurrentSourceDescriptor.isSubclassOf(tempCurrentOriginDescriptor) + } else { + val tempOverriddenDescriptors = when (tempSourceDescriptor) { + is FunctionDescriptor -> tempSourceDescriptor.overriddenTreeUniqueAsSequence(false).toList() + is PropertyDescriptor -> tempSourceDescriptor.overriddenTreeUniqueAsSequence(false).toList() + else -> return false + }.mapNotNull { + tempSourceModuleDescriptor.findCurrentDescriptor(it) + } + + tempSourceModuleDescriptor.findCurrentDescriptor(tempOriginDescriptor) in tempOverriddenDescriptors + } } - + + private fun KtElement.tryGetDescriptor(): Pair { + val (bindingContext, moduleDescriptor) = KotlinAnalyzer.analyzeFile(containingKtFile).analysisResult + return Pair(moduleDescriptor, bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, this]) + } + + override fun isApplicable(sourceElement: IJavaElement, originElement: IJavaElement): Boolean = false +} + +object ResolvedReferenceFilter : SearchFilterAfterResolve { + override fun isApplicable(sourceElement: KtElement, originElement: KtElement): Boolean { + return sourceElement == originElement || InheritorsFilter.isApplicable(sourceElement, originElement) + } + override fun isApplicable(sourceElement: IJavaElement, originElement: IJavaElement): Boolean { - return referenceFilter(sourceElement, originElement) + return referenceFilter(sourceElement, originElement) } - + private fun referenceFilter(potentialElement: IJavaElement, originElement: IJavaElement): Boolean { return when { originElement.isConstructorCall() && potentialElement.isConstructorCall() -> { - (originElement as IMethod).getDeclaringType() == (potentialElement as IMethod).getDeclaringType() + (originElement as IMethod).declaringType == (potentialElement as IMethod).declaringType } - + originElement.isConstructorCall() -> { - (originElement as IMethod).getDeclaringType() == potentialElement + (originElement as IMethod).declaringType == potentialElement } - + potentialElement.isConstructorCall() -> { - originElement == (potentialElement as IMethod).getDeclaringType() + originElement == (potentialElement as IMethod).declaringType } - + else -> potentialElement == originElement } } - - private fun IJavaElement.isConstructorCall() = this is IMethod && this.isConstructor() -} \ No newline at end of file + + private fun IJavaElement.isConstructorCall() = this is IMethod && isConstructor +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/utils/DescriptorUtils.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/utils/DescriptorUtils.kt new file mode 100644 index 000000000..d4d41bee2 --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/utils/DescriptorUtils.kt @@ -0,0 +1,47 @@ +package org.jetbrains.kotlin.utils + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.resolve.scopes.MemberScope.Companion.ALL_NAME_FILTER + +private fun ModuleDescriptor.findCurrentDescriptorForMember(originalDescriptor: MemberDescriptor): DeclarationDescriptor? { + val containingDeclaration = findCurrentDescriptor(originalDescriptor.containingDeclaration) + val memberScope = containingDeclaration?.memberScope ?: return null + + val renderedOriginal: String = DescriptorRenderer.FQ_NAMES_IN_TYPES.render(originalDescriptor) + val descriptors: Collection = + if (originalDescriptor is ConstructorDescriptor && containingDeclaration is ClassDescriptor) { + containingDeclaration.constructors + } else { + memberScope.getContributedDescriptors(DescriptorKindFilter.ALL, ALL_NAME_FILTER) + } + for (member in descriptors) { + if (renderedOriginal == DescriptorRenderer.FQ_NAMES_IN_TYPES.render(member)) { + return member + } + } + return null +} + +fun ModuleDescriptor.findCurrentDescriptor(originalDescriptor: DeclarationDescriptor): DeclarationDescriptor? { + if (originalDescriptor is ClassDescriptor) { + val classId: ClassId = originalDescriptor.classId ?: return null + return findClassAcrossModuleDependencies(classId) + } + if (originalDescriptor is PackageFragmentDescriptor) { + return getPackage(originalDescriptor.fqName) + } + return if (originalDescriptor is MemberDescriptor) { + findCurrentDescriptorForMember(originalDescriptor) + } else null +} + +private val DeclarationDescriptor.memberScope: MemberScope? get() = when (this) { + is ClassDescriptor -> defaultType.memberScope + is PackageFragmentDescriptor -> getMemberScope() + else -> null +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/NewUnitWizard.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/NewUnitWizard.java index 22ab6f591..4ba0a733f 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/NewUnitWizard.java +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/NewUnitWizard.java @@ -47,9 +47,12 @@ public class NewUnitWizard extends AbstractWizard { private static final String PACKAGE_FORMAT = "package %s\n\n"; private final WizardType type; + + private boolean isDynamicType; public NewUnitWizard() { this(WizardType.NONE); + isDynamicType = true; } public NewUnitWizard(WizardType type) { @@ -59,7 +62,13 @@ public NewUnitWizard(WizardType type) { @Override public boolean performFinish() { NewUnitWizardPage wizardPage = getWizardPage(); - String contents = createPackageHeader() + createTypeBody(); + WizardType finalType; + if(isDynamicType) { + finalType = wizardPage.getType(); + } else { + finalType = type; + } + String contents = createPackageHeader() + createTypeBody(finalType); IFile kotlinSourceFile; try { @@ -108,7 +117,7 @@ protected String getPageTitle() { @Override protected NewUnitWizardPage createWizardPage() { return new NewUnitWizardPage(getPageTitle(), String.format(DESCRIPTION_FORMAT, - type.getWizardTypeName().toLowerCase()), DEFAULT_FILE_NAME, getStructuredSelection()); + type.getWizardTypeName().toLowerCase()), DEFAULT_FILE_NAME, getStructuredSelection(), isDynamicType); } @Nullable @@ -130,12 +139,12 @@ public static IFile createKotlinSourceFile( return operation.getResult(); } - private String createTypeBody() { - if (type == WizardType.NONE) { + private String createTypeBody(WizardType finalType) { + if (finalType == WizardType.NONE) { return DEFAULT_TYPE_BODY; } - return String.format(type.getFileBodyFormat(), FileCreationOp.getSimpleUnitName(getWizardPage().getUnitName())); + return String.format(finalType.getFileBodyFormat(), FileCreationOp.getSimpleUnitName(getWizardPage().getUnitName())); } private String createPackageHeader() { @@ -147,4 +156,4 @@ private String createPackageHeader() { return String.format(PACKAGE_FORMAT, pckg); } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/NewUnitWizardPage.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/NewUnitWizardPage.java index f6524769c..5a1e1ec4c 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/NewUnitWizardPage.java +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/NewUnitWizardPage.java @@ -16,75 +16,78 @@ *******************************************************************************/ package org.jetbrains.kotlin.wizards; -import static org.eclipse.jdt.internal.ui.refactoring.nls.SourceContainerDialog.getSourceContainer; -import static org.jetbrains.kotlin.wizards.FileCreationOp.fileExists; -import static org.jetbrains.kotlin.wizards.FileCreationOp.makeFile; -import static org.jetbrains.kotlin.wizards.SWTWizardUtils.createButton; -import static org.jetbrains.kotlin.wizards.SWTWizardUtils.createEmptySpace; -import static org.jetbrains.kotlin.wizards.SWTWizardUtils.createLabel; -import static org.jetbrains.kotlin.wizards.SWTWizardUtils.createSeparator; -import static org.jetbrains.kotlin.wizards.SWTWizardUtils.createText; - import org.eclipse.core.resources.IProject; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.IPackageFragmentRoot; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.*; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.SelectionDialog; import org.jetbrains.kotlin.core.log.KotlinLogger; +import java.util.Arrays; + +import static org.eclipse.jdt.internal.ui.refactoring.nls.SourceContainerDialog.getSourceContainer; +import static org.jetbrains.kotlin.wizards.FileCreationOp.fileExists; +import static org.jetbrains.kotlin.wizards.FileCreationOp.makeFile; +import static org.jetbrains.kotlin.wizards.SWTWizardUtils.*; + public class NewUnitWizardPage extends AbstractWizardPage { - + private static final String DEFAULT_SOURCE_FOLDER = ""; private static final String DEFAULT_PACKAGE = ""; - + private static final String NAME_LABEL_TITLE = "Na&me"; private static final String SOURCE_FOLDER_LABEL_TITLE = "Source fol&der"; private static final String PACKAGE_LABEL_TITLE = "Pac&kage"; - + private static final String ILLEGAL_UNIT_NAME_MESSAGE = "Please enter a legal compilation unit name"; private static final String SELECT_SOURCE_FOLDER_MESSAGE = "Please select a source folder"; private static final String ILLEGAL_PACKAGE_NAME_MESSAGE = "Please enter a legal package name"; private static final String UNIT_EXISTS_MESSAGE = "File already exists"; - + private static final String JAVA_IDENTIFIER_REGEXP = "[a-zA-Z_]\\w*"; - + private String unitName; private String packageName; private IPackageFragmentRoot sourceDir; private IPackageFragment packageFragment; + + private WizardType type = WizardType.NONE; + + private final boolean isDynamicType; private Text nameField = null; private final IStructuredSelection selection; - - protected NewUnitWizardPage(String title, String description, String unitName, IStructuredSelection selection) { + + protected NewUnitWizardPage(String title, String description, String unitName, IStructuredSelection selection, boolean isDynamicType) { super(title, description); - + this.selection = selection; this.unitName = unitName; + this.isDynamicType = isDynamicType; } - + public IPackageFragment getPackageFragment() { return packageFragment; } - + public IPackageFragmentRoot getSourceDir() { return sourceDir; } - + + public WizardType getType() { + return type; + } + public String getUnitName() { return unitName; } - + public IProject getProject() { if (sourceDir != null) { return sourceDir.getJavaProject().getProject(); @@ -92,17 +95,36 @@ public IProject getProject() { return null; } } - + @Override protected void createControls(Composite parent) { createSourceFolderField(parent); createPackageField(parent); - + createSeparator(parent); - + nameField = createNameField(parent); + if (isDynamicType) { + createDynamicTypeField(parent); + } } - + + private void createDynamicTypeField(Composite parent) { + createLabel(parent, "Type:"); + Combo tempCombo = new Combo(parent, SWT.READ_ONLY); + for (WizardType tempType : WizardType.values()) { + tempCombo.add(tempType.getWizardTypeName()); + } + tempCombo.select(0); + + tempCombo.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + type = Arrays.stream(WizardType.values()).filter(it -> it.getWizardTypeName().equals(tempCombo.getText())).findFirst().orElse(WizardType.CLASS); + } + }); + } + @Override public void setVisible(boolean visible) { super.setVisible(visible); @@ -117,12 +139,9 @@ private Text createNameField(Composite parent) { createLabel(parent, NAME_LABEL_TITLE); final Text name = createText(parent, unitName); - name.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - unitName = name.getText(); - validate(); - } + name.addModifyListener(e -> { + unitName = name.getText(); + validate(); }); createEmptySpace(parent); @@ -146,7 +165,7 @@ private void setSourceDirByFolderName(String srcFolder) { } } - private Text createSourceFolderField(Composite parent) { + private void createSourceFolderField(Composite parent) { createLabel(parent, SOURCE_FOLDER_LABEL_TITLE); IPackageFragmentRoot srcFolder = WizardUtilsKt.getSourceFolderBySelection(selection); @@ -154,12 +173,9 @@ private Text createSourceFolderField(Composite parent) { sourceDir = srcFolder; final Text folder = createText(parent, sourceFolderFromSelection); - folder.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - setSourceDirByFolderName(folder.getText()); - validate(); - } + folder.addModifyListener(e -> { + setSourceDirByFolderName(folder.getText()); + validate(); }); createButton(parent, BROWSE_BUTTON_TITLE, new SelectionAdapter() { @@ -176,11 +192,10 @@ public void widgetSelected(SelectionEvent e) { validate(); } }); - - return folder; + } - private Text createPackageField(Composite parent) { + private void createPackageField(Composite parent) { createLabel(parent, PACKAGE_LABEL_TITLE); IPackageFragment fragment = WizardUtilsKt.getPackageBySelection(selection); @@ -188,12 +203,9 @@ private Text createPackageField(Composite parent) { packageName = packageFromSelection; final Text pkg = createText(parent, packageFromSelection); - pkg.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - packageName = pkg.getText(); - validate(); - } + pkg.addModifyListener(e -> { + packageName = pkg.getText(); + validate(); }); createButton(parent, BROWSE_BUTTON_TITLE, new SelectionAdapter() { @@ -226,8 +238,7 @@ public void widgetSelected(SelectionEvent e) { } } }); - - return pkg; + } @Override diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/WizardType.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/WizardType.kt index fc7e146a6..1a7378f92 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/WizardType.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/WizardType.kt @@ -22,12 +22,16 @@ import org.jetbrains.kotlin.lexer.KtToken enum class WizardType(val wizardTypeName: String, val fileBodyFormat: String = "") { NONE("Source"), CLASS("Class", buildFileBody(KtTokens.CLASS_KEYWORD)), + SEALED_CLASS("Sealed Class", buildFileBody(KtTokens.SEALED_KEYWORD, KtTokens.CLASS_KEYWORD)), INTERFACE("Interface", buildFileBody(KtTokens.INTERFACE_KEYWORD)), + SEALED_INTERFACE("Sealed Interface", buildFileBody(KtTokens.SEALED_KEYWORD, KtTokens.INTERFACE_KEYWORD)), OBJECT("Object", buildFileBody(KtTokens.OBJECT_KEYWORD)), - ENUM("Enum", buildFileBody(KtTokens.ENUM_KEYWORD, KtTokens.CLASS_KEYWORD)) + ENUM("Enum", buildFileBody(KtTokens.ENUM_KEYWORD, KtTokens.CLASS_KEYWORD)), + DATA("Data", buildFileBody(KtTokens.DATA_KEYWORD, KtTokens.CLASS_KEYWORD)), + ANNOTATION("Annotation", buildFileBody(KtTokens.ANNOTATION_KEYWORD, KtTokens.CLASS_KEYWORD)), } -private val NOT_EMPTY_BODY_FORMAT = "%s {\n}" +private const val NOT_EMPTY_BODY_FORMAT = "%s {\n}" private fun buildFileBody(vararg modifiers: KtToken): String = - "${modifiers.joinToString(separator = " ")} $NOT_EMPTY_BODY_FORMAT" \ No newline at end of file + "${modifiers.joinToString(separator = " ")} $NOT_EMPTY_BODY_FORMAT" diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/unitWizards.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/unitWizards.kt index af532377e..157c65e18 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/unitWizards.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/unitWizards.kt @@ -14,10 +14,10 @@ * limitations under the License. * *******************************************************************************/ +@file:Suppress("unused") + package org.jetbrains.kotlin.wizards -import org.eclipse.core.resources.IFile -import org.eclipse.core.runtime.IPath import org.eclipse.jface.viewers.IStructuredSelection import org.eclipse.ui.IWorkbench import org.eclipse.ui.dialogs.WizardNewFileCreationPage @@ -26,37 +26,41 @@ import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard import org.jetbrains.kotlin.parsing.KotlinParserDefinition class NewClassWizard : NewUnitWizard(WizardType.CLASS) +class NewSealedClassWizard : NewUnitWizard(WizardType.SEALED_CLASS) class NewEnumWizard : NewUnitWizard(WizardType.ENUM) +class NewDataClassWizard : NewUnitWizard(WizardType.DATA) +class NewAnnotationWizard : NewUnitWizard(WizardType.ANNOTATION) class NewObjectWizard : NewUnitWizard(WizardType.OBJECT) class NewInterfaceWizard : NewUnitWizard(WizardType.INTERFACE) +class NewSealedInterfaceWizard : NewUnitWizard(WizardType.SEALED_INTERFACE) class NewScriptWizard : BasicNewResourceWizard() { companion object { private const val pageName = "New Kotlin Script" } - + private lateinit var mainPage: WizardNewFileCreationPage - + override fun addPages() { super.addPages() - + mainPage = WizardNewFileCreationPage(pageName, getSelection()).apply { - setFileExtension(KotlinParserDefinition.STD_SCRIPT_SUFFIX) - setTitle("Kotlin Script") - setDescription("Create a new Kotlin script") + fileExtension = KotlinParserDefinition.STD_SCRIPT_SUFFIX + title = "Kotlin Script" + description = "Create a new Kotlin script" } - + addPage(mainPage) } - + override fun init(workbench: IWorkbench, currentSelection: IStructuredSelection) { super.init(workbench, currentSelection) - setWindowTitle(pageName) + windowTitle = pageName } - + override fun performFinish(): Boolean { val file = mainPage.createNewFile() ?: return false - + selectAndReveal(file) workbench.activeWorkbenchWindow?.let { val page = it.activePage @@ -64,7 +68,7 @@ class NewScriptWizard : BasicNewResourceWizard() { IDE.openEditor(page, file, true) } } - + return true } -} \ No newline at end of file +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/wizardUtils.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/wizardUtils.kt index 6fe94e931..899c941fb 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/wizardUtils.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/wizards/wizardUtils.kt @@ -16,21 +16,15 @@ *******************************************************************************/ package org.jetbrains.kotlin.wizards +import org.eclipse.core.resources.IResource +import org.eclipse.jdt.core.* import org.eclipse.jface.viewers.IStructuredSelection import org.jetbrains.kotlin.core.utils.sourceFolders -import org.eclipse.jdt.core.IJavaProject -import org.eclipse.jdt.core.IPackageFragmentRoot -import org.eclipse.jdt.core.IPackageFragment -import org.eclipse.jdt.core.ICompilationUnit -import org.eclipse.core.resources.IFile -import org.eclipse.jdt.core.JavaCore -import org.eclipse.core.resources.IResource fun getSourceFolderBySelection(selection: IStructuredSelection): IPackageFragmentRoot? { if (selection.isEmpty) return null - - val element = selection.firstElement - return when (element) { + + return when (val element = selection.firstElement) { is IPackageFragmentRoot -> element is IJavaProject -> element.sourceFolders.firstOrNull() is IPackageFragment -> element.parent as IPackageFragmentRoot @@ -42,15 +36,14 @@ fun getSourceFolderBySelection(selection: IStructuredSelection): IPackageFragmen fun getPackageBySelection(selection: IStructuredSelection): IPackageFragment? { if (selection.isEmpty) return null - - val element = selection.firstElement - return when (element) { + + return when (val element = selection.firstElement) { is IPackageFragment -> element is ICompilationUnit -> element.parent as IPackageFragment is IResource -> { val javaProject = JavaCore.create(element.project) - javaProject.findPackageFragment(element.getFullPath().removeLastSegments(1)) + javaProject.findPackageFragment(element.fullPath.removeLastSegments(1)) } else -> null } -} \ No newline at end of file +} diff --git a/kotlin-weaving-feature/.project b/kotlin-weaving-feature/.project deleted file mode 100644 index fe4f7f2ee..000000000 --- a/kotlin-weaving-feature/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - kotlin-weaving-feature - - - - - - org.eclipse.pde.FeatureBuilder - - - - - - org.eclipse.pde.FeatureNature - - diff --git a/kotlin-weaving-feature/feature.xml b/kotlin-weaving-feature/feature.xml index 5be8b0724..b44170db7 100644 --- a/kotlin-weaving-feature/feature.xml +++ b/kotlin-weaving-feature/feature.xml @@ -2,7 +2,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT org.jetbrains.kotlin.weaving.feature - kotlin.eclipse - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT eclipse-feature \ No newline at end of file diff --git a/maven-build/.project b/maven-build/.project deleted file mode 100644 index 1416d95ea..000000000 --- a/maven-build/.project +++ /dev/null @@ -1,18 +0,0 @@ - - - maven-build - - - - - - - - - - pom.xml - 1 - PARENT-1-PROJECT_LOC/pom.xml - - - diff --git a/pom.xml b/pom.xml index aa95302be..a815b4983 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 kotlin.eclipse kotlin.eclipse.plugin - 0.8.21-SNAPSHOT + 1.6.21-SNAPSHOT pom @@ -10,7 +10,7 @@ kotlin-eclipse-aspects kotlin-eclipse-core kotlin-eclipse-ui - kotlin-eclipse-ui-test + kotlin-eclipse-test-framework kotlin-eclipse-policy kotlin-eclipse-feature @@ -23,20 +23,16 @@ - 1.3.0 - 1.3.0 + 2.4.0 + 2.4.0 - http://download.eclipse.org/releases/2019-03 + http://download.eclipse.org/releases/2021-09 UTF-8 - http://download.eclipse.org/tools/ajdt/46/dev/update - + http://download.eclipse.org/tools/ajdt/48/dev/update http://download.eclipse.org/buildship/updates/e49/releases/3.x - 1.4.10 - - 1.8.7 - 1.8 + 1.7.20 1.1.200.v20150730-1648 @@ -137,18 +133,6 @@ -err:-forbidden - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - org.aspectj - aspectjtools - ${aspectj.version} - - - org.eclipse.tycho tycho-packaging-plugin @@ -175,7 +159,7 @@ tycho-surefire-plugin ${tycho.version} - true + true @@ -218,7 +202,7 @@ none - https://download.eclipse.org/eclipse/updates/4.11 + https://download.eclipse.org/eclipse/updates/4.21