From 936440fb76729b50126b744688c62df1f011ff70 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Fri, 28 Jul 2023 15:18:59 +0200 Subject: [PATCH 001/165] [kotlin] Restore cooperative development in the `kt-master` branch GitOrigin-RevId: 4ca67d9a3b3209f306a5d3dce480f239a0f83252 --- .../kotlinc_allopen_compiler_plugin.xml | 13 ++----- .../kotlinc_analysis_api_providers.xml | 13 ++----- .../kotlinc_analysis_project_structure.xml | 13 ++----- ...inc_android_extensions_compiler_plugin.xml | 13 ++----- .../kotlinc_assignment_compiler_plugin.xml | 13 ++----- .idea/libraries/kotlinc_high_level_api.xml | 13 ++----- .../libraries/kotlinc_high_level_api_fe10.xml | 13 ++----- .../libraries/kotlinc_high_level_api_fir.xml | 13 ++----- .../kotlinc_high_level_api_fir_tests.xml | 13 ++----- .../kotlinc_high_level_api_impl_base.xml | 13 ++----- ...kotlinc_high_level_api_impl_base_tests.xml | 13 ++----- ...inc_incremental_compilation_impl_tests.xml | 13 ++----- .../kotlinc_kotlin_build_common_tests.xml | 13 ++----- .../libraries/kotlinc_kotlin_compiler_cli.xml | 13 ++----- .../kotlinc_kotlin_compiler_common.xml | 13 ++----- .../kotlinc_kotlin_compiler_fe10.xml | 13 ++----- .../libraries/kotlinc_kotlin_compiler_fir.xml | 13 ++----- .../libraries/kotlinc_kotlin_compiler_ir.xml | 13 ++----- .../kotlinc_kotlin_compiler_tests.xml | 13 ++----- .../kotlinc_kotlin_gradle_statistics.xml | 13 ++----- .idea/libraries/kotlinc_kotlin_jps_common.xml | 13 ++----- .../kotlinc_kotlin_script_runtime.xml | 13 ++----- .../kotlinc_kotlin_scripting_common.xml | 13 ++----- ...kotlinc_kotlin_scripting_compiler_impl.xml | 13 ++----- .../kotlinc_kotlin_scripting_jvm.xml | 13 ++----- .idea/libraries/kotlinc_kotlin_stdlib.xml | 37 +++++-------------- ...kotlinc_kotlin_stdlib_minimal_for_test.xml | 13 ++----- ..._kotlinx_serialization_compiler_plugin.xml | 13 ++----- .../kotlinc_lombok_compiler_plugin.xml | 13 ++----- .idea/libraries/kotlinc_low_level_api_fir.xml | 13 ++----- .../kotlinc_noarg_compiler_plugin.xml | 13 ++----- .../kotlinc_parcelize_compiler_plugin.xml | 13 ++----- ...linc_sam_with_receiver_compiler_plugin.xml | 13 ++----- .../kotlinc_scripting_compiler_plugin.xml | 13 ++----- .../kotlinc_symbol_light_classes.xml | 13 ++----- .../resources/model.properties | 2 +- 36 files changed, 112 insertions(+), 369 deletions(-) diff --git a/.idea/libraries/kotlinc_allopen_compiler_plugin.xml b/.idea/libraries/kotlinc_allopen_compiler_plugin.xml index 23dbeabd4f2e..b4241b099d2d 100644 --- a/.idea/libraries/kotlinc_allopen_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_allopen_compiler_plugin.xml @@ -1,18 +1,11 @@ - - - - - ddf72df178668a0deab4460fcfd64642f823b9834b8a88102a7bf4145eca0efe - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_analysis_api_providers.xml b/.idea/libraries/kotlinc_analysis_api_providers.xml index 770637ab1be4..4b9e306e97fd 100644 --- a/.idea/libraries/kotlinc_analysis_api_providers.xml +++ b/.idea/libraries/kotlinc_analysis_api_providers.xml @@ -1,18 +1,11 @@ - - - - - 89fdf915639b991a00e24209669f8eabf2127bd6ee02247adc81e328df5632fb - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_analysis_project_structure.xml b/.idea/libraries/kotlinc_analysis_project_structure.xml index d3d24f51563e..0f08ef95bf7c 100644 --- a/.idea/libraries/kotlinc_analysis_project_structure.xml +++ b/.idea/libraries/kotlinc_analysis_project_structure.xml @@ -1,18 +1,11 @@ - - - - - ec3a35f2cb718777d77265c84165b562a8f666526ea5c9073b65f0df8f3a0b94 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_android_extensions_compiler_plugin.xml b/.idea/libraries/kotlinc_android_extensions_compiler_plugin.xml index 9fbe8eac953e..32f17ac3b24a 100644 --- a/.idea/libraries/kotlinc_android_extensions_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_android_extensions_compiler_plugin.xml @@ -1,18 +1,11 @@ - - - - - a7007b8bbef5f9f019e0153eb78b1ddb5cf4e59cb69f66297e9fddb9edac0a66 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_assignment_compiler_plugin.xml b/.idea/libraries/kotlinc_assignment_compiler_plugin.xml index 420ad79cf061..71295b39ea41 100644 --- a/.idea/libraries/kotlinc_assignment_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_assignment_compiler_plugin.xml @@ -1,18 +1,11 @@ - - - - - 7d68c0df49e2a70e5629f790cd0b339cbfc5341a2e5bf6d2bbfda16abf7d4285 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_high_level_api.xml b/.idea/libraries/kotlinc_high_level_api.xml index f2a14c747c9a..ec4c32cc75f4 100644 --- a/.idea/libraries/kotlinc_high_level_api.xml +++ b/.idea/libraries/kotlinc_high_level_api.xml @@ -1,18 +1,11 @@ - - - - - bf44c46253233cf22b1cb51d817799ae22b1a9d24067a9cbbd731e5ab6caded4 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_high_level_api_fe10.xml b/.idea/libraries/kotlinc_high_level_api_fe10.xml index b0a2311bd71d..0c93b8382ad6 100644 --- a/.idea/libraries/kotlinc_high_level_api_fe10.xml +++ b/.idea/libraries/kotlinc_high_level_api_fe10.xml @@ -1,18 +1,11 @@ - - - - - 790c9d1ef0da1f56904a3233150ff8b70a6e8d86839e4e5bfa47e6c8a7897154 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_high_level_api_fir.xml b/.idea/libraries/kotlinc_high_level_api_fir.xml index bf0451acd960..6330f8778c6f 100644 --- a/.idea/libraries/kotlinc_high_level_api_fir.xml +++ b/.idea/libraries/kotlinc_high_level_api_fir.xml @@ -1,18 +1,11 @@ - - - - - 4861094faece32eec7fbab70599af86123ef27a5c40b908b32e56255657a4d39 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_high_level_api_fir_tests.xml b/.idea/libraries/kotlinc_high_level_api_fir_tests.xml index 0e4cbeaf9a5b..c18c2e60efcb 100644 --- a/.idea/libraries/kotlinc_high_level_api_fir_tests.xml +++ b/.idea/libraries/kotlinc_high_level_api_fir_tests.xml @@ -1,18 +1,11 @@ - - - - - eae32f4e907720e000ee9c0e89a8c2ae846c3b09c70484cf1fb99c198833078e - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_high_level_api_impl_base.xml b/.idea/libraries/kotlinc_high_level_api_impl_base.xml index b227e47b4cb3..fd6dc0b987fd 100644 --- a/.idea/libraries/kotlinc_high_level_api_impl_base.xml +++ b/.idea/libraries/kotlinc_high_level_api_impl_base.xml @@ -1,18 +1,11 @@ - - - - - d809596ffec9bb278947ec1fe3c20b18ac36d93e0beb8bd4918011ebe34e8a4c - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_high_level_api_impl_base_tests.xml b/.idea/libraries/kotlinc_high_level_api_impl_base_tests.xml index cbc8f0caa669..32d2114f18b3 100644 --- a/.idea/libraries/kotlinc_high_level_api_impl_base_tests.xml +++ b/.idea/libraries/kotlinc_high_level_api_impl_base_tests.xml @@ -1,18 +1,11 @@ - - - - - a3f332e6a539b64db0c3786183f72a4894901f0504e56d3cf24a98773b6e9818 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_incremental_compilation_impl_tests.xml b/.idea/libraries/kotlinc_incremental_compilation_impl_tests.xml index 5e3b0c8306d9..f88f6ca3f728 100644 --- a/.idea/libraries/kotlinc_incremental_compilation_impl_tests.xml +++ b/.idea/libraries/kotlinc_incremental_compilation_impl_tests.xml @@ -1,18 +1,11 @@ - - - - - 2dbf046fc51ad2ab2a3e4ab1668a76a17039ab6d211748bded2d32dc80f598b0 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_build_common_tests.xml b/.idea/libraries/kotlinc_kotlin_build_common_tests.xml index 0570ff42a050..78568afb8097 100644 --- a/.idea/libraries/kotlinc_kotlin_build_common_tests.xml +++ b/.idea/libraries/kotlinc_kotlin_build_common_tests.xml @@ -1,18 +1,11 @@ - - - - - fd32673e172771aa481748ed3b5ae7c41d3bf57858a243d45a78ad9b9e317413 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_compiler_cli.xml b/.idea/libraries/kotlinc_kotlin_compiler_cli.xml index ad8e0eb2c649..70a6aad2489a 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_cli.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_cli.xml @@ -1,18 +1,11 @@ - - - - - 8e9b234e635346b81c55784563829d3feb14ece392eba0d748921b33e77889c8 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_compiler_common.xml b/.idea/libraries/kotlinc_kotlin_compiler_common.xml index 85d9bd938a84..9d889e08ce49 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_common.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_common.xml @@ -1,18 +1,11 @@ - - - - - 2d25341dddb8ba0e0c39a1499955315f2f44106833de8917f5009050a80edd45 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_compiler_fe10.xml b/.idea/libraries/kotlinc_kotlin_compiler_fe10.xml index 7c8ff55da80a..e94371825c15 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_fe10.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_fe10.xml @@ -1,18 +1,11 @@ - - - - - ab90822d2c5c5971c4bf38c0be4f12ba58753293ab995ba13652d0446c345e2c - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_compiler_fir.xml b/.idea/libraries/kotlinc_kotlin_compiler_fir.xml index c2d9e20e02fe..1d70088b3672 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_fir.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_fir.xml @@ -1,18 +1,11 @@ - - - - - 6a5e30e7d2117f4cf318c6534a524259cedcc04b0747d5d8d934375b4c91a537 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_compiler_ir.xml b/.idea/libraries/kotlinc_kotlin_compiler_ir.xml index 597b6311104e..72526fa5a4a1 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_ir.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_ir.xml @@ -1,18 +1,11 @@ - - - - - d7ca67c2016096cc8188406f403187fac067caa3e751c97775dd6ccbbe42bb52 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_compiler_tests.xml b/.idea/libraries/kotlinc_kotlin_compiler_tests.xml index bf9194b9eedf..1bd77f9f07bb 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_tests.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_tests.xml @@ -1,18 +1,11 @@ - - - - - 4690fd58984f14ade528fd4b9871120275c57af5ece530ec1c46b0fc0a5ea568 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_gradle_statistics.xml b/.idea/libraries/kotlinc_kotlin_gradle_statistics.xml index 2319ffe9620f..35c4996d44f0 100644 --- a/.idea/libraries/kotlinc_kotlin_gradle_statistics.xml +++ b/.idea/libraries/kotlinc_kotlin_gradle_statistics.xml @@ -1,18 +1,11 @@ - - - - - ef0252705e16616de7416052b549a3751776a4afd612f2dfd2aa8b5013c9a75d - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_jps_common.xml b/.idea/libraries/kotlinc_kotlin_jps_common.xml index bb9ffaf8ab46..8ec96bc94777 100644 --- a/.idea/libraries/kotlinc_kotlin_jps_common.xml +++ b/.idea/libraries/kotlinc_kotlin_jps_common.xml @@ -1,18 +1,11 @@ - - - - - 704a1119fb9d230dd1df129adeb81ddf549e48fbd33ff1c417636a218050b2de - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_script_runtime.xml b/.idea/libraries/kotlinc_kotlin_script_runtime.xml index 52707ddc1a2d..e17c173d563b 100644 --- a/.idea/libraries/kotlinc_kotlin_script_runtime.xml +++ b/.idea/libraries/kotlinc_kotlin_script_runtime.xml @@ -1,18 +1,11 @@ - - - - - 00965fa842543f930c8cbef0648b48b444c8571e1b30a8c3d3c6ceb5bec99701 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_scripting_common.xml b/.idea/libraries/kotlinc_kotlin_scripting_common.xml index 796f7d8f1598..53b4457b3acd 100644 --- a/.idea/libraries/kotlinc_kotlin_scripting_common.xml +++ b/.idea/libraries/kotlinc_kotlin_scripting_common.xml @@ -1,18 +1,11 @@ - - - - - e1e6d7c7c0d08c37d6940327d289f72b226910722855c4e12644891e15601f5f - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_scripting_compiler_impl.xml b/.idea/libraries/kotlinc_kotlin_scripting_compiler_impl.xml index c9fa627cbae3..269c2b7bd351 100644 --- a/.idea/libraries/kotlinc_kotlin_scripting_compiler_impl.xml +++ b/.idea/libraries/kotlinc_kotlin_scripting_compiler_impl.xml @@ -1,18 +1,11 @@ - - - - - fbba3ed8915bc536f6d8033363f2b27652f16604df87c1a292dd1d14a88b73a3 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_scripting_jvm.xml b/.idea/libraries/kotlinc_kotlin_scripting_jvm.xml index 33108cac8fcd..b68719d24f8f 100644 --- a/.idea/libraries/kotlinc_kotlin_scripting_jvm.xml +++ b/.idea/libraries/kotlinc_kotlin_scripting_jvm.xml @@ -1,18 +1,11 @@ - - - - - 4292efd8dfd2ee0c22edf048f5d2420d21d3dfb563dc9bce26ade225ade7273c - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_stdlib.xml b/.idea/libraries/kotlinc_kotlin_stdlib.xml index 390f05a5339f..2534610ad395 100644 --- a/.idea/libraries/kotlinc_kotlin_stdlib.xml +++ b/.idea/libraries/kotlinc_kotlin_stdlib.xml @@ -1,39 +1,20 @@ - - - - - 1f71be99add6fb58560f6f588b7d7ef28b7dcc6f84a3d8a5d490ea6ca61f3a29 - - - 465b9a646b1a79fea62ab55f09058873ce2a283764bb0d727611c2a03b610657 - - - 0571192be26fb22f7b63d40351ffb5d9f7e6a4150df55f9e8bebe2623c400bb9 - - - 02bd856fe93d67afd252e9903f95ebd78e8a34507f211477e44a1a580f070584 - - - - - - + - - - - + + + + - - - - + + + + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_stdlib_minimal_for_test.xml b/.idea/libraries/kotlinc_kotlin_stdlib_minimal_for_test.xml index b70b1e0ab337..093ed9623c63 100644 --- a/.idea/libraries/kotlinc_kotlin_stdlib_minimal_for_test.xml +++ b/.idea/libraries/kotlinc_kotlin_stdlib_minimal_for_test.xml @@ -1,18 +1,11 @@ - - - - - 6c4df6978ac2dd6313c737583e58300148442add91932a008dcbcfb063704639 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlinx_serialization_compiler_plugin.xml b/.idea/libraries/kotlinc_kotlinx_serialization_compiler_plugin.xml index d51dc870521a..69dc43051f7c 100644 --- a/.idea/libraries/kotlinc_kotlinx_serialization_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_kotlinx_serialization_compiler_plugin.xml @@ -1,18 +1,11 @@ - - - - - 511745d5976bfb0bce4a993f0f848e5e4f15558ac63e90f8b354d86d8e535aae - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_lombok_compiler_plugin.xml b/.idea/libraries/kotlinc_lombok_compiler_plugin.xml index 937e5744bff4..53e0d754b3da 100644 --- a/.idea/libraries/kotlinc_lombok_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_lombok_compiler_plugin.xml @@ -1,18 +1,11 @@ - - - - - 994e0de733fe43b3c2c594ec8c5ac8106e2372e14bcf0a60942c6ae23fe682b3 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_low_level_api_fir.xml b/.idea/libraries/kotlinc_low_level_api_fir.xml index eb76eb5a7e00..9a640dd8d49e 100644 --- a/.idea/libraries/kotlinc_low_level_api_fir.xml +++ b/.idea/libraries/kotlinc_low_level_api_fir.xml @@ -1,18 +1,11 @@ - - - - - eb69492c21b257aaaccff158a4db8822efd77e9b61a06941fbcddc73cedd0fbe - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_noarg_compiler_plugin.xml b/.idea/libraries/kotlinc_noarg_compiler_plugin.xml index cab07cdcefaa..2c1a292400eb 100644 --- a/.idea/libraries/kotlinc_noarg_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_noarg_compiler_plugin.xml @@ -1,18 +1,11 @@ - - - - - efb8097b25caed72eb220f0836959a6ed3d264a94f6a21233cb4c57a09c38b42 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_parcelize_compiler_plugin.xml b/.idea/libraries/kotlinc_parcelize_compiler_plugin.xml index d036ed0764f9..d302a3eaa5a0 100644 --- a/.idea/libraries/kotlinc_parcelize_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_parcelize_compiler_plugin.xml @@ -1,18 +1,11 @@ - - - - - e1cae6d063de2c43011204e3fdb8ea9b209a68742b6856d2b67d140f04074836 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_sam_with_receiver_compiler_plugin.xml b/.idea/libraries/kotlinc_sam_with_receiver_compiler_plugin.xml index e5b811207900..a098b3ac0a4e 100644 --- a/.idea/libraries/kotlinc_sam_with_receiver_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_sam_with_receiver_compiler_plugin.xml @@ -1,18 +1,11 @@ - - - - - 59a4f1fae9b7a4d8c3ea3739f728c6ea6973612554aea0f210eb1543499227f1 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_scripting_compiler_plugin.xml b/.idea/libraries/kotlinc_scripting_compiler_plugin.xml index 3b3406090ad4..ac1898242d85 100644 --- a/.idea/libraries/kotlinc_scripting_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_scripting_compiler_plugin.xml @@ -1,18 +1,11 @@ - - - - - e6babe8a19873e036c635f8219280bf8c67f1570eea9a2dcdbf5932fee2ed0d3 - - - + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_symbol_light_classes.xml b/.idea/libraries/kotlinc_symbol_light_classes.xml index 34b8b750062f..ee35f2b3f987 100644 --- a/.idea/libraries/kotlinc_symbol_light_classes.xml +++ b/.idea/libraries/kotlinc_symbol_light_classes.xml @@ -1,18 +1,11 @@ - - - - - 6d093b58dc94e04727988716535b59240cefd326832f31036b8b13c54f3f47fa - - - + - + - + \ No newline at end of file diff --git a/plugins/kotlin/util/project-model-updater/resources/model.properties b/plugins/kotlin/util/project-model-updater/resources/model.properties index e1c9c6389b23..e937f46db2c9 100644 --- a/plugins/kotlin/util/project-model-updater/resources/model.properties +++ b/plugins/kotlin/util/project-model-updater/resources/model.properties @@ -1,5 +1,5 @@ kotlincVersion=1.9.20-dev-8143 -kotlincArtifactsMode=MAVEN +kotlincArtifactsMode=BOOTSTRAP jpsPluginVersion=1.9.0-release-358 jpsPluginArtifactsMode=MAVEN From eeeb9c0dda817a5f6eacae169aa7e4d75067c2f6 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Fri, 28 Jul 2023 17:09:21 +0200 Subject: [PATCH 002/165] [kotlin] Fix test data #KTIJ-389 GitOrigin-RevId: 5d5b671dc79f23e2fd1ae0718e55a85c2b1c2c24 --- .../idea/tests/testData/codeInsight/postfix/forNumber2.kt | 4 ++-- .../tests/testData/codeInsight/postfix/forNumber2.kt.after | 4 ++-- .../tests/testData/quickfix/addVarianceModifier/abstractIn.kt | 3 ++- .../testData/quickfix/addVarianceModifier/abstractIn.kt.after | 3 ++- .../testData/quickfix/addVarianceModifier/abstractOut.kt | 3 ++- .../quickfix/addVarianceModifier/abstractOut.kt.after | 3 ++- .../testData/quickfix/kdocMissingDocumentation/simple.kt | 3 ++- .../quickfix/kdocMissingDocumentation/simple.kt.after | 3 ++- .../quickfix/kdocMissingDocumentation/withIndentation.kt | 3 ++- .../kdocMissingDocumentation/withIndentation.kt.after | 3 ++- .../quickfix/memberVisibilityCanBePrivate/constructorParam.kt | 3 ++- .../memberVisibilityCanBePrivate/constructorParam.kt.after | 3 ++- .../quickfix/memberVisibilityCanBePrivate/internal.kt | 3 ++- .../quickfix/memberVisibilityCanBePrivate/internal.kt.after | 3 ++- .../quickfix/memberVisibilityCanBePrivate/noModifier.kt | 3 ++- .../quickfix/memberVisibilityCanBePrivate/noModifier.kt.after | 3 ++- .../quickfix/memberVisibilityCanBePrivate/protected.kt | 3 ++- .../quickfix/memberVisibilityCanBePrivate/protected.kt.after | 3 ++- .../testData/quickfix/memberVisibilityCanBePrivate/public.kt | 3 ++- .../quickfix/memberVisibilityCanBePrivate/public.kt.after | 3 ++- 20 files changed, 40 insertions(+), 22 deletions(-) diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/postfix/forNumber2.kt b/plugins/kotlin/idea/tests/testData/codeInsight/postfix/forNumber2.kt index e167f83fe7db..418db8de3ead 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/postfix/forNumber2.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/postfix/forNumber2.kt @@ -1,3 +1,3 @@ -fun foo(i: Int) { - i.fori +fun foo(int: Int) { + int.fori } diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/postfix/forNumber2.kt.after b/plugins/kotlin/idea/tests/testData/codeInsight/postfix/forNumber2.kt.after index 041321a84cfa..ef8e632786cd 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/postfix/forNumber2.kt.after +++ b/plugins/kotlin/idea/tests/testData/codeInsight/postfix/forNumber2.kt.after @@ -1,5 +1,5 @@ -fun foo(i: Int) { - for (i1 in 0..i) { +fun foo(int: Int) { + for (i in 0..int) { } } diff --git a/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractIn.kt b/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractIn.kt index 1f83fe2629e4..b62711f56de2 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractIn.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractIn.kt @@ -2,4 +2,5 @@ abstract class AbstractIn<T>(private val foo: T) { fun bar(arg: T) = foo == arg } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractIn.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractIn.kt.after index c4ed6bd5a046..3ceba175d510 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractIn.kt.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractIn.kt.after @@ -2,4 +2,5 @@ abstract class AbstractIn(private val foo: T) { fun bar(arg: T) = foo == arg } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractOut.kt b/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractOut.kt index 7475240c5d21..16dfe62cafbd 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractOut.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractOut.kt @@ -3,4 +3,5 @@ abstract class AbstractOut<T> { abstract val foo: T private var bar = foo } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractOut.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractOut.kt.after index 2c54af72325a..c4ce4e1297a1 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractOut.kt.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/addVarianceModifier/abstractOut.kt.after @@ -3,4 +3,5 @@ abstract class AbstractOut { abstract val foo: T private var bar = foo } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.AddVarianceModifierInspection$AddVarianceFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/simple.kt b/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/simple.kt index 6345a79fbbc7..966600f7e5f2 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/simple.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/simple.kt @@ -3,4 +3,5 @@ class C { } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/simple.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/simple.kt.after index dfe1ed6acb08..e6d15781ee11 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/simple.kt.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/simple.kt.after @@ -6,4 +6,5 @@ class C { } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/withIndentation.kt b/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/withIndentation.kt index 525ed9ad040c..d1c93294a1ae 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/withIndentation.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/withIndentation.kt @@ -8,4 +8,5 @@ class C { } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/withIndentation.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/withIndentation.kt.after index f672bb838b34..288292298ace 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/withIndentation.kt.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/kdocMissingDocumentation/withIndentation.kt.after @@ -11,4 +11,5 @@ class C { } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.inspections.kdoc.KDocMissingDocumentationInspection$AddDocumentationFix \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/constructorParam.kt b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/constructorParam.kt index 0397ab0cd24f..7e2c0b390d72 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/constructorParam.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/constructorParam.kt @@ -5,4 +5,5 @@ class A(internal val a: String = "") { } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/constructorParam.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/constructorParam.kt.after index db02bfd39635..c35ae1ad7f32 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/constructorParam.kt.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/constructorParam.kt.after @@ -5,4 +5,5 @@ class A(private val a: String = "") { } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/internal.kt b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/internal.kt index 8814e9010662..21645a1d4a51 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/internal.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/internal.kt @@ -6,4 +6,5 @@ class A { a } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/internal.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/internal.kt.after index e8e31ecf770f..0e03316edf2b 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/internal.kt.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/internal.kt.after @@ -6,4 +6,5 @@ class A { a } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/noModifier.kt b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/noModifier.kt index f5d4b63a0c92..cdbafe765c8c 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/noModifier.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/noModifier.kt @@ -6,4 +6,5 @@ class A { a } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/noModifier.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/noModifier.kt.after index e8e31ecf770f..0e03316edf2b 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/noModifier.kt.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/noModifier.kt.after @@ -6,4 +6,5 @@ class A { a } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/protected.kt b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/protected.kt index 87fbd2fbcc2a..b18fcf081765 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/protected.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/protected.kt @@ -6,4 +6,5 @@ open class A { a } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/protected.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/protected.kt.after index ab4c51a3f78c..5ed74ec530f0 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/protected.kt.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/protected.kt.after @@ -6,4 +6,5 @@ open class A { a } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/public.kt b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/public.kt index b8046fcebe05..d861e7718f64 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/public.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/public.kt @@ -6,4 +6,5 @@ class A { a } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/public.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/public.kt.after index e8e31ecf770f..0e03316edf2b 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/public.kt.after +++ b/plugins/kotlin/idea/tests/testData/quickfix/memberVisibilityCanBePrivate/public.kt.after @@ -6,4 +6,5 @@ class A { a } } -// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file +// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 +// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.AddModifierFixFE10 \ No newline at end of file From 868065975f66525f55c092d54815b5a5d2916311 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 28 Jul 2023 20:24:18 +0200 Subject: [PATCH 003/165] [kotlin] k2: fix testdata after the actual fix GitOrigin-RevId: bbccf81f6f8be95c0a425ab8d9d8bd0e906dba40 --- .../baseAndOverridingPropertyInCtrUsages.fir.results.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 plugins/kotlin/idea/tests/testData/findUsages/kotlin/findPropertyUsages/baseAndOverridingPropertyInCtrUsages.fir.results.txt diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findPropertyUsages/baseAndOverridingPropertyInCtrUsages.fir.results.txt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findPropertyUsages/baseAndOverridingPropertyInCtrUsages.fir.results.txt deleted file mode 100644 index 207e11615696..000000000000 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findPropertyUsages/baseAndOverridingPropertyInCtrUsages.fir.results.txt +++ /dev/null @@ -1,2 +0,0 @@ -Value read 11 val d = m.openProp -Value write 13 m.openProp = "" From f18f01ad0085656da52597848ff663536232b7ae Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 28 Jul 2023 21:08:44 +0200 Subject: [PATCH 004/165] [kotlin] k2: ensure validator finds conflicts with locals in top level functions see e.g `KotlinPostfixTemplateTestGenerated.Fori.testForIndexed2` GitOrigin-RevId: f122c464e0ddaee7e2dbee0402c32b107be41098 --- .../base/codeInsight/KotlinDeclarationNameValidator.kt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/base/codeInsight/KotlinDeclarationNameValidator.kt b/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/base/codeInsight/KotlinDeclarationNameValidator.kt index 7f3226a04d5d..0e9fabec453e 100644 --- a/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/base/codeInsight/KotlinDeclarationNameValidator.kt +++ b/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/base/codeInsight/KotlinDeclarationNameValidator.kt @@ -40,17 +40,13 @@ class KotlinDeclarationNameValidator( context(KtAnalysisSession) private fun hasConflict(identifier: Name): Boolean { - fun KtVariableLikeSymbol.isVisible(): Boolean { - val classSymbol = visibleDeclarationsContext.containingClass()?.getClassOrObjectSymbol() ?: return false - return isVisibleInClass(classSymbol) - } - return when(target) { KotlinNameSuggestionProvider.ValidatorTarget.PROPERTY, KotlinNameSuggestionProvider.ValidatorTarget.VARIABLE, KotlinNameSuggestionProvider.ValidatorTarget.PARAMETER -> { val scope = visibleDeclarationsContext.containingKtFile.getScopeContextForPosition(visibleDeclarationsContext).getCompositeScope() + val containingClassSymbol = lazy(LazyThreadSafetyMode.NONE) { visibleDeclarationsContext.containingClass()?.getClassOrObjectSymbol() } scope.getCallableSymbols(identifier).filterIsInstance().any { - !it.isExtension && it.isVisible() + !it.isExtension && (containingClassSymbol.value?.let { cl -> it.isVisibleInClass(cl) } != false) } } else -> false From b4711810bfa1c954eea1db82b5b53a809e5191da Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Fri, 28 Jul 2023 15:46:49 +0200 Subject: [PATCH 005/165] [kotlin] update testdata after KTIJ-24230 is fixed GitOrigin-RevId: 4d9d5000046757f166d1569727d366a85c3c65c0 --- .../kotlinReifiedTypeParameterUsages.0.kt | 2 +- ...ReifiedTypeParameterUsages.fir.results.txt | 2 -- ...tlinReifiedTypeParameterUsages.results.txt | 2 +- .../legacyResolved/Reified.resolved.fir.txt | 27 ------------------- ...resolved.fe10.txt => Reified.resolved.txt} | 0 5 files changed, 2 insertions(+), 31 deletions(-) delete mode 100644 plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.fir.results.txt delete mode 100644 plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyResolved/Reified.resolved.fir.txt rename plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyResolved/{Reified.resolved.fe10.txt => Reified.resolved.txt} (100%) diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.0.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.0.kt index 246bb308f4a3..8c242d754ec2 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.0.kt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.0.kt @@ -3,5 +3,5 @@ inline fun T> fff(labelText: String, a: Any): T { if (a is T) {} - return T::class.java.getConstructor().newInstance() //not found in K2, KTIJ-24230 + return T::class.java.getConstructor().newInstance() } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.fir.results.txt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.fir.results.txt deleted file mode 100644 index ef5aa14d81eb..000000000000 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.fir.results.txt +++ /dev/null @@ -1,2 +0,0 @@ -Function return types 4 inline fun fff(labelText: String, a: Any): T { -Target type of 'is' operation 5 if (a is T) {} diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.results.txt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.results.txt index 70118629da9a..d6d5d6b971b3 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.results.txt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.results.txt @@ -1,3 +1,3 @@ Function return types 4 inline fun fff(labelText: String, a: Any): T { Target type of 'is' operation 5 if (a is T) {} -Unclassified 6 return T::class.java.getConstructor().newInstance() //not found in K2, KTIJ-24230 +Unclassified 6 return T::class.java.getConstructor().newInstance() diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyResolved/Reified.resolved.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyResolved/Reified.resolved.fir.txt deleted file mode 100644 index c48904db2d35..000000000000 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyResolved/Reified.resolved.fir.txt +++ /dev/null @@ -1,27 +0,0 @@ -null -> UQualifiedReferenceExpression -> PsiPackage:test.pkg: pkg -UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = test) -> PsiPackage:test: test -UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = pkg) -> PsiPackage:test.pkg: pkg -UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to null) -> USimpleNameReferenceExpression (identifier = getSystemService) -> null: null -UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to null) -> UQualifiedReferenceExpression -> Decompiled_Method: getJavaClass -UClassLiteralExpression -> USimpleNameReferenceExpression (identifier = T) -> null: null -UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> Decompiled_Method: getJavaClass -UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to null) -> USimpleNameReferenceExpression (identifier = getSystemService) -> null: null -UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to null) -> UQualifiedReferenceExpression -> Decompiled_Method: getJavaClass -UClassLiteralExpression -> USimpleNameReferenceExpression (identifier = String) -> Decompiled_Class: String -UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> Decompiled_Method: getJavaClass -UTypeReferenceExpression (name = test.pkg.Context) -> USimpleNameReferenceExpression (identifier = Context) -> Kotlin_Light_Class:class Context { - inline fun ownSystemService1() = getSystemService(T::class.java) - inline fun ownSystemService2() = getSystemService(String::class.java) -}: Context -UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to null) -> USimpleNameReferenceExpression (identifier = getSystemService) -> null: null -UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to null) -> UQualifiedReferenceExpression -> Decompiled_Method: getJavaClass -UClassLiteralExpression -> USimpleNameReferenceExpression (identifier = T) -> null: null -UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> Decompiled_Method: getJavaClass -UTypeReferenceExpression (name = test.pkg.Context) -> USimpleNameReferenceExpression (identifier = Context) -> Kotlin_Light_Class:class Context { - inline fun ownSystemService1() = getSystemService(T::class.java) - inline fun ownSystemService2() = getSystemService(String::class.java) -}: Context -UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to null) -> USimpleNameReferenceExpression (identifier = getSystemService) -> null: null -UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to null) -> UQualifiedReferenceExpression -> Decompiled_Method: getJavaClass -UClassLiteralExpression -> USimpleNameReferenceExpression (identifier = String) -> Decompiled_Class: String -UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> Decompiled_Method: getJavaClass diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyResolved/Reified.resolved.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyResolved/Reified.resolved.txt similarity index 100% rename from plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyResolved/Reified.resolved.fe10.txt rename to plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyResolved/Reified.resolved.txt From e77387d337d618dc0e8366d5448b6849cefccb9c Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Fri, 21 Jul 2023 16:44:47 +0300 Subject: [PATCH 006/165] [kotlin] K2: add test for KTIJ-26113 GitOrigin-RevId: d46e3623a975db8786801ad95e9f8871a618ca14 --- .../testData/basic/common/when/smartCast.kt | 8 +++++++ .../testData/basic/common/when/smartCast2.kt | 8 +++++++ .../testData/basic/common/when/smartCast3.kt | 8 +++++++ .../test/JSBasicCompletionTestGenerated.java | 23 +++++++++++++++++++ .../test/JvmBasicCompletionTestGenerated.java | 23 +++++++++++++++++++ ...hLevelJvmBasicCompletionTestGenerated.java | 23 +++++++++++++++++++ 6 files changed, 93 insertions(+) create mode 100644 plugins/kotlin/completion/testData/basic/common/when/smartCast.kt create mode 100644 plugins/kotlin/completion/testData/basic/common/when/smartCast2.kt create mode 100644 plugins/kotlin/completion/testData/basic/common/when/smartCast3.kt diff --git a/plugins/kotlin/completion/testData/basic/common/when/smartCast.kt b/plugins/kotlin/completion/testData/basic/common/when/smartCast.kt new file mode 100644 index 000000000000..1b417f680871 --- /dev/null +++ b/plugins/kotlin/completion/testData/basic/common/when/smartCast.kt @@ -0,0 +1,8 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +private fun Any.test(): Int = when { + this is String -> { len } + //else -> 0 +} + +// EXIST: length \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/basic/common/when/smartCast2.kt b/plugins/kotlin/completion/testData/basic/common/when/smartCast2.kt new file mode 100644 index 000000000000..3da8f4f2913e --- /dev/null +++ b/plugins/kotlin/completion/testData/basic/common/when/smartCast2.kt @@ -0,0 +1,8 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +private fun Any.test(): Int = when { + this is String -> len + else -> 0 +} + +// EXIST: length \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/basic/common/when/smartCast3.kt b/plugins/kotlin/completion/testData/basic/common/when/smartCast3.kt new file mode 100644 index 000000000000..2eb841f5feeb --- /dev/null +++ b/plugins/kotlin/completion/testData/basic/common/when/smartCast3.kt @@ -0,0 +1,8 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +private fun Any.test(): Int = when { + this !is String || len -> 1 + else -> 0 +} + +// EXIST: length \ No newline at end of file diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index 60d138ad1363..1c2df46b89bd 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -3349,6 +3349,29 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp runTest("../testData/basic/common/visibility/VisibilityPrivateToThisWithWrongThis.kt"); } } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../testData/basic/common/when") + public static class When extends AbstractJSBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("smartCast.kt") + public void testSmartCast() throws Exception { + runTest("../testData/basic/common/when/smartCast.kt"); + } + + @TestMetadata("smartCast2.kt") + public void testSmartCast2() throws Exception { + runTest("../testData/basic/common/when/smartCast2.kt"); + } + + @TestMetadata("smartCast3.kt") + public void testSmartCast3() throws Exception { + runTest("../testData/basic/common/when/smartCast3.kt"); + } + } } @RunWith(JUnit3RunnerWithInners.class) diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index 66c38ff5cc13..f656e81cd119 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -3349,6 +3349,29 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo runTest("../testData/basic/common/visibility/VisibilityPrivateToThisWithWrongThis.kt"); } } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../testData/basic/common/when") + public static class When extends AbstractJvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("smartCast.kt") + public void testSmartCast() throws Exception { + runTest("../testData/basic/common/when/smartCast.kt"); + } + + @TestMetadata("smartCast2.kt") + public void testSmartCast2() throws Exception { + runTest("../testData/basic/common/when/smartCast2.kt"); + } + + @TestMetadata("smartCast3.kt") + public void testSmartCast3() throws Exception { + runTest("../testData/basic/common/when/smartCast3.kt"); + } + } } @RunWith(JUnit3RunnerWithInners.class) diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java index 1dcad8542ab8..f10b23cac1a9 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java @@ -3349,6 +3349,29 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH runTest("../completion/testData/basic/common/visibility/VisibilityPrivateToThisWithWrongThis.kt"); } } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../completion/testData/basic/common/when") + public static class When extends AbstractHighLevelJvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("smartCast.kt") + public void testSmartCast() throws Exception { + runTest("../completion/testData/basic/common/when/smartCast.kt"); + } + + @TestMetadata("smartCast2.kt") + public void testSmartCast2() throws Exception { + runTest("../completion/testData/basic/common/when/smartCast2.kt"); + } + + @TestMetadata("smartCast3.kt") + public void testSmartCast3() throws Exception { + runTest("../completion/testData/basic/common/when/smartCast3.kt"); + } + } } @RunWith(JUnit3RunnerWithInners.class) From 7347a26e274dceade056d5a24fdf6101cf91b0c2 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Wed, 26 Jul 2023 14:16:56 +0200 Subject: [PATCH 007/165] [kotlin] get rid of `analyzeWithReadAction` usages It's removed from the Analysis API GitOrigin-RevId: 22ce4aa378ef35348cb9d618ca8da8d83229e30a --- ...actKotlinApplicableIntentionWithContext.kt | 2 +- .../usages/KotlinK2SearchUsagesSupport.kt | 35 ++++++++++--------- .../usages/KotlinK2UsageTypeProvider.kt | 4 +-- .../idea/searching/usages/findUsagesUtils.kt | 4 +-- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/plugins/kotlin/code-insight/api/src/org/jetbrains/kotlin/idea/codeinsight/api/applicable/intentions/AbstractKotlinApplicableIntentionWithContext.kt b/plugins/kotlin/code-insight/api/src/org/jetbrains/kotlin/idea/codeinsight/api/applicable/intentions/AbstractKotlinApplicableIntentionWithContext.kt index 18c2c2111e54..be25a5a72e4d 100644 --- a/plugins/kotlin/code-insight/api/src/org/jetbrains/kotlin/idea/codeinsight/api/applicable/intentions/AbstractKotlinApplicableIntentionWithContext.kt +++ b/plugins/kotlin/code-insight/api/src/org/jetbrains/kotlin/idea/codeinsight/api/applicable/intentions/AbstractKotlinApplicableIntentionWithContext.kt @@ -33,7 +33,7 @@ abstract class AbstractKotlinApplicableIntentionWithContext { - analyzeWithReadAction(psiElement) { + analyze(psiElement) { fun getPsiClassOfKtType(ktType: KtType): PsiClass? { val psi = ktType.asPsiType(psiElement, allowErrorTypes = false, KtTypeMappingMode.DEFAULT, isAnnotationMethod = false) return (psi as? PsiClassReferenceType)?.resolve() @@ -170,22 +171,24 @@ internal class KotlinK2SearchUsagesSupport : KotlinSearchUsagesSupport { is KtValueParameterSymbol -> { // TODO: The following code handles only constructors. Handle other cases e.g., // look for uses of component functions cf [isDestructionDeclarationSearch] - val psiClass = PsiTreeUtil.getParentOfType(psiElement, KtClassOrObject::class.java)?.toLightClass() ?: return@analyzeWithReadAction null + val psiClass = PsiTreeUtil.getParentOfType(psiElement, KtClassOrObject::class.java)?.toLightClass() ?: return@analyze null val classPointer = psiClass.createSmartPointer() ReceiverTypeSearcherInfo(psiClass) { declaration -> - analyzeWithReadAction(declaration) { - fun KtType.containsClassType(clazz: PsiClass?): Boolean { - if (clazz == null) return false - return this is KtNonErrorClassType && (clazz.unwrapped?.isEquivalentTo(classSymbol.psi) == true || ownTypeArguments.any { arg -> - when (arg) { - is KtStarTypeProjection -> false - is KtTypeArgumentWithVariance -> arg.type.containsClassType(clazz) - } - }) - } + runReadAction { + analyze(declaration) { + fun KtType.containsClassType(clazz: PsiClass?): Boolean { + if (clazz == null) return false + return this is KtNonErrorClassType && (clazz.unwrapped?.isEquivalentTo(classSymbol.psi) == true || ownTypeArguments.any { arg -> + when (arg) { + is KtStarTypeProjection -> false + is KtTypeArgumentWithVariance -> arg.type.containsClassType(clazz) + } + }) + } - declaration.getReturnKtType().containsClassType(classPointer.element) + declaration.getReturnKtType().containsClassType(classPointer.element) + } } } } @@ -288,7 +291,7 @@ internal class KotlinK2SearchUsagesSupport : KotlinSearchUsagesSupport { override fun isInheritable(ktClass: KtClass): Boolean { if (ApplicationManager.getApplication().isDispatchThread) { return ProgressManager.getInstance().runProcessWithProgressSynchronously( - Runnable { isOverridableBySymbol(ktClass) }, + Runnable { runReadAction { isOverridableBySymbol(ktClass) } }, KotlinBundle.message("dialog.title.resolving.inheritable.status"), true, ktClass.project @@ -297,12 +300,12 @@ internal class KotlinK2SearchUsagesSupport : KotlinSearchUsagesSupport { return isOverridableBySymbol(ktClass) } - private fun isOverridableBySymbol(declaration: KtDeclaration) = analyzeWithReadAction(declaration) { + private fun isOverridableBySymbol(declaration: KtDeclaration) = analyze(declaration) { var declarationSymbol : KtSymbol? = declaration.getSymbol() if (declarationSymbol is KtValueParameterSymbol) { declarationSymbol = declarationSymbol.generatedPrimaryConstructorProperty } - val symbol = declarationSymbol as? KtSymbolWithModality ?: return@analyzeWithReadAction false + val symbol = declarationSymbol as? KtSymbolWithModality ?: return@analyze false when (symbol.modality) { Modality.OPEN, Modality.SEALED, Modality.ABSTRACT -> true Modality.FINAL -> false diff --git a/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/KotlinK2UsageTypeProvider.kt b/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/KotlinK2UsageTypeProvider.kt index 7d7cfa317b5e..db3baeb1f572 100644 --- a/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/KotlinK2UsageTypeProvider.kt +++ b/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/KotlinK2UsageTypeProvider.kt @@ -3,7 +3,7 @@ package org.jetbrains.kotlin.idea.searching.usages import com.intellij.psi.PsiPackage -import org.jetbrains.kotlin.analysis.api.analyzeWithReadAction +import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.idea.base.searching.usages.KotlinUsageTypeProvider import org.jetbrains.kotlin.idea.base.searching.usages.UsageTypeEnum @@ -46,7 +46,7 @@ internal class KotlinK2UsageTypeProvider : KotlinUsageTypeProvider() { } } - return analyzeWithReadAction(refExpr) { + return analyze(refExpr) { when (val targetElement = reference.resolveToSymbol()) { is KtClassifierSymbol -> when (targetElement) { diff --git a/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/findUsagesUtils.kt b/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/findUsagesUtils.kt index 7b4dc9edfcc6..6f3dbbcf86e8 100644 --- a/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/findUsagesUtils.kt +++ b/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/findUsagesUtils.kt @@ -2,7 +2,7 @@ package org.jetbrains.kotlin.idea.searching.usages import org.jetbrains.kotlin.analysis.api.KtAnalysisSession -import org.jetbrains.kotlin.analysis.api.analyzeWithReadAction +import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.calls.KtCall import org.jetbrains.kotlin.analysis.api.calls.calls import org.jetbrains.kotlin.idea.base.facet.platform.platform @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.ImportPath internal inline fun withResolvedCall(element: KtElement, crossinline block: KtAnalysisSession.(KtCall) -> R): R? { - return analyzeWithReadAction(element) { + return analyze(element) { element.resolveCall()?.calls?.singleOrNull()?.let { block(it) } } } From 6af5bcffc4669583ecde199b079ab57d985ac106 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Wed, 26 Jul 2023 14:37:41 +0200 Subject: [PATCH 008/165] [Kotlin] remove `analyzeInModalWindow` to the intellij repository As it's IDE-specific functionality GitOrigin-RevId: f1ab6d9d236e60e4a78e3ce10c7197692c336a21 --- .../base/analysis/api/utils/analyzeUtils.kt | 32 +++++++++++++++++++ .../usages/KotlinK2FindUsagesSupport.kt | 2 +- .../KotlinIntroduceVariableHandler.kt | 2 +- .../KotlinVariableInplaceIntroducer.kt | 2 +- .../elementSelectionUtils.kt | 2 +- .../introduceVariableUtil.kt | 2 +- .../KotlinFirSafeDeleteProcessor.kt | 2 +- .../kotlin/idea/k2/refactoring/utils.kt | 2 +- 8 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/analyzeUtils.kt diff --git a/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/analyzeUtils.kt b/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/analyzeUtils.kt new file mode 100644 index 000000000000..2d4e44878db7 --- /dev/null +++ b/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/analyzeUtils.kt @@ -0,0 +1,32 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.base.analysis.api.utils + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.runReadAction +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.Task +import com.intellij.openapi.util.NlsContexts.DialogTitle +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.analyze +import org.jetbrains.kotlin.psi.KtElement + +/** + * Show a modal window with a progress bar and specified [windowTitle] + * and execute given [action] task with [KtAnalysisSession] context + * If [action] throws some exception, then [analyzeInModalWindow] will rethrow it + * Should be executed from EDT only + * If you want to analyse something from non-EDT thread, consider using [analyze] + */ +inline fun analyzeInModalWindow( + contextElement: KtElement, + @DialogTitle windowTitle: String, + crossinline action: KtAnalysisSession.() -> R +): R { + ApplicationManager.getApplication().assertIsDispatchThread() + val task = object : Task.WithResult(contextElement.project, windowTitle, /*canBeCancelled*/ true) { + override fun compute(indicator: ProgressIndicator): R = + runReadAction { analyze(contextElement, action) } + } + task.queue() + return task.result +} diff --git a/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/KotlinK2FindUsagesSupport.kt b/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/KotlinK2FindUsagesSupport.kt index 12a46d544320..e1a8ab0e6e2c 100644 --- a/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/KotlinK2FindUsagesSupport.kt +++ b/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/usages/KotlinK2FindUsagesSupport.kt @@ -13,7 +13,7 @@ import com.intellij.psi.util.PsiFormatUtilBase import com.intellij.util.Processor import org.jetbrains.annotations.Nls import org.jetbrains.kotlin.analysis.api.KtAnalysisSession -import org.jetbrains.kotlin.analysis.api.analyzeInModalWindow +import org.jetbrains.kotlin.idea.base.analysis.api.utils.analyzeInModalWindow import org.jetbrains.kotlin.analysis.api.calls.* import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KtRendererAnnotationsFilter import org.jetbrains.kotlin.analysis.api.renderer.declarations.KtDeclarationRenderer diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt b/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt index e12e784915ad..7d29a09eb2f8 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt @@ -21,7 +21,7 @@ import com.intellij.util.SmartList import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisFromWriteAction import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.analyze -import org.jetbrains.kotlin.analysis.api.analyzeInModalWindow +import org.jetbrains.kotlin.idea.base.analysis.api.utils.analyzeInModalWindow import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisFromWriteAction import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KtRendererAnnotationsFilter diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/KotlinVariableInplaceIntroducer.kt b/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/KotlinVariableInplaceIntroducer.kt index b12cb6bd7510..53ac220f4e51 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/KotlinVariableInplaceIntroducer.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/KotlinVariableInplaceIntroducer.kt @@ -24,7 +24,7 @@ import com.intellij.refactoring.rename.inplace.TemplateInlayUtil.createSettingsP import com.intellij.ui.dsl.builder.actionListener import com.intellij.ui.dsl.builder.panel import com.intellij.ui.dsl.builder.selected -import org.jetbrains.kotlin.analysis.api.analyzeInModalWindow +import org.jetbrains.kotlin.idea.base.analysis.api.utils.analyzeInModalWindow import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.codeinsights.impl.base.CallableReturnTypeUpdaterUtils import org.jetbrains.kotlin.idea.refactoring.KotlinCommonRefactoringSettings diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/elementSelectionUtils.kt b/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/elementSelectionUtils.kt index 2444d0e9be1e..6fe3643acbc3 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/elementSelectionUtils.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/elementSelectionUtils.kt @@ -10,7 +10,7 @@ import com.intellij.openapi.util.NlsSafe import com.intellij.platform.backend.presentation.TargetPresentation import com.intellij.psi.* import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.analysis.api.analyzeInModalWindow +import org.jetbrains.kotlin.idea.base.analysis.api.utils.analyzeInModalWindow import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.refactoring.introduce.IntroduceRefactoringException import org.jetbrains.kotlin.idea.refactoring.renderTrimmed diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/introduceVariableUtil.kt b/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/introduceVariableUtil.kt index b392cf241704..10391b0b3984 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/introduceVariableUtil.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.introduce.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/introduceVariable/introduceVariableUtil.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.idea.k2.refactoring.introduce.introduceVariable import com.intellij.openapi.editor.Editor import com.intellij.openapi.ui.popup.JBPopupFactory import org.jetbrains.kotlin.analysis.api.KtAnalysisSession -import org.jetbrains.kotlin.analysis.api.analyzeInModalWindow +import org.jetbrains.kotlin.idea.base.analysis.api.utils.analyzeInModalWindow import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability import org.jetbrains.kotlin.idea.base.resources.KotlinBundle diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/KotlinFirSafeDeleteProcessor.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/KotlinFirSafeDeleteProcessor.kt index 74527c517cc2..dfee5d3afb3f 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/KotlinFirSafeDeleteProcessor.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/KotlinFirSafeDeleteProcessor.kt @@ -18,7 +18,7 @@ import com.intellij.usageView.UsageInfo import com.intellij.util.Processor import com.intellij.util.containers.map2Array import org.jetbrains.kotlin.analysis.api.analyze -import org.jetbrains.kotlin.analysis.api.analyzeInModalWindow +import org.jetbrains.kotlin.idea.base.analysis.api.utils.analyzeInModalWindow import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/utils.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/utils.kt index eb6cf2333410..803ca2ee6942 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/utils.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/utils.kt @@ -8,7 +8,7 @@ import com.intellij.psi.ElementDescriptionUtil import com.intellij.psi.PsiElement import com.intellij.refactoring.util.RefactoringDescriptionLocation import org.jetbrains.annotations.Nls -import org.jetbrains.kotlin.analysis.api.analyzeInModalWindow +import org.jetbrains.kotlin.idea.base.analysis.api.utils.analyzeInModalWindow import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.idea.util.application.isUnitTestMode import org.jetbrains.kotlin.lexer.KtTokens From d844a6764da6192b78615c68da5c825f552c52e0 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Wed, 26 Jul 2023 14:38:23 +0200 Subject: [PATCH 009/165] [Kotlin] fix capitalization of window title in K2 refactorings GitOrigin-RevId: b8767ffc4bc3f54bd702f11b33bee976274ef177 --- plugins/kotlin/kotlin.searching/kotlin.searching.k2.iml | 1 + .../resources/messages/KotlinK2RefactoringsBundle.properties | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/kotlin/kotlin.searching/kotlin.searching.k2.iml b/plugins/kotlin/kotlin.searching/kotlin.searching.k2.iml index 68c3c58aeaea..2ecbe5d53ebd 100644 --- a/plugins/kotlin/kotlin.searching/kotlin.searching.k2.iml +++ b/plugins/kotlin/kotlin.searching/kotlin.searching.k2.iml @@ -40,5 +40,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/resources/messages/KotlinK2RefactoringsBundle.properties b/plugins/kotlin/refactorings/kotlin.refactorings.k2/resources/messages/KotlinK2RefactoringsBundle.properties index 4726252653c1..9a614e1fd9c3 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/resources/messages/KotlinK2RefactoringsBundle.properties +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/resources/messages/KotlinK2RefactoringsBundle.properties @@ -1,3 +1,3 @@ override.declaration.x.overrides.y.in.class.list={0} overrides declarations in the following classes/interfaces: {1} Do you want to {2} the base declarations? -resolving.super.methods.progress.title=Resolving super methods\u2026 +resolving.super.methods.progress.title=Resolving Super Methods? safe.delete.implements.conflict.message={0} implements {1}. From 6b3554d6c49b419aa314f74a1607375dc82d66a0 Mon Sep 17 00:00:00 2001 From: Bart van Helvert Date: Mon, 31 Jul 2023 17:45:14 +0200 Subject: [PATCH 010/165] [kotlin] Fix bindToElement K2 KDoc tests GitOrigin-RevId: 946f50ba59dede4fa0e0f0986452c6932322d0c3 --- .../kotlin.refactorings.tests.k2.iml | 1 + .../safeDelete/AbstractK2BindToElementTest.kt | 18 +- .../K2BindToElementTestGenerated.java | 160 ++++++++++++------ .../GenerateK2RefactoringsTests.kt | 11 +- 4 files changed, 117 insertions(+), 73 deletions(-) diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/kotlin.refactorings.tests.k2.iml b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/kotlin.refactorings.tests.k2.iml index 25b4ffae4b38..38c18b9300d4 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/kotlin.refactorings.tests.k2.iml +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/kotlin.refactorings.tests.k2.iml @@ -15,5 +15,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/AbstractK2BindToElementTest.kt b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/AbstractK2BindToElementTest.kt index 568239c4b447..88e231585703 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/AbstractK2BindToElementTest.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/AbstractK2BindToElementTest.kt @@ -2,7 +2,6 @@ package org.jetbrains.kotlin.idea.k2.refactoring.safeDelete import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.search.GlobalSearchScope @@ -11,8 +10,10 @@ import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex import org.jetbrains.kotlin.idea.test.* import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.kdoc.psi.impl.KDocName import org.jetbrains.kotlin.psi.KtSimpleNameExpression abstract class AbstractK2BindToElementTest : KotlinMultiFileLightCodeInsightFixtureTestCase() { @@ -25,23 +26,24 @@ abstract class AbstractK2BindToElementTest : KotlinMultiFileLightCodeInsightFixt val mainFile = files.first() myFixture.configureFromExistingVirtualFile(mainFile.virtualFile) val elem = mainFile.findElementAt(myFixture.caretOffset) ?: error("Couldn't find element at caret") - val nameReference = elem.parentOfType(withSelf = true) + val refElement = elem.parentOfType(withSelf = true) + ?: elem.parentOfType() ?: error("Element at caret isn't of type 'KtSimpleNameExpression'") + val mainReference = refElement.mainReference ?: error("Ref element doesn't have a main reference") val bindTarget = findElementToBind()?.unwrapped ?: error("Could not find element to bind") myFixture.project.executeWriteCommand("bindToElement") { - nameReference.mainReference.bindToElement(bindTarget) + mainReference.bindToElement(bindTarget) } myFixture.checkResultByFile("${dataFile().name}.after") } private fun findElementToBind(): PsiElement? { - val classToBind = InTextDirectivesUtils.findStringWithPrefixes(file.text, BIND_TO) - return classToBind?.let(::findClass) + val nameToBind = InTextDirectivesUtils.findStringWithPrefixes(file.text, BIND_TO) ?: return null + val projectScope = GlobalSearchScope.allScope(myFixture.project) + return JavaPsiFacade.getInstance(myFixture.project).findClass(nameToBind, projectScope) + ?: KotlinTopLevelFunctionFqnNameIndex[nameToBind, myFixture.project, projectScope].firstOrNull() } - private fun findClass(fqn: String): PsiClass? = JavaPsiFacade.getInstance(myFixture.project) - .findClass(fqn, GlobalSearchScope.allScope(myFixture.project)) - private companion object { const val BIND_TO = "BIND_TO" } diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java index d174f305d85c..67e34ffdc2fe 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java @@ -17,7 +17,54 @@ import org.junit.runner.RunWith; @TestRoot("refactorings/kotlin.refactorings.tests.k2") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) +@TestMetadata("../../idea/tests/testData/refactoring/bindToElement") public abstract class K2BindToElementTestGenerated extends AbstractK2BindToElementTest { + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/annotationCall") + public static class AnnotationCall extends AbstractK2BindToElementTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("FullyQualified.kt") + public void testFullyQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/annotationCall/FullyQualified.kt"); + } + + @TestMetadata("RootPkg.kt") + public void testRootPkg() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/annotationCall/RootPkg.kt"); + } + + @TestMetadata("UnQualified.kt") + public void testUnQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/annotationCall/UnQualified.kt"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/annotationReference") + public static class AnnotationReference extends AbstractK2BindToElementTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("FullyQualified.kt") + public void testFullyQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/annotationReference/FullyQualified.kt"); + } + + @TestMetadata("RootPkg.kt") + public void testRootPkg() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/annotationReference/RootPkg.kt"); + } + + @TestMetadata("UnQualified.kt") + public void testUnQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/annotationReference/UnQualified.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/callableReference") public static class CallableReference extends AbstractK2BindToElementTest { @@ -41,6 +88,19 @@ public abstract class K2BindToElementTestGenerated extends AbstractK2BindToEleme } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/changeImport") + public static class ChangeImport extends AbstractK2BindToElementTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("ChangeImport.kt") + public void testChangeImport() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/changeImport/ChangeImport.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/constructorCall") public static class ConstructorCall extends AbstractK2BindToElementTest { @@ -70,48 +130,48 @@ public abstract class K2BindToElementTestGenerated extends AbstractK2BindToEleme } @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/superTypeCall") - public static class SuperTypeCall extends AbstractK2BindToElementTest { + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/delegatedSuperTypeReference") + public static class DelegatedSuperTypeReference extends AbstractK2BindToElementTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @TestMetadata("FullyQualified.kt") public void testFullyQualified() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/superTypeCall/FullyQualified.kt"); + runTest("../../idea/tests/testData/refactoring/bindToElement/delegatedSuperTypeReference/FullyQualified.kt"); } @TestMetadata("RootPkg.kt") public void testRootPkg() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/superTypeCall/RootPkg.kt"); + runTest("../../idea/tests/testData/refactoring/bindToElement/delegatedSuperTypeReference/RootPkg.kt"); } - @TestMetadata("UnQualified.kt") - public void testUnQualified() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/superTypeCall/UnQualified.kt"); + @TestMetadata("Unqualified.kt") + public void testUnqualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/delegatedSuperTypeReference/Unqualified.kt"); } } @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/annotationCall") - public static class AnnotationCall extends AbstractK2BindToElementTest { + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/docReference") + public static class DocReference extends AbstractK2BindToElementTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @TestMetadata("FullyQualified.kt") public void testFullyQualified() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/annotationCall/FullyQualified.kt"); + runTest("../../idea/tests/testData/refactoring/bindToElement/docReference/FullyQualified.kt"); } @TestMetadata("RootPkg.kt") public void testRootPkg() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/annotationCall/RootPkg.kt"); + runTest("../../idea/tests/testData/refactoring/bindToElement/docReference/RootPkg.kt"); } @TestMetadata("UnQualified.kt") public void testUnQualified() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/annotationCall/UnQualified.kt"); + runTest("../../idea/tests/testData/refactoring/bindToElement/docReference/UnQualified.kt"); } } @@ -161,6 +221,29 @@ public abstract class K2BindToElementTestGenerated extends AbstractK2BindToEleme } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/superTypeCall") + public static class SuperTypeCall extends AbstractK2BindToElementTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("FullyQualified.kt") + public void testFullyQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/superTypeCall/FullyQualified.kt"); + } + + @TestMetadata("RootPkg.kt") + public void testRootPkg() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/superTypeCall/RootPkg.kt"); + } + + @TestMetadata("UnQualified.kt") + public void testUnQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/superTypeCall/UnQualified.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/superTypeReference") public static class SuperTypeReference extends AbstractK2BindToElementTest { @@ -185,61 +268,28 @@ public abstract class K2BindToElementTestGenerated extends AbstractK2BindToEleme } @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/delegatedSuperTypeReference") - public static class DelegatedSuperTypeReference extends AbstractK2BindToElementTest { + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall") + public static class TopLevelFunctionCall extends AbstractK2BindToElementTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } - @TestMetadata("FullyQualified.kt") - public void testFullyQualified() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/delegatedSuperTypeReference/FullyQualified.kt"); - } - - @TestMetadata("RootPkg.kt") - public void testRootPkg() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/delegatedSuperTypeReference/RootPkg.kt"); - } - - @TestMetadata("Unqualified.kt") - public void testUnqualified() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/delegatedSuperTypeReference/Unqualified.kt"); + @TestMetadata("TopLevelFunctionCall.kt") + public void testTopLevelFunctionCall() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt"); } } @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/annotationReference") - public static class AnnotationReference extends AbstractK2BindToElementTest { + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/importReference") + public static class ImportReference extends AbstractK2BindToElementTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } - @TestMetadata("FullyQualified.kt") - public void testFullyQualified() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/annotationReference/FullyQualified.kt"); - } - - @TestMetadata("RootPkg.kt") - public void testRootPkg() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/annotationReference/RootPkg.kt"); - } - - @TestMetadata("UnQualified.kt") - public void testUnQualified() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/annotationReference/UnQualified.kt"); - } - } - - @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/changeImport") - public static class ChangeImport extends AbstractK2BindToElementTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); - } - - @TestMetadata("ChangeImport.kt") - public void testChangeImport() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/changeImport/ChangeImport.kt"); + @TestMetadata("ImportReference.kt") + public void testImportReference() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt"); } } } diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2RefactoringsTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2RefactoringsTests.kt index d72eb848c31a..f6c3029f6151 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2RefactoringsTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2RefactoringsTests.kt @@ -32,16 +32,7 @@ internal fun MutableTWorkspace.generateK2RefactoringsTests() { model("refactoring/safeDelete/deleteValueParameter/javaParameterWithKotlin", pattern = Patterns.JAVA, testMethodName = "doJavaParameterTest") } testClass { - model("refactoring/bindToElement/callableReference") - model("refactoring/bindToElement/constructorCall") - model("refactoring/bindToElement/superTypeCall") - model("refactoring/bindToElement/annotationCall") - model("refactoring/bindToElement/propertyTypeReference") - model("refactoring/bindToElement/returnTypeReference") - model("refactoring/bindToElement/superTypeReference") - model("refactoring/bindToElement/delegatedSuperTypeReference") - model("refactoring/bindToElement/annotationReference") - model("refactoring/bindToElement/changeImport") + model("refactoring/bindToElement") } } From c06d74f2fa40760f3fc05349f2c02539ed7a6508 Mon Sep 17 00:00:00 2001 From: Bart van Helvert Date: Mon, 31 Jul 2023 17:46:18 +0200 Subject: [PATCH 011/165] [kotlin] Add support for binding top level function calls and imports GitOrigin-RevId: 1fe45df0a90b9cfd7045175329a21cf338f84b0c --- .../importReference/ImportReference.kt | 19 +++++++++++ .../importReference/ImportReference.kt.after | 10 ++++++ .../TopLevelFunctionCall.kt | 19 +++++++++++ .../TopLevelFunctionCall.kt.after | 11 ++++++ .../refactoring/K2ReferenceMutateService.kt | 34 +++++++++++++------ 5 files changed, 82 insertions(+), 11 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt.after create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt.after diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt new file mode 100644 index 000000000000..28b03fc9813f --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt @@ -0,0 +1,19 @@ +// FILE: test/ChangeImport.kt +// BIND_TO test.bar.A +package test + +import test.foo.A + +fun foo() { + val x = A() +} + +// FILE: test/foo/A.kt +package test.foo + +class A { } + +// FILE: test/bar/A.kt +package test.bar + +class A { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt.after new file mode 100644 index 000000000000..d18d33c9a2b9 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt.after @@ -0,0 +1,10 @@ +// FILE: test/ChangeImport.kt +// BIND_TO test.bar.A +package test + +import test.bar.A + +fun foo() { + val x = A() +} + diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt new file mode 100644 index 000000000000..940c4324c341 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt @@ -0,0 +1,19 @@ +// FILE: test/TopLevelFunction.kt +// BIND_TO test.bar.fooBar +package test + +import test.foo.fooBar + +fun foo() { + fooBar() +} + +// FILE: test/foo/Test.kt +package test.foo + +fun fooBar() { } + +// FILE: test/bar/Test.kt +package test.bar + +fun fooBar() { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt.after new file mode 100644 index 000000000000..b79d7b4ae0d7 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt.after @@ -0,0 +1,11 @@ +// FILE: test/TopLevelFunction.kt +// BIND_TO test.bar.fooBar +package test + + +import test.bar.fooBar + +fun foo() { + fooBar() +} + diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt index 603c783894f9..f5ea31f0e3d7 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt @@ -73,43 +73,55 @@ internal class K2ReferenceMutateService : KtReferenceMutateServiceBase() { if (targetElement !is KtElement) operationNotSupportedInK2Error() // TODO fix reference shortener for non-Kotlin target elements val expression = simpleNameReference.expression if (fqName.isRoot) return expression + val importDirective = expression.parentOfType(withSelf = false) + if (importDirective != null) return importDirective.replaceWith(fqName) ?: expression return expression.containingKtFile.withOptimizedImports { val anchorElement = expression.parentOfType(withSelf = false) ?: expression.parentOfType(withSelf = false) + ?: expression.parent as? KtCallExpression? ?: expression when (anchorElement) { is KtUserType -> anchorElement.replaceWith(fqName) - is KtSimpleNameExpression -> anchorElement.replaceWith(fqName) is KtDotQualifiedExpression -> anchorElement.replaceWith(fqName) + is KtCallExpression -> anchorElement.replaceWith(fqName) + is KtSimpleNameExpression -> anchorElement.replaceWith(fqName) else -> null } } ?: expression } + private fun KtImportDirective.replaceWith(fqName: FqName): KtExpression? { + val newImportReferenceExpression = KtPsiFactory(project).createExpression(fqName.asString()) + return importedReference?.replaced(newImportReferenceExpression) + } + private fun KtTypeElement.replaceWith(fqName: FqName): KtTypeElement { val newReference = KtPsiFactory(project).createType(fqName.asString()).typeElement ?: error("Could not create type from $fqName") return replaced(newReference) } + private fun KtCallExpression.replaceWith(fqName: FqName): KtExpression { + val psiFactory = KtPsiFactory(project) + val newName = psiFactory.createSimpleName(fqName.shortName().asString()) + calleeExpression?.replace(newName) + val parentFqName = fqName.parent() + if (parentFqName.isRoot) return this + val packageName = fqName.parent().asString() + val newQualifiedExpression = psiFactory.createExpression("$packageName.${text}") + return replaced(newQualifiedExpression) + } + private fun KtSimpleNameExpression.replaceWith(fqName: FqName): KtExpression { val newNameExpression = KtPsiFactory(project).createExpression(fqName.asString()) return replaced(newNameExpression) } private fun KtDotQualifiedExpression.replaceWith(fqName: FqName): KtExpression? { - val psiFactory = KtPsiFactory(project) val selectorExpression = selectorExpression ?: return null val newExpression = when (selectorExpression) { - is KtNameReferenceExpression -> { - psiFactory.createExpression(fqName.asString()) - } - is KtCallExpression -> { - val newName = psiFactory.createSimpleName(fqName.shortName().asString()) - selectorExpression.calleeExpression?.replace(newName) - val packageName = fqName.parent().asString() - psiFactory.createExpression("$packageName.${selectorExpression.text}") - } + is KtSimpleNameExpression -> selectorExpression.replaceWith(fqName) + is KtCallExpression -> selectorExpression.replaceWith(fqName) else -> return null } return replaced(newExpression) From ef38e22b448048fab64d6d4359d16070351ec173 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 18 Apr 2023 14:41:38 +0200 Subject: [PATCH 012/165] [kotlin] KT-57743 Add tests for circular session creation & invalidation GitOrigin-RevId: e13b6cc962e47e21523221611421df9fba1fdff0 --- .../SessionsInvalidationTestGenerated.java | 15 +++++++++++++++ .../sessionInvalidation/cyclical/structure.json | 10 ++++++++++ .../cyclicalWithOutsideDependency/structure.json | 11 +++++++++++ .../linearWithCyclicalDependency/structure.json | 12 ++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/cyclical/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/cyclicalWithOutsideDependency/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/linearWithCyclicalDependency/structure.json diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/SessionsInvalidationTestGenerated.java b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/SessionsInvalidationTestGenerated.java index 35c579784bb2..c123c6e11567 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/SessionsInvalidationTestGenerated.java +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/SessionsInvalidationTestGenerated.java @@ -43,11 +43,26 @@ public class SessionsInvalidationTestGenerated extends AbstractSessionsInvalidat runTest("testData/sessionInvalidation/binaryTreeWithInvalidInRoot/"); } + @TestMetadata("cyclical") + public void testCyclical() throws Exception { + runTest("testData/sessionInvalidation/cyclical/"); + } + + @TestMetadata("cyclicalWithOutsideDependency") + public void testCyclicalWithOutsideDependency() throws Exception { + runTest("testData/sessionInvalidation/cyclicalWithOutsideDependency/"); + } + @TestMetadata("linear") public void testLinear() throws Exception { runTest("testData/sessionInvalidation/linear/"); } + @TestMetadata("linearWithCyclicalDependency") + public void testLinearWithCyclicalDependency() throws Exception { + runTest("testData/sessionInvalidation/linearWithCyclicalDependency/"); + } + @TestMetadata("rhombus") public void testRhombus() throws Exception { runTest("testData/sessionInvalidation/rhombus/"); diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/cyclical/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/cyclical/structure.json new file mode 100644 index 000000000000..3d89bf5bb593 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/cyclical/structure.json @@ -0,0 +1,10 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["B"] }, + { "name": "B", "dependsOn": ["C"] }, + { "name": "C", "dependsOn": ["A"] } + ], + "rootModule": "A", + "modulesToMakeOOBM": ["C"], + "expectedInvalidatedModules": ["A", "B", "C"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/cyclicalWithOutsideDependency/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/cyclicalWithOutsideDependency/structure.json new file mode 100644 index 000000000000..1297a653ad61 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/cyclicalWithOutsideDependency/structure.json @@ -0,0 +1,11 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["B"] }, + { "name": "B", "dependsOn": ["C", "O"] }, + { "name": "C", "dependsOn": ["A"] }, + { "name": "O", "dependsOn": [] } + ], + "rootModule": "A", + "modulesToMakeOOBM": ["O"], + "expectedInvalidatedModules": ["A", "B", "C", "O"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/linearWithCyclicalDependency/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/linearWithCyclicalDependency/structure.json new file mode 100644 index 000000000000..04a8f4747515 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/sessionInvalidation/linearWithCyclicalDependency/structure.json @@ -0,0 +1,12 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["B"] }, + { "name": "B", "dependsOn": ["C1"] }, + { "name": "C1", "dependsOn": ["C2"] }, + { "name": "C2", "dependsOn": ["C3"] }, + { "name": "C3", "dependsOn": ["C1"] } + ], + "rootModule": "A", + "modulesToMakeOOBM": ["B"], + "expectedInvalidatedModules": ["A", "B"] +} From f3f04eb01883ab9bc3111ea547a7da7c3ae5df26 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Fri, 21 Apr 2023 20:17:53 +0200 Subject: [PATCH 013/165] [kotlin] KT-58257 Add IDE implementation of subscription-directed invalidation API - `FirIdeOutOfBlockModificationService` is a new service of the FIR IDE implementation which raises out-of-block modification events for subscriptions and increments OOB modification trackers. - This OOBM tracking has been extended to raise modification events for script and not-under-content-root modules via a `VFS_CHANGES` file listener. - Because the new API expects module state modification to be published via events, `KotlinModuleStateTrackerProvider` has been rewritten into a `KotlinModuleStateModificationService` which publishes module state modification events. - FE10 does not subscribe to Analysis API modification events, so while `KotlinModuleStateModificationService` works out of the box because it is shared between FE10 and FIR, there is currently no implementation for FE10 module out-of-block modification publishing. GitOrigin-RevId: 64a671edac4146c9cb0a73331bfbe4800c8fd663 --- .../kotlin.base.analysis-api-providers.xml | 3 + ...> KotlinModuleStateModificationService.kt} | 180 ++++++------------ .../AbstractSingleFileModuleFileListener.kt | 49 +++++ ...otlin.base.fe10.analysis-api-providers.xml | 5 +- .../Fe10KotlinGlobalModificationService.kt | 16 ++ .../Fe10KotlinModificationTrackerFactory.kt | 22 --- ...kotlin.base.fir.analysis-api-providers.xml | 8 +- .../FirIdeKotlinGlobalModificationService.kt | 13 ++ .../FirIdeKotlinModificationTrackerFactory.kt | 36 ++-- ...deKotlinModuleStateModificationService.kt} | 9 +- .../FirIdeModificationTrackerService.kt | 72 ------- .../FirIdeOutOfBlockModificationService.kt | 91 +++++++++ ...rIdeOutOfBlockPsiTreeChangePreprocessor.kt | 4 +- .../KotlinProjectStructureUtils.kt | 9 + .../ModuleInfoProviderUtils.kt | 2 +- .../ProjectStructureProviderIdeImpl.kt | 2 +- 16 files changed, 267 insertions(+), 254 deletions(-) rename plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/{KotlinModuleStateTrackerProvider.kt => KotlinModuleStateModificationService.kt} (54%) create mode 100644 plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileListener.kt create mode 100644 plugins/kotlin/base/fe10/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fe10/analysisApiProviders/Fe10KotlinGlobalModificationService.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinGlobalModificationService.kt rename plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/{FirIdeKotlinModuleStateTrackerProvider.kt => FirIdeKotlinModuleStateModificationService.kt} (68%) delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeModificationTrackerService.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt diff --git a/plugins/kotlin/base/analysis-api-providers/resources/kotlin.base.analysis-api-providers.xml b/plugins/kotlin/base/analysis-api-providers/resources/kotlin.base.analysis-api-providers.xml index 5a7a3bed56a3..0b39310a2e6e 100644 --- a/plugins/kotlin/base/analysis-api-providers/resources/kotlin.base.analysis-api-providers.xml +++ b/plugins/kotlin/base/analysis-api-providers/resources/kotlin.base.analysis-api-providers.xml @@ -15,6 +15,9 @@ + diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateTrackerProvider.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt similarity index 54% rename from plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateTrackerProvider.kt rename to plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 61f5b83d818f..f73031adcac6 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateTrackerProvider.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -11,7 +11,6 @@ import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.StandardFileSystems -import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.newvfs.BulkFileListener import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent @@ -31,117 +30,78 @@ import com.intellij.platform.workspace.storage.EntityChange import com.intellij.platform.workspace.storage.EntityStorage import com.intellij.platform.workspace.storage.VersionedStorageChange import com.intellij.platform.workspace.storage.WorkspaceEntity -import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.analysis.project.structure.* -import org.jetbrains.kotlin.analysis.providers.KtModuleStateTracker -import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo -import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.LibraryInfo -import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.ModuleSourceInfo +import org.jetbrains.kotlin.analysis.providers.KotlinGlobalModificationService +import org.jetbrains.kotlin.analysis.providers.analysisMessageBus +import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics +import org.jetbrains.kotlin.idea.base.projectStructure.getBinaryAndSourceModuleInfos +import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.IdeaModuleInfo import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.SdkInfo -import org.jetbrains.kotlin.idea.base.util.Frontend10ApiUsage -import org.jetbrains.kotlin.parsing.KotlinParserDefinition -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.AtomicLong +import org.jetbrains.kotlin.idea.base.projectStructure.sourceModuleInfos +import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule +import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleFileListener -@OptIn(Frontend10ApiUsage::class) -open class KotlinModuleStateTrackerProvider(val project: Project) : Disposable { +open class KotlinModuleStateModificationService(val project: Project) : Disposable { init { val busConnection = project.messageBus.connect(this) busConnection.subscribe(WorkspaceModelTopics.CHANGED, ModelChangeListener()) busConnection.subscribe(ProjectJdkTable.JDK_TABLE_TOPIC, JdkListener()) - busConnection.subscribe(VirtualFileManager.VFS_CHANGES, ScriptFileListener()) + busConnection.subscribe(VirtualFileManager.VFS_CHANGES, SingleFileModuleFileListener()) busConnection.subscribe(VirtualFileManager.VFS_CHANGES, LibraryUpdatesListener()) } - private val builtinTracker = ModuleStateTrackerImpl() - private val libraryCache = ConcurrentHashMap() - private val sourceModuleCache = ConcurrentHashMap() - private val sdkCache = ConcurrentHashMap() - private val scriptCache = ConcurrentHashMap() + protected open fun mayBuiltinsHaveChanged(events: List): Boolean { return false } - protected open fun shouldInvalidateBuiltinSession(events: List): Boolean { return false } - - fun getModuleStateTrackerFor(module: KtModule): KtModuleStateTracker { - return when (module) { - is KtScriptDependencyModule -> ModuleStateTrackerImpl() + private fun invalidateSourceModule(module: Module, isRemoval: Boolean = false) { + invalidateByModuleInfos(module.sourceModuleInfos, isRemoval) + } - is KtLibraryModule -> { - val libraryInfo = module.moduleInfo as LibraryInfo - libraryInfo.checkValidity() - return libraryCache.computeIfAbsent(libraryInfo.library) { ModuleStateTrackerImpl() } - } + private fun invalidateLibraryModule(library: Library, isRemoval: Boolean = false) { + invalidateByModuleInfos(library.getBinaryAndSourceModuleInfos(project), isRemoval) + } - is KtSdkModule -> { - val sdkInfo = module.moduleInfo as SdkInfo - sdkInfo.checkValidity() - val sdk = sdkInfo.sdk - return sdkCache.computeIfAbsent(sdk) { ModuleStateTrackerImpl() } - } - - is KtSourceModule -> { - val sourceModule = module.moduleInfo as ModuleSourceInfo - sourceModule.checkValidity() - return sourceModuleCache.computeIfAbsent(sourceModule.module) { ModuleStateTrackerImpl() } - } - - is KtLibrarySourceModule -> getModuleStateTrackerFor(module.binaryLibrary) - - is KtBuiltinsModule -> builtinTracker - - is KtScriptModule -> { - val virtualFile = module.file.virtualFile ?: error("Script ${module.file} does not have a backing 'VirtualFile'") - scriptCache.computeIfAbsent(virtualFile) { ModuleStateTrackerImpl() } - } - - is KtNotUnderContentRootModule -> ModuleStateTrackerImpl() // TODO need proper cache? + private fun invalidateByModuleInfos(moduleInfos: Iterable, isRemoval: Boolean) { + moduleInfos.forEach { moduleInfo -> + project.publishModuleStateModification(moduleInfo.toKtModule(), isRemoval) } } - private inner class ScriptFileListener : BulkFileListener { - override fun after(events: List) { - for (event in events) { - val file = when (event) { - is VFileDeleteEvent -> event.file - is VFileMoveEvent -> event.file - else -> continue - } + /** + * Publishes module state modification events for script and not-under-content-root [KtModule]s. + */ + private inner class SingleFileModuleFileListener : AbstractSingleFileModuleFileListener(project) { + override fun shouldProcessEvent(event: VFileEvent): Boolean = event is VFileDeleteEvent || event is VFileMoveEvent - if (file.extension == KotlinParserDefinition.STD_SCRIPT_SUFFIX) { - scriptCache.remove(file)?.invalidate() - } - } + override fun processEvent(event: VFileEvent, module: KtModule) { + project.publishModuleStateModification(module, isRemoval = event is VFileDeleteEvent) } } private inner class LibraryUpdatesListener : BulkFileListener { val index = ProjectRootManager.getInstance(project).fileIndex + override fun after(events: List) { - if (shouldInvalidateBuiltinSession(events)) { - builtinTracker.incModificationCount() - libraryCache.values.forEach { it.incModificationCount() } - sourceModuleCache.values.forEach { it.incModificationCount() } - sdkCache.values.forEach { it.incModificationCount() } - scriptCache.values.forEach { it.incModificationCount() } + if (mayBuiltinsHaveChanged(events)) { + KotlinGlobalModificationService.getInstance(project).publishGlobalModuleStateModification() return } + events.mapNotNull { event -> val file = when (event) { - //for all other events workspace model should do the job + //for all other events workspace model should do the job is VFileContentChangeEvent -> event.file else -> return@mapNotNull null } if (file.extension != "jar") return@mapNotNull null //react only on jars val jarRoot = StandardFileSystems.jar().findFileByPath(file.path + URLUtil.JAR_SEPARATOR) ?: return@mapNotNull null (index.getOrderEntriesForFile(jarRoot).firstOrNull { it is LibraryOrderEntry } as? LibraryOrderEntry)?.library - }.distinct().forEach { - libraryCache[it]?.incModificationCount() - } + }.distinct().forEach { invalidateLibraryModule(it) } } } private inner class JdkListener : ProjectJdkTable.Listener { override fun jdkRemoved(jdk: Sdk) { - sdkCache.remove(jdk)?.invalidate() + project.publishModuleStateModification(SdkInfo(project, jdk).toKtModule(), isRemoval = true) } } @@ -154,7 +114,7 @@ open class KotlinModuleStateTrackerProvider(val project: Project) : Disposable { private fun handleContentRootInModuleChanges(event: VersionedStorageChange) { for (changedModule in event.getChangedModules()) { - sourceModuleCache[changedModule]?.incModificationCount() + invalidateSourceModule(changedModule) } } @@ -192,14 +152,14 @@ open class KotlinModuleStateTrackerProvider(val project: Project) : Disposable { when (change) { is EntityChange.Added -> {} is EntityChange.Removed -> { - change.oldEntity.findLibraryBridge(event.storageBefore)?.let { library -> - libraryCache.remove(library)?.invalidate() - } + change.oldEntity + .findLibraryBridge(event.storageBefore) + ?.let { invalidateLibraryModule(it, isRemoval = true) } } is EntityChange.Replaced -> { val changedLibrary = change.getReplacedEntity(event, LibraryEntity::findLibraryBridge) ?: continue - libraryCache[changedLibrary]?.incModificationCount() + invalidateLibraryModule(changedLibrary) } } } @@ -212,67 +172,39 @@ open class KotlinModuleStateTrackerProvider(val project: Project) : Disposable { is EntityChange.Added -> {} is EntityChange.Removed -> { change.oldEntity.findModule(event.storageBefore)?.let { module -> - sourceModuleCache.remove(module)?.invalidate() + invalidateSourceModule(module, isRemoval = true) } } is EntityChange.Replaced -> { val changedModule = change.getReplacedEntity(event, ModuleEntity::findModule) ?: continue - sourceModuleCache[changedModule]?.incModificationCount() + invalidateSourceModule(changedModule) } } } } } - private fun EntityChange.Replaced.getReplacedEntity( - event: VersionedStorageChange, - get: (C, EntityStorage) -> E - ): E { - val old = get(oldEntity, event.storageBefore) - val new = get(newEntity, event.storageAfter) - check(old == new) { - "$old should be equal to $new for ${EntityChange.Replaced::class.java}" - } - return new - } - - @TestOnly - fun incrementModificationCountForAllModules(includeBinaryModules: Boolean) { - sourceModuleCache.forEach { _, tracker -> tracker.incModificationCount() } - if (includeBinaryModules) { - libraryCache.forEach { _, tracker -> tracker.incModificationCount() } - sdkCache.forEach { _, tracker -> tracker.incModificationCount() } - } - } - override fun dispose() {} companion object { - fun getInstance(project: Project): KotlinModuleStateTrackerProvider = - project.getService(KotlinModuleStateTrackerProvider::class.java) + fun getInstance(project: Project): KotlinModuleStateModificationService = + project.getService(KotlinModuleStateModificationService::class.java) } - } -class ModuleStateTrackerImpl : KtModuleStateTracker { - private val modificationCount = AtomicLong() - - @Volatile - override var isValid: Boolean = true - private set - - fun incModificationCount() { - if (isValid) { - modificationCount.incrementAndGet() - } +private fun EntityChange.Replaced.getReplacedEntity( + event: VersionedStorageChange, + get: (C, EntityStorage) -> E +): E { + val old = get(oldEntity, event.storageBefore) + val new = get(newEntity, event.storageAfter) + check(old == new) { + "$old should be equal to $new for ${EntityChange.Replaced::class.java}" } + return new +} - fun invalidate() { - incModificationCount() - isValid = false - } - - override val rootModificationCount: Long - get() = modificationCount.get() -} \ No newline at end of file +private fun Project.publishModuleStateModification(module: KtModule, isRemoval: Boolean) { + analysisMessageBus.syncPublisher(KotlinTopics.MODULE_STATE_MODIFICATION).afterModification(module, isRemoval) +} diff --git a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileListener.kt b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileListener.kt new file mode 100644 index 000000000000..a7e0350aabe4 --- /dev/null +++ b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileListener.kt @@ -0,0 +1,49 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.util + +import com.intellij.openapi.module.ModuleUtilCore +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.newvfs.BulkFileListener +import com.intellij.openapi.vfs.newvfs.events.VFileEvent +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.KtNotUnderContentRootModule +import org.jetbrains.kotlin.analysis.project.structure.KtScriptDependencyModule +import org.jetbrains.kotlin.analysis.project.structure.KtScriptModule +import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider +import org.jetbrains.kotlin.idea.core.util.toPsiFile +import org.jetbrains.kotlin.parsing.KotlinParserDefinition + +/** + * [AbstractSingleFileModuleFileListener] listens to file events and calls [processEvent] with the [KtModule] associated with the script or + * not-under-content-root file of an event. An event is only processed if it passes [shouldProcessEvent]. + */ +abstract class AbstractSingleFileModuleFileListener(private val project: Project) : BulkFileListener { + protected abstract fun shouldProcessEvent(event: VFileEvent): Boolean + + protected abstract fun processEvent(event: VFileEvent, module: KtModule) + + override fun after(events: List) { + for (event in events) { + if (!shouldProcessEvent(event)) continue + val file = event.file ?: continue + + if (file.mayBeFromSingleFileModule()) { + val module = + file.toPsiFile(project)?.let { ProjectStructureProvider.getModule(project, it, contextualModule = null) } ?: continue + + if (module is KtScriptModule || module is KtScriptDependencyModule || module is KtNotUnderContentRootModule) { + processEvent(event, module) + } + } + } + } + + /** + * The file is a script if its extension is `.kts`. Alternatively, the file can only belong to a not-under-content-root `KtModule` if it + * has no module associated with it. + */ + private fun VirtualFile.mayBeFromSingleFileModule(): Boolean = + extension == KotlinParserDefinition.STD_SCRIPT_SUFFIX || + isKotlinFileType() && ModuleUtilCore.findModuleForFile(this, project) == null +} diff --git a/plugins/kotlin/base/fe10/analysis-api-providers/resources/kotlin.base.fe10.analysis-api-providers.xml b/plugins/kotlin/base/fe10/analysis-api-providers/resources/kotlin.base.fe10.analysis-api-providers.xml index 8e5d7f8e1137..c8771683844d 100644 --- a/plugins/kotlin/base/fe10/analysis-api-providers/resources/kotlin.base.fe10.analysis-api-providers.xml +++ b/plugins/kotlin/base/fe10/analysis-api-providers/resources/kotlin.base.fe10.analysis-api-providers.xml @@ -5,7 +5,10 @@ serviceInterface="org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory" serviceImplementation="org.jetbrains.kotlin.idea.base.fe10.analysisApiProviders.Fe10KotlinModificationTrackerFactory"/> + serviceImplementation="org.jetbrains.kotlin.idea.base.analysisApiProviders.KotlinModuleStateModificationService"/> + diff --git a/plugins/kotlin/base/fe10/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fe10/analysisApiProviders/Fe10KotlinGlobalModificationService.kt b/plugins/kotlin/base/fe10/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fe10/analysisApiProviders/Fe10KotlinGlobalModificationService.kt new file mode 100644 index 000000000000..1a79e278899b --- /dev/null +++ b/plugins/kotlin/base/fe10/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fe10/analysisApiProviders/Fe10KotlinGlobalModificationService.kt @@ -0,0 +1,16 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.base.fe10.analysisApiProviders + +import com.intellij.openapi.project.Project +import org.jetbrains.annotations.TestOnly +import org.jetbrains.kotlin.analysis.providers.impl.KotlinGlobalModificationServiceBase +import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener +import org.jetbrains.kotlin.idea.caches.trackers.KotlinModuleOutOfCodeBlockModificationTracker + +internal class Fe10KotlinGlobalModificationService(private val project: Project) : KotlinGlobalModificationServiceBase(project) { + @TestOnly + override fun incrementModificationTrackers(includeBinaryTrackers: Boolean) { + KotlinCodeBlockModificationListener.getInstance(project).incModificationCount() + KotlinModuleOutOfCodeBlockModificationTracker.incrementModificationCountForAllModules(project) + } +} diff --git a/plugins/kotlin/base/fe10/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fe10/analysisApiProviders/Fe10KotlinModificationTrackerFactory.kt b/plugins/kotlin/base/fe10/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fe10/analysisApiProviders/Fe10KotlinModificationTrackerFactory.kt index 21182bceb18b..4db137359b53 100644 --- a/plugins/kotlin/base/fe10/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fe10/analysisApiProviders/Fe10KotlinModificationTrackerFactory.kt +++ b/plugins/kotlin/base/fe10/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fe10/analysisApiProviders/Fe10KotlinModificationTrackerFactory.kt @@ -4,37 +4,15 @@ package org.jetbrains.kotlin.idea.base.fe10.analysisApiProviders import com.intellij.java.library.JavaLibraryModificationTracker import com.intellij.openapi.project.Project import com.intellij.openapi.util.ModificationTracker -import org.jetbrains.annotations.TestOnly -import org.jetbrains.kotlin.analysis.project.structure.KtModule -import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory -import org.jetbrains.kotlin.analysis.providers.KtModuleStateTracker -import org.jetbrains.kotlin.idea.base.analysisApiProviders.KotlinModuleStateTrackerProvider -import org.jetbrains.kotlin.idea.base.projectStructure.ideaModule import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener -import org.jetbrains.kotlin.idea.caches.trackers.KotlinModuleOutOfCodeBlockModificationTracker internal class Fe10KotlinModificationTrackerFactory(private val project: Project) : KotlinModificationTrackerFactory() { override fun createProjectWideOutOfBlockModificationTracker(): ModificationTracker { return KotlinCodeBlockModificationListener.getInstance(project).kotlinOutOfCodeBlockTracker } - override fun createModuleWithoutDependenciesOutOfBlockModificationTracker(module: KtSourceModule): ModificationTracker { - return KotlinModuleOutOfCodeBlockModificationTracker(module.ideaModule) - } - override fun createLibrariesWideModificationTracker(): ModificationTracker { return JavaLibraryModificationTracker.getInstance(project) } - - override fun createModuleStateTracker(module: KtModule): KtModuleStateTracker { - return KotlinModuleStateTrackerProvider.getInstance(project).getModuleStateTrackerFor(module) - } - - @TestOnly - override fun incrementModificationsCount(includeBinaryTrackers: Boolean) { - KotlinCodeBlockModificationListener.getInstance(project).incModificationCount() - KotlinModuleOutOfCodeBlockModificationTracker.incrementModificationCountForAllModules(project) - KotlinModuleStateTrackerProvider.getInstance(project).incrementModificationCountForAllModules(includeBinaryTrackers) - } } \ No newline at end of file diff --git a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml index f9c2b4012ee2..69706fb47b2b 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml +++ b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml @@ -4,10 +4,12 @@ - + serviceInterface="org.jetbrains.kotlin.idea.base.analysisApiProviders.KotlinModuleStateModificationService" + serviceImplementation="org.jetbrains.kotlin.idea.base.fir.analysisApiProviders.FirIdeKotlinModuleStateModificationService"/> + diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinGlobalModificationService.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinGlobalModificationService.kt new file mode 100644 index 000000000000..48d609285056 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinGlobalModificationService.kt @@ -0,0 +1,13 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.base.fir.analysisApiProviders + +import com.intellij.openapi.project.Project +import org.jetbrains.annotations.TestOnly +import org.jetbrains.kotlin.analysis.providers.impl.KotlinGlobalModificationServiceBase + +internal class FirIdeKotlinGlobalModificationService(private val project: Project) : KotlinGlobalModificationServiceBase(project) { + @TestOnly + override fun incrementModificationTrackers(includeBinaryTrackers: Boolean) { + FirIdeKotlinModificationTrackerFactory.getInstance(project).incrementModificationsCount(includeBinaryTrackers) + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModificationTrackerFactory.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModificationTrackerFactory.kt index c0259af91d5f..6331d6c3891e 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModificationTrackerFactory.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModificationTrackerFactory.kt @@ -5,39 +5,29 @@ import com.intellij.java.library.JavaLibraryModificationTracker import com.intellij.openapi.project.Project import com.intellij.openapi.util.ModificationTracker import org.jetbrains.annotations.TestOnly -import org.jetbrains.kotlin.analysis.project.structure.KtModule -import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory -import org.jetbrains.kotlin.analysis.providers.KtModuleStateTracker -import org.jetbrains.kotlin.idea.base.analysisApiProviders.KotlinModuleStateTrackerProvider -import org.jetbrains.kotlin.idea.base.projectStructure.ideaModule internal class FirIdeKotlinModificationTrackerFactory(private val project: Project) : KotlinModificationTrackerFactory() { - private val modificationTrackerService = project.getService(FirIdeModificationTrackerService::class.java) + private val projectOutOfBlockModificationTracker + get() = FirIdeOutOfBlockModificationService.getInstance(project).projectOutOfBlockModificationTracker - override fun createProjectWideOutOfBlockModificationTracker(): ModificationTracker = - modificationTrackerService.projectOutOfBlockModificationTracker + private val libraryModificationTracker + get() = JavaLibraryModificationTracker.getInstance(project) as JavaLibraryModificationTracker - override fun createModuleWithoutDependenciesOutOfBlockModificationTracker(module: KtSourceModule): ModificationTracker = - modificationTrackerService.getModuleOutOfBlockModificationTracker(module.ideaModule) + override fun createProjectWideOutOfBlockModificationTracker(): ModificationTracker = projectOutOfBlockModificationTracker - override fun createLibrariesWideModificationTracker(): ModificationTracker { - return JavaLibraryModificationTracker.getInstance(project) - } - - override fun createModuleStateTracker(module: KtModule): KtModuleStateTracker { - return KotlinModuleStateTrackerProvider.getInstance(project).getModuleStateTrackerFor(module) - } + override fun createLibrariesWideModificationTracker(): ModificationTracker = libraryModificationTracker @TestOnly - override fun incrementModificationsCount(includeBinaryTrackers: Boolean) { + internal fun incrementModificationsCount(includeBinaryTrackers: Boolean) { + projectOutOfBlockModificationTracker.incModificationCount() if (includeBinaryTrackers) { - (createLibrariesWideModificationTracker() as JavaLibraryModificationTracker).incModificationCount() + libraryModificationTracker.incModificationCount() } + } - // `FirIdeModificationTrackerService` is for source modules only. - modificationTrackerService.increaseModificationCountForAllModules() - - KotlinModuleStateTrackerProvider.getInstance(project).incrementModificationCountForAllModules(includeBinaryTrackers) + companion object { + fun getInstance(project: Project): FirIdeKotlinModificationTrackerFactory = + KotlinModificationTrackerFactory.getInstance(project) as FirIdeKotlinModificationTrackerFactory } } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModuleStateTrackerProvider.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModuleStateModificationService.kt similarity index 68% rename from plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModuleStateTrackerProvider.kt rename to plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModuleStateModificationService.kt index c8269ee0f08a..5465e46dcc67 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModuleStateTrackerProvider.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModuleStateModificationService.kt @@ -4,16 +4,15 @@ package org.jetbrains.kotlin.idea.base.fir.analysisApiProviders import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent import com.intellij.openapi.vfs.newvfs.events.VFileEvent +import org.jetbrains.kotlin.idea.base.analysisApiProviders.KotlinModuleStateModificationService import java.util.regex.Pattern -import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsSessionFactory -import org.jetbrains.kotlin.idea.base.analysisApiProviders.KotlinModuleStateTrackerProvider private val STDLIB_PATTERN = Pattern.compile("kotlin-stdlib-(\\d*)\\.(\\d*)\\.(\\d*)\\.jar") -class FirIdeKotlinModuleStateTrackerProvider(project: Project) : KotlinModuleStateTrackerProvider(project) { - override fun shouldInvalidateBuiltinSession(events: List): Boolean { +class FirIdeKotlinModuleStateModificationService(project: Project) : KotlinModuleStateModificationService(project) { + override fun mayBuiltinsHaveChanged(events: List): Boolean { return events.find { event -> event is VFileContentChangeEvent && STDLIB_PATTERN.matcher(event.file.name).matches() } != null } -} \ No newline at end of file +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeModificationTrackerService.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeModificationTrackerService.kt deleted file mode 100644 index d0c456ddea30..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeModificationTrackerService.kt +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. - -package org.jetbrains.kotlin.idea.base.fir.analysisApiProviders - -import com.intellij.openapi.Disposable -import com.intellij.openapi.module.Module -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.ModificationTracker -import com.intellij.openapi.util.SimpleModificationTracker -import org.jetbrains.kotlin.analysis.api.fir.utils.createCompositeModificationTracker -import java.util.concurrent.ConcurrentHashMap - -internal class FirIdeModificationTrackerService(val project : Project) : Disposable { - /** - * A project-wide out-of-block modification tracker for Kotlin sources. The modification count of this tracker will be incremented on - * global PSI tree changes or for test purposes. - */ - val projectOutOfBlockModificationTracker: SimpleModificationTracker = SimpleModificationTracker() - - /** - * A module modification tracker is used by dependents which want to depend on *specific* module changes. This modification tracker for - * *all* modules gives us the option to force such an update for all source modules. - * - * That functionality is distinct from [projectOutOfBlockModificationTracker], because a dependent will explicitly use a project OOB - * tracker if it wants to depend on *any* OOB modification in the project. - */ - private val allModulesOutOfBlockModificationTracker: SimpleModificationTracker = SimpleModificationTracker() - - private val moduleOutOfBlockModificationTrackerWrappers = ConcurrentHashMap() - - fun getModuleOutOfBlockModificationTracker(module: Module): ModificationTracker = - getModuleOutOfBlockModificationTrackerWrapper(module).compositeModificationTracker - - private fun getModuleOutOfBlockModificationTrackerWrapper(module: Module): ModuleOutOfBlockModificationTrackerWrapper = - moduleOutOfBlockModificationTrackerWrappers.computeIfAbsent(module) { - ModuleOutOfBlockModificationTrackerWrapper( - allModulesOutOfBlockModificationTracker, - SimpleModificationTracker(), - ) - } - - override fun dispose() {} - - fun increaseModificationCountForAllModules() { - projectOutOfBlockModificationTracker.incModificationCount() - allModulesOutOfBlockModificationTracker.incModificationCount() - } - - fun increaseModificationCountForModule(module: Module) { - getModuleOutOfBlockModificationTrackerWrapper(module).moduleModificationTracker.incModificationCount() - } - - fun increaseModificationCountForModuleAndProject(module: Module?) { - if (module != null) { - increaseModificationCountForModule(module) - } - projectOutOfBlockModificationTracker.incModificationCount() - } -} - -/** - * The module's out-of-block modification tracker is a _composite_ modification tracker because it is made up of both the specific module's - * tracker and the tracker for _all_ modules. Should these trackers be flattened into another composite modification tracker, the - * "all modules" modification tracker will only be contained once in the resulting modification tracker, because modification trackers are - * flattened uniquely by identity and there must only be a single instance of the "all modules" modification tracker per project. - */ -internal class ModuleOutOfBlockModificationTrackerWrapper( - allModulesModificationTracker: ModificationTracker, - val moduleModificationTracker: SimpleModificationTracker, -) { - val compositeModificationTracker = listOf(allModulesModificationTracker, moduleModificationTracker).createCompositeModificationTracker() -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt new file mode 100644 index 000000000000..5682b21ba36c --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt @@ -0,0 +1,91 @@ +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + +package org.jetbrains.kotlin.idea.base.fir.analysisApiProviders + +import com.intellij.openapi.Disposable +import com.intellij.openapi.components.Service +import com.intellij.openapi.module.Module +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.SimpleModificationTracker +import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent +import com.intellij.openapi.vfs.newvfs.events.VFileEvent +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.providers.analysisMessageBus +import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleOutOfBlockModificationListener +import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics +import org.jetbrains.kotlin.idea.base.projectStructure.sourceModuleInfos +import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule +import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleFileListener + +/** + * [FirIdeOutOfBlockModificationService] increments modification trackers and publishes subscription events on out-of-block modification + * after PSI tree changes and for tests. + */ +@Service(Service.Level.PROJECT) +internal class FirIdeOutOfBlockModificationService(val project: Project) : Disposable { + /** + * A project-wide out-of-block modification tracker for Kotlin sources which will be incremented on global PSI tree changes, on any + * module out-of-block modification, and by tests. + */ + val projectOutOfBlockModificationTracker: SimpleModificationTracker = SimpleModificationTracker() + + init { + val busConnection = project.messageBus.connect(this) + busConnection.subscribe(VirtualFileManager.VFS_CHANGES, SingleFileModuleFileListener(project)) + } + + override fun dispose() {} + + /** + * Publishes out-of-block modification for [module]'s [KtModule]s. + */ + fun publishModuleOnlyOutOfBlockModification(module: Module) { + module.sourceModuleInfos.forEach { + project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).afterModification(it.toKtModule()) + } + } + + /** + * Publishes out-of-block modification for [module]'s [KtModule]s and the project itself. + * + * [publishModuleAndProjectOutOfBlockModification] cannot be used for single file-based [KtModule]s (such as scripts), because they + * don't have an associated IntelliJ [Module]. + */ + fun publishModuleAndProjectOutOfBlockModification(module: Module?) { + if (module != null) { + publishModuleOnlyOutOfBlockModification(module) + } + projectOutOfBlockModificationTracker.incModificationCount() + } + + fun publishGlobalOutOfBlockModification() { + projectOutOfBlockModificationTracker.incModificationCount() + + // We should not invalidate binary module content here, because global PSI tree changes have no effect on binary modules. + project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_SOURCE_OUT_OF_BLOCK_MODIFICATION).afterModification() + } + + companion object { + fun getInstance(project: Project): FirIdeOutOfBlockModificationService = + project.getService(FirIdeOutOfBlockModificationService::class.java) + } +} + +/** + * An [AbstractSingleFileModuleFileListener] that publishes out-of-block modification events for the associated [KtModule]s. + * + * Any file modification triggers an out-of-block modification event, not just actual out-of-block modifications, which is allowed per the + * contract of [KotlinModuleOutOfBlockModificationListener]. + * + * Because Kotlin script and not-under-content-root files aren't associated with a [Module], + * [FirIdeOutOfBlockModificationService.publishModuleAndProjectOutOfBlockModification] cannot be used to publish out-of-block modification + * events for such [KtModule]s, hence the existence of this listener. + */ +private class SingleFileModuleFileListener(private val project: Project) : AbstractSingleFileModuleFileListener(project) { + override fun shouldProcessEvent(event: VFileEvent): Boolean = event is VFileContentChangeEvent + + override fun processEvent(event: VFileEvent, module: KtModule) { + project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).afterModification(module) + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt index 9e3b52adc5cb..544e147d03f6 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt @@ -27,7 +27,7 @@ internal class FirIdeOutOfBlockPsiTreeChangePreprocessor(private val project: Pr } if (event.isGlobalChange()) { - project.getService(FirIdeModificationTrackerService::class.java).increaseModificationCountForAllModules() + FirIdeOutOfBlockModificationService.getInstance(project).publishGlobalOutOfBlockModification() return } @@ -63,7 +63,7 @@ internal class FirIdeOutOfBlockPsiTreeChangePreprocessor(private val project: Pr } private fun outOfBlockInvalidation(element: PsiElement) { - project.getService(FirIdeModificationTrackerService::class.java).increaseModificationCountForModuleAndProject(element.module) + FirIdeOutOfBlockModificationService.getInstance(project).publishModuleAndProjectOutOfBlockModification(element.module) } private fun calculateChangeType( diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/KotlinProjectStructureUtils.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/KotlinProjectStructureUtils.kt index f0b2a340afe2..9a65c3cfe52b 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/KotlinProjectStructureUtils.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/KotlinProjectStructureUtils.kt @@ -12,6 +12,8 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.project.rootManager import com.intellij.openapi.roots.FileIndex import com.intellij.openapi.roots.ProjectFileIndex +import com.intellij.openapi.roots.impl.libraries.LibraryEx +import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.util.Key import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.JavaPsiFacade @@ -94,6 +96,13 @@ private fun Module.hasRootsOfType(rootTypes: Set>): B return rootManager.contentEntries.any { it.getSourceFolders(rootTypes).isNotEmpty() } } +fun Library.getBinaryAndSourceModuleInfos(project: Project): List = buildList { + LibraryInfoCache.getInstance(project)[this@getBinaryAndSourceModuleInfos].forEach { libraryInfo -> + add(libraryInfo) + add(libraryInfo.sourcesModuleInfo) + } +} + /** * [forcedModuleInfo] provides a [ModuleInfo] instance for a dummy file. It must not be changed after the first assignment because * [ModuleInfoProvider] might cache the module info. diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProviderUtils.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProviderUtils.kt index e60870aa431c..a01569f331e9 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProviderUtils.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProviderUtils.kt @@ -34,7 +34,7 @@ private fun cachedModuleInfo(psiFile: PsiFile): IdeaModuleInfo? = CachedValuesMa ModuleInfoProvider.getInstance(project).firstOrNull(psiFile), ProjectRootModificationTracker.getInstance(project), JavaLibraryModificationTracker.getInstance(project), - KotlinModificationTrackerFactory.getService(project).createProjectWideOutOfBlockModificationTracker(), + KotlinModificationTrackerFactory.getInstance(project).createProjectWideOutOfBlockModificationTracker(), ) } diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectStructureProviderIdeImpl.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectStructureProviderIdeImpl.kt index 848a83d6a62f..81d11c62f8b3 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectStructureProviderIdeImpl.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectStructureProviderIdeImpl.kt @@ -67,7 +67,7 @@ private fun cachedKtModule(psiFile: PsiFile): KtModule = CachedValuesManager.get calculateKtModule(psiFile), ProjectRootModificationTracker.getInstance(project), JavaLibraryModificationTracker.getInstance(project), - KotlinModificationTrackerFactory.getService(project).createProjectWideOutOfBlockModificationTracker(), + KotlinModificationTrackerFactory.getInstance(project).createProjectWideOutOfBlockModificationTracker(), ) } From 5cfdc33e343622c8c621dd7adfd65bc3583f01ea Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 2 May 2023 19:00:41 +0200 Subject: [PATCH 014/165] [kotlin] KT-58257 Register project listeners for `KotlinModuleStateModificationService` via XML plugin configuration - The `init` block was never executed, as the service isn't requested anymore, because it doesn't provide modification trackers anymore. Hence, listeners weren't registered with the message bus. - Registering listeners via the XML plugin configuration does not require the service to be requested first. GitOrigin-RevId: 9e29a2e221b584d88b7c8590d45e861041687942 --- .../KotlinModuleStateModificationService.kt | 36 ++++++++----------- ...kotlin.base.fir.analysis-api-providers.xml | 11 ++++++ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index f73031adcac6..4f0452ad2f14 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -11,7 +11,6 @@ import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.StandardFileSystems -import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.newvfs.BulkFileListener import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent @@ -23,7 +22,6 @@ import com.intellij.platform.workspace.jps.entities.ModuleEntity import com.intellij.platform.workspace.jps.entities.SourceRootEntity import com.intellij.util.io.URLUtil import com.intellij.platform.backend.workspace.WorkspaceModelChangeListener -import com.intellij.platform.backend.workspace.WorkspaceModelTopics import com.intellij.workspaceModel.ide.impl.legacyBridge.library.findLibraryBridge import com.intellij.workspaceModel.ide.impl.legacyBridge.module.findModule import com.intellij.platform.workspace.storage.EntityChange @@ -42,14 +40,6 @@ import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleFileListener open class KotlinModuleStateModificationService(val project: Project) : Disposable { - init { - val busConnection = project.messageBus.connect(this) - busConnection.subscribe(WorkspaceModelTopics.CHANGED, ModelChangeListener()) - busConnection.subscribe(ProjectJdkTable.JDK_TABLE_TOPIC, JdkListener()) - busConnection.subscribe(VirtualFileManager.VFS_CHANGES, SingleFileModuleFileListener()) - busConnection.subscribe(VirtualFileManager.VFS_CHANGES, LibraryUpdatesListener()) - } - protected open fun mayBuiltinsHaveChanged(events: List): Boolean { return false } private fun invalidateSourceModule(module: Module, isRemoval: Boolean = false) { @@ -69,7 +59,7 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab /** * Publishes module state modification events for script and not-under-content-root [KtModule]s. */ - private inner class SingleFileModuleFileListener : AbstractSingleFileModuleFileListener(project) { + class SingleFileModuleFileListener(private val project: Project) : AbstractSingleFileModuleFileListener(project) { override fun shouldProcessEvent(event: VFileEvent): Boolean = event is VFileDeleteEvent || event is VFileMoveEvent override fun processEvent(event: VFileEvent, module: KtModule) { @@ -77,11 +67,13 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab } } - private inner class LibraryUpdatesListener : BulkFileListener { + class LibraryUpdatesListener(private val project: Project) : BulkFileListener { val index = ProjectRootManager.getInstance(project).fileIndex + private val moduleStateModificationService: KotlinModuleStateModificationService get() = getInstance(project) + override fun after(events: List) { - if (mayBuiltinsHaveChanged(events)) { + if (moduleStateModificationService.mayBuiltinsHaveChanged(events)) { KotlinGlobalModificationService.getInstance(project).publishGlobalModuleStateModification() return } @@ -95,17 +87,19 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab if (file.extension != "jar") return@mapNotNull null //react only on jars val jarRoot = StandardFileSystems.jar().findFileByPath(file.path + URLUtil.JAR_SEPARATOR) ?: return@mapNotNull null (index.getOrderEntriesForFile(jarRoot).firstOrNull { it is LibraryOrderEntry } as? LibraryOrderEntry)?.library - }.distinct().forEach { invalidateLibraryModule(it) } + }.distinct().forEach { moduleStateModificationService.invalidateLibraryModule(it) } } } - private inner class JdkListener : ProjectJdkTable.Listener { + class JdkListener(private val project: Project) : ProjectJdkTable.Listener { override fun jdkRemoved(jdk: Sdk) { project.publishModuleStateModification(SdkInfo(project, jdk).toKtModule(), isRemoval = true) } } - private inner class ModelChangeListener : WorkspaceModelChangeListener { + class ModelChangeListener(private val project: Project) : WorkspaceModelChangeListener { + private val moduleStateModificationService: KotlinModuleStateModificationService get() = getInstance(project) + override fun beforeChanged(event: VersionedStorageChange) { handleLibraryChanges(event) handleModuleChanges(event) @@ -114,7 +108,7 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab private fun handleContentRootInModuleChanges(event: VersionedStorageChange) { for (changedModule in event.getChangedModules()) { - invalidateSourceModule(changedModule) + moduleStateModificationService.invalidateSourceModule(changedModule) } } @@ -154,12 +148,12 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab is EntityChange.Removed -> { change.oldEntity .findLibraryBridge(event.storageBefore) - ?.let { invalidateLibraryModule(it, isRemoval = true) } + ?.let { moduleStateModificationService.invalidateLibraryModule(it, isRemoval = true) } } is EntityChange.Replaced -> { val changedLibrary = change.getReplacedEntity(event, LibraryEntity::findLibraryBridge) ?: continue - invalidateLibraryModule(changedLibrary) + moduleStateModificationService.invalidateLibraryModule(changedLibrary) } } } @@ -172,13 +166,13 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab is EntityChange.Added -> {} is EntityChange.Removed -> { change.oldEntity.findModule(event.storageBefore)?.let { module -> - invalidateSourceModule(module, isRemoval = true) + moduleStateModificationService.invalidateSourceModule(module, isRemoval = true) } } is EntityChange.Replaced -> { val changedModule = change.getReplacedEntity(event, ModuleEntity::findModule) ?: continue - invalidateSourceModule(changedModule) + moduleStateModificationService.invalidateSourceModule(changedModule) } } } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml index 69706fb47b2b..a1db54ae9816 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml +++ b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml @@ -14,6 +14,17 @@ implementation="org.jetbrains.kotlin.idea.base.fir.analysisApiProviders.FirIdeOutOfBlockPsiTreeChangePreprocessor"/> + + + + + + + From e898fe5dc93d6304aa1d6fd61936758d77ac6605 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 3 May 2023 18:58:13 +0200 Subject: [PATCH 015/165] [kotlin] KT-58257 Rewrite global invalidation in tests to use `KotlinGlobalModificationService` - `KtAnalysisSessionProvider` caches do not need to be cleared, because the `KtAnalysisSession` will depend as a cached value on `LLFirSession`, which is cleared by global source module state modification. GitOrigin-RevId: a304337a5115be9275276fac9e59b669c02d3324 --- .../test/org/jetbrains/kotlin/idea/fir/testUtils.kt | 10 ++++------ .../performancePlugin/commands/ClearSourceCaches.java | 6 ++---- .../test/org/jetbrains/fir/uast/test/uastTestUtils.kt | 9 +++++---- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/testUtils.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/testUtils.kt index 0e8cdb88159c..ac13ea6335fb 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/testUtils.kt +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/testUtils.kt @@ -2,23 +2,21 @@ package org.jetbrains.kotlin.idea.fir -import com.intellij.java.library.JavaLibraryModificationTracker import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.openapi.util.io.FileUtil import com.intellij.testFramework.LightPlatformTestCase import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals -import org.jetbrains.kotlin.analysis.api.session.KtAnalysisSessionProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsSessionFactory -import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory import java.io.File +import org.jetbrains.kotlin.analysis.providers.KotlinGlobalModificationService @OptIn(KtAnalysisApiInternals::class) fun Project.invalidateCaches() { - JavaLibraryModificationTracker.incModificationCount(this) - service().incrementModificationsCount() - service().clearCaches() + runWriteAction { + KotlinGlobalModificationService.getInstance(this).publishGlobalModuleStateModification() + } service().clearForTheNextTest() } diff --git a/plugins/kotlin/kotlin.performanceExtendedPlugin/src/com/intellij/performance/performancePlugin/commands/ClearSourceCaches.java b/plugins/kotlin/kotlin.performanceExtendedPlugin/src/com/intellij/performance/performancePlugin/commands/ClearSourceCaches.java index a4f8e3eb9d91..5c3a5aaa7d3b 100644 --- a/plugins/kotlin/kotlin.performanceExtendedPlugin/src/com/intellij/performance/performancePlugin/commands/ClearSourceCaches.java +++ b/plugins/kotlin/kotlin.performanceExtendedPlugin/src/com/intellij/performance/performancePlugin/commands/ClearSourceCaches.java @@ -11,8 +11,7 @@ import com.jetbrains.performancePlugin.utils.ActionCallbackProfilerStopper; import org.jetbrains.annotations.NotNull; import org.jetbrains.concurrency.Promise; import org.jetbrains.concurrency.Promises; -import org.jetbrains.kotlin.analysis.api.session.KtAnalysisSessionProvider; -import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory; +import org.jetbrains.kotlin.analysis.providers.KotlinGlobalModificationService; import org.jetbrains.kotlin.idea.caches.trackers.KotlinIDEModificationTrackerService; public class ClearSourceCaches extends AbstractCommand { @@ -32,8 +31,7 @@ public class ClearSourceCaches extends AbstractCommand { PsiManager.getInstance(project).dropPsiCaches(); KotlinIDEModificationTrackerService.Companion.invalidateCaches(project); if (System.getProperty("idea.kotlin.plugin.use.k2", "false").equals("true")) { - KtAnalysisSessionProvider.Companion.getInstance(project).clearCaches(); - project.getService(KotlinModificationTrackerFactory.class).incrementModificationsCount(false); + KotlinGlobalModificationService.Companion.getInstance(project).publishGlobalSourceModuleStateModification(); } actionCallback.setDone(); }); diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/uastTestUtils.kt b/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/uastTestUtils.kt index 6d6ba8faf698..b118dc8e8738 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/uastTestUtils.kt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/uastTestUtils.kt @@ -2,16 +2,17 @@ package org.jetbrains.fir.uast.test +import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals -import org.jetbrains.kotlin.analysis.api.session.KtAnalysisSessionProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsSessionFactory -import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory +import org.jetbrains.kotlin.analysis.providers.KotlinGlobalModificationService @OptIn(KtAnalysisApiInternals::class) internal fun Project.invalidateAllCachesForUastTests() { - service().incrementModificationsCount() - service().clearCaches() + runWriteAction { + KotlinGlobalModificationService.getInstance(this).publishGlobalModuleStateModification() + } service().clearForTheNextTest() } \ No newline at end of file From 0e96948a170f71480820c3f5d56586c745473e86 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 3 May 2023 19:03:16 +0200 Subject: [PATCH 016/165] [kotlin] KT-58257 Use `FirIdeOutOfBlockModificationService` in `fir/analysis-api-providers` tests GitOrigin-RevId: 2af66bed796ea1e1052b9afbb7c717d12982c6f6 --- .../providers/sessions/AbstractSessionsInvalidationTest.kt | 4 ++-- .../kotlin/idea/fir/analysis/providers/testUtils.kt | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt index 89b7a3b868ee..9d7c7a1c0997 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectModule import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructure import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructureReader -import org.jetbrains.kotlin.idea.fir.analysis.providers.incModificationTracker +import org.jetbrains.kotlin.idea.fir.analysis.providers.publishOutOfBlockModification import org.jetbrains.kotlin.idea.jsonUtils.getString import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest import org.jetbrains.kotlin.idea.base.test.KotlinRoot @@ -54,7 +54,7 @@ abstract class AbstractSessionsInvalidationTest : AbstractMultiModuleTest() { val sessionsBeforeOOBM = getAllModuleSessions(rootModule) val modulesToMakeOOBM = testStructure.modulesToMakeOOBM.map(modulesByNames::getValue) - modulesToMakeOOBM.forEach { it.incModificationTracker() } + modulesToMakeOOBM.forEach { it.publishOutOfBlockModification() } val sessionsAfterOOBM = getAllModuleSessions(rootModule) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt index e09510b52a6b..1a0e990530b2 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt @@ -2,10 +2,9 @@ package org.jetbrains.kotlin.idea.fir.analysis.providers -import com.intellij.openapi.components.service import com.intellij.openapi.module.Module -import org.jetbrains.kotlin.idea.base.fir.analysisApiProviders.FirIdeModificationTrackerService +import org.jetbrains.kotlin.idea.base.fir.analysisApiProviders.FirIdeOutOfBlockModificationService -internal fun Module.incModificationTracker() { - project.service().increaseModificationCountForModule(this) +internal fun Module.publishOutOfBlockModification() { + FirIdeOutOfBlockModificationService.getInstance(project).publishModuleOnlyOutOfBlockModification(this) } \ No newline at end of file From d34ded500716291a6c808bcc3074d1e90795a06a Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Mon, 22 May 2023 18:34:54 +0200 Subject: [PATCH 017/165] [kotlin] KT-58257 Publish global module state modification event on SDK removal - The IDE implementation of `KotlinModuleDependentsProvider` cannot easily find all dependents for an SDK. Instead, SDK removal can be handled via global module state modification events, because most modules will depend on the SDK. GitOrigin-RevId: 7d6715b2c8e15fece224a9bf10db64e2491822e7 --- .../KotlinModuleStateModificationService.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 4f0452ad2f14..1ff5e5fd8af4 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -93,7 +93,10 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab class JdkListener(private val project: Project) : ProjectJdkTable.Listener { override fun jdkRemoved(jdk: Sdk) { - project.publishModuleStateModification(SdkInfo(project, jdk).toKtModule(), isRemoval = true) + // Most modules will depend on an SDK, so its removal constitutes global module state modification. We cannot be more + // fine-grained here because `KtSdkModules`s aren't supported by `IdeKotlinModuleDependentsProvider`, so invalidation based on + // a module-level modification event may not work as expected with a `KtSdkModule`. + KotlinGlobalModificationService.getInstance(project).publishGlobalModuleStateModification() } } From c574674b9c8f8265aad80f170083aa400012b882 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Mon, 22 May 2023 21:39:28 +0200 Subject: [PATCH 018/165] [kotlin] KT-58257 Implement `IdeKotlinModuleDependentsProvider` - `IdeKotlinModuleDependentsProvider` is using the workspace model because it knows about all modules and libraries. This is crucial to be able to return a complete list of `KtModule` dependents. - For now, direct and transitive dependents will remain uncached. We can optimize this separately if the performance is not acceptable. GitOrigin-RevId: 41eebb82d87ad0ff8b0db5d25ae7813e56c2902c --- .../IdeKotlinModuleDependentsProvider.kt | 53 +++++++++++++++++++ .../ProjectModuleByModuleInfo.kt | 7 +++ .../common/resources/META-INF/kotlin-core.xml | 3 ++ 3 files changed, 63 insertions(+) create mode 100644 plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt new file mode 100644 index 000000000000..305eea7d0b50 --- /dev/null +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt @@ -0,0 +1,53 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.base.projectStructure + +import com.intellij.openapi.project.Project +import com.intellij.workspaceModel.ide.WorkspaceModel +import com.intellij.workspaceModel.ide.impl.legacyBridge.module.findModule +import com.intellij.workspaceModel.storage.bridgeEntities.LibraryId +import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity +import com.intellij.workspaceModel.storage.bridgeEntities.ModuleId +import org.jetbrains.kotlin.analysis.project.structure.KtBuiltinsModule +import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.KtScriptDependencyModule +import org.jetbrains.kotlin.analysis.project.structure.KtScriptModule +import org.jetbrains.kotlin.analysis.project.structure.KtSdkModule +import org.jetbrains.kotlin.analysis.project.structure.impl.KotlinModuleDependentsProviderBase +import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments + +/** + * [IdeKotlinModuleDependentsProvider] provides [KtModule] dependents by querying the workspace model. + */ +internal class IdeKotlinModuleDependentsProvider(private val project: Project) : KotlinModuleDependentsProviderBase() { + override fun getDirectDependents(module: KtModule): Set { + val symbolicId = when (module) { + is KtSourceModuleByModuleInfo -> module.moduleId + is KtLibraryModuleByModuleInfo -> module.libraryId ?: return emptySet() + is KtLibrarySourceModuleByModuleInfo -> return getDirectDependents(module.binaryLibrary) + + // No dependents need to be provided for `KtSdkModule` and `KtBuiltinsModule` (see `KotlinModuleDependentsProvider`). + is KtSdkModule -> return emptySet() + is KtBuiltinsModule -> return emptySet() + + // Script modules are not supported yet (see KTIJ-25620). + is KtScriptModule, is KtScriptDependencyModule -> return emptySet() + + is NotUnderContentRootModuleByModuleInfo -> return emptySet() + + else -> throw KotlinExceptionWithAttachments("Unexpected ${KtModule::class.simpleName}").withAttachment("module.txt", module) + } + + val snapshot = WorkspaceModel.getInstance(project).currentSnapshot + return snapshot + .referrers(symbolicId, ModuleEntity::class.java) + .flatMapTo(mutableSetOf()) { moduleEntity -> + // The set of dependents should not include `module` itself. + if (moduleEntity.symbolicId == symbolicId) return@flatMapTo emptyList() + + // We can skip the module entity if `findModule` returns `null` because the module won't have been added to the project + // model yet and thus cannot be a proper `KtModule`. + moduleEntity.findModule(snapshot)?.sourceModuleInfos?.map { it.toKtModule() } ?: emptyList() + } + } +} diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectModuleByModuleInfo.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectModuleByModuleInfo.kt index d89c685158c1..515c004a0ca9 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectModuleByModuleInfo.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectModuleByModuleInfo.kt @@ -7,12 +7,15 @@ import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.ProjectRootModificationTracker import com.intellij.openapi.util.Key import com.intellij.openapi.vfs.VirtualFile +import com.intellij.platform.workspace.jps.entities.LibraryId +import com.intellij.platform.workspace.jps.entities.ModuleId import com.intellij.psi.PsiFile import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScopes import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager +import com.intellij.workspaceModel.ide.impl.legacyBridge.library.LibraryBridge import org.jetbrains.annotations.ApiStatus import org.jetbrains.kotlin.analysis.project.structure.* import org.jetbrains.kotlin.analyzer.ModuleInfo @@ -71,6 +74,8 @@ open class KtSourceModuleByModuleInfo(private val moduleInfo: ModuleSourceInfo) override val stableModuleName: String? get() = moduleInfo.stableName?.asString() + val moduleId: ModuleId get() = ModuleId(moduleName) + override val directRegularDependencies: List get() = moduleInfo.collectDependencies(ModuleDependencyCollector.CollectionMode.COLLECT_NON_IGNORED) @@ -158,6 +163,8 @@ internal class KtLibraryModuleByModuleInfo(private val moduleInfo: LibraryInfo) override val libraryName: String get() = moduleInfo.library.name ?: "Unnamed library" + val libraryId: LibraryId? get() = (moduleInfo.library as? LibraryBridge)?.libraryId + override val librarySources: KtLibrarySourceModule get() = moduleInfo.sourcesModuleInfo.toKtModuleOfType() diff --git a/plugins/kotlin/plugin/common/resources/META-INF/kotlin-core.xml b/plugins/kotlin/plugin/common/resources/META-INF/kotlin-core.xml index 446b908c7980..a50f642f7c71 100644 --- a/plugins/kotlin/plugin/common/resources/META-INF/kotlin-core.xml +++ b/plugins/kotlin/plugin/common/resources/META-INF/kotlin-core.xml @@ -84,6 +84,9 @@ + From bef3a2ee0b70091eb868948a71237e3ab1c63274 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Mon, 22 May 2023 21:45:17 +0200 Subject: [PATCH 019/165] [kotlin] Extract `AbstractProjectStructureTest` from `AbstractSessionsInvalidationTest` - `AbstractSessionsInvalidationTest` is only one of many possible tests that operate on a project structure defined via JSON. It makes sense to extract the test project structure handling into `AbstractProjectStructureTest`. GitOrigin-RevId: 606a40b718a384c8d8f8bc58f12f590baf53b27b --- .../providers/AbstractProjectStructureTest.kt | 45 +++++++++++ .../providers/TestProjectStructure.kt | 43 +++++------ .../AbstractSessionsInvalidationTest.kt | 74 ++++++------------- 3 files changed, 88 insertions(+), 74 deletions(-) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt new file mode 100644 index 000000000000..1132d6672ca9 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt @@ -0,0 +1,45 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers + +import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.module.Module +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.testFramework.PsiTestUtil +import java.nio.file.Paths +import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest + +typealias ModulesByNames = Map + +abstract class AbstractProjectStructureTest : AbstractMultiModuleTest() { + protected fun initializeProjectStructure(path: String, parser: TestProjectStructureParser): Pair { + val testStructure = TestProjectStructureReader.readToTestStructure( + Paths.get(path), + testProjectStructureParser = parser, + ) + + val modulesByNames = testStructure.modules.associate { moduleData -> + moduleData.name to createEmptyModule(moduleData.name) + } + + testStructure.modules.forEach { moduleData -> + val module = modulesByNames.getValue(moduleData.name) + moduleData.dependsOnModules.forEach { dependencyName -> + module.addDependency(modulesByNames.getValue(dependencyName)) + } + } + + return Pair(testStructure, modulesByNames) + } + + private fun createEmptyModule(name: String): Module { + val tmpDir = createTempDirectory().toPath() + val module: Module = createModule("$tmpDir/$name", moduleType) + val root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tmpDir.toFile())!! + WriteCommandAction.writeCommandAction(module.project).run { + root.refresh(false, true) + } + + PsiTestUtil.addSourceContentToRoots(module, root) + return module + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/TestProjectStructure.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/TestProjectStructure.kt index 9b73d569c74f..4ab5e04b2f47 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/TestProjectStructure.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/TestProjectStructure.kt @@ -10,23 +10,10 @@ import com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.idea.jsonUtils.getString import java.nio.file.Path -internal data class TestProjectStructure( - val modules: List, - val json: JsonObject, -) { - companion object { - fun parse(json: JsonElement): TestProjectStructure { - require(json is JsonObject) - - return TestProjectStructure( - json.getAsJsonArray("modules").map(TestProjectModule.Companion::parse), - json, - ) - } - } +interface TestProjectStructure { + val modules: List } - data class TestProjectModule(val name: String, val dependsOnModules: List) { companion object { fun parse(json: JsonElement): TestProjectModule { @@ -45,16 +32,30 @@ data class TestProjectModule(val name: String, val dependsOnModules: List read( + testDirectory: Path, + jsonFileName: String = "structure.json", + parser: TestProjectStructureParser, + ): S { val jsonFile = testDirectory.resolve(jsonFileName) val json = JsonParser.parseString(FileUtil.loadFile(jsonFile.toFile(), /*convertLineSeparators=*/true)) - return TestProjectStructure.parse(json) + require(json is JsonObject) + + val modules = json.getAsJsonArray("modules").map(TestProjectModule.Companion::parse) + return parser.parse(modules, json) } - fun readToTestStructure( + fun readToTestStructure( testDirectory: Path, jsonFileName: String = "structure.json", - toTestStructure: (TestProjectStructure) -> T, - ): T = read(testDirectory, jsonFileName).let(toTestStructure) -} \ No newline at end of file + testProjectStructureParser: TestProjectStructureParser, + ): S = read(testDirectory, jsonFileName, testProjectStructureParser) +} + +fun interface TestProjectStructureParser { + /** + * Parses a [TestProjectStructure] from an already parsed list of [TestProjectModule]s and the original [JsonObject]. + */ + fun parse(modules: List, json: JsonObject): S +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt index 9d7c7a1c0997..c46d030940b9 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt @@ -2,11 +2,9 @@ package org.jetbrains.kotlin.idea.fir.analysis.providers.sessions -import com.intellij.openapi.command.WriteCommandAction +import com.google.gson.JsonObject import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager -import com.intellij.openapi.vfs.LocalFileSystem -import com.intellij.testFramework.PsiTestUtil import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionService import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirModuleSession import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession @@ -17,36 +15,21 @@ import org.jetbrains.kotlin.idea.base.projectStructure.sourceModuleInfos import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectModule import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructure -import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructureReader import org.jetbrains.kotlin.idea.fir.analysis.providers.publishOutOfBlockModification import org.jetbrains.kotlin.idea.jsonUtils.getString -import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest import org.jetbrains.kotlin.idea.base.test.KotlinRoot import java.io.File -import java.nio.file.Paths +import org.jetbrains.kotlin.idea.fir.analysis.providers.AbstractProjectStructureTest +import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructureParser -abstract class AbstractSessionsInvalidationTest : AbstractMultiModuleTest() { +abstract class AbstractSessionsInvalidationTest : AbstractProjectStructureTest() { override fun isFirPlugin(): Boolean = true override fun getTestDataDirectory(): File = - KotlinRoot.DIR.resolve("fir-low-level-api-ide-impl").resolve("testData").resolve("sessionInvalidation") + KotlinRoot.DIR.resolve("base").resolve("fir").resolve("analysis-api-providers").resolve("testData").resolve("sessionInvalidation") protected fun doTest(path: String) { - val testStructure = TestProjectStructureReader.readToTestStructure( - Paths.get(path), - toTestStructure = MultiModuleTestProjectStructure.Companion::fromTestProjectStructure - ) - - val modulesByNames = testStructure.modules.associate { moduleData -> - moduleData.name to createEmptyModule(moduleData.name) - } - - testStructure.modules.forEach { moduleData -> - val module = modulesByNames.getValue(moduleData.name) - moduleData.dependsOnModules.forEach { dependencyName -> - module.addDependency(modulesByNames.getValue(dependencyName)) - } - } + val (testStructure, modulesByNames) = initializeProjectStructure(path, SessionInvalidationTestProjectStructureParser) val rootIdeaModule = modulesByNames.getValue(testStructure.rootModule) val rootModule = rootIdeaModule.getMainKtSourceModule()!! @@ -84,40 +67,25 @@ abstract class AbstractSessionsInvalidationTest : AbstractMultiModuleTest() { val resolveSession = LLFirResolveSessionService.getInstance(project).getFirResolveSession(mainModule) return projectModules.map(resolveSession::getSessionFor) } - - private fun createEmptyModule(name: String): Module { - val tmpDir = createTempDirectory().toPath() - val module: Module = createModule("$tmpDir/$name", moduleType) - val root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tmpDir.toFile())!! - WriteCommandAction.writeCommandAction(module.project).run { - root.refresh(false, true) - } - - PsiTestUtil.addSourceContentToRoots(module, root) - return module - } } -private data class MultiModuleTestProjectStructure( - val modules: List, +data class SessionInvalidationTestProjectStructure( + override val modules: List, val rootModule: String, val modulesToMakeOOBM: List, val expectedInvalidatedModules: List, -) { - companion object { - fun fromTestProjectStructure(testProjectStructure: TestProjectStructure): MultiModuleTestProjectStructure { - val json = testProjectStructure.json +) : TestProjectStructure - return MultiModuleTestProjectStructure( - testProjectStructure.modules, - json.getString(ROOT_MODULE_FIELD), - json.getAsJsonArray(MODULES_TO_MAKE_OOBM_IN_FIELD).map { it.asString }.sorted(), - json.getAsJsonArray(EXPECTED_INVALIDATED_MODULES_FIELD).map { it.asString }.sorted(), - ) - } +private object SessionInvalidationTestProjectStructureParser : TestProjectStructureParser { + private const val ROOT_MODULE_FIELD = "rootModule" + private const val MODULES_TO_MAKE_OOBM_IN_FIELD = "modulesToMakeOOBM" + private const val EXPECTED_INVALIDATED_MODULES_FIELD = "expectedInvalidatedModules" - private const val ROOT_MODULE_FIELD = "rootModule" - private const val MODULES_TO_MAKE_OOBM_IN_FIELD = "modulesToMakeOOBM" - private const val EXPECTED_INVALIDATED_MODULES_FIELD = "expectedInvalidatedModules" - } -} \ No newline at end of file + override fun parse(modules: List, json: JsonObject): SessionInvalidationTestProjectStructure = + SessionInvalidationTestProjectStructure( + modules, + json.getString(ROOT_MODULE_FIELD), + json.getAsJsonArray(MODULES_TO_MAKE_OOBM_IN_FIELD)!!.map { it.asString }.sorted(), + json.getAsJsonArray(EXPECTED_INVALIDATED_MODULES_FIELD)!!.map { it.asString }.sorted(), + ) +} From 578f5121f63dc6cd9f94e76ca523df0b00e9c45f Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Mon, 22 May 2023 22:27:48 +0200 Subject: [PATCH 020/165] [kotlin] KT-58257 Add tests for `IdeKotlinModuleDependentsProvider` GitOrigin-RevId: b9a8e9e0d58c38b143432517dd5b3f47ec852b9e --- .../AbstractModuleDependentsTest.kt | 61 +++++++++++++++++++ .../ModuleDependentsTestGenerated.java | 55 +++++++++++++++++ .../binaryTree/structure.json | 14 +++++ .../moduleDependents/cyclical/structure.json | 10 +++ .../cyclicalSelf/structure.json | 9 +++ .../structure.json | 11 ++++ .../moduleDependents/linear/structure.json | 12 ++++ .../moduleDependents/rhombus/structure.json | 11 ++++ .../fir/testGenerator/FirGenerateTests.kt | 5 ++ 9 files changed, 188 insertions(+) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt new file mode 100644 index 000000000000..3275171def40 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt @@ -0,0 +1,61 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.dependents + +import com.google.gson.JsonObject +import java.io.File +import org.jetbrains.kotlin.analysis.project.structure.KotlinModuleDependentsProvider +import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule +import org.jetbrains.kotlin.idea.base.projectStructure.getMainKtSourceModule +import org.jetbrains.kotlin.idea.base.test.KotlinRoot +import org.jetbrains.kotlin.idea.fir.analysis.providers.AbstractProjectStructureTest +import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectModule +import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructure +import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructureParser +import org.jetbrains.kotlin.idea.jsonUtils.getString + +abstract class AbstractModuleDependentsTest : AbstractProjectStructureTest() { + override fun isFirPlugin(): Boolean = true + + override fun getTestDataDirectory(): File = + KotlinRoot.DIR.resolve("base").resolve("fir").resolve("analysis-api-providers").resolve("testData").resolve("moduleDependents") + + protected fun doTest(path: String) { + val (testStructure, modulesByNames) = initializeProjectStructure(path, ModuleDependentsTestProjectStructureParser) + + val module = modulesByNames.getValue(testStructure.module).getMainKtSourceModule()!! + val moduleDependentsProvider = KotlinModuleDependentsProvider.getInstance(project) + + val directDependents = moduleDependentsProvider.getDirectDependents(module) + assertEquals( + testStructure.directDependents, + directDependents.map { (it as KtSourceModule).moduleName }.toSet(), + ) + + val transitiveDependents = moduleDependentsProvider.getTransitiveDependents(module) + assertEquals( + testStructure.transitiveDependents, + transitiveDependents.map { (it as KtSourceModule).moduleName }.toSet(), + ) + } +} + +data class ModuleDependentsTestProjectStructure( + override val modules: List, + val module: String, + val directDependents: Set, + val transitiveDependents: Set, +) : TestProjectStructure + +private object ModuleDependentsTestProjectStructureParser : TestProjectStructureParser { + private const val MODULE_FIELD = "module" + private const val DIRECT_DEPENDENTS_FIELD = "directDependents" + private const val TRANSITIVE_DEPENDENTS_FIELD = "transitiveDependents" + + override fun parse(modules: List, json: JsonObject): ModuleDependentsTestProjectStructure = + ModuleDependentsTestProjectStructure( + modules, + json.getString(MODULE_FIELD), + json.getAsJsonArray(DIRECT_DEPENDENTS_FIELD)!!.map { it.asString }.toSet(), + json.getAsJsonArray(TRANSITIVE_DEPENDENTS_FIELD)!!.map { it.asString }.toSet(), + ) +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java new file mode 100644 index 000000000000..1ee2560c2400 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java @@ -0,0 +1,55 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + +package org.jetbrains.kotlin.idea.fir.analysis.providers.dependents; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.idea.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.idea.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.jetbrains.kotlin.idea.base.test.TestRoot; +import org.junit.runner.RunWith; + +/** + * This class is generated by {@link org.jetbrains.kotlin.testGenerator.generator.TestGenerator}. + * DO NOT MODIFY MANUALLY. + */ +@SuppressWarnings("all") +@TestRoot("base/fir/analysis-api-providers") +@TestDataPath("$CONTENT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +@TestMetadata("testData/moduleDependents") +public class ModuleDependentsTestGenerated extends AbstractModuleDependentsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("binaryTree") + public void testBinaryTree() throws Exception { + runTest("testData/moduleDependents/binaryTree/"); + } + + @TestMetadata("cyclical") + public void testCyclical() throws Exception { + runTest("testData/moduleDependents/cyclical/"); + } + + @TestMetadata("cyclicalSelf") + public void testCyclicalSelf() throws Exception { + runTest("testData/moduleDependents/cyclicalSelf/"); + } + + @TestMetadata("cyclicalWithOutsideDependency") + public void testCyclicalWithOutsideDependency() throws Exception { + runTest("testData/moduleDependents/cyclicalWithOutsideDependency/"); + } + + @TestMetadata("linear") + public void testLinear() throws Exception { + runTest("testData/moduleDependents/linear/"); + } + + @TestMetadata("rhombus") + public void testRhombus() throws Exception { + runTest("testData/moduleDependents/rhombus/"); + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json new file mode 100644 index 000000000000..fdf4b497f067 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json @@ -0,0 +1,14 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["B", "C"] }, + { "name": "B", "dependsOn": ["D", "E"] }, + { "name": "C", "dependsOn": ["F", "G"] }, + { "name": "D", "dependsOn": [] }, + { "name": "E", "dependsOn": [] }, + { "name": "F", "dependsOn": [] }, + { "name": "G", "dependsOn": [] } + ], + "module": "F", + "directDependents": ["C"], + "transitiveDependents": ["C", "A"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json new file mode 100644 index 000000000000..5c63a69c941a --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json @@ -0,0 +1,10 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["B"] }, + { "name": "B", "dependsOn": ["C"] }, + { "name": "C", "dependsOn": ["A"] } + ], + "module": "A", + "directDependents": ["C"], + "transitiveDependents": ["B", "C"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json new file mode 100644 index 000000000000..6c832cebee73 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json @@ -0,0 +1,9 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["A"] }, + { "name": "B", "dependsOn": ["A"] } + ], + "module": "A", + "directDependents": ["B"], + "transitiveDependents": ["B"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json new file mode 100644 index 000000000000..4ff8c6961315 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json @@ -0,0 +1,11 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["B"] }, + { "name": "B", "dependsOn": ["C", "O"] }, + { "name": "C", "dependsOn": ["A"] }, + { "name": "O", "dependsOn": [] } + ], + "module": "O", + "directDependents": ["B"], + "transitiveDependents": ["A", "B", "C"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json new file mode 100644 index 000000000000..fce6777c73a0 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json @@ -0,0 +1,12 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["B"] }, + { "name": "B", "dependsOn": ["C"] }, + { "name": "C", "dependsOn": ["D"] }, + { "name": "D", "dependsOn": ["E"] }, + { "name": "E", "dependsOn": [] } + ], + "module": "E", + "directDependents": ["D"], + "transitiveDependents": ["A", "B", "C", "D"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json new file mode 100644 index 000000000000..70a440e4d646 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json @@ -0,0 +1,11 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["B", "C"] }, + { "name": "B", "dependsOn": ["D"] }, + { "name": "C", "dependsOn": ["D"] }, + { "name": "D", "dependsOn": [] } + ], + "module": "D", + "directDependents": ["B", "C"], + "transitiveDependents": ["A", "B", "C"] +} diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt index 324a05ed0371..d5858963d7ee 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt @@ -6,6 +6,7 @@ import org.jetbrains.fir.uast.test.* import org.jetbrains.kotlin.fir.testGenerator.codeinsight.generateK2CodeInsightTests import org.jetbrains.kotlin.idea.fir.actions.AbstractK2AddImportActionTest import org.jetbrains.kotlin.idea.fir.analysis.providers.AbstractIdeKotlinAnnotationsResolverTest +import org.jetbrains.kotlin.idea.fir.analysis.providers.dependents.AbstractModuleDependentsTest import org.jetbrains.kotlin.idea.fir.analysis.providers.sessions.AbstractSessionsInvalidationTest import org.jetbrains.kotlin.idea.fir.analysis.providers.trackers.AbstractProjectWideOutOfBlockKotlinModificationTrackerTest import org.jetbrains.kotlin.idea.fir.codeInsight.AbstractK2MultiModuleLineMarkerTest @@ -80,6 +81,10 @@ private fun assembleWorkspace(): TWorkspace = workspace { testClass { model("annotationsResolver", pattern = KT_WITHOUT_DOTS) } + + testClass { + model("moduleDependents", pattern = DIRECTORY, isRecursive = false) + } } testGroup("compiler-plugins/parcelize/tests/k2", testDataPath = "../testData") { From a4b5ed542b2cfb744cd7fef4f85d2949fb8ab7a1 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 23 May 2023 14:11:35 +0200 Subject: [PATCH 021/165] [kotlin] Add library support to `AbstractProjectStructureTest` - Library support in `AbstractProjectStructureTest` allows us to test how libraries affect module dependents and session invalidation. - Libraries can now be added via the `libraries` JSON attribute. The attribute is optional. - `TestProjectEntityReference` can be used to refer to a library or module, for example to specify a target for the module dependents test. GitOrigin-RevId: f92669b830b840c534beaade4d213b9511f6ad60 --- .../providers/AbstractProjectStructureTest.kt | 27 +++++- .../providers/TestProjectStructure.kt | 61 ------------- .../AbstractModuleDependentsTest.kt | 47 +++++++--- .../ModuleDependentsTestGenerated.java | 85 +++++++++++++------ .../AbstractSessionsInvalidationTest.kt | 12 ++- .../TestProjectEntityReference.kt | 30 +++++++ .../TestProjectStructure.kt | 49 +++++++++++ .../TestProjectStructureReader.kt | 35 ++++++++ .../kotlin/idea/test/ConfigLibraryUtil.kt | 13 ++- 9 files changed, 251 insertions(+), 108 deletions(-) delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/TestProjectStructure.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectEntityReference.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructureReader.kt diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt index 1132d6672ca9..4daeccedd8b2 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt @@ -3,34 +3,55 @@ package org.jetbrains.kotlin.idea.fir.analysis.providers import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.testFramework.PsiTestUtil import java.nio.file.Paths +import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.TestProjectStructureReader import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest +import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil +import org.jetbrains.kotlin.test.util.addDependency +typealias ProjectLibrariesByNames = Map typealias ModulesByNames = Map abstract class AbstractProjectStructureTest : AbstractMultiModuleTest() { - protected fun initializeProjectStructure(path: String, parser: TestProjectStructureParser): Pair { + protected fun initializeProjectStructure( + path: String, + parser: TestProjectStructureParser, + ): Triple { val testStructure = TestProjectStructureReader.readToTestStructure( Paths.get(path), testProjectStructureParser = parser, ) + val projectLibrariesByNames = testStructure.libraries.associate { libraryData -> + libraryData.name to createEmptyProjectLibrary(libraryData.name) + } + val modulesByNames = testStructure.modules.associate { moduleData -> moduleData.name to createEmptyModule(moduleData.name) } + val duplicateNames = projectLibrariesByNames.keys.intersect(modulesByNames.keys) + if (duplicateNames.isNotEmpty()) { + error("Test project libraries and modules may not share names. Duplicate names: ${duplicateNames.joinToString()}.") + } + testStructure.modules.forEach { moduleData -> val module = modulesByNames.getValue(moduleData.name) moduleData.dependsOnModules.forEach { dependencyName -> - module.addDependency(modulesByNames.getValue(dependencyName)) + projectLibrariesByNames[dependencyName] + ?.let { library -> module.addDependency(library) } + ?: module.addDependency(modulesByNames.getValue(dependencyName)) } } - return Pair(testStructure, modulesByNames) + return Triple(testStructure, projectLibrariesByNames, modulesByNames) } + private fun createEmptyProjectLibrary(name: String): Library = ConfigLibraryUtil.addProjectLibrary(project, name) { } + private fun createEmptyModule(name: String): Module { val tmpDir = createTempDirectory().toPath() val module: Module = createModule("$tmpDir/$name", moduleType) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/TestProjectStructure.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/TestProjectStructure.kt deleted file mode 100644 index 4ab5e04b2f47..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/TestProjectStructure.kt +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - -package org.jetbrains.kotlin.idea.fir.analysis.providers - -import com.google.gson.JsonElement -import com.google.gson.JsonObject -import com.google.gson.JsonParser -import com.google.gson.JsonPrimitive -import com.intellij.openapi.util.io.FileUtil -import org.jetbrains.kotlin.idea.jsonUtils.getString -import java.nio.file.Path - -interface TestProjectStructure { - val modules: List -} - -data class TestProjectModule(val name: String, val dependsOnModules: List) { - companion object { - fun parse(json: JsonElement): TestProjectModule { - require(json is JsonObject) - val dependencies = if (json.has(DEPENDS_ON_FIELD)) { - json.getAsJsonArray(DEPENDS_ON_FIELD).map { (it as JsonPrimitive).asString } - } else emptyList() - return TestProjectModule( - json.getString("name"), - dependencies - ) - } - - private const val DEPENDS_ON_FIELD = "dependsOn" - } -} - -internal object TestProjectStructureReader { - fun read( - testDirectory: Path, - jsonFileName: String = "structure.json", - parser: TestProjectStructureParser, - ): S { - val jsonFile = testDirectory.resolve(jsonFileName) - - val json = JsonParser.parseString(FileUtil.loadFile(jsonFile.toFile(), /*convertLineSeparators=*/true)) - require(json is JsonObject) - - val modules = json.getAsJsonArray("modules").map(TestProjectModule.Companion::parse) - return parser.parse(modules, json) - } - - fun readToTestStructure( - testDirectory: Path, - jsonFileName: String = "structure.json", - testProjectStructureParser: TestProjectStructureParser, - ): S = read(testDirectory, jsonFileName, testProjectStructureParser) -} - -fun interface TestProjectStructureParser { - /** - * Parses a [TestProjectStructure] from an already parsed list of [TestProjectModule]s and the original [JsonObject]. - */ - fun parse(modules: List, json: JsonObject): S -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt index 3275171def40..b97125a0e103 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt @@ -5,13 +5,19 @@ import com.google.gson.JsonObject import java.io.File import org.jetbrains.kotlin.analysis.project.structure.KotlinModuleDependentsProvider import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule +import org.jetbrains.kotlin.idea.base.projectStructure.LibraryInfoCache import org.jetbrains.kotlin.idea.base.projectStructure.getMainKtSourceModule +import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule import org.jetbrains.kotlin.idea.base.test.KotlinRoot import org.jetbrains.kotlin.idea.fir.analysis.providers.AbstractProjectStructureTest +import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectLibrary import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectModule import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructure import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructureParser -import org.jetbrains.kotlin.idea.jsonUtils.getString +import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.TestProjectEntityReference +import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.TestProjectEntityReferenceParser +import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.TestProjectLibraryReference +import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.TestProjectModuleReference abstract class AbstractModuleDependentsTest : AbstractProjectStructureTest() { override fun isFirPlugin(): Boolean = true @@ -20,18 +26,26 @@ abstract class AbstractModuleDependentsTest : AbstractProjectStructureTest + LibraryInfoCache.getInstance(project)[projectLibrariesByName.getValue(target.name)].first().toKtModule() + + is TestProjectModuleReference -> + modulesByNames.getValue(target.name).getMainKtSourceModule()!! + } - val module = modulesByNames.getValue(testStructure.module).getMainKtSourceModule()!! val moduleDependentsProvider = KotlinModuleDependentsProvider.getInstance(project) - val directDependents = moduleDependentsProvider.getDirectDependents(module) + val directDependents = moduleDependentsProvider.getDirectDependents(targetModule) assertEquals( testStructure.directDependents, directDependents.map { (it as KtSourceModule).moduleName }.toSet(), ) - val transitiveDependents = moduleDependentsProvider.getTransitiveDependents(module) + val transitiveDependents = moduleDependentsProvider.getTransitiveDependents(targetModule) assertEquals( testStructure.transitiveDependents, transitiveDependents.map { (it as KtSourceModule).moduleName }.toSet(), @@ -40,22 +54,27 @@ abstract class AbstractModuleDependentsTest : AbstractProjectStructureTest, override val modules: List, - val module: String, + val target: TestProjectEntityReference, val directDependents: Set, val transitiveDependents: Set, ) : TestProjectStructure private object ModuleDependentsTestProjectStructureParser : TestProjectStructureParser { - private const val MODULE_FIELD = "module" + private const val TARGET_FIELD = "target" private const val DIRECT_DEPENDENTS_FIELD = "directDependents" private const val TRANSITIVE_DEPENDENTS_FIELD = "transitiveDependents" - override fun parse(modules: List, json: JsonObject): ModuleDependentsTestProjectStructure = - ModuleDependentsTestProjectStructure( - modules, - json.getString(MODULE_FIELD), - json.getAsJsonArray(DIRECT_DEPENDENTS_FIELD)!!.map { it.asString }.toSet(), - json.getAsJsonArray(TRANSITIVE_DEPENDENTS_FIELD)!!.map { it.asString }.toSet(), - ) + override fun parse( + libraries: List, + modules: List, + json: JsonObject, + ): ModuleDependentsTestProjectStructure = ModuleDependentsTestProjectStructure( + libraries, + modules, + json.getAsJsonObject(TARGET_FIELD).let(TestProjectEntityReferenceParser::parse), + json.getAsJsonArray(DIRECT_DEPENDENTS_FIELD)!!.map { it.asString }.toSet(), + json.getAsJsonArray(TRANSITIVE_DEPENDENTS_FIELD)!!.map { it.asString }.toSet(), + ) } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java index 1ee2560c2400..0c4d6b80263c 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java @@ -17,39 +17,70 @@ import org.junit.runner.RunWith; @TestRoot("base/fir/analysis-api-providers") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -@TestMetadata("testData/moduleDependents") -public class ModuleDependentsTestGenerated extends AbstractModuleDependentsTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); +public abstract class ModuleDependentsTestGenerated extends AbstractModuleDependentsTest { + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("testData/moduleDependents/libraryTargets") + public static class LibraryTargets extends AbstractModuleDependentsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("cyclical") + public void testCyclical() throws Exception { + runTest("testData/moduleDependents/libraryTargets/cyclical/"); + } + + @TestMetadata("rhombus") + public void testRhombus() throws Exception { + runTest("testData/moduleDependents/libraryTargets/rhombus/"); + } + + @TestMetadata("rhombus2") + public void testRhombus2() throws Exception { + runTest("testData/moduleDependents/libraryTargets/rhombus2/"); + } + + @TestMetadata("singleRoot") + public void testSingleRoot() throws Exception { + runTest("testData/moduleDependents/libraryTargets/singleRoot/"); + } } - @TestMetadata("binaryTree") - public void testBinaryTree() throws Exception { - runTest("testData/moduleDependents/binaryTree/"); - } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("testData/moduleDependents/moduleTargets") + public static class ModuleTargets extends AbstractModuleDependentsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } - @TestMetadata("cyclical") - public void testCyclical() throws Exception { - runTest("testData/moduleDependents/cyclical/"); - } + @TestMetadata("binaryTree") + public void testBinaryTree() throws Exception { + runTest("testData/moduleDependents/moduleTargets/binaryTree/"); + } - @TestMetadata("cyclicalSelf") - public void testCyclicalSelf() throws Exception { - runTest("testData/moduleDependents/cyclicalSelf/"); - } + @TestMetadata("cyclical") + public void testCyclical() throws Exception { + runTest("testData/moduleDependents/moduleTargets/cyclical/"); + } - @TestMetadata("cyclicalWithOutsideDependency") - public void testCyclicalWithOutsideDependency() throws Exception { - runTest("testData/moduleDependents/cyclicalWithOutsideDependency/"); - } + @TestMetadata("cyclicalSelf") + public void testCyclicalSelf() throws Exception { + runTest("testData/moduleDependents/moduleTargets/cyclicalSelf/"); + } - @TestMetadata("linear") - public void testLinear() throws Exception { - runTest("testData/moduleDependents/linear/"); - } + @TestMetadata("cyclicalWithOutsideDependency") + public void testCyclicalWithOutsideDependency() throws Exception { + runTest("testData/moduleDependents/moduleTargets/cyclicalWithOutsideDependency/"); + } - @TestMetadata("rhombus") - public void testRhombus() throws Exception { - runTest("testData/moduleDependents/rhombus/"); + @TestMetadata("linear") + public void testLinear() throws Exception { + runTest("testData/moduleDependents/moduleTargets/linear/"); + } + + @TestMetadata("rhombus") + public void testRhombus() throws Exception { + runTest("testData/moduleDependents/moduleTargets/rhombus/"); + } } } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt index c46d030940b9..a2c2e84d1e8e 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/AbstractSessionsInvalidationTest.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.idea.jsonUtils.getString import org.jetbrains.kotlin.idea.base.test.KotlinRoot import java.io.File import org.jetbrains.kotlin.idea.fir.analysis.providers.AbstractProjectStructureTest +import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectLibrary import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructureParser abstract class AbstractSessionsInvalidationTest : AbstractProjectStructureTest() { @@ -29,7 +30,8 @@ abstract class AbstractSessionsInvalidationTest : AbstractProjectStructureTest, override val modules: List, val rootModule: String, val modulesToMakeOOBM: List, @@ -81,8 +84,13 @@ private object SessionInvalidationTestProjectStructureParser : TestProjectStruct private const val MODULES_TO_MAKE_OOBM_IN_FIELD = "modulesToMakeOOBM" private const val EXPECTED_INVALIDATED_MODULES_FIELD = "expectedInvalidatedModules" - override fun parse(modules: List, json: JsonObject): SessionInvalidationTestProjectStructure = + override fun parse( + libraries: List, + modules: List, + json: JsonObject, + ): SessionInvalidationTestProjectStructure = SessionInvalidationTestProjectStructure( + libraries, modules, json.getString(ROOT_MODULE_FIELD), json.getAsJsonArray(MODULES_TO_MAKE_OOBM_IN_FIELD)!!.map { it.asString }.sorted(), diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectEntityReference.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectEntityReference.kt new file mode 100644 index 000000000000..3a42b5aab4a7 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectEntityReference.kt @@ -0,0 +1,30 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure + +import com.google.gson.JsonObject +import org.jetbrains.kotlin.idea.jsonUtils.getNullableString + +/** + * A reference that points to a library or module in the test project structure. + */ +sealed interface TestProjectEntityReference + +data class TestProjectLibraryReference(val name: String) : TestProjectEntityReference + +data class TestProjectModuleReference(val name: String) : TestProjectEntityReference + +object TestProjectEntityReferenceParser { + private const val LIBRARY_FIELD = "library" + private const val MODULE_FIELD = "module" + + fun parse(json: JsonObject): TestProjectEntityReference { + val libraryTarget = json.getNullableString(LIBRARY_FIELD)?.let { TestProjectLibraryReference(it) } + val moduleTarget = json.getNullableString(MODULE_FIELD)?.let { TestProjectModuleReference(it) } + + if (libraryTarget == null && moduleTarget == null || libraryTarget != null && moduleTarget != null) { + error("Expected exactly one of `$LIBRARY_FIELD` and `$MODULE_FIELD` to be specified.") + } + + return libraryTarget ?: moduleTarget!! + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt new file mode 100644 index 000000000000..246d27be8094 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt @@ -0,0 +1,49 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + +package org.jetbrains.kotlin.idea.fir.analysis.providers + +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import com.google.gson.JsonPrimitive +import org.jetbrains.kotlin.idea.jsonUtils.getString + +interface TestProjectStructure { + /** + * A list of *project-level* libraries in the test project structure. + */ + val libraries: List + + val modules: List +} + +fun interface TestProjectStructureParser { + /** + * Parses a [TestProjectStructure] from already parsed lists of [TestProjectLibrary]s and [TestProjectModule]s, and the original + * [JsonObject]. + */ + fun parse(libraries: List, modules: List, json: JsonObject): S +} + +data class TestProjectLibrary(val name: String) + +object TestProjectLibraryParser { + fun parse(json: JsonElement): TestProjectLibrary { + require(json is JsonObject) + return TestProjectLibrary(json.getString("name")) + } +} + +data class TestProjectModule(val name: String, val dependsOnModules: List) + +object TestProjectModuleParser { + private const val DEPENDS_ON_FIELD = "dependsOn" + + fun parse(json: JsonElement): TestProjectModule { + require(json is JsonObject) + val dependencies = json.getAsJsonArray(DEPENDS_ON_FIELD)?.map { (it as JsonPrimitive).asString } ?: emptyList() + return TestProjectModule( + json.getString("name"), + dependencies + ) + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructureReader.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructureReader.kt new file mode 100644 index 000000000000..8f263714c4b2 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructureReader.kt @@ -0,0 +1,35 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure + +import com.google.gson.JsonObject +import com.google.gson.JsonParser +import com.intellij.openapi.util.io.FileUtil +import java.nio.file.Path +import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectLibraryParser +import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectModuleParser +import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructure +import org.jetbrains.kotlin.idea.fir.analysis.providers.TestProjectStructureParser + +internal object TestProjectStructureReader { + fun read( + testDirectory: Path, + jsonFileName: String = "structure.json", + parser: TestProjectStructureParser, + ): S { + val jsonFile = testDirectory.resolve(jsonFileName) + + @Suppress("DEPRECATION") // AS 4.0 + val json = JsonParser().parse(FileUtil.loadFile(jsonFile.toFile(), /*convertLineSeparators=*/true)) + require(json is JsonObject) + + val libraries = json.getAsJsonArray("libraries")?.map(TestProjectLibraryParser::parse) ?: emptyList() + val modules = json.getAsJsonArray("modules")!!.map(TestProjectModuleParser::parse) + return parser.parse(libraries, modules, json) + } + + fun readToTestStructure( + testDirectory: Path, + jsonFileName: String = "structure.json", + testProjectStructureParser: TestProjectStructureParser, + ): S = read(testDirectory, jsonFileName, testProjectStructureParser) +} diff --git a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt index 57f0dcfa83c7..dc734505ebbe 100644 --- a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt +++ b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.idea.test import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.module.Module +import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.ProjectJdkTable import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.LibraryOrderEntry @@ -13,6 +14,7 @@ import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.impl.libraries.LibraryEx import com.intellij.openapi.roots.libraries.Library +import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar import com.intellij.openapi.roots.libraries.PersistentLibraryKind import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor import com.intellij.openapi.vfs.VfsUtil @@ -107,6 +109,16 @@ object ConfigLibraryUtil { } } + fun addProjectLibrary( + project: Project, + name: String, + init: Library.ModifiableModel.() -> Unit, + ): Library = runWriteAction { + LibraryTablesRegistrar.getInstance().getLibraryTable(project).createLibrary(name).apply { + modifiableModel.init() + } + } + fun addLibrary(module: Module, name: String, kind: PersistentLibraryKind<*>? = null, init: Library.ModifiableModel.() -> Unit) { runWriteAction { ModuleRootManager.getInstance(module).modifiableModel.apply { @@ -147,7 +159,6 @@ object ConfigLibraryUtil { return library } - fun removeLibrary(module: Module, libraryName: String): Boolean { return runWriteAction { var removed = false From 2d3fc097aa9915c37a4a9f8da7c0e1c8c4de9417 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 23 May 2023 14:13:46 +0200 Subject: [PATCH 022/165] [kotlin] KT-58257 Add library tests for `IdeKotlinModuleDependentsProvider` GitOrigin-RevId: 23c5b307c8a36f4b894c87f7b999358532ebea3c --- .../libraryTargets/cyclical/structure.json | 13 ++++++++++++ .../libraryTargets/rhombus/structure.json | 15 ++++++++++++++ .../libraryTargets/rhombus2/structure.json | 15 ++++++++++++++ .../libraryTargets/singleRoot/structure.json | 20 +++++++++++++++++++ .../binaryTree/structure.json | 2 +- .../cyclical/structure.json | 2 +- .../cyclicalSelf/structure.json | 2 +- .../structure.json | 2 +- .../{ => moduleTargets}/linear/structure.json | 7 +++++-- .../rhombus/structure.json | 2 +- .../fir/testGenerator/FirGenerateTests.kt | 3 ++- 11 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/cyclical/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus2/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/singleRoot/structure.json rename plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/{ => moduleTargets}/binaryTree/structure.json (92%) rename plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/{ => moduleTargets}/cyclical/structure.json (87%) rename plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/{ => moduleTargets}/cyclicalSelf/structure.json (84%) rename plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/{ => moduleTargets}/cyclicalWithOutsideDependency/structure.json (89%) rename plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/{ => moduleTargets}/linear/structure.json (69%) rename plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/{ => moduleTargets}/rhombus/structure.json (89%) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/cyclical/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/cyclical/structure.json new file mode 100644 index 000000000000..30f44556c982 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/cyclical/structure.json @@ -0,0 +1,13 @@ +{ + "libraries": [ + { "name": "L1" } + ], + "modules" : [ + { "name": "A", "dependsOn": ["B"] }, + { "name": "B", "dependsOn": ["C", "L1"] }, + { "name": "C", "dependsOn": ["A"] } + ], + "target": { "library": "L1" }, + "directDependents": ["B"], + "transitiveDependents": ["A", "B", "C"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus/structure.json new file mode 100644 index 000000000000..3addd0d20b36 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus/structure.json @@ -0,0 +1,15 @@ +{ + "libraries": [ + { "name": "L1" }, + { "name": "L2" } + ], + "modules" : [ + { "name": "A", "dependsOn": ["B", "C"] }, + { "name": "B", "dependsOn": ["D"] }, + { "name": "C", "dependsOn": ["D", "L2"] }, + { "name": "D", "dependsOn": ["L1"] } + ], + "target": { "library": "L1" }, + "directDependents": ["D"], + "transitiveDependents": ["A", "B", "C", "D"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus2/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus2/structure.json new file mode 100644 index 000000000000..00ca79b3d82a --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus2/structure.json @@ -0,0 +1,15 @@ +{ + "libraries": [ + { "name": "L1" }, + { "name": "L2" } + ], + "modules" : [ + { "name": "A", "dependsOn": ["B", "C"] }, + { "name": "B", "dependsOn": ["D"] }, + { "name": "C", "dependsOn": ["D", "L2"] }, + { "name": "D", "dependsOn": ["L1"] } + ], + "target": { "library": "L2" }, + "directDependents": ["C"], + "transitiveDependents": ["A", "C"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/singleRoot/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/singleRoot/structure.json new file mode 100644 index 000000000000..cc0b86824fa2 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/singleRoot/structure.json @@ -0,0 +1,20 @@ +{ + "libraries": [ + { "name": "L1" }, + { "name": "L2" } + ], + "modules" : [ + { "name": "A", "dependsOn": ["B", "C", "H"] }, + { "name": "B", "dependsOn": ["D", "E"] }, + { "name": "C", "dependsOn": ["F", "G"] }, + { "name": "D", "dependsOn": ["L1"] }, + { "name": "E", "dependsOn": ["L1"] }, + { "name": "F", "dependsOn": ["L2"] }, + { "name": "G", "dependsOn": ["L2"] }, + { "name": "H", "dependsOn": ["I"] }, + { "name": "I", "dependsOn": ["L1"] } + ], + "target": { "library": "L1" }, + "directDependents": ["D", "E", "I"], + "transitiveDependents": ["D", "E", "I", "H", "B", "A"] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/binaryTree/structure.json similarity index 92% rename from plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json rename to plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/binaryTree/structure.json index fdf4b497f067..07bf08cfb7f7 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/binaryTree/structure.json @@ -8,7 +8,7 @@ { "name": "F", "dependsOn": [] }, { "name": "G", "dependsOn": [] } ], - "module": "F", + "target": { "module": "F" }, "directDependents": ["C"], "transitiveDependents": ["C", "A"] } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclical/structure.json similarity index 87% rename from plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json rename to plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclical/structure.json index 5c63a69c941a..072b227f822b 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclical/structure.json @@ -4,7 +4,7 @@ { "name": "B", "dependsOn": ["C"] }, { "name": "C", "dependsOn": ["A"] } ], - "module": "A", + "target": { "module": "A" }, "directDependents": ["C"], "transitiveDependents": ["B", "C"] } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalSelf/structure.json similarity index 84% rename from plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json rename to plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalSelf/structure.json index 6c832cebee73..e80da8b94335 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalSelf/structure.json @@ -3,7 +3,7 @@ { "name": "A", "dependsOn": ["A"] }, { "name": "B", "dependsOn": ["A"] } ], - "module": "A", + "target": { "module": "A" }, "directDependents": ["B"], "transitiveDependents": ["B"] } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalWithOutsideDependency/structure.json similarity index 89% rename from plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json rename to plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalWithOutsideDependency/structure.json index 4ff8c6961315..6c5f29ae27b8 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalWithOutsideDependency/structure.json @@ -5,7 +5,7 @@ { "name": "C", "dependsOn": ["A"] }, { "name": "O", "dependsOn": [] } ], - "module": "O", + "target": { "module": "O" }, "directDependents": ["B"], "transitiveDependents": ["A", "B", "C"] } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/linear/structure.json similarity index 69% rename from plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json rename to plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/linear/structure.json index fce6777c73a0..da6dda4f5c04 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/linear/structure.json @@ -1,12 +1,15 @@ { + "libraries": [ + { "name": "L1" } + ], "modules" : [ { "name": "A", "dependsOn": ["B"] }, { "name": "B", "dependsOn": ["C"] }, { "name": "C", "dependsOn": ["D"] }, { "name": "D", "dependsOn": ["E"] }, - { "name": "E", "dependsOn": [] } + { "name": "E", "dependsOn": ["L1"] } ], - "module": "E", + "target": { "module": "E" }, "directDependents": ["D"], "transitiveDependents": ["A", "B", "C", "D"] } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/rhombus/structure.json similarity index 89% rename from plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json rename to plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/rhombus/structure.json index 70a440e4d646..c57fd8f4c747 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/rhombus/structure.json @@ -5,7 +5,7 @@ { "name": "C", "dependsOn": ["D"] }, { "name": "D", "dependsOn": [] } ], - "module": "D", + "target": { "module": "D" }, "directDependents": ["B", "C"], "transitiveDependents": ["A", "B", "C"] } diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt index d5858963d7ee..aa7e1e203e31 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt @@ -83,7 +83,8 @@ private fun assembleWorkspace(): TWorkspace = workspace { } testClass { - model("moduleDependents", pattern = DIRECTORY, isRecursive = false) + model("moduleDependents/libraryTargets", pattern = DIRECTORY, isRecursive = false) + model("moduleDependents/moduleTargets", pattern = DIRECTORY, isRecursive = false) } } From 546aac31715f13f7ef5fc193cd4aadd84e660afa Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 24 May 2023 14:11:26 +0200 Subject: [PATCH 023/165] [kotlin] KT-58257 Enable `LLFirSessionInvalidationService` in K2 IDE GitOrigin-RevId: 52f2d6f0d69868b860ad980d0a9ebd209c940b73 --- ...kotlin.base.fir.analysis-api-providers.xml | 1 + ...nalysisEventSubscriptionProjectActivity.kt | 23 +++++++++++++++++++ .../k2/resources/META-INF/lowLevelApiFir.xml | 1 + 3 files changed, 25 insertions(+) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirAnalysisEventSubscriptionProjectActivity.kt diff --git a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml index a1db54ae9816..7908ac27ad06 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml +++ b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml @@ -12,6 +12,7 @@ serviceImplementation="org.jetbrains.kotlin.idea.base.fir.analysisApiProviders.FirIdeKotlinGlobalModificationService"/> + diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirAnalysisEventSubscriptionProjectActivity.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirAnalysisEventSubscriptionProjectActivity.kt new file mode 100644 index 000000000000..90dc84373436 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirAnalysisEventSubscriptionProjectActivity.kt @@ -0,0 +1,23 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.base.fir.analysisApiProviders + +import com.intellij.openapi.project.Project +import com.intellij.openapi.startup.ProjectActivity +import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionInvalidationService +import org.jetbrains.kotlin.analysis.providers.analysisMessageBus + +/** + * [FirAnalysisEventSubscriptionProjectActivity] sets up subscriptions to events published via [analysisMessageBus] for FIR services. This + * approach is favored over defining `projectListeners` in the plugin XML configuration for two reasons: + * + * 1. [analysisMessageBus] is not guaranteed to be the same as the [Project]'s message bus, by design, and `projectListeners` registers + * listeners with the project message bus. + * 2. Services like [LLFirSessionInvalidationService] have to register listeners when running in the IDE, but also in Analysis API + * standalone mode. We cannot register listeners via XML in standalone mode, so this approach allows putting the subscription + * configuration in one place. + */ +internal class FirAnalysisEventSubscriptionProjectActivity : ProjectActivity { + override suspend fun execute(project: Project) { + LLFirSessionInvalidationService.getInstance(project).subscribeToModificationEvents() + } +} diff --git a/plugins/kotlin/plugin/k2/resources/META-INF/lowLevelApiFir.xml b/plugins/kotlin/plugin/k2/resources/META-INF/lowLevelApiFir.xml index e6f28d6ec72a..c9d7d5326897 100644 --- a/plugins/kotlin/plugin/k2/resources/META-INF/lowLevelApiFir.xml +++ b/plugins/kotlin/plugin/k2/resources/META-INF/lowLevelApiFir.xml @@ -27,6 +27,7 @@ serviceImplementation="org.jetbrains.kotlin.analysis.low.level.api.fir.stubBased.deserialization.JvmStubBasedDeserializedSymbolProviderFactory"/> + \ No newline at end of file From 3f34fbd814973bc3ba8dff4b4d635f6f01054d8c Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 24 May 2023 14:13:36 +0200 Subject: [PATCH 024/165] [kotlin] KT-58257 Ensure that module out-of-block modification events are published in a write action - This is explicitly required by the event's topic. GitOrigin-RevId: 4021a301b67f90a99aab599722cd2c03599225d2 --- .../FirIdeOutOfBlockModificationService.kt | 8 ++++++-- .../kotlin/idea/fir/analysis/providers/testUtils.kt | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt index 5682b21ba36c..00e37f744473 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.idea.base.fir.analysisApiProviders import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.Service import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project @@ -38,16 +39,19 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo override fun dispose() {} /** - * Publishes out-of-block modification for [module]'s [KtModule]s. + * Publishes out-of-block modification for [module]'s [KtModule]s. Must be called in a write action. */ fun publishModuleOnlyOutOfBlockModification(module: Module) { + ApplicationManager.getApplication().assertWriteAccessAllowed() + module.sourceModuleInfos.forEach { project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).afterModification(it.toKtModule()) } } /** - * Publishes out-of-block modification for [module]'s [KtModule]s and the project itself. + * Publishes out-of-block modification for [module]'s [KtModule]s and the project itself. Must be called in a write action if [module] + * is not `null`. * * [publishModuleAndProjectOutOfBlockModification] cannot be used for single file-based [KtModule]s (such as scripts), because they * don't have an associated IntelliJ [Module]. diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt index 1a0e990530b2..3c4b2e6c41b3 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt @@ -2,9 +2,12 @@ package org.jetbrains.kotlin.idea.fir.analysis.providers +import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.module.Module import org.jetbrains.kotlin.idea.base.fir.analysisApiProviders.FirIdeOutOfBlockModificationService internal fun Module.publishOutOfBlockModification() { - FirIdeOutOfBlockModificationService.getInstance(project).publishModuleOnlyOutOfBlockModification(this) -} \ No newline at end of file + runWriteAction { + FirIdeOutOfBlockModificationService.getInstance(project).publishModuleOnlyOutOfBlockModification(this) + } +} From 7ec66ca85f89e5eeb88e2d551d9f3b7b3bd4af1e Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 24 May 2023 15:57:35 +0200 Subject: [PATCH 025/165] [kotlin] KT-58257 Remove modification tracker from `ExtensionForTests` - The XML file will not change during the test, so there is no need to publish modification events instead. GitOrigin-RevId: a6868c54d268f3c2061d9cf3ebe366bd8537f8bb --- .../fir/extensions/KtResolveExtensionProviderForTests.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/extensions/KtResolveExtensionProviderForTests.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/extensions/KtResolveExtensionProviderForTests.kt index 56158e10e251..fd2a81035682 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/extensions/KtResolveExtensionProviderForTests.kt +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/extensions/KtResolveExtensionProviderForTests.kt @@ -3,7 +3,6 @@ package org.jetbrains.kotlin.idea.fir.extensions import com.intellij.openapi.roots.OrderEnumerator import com.intellij.openapi.roots.OrderRootType -import com.intellij.openapi.util.ModificationTracker import com.intellij.psi.PsiElement import com.intellij.psi.PsiManager import com.intellij.psi.xml.XmlFile @@ -57,10 +56,6 @@ private class ExtensionForTests(private val xmlFile: XmlFile) : KtResolveExtensi override fun getKtFiles(): List { return files } - - override fun getModificationTracker(): ModificationTracker { - return ModificationTracker { xmlFile.modificationStamp } - } } private class ExtensionFileForTest(private val rootTag: XmlTag, private val packageName: FqName) : KtResolveExtensionFile() { From ac00519296caa06b6b3e0bb1a4c0707e9bda5517 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 22 Jun 2023 15:11:17 +0200 Subject: [PATCH 026/165] [kotlin] KT-58257 Replace `afterModification` with `onModification` after Kotlin modification event refactoring GitOrigin-RevId: deb8499b83bd9e5b266548c7c239bf9baad326ec --- .../KotlinModuleStateModificationService.kt | 2 +- .../FirIdeOutOfBlockModificationService.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 1ff5e5fd8af4..25d81c207308 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -203,5 +203,5 @@ private fun EntityChange.Replaced.getReplacedEntity( } private fun Project.publishModuleStateModification(module: KtModule, isRemoval: Boolean) { - analysisMessageBus.syncPublisher(KotlinTopics.MODULE_STATE_MODIFICATION).afterModification(module, isRemoval) + analysisMessageBus.syncPublisher(KotlinTopics.MODULE_STATE_MODIFICATION).onModification(module, isRemoval) } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt index 00e37f744473..b621dd712709 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt @@ -45,7 +45,7 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo ApplicationManager.getApplication().assertWriteAccessAllowed() module.sourceModuleInfos.forEach { - project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).afterModification(it.toKtModule()) + project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).onModification(it.toKtModule()) } } @@ -67,7 +67,7 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo projectOutOfBlockModificationTracker.incModificationCount() // We should not invalidate binary module content here, because global PSI tree changes have no effect on binary modules. - project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_SOURCE_OUT_OF_BLOCK_MODIFICATION).afterModification() + project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_SOURCE_OUT_OF_BLOCK_MODIFICATION).onModification() } companion object { @@ -90,6 +90,6 @@ private class SingleFileModuleFileListener(private val project: Project) : Abstr override fun shouldProcessEvent(event: VFileEvent): Boolean = event is VFileContentChangeEvent override fun processEvent(event: VFileEvent, module: KtModule) { - project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).afterModification(module) + project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).onModification(module) } } From 4245824fec9f45167718a63621a27c7927c72dbf Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 22 Jun 2023 15:18:38 +0200 Subject: [PATCH 027/165] [kotlin] KT-58257 Listen to single-file module file deletion events before the file is deleted - Tests which deleted Kotlin files during cleanup were failing because `AbstractSingleFileModuleFileListener.after` tried to get the PSI file for a deleted virtual file. - Instead of publishing a modification event after a file is deleted, we can publish it right before it is deleted, which still allows us to get the `KtModule` via the PSI file. GitOrigin-RevId: 29eeb9a315cfdfeba5893ae0e6e6fb64a571a005 --- .../KotlinModuleStateModificationService.kt | 39 +++++++++-- ...stractSingleFileModuleFileEventListener.kt | 68 +++++++++++++++++++ .../AbstractSingleFileModuleFileListener.kt | 49 ------------- ...kotlin.base.fir.analysis-api-providers.xml | 4 +- .../FirIdeOutOfBlockModificationService.kt | 13 ++-- 5 files changed, 112 insertions(+), 61 deletions(-) create mode 100644 plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileEventListener.kt delete mode 100644 plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileListener.kt diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 25d81c207308..a9cccff5b4dd 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -11,6 +11,7 @@ import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.newvfs.BulkFileListener import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent @@ -34,10 +35,10 @@ import org.jetbrains.kotlin.analysis.providers.analysisMessageBus import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics import org.jetbrains.kotlin.idea.base.projectStructure.getBinaryAndSourceModuleInfos import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.IdeaModuleInfo -import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.SdkInfo import org.jetbrains.kotlin.idea.base.projectStructure.sourceModuleInfos import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule -import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleFileListener +import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleAfterFileEventListener +import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleBeforeFileEventListener open class KotlinModuleStateModificationService(val project: Project) : Disposable { protected open fun mayBuiltinsHaveChanged(events: List): Boolean { return false } @@ -57,13 +58,39 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab } /** - * Publishes module state modification events for script and not-under-content-root [KtModule]s. + * Publishes a module state modification event for a script or not-under-content-root [KtModule] whose file has been moved. + * + * Even though the event is processed *after* the file has been moved, the [KtModule]s before and after the move are equal via their + * respective module infos, because: + * + * - In the case of `NotUnderContentRootModuleInfo`, the file pointer remains the same after the move. + * - In the case of `ScriptModuleInfo`, the virtual file and script definition remain the same after the move. + * + * A global out-of-block modification event will be published by `FirIdeOutOfBlockPsiTreeChangePreprocessor` after a Kotlin file is + * moved, but we still need this listener to publish a module state modification event specifically. */ - class SingleFileModuleFileListener(private val project: Project) : AbstractSingleFileModuleFileListener(project) { - override fun shouldProcessEvent(event: VFileEvent): Boolean = event is VFileDeleteEvent || event is VFileMoveEvent + class SingleFileModuleMoveListener(private val project: Project) : AbstractSingleFileModuleAfterFileEventListener(project) { + override fun isRelevantEvent(event: VFileEvent, file: VirtualFile): Boolean = event is VFileMoveEvent override fun processEvent(event: VFileEvent, module: KtModule) { - project.publishModuleStateModification(module, isRemoval = event is VFileDeleteEvent) + project.publishModuleStateModification(module, isRemoval = false) + } + } + + /** + * Publishes a module state modification event for a script or not-under-content-root [KtModule] whose file has been deleted. + * + * This listener processes events *before* the file is deleted, because getting a PSI file (and in turn the PSI file's [KtModule]) for a + * virtual file which has already been deleted is not feasible. + * + * A global out-of-block modification event will be published by `FirIdeOutOfBlockPsiTreeChangePreprocessor` after a Kotlin file is + * deleted, but we still need this listener to publish a module state modification event specifically. + */ + class SingleFileModuleDeletionListener(private val project: Project) : AbstractSingleFileModuleBeforeFileEventListener(project) { + override fun isRelevantEvent(event: VFileEvent, file: VirtualFile): Boolean = event is VFileDeleteEvent + + override fun processEvent(event: VFileEvent, module: KtModule) { + project.publishModuleStateModification(module, isRemoval = true) } } diff --git a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileEventListener.kt b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileEventListener.kt new file mode 100644 index 000000000000..8a88bfba2695 --- /dev/null +++ b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileEventListener.kt @@ -0,0 +1,68 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.util + +import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.ProjectFileIndex +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.newvfs.BulkFileListener +import com.intellij.openapi.vfs.newvfs.events.VFileEvent +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.KtNotUnderContentRootModule +import org.jetbrains.kotlin.analysis.project.structure.KtScriptDependencyModule +import org.jetbrains.kotlin.analysis.project.structure.KtScriptModule +import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider +import org.jetbrains.kotlin.idea.core.util.toPsiFile +import org.jetbrains.kotlin.parsing.KotlinParserDefinition + +/** + * [AbstractSingleFileModuleFileEventListener] listens to file events and calls [processEvent] with the single-file [KtModule] associated + * with the event's file. An event is only processed if it passes [isRelevantEvent]. + * + * Use one of the *before* or *after* variants to implement this listener: + * + * - [AbstractSingleFileModuleBeforeFileEventListener] + * - [AbstractSingleFileModuleAfterFileEventListener] + */ +sealed class AbstractSingleFileModuleFileEventListener(private val project: Project) : BulkFileListener { + protected abstract fun isRelevantEvent(event: VFileEvent, file: VirtualFile): Boolean + + protected abstract fun processEvent(event: VFileEvent, module: KtModule) + + internal fun processEvents(events: List) { + for (event in events) { + val file = event.file ?: continue + if (!isRelevantEvent(event, file)) continue + if (!file.mayBeFromSingleFileModule(project)) continue + + val module = file.getSingleFileModule() ?: continue + processEvent(event, module) + } + } + + /** + * Checks whether the given [VirtualFile] may come from a single-file [KtModule] with the following heuristics: + * + * 1. The file is a script if its extension is `.kts`. + * 2. The file can only belong to a not-under-content-root `KtModule` if it isn't in some module's source content. + */ + private fun VirtualFile.mayBeFromSingleFileModule(project: Project): Boolean = + extension == KotlinParserDefinition.STD_SCRIPT_SUFFIX || + isKotlinFileType() && !ProjectFileIndex.getInstance(project).isInSourceContent(this) + + private fun VirtualFile.getSingleFileModule(): KtModule? = + toPsiFile(project) + ?.let { ProjectStructureProvider.getModule(project, it, contextualModule = null) } + ?.takeIf { it is KtScriptModule || it is KtScriptDependencyModule || it is KtNotUnderContentRootModule } +} + +abstract class AbstractSingleFileModuleBeforeFileEventListener(project: Project) : AbstractSingleFileModuleFileEventListener(project) { + override fun before(events: List) { + processEvents(events) + } +} + +abstract class AbstractSingleFileModuleAfterFileEventListener(project: Project) : AbstractSingleFileModuleFileEventListener(project) { + override fun after(events: List) { + processEvents(events) + } +} diff --git a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileListener.kt b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileListener.kt deleted file mode 100644 index a7e0350aabe4..000000000000 --- a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileListener.kt +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.kotlin.idea.util - -import com.intellij.openapi.module.ModuleUtilCore -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vfs.newvfs.BulkFileListener -import com.intellij.openapi.vfs.newvfs.events.VFileEvent -import org.jetbrains.kotlin.analysis.project.structure.KtModule -import org.jetbrains.kotlin.analysis.project.structure.KtNotUnderContentRootModule -import org.jetbrains.kotlin.analysis.project.structure.KtScriptDependencyModule -import org.jetbrains.kotlin.analysis.project.structure.KtScriptModule -import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider -import org.jetbrains.kotlin.idea.core.util.toPsiFile -import org.jetbrains.kotlin.parsing.KotlinParserDefinition - -/** - * [AbstractSingleFileModuleFileListener] listens to file events and calls [processEvent] with the [KtModule] associated with the script or - * not-under-content-root file of an event. An event is only processed if it passes [shouldProcessEvent]. - */ -abstract class AbstractSingleFileModuleFileListener(private val project: Project) : BulkFileListener { - protected abstract fun shouldProcessEvent(event: VFileEvent): Boolean - - protected abstract fun processEvent(event: VFileEvent, module: KtModule) - - override fun after(events: List) { - for (event in events) { - if (!shouldProcessEvent(event)) continue - val file = event.file ?: continue - - if (file.mayBeFromSingleFileModule()) { - val module = - file.toPsiFile(project)?.let { ProjectStructureProvider.getModule(project, it, contextualModule = null) } ?: continue - - if (module is KtScriptModule || module is KtScriptDependencyModule || module is KtNotUnderContentRootModule) { - processEvent(event, module) - } - } - } - } - - /** - * The file is a script if its extension is `.kts`. Alternatively, the file can only belong to a not-under-content-root `KtModule` if it - * has no module associated with it. - */ - private fun VirtualFile.mayBeFromSingleFileModule(): Boolean = - extension == KotlinParserDefinition.STD_SCRIPT_SUFFIX || - isKotlinFileType() && ModuleUtilCore.findModuleForFile(this, project) == null -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml index 7908ac27ad06..818944eeda07 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml +++ b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml @@ -16,7 +16,9 @@ - + diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt index b621dd712709..de46ffb8e005 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt @@ -8,6 +8,7 @@ import com.intellij.openapi.components.Service import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.openapi.util.SimpleModificationTracker +import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent import com.intellij.openapi.vfs.newvfs.events.VFileEvent @@ -17,7 +18,7 @@ import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleOutOfBlockModi import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics import org.jetbrains.kotlin.idea.base.projectStructure.sourceModuleInfos import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule -import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleFileListener +import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleAfterFileEventListener /** * [FirIdeOutOfBlockModificationService] increments modification trackers and publishes subscription events on out-of-block modification @@ -33,7 +34,7 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo init { val busConnection = project.messageBus.connect(this) - busConnection.subscribe(VirtualFileManager.VFS_CHANGES, SingleFileModuleFileListener(project)) + busConnection.subscribe(VirtualFileManager.VFS_CHANGES, SingleFileModuleContentChangeListener(project)) } override fun dispose() {} @@ -77,7 +78,7 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo } /** - * An [AbstractSingleFileModuleFileListener] that publishes out-of-block modification events for the associated [KtModule]s. + * A single-file module file event listener that publishes out-of-block modification events for the associated [KtModule]s. * * Any file modification triggers an out-of-block modification event, not just actual out-of-block modifications, which is allowed per the * contract of [KotlinModuleOutOfBlockModificationListener]. @@ -86,8 +87,10 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo * [FirIdeOutOfBlockModificationService.publishModuleAndProjectOutOfBlockModification] cannot be used to publish out-of-block modification * events for such [KtModule]s, hence the existence of this listener. */ -private class SingleFileModuleFileListener(private val project: Project) : AbstractSingleFileModuleFileListener(project) { - override fun shouldProcessEvent(event: VFileEvent): Boolean = event is VFileContentChangeEvent +private class SingleFileModuleContentChangeListener( + private val project: Project, +) : AbstractSingleFileModuleAfterFileEventListener(project) { + override fun isRelevantEvent(event: VFileEvent, file: VirtualFile): Boolean = event is VFileContentChangeEvent override fun processEvent(event: VFileEvent, module: KtModule) { project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).onModification(module) From 8bd5082db4d094dfc02632581e849ebafe80d435 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 22 Jun 2023 18:39:20 +0200 Subject: [PATCH 028/165] [kotlin] KT-58257 Discover IDE friend dependencies in `IdeKotlinModuleDependentsProvider` - A production source `KtModule` has as a direct dependent its test source `KtModule` via friend dependencies. - Besides improving the correctness of direct dependents, this change also allows invalidating only either the production source `KtModule` or the test source `KtModule` if the former doesn't exist, without the need to invalidate *both* source sets separately. - Because the production source and test source `KtModule` are part of the same IntelliJ `Module`, they have the same dependents. Before this change, invalidating the production and test source `KtModule`s separately would mean invalidating the same set of transitive dependents twice. Now this set is only invalidated once. GitOrigin-RevId: 1bd2a62f351fa144184b03181271cafc5a76d7b1 --- .../KotlinModuleStateModificationService.kt | 8 ++-- .../IdeKotlinModuleDependentsProvider.kt | 38 ++++++++++++++----- .../KotlinProjectStructureUtils.kt | 3 ++ 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index a9cccff5b4dd..dbdf737dbe4b 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -29,13 +29,13 @@ import com.intellij.platform.workspace.storage.EntityChange import com.intellij.platform.workspace.storage.EntityStorage import com.intellij.platform.workspace.storage.VersionedStorageChange import com.intellij.platform.workspace.storage.WorkspaceEntity -import org.jetbrains.kotlin.analysis.project.structure.* +import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.providers.KotlinGlobalModificationService import org.jetbrains.kotlin.analysis.providers.analysisMessageBus import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics import org.jetbrains.kotlin.idea.base.projectStructure.getBinaryAndSourceModuleInfos import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.IdeaModuleInfo -import org.jetbrains.kotlin.idea.base.projectStructure.sourceModuleInfos +import org.jetbrains.kotlin.idea.base.projectStructure.productionOrTestSourceModuleInfo import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleAfterFileEventListener import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleBeforeFileEventListener @@ -44,7 +44,9 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab protected open fun mayBuiltinsHaveChanged(events: List): Boolean { return false } private fun invalidateSourceModule(module: Module, isRemoval: Boolean = false) { - invalidateByModuleInfos(module.sourceModuleInfos, isRemoval) + // A test source `KtModule` will be invalidated together with its production source `KtModule` because it is a direct dependent from + // friend dependencies. See `IdeKotlinModuleDependentsProvider`. + module.productionOrTestSourceModuleInfo?.let { project.publishModuleStateModification(it.toKtModule(), isRemoval) } } private fun invalidateLibraryModule(library: Library, isRemoval: Boolean = false) { diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt index 305eea7d0b50..c73ad90aefcb 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt @@ -2,19 +2,20 @@ package org.jetbrains.kotlin.idea.base.projectStructure import com.intellij.openapi.project.Project -import com.intellij.workspaceModel.ide.WorkspaceModel +import com.intellij.platform.backend.workspace.WorkspaceModel +import com.intellij.platform.workspace.jps.entities.ModuleEntity +import com.intellij.platform.workspace.storage.SymbolicEntityId +import com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId import com.intellij.workspaceModel.ide.impl.legacyBridge.module.findModule -import com.intellij.workspaceModel.storage.bridgeEntities.LibraryId -import com.intellij.workspaceModel.storage.bridgeEntities.ModuleEntity -import com.intellij.workspaceModel.storage.bridgeEntities.ModuleId import org.jetbrains.kotlin.analysis.project.structure.KtBuiltinsModule -import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.project.structure.KtScriptDependencyModule import org.jetbrains.kotlin.analysis.project.structure.KtScriptModule import org.jetbrains.kotlin.analysis.project.structure.KtSdkModule import org.jetbrains.kotlin.analysis.project.structure.impl.KotlinModuleDependentsProviderBase +import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.ModuleProductionSourceInfo import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments +import org.jetbrains.kotlin.utils.addIfNotNull /** * [IdeKotlinModuleDependentsProvider] provides [KtModule] dependents by querying the workspace model. @@ -38,16 +39,33 @@ internal class IdeKotlinModuleDependentsProvider(private val project: Project) : else -> throw KotlinExceptionWithAttachments("Unexpected ${KtModule::class.simpleName}").withAttachment("module.txt", module) } + val directDependents = mutableSetOf() + directDependents.addFriendDependents(module) + directDependents.addWorkspaceModelDependents(symbolicId) + + return directDependents + } + + private fun MutableSet.addFriendDependents(module: KtModule) { + // The only friend dependency that currently exists in the IDE is the dependency of an IDEA module's test sources on its production + // sources. Hence, a test source `KtModule` is a direct dependent of its production source `KtModule`. + if (module is KtSourceModuleByModuleInfo && module.ideaModuleInfo is ModuleProductionSourceInfo) { + addIfNotNull(module.ideaModule.testSourceInfo?.toKtModule()) + } + } + + private fun MutableSet.addWorkspaceModelDependents(symbolicId: SymbolicEntityId) { val snapshot = WorkspaceModel.getInstance(project).currentSnapshot - return snapshot + snapshot .referrers(symbolicId, ModuleEntity::class.java) - .flatMapTo(mutableSetOf()) { moduleEntity -> + .forEach { moduleEntity -> // The set of dependents should not include `module` itself. - if (moduleEntity.symbolicId == symbolicId) return@flatMapTo emptyList() + if (moduleEntity.symbolicId == symbolicId) return@forEach // We can skip the module entity if `findModule` returns `null` because the module won't have been added to the project - // model yet and thus cannot be a proper `KtModule`. - moduleEntity.findModule(snapshot)?.sourceModuleInfos?.map { it.toKtModule() } ?: emptyList() + // model yet and thus cannot be a proper `KtModule`. If there is a production source `KtModule`, we only need to add that + // because the test source `KtModule` will be a direct friend dependent of the production source `KtModule`. + addIfNotNull(moduleEntity.findModule(snapshot)?.productionOrTestSourceModuleInfo?.toKtModule()) } } } diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/KotlinProjectStructureUtils.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/KotlinProjectStructureUtils.kt index 9a65c3cfe52b..0546dc5f3130 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/KotlinProjectStructureUtils.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/KotlinProjectStructureUtils.kt @@ -92,6 +92,9 @@ fun Module.asSourceInfo(sourceRootType: KotlinSourceRootType?): ModuleSourceInfo val Module.sourceModuleInfos: List get() = listOfNotNull(testSourceInfo, productionSourceInfo) +val Module.productionOrTestSourceModuleInfo: ModuleSourceInfo? + get() = productionSourceInfo ?: testSourceInfo + private fun Module.hasRootsOfType(rootTypes: Set>): Boolean { return rootManager.contentEntries.any { it.getSourceFolders(rootTypes).isNotEmpty() } } From e17185bd0ba817a057ebaf3e2b76a4e51d48a029 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 22 Jun 2023 18:41:36 +0200 Subject: [PATCH 029/165] [kotlin] KT-58257 Publish out-of-block modification for single-file modules via the PSI tree change preprocessor - `VFileContentChangeEvent` does not occur on every keystroke in a file, but (it seems) only after a file has been saved. Hence, it is not a viable means to publish module out-of-block modification for single-file modules. - Instead, `FirIdeOutOfBlockPsiTreeChangePreprocessor` can actually be extended to publish out-of-block modification for all `KtModule`s, not only IntelliJ `Module`s. This is the preferred solution even without the issues with `VFileContentChangeEvent`, because it is much simpler and doesn't require an additional file listener for single-file modules. - Compared to the modification tracker-based solution, single-file modules (scripts and not-under-content-root files) now profit from file changes only being reported when they're out of block. Previously, out-of-block modification in single-file modules was tracked via `FileModificationTracker`, which has no distinction of "in block" or "out of block" modification. GitOrigin-RevId: 1b0eb380b56d73965bcb83b44b1f1fe1e83e3a2c --- .../FirIdeOutOfBlockModificationService.kt | 62 +++++-------------- ...rIdeOutOfBlockPsiTreeChangePreprocessor.kt | 5 +- .../idea/fir/analysis/providers/testUtils.kt | 2 +- 3 files changed, 20 insertions(+), 49 deletions(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt index de46ffb8e005..1d3d1a6ebdfd 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt @@ -8,17 +8,11 @@ import com.intellij.openapi.components.Service import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.openapi.util.SimpleModificationTracker -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vfs.VirtualFileManager -import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent -import com.intellij.openapi.vfs.newvfs.events.VFileEvent import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.providers.analysisMessageBus -import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleOutOfBlockModificationListener import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics -import org.jetbrains.kotlin.idea.base.projectStructure.sourceModuleInfos +import org.jetbrains.kotlin.idea.base.projectStructure.productionOrTestSourceModuleInfo import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule -import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleAfterFileEventListener /** * [FirIdeOutOfBlockModificationService] increments modification trackers and publishes subscription events on out-of-block modification @@ -32,35 +26,31 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo */ val projectOutOfBlockModificationTracker: SimpleModificationTracker = SimpleModificationTracker() - init { - val busConnection = project.messageBus.connect(this) - busConnection.subscribe(VirtualFileManager.VFS_CHANGES, SingleFileModuleContentChangeListener(project)) - } - override fun dispose() {} /** - * Publishes out-of-block modification for [module]'s [KtModule]s. Must be called in a write action. + * Publishes out-of-block modification for [module]. Must be called in a write action. */ - fun publishModuleOnlyOutOfBlockModification(module: Module) { + fun publishModuleOutOfBlockModification(module: KtModule) { ApplicationManager.getApplication().assertWriteAccessAllowed() - module.sourceModuleInfos.forEach { - project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).onModification(it.toKtModule()) - } + project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).onModification(module) } /** - * Publishes out-of-block modification for [module]'s [KtModule]s and the project itself. Must be called in a write action if [module] - * is not `null`. - * - * [publishModuleAndProjectOutOfBlockModification] cannot be used for single file-based [KtModule]s (such as scripts), because they - * don't have an associated IntelliJ [Module]. + * Publishes out-of-block modification for [module]. Must be called in a write action. */ - fun publishModuleAndProjectOutOfBlockModification(module: Module?) { - if (module != null) { - publishModuleOnlyOutOfBlockModification(module) - } + fun publishModuleOutOfBlockModification(module: Module) { + // A test source `KtModule` will be invalidated together with its production source `KtModule` because it is a direct dependent from + // friend dependencies. See `IdeKotlinModuleDependentsProvider`. + module.productionOrTestSourceModuleInfo?.let { publishModuleOutOfBlockModification(it.toKtModule()) } + } + + /** + * Publishes out-of-block modification for [module] and the project itself. Must be called in a write action. + */ + fun publishModuleAndProjectOutOfBlockModification(module: KtModule) { + publishModuleOutOfBlockModification(module) projectOutOfBlockModificationTracker.incModificationCount() } @@ -76,23 +66,3 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo project.getService(FirIdeOutOfBlockModificationService::class.java) } } - -/** - * A single-file module file event listener that publishes out-of-block modification events for the associated [KtModule]s. - * - * Any file modification triggers an out-of-block modification event, not just actual out-of-block modifications, which is allowed per the - * contract of [KotlinModuleOutOfBlockModificationListener]. - * - * Because Kotlin script and not-under-content-root files aren't associated with a [Module], - * [FirIdeOutOfBlockModificationService.publishModuleAndProjectOutOfBlockModification] cannot be used to publish out-of-block modification - * events for such [KtModule]s, hence the existence of this listener. - */ -private class SingleFileModuleContentChangeListener( - private val project: Project, -) : AbstractSingleFileModuleAfterFileEventListener(project) { - override fun isRelevantEvent(event: VFileEvent, file: VirtualFile): Boolean = event is VFileContentChangeEvent - - override fun processEvent(event: VFileEvent, module: KtModule) { - project.analysisMessageBus.syncPublisher(KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION).onModification(module) - } -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt index 544e147d03f6..f52881853365 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt @@ -12,8 +12,8 @@ import com.intellij.psi.impl.PsiTreeChangePreprocessor import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirInternals import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.getNonLocalReanalyzableContainingDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.invalidateAfterInBlockModification +import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.idea.base.util.module import org.jetbrains.kotlin.psi.KtDeclaration @OptIn(LLFirInternals::class) @@ -63,7 +63,8 @@ internal class FirIdeOutOfBlockPsiTreeChangePreprocessor(private val project: Pr } private fun outOfBlockInvalidation(element: PsiElement) { - FirIdeOutOfBlockModificationService.getInstance(project).publishModuleAndProjectOutOfBlockModification(element.module) + val module = ProjectStructureProvider.getModule(project, element, contextualModule = null) + FirIdeOutOfBlockModificationService.getInstance(project).publishModuleAndProjectOutOfBlockModification(module) } private fun calculateChangeType( diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt index 3c4b2e6c41b3..3eaaddc36aef 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testUtils.kt @@ -8,6 +8,6 @@ import org.jetbrains.kotlin.idea.base.fir.analysisApiProviders.FirIdeOutOfBlockM internal fun Module.publishOutOfBlockModification() { runWriteAction { - FirIdeOutOfBlockModificationService.getInstance(project).publishModuleOnlyOutOfBlockModification(this) + FirIdeOutOfBlockModificationService.getInstance(project).publishModuleOutOfBlockModification(this) } } From 4fe0e75c9c72a074bdeec75726b949bce4d66492 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Fri, 23 Jun 2023 15:10:20 +0200 Subject: [PATCH 030/165] [kotlin] KT-58257 Ignore file events from other projects in `AbstractSingleFileModuleFileEventListener` - Before this change, `AbstractSingleFileModuleFileEventListener` sometimes tried to get the PSI for virtual files from other projects, which caused tests to fail. GitOrigin-RevId: bef20206bbd871026093526a8f27549e20db5d13 --- .../idea/util/AbstractSingleFileModuleFileEventListener.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileEventListener.kt b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileEventListener.kt index 8a88bfba2695..6ad097c7533d 100644 --- a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileEventListener.kt +++ b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/AbstractSingleFileModuleFileEventListener.kt @@ -34,6 +34,13 @@ sealed class AbstractSingleFileModuleFileEventListener(private val project: Proj if (!isRelevantEvent(event, file)) continue if (!file.mayBeFromSingleFileModule(project)) continue + // A `BulkFileListener` may receive events from other projects, which need to be ignored. This check is placed after + // `mayBeFromSingleFileModule` because (1) `mayBeFromSingleFileModule` establishes that `file` is a Kotlin file, and we do not + // need to check `isInContent` for non-Kotlin files, as we don't want to process them, and (2) for the common case where the + // user has opened only one project and most Kotlin files are inside a source set, checking `!isInSourceContent` first excludes + // most files in a single check, as opposed to checking `isInContent` first and then `!isInSourceContent`. + if (!ProjectFileIndex.getInstance(project).isInContent(file)) continue + val module = file.getSingleFileModule() ?: continue processEvent(event, module) } From 094b9cb88b6093a694a6491675599e9c9dd139f7 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Fri, 23 Jun 2023 18:04:28 +0200 Subject: [PATCH 031/165] [kotlin] KT-58257 Avoid publishing duplicate module state modification events upon module removal - On module removal, `KotlinModuleStateModificationService` would publish one removal module state modification event via `handleModuleChanges`, and another non-removal module state modification event via `handleContentRootInModuleChanges`. - Previously, this would not have been an issue because a modification tracker would just have been incremented twice. Events are more expensive from the publishing side, so it's best if we try to avoid publishing an event twice. - It's also strange to publish a non-removal module state modification event after a removal one, so this should look more consistent for subscribers. GitOrigin-RevId: 90cc01796362460778b6c9c3cb741f657930b5dc --- .../KotlinModuleStateModificationService.kt | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index dbdf737dbe4b..37474d6de0c7 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -134,12 +134,16 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab override fun beforeChanged(event: VersionedStorageChange) { handleLibraryChanges(event) - handleModuleChanges(event) - handleContentRootInModuleChanges(event) + + // We keep track of the already invalidated modules because we don't need `handleContentRootInModuleChanges` to publish another + // module state modification event for the same module. + val alreadyInvalidatedModules = handleModuleChanges(event) + handleContentRootInModuleChanges(event, alreadyInvalidatedModules) } - private fun handleContentRootInModuleChanges(event: VersionedStorageChange) { + private fun handleContentRootInModuleChanges(event: VersionedStorageChange, alreadyInvalidatedModules: Set) { for (changedModule in event.getChangedModules()) { + if (changedModule in alreadyInvalidatedModules) continue moduleStateModificationService.invalidateSourceModule(changedModule) } } @@ -191,20 +195,28 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab } } - private fun handleModuleChanges(event: VersionedStorageChange) { - val moduleEntities = event.getChanges(ModuleEntity::class.java).ifEmpty { return } - for (change in moduleEntities) { - when (change) { - is EntityChange.Added -> {} - is EntityChange.Removed -> { - change.oldEntity.findModule(event.storageBefore)?.let { module -> - moduleStateModificationService.invalidateSourceModule(module, isRemoval = true) - } - } + /** + * Invalidates removed and replaced [Module]s and returns the set of these invalidated modules. + */ + private fun handleModuleChanges(event: VersionedStorageChange): Set { + val moduleEntities = event.getChanges(ModuleEntity::class.java).ifEmpty { return emptySet() } - is EntityChange.Replaced -> { - val changedModule = change.getReplacedEntity(event, ModuleEntity::findModule) ?: continue - moduleStateModificationService.invalidateSourceModule(changedModule) + return buildSet { + for (change in moduleEntities) { + when (change) { + is EntityChange.Added -> {} + is EntityChange.Removed -> { + change.oldEntity.findModule(event.storageBefore)?.let { module -> + moduleStateModificationService.invalidateSourceModule(module, isRemoval = true) + add(module) + } + } + + is EntityChange.Replaced -> { + val changedModule = change.getReplacedEntity(event, ModuleEntity::findModule) ?: continue + moduleStateModificationService.invalidateSourceModule(changedModule) + add(changedModule) + } } } } From 81cc43322d6883c457b6f4a2e570f8ede52ba0f8 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Fri, 23 Jun 2023 18:20:33 +0200 Subject: [PATCH 032/165] [kotlin] KT-58257 Port `ModuleStateTrackerTest` to `KotlinModuleStateModificationTest` GitOrigin-RevId: 27fc014a454e26d26ba7b42707a1c3e50781b637 --- .../KotlinModuleStateModificationTest.kt | 226 ++++++++++++++++++ .../trackers/ModuleStateTrackerTest.kt | 219 ----------------- 2 files changed, 226 insertions(+), 219 deletions(-) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/ModuleStateTrackerTest.kt diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt new file mode 100644 index 000000000000..0d57844ffcb8 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt @@ -0,0 +1,226 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.modificationEvents + +import com.intellij.openapi.Disposable +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.util.Disposer +import com.intellij.testFramework.PsiTestUtil +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.providers.analysisMessageBus +import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleStateModificationListener +import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics +import org.jetbrains.kotlin.idea.base.plugin.artifacts.TestKotlinArtifacts +import org.jetbrains.kotlin.idea.base.projectStructure.productionSourceInfo +import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule +import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest +import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil +import org.junit.Assert +import java.io.File + +class KotlinModuleStateModificationTest : AbstractMultiModuleTest() { + override fun isFirPlugin(): Boolean = true + + override fun getTestDataDirectory(): File = error("Should not be called") + + fun `test source module state modification after adding module dependency`() { + val moduleA = createModuleInTmpDir("a") + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + + val trackerA = createTracker(moduleA) + val trackerB = createTracker(moduleB) + val trackerC = createTracker(moduleC) + + moduleA.addDependency(moduleB) + + trackerA.assertModifiedOnce("module A with added module dependency") + trackerB.assertNotModified("unchanged module B") + trackerC.assertNotModified("unchanged module C") + + disposeTrackers(trackerA, trackerB, trackerC) + } + + fun `test source module state modification after adding module dependency with existing dependent`() { + val moduleA = createModuleInTmpDir("a") + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + + moduleC.addDependency(moduleA) + + val trackerA = createTracker(moduleA) + val trackerB = createTracker(moduleB) + val trackerC = createTracker(moduleC) + + moduleA.addDependency(moduleB) + + trackerA.assertModifiedOnce("module A with added module dependency") + trackerB.assertNotModified("unchanged module B") + trackerC.assertNotModified("unchanged module C with a dependency on module A") + + disposeTrackers(trackerA, trackerB, trackerC) + } + + fun `test source module state modification after removing module dependency`() { + val moduleA = createModuleInTmpDir("a") + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + + moduleA.addDependency(moduleB) + + val trackerA = createTracker(moduleA) + val trackerB = createTracker(moduleB) + val trackerC = createTracker(moduleC) + + moduleA.removeDependency(moduleB) + + trackerA.assertModifiedOnce("module A with removed module dependency") + trackerB.assertNotModified("unchanged module B") + trackerC.assertNotModified("unchanged module C") + + disposeTrackers(trackerA, trackerB, trackerC) + } + + fun `test source module state modification after adding module roots`() { + val moduleA = createModuleInTmpDir("a") + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + + val trackerA = createTracker(moduleA) + val trackerB = createTracker(moduleB) + val trackerC = createTracker(moduleC) + + moduleA.addContentRoot(createTempDirectory().toPath()) + + trackerA.assertModifiedOnce("module A with added module roots") + trackerB.assertNotModified("unchanged module B") + trackerC.assertNotModified("unchanged module C") + + disposeTrackers(trackerA, trackerB, trackerC) + } + + fun `test source module state modification after removing module roots`() { + val moduleA = createModuleInTmpDir("a") + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + + val root = moduleA.addContentRoot(createTempDirectory().toPath()) + + val trackerA = createTracker(moduleA) + val trackerB = createTracker(moduleB) + val trackerC = createTracker(moduleC) + + PsiTestUtil.removeContentEntry(moduleA, root.file!!) + + trackerA.assertModifiedOnce("module A with removed module roots") + trackerB.assertNotModified("unchanged module B") + trackerC.assertNotModified("unchanged module C") + + disposeTrackers(trackerA, trackerB, trackerC) + } + + fun `test source module state modification after adding library dependency`() { + val moduleA = createModuleInTmpDir("a") + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + + val trackerA = createTracker(moduleA) + val trackerB = createTracker(moduleB) + val trackerC = createTracker(moduleC) + + moduleA.addLibrary(TestKotlinArtifacts.kotlinTestJunit) + + trackerA.assertModifiedOnce("module A with added library dependency") + trackerB.assertNotModified("unchanged module B") + trackerC.assertNotModified("unchanged module C") + + disposeTrackers(trackerA, trackerB, trackerC) + } + + fun `test source module state modification after removing library dependency`() { + val moduleA = createModuleInTmpDir("a") + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + + moduleA.addLibrary(TestKotlinArtifacts.kotlinTestJunit, name = "junit") + + val trackerA = createTracker(moduleA) + val trackerB = createTracker(moduleB) + val trackerC = createTracker(moduleC) + + ConfigLibraryUtil.removeLibrary(moduleA, "junit") + + trackerA.assertModifiedOnce("module A with removed module dependency") + trackerB.assertNotModified("unchanged module B") + trackerC.assertNotModified("unchanged module C") + + disposeTrackers(trackerA, trackerB, trackerC) + } + + fun `test source module state modification after removal`() { + val moduleA = createModuleInTmpDir("a") + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + + val trackerA = createTracker(moduleA) + val trackerB = createTracker(moduleB) + val trackerC = createTracker(moduleC) + + ModuleManager.getInstance(myProject).disposeModule(moduleA) + + trackerA.assertModifiedOnce("disposed module A", shouldBeRemoval = true) + trackerB.assertNotModified("unchanged module B") + trackerC.assertNotModified("unchanged module C") + + disposeTrackers(trackerA, trackerB, trackerC) + } + + private fun createTracker(module: KtModule): ModuleStateModificationTracker = ModuleStateModificationTracker(module) + + private fun createTracker(module: Module): ModuleStateModificationTracker = createTracker(module.productionSourceInfo!!.toKtModule()) + + private fun disposeTrackers(vararg trackers: ModuleStateModificationTracker) { + trackers.forEach { Disposer.dispose(it) } + } + + private class ModuleStateModificationTracker(val module: KtModule) : Disposable { + private class ReceivedEvent(val isRemoval: Boolean) + + private val receivedEvents: MutableList = mutableListOf() + + init { + val busConnection = module.project.analysisMessageBus.connect(this) + busConnection.subscribe( + KotlinTopics.MODULE_STATE_MODIFICATION, + KotlinModuleStateModificationListener { eventModule, isRemoval -> + if (eventModule == module) { + receivedEvents.add(ReceivedEvent(isRemoval)) + } + } + ) + } + + override fun dispose() { } + + fun assertNotModified(label: String) { + Assert.assertTrue( + "Module state modification events for '$label' should not have been published, but ${receivedEvents.size} events were received.", + receivedEvents.isEmpty(), + ) + } + + fun assertModifiedOnce(label: String, shouldBeRemoval: Boolean = false) { + Assert.assertTrue( + "A single module state modification event for '$label' should have been published, but ${receivedEvents.size} events were received.", + receivedEvents.size == 1, + ) + + val receivedEvent = receivedEvents.single() + val shouldOrShouldNot = if (shouldBeRemoval) "should" else "should not" + Assert.assertTrue( + "The module state modification event for '$label' $shouldOrShouldNot be a removal event.", + receivedEvent.isRemoval == shouldBeRemoval, + ) + } + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/ModuleStateTrackerTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/ModuleStateTrackerTest.kt deleted file mode 100644 index aade2124bb9d..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/ModuleStateTrackerTest.kt +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.kotlin.idea.fir.analysis.providers.trackers - -import com.intellij.openapi.module.Module -import com.intellij.openapi.module.ModuleManager -import com.intellij.testFramework.PsiTestUtil -import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory -import org.jetbrains.kotlin.analysis.providers.KtModuleStateTracker -import org.jetbrains.kotlin.idea.base.plugin.artifacts.TestKotlinArtifacts -import org.jetbrains.kotlin.idea.base.projectStructure.getMainKtSourceModule -import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest -import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil -import org.junit.Assert -import java.io.File - -class ModuleStateTrackerTest : AbstractMultiModuleTest() { - override fun isFirPlugin(): Boolean = true - - override fun getTestDataDirectory(): File = error("Should not be called") - - fun testThatModuleModificationTrackedChangedAfterAddingModuleDependency() { - val moduleA = createModuleInTmpDir("a") - val moduleB = createModuleInTmpDir("b") - val moduleC = createModuleInTmpDir("c") - - val moduleAWithTracker = ModuleWithModuleStateTracker(moduleA) - val moduleBWithTracker = ModuleWithModuleStateTracker(moduleB) - val moduleCWithTracker = ModuleWithModuleStateTracker(moduleC) - - moduleA.addDependency(moduleB) - - Assert.assertTrue( - "Root modification count for module A with dependencies added should change, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module B without dependencies added should not change, modification count is ${moduleBWithTracker.modificationCount}", - moduleBWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module C without dependencies added should not change, modification count is ${moduleCWithTracker.modificationCount}", - moduleCWithTracker.changed() - ) - } - - fun testThatModuleModificationTrackedChangedAfterAddingModuleRoots() { - val moduleA = createModuleInTmpDir("a") - val moduleB = createModuleInTmpDir("b") - val moduleC = createModuleInTmpDir("c") - - val moduleAWithTracker = ModuleWithModuleStateTracker(moduleA) - val moduleBWithTracker = ModuleWithModuleStateTracker(moduleB) - val moduleCWithTracker = ModuleWithModuleStateTracker(moduleC) - - moduleA.addContentRoot(createTempDirectory().toPath()) - - Assert.assertTrue( - "Root modification count for module A with dependencies added should change, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module B without dependencies added should not change, modification count is ${moduleBWithTracker.modificationCount}", - moduleBWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module C without dependencies added should not change, modification count is ${moduleCWithTracker.modificationCount}", - moduleCWithTracker.changed() - ) - } - - fun testThatModuleModificationTrackedChangedAfterRemovingModuleRoots() { - val moduleA = createModuleInTmpDir("a") - val moduleB = createModuleInTmpDir("b") - val moduleC = createModuleInTmpDir("c") - - val root = moduleA.addContentRoot(createTempDirectory().toPath()) - - val moduleAWithTracker = ModuleWithModuleStateTracker(moduleA) - val moduleBWithTracker = ModuleWithModuleStateTracker(moduleB) - val moduleCWithTracker = ModuleWithModuleStateTracker(moduleC) - - PsiTestUtil.removeContentEntry(moduleA, root.file!!) - - Assert.assertTrue( - "Root modification count for module A with dependencies added should change, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module B without dependencies added should not change, modification count is ${moduleBWithTracker.modificationCount}", - moduleBWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module C without dependencies added should not change, modification count is ${moduleCWithTracker.modificationCount}", - moduleCWithTracker.changed() - ) - } - - - fun testThatModuleModificationTrackedChangedAfterAddingLibraryDependency() { - val moduleA = createModuleInTmpDir("a") - val moduleB = createModuleInTmpDir("b") - val moduleC = createModuleInTmpDir("c") - - val moduleAWithTracker = ModuleWithModuleStateTracker(moduleA) - val moduleBWithTracker = ModuleWithModuleStateTracker(moduleB) - val moduleCWithTracker = ModuleWithModuleStateTracker(moduleC) - - moduleA.addLibrary(TestKotlinArtifacts.kotlinTestJunit) - - Assert.assertTrue( - "Root modification count for module A with dependencies added should change, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module B without dependencies added should not change, modification count is ${moduleBWithTracker.modificationCount}", - moduleBWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module C without dependencies added should not change, modification count is ${moduleCWithTracker.modificationCount}", - moduleCWithTracker.changed() - ) - } - - - fun testThatModuleModificationTrackedChangedAfterRemovingModuleDependency() { - val moduleA = createModuleInTmpDir("a") - val moduleB = createModuleInTmpDir("b") - val moduleC = createModuleInTmpDir("c") - - moduleA.addDependency(moduleB) - - val moduleAWithTracker = ModuleWithModuleStateTracker(moduleA) - val moduleBWithTracker = ModuleWithModuleStateTracker(moduleB) - val moduleCWithTracker = ModuleWithModuleStateTracker(moduleC) - - moduleA.removeDependency(moduleB) - - Assert.assertTrue( - "Root modification count for module A with dependencies removed should change, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module B without dependencies removed should not change, modification count is ${moduleBWithTracker.modificationCount}", - moduleBWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module C without dependencies removed should not change, modification count is ${moduleCWithTracker.modificationCount}", - moduleCWithTracker.changed() - ) - } - - fun testThatModuleModificationTrackedChangedAfterRemovingLibraryDependency() { - val moduleA = createModuleInTmpDir("a") - val moduleB = createModuleInTmpDir("b") - val moduleC = createModuleInTmpDir("c") - - moduleA.addLibrary(TestKotlinArtifacts.kotlinTestJunit, name = "junit") - - val moduleAWithTracker = ModuleWithModuleStateTracker(moduleA) - val moduleBWithTracker = ModuleWithModuleStateTracker(moduleB) - val moduleCWithTracker = ModuleWithModuleStateTracker(moduleC) - - ConfigLibraryUtil.removeLibrary(moduleA, "junit") - - Assert.assertTrue( - "Root modification count for module A with dependencies removed should change, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module B without dependencies removed should not change, modification count is ${moduleBWithTracker.modificationCount}", - moduleBWithTracker.changed() - ) - Assert.assertFalse( - "Root modification count for module C without dependencies removed should not change, modification count is ${moduleCWithTracker.modificationCount}", - moduleCWithTracker.changed() - ) - } - - fun testThatModuleIsInvalidatedAfterRemoval() { - val moduleA = createModuleInTmpDir("a") - val moduleB = createModuleInTmpDir("b") - val moduleC = createModuleInTmpDir("c") - - val moduleAWithTracker = ModuleWithModuleStateTracker(moduleA) - val moduleBWithTracker = ModuleWithModuleStateTracker(moduleB) - val moduleCWithTracker = ModuleWithModuleStateTracker(moduleC) - - ModuleManager.getInstance(myProject).disposeModule(moduleA) - - Assert.assertTrue( - "Disposed module A should be invalidated", - moduleAWithTracker.isInvalidated() - ) - Assert.assertFalse( - "not disposed module B should not be invalidated", - moduleBWithTracker.isInvalidated() - ) - Assert.assertFalse( - "not disposed module C should not be invalidated", - moduleCWithTracker.isInvalidated() - ) - } - - - abstract class WithModuleStateTracker(val state: KtModuleStateTracker) { - private val initialModificationCount = state.rootModificationCount - val modificationCount: Long get() = state.rootModificationCount - - fun changed(): Boolean = - modificationCount != initialModificationCount - - fun isInvalidated(): Boolean = !state.isValid - } - - - private class ModuleWithModuleStateTracker(module: Module) : WithModuleStateTracker( - KotlinModificationTrackerFactory.getService(module.project).createModuleStateTracker(module.getMainKtSourceModule()!!) - ) -} \ No newline at end of file From 7cbf567b5f89d604248e61663648e217ea6d969d Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Mon, 26 Jun 2023 23:15:48 +0200 Subject: [PATCH 033/165] [kotlin] KT-58257 Establish an order between library info cache and module state modification workspace model listeners This commit fixes two problems: 1. Previously, it wasn't guaranteed that `LibraryInfoCache` would be the last component to receive "before change" events. If, for example, `KotlinModuleStateModificationService` receives the event after `LibraryInfoCache`, a situation as outlined in `FirOrderedWorkspaceModelChangeListener` might occur. The ordered workspace model change listener avoids this, because it is registered as a single listener and delegates the events to the other components in a clear order. 2. Previously, `LibraryInfoCache` couldn't be accessed for the first time from a workspace model listener (such as the listener in `KotlinModuleStateModificationService`), because this could lead to cache inconsistencies. - Reason: Subscribing to workspace model events (during initialization from first-time access) while a workspace model event is being processed means that that event won't be propagated to the new subscription. Hence, for exactly that event, `LibraryInfoCache` would not be invalidated, as its workspace model listener wouldn't be called, leading to a cache entry whose changes weren't picked up. - In more detail: 1. A root "before change" event for a library `L1` is published. 2. `KotlinModuleStateModificationService` calls `LibraryInfoCache` with `L1`. 3. `LibraryInfoCache` is initialized, the workspace model subscription is initialized, and `L1` is added to the cache with the root BEFORE the change because the event is a "before change" event. 4. The root change event skips `LibraryInfoCache`'s listener because the subscription was added during the event handling. 5. `L1` is still part of the cache, but now `LibraryInfoInnerCache.cache` contains a library `L1` with the new root (once the `LibraryBridge` has been updated), while `deduplicationCache` still contains the old root. - The solution is quite simple: the workspace model listener has to be registered before events might need to be handled. The combined listener is registered via XML, which guarantees this. GitOrigin-RevId: f31e7bda0ed1e7b9ea4aaebad757db6af54d4d8b --- .idea/modules.xml | 2 + .../build/kotlin/KotlinPluginBuilder.kt | 2 + .../KotlinModuleStateModificationService.kt | 141 +++++++++--------- .../kotlin.base.fe10.project-structure.iml | 33 ++++ .../kotlin.base.fe10.project-structure.xml | 6 + ...Fe10OrderedWorkspaceModelChangeListener.kt | 17 +++ ...kotlin.base.fir.analysis-api-providers.xml | 2 - .../kotlin.base.fir.project-structure.iml | 34 +++++ .../kotlin.base.fir.project-structure.xml | 10 ++ .../FirOrderedWorkspaceModelChangeListener.kt | 37 +++++ .../base/projectStructure/LibraryInfoCache.kt | 81 +++++----- .../intellij.kotlin.plugin.community.main.iml | 2 + plugins/kotlin/plugin/k1/kotlin.plugin.k1.iml | 1 + .../plugin/k1/resources/META-INF/k1.xml | 1 + plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml | 1 + .../plugin/k2/resources/META-INF/k2.xml | 2 + 16 files changed, 259 insertions(+), 113 deletions(-) create mode 100644 plugins/kotlin/base/fe10/project-structure/kotlin.base.fe10.project-structure.iml create mode 100644 plugins/kotlin/base/fe10/project-structure/resources/kotlin.base.fe10.project-structure.xml create mode 100644 plugins/kotlin/base/fe10/project-structure/src/org/jetbrains/kotlin/idea/base/fe10/projectStructure/Fe10OrderedWorkspaceModelChangeListener.kt create mode 100644 plugins/kotlin/base/fir/project-structure/kotlin.base.fir.project-structure.iml create mode 100644 plugins/kotlin/base/fir/project-structure/resources/kotlin.base.fir.project-structure.xml create mode 100644 plugins/kotlin/base/fir/project-structure/src/org/jetbrains/kotlin/idea/base/fir/projectStructure/FirOrderedWorkspaceModelChangeListener.kt diff --git a/.idea/modules.xml b/.idea/modules.xml index 4e48e515d9ae..e7a936d2d891 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -1148,8 +1148,10 @@ + + diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt index 1b7029fae40e..1cbbafcb75b3 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt @@ -62,6 +62,7 @@ object KotlinPluginBuilder { "kotlin.base.fe10.highlighting", "kotlin.base.fe10.code-insight", "kotlin.base.fe10.obsolete-compat", + "kotlin.base.fe10.project-structure", "kotlin.core", "kotlin.idea", "kotlin.fir.frontend-independent", @@ -156,6 +157,7 @@ object KotlinPluginBuilder { "kotlin.features-trainer", "kotlin.base.fir.analysis-api-providers", "kotlin.base.fir.code-insight", + "kotlin.base.fir.project-structure", "kotlin.code-insight.api", "kotlin.code-insight.utils", "kotlin.code-insight.intentions-shared", diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 37474d6de0c7..556fa1d24c1b 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -21,14 +21,14 @@ import com.intellij.platform.workspace.jps.entities.ContentRootEntity import com.intellij.platform.workspace.jps.entities.LibraryEntity import com.intellij.platform.workspace.jps.entities.ModuleEntity import com.intellij.platform.workspace.jps.entities.SourceRootEntity -import com.intellij.util.io.URLUtil -import com.intellij.platform.backend.workspace.WorkspaceModelChangeListener -import com.intellij.workspaceModel.ide.impl.legacyBridge.library.findLibraryBridge -import com.intellij.workspaceModel.ide.impl.legacyBridge.module.findModule import com.intellij.platform.workspace.storage.EntityChange import com.intellij.platform.workspace.storage.EntityStorage import com.intellij.platform.workspace.storage.VersionedStorageChange import com.intellij.platform.workspace.storage.WorkspaceEntity +import com.intellij.util.io.URLUtil +import com.intellij.workspaceModel.ide.impl.legacyBridge.library.findLibraryBridge +import com.intellij.workspaceModel.ide.impl.legacyBridge.module.findModule +import org.jetbrains.annotations.ApiStatus import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.providers.KotlinGlobalModificationService import org.jetbrains.kotlin.analysis.providers.analysisMessageBus @@ -129,94 +129,91 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab } } - class ModelChangeListener(private val project: Project) : WorkspaceModelChangeListener { - private val moduleStateModificationService: KotlinModuleStateModificationService get() = getInstance(project) + @ApiStatus.Internal + fun beforeWorkspaceModelChanged(event: VersionedStorageChange) { + handleLibraryChanges(event) - override fun beforeChanged(event: VersionedStorageChange) { - handleLibraryChanges(event) + // We keep track of the already invalidated modules because we don't need `handleContentRootInModuleChanges` to publish another + // module state modification event for the same module. + val alreadyInvalidatedModules = handleModuleChanges(event) + handleContentRootInModuleChanges(event, alreadyInvalidatedModules) + } - // We keep track of the already invalidated modules because we don't need `handleContentRootInModuleChanges` to publish another - // module state modification event for the same module. - val alreadyInvalidatedModules = handleModuleChanges(event) - handleContentRootInModuleChanges(event, alreadyInvalidatedModules) + private fun handleContentRootInModuleChanges(event: VersionedStorageChange, alreadyInvalidatedModules: Set) { + for (changedModule in event.getChangedModules()) { + if (changedModule in alreadyInvalidatedModules) continue + invalidateSourceModule(changedModule) + } + } + + private fun VersionedStorageChange.getChangedModules(): Set = buildSet { + getChanges(ContentRootEntity::class.java).mapNotNullTo(this) { + getChangedModule(it.oldEntity, it.newEntity) } - private fun handleContentRootInModuleChanges(event: VersionedStorageChange, alreadyInvalidatedModules: Set) { - for (changedModule in event.getChangedModules()) { - if (changedModule in alreadyInvalidatedModules) continue - moduleStateModificationService.invalidateSourceModule(changedModule) - } + getChanges(SourceRootEntity::class.java).mapNotNullTo(this) { + getChangedModule(it.oldEntity?.contentRoot, it.newEntity?.contentRoot) } - private fun VersionedStorageChange.getChangedModules(): Set = buildSet { - getChanges(ContentRootEntity::class.java).mapNotNullTo(this) { - getChangedModule(it.oldEntity, it.newEntity) - } + getChanges(JavaSourceRootPropertiesEntity::class.java).mapNotNullTo(this) { + getChangedModule(it.oldEntity?.sourceRoot?.contentRoot, it.newEntity?.sourceRoot?.contentRoot) + } + } - getChanges(SourceRootEntity::class.java).mapNotNullTo(this) { - getChangedModule(it.oldEntity?.contentRoot, it.newEntity?.contentRoot) - } - - getChanges(JavaSourceRootPropertiesEntity::class.java).mapNotNullTo(this) { - getChangedModule(it.oldEntity?.sourceRoot?.contentRoot, it.newEntity?.sourceRoot?.contentRoot) + private fun VersionedStorageChange.getChangedModule( + contentRootBefore: ContentRootEntity?, + contentRootAfter: ContentRootEntity? + ): Module? { + val oldModule = contentRootBefore?.module?.findModule(storageBefore) + val newModule = contentRootAfter?.module?.findModule(storageAfter) + if (newModule != null && oldModule != null) { + check(oldModule == newModule) { + "$oldModule should be equal to $newModule for ${EntityChange.Replaced::class.java}" } } + return oldModule ?: newModule + } - private fun VersionedStorageChange.getChangedModule( - contentRootBefore: ContentRootEntity?, - contentRootAfter: ContentRootEntity? - ): Module? { - val oldModule = contentRootBefore?.module?.findModule(storageBefore) - val newModule = contentRootAfter?.module?.findModule(storageAfter) - if (newModule != null && oldModule != null) { - check(oldModule == newModule) { - "$oldModule should be equal to $newModule for ${EntityChange.Replaced::class.java}" + private fun handleLibraryChanges(event: VersionedStorageChange) { + val libraryEntities = event.getChanges(LibraryEntity::class.java).ifEmpty { return } + for (change in libraryEntities) { + when (change) { + is EntityChange.Added -> {} + is EntityChange.Removed -> { + change.oldEntity + .findLibraryBridge(event.storageBefore) + ?.let { invalidateLibraryModule(it, isRemoval = true) } + } + + is EntityChange.Replaced -> { + val changedLibrary = change.getReplacedEntity(event, LibraryEntity::findLibraryBridge) ?: continue + invalidateLibraryModule(changedLibrary) } } - return oldModule ?: newModule } + } - private fun handleLibraryChanges(event: VersionedStorageChange) { - val libraryEntities = event.getChanges(LibraryEntity::class.java).ifEmpty { return } - for (change in libraryEntities) { + /** + * Invalidates removed and replaced [Module]s and returns the set of these invalidated modules. + */ + private fun handleModuleChanges(event: VersionedStorageChange): Set { + val moduleEntities = event.getChanges(ModuleEntity::class.java).ifEmpty { return emptySet() } + + return buildSet { + for (change in moduleEntities) { when (change) { is EntityChange.Added -> {} is EntityChange.Removed -> { - change.oldEntity - .findLibraryBridge(event.storageBefore) - ?.let { moduleStateModificationService.invalidateLibraryModule(it, isRemoval = true) } + change.oldEntity.findModule(event.storageBefore)?.let { module -> + invalidateSourceModule(module, isRemoval = true) + add(module) + } } is EntityChange.Replaced -> { - val changedLibrary = change.getReplacedEntity(event, LibraryEntity::findLibraryBridge) ?: continue - moduleStateModificationService.invalidateLibraryModule(changedLibrary) - } - } - } - } - - /** - * Invalidates removed and replaced [Module]s and returns the set of these invalidated modules. - */ - private fun handleModuleChanges(event: VersionedStorageChange): Set { - val moduleEntities = event.getChanges(ModuleEntity::class.java).ifEmpty { return emptySet() } - - return buildSet { - for (change in moduleEntities) { - when (change) { - is EntityChange.Added -> {} - is EntityChange.Removed -> { - change.oldEntity.findModule(event.storageBefore)?.let { module -> - moduleStateModificationService.invalidateSourceModule(module, isRemoval = true) - add(module) - } - } - - is EntityChange.Replaced -> { - val changedModule = change.getReplacedEntity(event, ModuleEntity::findModule) ?: continue - moduleStateModificationService.invalidateSourceModule(changedModule) - add(changedModule) - } + val changedModule = change.getReplacedEntity(event, ModuleEntity::findModule) ?: continue + invalidateSourceModule(changedModule) + add(changedModule) } } } diff --git a/plugins/kotlin/base/fe10/project-structure/kotlin.base.fe10.project-structure.iml b/plugins/kotlin/base/fe10/project-structure/kotlin.base.fe10.project-structure.iml new file mode 100644 index 000000000000..39dbeae67f48 --- /dev/null +++ b/plugins/kotlin/base/fe10/project-structure/kotlin.base.fe10.project-structure.iml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/kotlin/base/fe10/project-structure/resources/kotlin.base.fe10.project-structure.xml b/plugins/kotlin/base/fe10/project-structure/resources/kotlin.base.fe10.project-structure.xml new file mode 100644 index 000000000000..9068adc0c269 --- /dev/null +++ b/plugins/kotlin/base/fe10/project-structure/resources/kotlin.base.fe10.project-structure.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/plugins/kotlin/base/fe10/project-structure/src/org/jetbrains/kotlin/idea/base/fe10/projectStructure/Fe10OrderedWorkspaceModelChangeListener.kt b/plugins/kotlin/base/fe10/project-structure/src/org/jetbrains/kotlin/idea/base/fe10/projectStructure/Fe10OrderedWorkspaceModelChangeListener.kt new file mode 100644 index 000000000000..ada1794dbe9b --- /dev/null +++ b/plugins/kotlin/base/fe10/project-structure/src/org/jetbrains/kotlin/idea/base/fe10/projectStructure/Fe10OrderedWorkspaceModelChangeListener.kt @@ -0,0 +1,17 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.base.fe10.projectStructure + +import com.intellij.openapi.components.serviceIfCreated +import com.intellij.openapi.project.Project +import com.intellij.platform.backend.workspace.WorkspaceModelChangeListener +import com.intellij.platform.workspace.storage.VersionedStorageChange +import org.jetbrains.kotlin.idea.base.projectStructure.LibraryInfoCache + +/** + * See `FirOrderedWorkspaceModelChangeListener` for why this workspace model listener exists. + */ +internal class Fe10OrderedWorkspaceModelChangeListener(private val project: Project) : WorkspaceModelChangeListener { + override fun beforeChanged(event: VersionedStorageChange) { + project.serviceIfCreated()?.beforeWorkspaceModelChanged(event) + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml index 818944eeda07..be62e3a1053f 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml +++ b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml @@ -24,8 +24,6 @@ topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/> - diff --git a/plugins/kotlin/base/fir/project-structure/kotlin.base.fir.project-structure.iml b/plugins/kotlin/base/fir/project-structure/kotlin.base.fir.project-structure.iml new file mode 100644 index 000000000000..f11ffa14cf47 --- /dev/null +++ b/plugins/kotlin/base/fir/project-structure/kotlin.base.fir.project-structure.iml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/kotlin/base/fir/project-structure/resources/kotlin.base.fir.project-structure.xml b/plugins/kotlin/base/fir/project-structure/resources/kotlin.base.fir.project-structure.xml new file mode 100644 index 000000000000..434401a915ad --- /dev/null +++ b/plugins/kotlin/base/fir/project-structure/resources/kotlin.base.fir.project-structure.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/plugins/kotlin/base/fir/project-structure/src/org/jetbrains/kotlin/idea/base/fir/projectStructure/FirOrderedWorkspaceModelChangeListener.kt b/plugins/kotlin/base/fir/project-structure/src/org/jetbrains/kotlin/idea/base/fir/projectStructure/FirOrderedWorkspaceModelChangeListener.kt new file mode 100644 index 000000000000..5372b881b02c --- /dev/null +++ b/plugins/kotlin/base/fir/project-structure/src/org/jetbrains/kotlin/idea/base/fir/projectStructure/FirOrderedWorkspaceModelChangeListener.kt @@ -0,0 +1,37 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.base.fir.projectStructure + +import com.intellij.openapi.components.serviceIfCreated +import com.intellij.openapi.project.Project +import com.intellij.platform.backend.workspace.WorkspaceModelChangeListener +import com.intellij.platform.workspace.storage.VersionedStorageChange +import org.jetbrains.kotlin.idea.base.analysisApiProviders.KotlinModuleStateModificationService +import org.jetbrains.kotlin.idea.base.projectStructure.LibraryInfoCache + +/** + * [FirOrderedWorkspaceModelChangeListener] delegates to other components which process workspace model change events in a pre-defined + * order. + */ +internal class FirOrderedWorkspaceModelChangeListener(private val project: Project) : WorkspaceModelChangeListener { + override fun beforeChanged(event: VersionedStorageChange) { + KotlinModuleStateModificationService.getInstance(project).beforeWorkspaceModelChanged(event) + + // `LibraryInfoCache` is ordered last so that other listeners can still access `LibraryInfo`s before they might be invalidated in + // the context of the current event. If `LibraryInfoCache`'s invalidation was ordered first, the following hypothetical situation + // might occur: + // + // 1. A root is added to some library `L` and `FirOrderedWorkspaceModelChangeListener.beforeChanged` is called. + // 2. `LibraryInfoCache` receives the "before change" event and removes the library info for `L` from its cache. + // 3. `KotlinModuleStateModificationService` processes the same library change event. To publish a module state modification event + // for the `KtModule` of `L`, `KotlinModuleStateModificationService` accesses `LibraryInfoCache` to get `L`'s library infos. + // 4. Because `LibraryInfoCache` has already thrown away the library info for `L`, the cache returns a new `LibraryInfo`. + // 5. `LibraryInfo`s are referentially equal, so `KotlinModuleStateModificationService` publishes a module state modification event + // for a `KtModule` based on a *new* `LibraryInfo`. + // 6. The session invalidation service receives the module state modification event for the `KtModule`, but doesn't invalidate any + // sessions, because the new `LibraryInfo` key doesn't match the old `LibraryInfo` key still used in session hash maps. + // + // In the worst case, this will cause session invalidation to skip invalidation for all dependent modules as well, because it might + // think that `L` has already been invalidated. + project.serviceIfCreated()?.beforeWorkspaceModelChanged(event) + } +} diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/LibraryInfoCache.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/LibraryInfoCache.kt index f7e96f17a35c..e081ac8df451 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/LibraryInfoCache.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/LibraryInfoCache.kt @@ -12,15 +12,13 @@ import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.ModificationTracker import com.intellij.openapi.util.SimpleModificationTracker -import com.intellij.platform.workspace.storage.VersionedStorageChange import com.intellij.platform.workspace.jps.entities.LibraryEntity import com.intellij.platform.workspace.jps.entities.ModuleDependencyItem import com.intellij.platform.workspace.jps.entities.ModuleEntity +import com.intellij.platform.workspace.storage.VersionedStorageChange import com.intellij.serviceContainer.AlreadyDisposedException import com.intellij.util.PathUtil import com.intellij.util.messages.Topic -import com.intellij.platform.backend.workspace.WorkspaceModelChangeListener -import com.intellij.platform.backend.workspace.WorkspaceModelTopics import com.intellij.workspaceModel.ide.impl.legacyBridge.library.findLibraryBridge import org.jetbrains.annotations.ApiStatus import org.jetbrains.kotlin.idea.base.platforms.detectLibraryKind @@ -31,11 +29,7 @@ import org.jetbrains.kotlin.idea.base.util.caching.SynchronizedFineGrainedEntity import org.jetbrains.kotlin.platform.IdePlatformKind import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.idePlatformKind -import org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind -import org.jetbrains.kotlin.platform.impl.JsIdePlatformKind -import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind -import org.jetbrains.kotlin.platform.impl.NativeIdePlatformKind -import org.jetbrains.kotlin.platform.impl.WasmIdePlatformKind +import org.jetbrains.kotlin.platform.impl.* import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments import org.jetbrains.kotlin.utils.addIfNotNull @@ -60,9 +54,15 @@ class LibraryInfoCache(project: Project) : Disposable { initialize() } - override fun subscribe() { - project.messageBus.connect(this).subscribe(WorkspaceModelTopics.CHANGED, ModelChangeListener(project)) - } + // Due to ordering issues with other workspace model listeners that access `LibraryInfoCache`, workspace model changes for + // `LibraryInfoCache` are listened to via `FirOrderedWorkspaceModelChangeListener` and `FE10IdeOrderedWorkspaceModelChangeListener`. + // Note that, even if the order was insignificant, `LibraryInfoCache`'s workspace model listener would still need to be registered + // eagerly. The reason is that some other workspace model listener might access `LibraryInfoCache` and cause first-time + // initialization (including a call to `subscribe`). Subscribing to workspace model events while a workspace model event is being + // processed means that that event won't be propagated to the new subscription. Hence, for exactly that event, `LibraryInfoCache` + // would not be cleared, as its workspace model listener wouldn't be called. This can lead to cache inconsistency if a cache entry + // containing a changing library was added during that event by some other workspace listener. + override fun subscribe() { } override fun doInvalidate(cache: MutableMap>) { super.doInvalidate(cache) @@ -314,42 +314,40 @@ class LibraryInfoCache(project: Project) : Disposable { JvmPlatforms.defaultJvmPlatform } - inner class ModelChangeListener(project: Project) : WorkspaceModelChangeListener { - override fun beforeChanged(event: VersionedStorageChange) { - val storageBefore = event.storageBefore - val libraryChanges = event.getChanges(LibraryEntity::class.java) - val moduleChanges = event.getChanges(ModuleEntity::class.java) + fun beforeWorkspaceModelChanged(event: VersionedStorageChange) { + val storageBefore = event.storageBefore + val libraryChanges = event.getChanges(LibraryEntity::class.java) + val moduleChanges = event.getChanges(ModuleEntity::class.java) - if (libraryChanges.none() && moduleChanges.none()) return + if (libraryChanges.none() && moduleChanges.none()) return - val outdatedLibraries: MutableList = libraryChanges - .mapNotNull { it.oldEntity?.findLibraryBridge(storageBefore) } - .toMutableList() + val outdatedLibraries: MutableList = libraryChanges + .mapNotNull { it.oldEntity?.findLibraryBridge(storageBefore) } + .toMutableList() - val oldLibDependencies = moduleChanges.mapNotNull { - it.oldEntity?.dependencies?.filterIsInstance() - }.flatten().associateBy { it.library } + val oldLibDependencies = moduleChanges.mapNotNull { + it.oldEntity?.dependencies?.filterIsInstance() + }.flatten().associateBy { it.library } - val newLibDependencies = moduleChanges.mapNotNull { - it.newEntity?.dependencies?.filterIsInstance() - }.flatten().associateBy { it.library } + val newLibDependencies = moduleChanges.mapNotNull { + it.newEntity?.dependencies?.filterIsInstance() + }.flatten().associateBy { it.library } - for (entry in oldLibDependencies.entries) { - val value = entry.value - if (value != newLibDependencies[entry.key]) { - val libraryBridge = value.library.findLibraryBridge(storageBefore, project) - outdatedLibraries.addIfNotNull(libraryBridge) - } + for (entry in oldLibDependencies.entries) { + val value = entry.value + if (value != newLibDependencies[entry.key]) { + val libraryBridge = value.library.findLibraryBridge(storageBefore, project) + outdatedLibraries.addIfNotNull(libraryBridge) } + } - if (outdatedLibraries.isNotEmpty()) { - val droppedLibraryInfos = - invalidateKeysAndGetOutdatedValues(outdatedLibraries.map { it as LibraryEx }).flattenTo(hashSetOf()) + if (outdatedLibraries.isNotEmpty()) { + val droppedLibraryInfos = + invalidateKeysAndGetOutdatedValues(outdatedLibraries.map { it as LibraryEx }).flattenTo(hashSetOf()) - if (droppedLibraryInfos.isNotEmpty()) { - removedLibraryInfoTracker.incModificationCount() - project.messageBus.syncPublisher(LibraryInfoListener.TOPIC).libraryInfosRemoved(droppedLibraryInfos) - } + if (droppedLibraryInfos.isNotEmpty()) { + removedLibraryInfoTracker.incModificationCount() + project.messageBus.syncPublisher(LibraryInfoListener.TOPIC).libraryInfosRemoved(droppedLibraryInfos) } } } @@ -362,6 +360,11 @@ class LibraryInfoCache(project: Project) : Disposable { fun deduplicatedLibrary(key: Library): Library = get(key).first().library + @ApiStatus.Internal + fun beforeWorkspaceModelChanged(event: VersionedStorageChange) { + libraryInfoCache.beforeWorkspaceModelChanged(event) + } + override fun dispose() = Unit fun removedLibraryInfoTracker(): ModificationTracker = libraryInfoCache.removedLibraryInfoTracker diff --git a/plugins/kotlin/intellij.kotlin.plugin.community.main.iml b/plugins/kotlin/intellij.kotlin.plugin.community.main.iml index 7e83a19feea0..dbe52f8d8698 100644 --- a/plugins/kotlin/intellij.kotlin.plugin.community.main.iml +++ b/plugins/kotlin/intellij.kotlin.plugin.community.main.iml @@ -39,8 +39,10 @@ + + diff --git a/plugins/kotlin/plugin/k1/kotlin.plugin.k1.iml b/plugins/kotlin/plugin/k1/kotlin.plugin.k1.iml index 8d586e31619c..8ef5588d3540 100644 --- a/plugins/kotlin/plugin/k1/kotlin.plugin.k1.iml +++ b/plugins/kotlin/plugin/k1/kotlin.plugin.k1.iml @@ -45,6 +45,7 @@ + diff --git a/plugins/kotlin/plugin/k1/resources/META-INF/k1.xml b/plugins/kotlin/plugin/k1/resources/META-INF/k1.xml index 549f653ffe1f..2e491919e851 100644 --- a/plugins/kotlin/plugin/k1/resources/META-INF/k1.xml +++ b/plugins/kotlin/plugin/k1/resources/META-INF/k1.xml @@ -46,6 +46,7 @@ + diff --git a/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml b/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml index 5b18ad546f85..be823a0c8345 100644 --- a/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml +++ b/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml @@ -72,6 +72,7 @@ + diff --git a/plugins/kotlin/plugin/k2/resources/META-INF/k2.xml b/plugins/kotlin/plugin/k2/resources/META-INF/k2.xml index 009a9d2b4bd9..75e2e2ee5090 100644 --- a/plugins/kotlin/plugin/k2/resources/META-INF/k2.xml +++ b/plugins/kotlin/plugin/k2/resources/META-INF/k2.xml @@ -208,6 +208,8 @@ + + From c6a67b74b52f3fa91b15abd7f88fbfa157974b89 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Mon, 26 Jun 2023 23:44:44 +0200 Subject: [PATCH 034/165] [kotlin] KT-58257 Add a root to project libraries in tests - `LibraryInfoCache` deduplicates libraries based on their roots, so two libraries with different names but no roots are effectively the same in tests, which breaks some tests. (This affects library module state modification tests, which will be added in the next commit.) - In addition to breaking tests, the deduplication actually is an issue for the module dependents provider, but that issue will be tackled separate. GitOrigin-RevId: 064451550b6058f9a47c7a36a9703685d4e63118 --- .../providers/AbstractProjectStructureTest.kt | 6 +++--- .../kotlin/idea/test/ConfigLibraryUtil.kt | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt index 4daeccedd8b2..8f7a30e6c240 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt @@ -6,11 +6,11 @@ import com.intellij.openapi.module.Module import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.testFramework.PsiTestUtil -import java.nio.file.Paths import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.TestProjectStructureReader import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import org.jetbrains.kotlin.test.util.addDependency +import java.nio.file.Paths typealias ProjectLibrariesByNames = Map typealias ModulesByNames = Map @@ -26,7 +26,7 @@ abstract class AbstractProjectStructureTest : Abstract ) val projectLibrariesByNames = testStructure.libraries.associate { libraryData -> - libraryData.name to createEmptyProjectLibrary(libraryData.name) + libraryData.name to createProjectLibrary(libraryData.name) } val modulesByNames = testStructure.modules.associate { moduleData -> @@ -50,7 +50,7 @@ abstract class AbstractProjectStructureTest : Abstract return Triple(testStructure, projectLibrariesByNames, modulesByNames) } - private fun createEmptyProjectLibrary(name: String): Library = ConfigLibraryUtil.addProjectLibrary(project, name) { } + private fun createProjectLibrary(name: String): Library = ConfigLibraryUtil.addProjectLibraryWithClassesRoot(project, name) private fun createEmptyModule(name: String): Module { val tmpDir = createTempDirectory().toPath() diff --git a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt index dc734505ebbe..c1b153575fb8 100644 --- a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt +++ b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt @@ -19,6 +19,7 @@ import com.intellij.openapi.roots.libraries.PersistentLibraryKind import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor import com.intellij.openapi.vfs.VfsUtil import com.intellij.util.PathUtil +import com.intellij.util.io.jarFile import org.jetbrains.kotlin.idea.base.platforms.KotlinCommonLibraryKind import org.jetbrains.kotlin.idea.base.platforms.KotlinJavaScriptLibraryKind import org.jetbrains.kotlin.idea.base.plugin.artifacts.TestKotlinArtifacts @@ -119,6 +120,14 @@ object ConfigLibraryUtil { } } + fun addProjectLibraryWithClassesRoot(project: Project, name: String): Library = runWriteAction { + addProjectLibrary(project, name) { + // Add a unique root to avoid deduplication of library infos in tests (see `LibraryInfoCache`). + addEmptyClassesRoot() + commit() + } + } + fun addLibrary(module: Module, name: String, kind: PersistentLibraryKind<*>? = null, init: Library.ModifiableModel.() -> Unit) { runWriteAction { ModuleRootManager.getInstance(module).modifiableModel.apply { @@ -235,4 +244,9 @@ object ConfigLibraryUtil { fun Library.ModifiableModel.addRoot(file: File, kind: OrderRootType) { addRoot(VfsUtil.getUrlForLibraryRoot(file), kind) -} \ No newline at end of file +} + +fun Library.ModifiableModel.addEmptyClassesRoot() { + val jarFile = jarFile { }.generateInTempDir() + addRoot(jarFile.toFile(), OrderRootType.CLASSES) +} From aca1edf101cff947bfa1341d70adf6130c8493a0 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Mon, 26 Jun 2023 23:47:30 +0200 Subject: [PATCH 035/165] [kotlin] KT-58257 Add library module state modification tests GitOrigin-RevId: 10b0dae6dae21b249eccee2063ce5ca665339a48 --- .../KotlinModuleStateModificationTest.kt | 68 +++++++++++++++++++ .../kotlin/idea/test/ConfigLibraryUtil.kt | 6 ++ 2 files changed, 74 insertions(+) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt index 0d57844ffcb8..8ffaeb11cede 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt @@ -2,8 +2,11 @@ package org.jetbrains.kotlin.idea.fir.analysis.providers.modificationEvents import com.intellij.openapi.Disposable +import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.roots.OrderRootType +import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.util.Disposer import com.intellij.testFramework.PsiTestUtil import org.jetbrains.kotlin.analysis.project.structure.KtModule @@ -11,12 +14,15 @@ import org.jetbrains.kotlin.analysis.providers.analysisMessageBus import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleStateModificationListener import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics import org.jetbrains.kotlin.idea.base.plugin.artifacts.TestKotlinArtifacts +import org.jetbrains.kotlin.idea.base.projectStructure.LibraryInfoCache import org.jetbrains.kotlin.idea.base.projectStructure.productionSourceInfo import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil +import org.jetbrains.kotlin.idea.test.addEmptyClassesRoot import org.junit.Assert import java.io.File +import org.jetbrains.kotlin.test.util.addDependency class KotlinModuleStateModificationTest : AbstractMultiModuleTest() { override fun isFirPlugin(): Boolean = true @@ -175,10 +181,72 @@ class KotlinModuleStateModificationTest : AbstractMultiModuleTest() { disposeTrackers(trackerA, trackerB, trackerC) } + fun `test library module state modification after root replacement`() { + val libraryA = createProjectLibrary("a") + val libraryB = createProjectLibrary("b") + val moduleC = createModuleInTmpDir("c") + val moduleD = createModuleInTmpDir("d") + + moduleC.addDependency(libraryA) + moduleC.addDependency(libraryB) + + val trackerA = createTracker(libraryA) + val trackerB = createTracker(libraryB) + val trackerC = createTracker(moduleC) + val trackerD = createTracker(moduleD) + + libraryA.swapRoot() + + trackerA.assertModifiedOnce("project library A with replaced root") + trackerB.assertNotModified("unchanged library B") + trackerC.assertNotModified("unchanged module C") + trackerD.assertNotModified("unchanged module D") + + disposeTrackers(trackerA, trackerB, trackerC, trackerD) + } + + private fun Library.swapRoot() = runWriteAction { + val existingRootUrl = rootProvider.getUrls(OrderRootType.CLASSES)[0]!! + modifiableModel.apply { + removeRoot(existingRootUrl, OrderRootType.CLASSES) + addEmptyClassesRoot() + commit() + } + } + + fun `test library module state modification after removal`() { + val libraryA = createProjectLibrary("a") + val libraryB = createProjectLibrary("b") + val moduleC = createModuleInTmpDir("c") + val moduleD = createModuleInTmpDir("d") + + moduleC.addDependency(libraryA) + moduleC.addDependency(libraryB) + + val trackerA = createTracker(libraryA) + val trackerB = createTracker(libraryB) + val trackerC = createTracker(moduleC) + val trackerD = createTracker(moduleD) + + ConfigLibraryUtil.removeProjectLibrary(myProject, libraryA) + + trackerA.assertModifiedOnce("removed project library A", shouldBeRemoval = true) + trackerB.assertNotModified("unchanged library B") + trackerC.assertNotModified("unchanged module C") + trackerD.assertNotModified("unchanged module D") + + disposeTrackers(trackerA, trackerB, trackerC, trackerD) + } + + private fun createProjectLibrary(name: String): Library = ConfigLibraryUtil.addProjectLibraryWithClassesRoot(myProject, name) + private fun createTracker(module: KtModule): ModuleStateModificationTracker = ModuleStateModificationTracker(module) private fun createTracker(module: Module): ModuleStateModificationTracker = createTracker(module.productionSourceInfo!!.toKtModule()) + private fun createTracker(library: Library): ModuleStateModificationTracker = + createTracker(LibraryInfoCache.getInstance(myProject)[library].single().toKtModule()) + private fun disposeTrackers(vararg trackers: ModuleStateModificationTracker) { trackers.forEach { Disposer.dispose(it) } } diff --git a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt index c1b153575fb8..7329af302655 100644 --- a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt +++ b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt @@ -128,6 +128,12 @@ object ConfigLibraryUtil { } } + fun removeProjectLibrary(project: Project, library: Library) { + runWriteAction { + LibraryTablesRegistrar.getInstance().getLibraryTable(project).removeLibrary(library) + } + } + fun addLibrary(module: Module, name: String, kind: PersistentLibraryKind<*>? = null, init: Library.ModifiableModel.() -> Unit) { runWriteAction { ModuleRootManager.getInstance(module).modifiableModel.apply { From 19b4939130b3072c228110e700877c8fd6f3d331 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 27 Jun 2023 18:53:26 +0200 Subject: [PATCH 036/165] [kotlin] KT-58257 Handle single-file module file move events before the file is moved - As explained in the comment of `SingleFileModuleModificationListener`, move events have to be handled before the file is moved because the file might be moved out of the project's content root, which would lead the listener to skip the event. - This is also more consistent with file deletion, which was already handled before the deletion. GitOrigin-RevId: 408147db93c51bda89f874e2b574cbd4601cdb40 --- .../KotlinModuleStateModificationService.kt | 35 +++++-------------- ...kotlin.base.fir.analysis-api-providers.xml | 4 +-- 2 files changed, 9 insertions(+), 30 deletions(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 556fa1d24c1b..8b87133de02e 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -37,7 +37,6 @@ import org.jetbrains.kotlin.idea.base.projectStructure.getBinaryAndSourceModuleI import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.IdeaModuleInfo import org.jetbrains.kotlin.idea.base.projectStructure.productionOrTestSourceModuleInfo import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule -import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleAfterFileEventListener import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleBeforeFileEventListener open class KotlinModuleStateModificationService(val project: Project) : Disposable { @@ -60,39 +59,21 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab } /** - * Publishes a module state modification event for a script or not-under-content-root [KtModule] whose file has been moved. + * Publishes a module state modification event for a script or not-under-content-root [KtModule] whose file is being moved or deleted. * - * Even though the event is processed *after* the file has been moved, the [KtModule]s before and after the move are equal via their - * respective module infos, because: + * This listener processes events *before* the file is moved/deleted due to the following reasons: * - * - In the case of `NotUnderContentRootModuleInfo`, the file pointer remains the same after the move. - * - In the case of `ScriptModuleInfo`, the virtual file and script definition remain the same after the move. + * 1. Move: The file may be moved outside the project's content root. The listener cannot react to such files. + * 2. Deletion: Getting a PSI file (and in turn the PSI file's [KtModule]) for a virtual file which has been deleted is not feasible. * - * A global out-of-block modification event will be published by `FirIdeOutOfBlockPsiTreeChangePreprocessor` after a Kotlin file is + * A global out-of-block modification event will be published by `FirIdeOutOfBlockPsiTreeChangePreprocessor` when a Kotlin file is * moved, but we still need this listener to publish a module state modification event specifically. */ - class SingleFileModuleMoveListener(private val project: Project) : AbstractSingleFileModuleAfterFileEventListener(project) { - override fun isRelevantEvent(event: VFileEvent, file: VirtualFile): Boolean = event is VFileMoveEvent + class SingleFileModuleModificationListener(private val project: Project) : AbstractSingleFileModuleBeforeFileEventListener(project) { + override fun isRelevantEvent(event: VFileEvent, file: VirtualFile): Boolean = event is VFileMoveEvent || event is VFileDeleteEvent override fun processEvent(event: VFileEvent, module: KtModule) { - project.publishModuleStateModification(module, isRemoval = false) - } - } - - /** - * Publishes a module state modification event for a script or not-under-content-root [KtModule] whose file has been deleted. - * - * This listener processes events *before* the file is deleted, because getting a PSI file (and in turn the PSI file's [KtModule]) for a - * virtual file which has already been deleted is not feasible. - * - * A global out-of-block modification event will be published by `FirIdeOutOfBlockPsiTreeChangePreprocessor` after a Kotlin file is - * deleted, but we still need this listener to publish a module state modification event specifically. - */ - class SingleFileModuleDeletionListener(private val project: Project) : AbstractSingleFileModuleBeforeFileEventListener(project) { - override fun isRelevantEvent(event: VFileEvent, file: VirtualFile): Boolean = event is VFileDeleteEvent - - override fun processEvent(event: VFileEvent, module: KtModule) { - project.publishModuleStateModification(module, isRemoval = true) + project.publishModuleStateModification(module, isRemoval = event is VFileDeleteEvent) } } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml index be62e3a1053f..221c0bd73f81 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml +++ b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml @@ -16,9 +16,7 @@ - - From af25f063a1c67833716db88c2e63909c79360a96 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 27 Jun 2023 18:54:46 +0200 Subject: [PATCH 037/165] [kotlin] KT-58257 Add script module state modification tests GitOrigin-RevId: 2f2c1592407c81a4eb160e91a767079fb16f23b2 --- .../KotlinModuleStateModificationTest.kt | 82 +++++++++++++++++++ .../idea/stubs/AbstractMultiModuleTest.kt | 18 +++- 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt index 8ffaeb11cede..a574bd23167b 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt @@ -10,6 +10,7 @@ import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.util.Disposer import com.intellij.testFramework.PsiTestUtil import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.analysis.providers.analysisMessageBus import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleStateModificationListener import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics @@ -20,6 +21,7 @@ import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import org.jetbrains.kotlin.idea.test.addEmptyClassesRoot +import org.jetbrains.kotlin.psi.KtFile import org.junit.Assert import java.io.File import org.jetbrains.kotlin.test.util.addDependency @@ -238,8 +240,85 @@ class KotlinModuleStateModificationTest : AbstractMultiModuleTest() { disposeTrackers(trackerA, trackerB, trackerC, trackerD) } + fun `test script module state modification after moving the script file to another module`() { + val scriptA = createScript("a") + val scriptB = createScript("b") + val libraryC = createProjectLibrary("c") + val moduleD = createModuleInTmpDir("d") + val moduleE = createModuleInTmpDir("e") + + val destination = getVirtualFile(createTempDirectory()) + PsiTestUtil.addContentRoot(moduleE, destination) + + val trackerA = createTracker(scriptA) + val trackerB = createTracker(scriptB) + val trackerC = createTracker(libraryC) + val trackerD = createTracker(moduleD) + val trackerE = createTracker(moduleE) + + move(scriptA.virtualFile, destination) + + trackerA.assertModifiedOnce("moved script A") + trackerB.assertNotModified("unchanged script B") + trackerC.assertNotModified("unchanged library C") + trackerD.assertNotModified("unchanged module D") + + // The file move will cause a global PSI tree change event, and thereby a global out-of-block modification event, but the module + // state of the destination module E is not affected by a file move, so the tracker should not register any module state + // modification events. + trackerE.assertNotModified("unchanged destination module E") + + disposeTrackers(trackerA, trackerB, trackerC, trackerD, trackerE) + } + + fun `test script module state modification after moving the script file outside the content root`() { + val scriptA = createScript("a") + val scriptB = createScript("b") + val libraryC = createProjectLibrary("c") + val moduleD = createModuleInTmpDir("d") + + val destination = getVirtualFile(createTempDirectory()) + + val trackerA = createTracker(scriptA) + val trackerB = createTracker(scriptB) + val trackerC = createTracker(libraryC) + val trackerD = createTracker(moduleD) + + move(scriptA.virtualFile, destination) + + trackerA.assertModifiedOnce("moved script A") + trackerB.assertNotModified("unchanged script B") + trackerC.assertNotModified("unchanged library C") + trackerD.assertNotModified("unchanged module D") + + disposeTrackers(trackerA, trackerB, trackerC, trackerD) + } + + fun `test script module state modification after deleting the script file`() { + val scriptA = createScript("a") + val scriptB = createScript("b") + val libraryC = createProjectLibrary("c") + val moduleD = createModuleInTmpDir("d") + + val trackerA = createTracker(scriptA) + val trackerB = createTracker(scriptB) + val trackerC = createTracker(libraryC) + val trackerD = createTracker(moduleD) + + delete(scriptA.virtualFile) + + trackerA.assertModifiedOnce("deleted script A", shouldBeRemoval = true) + trackerB.assertNotModified("unchanged script B") + trackerC.assertNotModified("unchanged library C") + trackerD.assertNotModified("unchanged module D") + + disposeTrackers(trackerA, trackerB, trackerC, trackerD) + } + private fun createProjectLibrary(name: String): Library = ConfigLibraryUtil.addProjectLibraryWithClassesRoot(myProject, name) + private fun createScript(name: String): KtFile = createKtFileUnderNewContentRoot(FileWithText("$name.kts", "")) + private fun createTracker(module: KtModule): ModuleStateModificationTracker = ModuleStateModificationTracker(module) private fun createTracker(module: Module): ModuleStateModificationTracker = createTracker(module.productionSourceInfo!!.toKtModule()) @@ -247,6 +326,9 @@ class KotlinModuleStateModificationTest : AbstractMultiModuleTest() { private fun createTracker(library: Library): ModuleStateModificationTracker = createTracker(LibraryInfoCache.getInstance(myProject)[library].single().toKtModule()) + private fun createTracker(file: KtFile): ModuleStateModificationTracker = + createTracker(ProjectStructureProvider.getModule(myProject, file, contextualModule = null)) + private fun disposeTrackers(vararg trackers: ModuleStateModificationTracker) { trackers.forEach { Disposer.dispose(it) } } diff --git a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt index 400b58e8b99b..79e4a26fea27 100644 --- a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt +++ b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt @@ -25,6 +25,7 @@ import com.intellij.util.ThrowableRunnable import org.jetbrains.kotlin.config.CompilerSettings import org.jetbrains.kotlin.config.KotlinFacetSettings import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider +import org.jetbrains.kotlin.idea.core.util.toPsiFile import org.jetbrains.kotlin.idea.facet.getOrCreateFacet import org.jetbrains.kotlin.idea.facet.initializeIfNeeded import org.jetbrains.kotlin.idea.test.* @@ -32,9 +33,9 @@ import org.jetbrains.kotlin.idea.test.KotlinTestUtils.allowProjectRootAccess import org.jetbrains.kotlin.idea.test.KotlinTestUtils.disposeVfsRootAccess import org.jetbrains.kotlin.idea.test.util.slashedPath import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.psi.KtFile import org.junit.Assert import java.io.File -import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.* @@ -99,7 +100,6 @@ abstract class AbstractMultiModuleTest : DaemonAnalyzerTestCase() { protected data class FileWithText(val name: String, val text: String) - override fun tearDown() { runAll( ThrowableRunnable { disposeVfsRootAccess(vfsDisposable) }, @@ -188,6 +188,20 @@ abstract class AbstractMultiModuleTest : DaemonAnalyzerTestCase() { facetSettings.useProjectSettings = false } + protected fun createKtFileUnderNewContentRoot(fileWithText: FileWithText): KtFile { + val tmpDir = createTempDirectory().toPath() + + // We need to add the script to a module so that it's part of the project's content root. + val containingModule = createModule(tmpDir, moduleType) + PsiTestUtil.addContentRoot(containingModule, getVirtualFile(tmpDir.toFile())) + + val filePath = tmpDir / fileWithText.name + filePath.writeText(fileWithText.text) + + val file = getVirtualFile(filePath.toFile()) + return file.toPsiFile(project)!! as KtFile + } + protected fun checkFiles( findFiles: () -> List, check: () -> Unit From 3bd9a444e51d2ad01de2567d2313fb1be1cc0141 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 27 Jun 2023 19:06:08 +0200 Subject: [PATCH 038/165] [kotlin] KT-58257 Add not-under-content-root file module state modification tests GitOrigin-RevId: 823c00da0e54037c3ffd1c5f81a11fb46674036a --- .../KotlinModuleStateModificationTest.kt | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt index a574bd23167b..6de8e087403a 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt @@ -315,10 +315,90 @@ class KotlinModuleStateModificationTest : AbstractMultiModuleTest() { disposeTrackers(trackerA, trackerB, trackerC, trackerD) } + fun `test not-under-content-root module state modification after moving the file to another module`() { + val fileA = createNotUnderContentRootFile("a") + val fileB = createNotUnderContentRootFile("b") + val libraryC = createProjectLibrary("c") + val moduleD = createModuleInTmpDir("d") + val moduleE = createModuleInTmpDir("e") + + val destination = getVirtualFile(createTempDirectory()) + PsiTestUtil.addContentRoot(moduleE, destination) + + val trackerA = createTracker(fileA) + val trackerB = createTracker(fileB) + val trackerC = createTracker(libraryC) + val trackerD = createTracker(moduleD) + val trackerE = createTracker(moduleE) + + move(fileA.virtualFile, destination) + + trackerA.assertModifiedOnce("moved not-under-content-root file A") + trackerB.assertNotModified("unchanged not-under-content-root file B") + trackerC.assertNotModified("unchanged library C") + trackerD.assertNotModified("unchanged module D") + + // The file move will cause a global PSI tree change event, and thereby a global out-of-block modification event, but the module + // state of the destination module E is not affected by a file move, so the tracker should not register any module state + // modification events. + trackerE.assertNotModified("unchanged destination module E") + + disposeTrackers(trackerA, trackerB, trackerC, trackerD, trackerE) + } + + fun `test not-under-content-root module state modification after moving the file outside the content root`() { + val fileA = createNotUnderContentRootFile("a") + val fileB = createNotUnderContentRootFile("b") + val libraryC = createProjectLibrary("c") + val moduleD = createModuleInTmpDir("d") + + val destination = getVirtualFile(createTempDirectory()) + + val trackerA = createTracker(fileA) + val trackerB = createTracker(fileB) + val trackerC = createTracker(libraryC) + val trackerD = createTracker(moduleD) + + move(fileA.virtualFile, destination) + + trackerA.assertModifiedOnce("moved not-under-content-root file A") + trackerB.assertNotModified("unchanged not-under-content-root file B") + trackerC.assertNotModified("unchanged library C") + trackerD.assertNotModified("unchanged module D") + + disposeTrackers(trackerA, trackerB, trackerC, trackerD) + } + + fun `test not-under-content-root module state modification after deleting the file`() { + val fileA = createNotUnderContentRootFile("a") + val fileB = createNotUnderContentRootFile("b") + val libraryC = createProjectLibrary("c") + val moduleD = createModuleInTmpDir("d") + + val trackerA = createTracker(fileA) + val trackerB = createTracker(fileB) + val trackerC = createTracker(libraryC) + val trackerD = createTracker(moduleD) + + delete(fileA.virtualFile) + + trackerA.assertModifiedOnce("deleted not-under-content-root file A", shouldBeRemoval = true) + trackerB.assertNotModified("unchanged not-under-content-root file B") + trackerC.assertNotModified("unchanged library C") + trackerD.assertNotModified("unchanged module D") + + disposeTrackers(trackerA, trackerB, trackerC, trackerD) + } + private fun createProjectLibrary(name: String): Library = ConfigLibraryUtil.addProjectLibraryWithClassesRoot(myProject, name) private fun createScript(name: String): KtFile = createKtFileUnderNewContentRoot(FileWithText("$name.kts", "")) + private fun createNotUnderContentRootFile(name: String): KtFile = + // While the not-under-content-root module is named as it is, it is still decidedly under the project's content root, just not a + // part of any other kind of `KtModule`. + createKtFileUnderNewContentRoot(FileWithText("$name.kt", "")) + private fun createTracker(module: KtModule): ModuleStateModificationTracker = ModuleStateModificationTracker(module) private fun createTracker(module: Module): ModuleStateModificationTracker = createTracker(module.productionSourceInfo!!.toKtModule()) From 85735d4db8730dcadeb7b3b900a350d8c7ffb17f Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 28 Jun 2023 14:56:22 +0200 Subject: [PATCH 039/165] [kotlin] KT-58257 Port `KotlinModuleOutOfBlockTrackerTest` to modification event tests - *Module* out-of-block modification is verified in `KotlinModuleOutOfBlockModificationTest`. - *Global source* out-of-block modification is verified in `KotlinGlobalSourceOutOfBlockModificationTest`. - Another test from `KotlinModuleOutOfBlockTrackerTest` has been moved to `ProjectWideOutOfBlockModificationTrackerTest` as it concerns the project-wide out-of-block modification tracker, which still exists, and is separate from event-based out-of-block modification. GitOrigin-RevId: acf6787ee57be82b8dbdd6b898b3a8cc3c359c30 --- ...stractKotlinGlobalModificationEventTest.kt | 12 + .../AbstractKotlinModificationEventTest.kt | 80 +++++ ...stractKotlinModuleModificationEventTest.kt | 40 +++ ...nGlobalSourceOutOfBlockModificationTest.kt | 63 ++++ .../KotlinModuleOutOfBlockModificationTest.kt | 317 +++++++++++++++++ .../KotlinModuleStateModificationTest.kt | 91 +---- .../KotlinModuleOutOfBlockTrackerTest.kt | 328 ------------------ ...ctWideOutOfBlockModificationTrackerTest.kt | 46 +++ 8 files changed, 571 insertions(+), 406 deletions(-) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinGlobalModificationEventTest.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModificationEventTest.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModuleModificationEventTest.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleOutOfBlockModificationTest.kt delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/KotlinModuleOutOfBlockTrackerTest.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/ProjectWideOutOfBlockModificationTrackerTest.kt diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinGlobalModificationEventTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinGlobalModificationEventTest.kt new file mode 100644 index 000000000000..364775fe97c3 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinGlobalModificationEventTest.kt @@ -0,0 +1,12 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.modificationEvents + +import com.intellij.openapi.project.Project + +abstract class AbstractKotlinGlobalModificationEventTest : AbstractKotlinModificationEventTest() { + abstract fun constructTracker(): TRACKER + + fun createTracker(): TRACKER = constructTracker().apply { initialize() } +} + +abstract class GlobalModificationEventTracker(project: Project, eventKind: String) : ModificationEventTracker(project, eventKind) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModificationEventTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModificationEventTest.kt new file mode 100644 index 000000000000..99f9767d0a75 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModificationEventTest.kt @@ -0,0 +1,80 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.modificationEvents + +import com.intellij.openapi.Disposable +import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.libraries.Library +import com.intellij.openapi.util.Disposer +import com.intellij.util.messages.MessageBusConnection +import org.jetbrains.kotlin.analysis.providers.analysisMessageBus +import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest +import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil +import org.jetbrains.kotlin.psi.KtFile +import org.junit.Assert +import java.io.File + +abstract class AbstractKotlinModificationEventTest : AbstractMultiModuleTest() { + override fun getTestDataDirectory(): File = error("Should not be called") + + override fun isFirPlugin(): Boolean = true + + protected fun createProjectLibrary(name: String): Library = ConfigLibraryUtil.addProjectLibraryWithClassesRoot(myProject, name) + + protected fun createScript(name: String): KtFile = createKtFileUnderNewContentRoot(FileWithText("$name.kts", "")) + + protected fun createNotUnderContentRootFile(name: String): KtFile = + // While the not-under-content-root module is named as it is, it is still decidedly under the project's content root, just not a + // part of any other kind of `KtModule`. + createKtFileUnderNewContentRoot(FileWithText("$name.kt", "")) + + protected fun disposeTrackers(vararg trackers: TRACKER) { + trackers.forEach { Disposer.dispose(it) } + } +} + +abstract class ModificationEventTracker( + private val project: Project, + private val eventKind: String, +) : Disposable { + protected class ReceivedEvent(val isRemoval: Boolean) + + protected val receivedEvents: MutableList = mutableListOf() + + fun initialize() { + val busConnection = project.analysisMessageBus.connect(this) + configureSubscriptions(busConnection) + } + + protected abstract fun configureSubscriptions(busConnection: MessageBusConnection) + + override fun dispose() { } + + fun assertNotModified(label: String) { + Assert.assertTrue( + "${eventKind.replaceFirstChar { it.uppercaseChar() }} events for '$label' should not have been published, but ${receivedEvents.size} events were received.", + receivedEvents.isEmpty(), + ) + } + + fun assertModifiedOnce(label: String, shouldBeRemoval: Boolean = false) { + assertModified(label, expectedEventCount = 1, shouldBeRemoval) + } + + fun assertModified(label: String, expectedEventCount: Int, shouldBeRemoval: Boolean = false) { + val eventCountString = if (expectedEventCount == 1) "A single" else expectedEventCount.toString() + val eventOrEvents = if (expectedEventCount == 1) "event" else "events" + Assert.assertTrue( + "$eventCountString $eventKind $eventOrEvents for '$label' should have been published, but ${receivedEvents.size} events were received.", + receivedEvents.size == expectedEventCount, + ) + + val shouldOrShouldNotBeRemoval = if (shouldBeRemoval) "should" else "should not" + receivedEvents.forEachIndexed { index, receivedEvent -> + val indexInfo = if (expectedEventCount > 0) " (event index: $index)" else "" + Assert.assertTrue( + "The $eventKind event for '$label' $shouldOrShouldNotBeRemoval be a removal event$indexInfo.", + receivedEvent.isRemoval == shouldBeRemoval, + ) + } + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModuleModificationEventTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModuleModificationEventTest.kt new file mode 100644 index 000000000000..16b2df817931 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModuleModificationEventTest.kt @@ -0,0 +1,40 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.modificationEvents + +import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.libraries.Library +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider +import org.jetbrains.kotlin.idea.base.projectStructure.LibraryInfoCache +import org.jetbrains.kotlin.idea.base.projectStructure.productionSourceInfo +import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule +import org.jetbrains.kotlin.psi.KtFile + +abstract class AbstractKotlinModuleModificationEventTest : AbstractKotlinModificationEventTest() { + protected abstract fun constructTracker(module: KtModule): TRACKER + + protected fun createTracker(module: KtModule): TRACKER = constructTracker(module).apply { initialize() } + + protected fun createTracker(module: Module): TRACKER = createTracker(module.productionSourceInfo!!.toKtModule()) + + protected fun createTracker(library: Library): TRACKER = + createTracker(LibraryInfoCache.getInstance(myProject)[library].single().toKtModule()) + + protected fun createTracker(file: KtFile): TRACKER = + createTracker(ProjectStructureProvider.getModule(myProject, file, contextualModule = null)) +} + +abstract class ModuleModificationEventTracker( + private val module: KtModule, + eventKind: String, +) : ModificationEventTracker(module.project, eventKind) { + fun handleEvent(eventModule: KtModule, isRemoval: Boolean) { + if (eventModule == module) { + receivedEvents.add(ReceivedEvent(isRemoval)) + } + } + + fun handleEvent(eventModule: KtModule) { + handleEvent(eventModule, isRemoval = false) + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt new file mode 100644 index 000000000000..841f89d423c5 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt @@ -0,0 +1,63 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.modificationEvents + +import com.intellij.openapi.application.runWriteAction +import com.intellij.openapi.project.Project +import com.intellij.util.messages.MessageBusConnection +import org.jetbrains.kotlin.analysis.providers.topics.KotlinGlobalSourceOutOfBlockModificationListener +import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics +import org.jetbrains.kotlin.idea.util.sourceRoots + +class KotlinGlobalSourceOutOfBlockModificationTest : AbstractKotlinGlobalModificationEventTest() { + override fun constructTracker() = GlobalSourceOutOfBlockModificationEventTracker(myProject) + + fun `test that global source out-of-block modification occurs after a file is added to a module content root`() { + val moduleA = createModuleInTmpDir("a") + createModuleInTmpDir("b") + createModuleInTmpDir("c") + + val tracker = createTracker() + + runWriteAction { + moduleA.sourceRoots.first().createChildData(/* requestor = */ null, "file.kt") + } + + tracker.assertModifiedOnce("the project after a file is added to the content root of module A") + + disposeTrackers(tracker) + } + + fun `test that global source out-of-block modification occurs after a file is moved to another module content root`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText("main.kt", "fun main() {}") + ) + } + val moduleB = createModuleInTmpDir("b") + createModuleInTmpDir("c") + + val tracker = createTracker() + + val file = moduleA.sourceRoots.first().findChild("main.kt")!! + val destination = moduleB.sourceRoots.first() + move(file, destination) + + tracker.assertModifiedOnce("the project after a file from module A is moved to the content root of module B") + + disposeTrackers(tracker) + } +} + +class GlobalSourceOutOfBlockModificationEventTracker(project: Project) : GlobalModificationEventTracker( + project, + eventKind = "global source out-of-block modification", +) { + override fun configureSubscriptions(busConnection: MessageBusConnection) { + busConnection.subscribe( + KotlinTopics.GLOBAL_SOURCE_OUT_OF_BLOCK_MODIFICATION, + KotlinGlobalSourceOutOfBlockModificationListener { + receivedEvents.add(ReceivedEvent(isRemoval = false)) + }, + ) + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleOutOfBlockModificationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleOutOfBlockModificationTest.kt new file mode 100644 index 000000000000..39e581131352 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleOutOfBlockModificationTest.kt @@ -0,0 +1,317 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + +package org.jetbrains.kotlin.idea.fir.analysis.providers.modificationEvents + +import com.intellij.openapi.application.runWriteAction +import com.intellij.openapi.module.Module +import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiManager +import com.intellij.util.messages.MessageBusConnection +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleOutOfBlockModificationListener +import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics +import org.jetbrains.kotlin.idea.util.sourceRoots +import org.jetbrains.kotlin.psi.* +import org.junit.Assert + +class KotlinModuleOutOfBlockModificationTest : AbstractKotlinModuleModificationEventTest() { + override fun constructTracker(module: KtModule): ModuleOutOfBlockModificationEventTracker = ModuleOutOfBlockModificationEventTracker(module) + + fun `test that source module out-of-block modification affects a single module`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText("main.kt", "fun main() = 10") + ) + } + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + + val trackerA = createTracker(moduleA) + val trackerB = createTracker(moduleB) + val trackerC = createTracker(moduleC) + + moduleA.configureEditorForFile("main.kt").apply { + typeHelloInSingleFunctionBody(textAfterTyping = "fun main() = hello10") + } + + // We expect two events: One published before and one after the PSI tree modification. + trackerA.assertModified("module A with out-of-block change after typing", expectedEventCount = 2) + trackerB.assertNotModified("unmodified module B") + trackerC.assertNotModified("unmodified module C") + + disposeTrackers(trackerA, trackerB, trackerC) + } + + fun `test that source module out-of-block modification does not occur after deleting a symbol in a function body`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText( + "main.kt", + "fun main() {\n" + + "val v = \n" + + "}" + ) + ) + } + + val trackerA = createTracker(moduleA) + + moduleA.configureEditorForFile("main.kt").apply { + modify(textAfterModification = "fun main() {\n" + "val v =\n" + "}") { + backspace() + } + } + + trackerA.assertNotModified("module A with an in-block modification") + + disposeTrackers(trackerA) + } + + fun `test that source module out-of-block modification does not occur after deleting whitespace`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText( + "main.kt", + "class Main { fun main() {}\n}" + ) + ) + } + + val trackerA = createTracker(moduleA) + + moduleA.configureEditorForFile("main.kt").apply { + modify(textAfterModification = "class Main { fun main() {}\n}", getSingleMemberInClassOffset()) { + backspace() + } + } + + trackerA.assertNotModified("module A after deleting whitespace") + + disposeTrackers(trackerA) + } + + fun `test that source module out-of-block modification occurs after adding a space in an identifier`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText( + "main.kt", + "class Main { fun main() {}\n}" + ) + ) + } + + val trackerA = createTracker(moduleA) + + moduleA.configureEditorForFile("main.kt").apply { + modify( + textAfterModification = "class Main { fun m ain() {}\n}", + getSingleMemberInClassOffset() + "fun m".length, + ) { + type(" ") + } + } + + // In total, seven PSI tree changes are processed: Two `BEFORE_CHILD_REPLACEMENT`, one `CHILDREN_CHANGED`, and four `CHILD_ADDED`. + trackerA.assertModified("module A after adding a space in an identifier", expectedEventCount = 7) + + disposeTrackers(trackerA) + } + + fun `test that source module out-of-block modification occurs after commenting out a function`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText( + "main.kt", "class Main { fun main() {}\n}" + ) + ) + } + + val trackerA = createTracker(moduleA) + + moduleA.configureEditorForFile("main.kt").apply { + modify("class Main { //fun main() {}\n}", getSingleMemberInClassOffset()) { + type("//") + } + } + + trackerA.assertModifiedOnce("module A after commenting out a function") + + disposeTrackers(trackerA) + } + + fun `test that source module out-of-block modification does not occur after commenting out a type inside a function body`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText( + "main.kt", + "class Main {\n" + + " fun main() {\n" + + " class Local {}\n" + + " }\n" + + "}" + ) + ) + } + + val trackerA = createTracker(moduleA) + + moduleA.configureEditorForFile("main.kt").apply { + val textAfterModification = + "class Main {\n" + + " fun main() {\n" + + "// class Local {}\n" + + " }\n" + + "}" + + val singleFunction = (declarations[0] as KtClass).declarations.single() as KtFunction + val offset = singleFunction.bodyBlockExpression?.lBrace?.textOffset!! + 2 + + modify(textAfterModification, offset) { + type("//") + } + } + + trackerA.assertNotModified("module A after commenting out a type inside a function body") + + disposeTrackers(trackerA) + } + + fun `test that source module out-of-block modification occurs after commenting out a type`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText( + "main.kt", "class Main {}" + ) + ) + } + + val trackerA = createTracker(moduleA) + + moduleA.configureEditorForFile("main.kt").apply { + modify(textAfterModification = "//class Main {}", 0) { + type("//") + } + } + + trackerA.assertModifiedOnce("module A after commenting out a type") + + disposeTrackers(trackerA) + } + + fun `test that source module out-of-block modification occurs after adding a modifier to a function`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText( + "main.kt", "inline fun main() {}" + ) + ) + } + + val trackerA = createTracker(moduleA) + + moduleA.configureEditorForFile("main.kt").apply { + modify("private inline fun main() {}") { + type("private ") + } + } + + // In total, seven PSI tree changes are processed: Three `BEFORE_CHILD_REMOVAL`, three `CHILD_REMOVED`, and one `CHILD_ADDED`. + trackerA.assertModified("module A after adding a modifier to a function", expectedEventCount = 7) + + disposeTrackers(trackerA) + } + + fun `test that source module out-of-block modification occurs after adding a return type to a function`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText( + "main.kt", "fun foo() = 10" + ) + ) + } + + val trackerA = createTracker(moduleA) + + moduleA.configureEditorForFile("main.kt").apply { + modify("fun foo(): Byte = 10") { + type(": Byte") + } + } + + // In total, seventeen PSI tree changes are processed: Five `BEFORE_CHILD_REMOVAL`, two `CHILDREN_CHANGED`, seven `CHILD_REMOVED`, + // two `CHILD_ADDED`, and one `BEFORE_CHILD_REPLACEMENT`. + trackerA.assertModified("module A after adding a return type to a function", expectedEventCount = 17) + + disposeTrackers(trackerA) + } + + fun `test that source module out-of-block modification does not occur after changing a non-physical file`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText("main.kt", "fun main() {}") + ) + } + val moduleB = createModuleInTmpDir("b") + + val trackerA = createTracker(moduleA) + val trackerB = createTracker(moduleB) + + runWriteAction { + val nonPhysicalPsi = KtPsiFactory(moduleA.project).createFile("nonPhysical", "val a = c") + nonPhysicalPsi.add(KtPsiFactory(moduleA.project).createFunction("fun x(){}")) + } + + trackerA.assertNotModified("module A") + trackerB.assertNotModified("module B") + + disposeTrackers(trackerA, trackerB) + } + + private fun KtFile.configureEditor() { + configureByExistingFile(virtualFile) + } + + private fun Module.configureEditorForFile(fileName: String): KtFile { + val file = "${sourceRoots.first().url}/$fileName" + val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! + val ktFile = PsiManager.getInstance(myProject).findFile(virtualFile) as KtFile + ktFile.configureEditor() + return ktFile + } + + private fun KtFile.modify(textAfterModification: String, targetOffset: Int? = null, edit: () -> Unit) { + targetOffset?.let(editor.caretModel::moveToOffset) + edit() + PsiDocumentManager.getInstance(myProject).commitAllDocuments() + Assert.assertEquals(textAfterModification, text) + } + + private fun KtFile.typeHelloInSingleFunctionBody(textAfterTyping: String) { + modify(textAfterTyping, getSingleFunctionBodyOffset()) { + type("hello") + } + } + + private fun KtFile.getSingleFunctionBodyOffset(): Int { + val singleFunction = declarations.single() as KtNamedFunction + return singleFunction.bodyExpression!!.textOffset + } + + private fun KtFile.getSingleMemberInClassOffset(): Int { + val singleMember = (declarations[0] as KtClass).declarations.single() + return singleMember.textRange.startOffset + } +} + +class ModuleOutOfBlockModificationEventTracker(module: KtModule) : ModuleModificationEventTracker( + module, + eventKind = "module out-of-block modification", +) { + override fun configureSubscriptions(busConnection: MessageBusConnection) { + busConnection.subscribe( + KotlinTopics.MODULE_OUT_OF_BLOCK_MODIFICATION, + KotlinModuleOutOfBlockModificationListener(::handleEvent), + ) + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt index 6de8e087403a..604001979a39 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleStateModificationTest.kt @@ -1,35 +1,22 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.fir.analysis.providers.modificationEvents -import com.intellij.openapi.Disposable import com.intellij.openapi.application.runWriteAction -import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.libraries.Library -import com.intellij.openapi.util.Disposer import com.intellij.testFramework.PsiTestUtil +import com.intellij.util.messages.MessageBusConnection import org.jetbrains.kotlin.analysis.project.structure.KtModule -import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider -import org.jetbrains.kotlin.analysis.providers.analysisMessageBus import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleStateModificationListener import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics import org.jetbrains.kotlin.idea.base.plugin.artifacts.TestKotlinArtifacts -import org.jetbrains.kotlin.idea.base.projectStructure.LibraryInfoCache -import org.jetbrains.kotlin.idea.base.projectStructure.productionSourceInfo -import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule -import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import org.jetbrains.kotlin.idea.test.addEmptyClassesRoot -import org.jetbrains.kotlin.psi.KtFile -import org.junit.Assert -import java.io.File import org.jetbrains.kotlin.test.util.addDependency -class KotlinModuleStateModificationTest : AbstractMultiModuleTest() { - override fun isFirPlugin(): Boolean = true - - override fun getTestDataDirectory(): File = error("Should not be called") +class KotlinModuleStateModificationTest : AbstractKotlinModuleModificationEventTest() { + override fun constructTracker(module: KtModule): ModuleStateModificationEventTracker = ModuleStateModificationEventTracker(module) fun `test source module state modification after adding module dependency`() { val moduleA = createModuleInTmpDir("a") @@ -389,68 +376,16 @@ class KotlinModuleStateModificationTest : AbstractMultiModuleTest() { disposeTrackers(trackerA, trackerB, trackerC, trackerD) } +} - private fun createProjectLibrary(name: String): Library = ConfigLibraryUtil.addProjectLibraryWithClassesRoot(myProject, name) - - private fun createScript(name: String): KtFile = createKtFileUnderNewContentRoot(FileWithText("$name.kts", "")) - - private fun createNotUnderContentRootFile(name: String): KtFile = - // While the not-under-content-root module is named as it is, it is still decidedly under the project's content root, just not a - // part of any other kind of `KtModule`. - createKtFileUnderNewContentRoot(FileWithText("$name.kt", "")) - - private fun createTracker(module: KtModule): ModuleStateModificationTracker = ModuleStateModificationTracker(module) - - private fun createTracker(module: Module): ModuleStateModificationTracker = createTracker(module.productionSourceInfo!!.toKtModule()) - - private fun createTracker(library: Library): ModuleStateModificationTracker = - createTracker(LibraryInfoCache.getInstance(myProject)[library].single().toKtModule()) - - private fun createTracker(file: KtFile): ModuleStateModificationTracker = - createTracker(ProjectStructureProvider.getModule(myProject, file, contextualModule = null)) - - private fun disposeTrackers(vararg trackers: ModuleStateModificationTracker) { - trackers.forEach { Disposer.dispose(it) } - } - - private class ModuleStateModificationTracker(val module: KtModule) : Disposable { - private class ReceivedEvent(val isRemoval: Boolean) - - private val receivedEvents: MutableList = mutableListOf() - - init { - val busConnection = module.project.analysisMessageBus.connect(this) - busConnection.subscribe( - KotlinTopics.MODULE_STATE_MODIFICATION, - KotlinModuleStateModificationListener { eventModule, isRemoval -> - if (eventModule == module) { - receivedEvents.add(ReceivedEvent(isRemoval)) - } - } - ) - } - - override fun dispose() { } - - fun assertNotModified(label: String) { - Assert.assertTrue( - "Module state modification events for '$label' should not have been published, but ${receivedEvents.size} events were received.", - receivedEvents.isEmpty(), - ) - } - - fun assertModifiedOnce(label: String, shouldBeRemoval: Boolean = false) { - Assert.assertTrue( - "A single module state modification event for '$label' should have been published, but ${receivedEvents.size} events were received.", - receivedEvents.size == 1, - ) - - val receivedEvent = receivedEvents.single() - val shouldOrShouldNot = if (shouldBeRemoval) "should" else "should not" - Assert.assertTrue( - "The module state modification event for '$label' $shouldOrShouldNot be a removal event.", - receivedEvent.isRemoval == shouldBeRemoval, - ) - } +class ModuleStateModificationEventTracker(module: KtModule) : ModuleModificationEventTracker( + module, + eventKind = "module state modification", +) { + override fun configureSubscriptions(busConnection: MessageBusConnection) { + busConnection.subscribe( + KotlinTopics.MODULE_STATE_MODIFICATION, + KotlinModuleStateModificationListener(::handleEvent), + ) } } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/KotlinModuleOutOfBlockTrackerTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/KotlinModuleOutOfBlockTrackerTest.kt deleted file mode 100644 index 705763644b8a..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/KotlinModuleOutOfBlockTrackerTest.kt +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. - -package org.jetbrains.kotlin.idea.fir.analysis.providers.trackers - -import com.intellij.openapi.application.runWriteAction -import com.intellij.openapi.module.Module -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.ModificationTracker -import com.intellij.openapi.vfs.VirtualFileManager -import com.intellij.psi.PsiDocumentManager -import com.intellij.psi.PsiManager -import org.jetbrains.kotlin.analysis.providers.createModuleWithoutDependenciesOutOfBlockModificationTracker -import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker -import org.jetbrains.kotlin.idea.base.projectStructure.getMainKtSourceModule -import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest -import org.jetbrains.kotlin.idea.util.sourceRoots -import org.jetbrains.kotlin.psi.* -import org.junit.Assert -import java.io.File - -class KotlinModuleOutOfBlockTrackerTest : AbstractMultiModuleTest() { - override fun getTestDataDirectory(): File = error("Should not be called") - - override fun isFirPlugin(): Boolean = true - - fun testThatModuleOutOfBlockChangeInfluenceOnlySingleModule() { - val moduleA = createModuleInTmpDir("a") { - listOf( - FileWithText("main.kt", "fun main() = 10") - ) - } - val moduleB = createModuleInTmpDir("b") - val moduleC = createModuleInTmpDir("c") - - - val moduleAWithTracker = ModuleWithModificationTracker(moduleA) - val moduleBWithTracker = ModuleWithModificationTracker(moduleB) - val moduleCWithTracker = ModuleWithModificationTracker(moduleC) - - moduleA.typeInFunctionBody("main.kt", textAfterTyping = "fun main() = hello10") - - Assert.assertTrue( - "Out of block modification count for module A with out of block should change after typing, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertFalse( - "Out of block modification count for module B without out of block should not change after typing, modification count is ${moduleBWithTracker.modificationCount}", - moduleBWithTracker.changed() - ) - Assert.assertFalse( - "Out of block modification count for module C without out of block should not change after typing, modification count is ${moduleCWithTracker.modificationCount}", - moduleCWithTracker.changed() - ) - } - - fun testThatDeleteSymbolInBodyDoesNotLeadToOutOfBlockChange() { - val moduleA = createModuleInTmpDir("a") { - listOf( - FileWithText( - "main.kt", "fun main() {\n" + - "val v = \n" + - "}" - ) - ) - } - - val moduleAWithTracker = ModuleWithModificationTracker(moduleA) - - val file = "${moduleA.sourceRoots.first().url}/${"main.kt"}" - val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! - val ktFile = PsiManager.getInstance(moduleA.project).findFile(virtualFile) as KtFile - configureByExistingFile(virtualFile) - backspace() - PsiDocumentManager.getInstance(moduleA.project).commitAllDocuments() - - Assert.assertFalse( - "Out of block modification count for module A should not change after deleting, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertEquals("fun main() {\n" + - "val v =\n" + - "}", ktFile.text) - } - - //1. outside function - //2. in function identifier - fun testWhitespace() { - val moduleA = createModuleInTmpDir("a") { - listOf( - FileWithText( - "main.kt", "class Main {" + - " fun main() {}\n" + - "}" - ) - ) - } - - val moduleAWithTracker = ModuleWithModificationTracker(moduleA) - - val file = "${moduleA.sourceRoots.first().url}/${"main.kt"}" - val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! - val ktFile = PsiManager.getInstance(moduleA.project).findFile(virtualFile) as KtFile - configureByExistingFile(virtualFile) - val singleFunction = (ktFile.declarations[0] as KtClass).declarations.single() - val startOffset = singleFunction.textRange.startOffset - editor.caretModel.moveToOffset(startOffset) - backspace() - PsiDocumentManager.getInstance(moduleA.project).commitAllDocuments() - - Assert.assertFalse( - "Out of block modification count for module A should not change after deleting, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertEquals("class Main { fun main() {}\n" + - "}", ktFile.text) - - editor.caretModel.moveToOffset(startOffset + "fun ".length) - type(" ") - PsiDocumentManager.getInstance(moduleA.project).commitAllDocuments() - Assert.assertTrue( - "Out of block modification count for module A should change after adding space in identifier, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertEquals("class Main { fun m ain() {}\n" + - "}", ktFile.text) - - } - - fun testCommentFunction() { - val moduleA = createModuleInTmpDir("a") { - listOf( - FileWithText( - "main.kt", "class Main {" + - " fun main() {}\n" + - "}" - ) - ) - } - - val moduleAWithTracker = ModuleWithModificationTracker(moduleA) - - val file = "${moduleA.sourceRoots.first().url}/${"main.kt"}" - val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! - val ktFile = PsiManager.getInstance(moduleA.project).findFile(virtualFile) as KtFile - configureByExistingFile(virtualFile) - val singleFunction = (ktFile.declarations[0] as KtClass).declarations.single() - val startOffset = singleFunction.textRange.startOffset - editor.caretModel.moveToOffset(startOffset) - type("//") - PsiDocumentManager.getInstance(moduleA.project).commitAllDocuments() - - Assert.assertTrue( - "Out of block modification count for module A should change after commenting, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - } - - fun testLocalCommentType() { - val moduleA = createModuleInTmpDir("a") { - listOf( - FileWithText( - "main.kt", "class Main {\n" + - " fun main() {\n" + - " class Local {}\n" + - " }\n" + - "}" - ) - ) - } - - val moduleAWithTracker = ModuleWithModificationTracker(moduleA) - - val file = "${moduleA.sourceRoots.first().url}/${"main.kt"}" - val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! - val ktFile = PsiManager.getInstance(moduleA.project).findFile(virtualFile) as KtFile - configureByExistingFile(virtualFile) - val singleFunction = (ktFile.declarations[0] as KtClass).declarations.single() as KtFunction - val startOffset = (singleFunction.bodyBlockExpression?.lBrace?.textOffset ?: 0) + 2 - editor.caretModel.moveToOffset(startOffset) - type("//") - PsiDocumentManager.getInstance(moduleA.project).commitAllDocuments() - - Assert.assertFalse( - "Out of block modification count for module A should not change after commenting, local classes are not available outside of the method," + - "modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - } - - fun testCommentType() { - val moduleA = createModuleInTmpDir("a") { - listOf( - FileWithText( - "main.kt", "class Main {}" - ) - ) - } - val moduleAWithTracker = ModuleWithModificationTracker(moduleA) - val file = "${moduleA.sourceRoots.first().url}/${"main.kt"}" - val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! - configureByExistingFile(virtualFile) - editor.caretModel.moveToOffset(0) - type("//") - PsiDocumentManager.getInstance(moduleA.project).commitAllDocuments() - - Assert.assertTrue( - "Out of block modification count for module A should change after commenting, local classes are not available outside of the method," + - "modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - } - - fun testThatAddModifierDoesLeadToOutOfBlockChange() { - val moduleA = createModuleInTmpDir("a") { - listOf( - FileWithText( - "main.kt", "inline fun main() {}" - ) - ) - } - - val moduleAWithTracker = ModuleWithModificationTracker(moduleA) - - val file = "${moduleA.sourceRoots.first().url}/${"main.kt"}" - val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! - val ktFile = PsiManager.getInstance(moduleA.project).findFile(virtualFile) as KtFile - configureByExistingFile(virtualFile) - type("private ") - PsiDocumentManager.getInstance(moduleA.project).commitAllDocuments() - - Assert.assertTrue( - "Out of block modification count for module A should be changed after specifying return type, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertEquals("private inline fun main() {}", ktFile.text) - } - - fun testThatInEveryModuleOutOfBlockWillHappenAfterContentRootChange() { - val moduleA = createModuleInTmpDir("a") - val moduleB = createModuleInTmpDir("b") - val moduleC = createModuleInTmpDir("c") - - val moduleAWithTracker = ModuleWithModificationTracker(moduleA) - val moduleBWithTracker = ModuleWithModificationTracker(moduleB) - val moduleCWithTracker = ModuleWithModificationTracker(moduleC) - - runWriteAction { - moduleA.sourceRoots.first().createChildData(/* requestor = */ null, "file.kt") - } - - Assert.assertTrue( - "Out of block modification count for module A should change after content root change, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertTrue( - "Out of block modification count for module B should change after content root change, modification count is ${moduleBWithTracker.modificationCount}", - moduleBWithTracker.changed() - ) - Assert.assertTrue( - "Out of block modification count for module C should change after content root change modification count is ${moduleCWithTracker.modificationCount}", - moduleCWithTracker.changed() - ) - } - - fun testThatNonPhysicalFileChangeNotCausingBOOM() { - val moduleA = createModuleInTmpDir("a") { - listOf( - FileWithText("main.kt", "fun main() {}") - ) - } - val moduleB = createModuleInTmpDir("b") - - val moduleAWithTracker = ModuleWithModificationTracker(moduleA) - val moduleBWithTracker = ModuleWithModificationTracker(moduleB) - - - val projectWithModificationTracker = ProjectWithModificationTracker(project) - - runWriteAction { - val nonPhysicalPsi = KtPsiFactory(moduleA.project).createFile("nonPhysical", "val a = c") - nonPhysicalPsi.add(KtPsiFactory(moduleA.project).createFunction("fun x(){}")) - } - - Assert.assertFalse( - "Out of block modification count for module A should not change after non physical file change, modification count is ${moduleAWithTracker.modificationCount}", - moduleAWithTracker.changed() - ) - Assert.assertFalse( - "Out of block modification count for module B should not change after non physical file change, modification count is ${moduleBWithTracker.modificationCount}", - moduleBWithTracker.changed() - ) - - Assert.assertFalse( - "Out of block modification count for project should not change after non physical file change, modification count is ${projectWithModificationTracker.modificationCount}", - projectWithModificationTracker.changed() - ) - } - - private fun Module.typeInFunctionBody(fileName: String, textAfterTyping: String) { - val file = "${sourceRoots.first().url}/$fileName" - val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! - val ktFile = PsiManager.getInstance(project).findFile(virtualFile) as KtFile - configureByExistingFile(virtualFile) - - val singleFunction = ktFile.declarations.single() as KtNamedFunction - - editor.caretModel.moveToOffset(singleFunction.bodyExpression!!.textOffset) - type("hello") - PsiDocumentManager.getInstance(project).commitAllDocuments() - Assert.assertEquals(textAfterTyping, ktFile.text) - } - - abstract class WithModificationTracker(private val modificationTracker: ModificationTracker) { - private val initialModificationCount = modificationTracker.modificationCount - val modificationCount: Long get() = modificationTracker.modificationCount - - fun changed(): Boolean = - modificationTracker.modificationCount != initialModificationCount - } - - private class ModuleWithModificationTracker(module: Module) : WithModificationTracker( - module.getMainKtSourceModule()!!.createModuleWithoutDependenciesOutOfBlockModificationTracker(module.project) - ) - - private class ProjectWithModificationTracker(project: Project) : WithModificationTracker( - project.createProjectWideOutOfBlockModificationTracker() - ) -} \ No newline at end of file diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/ProjectWideOutOfBlockModificationTrackerTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/ProjectWideOutOfBlockModificationTrackerTest.kt new file mode 100644 index 000000000000..da4bc3ba41f1 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/trackers/ProjectWideOutOfBlockModificationTrackerTest.kt @@ -0,0 +1,46 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.trackers + +import com.intellij.openapi.application.runWriteAction +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.ModificationTracker +import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker +import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.junit.Assert +import java.io.File + +class ProjectWideOutOfBlockModificationTrackerTest : AbstractMultiModuleTest() { + override fun getTestDataDirectory(): File = error("Should not be called") + + override fun isFirPlugin(): Boolean = true + + fun `test that the project-wide out-of-block modification tracker remains unchanged after changing a non-physical file`() { + val moduleA = createModuleInTmpDir("a") { + listOf(FileWithText("main.kt", "fun main() {}")) + } + + val projectModificationCountChecker = createModificationCountChecker(myProject) + + runWriteAction { + val nonPhysicalPsi = KtPsiFactory(moduleA.project).createFile("nonPhysical", "val a = c") + nonPhysicalPsi.add(KtPsiFactory(moduleA.project).createFunction("fun x(){}")) + } + + Assert.assertFalse( + "Out-of-block modification count for the project should not change after a non-physical file change, modification count is ${projectModificationCountChecker.modificationCount}", + projectModificationCountChecker.hasChanged() + ) + } + + private fun createModificationCountChecker(project: Project): ProjectOutOfBlockModificationCountChecker = + ProjectOutOfBlockModificationCountChecker(project.createProjectWideOutOfBlockModificationTracker()) + + class ProjectOutOfBlockModificationCountChecker(private val modificationTracker: ModificationTracker) { + private val initialModificationCount = modificationTracker.modificationCount + + val modificationCount: Long get() = modificationTracker.modificationCount + + fun hasChanged(): Boolean = modificationTracker.modificationCount != initialModificationCount + } +} From 33d8df2242c9d51aa81378ae2487fad67c0da584 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 28 Jun 2023 17:07:53 +0200 Subject: [PATCH 040/165] [kotlin] KT-58257 Add script and not-under-content-root module out-of-block modification tests GitOrigin-RevId: be4ce70bd787159998a3a81fbdb4ed8d47e2cdad --- .../AbstractKotlinModificationEventTest.kt | 7 +- .../KotlinModuleOutOfBlockModificationTest.kt | 74 ++++++++++++++++--- 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModificationEventTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModificationEventTest.kt index 99f9767d0a75..7bca9cce17f1 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModificationEventTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModificationEventTest.kt @@ -20,12 +20,13 @@ abstract class AbstractKotlinModificationEventTest() { @@ -32,11 +33,13 @@ class KotlinModuleOutOfBlockModificationTest : AbstractKotlinModuleModificationE val trackerC = createTracker(moduleC) moduleA.configureEditorForFile("main.kt").apply { - typeHelloInSingleFunctionBody(textAfterTyping = "fun main() = hello10") + modify(textAfterModification = "fun main() = hello10", getSingleFunctionBodyOffset()) { + type("hello") + } } // We expect two events: One published before and one after the PSI tree modification. - trackerA.assertModified("module A with out-of-block change after typing", expectedEventCount = 2) + trackerA.assertModified("module A after out-of-block change", expectedEventCount = 2) trackerB.assertNotModified("unmodified module B") trackerC.assertNotModified("unmodified module C") @@ -268,10 +271,69 @@ class KotlinModuleOutOfBlockModificationTest : AbstractKotlinModuleModificationE disposeTrackers(trackerA, trackerB) } + fun `test that script module out-of-block modification affects a single script module`() { + val scriptA = createScript("a", "fun foo() = 10") + val scriptB = createScript("b", "fun bar() = 10") + val moduleC = createModuleInTmpDir("c") + val fileD = createNotUnderContentRootFile("d", "fun baz() = 10") + + val trackerA = createTracker(scriptA) + val trackerB = createTracker(scriptB) + val trackerC = createTracker(moduleC) + val trackerD = createTracker(fileD) + + scriptA.withConfiguredEditor { + val singleFunction = (declarations.single() as KtScript).declarations.single() as KtNamedFunction + val offset = singleFunction.bodyExpression!!.startOffset + modify(textAfterModification = "fun foo() = hello10", offset) { + type("hello") + } + } + + // We expect two events: One published before and one after the PSI tree modification. + trackerA.assertModified("script A after out-of-block modification", expectedEventCount = 2) + trackerB.assertNotModified("unmodified script B") + trackerC.assertNotModified("unmodified module C") + trackerD.assertNotModified("unmodified not-under-content-root file D") + + disposeTrackers(trackerA, trackerB, trackerC, trackerD) + } + + fun `test that not-under-content-root module out-of-block modification affects a single not-under-content-root module`() { + val fileA = createNotUnderContentRootFile("a", "fun foo() = 10") + val fileB = createNotUnderContentRootFile("b", "fun bar() = 10") + val moduleC = createModuleInTmpDir("c") + val scriptD = createScript("d", "fun baz() = 10") + + val trackerA = createTracker(fileA) + val trackerB = createTracker(fileB) + val trackerC = createTracker(moduleC) + val trackerD = createTracker(scriptD) + + fileA.withConfiguredEditor { + modify(textAfterModification = "fun foo() = hello10", getSingleFunctionBodyOffset()) { + type("hello") + } + } + + // We expect two events: One published before and one after the PSI tree modification. + trackerA.assertModified("not-under-content-root file A after out-of-block modification", expectedEventCount = 2) + trackerB.assertNotModified("unmodified not-under-content-root file B") + trackerC.assertNotModified("unmodified module C") + trackerD.assertNotModified("unmodified script D") + + disposeTrackers(trackerA, trackerB, trackerC, trackerD) + } + private fun KtFile.configureEditor() { configureByExistingFile(virtualFile) } + private fun KtFile.withConfiguredEditor(f: KtFile.() -> Unit) { + configureEditor() + f() + } + private fun Module.configureEditorForFile(fileName: String): KtFile { val file = "${sourceRoots.first().url}/$fileName" val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! @@ -287,12 +349,6 @@ class KotlinModuleOutOfBlockModificationTest : AbstractKotlinModuleModificationE Assert.assertEquals(textAfterModification, text) } - private fun KtFile.typeHelloInSingleFunctionBody(textAfterTyping: String) { - modify(textAfterTyping, getSingleFunctionBodyOffset()) { - type("hello") - } - } - private fun KtFile.getSingleFunctionBodyOffset(): Int { val singleFunction = declarations.single() as KtNamedFunction return singleFunction.bodyExpression!!.textOffset @@ -300,7 +356,7 @@ class KotlinModuleOutOfBlockModificationTest : AbstractKotlinModuleModificationE private fun KtFile.getSingleMemberInClassOffset(): Int { val singleMember = (declarations[0] as KtClass).declarations.single() - return singleMember.textRange.startOffset + return singleMember.startOffset } } From 3e460e4b278cddd241f72b970a4a92e35516b2fb Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 28 Jun 2023 18:40:36 +0200 Subject: [PATCH 041/165] [kotlin] KT-58257 Add script and not-under-content-root global source out-of-block modification tests GitOrigin-RevId: 623c17a650c681b6f99e07c4f0b3035f8624b875 --- ...nGlobalSourceOutOfBlockModificationTest.kt | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt index 841f89d423c5..642e299ed50c 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.idea.fir.analysis.providers.modificationEvents import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.project.Project +import com.intellij.testFramework.PsiTestUtil import com.intellij.util.messages.MessageBusConnection import org.jetbrains.kotlin.analysis.providers.topics.KotlinGlobalSourceOutOfBlockModificationListener import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics @@ -46,6 +47,90 @@ class KotlinGlobalSourceOutOfBlockModificationTest : AbstractKotlinGlobalModific disposeTrackers(tracker) } + + fun `test that global source out-of-block modification occurs after moving a script file to a non-source module content root`() { + val scriptA = createScript("a") + val moduleB = createModuleInTmpDir("b") + + val destination = getVirtualFile(createTempDirectory()) + PsiTestUtil.addContentRoot(moduleB, destination) + + val tracker = createTracker() + + move(scriptA.virtualFile, destination) + + tracker.assertModifiedOnce("the project after a script file is moved to a non-source content root of module B") + + disposeTrackers(tracker) + } + + fun `test that global source out-of-block modification occurs after moving a script file outside the project content root`() { + val scriptA = createScript("a") + val destination = getVirtualFile(createTempDirectory()) + + val tracker = createTracker() + + move(scriptA.virtualFile, destination) + + tracker.assertModifiedOnce("the project after a script file is moved outside the project content root") + + disposeTrackers(tracker) + } + + fun `test that global source out-of-block modification occurs after deleting a script file`() { + val scriptA = createScript("a") + + val tracker = createTracker() + + delete(scriptA.virtualFile) + + tracker.assertModified("the project after a script file is deleted", expectedEventCount = 2) + + disposeTrackers(tracker) + } + + fun `test that global source out-of-block modification occurs after moving a not-under-content-root file to a non-source module content root`() { + val fileA = createNotUnderContentRootFile("a") + val moduleB = createModuleInTmpDir("b") + + val destination = getVirtualFile(createTempDirectory()) + PsiTestUtil.addContentRoot(moduleB, destination) + + val tracker = createTracker() + + move(fileA.virtualFile, destination) + + tracker.assertModifiedOnce("the project after a not-under-content-root file is moved to a non-source content root of module B") + + disposeTrackers(tracker) + } + + fun `test that global source out-of-block modification occurs after moving a not-under-content-root file outside the project content root`() { + val fileA = createNotUnderContentRootFile("a") + val destination = getVirtualFile(createTempDirectory()) + + val tracker = createTracker() + + // Note that the "not-under-content-root" file is under the content root of the project, and so moving it outside the content root + // of the project does have an effect. + move(fileA.virtualFile, destination) + + tracker.assertModifiedOnce("the project after a not-under-content-root file is moved outside the project content root") + + disposeTrackers(tracker) + } + + fun `test that global source out-of-block modification occurs after deleting a not-under-content-root file`() { + val fileA = createNotUnderContentRootFile("a") + + val tracker = createTracker() + + delete(fileA.virtualFile) + + tracker.assertModified("the project after a not-under-content-root file is deleted", expectedEventCount = 2) + + disposeTrackers(tracker) + } } class GlobalSourceOutOfBlockModificationEventTracker(project: Project) : GlobalModificationEventTracker( From bad39a01eded1af399b74bb0fe5b190d9ad28c6a Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 29 Jun 2023 14:44:45 +0200 Subject: [PATCH 042/165] [kotlin] Extract `findSourceKtFile` to `AbstractMultiModuleTest` GitOrigin-RevId: 45ad7df8245a005bd07e16c470465def831d9e6d --- .../KotlinModuleOutOfBlockModificationTest.kt | 11 +---------- .../kotlin/idea/stubs/AbstractMultiModuleTest.kt | 9 +++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleOutOfBlockModificationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleOutOfBlockModificationTest.kt index 0dc635eff051..9d9af7e4feea 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleOutOfBlockModificationTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinModuleOutOfBlockModificationTest.kt @@ -4,14 +4,11 @@ package org.jetbrains.kotlin.idea.fir.analysis.providers.modificationEvents import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.module.Module -import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiDocumentManager -import com.intellij.psi.PsiManager import com.intellij.util.messages.MessageBusConnection import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleOutOfBlockModificationListener import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics -import org.jetbrains.kotlin.idea.util.sourceRoots import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.junit.Assert @@ -334,13 +331,7 @@ class KotlinModuleOutOfBlockModificationTest : AbstractKotlinModuleModificationE f() } - private fun Module.configureEditorForFile(fileName: String): KtFile { - val file = "${sourceRoots.first().url}/$fileName" - val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! - val ktFile = PsiManager.getInstance(myProject).findFile(virtualFile) as KtFile - ktFile.configureEditor() - return ktFile - } + private fun Module.configureEditorForFile(fileName: String): KtFile = findSourceKtFile(fileName).apply { configureEditor() } private fun KtFile.modify(textAfterModification: String, targetOffset: Int? = null, edit: () -> Unit) { targetOffset?.let(editor.caretModel::moveToOffset) diff --git a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt index 79e4a26fea27..c44478b13d2a 100644 --- a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt +++ b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt @@ -18,7 +18,9 @@ import com.intellij.openapi.util.Ref import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiFile +import com.intellij.psi.PsiManager import com.intellij.testFramework.IdeaTestUtil import com.intellij.testFramework.PsiTestUtil import com.intellij.util.ThrowableRunnable @@ -32,6 +34,7 @@ import org.jetbrains.kotlin.idea.test.* import org.jetbrains.kotlin.idea.test.KotlinTestUtils.allowProjectRootAccess import org.jetbrains.kotlin.idea.test.KotlinTestUtils.disposeVfsRootAccess import org.jetbrains.kotlin.idea.test.util.slashedPath +import org.jetbrains.kotlin.idea.util.sourceRoots import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.psi.KtFile import org.junit.Assert @@ -169,6 +172,12 @@ abstract class AbstractMultiModuleTest : DaemonAnalyzerTestCase() { } } + fun Module.findSourceKtFile(fileName: String): KtFile { + val file = "${sourceRoots.first().url}/$fileName" + val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! + return PsiManager.getInstance(myProject).findFile(virtualFile) as KtFile + } + fun Module.enableMultiPlatform(additionalCompilerArguments: String = "") { createFacet() val facetSettings = KotlinFacetSettingsProvider.getInstance(project)?.getInitializedSettings(this) From bc8db9a88c9d38cb4832a72cd5c6e25c37dede61 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 29 Jun 2023 14:47:58 +0200 Subject: [PATCH 043/165] [kotlin] KT-57743 Add a test for cyclic dependency symbol providers - Even though `AbstractSessionsInvalidationTest` already verifies that cyclic sessions can be built, it does not access symbol providers. - `CyclicDependenciesSymbolResolutionTest` tests symbol resolution with a cyclic module structure, which at least smoke tests the ability to construct dependency symbol providers in such an environment. - Because cyclic dependencies are a feature of JPS, this test isn't easily placed on the Analysis API side. GitOrigin-RevId: 26ae37e5294517edb44117f98ab8a40e6b54dca1 --- ...kotlin.base.fir.analysis-api-providers.iml | 17 +++++ .../CyclicDependenciesSymbolResolutionTest.kt | 75 +++++++++++++++++++ .../idea/stubs/AbstractMultiModuleTest.kt | 11 +++ 3 files changed, 103 insertions(+) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/CyclicDependenciesSymbolResolutionTest.kt diff --git a/plugins/kotlin/base/fir/analysis-api-providers/kotlin.base.fir.analysis-api-providers.iml b/plugins/kotlin/base/fir/analysis-api-providers/kotlin.base.fir.analysis-api-providers.iml index 64dbe9fe223b..4a0994051955 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/kotlin.base.fir.analysis-api-providers.iml +++ b/plugins/kotlin/base/fir/analysis-api-providers/kotlin.base.fir.analysis-api-providers.iml @@ -1,5 +1,21 @@ + + + + + + + + + + + + + + + @@ -15,6 +31,7 @@ + diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/CyclicDependenciesSymbolResolutionTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/CyclicDependenciesSymbolResolutionTest.kt new file mode 100644 index 000000000000..8814b5602493 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/CyclicDependenciesSymbolResolutionTest.kt @@ -0,0 +1,75 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.sessions + +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.analyzeInModalWindow +import org.jetbrains.kotlin.analysis.api.calls.successfulFunctionCallOrNull +import org.jetbrains.kotlin.analysis.api.calls.symbol +import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtSimpleNameExpression +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance +import org.junit.Assert +import java.io.File + +/** + * [CyclicDependenciesSymbolResolutionTest] ensures that sessions with cyclic dependencies can not only be created (which + * [AbstractSessionsInvalidationTest] already ensures), but also that these sessions' dependency symbol providers don't run into any stack + * overflow errors. + * + * A corresponding (or replacement) test on the Analysis API side does not exist yet, because the Analysis API test infrastructure does not + * support cyclic module dependencies, which makes this strictly an issue of JPS project structures. + */ +class CyclicDependenciesSymbolResolutionTest : AbstractMultiModuleTest() { + override fun getTestDataDirectory(): File = error("Should not be called") + + override fun isFirPlugin(): Boolean = true + + fun `test that function symbols from cyclic dependencies can be resolved`() { + val moduleA = createModuleInTmpDir("a") { + listOf( + FileWithText("a.kt", "fun foo(): Int = bar()") + ) + } + val moduleB = createModuleInTmpDir("b") { + listOf( + FileWithText("b.kt", "fun bar(): Int = foo()") + ) + } + + moduleA.addKotlinStdlib() + moduleB.addKotlinStdlib() + + moduleA.addDependency(moduleB) + moduleB.addDependency(moduleA) + + val fileA = moduleA.findSourceKtFile("a.kt") + analyzeInModalWindow(fileA, "test") { + fileA.getFirstFunctionDeclaration().getBodyCallExpression().assertCalleeNameAndType(fileA, "bar", builtinTypes.INT) + } + + val fileB = moduleB.findSourceKtFile("b.kt") + analyzeInModalWindow(fileB, "test") { + fileB.getFirstFunctionDeclaration().getBodyCallExpression().assertCalleeNameAndType(fileB, "foo", builtinTypes.INT) + } + } + + private fun KtFile.getFirstFunctionDeclaration(): KtNamedFunction = declarations.firstIsInstance() + + private fun KtNamedFunction.getBodyCallExpression(): KtCallExpression = bodyExpression!! as KtCallExpression + + context(KtAnalysisSession) + private fun KtCallExpression.assertCalleeNameAndType(file: KtFile, expectedName: String, expectedType: KtType) { + val ktFunction = file.declarations.first() as KtNamedFunction + val ktCall = ktFunction.bodyExpression!! as KtCallExpression + + val ktCallee = ktCall.calleeExpression as KtSimpleNameExpression + Assert.assertEquals(expectedName, ktCallee.getReferencedName()) + + val callableSymbol = ktCall.resolveCall()!!.successfulFunctionCallOrNull()!!.symbol + Assert.assertEquals(expectedType, callableSymbol.returnType) + } +} diff --git a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt index c44478b13d2a..5be0b9140e80 100644 --- a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt +++ b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt @@ -5,11 +5,13 @@ package org.jetbrains.kotlin.idea.stubs import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase import com.intellij.openapi.Disposable import com.intellij.openapi.application.WriteAction +import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.externalSystem.service.project.ProjectDataManager import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleType import com.intellij.openapi.module.StdModuleTypes +import com.intellij.openapi.project.rootManager import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.* import com.intellij.openapi.roots.libraries.PersistentLibraryKind @@ -172,6 +174,15 @@ abstract class AbstractMultiModuleTest : DaemonAnalyzerTestCase() { } } + fun Module.addKotlinStdlib() = runWriteAction { + val modifiableModel = rootManager.modifiableModel + KotlinWithJdkAndRuntimeLightProjectDescriptor.JDK_AND_RUNTIME_LIGHT_PROJECT_DESCRIPTOR.configureModule( + this, + modifiableModel, + ) + modifiableModel.commit() + } + fun Module.findSourceKtFile(fileName: String): KtFile { val file = "${sourceRoots.first().url}/$fileName" val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! From 53c94c1b40f50c431ab90061c8b7b4ff2fbc130f Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 29 Jun 2023 16:08:16 +0200 Subject: [PATCH 044/165] [kotlin] Avoid `NullPointerException` in `ModuleInfoProvider` when `containingFile` is `null` - An error is already reported further above, so there is no need to report an error here. GitOrigin-RevId: a65c41e705f675ca1d6f3e0784ba25e8a19a6570 --- .../projectStructure/ModuleInfoProvider.kt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProvider.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProvider.kt index 8429871dcfef..168d3ff02171 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProvider.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProvider.kt @@ -155,14 +155,16 @@ class ModuleInfoProvider(private val project: Project) { } } - val virtualFile = containingFile.originalFile.virtualFile - if (virtualFile != null) { - val isLibrarySource = if (containingKtFile != null) isLibrarySource(containingKtFile, config) else false - collectByFile(virtualFile, isLibrarySource) - callExtensions { collectByElement(element, containingFile, virtualFile) } - } else { - val message = "Analyzing element of type ${element::class.java} in non-physical file of type ${containingFile::class.java}" - reportError(KotlinExceptionWithAttachments(message).withAttachment("file.kt", containingFile.text)) + if (containingFile != null) { + val virtualFile = containingFile.originalFile.virtualFile + if (virtualFile != null) { + val isLibrarySource = if (containingKtFile != null) isLibrarySource(containingKtFile, config) else false + collectByFile(virtualFile, isLibrarySource) + callExtensions { collectByElement(element, containingFile, virtualFile) } + } else { + val message = "Analyzing element of type ${element::class.java} in non-physical file of type ${containingFile::class.java}" + reportError(KotlinExceptionWithAttachments(message).withAttachment("file.kt", containingFile.text)) + } } } From 597836fe3eb831c0d2b8af9608a2dce17cbd223e Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 29 Jun 2023 16:10:44 +0200 Subject: [PATCH 045/165] [kotlin] KT-58257 FIR PSI tree change preprocessor: Avoid calling `getModule` on PSI elements without a containing file GitOrigin-RevId: ad1a5f6cad5512e2d107e50a9b94c0688d2d6d75 --- .../FirIdeOutOfBlockModificationService.kt | 9 +++++++++ .../FirIdeOutOfBlockPsiTreeChangePreprocessor.kt | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt index 1d3d1a6ebdfd..64c24caf37c4 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt @@ -54,6 +54,15 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo projectOutOfBlockModificationTracker.incModificationCount() } + /** + * Publishes out-of-block modification for [module]'s production and test source [KtModule]s and the project itself. Must be called in a + * write action. + */ + fun publishModuleAndProjectOutOfBlockModification(module: Module) { + publishModuleOutOfBlockModification(module) + projectOutOfBlockModificationTracker.incModificationCount() + } + fun publishGlobalOutOfBlockModification() { projectOutOfBlockModificationTracker.incModificationCount() diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt index f52881853365..703685b22a72 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.getNonLoca import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.invalidateAfterInBlockModification import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.idea.base.util.module import org.jetbrains.kotlin.psi.KtDeclaration @OptIn(LLFirInternals::class) @@ -63,6 +64,15 @@ internal class FirIdeOutOfBlockPsiTreeChangePreprocessor(private val project: Pr } private fun outOfBlockInvalidation(element: PsiElement) { + if (element.containingFile == null) { + // PSI elements without a containing file, such as `PsiJavaDirectory`, are not supported by `ProjectStructureProvider` + // and have no corresponding meaningful `KtModule`. + element.module?.let { module -> + FirIdeOutOfBlockModificationService.getInstance(project).publishModuleAndProjectOutOfBlockModification(module) + } + return + } + val module = ProjectStructureProvider.getModule(project, element, contextualModule = null) FirIdeOutOfBlockModificationService.getInstance(project).publishModuleAndProjectOutOfBlockModification(module) } From a4fed130293edbbae75eba25483d2fbe190c0716 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Fri, 30 Jun 2023 19:00:40 +0200 Subject: [PATCH 046/165] [kotlin] KT-58257 Cache transitive dependents in `IdeKotlinModuleDependentsProvider` - Without the cache, invalidation of modules with large sets of transitive dependents does not have acceptable performance (according to snapshots) when typing causes frequent out-of-block modification events. In my tests, a workspace model-related module in the `intellij` project had over 2000 transitive dependents. - The cache makes `getTransitiveDependents` in my local tests about 20-30x faster for the module with >2000 transitive dependents. The remaining impact of `getTransitiveDependents` is now negligible. GitOrigin-RevId: e3ce642b5fae770038b4a2a423484428ae8e4e89 --- ...veModuleDependentsCacheInvalidationTest.kt | 76 +++++++++++++++++++ .../kotlin.base.project-structure.iml | 1 + .../IdeKotlinModuleDependentsProvider.kt | 32 ++++++++ 3 files changed, 109 insertions(+) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/TransitiveModuleDependentsCacheInvalidationTest.kt diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/TransitiveModuleDependentsCacheInvalidationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/TransitiveModuleDependentsCacheInvalidationTest.kt new file mode 100644 index 000000000000..a81ba3060b48 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/TransitiveModuleDependentsCacheInvalidationTest.kt @@ -0,0 +1,76 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.dependents + +import org.jetbrains.kotlin.analysis.project.structure.KotlinModuleDependentsProvider +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule +import org.jetbrains.kotlin.idea.base.projectStructure.LibraryInfoCache +import org.jetbrains.kotlin.idea.base.projectStructure.getMainKtSourceModule +import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule +import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest +import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil +import org.jetbrains.kotlin.test.util.addDependency +import org.junit.Assert +import java.io.File + +/** + * This test ensures that cached transitive dependents of the IDE's [KotlinModuleDependentsProvider] are properly invalidated. + */ +class TransitiveModuleDependentsCacheInvalidationTest : AbstractMultiModuleTest() { + override fun getTestDataDirectory(): File = error("Should not be called") + + override fun isFirPlugin(): Boolean = true + + private val moduleDependentsProvider get() = KotlinModuleDependentsProvider.getInstance(project) + + fun `test that cached transitive dependents of a module are invalidated after adding a new dependent`() { + val moduleA = createModuleInTmpDir("a") + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + val moduleD = createModuleInTmpDir("d") + + moduleB.addDependency(moduleA) + moduleC.addDependency(moduleB) + + val ktModuleA = moduleA.getMainKtSourceModule()!! + + Assert.assertEquals( + setOf("b", "c"), + ktModuleA.getTransitiveDependentNames(), + ) + + moduleD.addDependency(moduleA) + + Assert.assertEquals( + setOf("b", "c", "d"), + ktModuleA.getTransitiveDependentNames(), + ) + } + + fun `test that cached transitive dependents of a library are invalidated after adding a new dependent`() { + val libraryA = ConfigLibraryUtil.addProjectLibraryWithClassesRoot(project, "a") + val moduleB = createModuleInTmpDir("b") + val moduleC = createModuleInTmpDir("c") + val moduleD = createModuleInTmpDir("d") + + moduleB.addDependency(libraryA) + moduleC.addDependency(moduleB) + + val ktModuleA = LibraryInfoCache.getInstance(project)[libraryA].first().toKtModule() + + Assert.assertEquals( + setOf("b", "c"), + ktModuleA.getTransitiveDependentNames(), + ) + + moduleD.addDependency(libraryA) + + Assert.assertEquals( + setOf("b", "c", "d"), + ktModuleA.getTransitiveDependentNames(), + ) + } + + private fun KtModule.getTransitiveDependentNames(): Set = + moduleDependentsProvider.getTransitiveDependents(this).mapTo(mutableSetOf()) { (it as KtSourceModule).moduleName } +} diff --git a/plugins/kotlin/base/project-structure/kotlin.base.project-structure.iml b/plugins/kotlin/base/project-structure/kotlin.base.project-structure.iml index 17399f405794..129a4ff8b328 100644 --- a/plugins/kotlin/base/project-structure/kotlin.base.project-structure.iml +++ b/plugins/kotlin/base/project-structure/kotlin.base.project-structure.iml @@ -46,5 +46,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt index c73ad90aefcb..4a3d0787aeba 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt @@ -1,11 +1,17 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.base.projectStructure +import com.github.benmanes.caffeine.cache.Cache +import com.github.benmanes.caffeine.cache.Caffeine import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.ProjectRootModificationTracker import com.intellij.platform.backend.workspace.WorkspaceModel import com.intellij.platform.workspace.jps.entities.ModuleEntity import com.intellij.platform.workspace.storage.SymbolicEntityId import com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId +import com.intellij.psi.util.CachedValue +import com.intellij.psi.util.CachedValueProvider +import com.intellij.psi.util.CachedValuesManager import com.intellij.workspaceModel.ide.impl.legacyBridge.module.findModule import org.jetbrains.kotlin.analysis.project.structure.KtBuiltinsModule import org.jetbrains.kotlin.analysis.project.structure.KtModule @@ -68,4 +74,30 @@ internal class IdeKotlinModuleDependentsProvider(private val project: Project) : addIfNotNull(moduleEntity.findModule(snapshot)?.productionOrTestSourceModuleInfo?.toKtModule()) } } + + /** + * Caching transitive dependents is crucial. [getTransitiveDependents] will frequently be called by session invalidation when typing in + * a Kotlin file. Large projects might have core modules with over a hundred or even a thousand transitive dependents. At the same time, + * we can keep the size of this cache small, because transitive dependents will usually only be requested for a single module (e.g. the + * module to be invalidated after an out-of-block modification). + * + * The timing of invalidation is important, since the [IdeKotlinModuleDependentsProvider] may be used in workspace model listeners when + * project structure changes. Using a *before change* workspace model listener is not an option, because we'd have to guarantee that + * this listener is placed after all other listeners which might use `IdeKotlinModuleDependentsProvider`. It's not entirely impossible + * due to the existence of `Fe10/FirOrderedWorkspaceModelChangeListener`, but a simpler solution such as the project root modification + * tracker, which is incremented after *before change* events have been handled, seems preferable. + */ + private val transitiveDependentsCache: CachedValue>> = CachedValuesManager.getManager(project).createCachedValue { + CachedValueProvider.Result.create( + Caffeine.newBuilder().maximumSize(100).build(), + ProjectRootModificationTracker.getInstance(project), + ) + } + + override fun getTransitiveDependents(module: KtModule): Set = + transitiveDependentsCache.value.get(module) { + // The computation does not reuse sub-results that may already have been cached because transitive dependents are usually only + // computed for select modules, so the performance impact of this computation is expected to be negligible. + computeTransitiveDependents(it) + } } From 99cdce663a846d97bc56e8cd73b2257dc1f7d618 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 6 Jul 2023 15:18:10 +0200 Subject: [PATCH 047/165] [kotlin] KT-58257 Temporarily disable a script deletion global source out-of-block modification test - The test triggers the issue described in IDEA-324516, which leads to a failing "project leak" test (which also checks stale indices), so the test needs to be disabled until that issue is fixed. GitOrigin-RevId: e8a722506ff1b7393b65cf9431964f3b5b2c9df4 --- ...nGlobalSourceOutOfBlockModificationTest.kt | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt index 642e299ed50c..78c5ff1c1fc9 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/KotlinGlobalSourceOutOfBlockModificationTest.kt @@ -77,17 +77,18 @@ class KotlinGlobalSourceOutOfBlockModificationTest : AbstractKotlinGlobalModific disposeTrackers(tracker) } - fun `test that global source out-of-block modification occurs after deleting a script file`() { - val scriptA = createScript("a") - - val tracker = createTracker() - - delete(scriptA.virtualFile) - - tracker.assertModified("the project after a script file is deleted", expectedEventCount = 2) - - disposeTrackers(tracker) - } + // TODO (marco): This test can be enabled once IDEA-324516 is fixed. + //fun `test that global source out-of-block modification occurs after deleting a script file`() { + // val scriptA = createScript("a") + // + // val tracker = createTracker() + // + // delete(scriptA.virtualFile) + // + // tracker.assertModified("the project after a script file is deleted", expectedEventCount = 2) + // + // disposeTrackers(tracker) + //} fun `test that global source out-of-block modification occurs after moving a not-under-content-root file to a non-source module content root`() { val fileA = createNotUnderContentRootFile("a") From ed1ad9a36295afb0bb88baf14cf277e582cb9d72 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 11 Jul 2023 22:19:11 +0200 Subject: [PATCH 048/165] [kotlin] KT-58257 Publish module modification events for test source modules as well - In case of session invalidation, we only want to publish an event for the production source module (or the test source module as a fallback), because the test source module is a friend dependent of the production source module. However, we also have to take use cases outside invalidation into account, where we cannot expect the subscriber to know that a production source module event implies an event for the test source module. - We can also almost keep the nice property that sessions are only invalidated once, despite the two separate events. Ordering the production source module first means that the test source module will be invalidated right away, allowing the session invalidation service to skip invalidation of the test source module on the second event. GitOrigin-RevId: 8119f5a2232febf01965b2aaeb2cf5343ffafb2d --- .../KotlinModuleStateModificationService.kt | 8 ++++---- .../idea/util/modificationEventUtils.kt | 19 +++++++++++++++++++ .../FirIdeOutOfBlockModificationService.kt | 9 +++------ 3 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/modificationEventUtils.kt diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 8b87133de02e..4a90fafc7cb1 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -35,17 +35,17 @@ import org.jetbrains.kotlin.analysis.providers.analysisMessageBus import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics import org.jetbrains.kotlin.idea.base.projectStructure.getBinaryAndSourceModuleInfos import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.IdeaModuleInfo -import org.jetbrains.kotlin.idea.base.projectStructure.productionOrTestSourceModuleInfo import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule import org.jetbrains.kotlin.idea.util.AbstractSingleFileModuleBeforeFileEventListener +import org.jetbrains.kotlin.idea.util.toKtModulesForModificationEvents open class KotlinModuleStateModificationService(val project: Project) : Disposable { protected open fun mayBuiltinsHaveChanged(events: List): Boolean { return false } private fun invalidateSourceModule(module: Module, isRemoval: Boolean = false) { - // A test source `KtModule` will be invalidated together with its production source `KtModule` because it is a direct dependent from - // friend dependencies. See `IdeKotlinModuleDependentsProvider`. - module.productionOrTestSourceModuleInfo?.let { project.publishModuleStateModification(it.toKtModule(), isRemoval) } + module.toKtModulesForModificationEvents().forEach { ktModule -> + project.publishModuleStateModification(ktModule, isRemoval) + } } private fun invalidateLibraryModule(library: Library, isRemoval: Boolean = false) { diff --git a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/modificationEventUtils.kt b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/modificationEventUtils.kt new file mode 100644 index 000000000000..1dbfb89f4227 --- /dev/null +++ b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/util/modificationEventUtils.kt @@ -0,0 +1,19 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.util + +import com.intellij.openapi.module.Module +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.idea.base.projectStructure.productionSourceInfo +import org.jetbrains.kotlin.idea.base.projectStructure.testSourceInfo +import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule + +/** + * Returns the [KtModule]s for which modification events need to be published when this [Module] is affected. + * + * An event should be published for the production source info first, so this function cannot use `sourceModuleInfos` as is. Ordering the + * production source module first allows some subscribers like session invalidation to *also* invalidate the test source module right away + * via friend dependencies. Then the invalidation service can quickly skip invalidation of the test source module on the second event, as it + * will already be invalidated. + */ +fun Module.toKtModulesForModificationEvents(): List = + listOfNotNull(productionSourceInfo?.toKtModule(), testSourceInfo?.toKtModule()) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt index 64c24caf37c4..605887ebd76f 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt @@ -11,8 +11,7 @@ import com.intellij.openapi.util.SimpleModificationTracker import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.providers.analysisMessageBus import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics -import org.jetbrains.kotlin.idea.base.projectStructure.productionOrTestSourceModuleInfo -import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule +import org.jetbrains.kotlin.idea.util.toKtModulesForModificationEvents /** * [FirIdeOutOfBlockModificationService] increments modification trackers and publishes subscription events on out-of-block modification @@ -38,12 +37,10 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo } /** - * Publishes out-of-block modification for [module]. Must be called in a write action. + * Publishes out-of-block modification for [module]'s production and test source [KtModule]s. Must be called in a write action. */ fun publishModuleOutOfBlockModification(module: Module) { - // A test source `KtModule` will be invalidated together with its production source `KtModule` because it is a direct dependent from - // friend dependencies. See `IdeKotlinModuleDependentsProvider`. - module.productionOrTestSourceModuleInfo?.let { publishModuleOutOfBlockModification(it.toKtModule()) } + module.toKtModulesForModificationEvents().forEach { publishModuleOutOfBlockModification(it) } } /** From 6733dc673e82c0bf04d386883ca684553b0f516b Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 11 Jul 2023 22:34:57 +0200 Subject: [PATCH 049/165] [kotlin] KTIJ-26241 Support library dependents of anchor modules in `IdeKotlinModuleDependentsProvider` - For specifics, please consult the linked issue, or documentation in `IdeKotlinModuleDependentsProvider.addAnchorModuleDependents`. ^KTIJ-26241 fixed GitOrigin-RevId: 64c7a8942ca736e5677fd12342ffe30688ea5cfa --- .../resolve/ResolutionAnchorCacheService.kt | 62 +++++++++---------- .../IdeKotlinModuleDependentsProvider.kt | 28 +++++++++ .../ResolutionAnchorCacheService.kt | 3 + .../util/libraryDependenciesUtil.kt | 32 ++++++++++ 4 files changed, 92 insertions(+), 33 deletions(-) create mode 100644 plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/util/libraryDependenciesUtil.kt diff --git a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ResolutionAnchorCacheService.kt b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ResolutionAnchorCacheService.kt index 8b604c1cd98a..2c2d5c38db96 100644 --- a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ResolutionAnchorCacheService.kt +++ b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ResolutionAnchorCacheService.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.idea.base.projectStructure.LibraryDependenciesCache import org.jetbrains.kotlin.idea.base.projectStructure.libraryToSourceAnalysis.ResolutionAnchorCacheService import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.LibraryInfo import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.ModuleSourceInfo +import org.jetbrains.kotlin.idea.base.projectStructure.util.getTransitiveLibraryDependencyInfos import org.jetbrains.kotlin.idea.caches.project.getModuleInfosFromIdeaModel import org.jetbrains.kotlin.idea.caches.trackers.ModuleModificationTracker import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus.checkCanceled @@ -46,16 +47,27 @@ class ResolutionAnchorCacheServiceImpl( myState = State(mapping) } - override val resolutionAnchorsForLibraries: Map + private class AnchorMapping( + val anchorByLibrary: Map, + val librariesByAnchor: Map>, + ) + + private val anchorMapping: AnchorMapping get() = CachedValuesManager.getManager(project).getCachedValue(project) { CachedValueProvider.Result.create( - mapResolutionAnchorForLibraries(), - ModuleModificationTracker.getInstance(project), - JavaLibraryModificationTracker.getInstance(project) + createResolutionAnchorMapping(), + ModuleModificationTracker.getInstance(project), + JavaLibraryModificationTracker.getInstance(project) ) } + override val resolutionAnchorsForLibraries: Map + get() = anchorMapping.anchorByLibrary + + override val librariesForResolutionAnchors: Map> + get() = anchorMapping.librariesByAnchor + private val resolutionAnchorDependenciesCache: MutableMap> get() = CachedValuesManager.getManager(project).getCachedValue(project) { @@ -71,13 +83,7 @@ class ResolutionAnchorCacheServiceImpl( return it } - val allTransitiveLibraryDependencies = with(LibraryDependenciesCache.getInstance(project)) { - val directDependenciesOnLibraries = getLibraryDependencies(libraryInfo).libraries - directDependenciesOnLibraries.closure { libraryDependency -> - checkCanceled() - getLibraryDependencies(libraryDependency).libraries - } - } + val allTransitiveLibraryDependencies = LibraryDependenciesCache.getInstance(project).getTransitiveLibraryDependencyInfos(libraryInfo) val dependencyResolutionAnchors = allTransitiveLibraryDependencies.mapNotNullTo(mutableSetOf()) { resolutionAnchorsForLibraries[it] } resolutionAnchorDependenciesCache.putIfAbsent(libraryInfo, dependencyResolutionAnchors)?.let { @@ -106,41 +112,31 @@ class ResolutionAnchorCacheServiceImpl( } } - private fun mapResolutionAnchorForLibraries(): Map { + private fun createResolutionAnchorMapping(): AnchorMapping { val modulesByNames: Map = associateModulesByNames() - return myState.moduleNameToAnchorName.entries.mapNotNull { (libraryName, anchorName) -> + val anchorByLibrary = mutableMapOf() + val librariesByAnchor = mutableMapOf>() + + myState.moduleNameToAnchorName.entries.forEach { (libraryName, anchorName) -> val library: LibraryInfo = modulesByNames[libraryName]?.safeAs() ?: run { logger.warn("Resolution anchor mapping key doesn't point to a known library: $libraryName. Skipping this anchor") - return@mapNotNull null + return@forEach } val anchor: ModuleSourceInfo = modulesByNames[anchorName]?.safeAs() ?: run { logger.warn("Resolution anchor mapping value doesn't point to a source module: $anchorName. Skipping this anchor") - return@mapNotNull null + return@forEach } - library to anchor - }.toMap() + anchorByLibrary.put(library, anchor) + librariesByAnchor.getOrPut(anchor) { mutableListOf() }.add(library) + } + + return AnchorMapping(anchorByLibrary, librariesByAnchor) } companion object { private val logger = logger() } } -fun Collection.closure(f: (T) -> Collection): Collection { - if (isEmpty()) return this - - val result = HashSet(this) - var elementsToCheck = result - var oldSize = 0 - while (result.size > oldSize) { - oldSize = result.size - val toAdd = hashSetOf() - elementsToCheck.forEach { toAdd.addAll(f(it)) } - result.addAll(toAdd) - elementsToCheck = toAdd - } - - return result -} diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt index 4a3d0787aeba..4324466ad06c 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt @@ -19,7 +19,10 @@ import org.jetbrains.kotlin.analysis.project.structure.KtScriptDependencyModule import org.jetbrains.kotlin.analysis.project.structure.KtScriptModule import org.jetbrains.kotlin.analysis.project.structure.KtSdkModule import org.jetbrains.kotlin.analysis.project.structure.impl.KotlinModuleDependentsProviderBase +import org.jetbrains.kotlin.idea.base.projectStructure.libraryToSourceAnalysis.ResolutionAnchorCacheService import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.ModuleProductionSourceInfo +import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.ModuleSourceInfo +import org.jetbrains.kotlin.idea.base.projectStructure.util.getTransitiveLibraryDependencyInfos import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments import org.jetbrains.kotlin.utils.addIfNotNull @@ -48,6 +51,7 @@ internal class IdeKotlinModuleDependentsProvider(private val project: Project) : val directDependents = mutableSetOf() directDependents.addFriendDependents(module) directDependents.addWorkspaceModelDependents(symbolicId) + directDependents.addAnchorModuleDependents(module) return directDependents } @@ -75,6 +79,30 @@ internal class IdeKotlinModuleDependentsProvider(private val project: Project) : } } + private fun MutableSet.addAnchorModuleDependents(module: KtModule) { + val moduleInfo = (module as? KtSourceModuleByModuleInfo)?.ideaModuleInfo as? ModuleSourceInfo ?: return + + // If `module` is an anchor module, it has library dependents in the form of anchoring libraries. See + // `ResolutionAnchorCacheService` for additional documentation. + val anchoringLibraries = ResolutionAnchorCacheService.getInstance(project).librariesForResolutionAnchors[moduleInfo] ?: return + + // Because dependency relationships between libraries aren't supported by the project model (as noted in + // `ResolutionAnchorCacheService`), library dependencies are approximated by the following relationship: If a module `M1` depends on + // two libraries `L1` and `L2`, `L1` depends on `L2` and `L2` depends on `L1` (`L1 <--> L2`). This does not apply without + // restriction for multi-platform projects. However, anchor module usage is strictly limited to the `intellij` project, which is not + // a multi-platform project. Because the approximate library dependencies are bidirectional, library dependencies are also library + // dependents, and we can simply use `getTransitiveLibraryDependencyInfos`. + // + // Because anchor modules are rare and `getTransitiveDependents` already caches dependents as a whole, there is currently no need to + // cache these transitive library dependencies. + LibraryDependenciesCache.getInstance(project) + .getTransitiveLibraryDependencyInfos(anchoringLibraries) + .forEach { libraryInfo -> + add(libraryInfo.toKtModule()) + add(libraryInfo.sourcesModuleInfo.toKtModule()) + } + } + /** * Caching transitive dependents is crucial. [getTransitiveDependents] will frequently be called by session invalidation when typing in * a Kotlin file. Large projects might have core modules with over a hundred or even a thousand transitive dependents. At the same time, diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/libraryToSourceAnalysis/ResolutionAnchorCacheService.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/libraryToSourceAnalysis/ResolutionAnchorCacheService.kt index 701e2f81c885..bc9b5f8d2b7a 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/libraryToSourceAnalysis/ResolutionAnchorCacheService.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/libraryToSourceAnalysis/ResolutionAnchorCacheService.kt @@ -9,6 +9,8 @@ import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.ModuleSourceIn interface ResolutionAnchorCacheService { val resolutionAnchorsForLibraries: Map + val librariesForResolutionAnchors: Map> + /** * Anchor module is a source module that could replace library. * @@ -29,6 +31,7 @@ interface ResolutionAnchorCacheService { companion object { val Empty = object : ResolutionAnchorCacheService { override val resolutionAnchorsForLibraries: Map get() = emptyMap() + override val librariesForResolutionAnchors: Map> get() = emptyMap() override fun getDependencyResolutionAnchors(libraryInfo: LibraryInfo): Set = emptySet() } diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/util/libraryDependenciesUtil.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/util/libraryDependenciesUtil.kt new file mode 100644 index 000000000000..bc61d8cb6691 --- /dev/null +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/util/libraryDependenciesUtil.kt @@ -0,0 +1,32 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.base.projectStructure.util + +import org.jetbrains.kotlin.idea.base.projectStructure.LibraryDependenciesCache +import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.LibraryInfo +import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus.checkCanceled + +fun LibraryDependenciesCache.getTransitiveLibraryDependencyInfos(libraryInfo: LibraryInfo): Collection = + getTransitiveLibraryDependencyInfos(getLibraryDependencies(libraryInfo).libraries) + +fun LibraryDependenciesCache.getTransitiveLibraryDependencyInfos(libraryInfos: Collection): Collection = + libraryInfos.closure { libraryDependency -> + checkCanceled() + getLibraryDependencies(libraryDependency).libraries + } + +private fun Collection.closure(f: (T) -> Collection): Collection { + if (isEmpty()) return this + + val result = HashSet(this) + var elementsToCheck = result + var oldSize = 0 + while (result.size > oldSize) { + oldSize = result.size + val toAdd = hashSetOf() + elementsToCheck.forEach { toAdd.addAll(f(it)) } + result.addAll(toAdd) + elementsToCheck = toAdd + } + + return result +} From 30780b5d140656bf2f72a89944ad7150be963de9 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 12 Jul 2023 22:02:58 +0200 Subject: [PATCH 050/165] [kotlin] KT-58257 Implement `IdeKotlinAnchorModuleProvider.getAllAnchorModules` GitOrigin-RevId: 8b054e3de0bfede122f69e3fc31fb3e549bb04fd --- .../IdeKotlinAnchorModuleProvider.kt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/IdeKotlinAnchorModuleProvider.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/IdeKotlinAnchorModuleProvider.kt index 83a07488749a..0f6d269b47c0 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/IdeKotlinAnchorModuleProvider.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/IdeKotlinAnchorModuleProvider.kt @@ -5,7 +5,7 @@ import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule import org.jetbrains.kotlin.analysis.providers.KotlinAnchorModuleProvider -import org.jetbrains.kotlin.idea.base.projectStructure.libraryToSourceAnalysis.ResolutionAnchorCacheService.Companion.getInstance +import org.jetbrains.kotlin.idea.base.projectStructure.libraryToSourceAnalysis.ResolutionAnchorCacheService import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.LibraryInfo import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule @@ -15,6 +15,11 @@ class IdeKotlinAnchorModuleProvider(val project: Project) : KotlinAnchorModulePr override fun getAnchorModule(libraryModule: KtLibraryModule): KtSourceModule? { @OptIn(Frontend10ApiUsage::class) val libraryInfo = libraryModule.moduleInfo as? LibraryInfo ?: return null - return getInstance(project).resolutionAnchorsForLibraries[libraryInfo]?.toKtModule() as? KtSourceModule + return ResolutionAnchorCacheService.getInstance(project).resolutionAnchorsForLibraries[libraryInfo]?.toKtModule() as? KtSourceModule } -} \ No newline at end of file + + override fun getAllAnchorModules(): Collection = + ResolutionAnchorCacheService.getInstance(project) + .librariesForResolutionAnchors.keys + .mapNotNull { it.toKtModule() as? KtSourceModule } +} From 60670d889826af7e3766c53586358ef58c8b6a95 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 12 Jul 2023 22:11:16 +0200 Subject: [PATCH 051/165] [kotlin] KT-58257 Don't publish global source out-of-block modification events on PSI roots changes - Roots changes cause module state modification events, because this allows granular session invalidation limited to the modified module's dependents. Publishing a global out-of-block modification event on roots changes, which invalidates all source modules at once, undermines this effort. - Roots changes are propagated to `FirIdeOutOfBlockPsiTreeChangePreprocessor` via an "after change" workspace model listener (in detail, the `LegacyProjectModelListenersBridge` workspace model listener invokes the `ModuleRootListener` of `PsiVFSListener`, which in turn publishes the PSI roots changed event). If that listener is registered before the workspace model listener of `ModuleCache` (which is certain because `ModuleCache` subscribes lazily), then a subscriber of global out-of-block modification events such as `LLFirSessionInvalidationService` cannot access the `ModuleCache` (even indirectly via services such as `KotlinAnchorModuleProvider`) because the cache may be out of sync. - Module state modification events published by `KotlinModuleStateModificationService` are triggered properly *before* the actual roots change, which allows subscribers to still access the modules. Global PSI root changes can be triggered after the root has already been changed, which is unfortunate timing because some modules may be disposed. - `KotlinModuleStateModificationService` also only publishes module modification events when needed. For example, we do not need to publish any event for a module which has no content roots yet, because no `KtModule`s can exist for it. A roots PSI tree change event, on the other hand, cannot distinguish such cases, which contributes to event and session invalidation spam. - Any bugs with missing events that this change may cause should be fixed by expanding `KotlinModuleStateModificationService`, but I couldn't find any such missing cases. I believe anything covered by `PsiTreeChangeEvent.PROP_ROOTS` can be covered by a proper workspace model listener. GitOrigin-RevId: cb57d0ccc000d77317af37bc93130177499f5aa7 --- .../FirIdeOutOfBlockModificationService.kt | 2 +- ...irIdeOutOfBlockPsiTreeChangePreprocessor.kt | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt index 605887ebd76f..83a19a7eb9d7 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockModificationService.kt @@ -60,7 +60,7 @@ internal class FirIdeOutOfBlockModificationService(val project: Project) : Dispo projectOutOfBlockModificationTracker.incModificationCount() } - fun publishGlobalOutOfBlockModification() { + fun publishGlobalSourceOutOfBlockModification() { projectOutOfBlockModificationTracker.incModificationCount() // We should not invalidate binary module content here, because global PSI tree changes have no effect on binary modules. diff --git a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt index 703685b22a72..95b66132dc71 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeOutOfBlockPsiTreeChangePreprocessor.kt @@ -12,6 +12,7 @@ import com.intellij.psi.impl.PsiTreeChangePreprocessor import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirInternals import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.getNonLocalReanalyzableContainingDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.invalidateAfterInBlockModification +import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.base.util.module @@ -28,7 +29,7 @@ internal class FirIdeOutOfBlockPsiTreeChangePreprocessor(private val project: Pr } if (event.isGlobalChange()) { - FirIdeOutOfBlockModificationService.getInstance(project).publishGlobalOutOfBlockModification() + FirIdeOutOfBlockModificationService.getInstance(project).publishGlobalSourceOutOfBlockModification() return } @@ -105,11 +106,18 @@ internal class FirIdeOutOfBlockPsiTreeChangePreprocessor(private val project: Pr } } - // Copy logic from PsiModificationTrackerImpl.treeChanged(). Some out-of-code-block events are written to language modification - // tracker in PsiModificationTrackerImpl but don't have correspondent PomModelEvent. Increase kotlinOutOfCodeBlockTracker - // manually if needed. + /** + * The logic for detecting global changes is taken from [PsiModificationTrackerImpl], with the following difference. + * + * We don't want to publish any global out-of-block modification on roots changes, because relevant roots changes already cause module + * state modification events. Such a module state modification event includes the exact module that was affected by the roots change, + * instead of a less specific global out-of-block modification event. This allows a consumer such as session invalidation to invalidate + * sessions more granularly. Additionally, many roots changes don't require any event to be published because a corresponding [KtModule] + * does not exist for the changed module (e.g. when no content roots have been added yet), so roots changes [PsiTreeChangeEvent]s are + * overzealous, while the module state modification service can handle such cases gracefully. + */ private fun PsiTreeChangeEventImpl.isGlobalChange() = when (code) { - PsiEventType.PROPERTY_CHANGED -> propertyName === PsiTreeChangeEvent.PROP_UNLOADED_PSI || propertyName === PsiTreeChangeEvent.PROP_ROOTS + PsiEventType.PROPERTY_CHANGED -> propertyName === PsiTreeChangeEvent.PROP_UNLOADED_PSI PsiEventType.CHILD_MOVED -> oldParent is PsiDirectory || newParent is PsiDirectory else -> parent is PsiDirectory } From 36a5950c84d14a5f50d3e648f789d7a04f52d463 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 13 Jul 2023 15:03:23 +0200 Subject: [PATCH 052/165] [kotlin] KT-58257 Turn `LibraryUpdatesListener` into a "before change" listener - We want module state modification events to guarantee that the event is published before a module is removed, so that the provided `KtModule` can still be used without fear of it being disposed. - `LibraryUpdatesListener` is the only listener which had been publishing module state modification events *after* the change. GitOrigin-RevId: 42f4b9280c54b85b952a3bb27d34b3684daa658e --- .../KotlinModuleStateModificationService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 4a90fafc7cb1..c0fcedde6909 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -82,7 +82,7 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab private val moduleStateModificationService: KotlinModuleStateModificationService get() = getInstance(project) - override fun after(events: List) { + override fun before(events: List) { if (moduleStateModificationService.mayBuiltinsHaveChanged(events)) { KotlinGlobalModificationService.getInstance(project).publishGlobalModuleStateModification() return From c6d3d100109a35e6203feb7c1bdb94e0edcc1987 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 18 Jul 2023 16:45:09 +0200 Subject: [PATCH 053/165] [kotlin] KT-58257 Adapt to new `KotlinModuleStateModificationKind` enum GitOrigin-RevId: 6488a21de42caf510431553d111de258058b23c9 --- .../KotlinModuleStateModificationService.kt | 33 ++++++++++++------- ...stractKotlinModuleModificationEventTest.kt | 7 ++-- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index c0fcedde6909..7a4f40a2fa09 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -32,6 +32,7 @@ import org.jetbrains.annotations.ApiStatus import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.providers.KotlinGlobalModificationService import org.jetbrains.kotlin.analysis.providers.analysisMessageBus +import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleStateModificationKind import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics import org.jetbrains.kotlin.idea.base.projectStructure.getBinaryAndSourceModuleInfos import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.IdeaModuleInfo @@ -42,19 +43,25 @@ import org.jetbrains.kotlin.idea.util.toKtModulesForModificationEvents open class KotlinModuleStateModificationService(val project: Project) : Disposable { protected open fun mayBuiltinsHaveChanged(events: List): Boolean { return false } - private fun invalidateSourceModule(module: Module, isRemoval: Boolean = false) { + private fun invalidateSourceModule( + module: Module, + modificationKind: KotlinModuleStateModificationKind = KotlinModuleStateModificationKind.UPDATE, + ) { module.toKtModulesForModificationEvents().forEach { ktModule -> - project.publishModuleStateModification(ktModule, isRemoval) + project.publishModuleStateModification(ktModule, modificationKind) } } - private fun invalidateLibraryModule(library: Library, isRemoval: Boolean = false) { - invalidateByModuleInfos(library.getBinaryAndSourceModuleInfos(project), isRemoval) + private fun invalidateLibraryModule( + library: Library, + modificationKind: KotlinModuleStateModificationKind = KotlinModuleStateModificationKind.UPDATE, + ) { + invalidateByModuleInfos(library.getBinaryAndSourceModuleInfos(project), modificationKind) } - private fun invalidateByModuleInfos(moduleInfos: Iterable, isRemoval: Boolean) { + private fun invalidateByModuleInfos(moduleInfos: Iterable, modificationKind: KotlinModuleStateModificationKind) { moduleInfos.forEach { moduleInfo -> - project.publishModuleStateModification(moduleInfo.toKtModule(), isRemoval) + project.publishModuleStateModification(moduleInfo.toKtModule(), modificationKind) } } @@ -73,7 +80,11 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab override fun isRelevantEvent(event: VFileEvent, file: VirtualFile): Boolean = event is VFileMoveEvent || event is VFileDeleteEvent override fun processEvent(event: VFileEvent, module: KtModule) { - project.publishModuleStateModification(module, isRemoval = event is VFileDeleteEvent) + val modificationKind = when (event) { + is VFileDeleteEvent -> KotlinModuleStateModificationKind.REMOVAL + else -> KotlinModuleStateModificationKind.UPDATE + } + project.publishModuleStateModification(module, modificationKind) } } @@ -163,7 +174,7 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab is EntityChange.Removed -> { change.oldEntity .findLibraryBridge(event.storageBefore) - ?.let { invalidateLibraryModule(it, isRemoval = true) } + ?.let { invalidateLibraryModule(it, KotlinModuleStateModificationKind.REMOVAL) } } is EntityChange.Replaced -> { @@ -186,7 +197,7 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab is EntityChange.Added -> {} is EntityChange.Removed -> { change.oldEntity.findModule(event.storageBefore)?.let { module -> - invalidateSourceModule(module, isRemoval = true) + invalidateSourceModule(module, KotlinModuleStateModificationKind.REMOVAL) add(module) } } @@ -221,6 +232,6 @@ private fun EntityChange.Replaced.getReplacedEntity( return new } -private fun Project.publishModuleStateModification(module: KtModule, isRemoval: Boolean) { - analysisMessageBus.syncPublisher(KotlinTopics.MODULE_STATE_MODIFICATION).onModification(module, isRemoval) +private fun Project.publishModuleStateModification(module: KtModule, modificationKind: KotlinModuleStateModificationKind) { + analysisMessageBus.syncPublisher(KotlinTopics.MODULE_STATE_MODIFICATION).onModification(module, modificationKind) } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModuleModificationEventTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModuleModificationEventTest.kt index 16b2df817931..13cb02c3b6cb 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModuleModificationEventTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/modificationEvents/AbstractKotlinModuleModificationEventTest.kt @@ -5,6 +5,7 @@ import com.intellij.openapi.module.Module import com.intellij.openapi.roots.libraries.Library import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider +import org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleStateModificationKind import org.jetbrains.kotlin.idea.base.projectStructure.LibraryInfoCache import org.jetbrains.kotlin.idea.base.projectStructure.productionSourceInfo import org.jetbrains.kotlin.idea.base.projectStructure.toKtModule @@ -28,13 +29,13 @@ abstract class ModuleModificationEventTracker( private val module: KtModule, eventKind: String, ) : ModificationEventTracker(module.project, eventKind) { - fun handleEvent(eventModule: KtModule, isRemoval: Boolean) { + fun handleEvent(eventModule: KtModule, modificationKind: KotlinModuleStateModificationKind) { if (eventModule == module) { - receivedEvents.add(ReceivedEvent(isRemoval)) + receivedEvents.add(ReceivedEvent(modificationKind == KotlinModuleStateModificationKind.REMOVAL)) } } fun handleEvent(eventModule: KtModule) { - handleEvent(eventModule, isRemoval = false) + handleEvent(eventModule, KotlinModuleStateModificationKind.UPDATE) } } From 65c8b90e6e4da6e103a30a8add47b6f4716b43d3 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 18 Jul 2023 20:40:19 +0200 Subject: [PATCH 054/165] [kotlin] KT-58257 Listen to non-workspace module root events in `KotlinModuleStateModificationService` GitOrigin-RevId: 6ea844e4d6a1ff99bb77fd578f05ba2c03a41e66 --- .../KotlinModuleStateModificationService.kt | 13 +++++++++++++ .../kotlin.base.fir.analysis-api-providers.xml | 2 ++ 2 files changed, 15 insertions(+) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 7a4f40a2fa09..9274b76d5e19 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -8,6 +8,8 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.ProjectJdkTable import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.LibraryOrderEntry +import com.intellij.openapi.roots.ModuleRootEvent +import com.intellij.openapi.roots.ModuleRootListener import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.StandardFileSystems @@ -121,6 +123,17 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab } } + class NonWorkspaceModuleRootListener(private val project: Project) : ModuleRootListener { + override fun beforeRootsChange(event: ModuleRootEvent) { + if (event.isCausedByWorkspaceModelChangesOnly) return + + // The cases described in `isCausedByWorkspaceModelChangesOnly` are rare enough to publish global module state modification + // events for simplicity. `NonWorkspaceModuleRootListener` can eventually be removed once the APIs described in + // `isCausedByWorkspaceModelChangesOnly` are removed. + KotlinGlobalModificationService.getInstance(project).publishGlobalModuleStateModification() + } + } + @ApiStatus.Internal fun beforeWorkspaceModelChanged(event: VersionedStorageChange) { handleLibraryChanges(event) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml index 221c0bd73f81..9ce80aec079f 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml +++ b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml @@ -22,6 +22,8 @@ topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/> + From 16d8da92d6650210f4f88b1da4dfadd20df15bb1 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Fri, 21 Jul 2023 15:56:50 +0200 Subject: [PATCH 055/165] [kotlin] KT-58257 Add support for multiple targets in `AbstractModuleDependentsTest` - This allows us to check the dependents of all libraries and modules defined in the test project structure, without duplicating the same project structure in multiple tests. - This makes the test data subcategories `moduleTargets` and `libraryTargets` meaningless and allows us to merge certain tests. GitOrigin-RevId: daeae01621791d860e1440664cf7492a9f3c7bad --- .../providers/AbstractProjectStructureTest.kt | 20 ++--- .../AbstractModuleDependentsTest.kt | 72 +++++++++++---- .../ModuleDependentsTestGenerated.java | 88 +++++++------------ .../TestProjectEntityReference.kt | 8 +- .../TestProjectStructure.kt | 4 +- .../testProjectStructure/jsonUtils.kt | 9 ++ .../binaryTree/structure.json | 56 ++++++++++++ .../moduleDependents/cyclical/structure.json | 32 +++++++ .../cyclicalSelf/structure.json | 18 ++++ .../structure.json | 30 +++++++ .../libraryTargets/cyclical/structure.json | 13 --- .../libraryTargets/rhombus/structure.json | 15 ---- .../libraryTargets/rhombus2/structure.json | 15 ---- .../libraryTargets/singleRoot/structure.json | 20 ----- .../moduleDependents/linear/structure.json | 44 ++++++++++ .../moduleTargets/binaryTree/structure.json | 14 --- .../moduleTargets/cyclical/structure.json | 10 --- .../moduleTargets/cyclicalSelf/structure.json | 9 -- .../structure.json | 11 --- .../moduleTargets/linear/structure.json | 15 ---- .../moduleTargets/rhombus/structure.json | 11 --- .../moduleDependents/rhombus/structure.json | 44 ++++++++++ .../singleRoot/structure.json | 74 ++++++++++++++++ .../fir/testGenerator/FirGenerateTests.kt | 3 +- 24 files changed, 411 insertions(+), 224 deletions(-) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/jsonUtils.kt create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/cyclical/structure.json delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus/structure.json delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus2/structure.json delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/singleRoot/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/binaryTree/structure.json delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclical/structure.json delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalSelf/structure.json delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalWithOutsideDependency/structure.json delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/linear/structure.json delete mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/rhombus/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/singleRoot/structure.json diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt index 8f7a30e6c240..5abca5f644e9 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt @@ -12,42 +12,42 @@ import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import org.jetbrains.kotlin.test.util.addDependency import java.nio.file.Paths -typealias ProjectLibrariesByNames = Map -typealias ModulesByNames = Map +typealias ProjectLibrariesByName = Map +typealias ModulesByName = Map abstract class AbstractProjectStructureTest : AbstractMultiModuleTest() { protected fun initializeProjectStructure( path: String, parser: TestProjectStructureParser, - ): Triple { + ): Triple { val testStructure = TestProjectStructureReader.readToTestStructure( Paths.get(path), testProjectStructureParser = parser, ) - val projectLibrariesByNames = testStructure.libraries.associate { libraryData -> + val projectLibrariesByName = testStructure.libraries.associate { libraryData -> libraryData.name to createProjectLibrary(libraryData.name) } - val modulesByNames = testStructure.modules.associate { moduleData -> + val modulesByName = testStructure.modules.associate { moduleData -> moduleData.name to createEmptyModule(moduleData.name) } - val duplicateNames = projectLibrariesByNames.keys.intersect(modulesByNames.keys) + val duplicateNames = projectLibrariesByName.keys.intersect(modulesByName.keys) if (duplicateNames.isNotEmpty()) { error("Test project libraries and modules may not share names. Duplicate names: ${duplicateNames.joinToString()}.") } testStructure.modules.forEach { moduleData -> - val module = modulesByNames.getValue(moduleData.name) + val module = modulesByName.getValue(moduleData.name) moduleData.dependsOnModules.forEach { dependencyName -> - projectLibrariesByNames[dependencyName] + projectLibrariesByName[dependencyName] ?.let { library -> module.addDependency(library) } - ?: module.addDependency(modulesByNames.getValue(dependencyName)) + ?: module.addDependency(modulesByName.getValue(dependencyName)) } } - return Triple(testStructure, projectLibrariesByNames, modulesByNames) + return Triple(testStructure, projectLibrariesByName, modulesByName) } private fun createProjectLibrary(name: String): Library = ConfigLibraryUtil.addProjectLibraryWithClassesRoot(project, name) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt index b97125a0e103..062325b743bd 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/AbstractModuleDependentsTest.kt @@ -18,6 +18,10 @@ import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.Tes import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.TestProjectEntityReferenceParser import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.TestProjectLibraryReference import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.TestProjectModuleReference +import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.getAsJsonObjectList +import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.getAsStringList +import org.jetbrains.kotlin.idea.fir.analysis.providers.ProjectLibrariesByName +import org.jetbrains.kotlin.idea.fir.analysis.providers.ModulesByName abstract class AbstractModuleDependentsTest : AbstractProjectStructureTest() { override fun isFirPlugin(): Boolean = true @@ -25,46 +29,60 @@ abstract class AbstractModuleDependentsTest : AbstractProjectStructureTest - LibraryInfoCache.getInstance(project)[projectLibrariesByName.getValue(target.name)].first().toKtModule() + LibraryInfoCache.getInstance(project)[projectLibrariesByName.getValue(entityReference.name)].first().toKtModule() is TestProjectModuleReference -> - modulesByNames.getValue(target.name).getMainKtSourceModule()!! + modulesByName.getValue(entityReference.name).getMainKtSourceModule()!! } - val moduleDependentsProvider = KotlinModuleDependentsProvider.getInstance(project) - val directDependents = moduleDependentsProvider.getDirectDependents(targetModule) assertEquals( - testStructure.directDependents, + "Direct dependents of ${entityReference.name}:", + target.directDependents, directDependents.map { (it as KtSourceModule).moduleName }.toSet(), ) val transitiveDependents = moduleDependentsProvider.getTransitiveDependents(targetModule) assertEquals( - testStructure.transitiveDependents, + "Transitive dependents of ${entityReference.name}:", + target.transitiveDependents, transitiveDependents.map { (it as KtSourceModule).moduleName }.toSet(), ) } } +/** + * The module dependents test supports multiple module/library targets, which allows checking module dependents of all `KtModule`s defined + * in the project structure, without duplicating the same project structure in multiple tests. + */ data class ModuleDependentsTestProjectStructure( override val libraries: List, override val modules: List, - val target: TestProjectEntityReference, - val directDependents: Set, - val transitiveDependents: Set, + val targets: List, ) : TestProjectStructure private object ModuleDependentsTestProjectStructureParser : TestProjectStructureParser { - private const val TARGET_FIELD = "target" - private const val DIRECT_DEPENDENTS_FIELD = "directDependents" - private const val TRANSITIVE_DEPENDENTS_FIELD = "transitiveDependents" + private const val TARGETS_FIELD = "targets" override fun parse( libraries: List, @@ -73,8 +91,28 @@ private object ModuleDependentsTestProjectStructureParser : TestProjectStructure ): ModuleDependentsTestProjectStructure = ModuleDependentsTestProjectStructure( libraries, modules, - json.getAsJsonObject(TARGET_FIELD).let(TestProjectEntityReferenceParser::parse), - json.getAsJsonArray(DIRECT_DEPENDENTS_FIELD)!!.map { it.asString }.toSet(), - json.getAsJsonArray(TRANSITIVE_DEPENDENTS_FIELD)!!.map { it.asString }.toSet(), + json.getAsJsonObjectList(TARGETS_FIELD)!!.map(ModuleDependentsTestTargetParser::parse), ) } + +data class ModuleDependentsTestTarget( + val entityReference: TestProjectEntityReference, + val directDependents: Set, + val transitiveDependents: Set, +) + +private object ModuleDependentsTestTargetParser { + private const val DIRECT_DEPENDENTS_FIELD = "directDependents" + private const val TRANSITIVE_DEPENDENTS_FIELD = "transitiveDependents" + + fun parse(json: JsonObject): ModuleDependentsTestTarget { + // We can parse `json` as the entity reference itself to avoid boilerplate around the entity reference. + val entityReference = TestProjectEntityReferenceParser.parse(json) + + return ModuleDependentsTestTarget( + entityReference, + json.getAsStringList(DIRECT_DEPENDENTS_FIELD)!!.toSet(), + json.getAsStringList(TRANSITIVE_DEPENDENTS_FIELD)!!.toSet(), + ) + } +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java index 0c4d6b80263c..d7983e8914ce 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java @@ -17,70 +17,44 @@ import org.junit.runner.RunWith; @TestRoot("base/fir/analysis-api-providers") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -public abstract class ModuleDependentsTestGenerated extends AbstractModuleDependentsTest { - @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("testData/moduleDependents/libraryTargets") - public static class LibraryTargets extends AbstractModuleDependentsTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); - } - - @TestMetadata("cyclical") - public void testCyclical() throws Exception { - runTest("testData/moduleDependents/libraryTargets/cyclical/"); - } - - @TestMetadata("rhombus") - public void testRhombus() throws Exception { - runTest("testData/moduleDependents/libraryTargets/rhombus/"); - } - - @TestMetadata("rhombus2") - public void testRhombus2() throws Exception { - runTest("testData/moduleDependents/libraryTargets/rhombus2/"); - } - - @TestMetadata("singleRoot") - public void testSingleRoot() throws Exception { - runTest("testData/moduleDependents/libraryTargets/singleRoot/"); - } +@TestMetadata("testData/moduleDependents") +public class ModuleDependentsTestGenerated extends AbstractModuleDependentsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } - @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("testData/moduleDependents/moduleTargets") - public static class ModuleTargets extends AbstractModuleDependentsTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); - } + @TestMetadata("binaryTree") + public void testBinaryTree() throws Exception { + runTest("testData/moduleDependents/binaryTree/"); + } - @TestMetadata("binaryTree") - public void testBinaryTree() throws Exception { - runTest("testData/moduleDependents/moduleTargets/binaryTree/"); - } + @TestMetadata("cyclical") + public void testCyclical() throws Exception { + runTest("testData/moduleDependents/cyclical/"); + } - @TestMetadata("cyclical") - public void testCyclical() throws Exception { - runTest("testData/moduleDependents/moduleTargets/cyclical/"); - } + @TestMetadata("cyclicalSelf") + public void testCyclicalSelf() throws Exception { + runTest("testData/moduleDependents/cyclicalSelf/"); + } - @TestMetadata("cyclicalSelf") - public void testCyclicalSelf() throws Exception { - runTest("testData/moduleDependents/moduleTargets/cyclicalSelf/"); - } + @TestMetadata("cyclicalWithOutsideDependency") + public void testCyclicalWithOutsideDependency() throws Exception { + runTest("testData/moduleDependents/cyclicalWithOutsideDependency/"); + } - @TestMetadata("cyclicalWithOutsideDependency") - public void testCyclicalWithOutsideDependency() throws Exception { - runTest("testData/moduleDependents/moduleTargets/cyclicalWithOutsideDependency/"); - } + @TestMetadata("linear") + public void testLinear() throws Exception { + runTest("testData/moduleDependents/linear/"); + } - @TestMetadata("linear") - public void testLinear() throws Exception { - runTest("testData/moduleDependents/moduleTargets/linear/"); - } + @TestMetadata("rhombus") + public void testRhombus() throws Exception { + runTest("testData/moduleDependents/rhombus/"); + } - @TestMetadata("rhombus") - public void testRhombus() throws Exception { - runTest("testData/moduleDependents/moduleTargets/rhombus/"); - } + @TestMetadata("singleRoot") + public void testSingleRoot() throws Exception { + runTest("testData/moduleDependents/singleRoot/"); } } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectEntityReference.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectEntityReference.kt index 3a42b5aab4a7..b0bf3b6bd74c 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectEntityReference.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectEntityReference.kt @@ -7,11 +7,13 @@ import org.jetbrains.kotlin.idea.jsonUtils.getNullableString /** * A reference that points to a library or module in the test project structure. */ -sealed interface TestProjectEntityReference +sealed interface TestProjectEntityReference { + val name: String +} -data class TestProjectLibraryReference(val name: String) : TestProjectEntityReference +data class TestProjectLibraryReference(override val name: String) : TestProjectEntityReference -data class TestProjectModuleReference(val name: String) : TestProjectEntityReference +data class TestProjectModuleReference(override val name: String) : TestProjectEntityReference object TestProjectEntityReferenceParser { private const val LIBRARY_FIELD = "library" diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt index 246d27be8094..600daeb29604 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt @@ -4,7 +4,7 @@ package org.jetbrains.kotlin.idea.fir.analysis.providers import com.google.gson.JsonElement import com.google.gson.JsonObject -import com.google.gson.JsonPrimitive +import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.getAsStringList import org.jetbrains.kotlin.idea.jsonUtils.getString interface TestProjectStructure { @@ -40,7 +40,7 @@ object TestProjectModuleParser { fun parse(json: JsonElement): TestProjectModule { require(json is JsonObject) - val dependencies = json.getAsJsonArray(DEPENDS_ON_FIELD)?.map { (it as JsonPrimitive).asString } ?: emptyList() + val dependencies = json.getAsStringList(DEPENDS_ON_FIELD) ?: emptyList() return TestProjectModule( json.getString("name"), dependencies diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/jsonUtils.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/jsonUtils.kt new file mode 100644 index 000000000000..acbff89f8b85 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/jsonUtils.kt @@ -0,0 +1,9 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure + +import com.google.gson.JsonObject +import com.google.gson.JsonPrimitive + +fun JsonObject.getAsStringList(memberName: String): List? = getAsJsonArray(memberName)?.map { (it as JsonPrimitive).asString } + +fun JsonObject.getAsJsonObjectList(memberName: String): List? = getAsJsonArray(memberName)?.map { it as JsonObject } diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json new file mode 100644 index 000000000000..b7c7a431deb5 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/binaryTree/structure.json @@ -0,0 +1,56 @@ +{ + "libraries": [ + { "name": "L1" } + ], + "modules" : [ + { "name": "A", "dependsOn": ["B", "C"] }, + { "name": "B", "dependsOn": ["D", "E"] }, + { "name": "C", "dependsOn": ["F", "G"] }, + { "name": "D", "dependsOn": [] }, + { "name": "E", "dependsOn": [] }, + { "name": "F", "dependsOn": ["L1"] }, + { "name": "G", "dependsOn": [] } + ], + "targets": [ + { + "library": "L1", + "directDependents": ["F"], + "transitiveDependents": ["F", "C", "A"] + }, + { + "module": "A", + "directDependents": [], + "transitiveDependents": [] + }, + { + "module": "B", + "directDependents": ["A"], + "transitiveDependents": ["A"] + }, + { + "module": "C", + "directDependents": ["A"], + "transitiveDependents": ["A"] + }, + { + "module": "D", + "directDependents": ["B"], + "transitiveDependents": ["B", "A"] + }, + { + "module": "E", + "directDependents": ["B"], + "transitiveDependents": ["B", "A"] + }, + { + "module": "F", + "directDependents": ["C"], + "transitiveDependents": ["C", "A"] + }, + { + "module": "G", + "directDependents": ["C"], + "transitiveDependents": ["C", "A"] + } + ] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json new file mode 100644 index 000000000000..b15f0aaa0636 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclical/structure.json @@ -0,0 +1,32 @@ +{ + "libraries": [ + { "name": "L1" } + ], + "modules" : [ + { "name": "A", "dependsOn": ["B"] }, + { "name": "B", "dependsOn": ["C", "L1"] }, + { "name": "C", "dependsOn": ["A"] } + ], + "targets": [ + { + "library": "L1", + "directDependents": ["B"], + "transitiveDependents": ["A", "B", "C"] + }, + { + "module": "A", + "directDependents": ["C"], + "transitiveDependents": ["B", "C"] + }, + { + "module": "B", + "directDependents": ["A"], + "transitiveDependents": ["A", "C"] + }, + { + "module": "C", + "directDependents": ["B"], + "transitiveDependents": ["A", "B"] + } + ] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json new file mode 100644 index 000000000000..a81121242a80 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalSelf/structure.json @@ -0,0 +1,18 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["A"] }, + { "name": "B", "dependsOn": ["A"] } + ], + "targets": [ + { + "module": "A", + "directDependents": ["B"], + "transitiveDependents": ["B"] + }, + { + "module": "B", + "directDependents": [], + "transitiveDependents": [] + } + ] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json new file mode 100644 index 000000000000..17a33b09ae2f --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/cyclicalWithOutsideDependency/structure.json @@ -0,0 +1,30 @@ +{ + "modules" : [ + { "name": "A", "dependsOn": ["B"] }, + { "name": "B", "dependsOn": ["C", "O"] }, + { "name": "C", "dependsOn": ["A"] }, + { "name": "O", "dependsOn": [] } + ], + "targets": [ + { + "module": "A", + "directDependents": ["C"], + "transitiveDependents": ["B", "C"] + }, + { + "module": "B", + "directDependents": ["A"], + "transitiveDependents": ["A", "C"] + }, + { + "module": "C", + "directDependents": ["B"], + "transitiveDependents": ["A", "B"] + }, + { + "module": "O", + "directDependents": ["B"], + "transitiveDependents": ["A", "B", "C"] + } + ] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/cyclical/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/cyclical/structure.json deleted file mode 100644 index 30f44556c982..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/cyclical/structure.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "libraries": [ - { "name": "L1" } - ], - "modules" : [ - { "name": "A", "dependsOn": ["B"] }, - { "name": "B", "dependsOn": ["C", "L1"] }, - { "name": "C", "dependsOn": ["A"] } - ], - "target": { "library": "L1" }, - "directDependents": ["B"], - "transitiveDependents": ["A", "B", "C"] -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus/structure.json deleted file mode 100644 index 3addd0d20b36..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus/structure.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "libraries": [ - { "name": "L1" }, - { "name": "L2" } - ], - "modules" : [ - { "name": "A", "dependsOn": ["B", "C"] }, - { "name": "B", "dependsOn": ["D"] }, - { "name": "C", "dependsOn": ["D", "L2"] }, - { "name": "D", "dependsOn": ["L1"] } - ], - "target": { "library": "L1" }, - "directDependents": ["D"], - "transitiveDependents": ["A", "B", "C", "D"] -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus2/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus2/structure.json deleted file mode 100644 index 00ca79b3d82a..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/rhombus2/structure.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "libraries": [ - { "name": "L1" }, - { "name": "L2" } - ], - "modules" : [ - { "name": "A", "dependsOn": ["B", "C"] }, - { "name": "B", "dependsOn": ["D"] }, - { "name": "C", "dependsOn": ["D", "L2"] }, - { "name": "D", "dependsOn": ["L1"] } - ], - "target": { "library": "L2" }, - "directDependents": ["C"], - "transitiveDependents": ["A", "C"] -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/singleRoot/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/singleRoot/structure.json deleted file mode 100644 index cc0b86824fa2..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/libraryTargets/singleRoot/structure.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "libraries": [ - { "name": "L1" }, - { "name": "L2" } - ], - "modules" : [ - { "name": "A", "dependsOn": ["B", "C", "H"] }, - { "name": "B", "dependsOn": ["D", "E"] }, - { "name": "C", "dependsOn": ["F", "G"] }, - { "name": "D", "dependsOn": ["L1"] }, - { "name": "E", "dependsOn": ["L1"] }, - { "name": "F", "dependsOn": ["L2"] }, - { "name": "G", "dependsOn": ["L2"] }, - { "name": "H", "dependsOn": ["I"] }, - { "name": "I", "dependsOn": ["L1"] } - ], - "target": { "library": "L1" }, - "directDependents": ["D", "E", "I"], - "transitiveDependents": ["D", "E", "I", "H", "B", "A"] -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json new file mode 100644 index 000000000000..8852ef6dab3d --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/linear/structure.json @@ -0,0 +1,44 @@ +{ + "libraries": [ + { "name": "L1" } + ], + "modules" : [ + { "name": "A", "dependsOn": ["B"] }, + { "name": "B", "dependsOn": ["C"] }, + { "name": "C", "dependsOn": ["D"] }, + { "name": "D", "dependsOn": ["E"] }, + { "name": "E", "dependsOn": ["L1"] } + ], + "targets": [ + { + "library": "L1", + "directDependents": ["E"], + "transitiveDependents": ["E", "D", "C", "B", "A"] + }, + { + "module": "A", + "directDependents": [], + "transitiveDependents": [] + }, + { + "module": "B", + "directDependents": ["A"], + "transitiveDependents": ["A"] + }, + { + "module": "C", + "directDependents": ["B"], + "transitiveDependents": ["B", "A"] + }, + { + "module": "D", + "directDependents": ["C"], + "transitiveDependents": ["C", "B", "A"] + }, + { + "module": "E", + "directDependents": ["D"], + "transitiveDependents": ["D", "C", "B", "A"] + } + ] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/binaryTree/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/binaryTree/structure.json deleted file mode 100644 index 07bf08cfb7f7..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/binaryTree/structure.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "modules" : [ - { "name": "A", "dependsOn": ["B", "C"] }, - { "name": "B", "dependsOn": ["D", "E"] }, - { "name": "C", "dependsOn": ["F", "G"] }, - { "name": "D", "dependsOn": [] }, - { "name": "E", "dependsOn": [] }, - { "name": "F", "dependsOn": [] }, - { "name": "G", "dependsOn": [] } - ], - "target": { "module": "F" }, - "directDependents": ["C"], - "transitiveDependents": ["C", "A"] -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclical/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclical/structure.json deleted file mode 100644 index 072b227f822b..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclical/structure.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "modules" : [ - { "name": "A", "dependsOn": ["B"] }, - { "name": "B", "dependsOn": ["C"] }, - { "name": "C", "dependsOn": ["A"] } - ], - "target": { "module": "A" }, - "directDependents": ["C"], - "transitiveDependents": ["B", "C"] -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalSelf/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalSelf/structure.json deleted file mode 100644 index e80da8b94335..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalSelf/structure.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "modules" : [ - { "name": "A", "dependsOn": ["A"] }, - { "name": "B", "dependsOn": ["A"] } - ], - "target": { "module": "A" }, - "directDependents": ["B"], - "transitiveDependents": ["B"] -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalWithOutsideDependency/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalWithOutsideDependency/structure.json deleted file mode 100644 index 6c5f29ae27b8..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/cyclicalWithOutsideDependency/structure.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "modules" : [ - { "name": "A", "dependsOn": ["B"] }, - { "name": "B", "dependsOn": ["C", "O"] }, - { "name": "C", "dependsOn": ["A"] }, - { "name": "O", "dependsOn": [] } - ], - "target": { "module": "O" }, - "directDependents": ["B"], - "transitiveDependents": ["A", "B", "C"] -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/linear/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/linear/structure.json deleted file mode 100644 index da6dda4f5c04..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/linear/structure.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "libraries": [ - { "name": "L1" } - ], - "modules" : [ - { "name": "A", "dependsOn": ["B"] }, - { "name": "B", "dependsOn": ["C"] }, - { "name": "C", "dependsOn": ["D"] }, - { "name": "D", "dependsOn": ["E"] }, - { "name": "E", "dependsOn": ["L1"] } - ], - "target": { "module": "E" }, - "directDependents": ["D"], - "transitiveDependents": ["A", "B", "C", "D"] -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/rhombus/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/rhombus/structure.json deleted file mode 100644 index c57fd8f4c747..000000000000 --- a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/moduleTargets/rhombus/structure.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "modules" : [ - { "name": "A", "dependsOn": ["B", "C"] }, - { "name": "B", "dependsOn": ["D"] }, - { "name": "C", "dependsOn": ["D"] }, - { "name": "D", "dependsOn": [] } - ], - "target": { "module": "D" }, - "directDependents": ["B", "C"], - "transitiveDependents": ["A", "B", "C"] -} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json new file mode 100644 index 000000000000..214efc4cc715 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/rhombus/structure.json @@ -0,0 +1,44 @@ +{ + "libraries": [ + { "name": "L1" }, + { "name": "L2" } + ], + "modules" : [ + { "name": "A", "dependsOn": ["B", "C"] }, + { "name": "B", "dependsOn": ["D"] }, + { "name": "C", "dependsOn": ["D", "L2"] }, + { "name": "D", "dependsOn": ["L1"] } + ], + "targets": [ + { + "library": "L1", + "directDependents": ["D"], + "transitiveDependents": ["A", "B", "C", "D"] + }, + { + "library": "L2", + "directDependents": ["C"], + "transitiveDependents": ["A", "C"] + }, + { + "module": "A", + "directDependents": [], + "transitiveDependents": [] + }, + { + "module": "B", + "directDependents": ["A"], + "transitiveDependents": ["A"] + }, + { + "module": "C", + "directDependents": ["A"], + "transitiveDependents": ["A"] + }, + { + "module": "D", + "directDependents": ["B", "C"], + "transitiveDependents": ["A", "B", "C"] + } + ] +} diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/singleRoot/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/singleRoot/structure.json new file mode 100644 index 000000000000..2b7551714695 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/singleRoot/structure.json @@ -0,0 +1,74 @@ +{ + "libraries": [ + { "name": "L1" }, + { "name": "L2" } + ], + "modules" : [ + { "name": "A", "dependsOn": ["B", "C", "H"] }, + { "name": "B", "dependsOn": ["D", "E"] }, + { "name": "C", "dependsOn": ["F", "G"] }, + { "name": "D", "dependsOn": ["L1"] }, + { "name": "E", "dependsOn": ["L1"] }, + { "name": "F", "dependsOn": ["L2"] }, + { "name": "G", "dependsOn": ["L2"] }, + { "name": "H", "dependsOn": ["I"] }, + { "name": "I", "dependsOn": ["L1"] } + ], + "targets": [ + { + "library": "L1", + "directDependents": ["D", "E", "I"], + "transitiveDependents": ["D", "E", "I", "H", "B", "A"] + }, + { + "library": "L2", + "directDependents": ["F", "G"], + "transitiveDependents": ["F", "G", "C", "A"] + }, + { + "module": "A", + "directDependents": [], + "transitiveDependents": [] + }, + { + "module": "B", + "directDependents": ["A"], + "transitiveDependents": ["A"] + }, + { + "module": "C", + "directDependents": ["A"], + "transitiveDependents": ["A"] + }, + { + "module": "D", + "directDependents": ["B"], + "transitiveDependents": ["B", "A"] + }, + { + "module": "E", + "directDependents": ["B"], + "transitiveDependents": ["B", "A"] + }, + { + "module": "F", + "directDependents": ["C"], + "transitiveDependents": ["C", "A"] + }, + { + "module": "G", + "directDependents": ["C"], + "transitiveDependents": ["C", "A"] + }, + { + "module": "H", + "directDependents": ["A"], + "transitiveDependents": ["A"] + }, + { + "module": "I", + "directDependents": ["H"], + "transitiveDependents": ["H", "A"] + } + ] +} diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt index aa7e1e203e31..d5858963d7ee 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt @@ -83,8 +83,7 @@ private fun assembleWorkspace(): TWorkspace = workspace { } testClass { - model("moduleDependents/libraryTargets", pattern = DIRECTORY, isRecursive = false) - model("moduleDependents/moduleTargets", pattern = DIRECTORY, isRecursive = false) + model("moduleDependents", pattern = DIRECTORY, isRecursive = false) } } From 0c50064c80293ad2820b84566f5c7e8cd90bd5dd Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 25 Jul 2023 12:14:03 +0200 Subject: [PATCH 056/165] [kotlin] `LibraryUpdatesListener`: Use case-insensitive JAR file extension comparison GitOrigin-RevId: ad69f007df2f547935d53dbdcfd90f56fb8656ba --- .../KotlinModuleStateModificationService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 9274b76d5e19..6633c5bfdc9d 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -107,7 +107,7 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab is VFileContentChangeEvent -> event.file else -> return@mapNotNull null } - if (file.extension != "jar") return@mapNotNull null //react only on jars + if (!file.extension.equals("jar", ignoreCase = true)) return@mapNotNull null //react only on jars val jarRoot = StandardFileSystems.jar().findFileByPath(file.path + URLUtil.JAR_SEPARATOR) ?: return@mapNotNull null (index.getOrderEntriesForFile(jarRoot).firstOrNull { it is LibraryOrderEntry } as? LibraryOrderEntry)?.library }.distinct().forEach { moduleStateModificationService.invalidateLibraryModule(it) } From 7aac691365d9992e32cd0f060d69fc7c356bf6f3 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 27 Jul 2023 15:08:37 +0200 Subject: [PATCH 057/165] [kotlin] KT-58257 Avoid file deletion in K2 anchor module reference resolve tests - File deletion in projects with anchor modules may cause stale file index entries due to IDEA-324516. That is because when a file is deleted, it constitutes a global PSI change, which leads to global source out-of-block modification. When `LLFirSessionInvalidationService.invalidateAll` is called with `includeLibraryModules = false` (which is the case for global source modification events), the service invokes `invalidate` for all anchor modules. This leads, via getting transitive dependents and `addAnchorModuleDependents`, to a call to `getTransitiveLibraryDependencyInfos`, which accesses indices via `isCoreKotlinLibrary`, triggering the "deleted file was restored" fallback mechanism described in IDEA-324516. - In the anchor module tests, the file is deleted because the test deletes the whole Java class, which causes the file to be deleted automatically via special handling in `JavaFileElement.deleteChildInternal`. Renaming the class to `Element2` works well for the test, too, without triggering IDEA-324516. GitOrigin-RevId: f61eb123b9385f5b23403ddf228dde60d81d2fcd --- .../fir/resolve/AbstractK2MultiModuleHighlightingTest.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractK2MultiModuleHighlightingTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractK2MultiModuleHighlightingTest.kt index 9885afb7c289..5788ee9fc052 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractK2MultiModuleHighlightingTest.kt +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractK2MultiModuleHighlightingTest.kt @@ -74,8 +74,10 @@ abstract class AbstractK2MultiModuleHighlightingTest : AbstractMultiModuleTest() val dep = ModuleManager.getInstance(project).findModuleByName(moduleName)!! val targetFileInTemp = dep.sourceRoots[0].findFileByRelativePath(relativePath)!! WriteCommandAction.writeCommandAction(project).run { - //this should trigger cache invalidation - (PsiManager.getInstance(project).findFile(targetFileInTemp) as PsiClassOwner).classes[0].unwrapped!!.delete() + // This should trigger cache invalidation. + val psiFile = (PsiManager.getInstance(project).findFile(targetFileInTemp) as PsiClassOwner) + val psiClassOrKtClass = psiFile.classes[0].unwrapped!! as PsiNamedElement + psiClassOrKtClass.setName("Element2") } assertNull(psiReference.resolve()) } From 3d8e8794f6d9d51dbef6d3e01fb81c1bffa2b58c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 28 Jul 2023 15:48:22 +0200 Subject: [PATCH 058/165] [kotlin] k2: test to ensure navigation from invalid annotation call works (KTIJ-26441) GitOrigin-RevId: be20bc5a90899712524e16baced06bcf8f449d38 --- .../fir/navigation/FirGotoDeclarationTestGenerated.java | 5 +++++ .../idea/navigation/GotoDeclarationTestGenerated.java | 5 +++++ .../gotoDeclaration/annotationCallWithMissedTypeArgs.test | 8 ++++++++ 3 files changed, 18 insertions(+) create mode 100644 plugins/kotlin/idea/tests/testData/navigation/gotoDeclaration/annotationCallWithMissedTypeArgs.test diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/navigation/FirGotoDeclarationTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/navigation/FirGotoDeclarationTestGenerated.java index f9bee9b05e9e..08ad4a56fcf8 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/navigation/FirGotoDeclarationTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/navigation/FirGotoDeclarationTestGenerated.java @@ -23,6 +23,11 @@ public class FirGotoDeclarationTestGenerated extends AbstractFirGotoDeclarationT KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("annotationCallWithMissedTypeArgs.test") + public void testAnnotationCallWithMissedTypeArgs() throws Exception { + runTest("../idea/tests/testData/navigation/gotoDeclaration/annotationCallWithMissedTypeArgs.test"); + } + @TestMetadata("dataClassToString.test") public void testDataClassToString() throws Exception { runTest("../idea/tests/testData/navigation/gotoDeclaration/dataClassToString.test"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/navigation/GotoDeclarationTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/navigation/GotoDeclarationTestGenerated.java index a54fbc5d02c2..394bf6e3e129 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/navigation/GotoDeclarationTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/navigation/GotoDeclarationTestGenerated.java @@ -23,6 +23,11 @@ public class GotoDeclarationTestGenerated extends AbstractGotoDeclarationTest { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("annotationCallWithMissedTypeArgs.test") + public void testAnnotationCallWithMissedTypeArgs() throws Exception { + runTest("testData/navigation/gotoDeclaration/annotationCallWithMissedTypeArgs.test"); + } + @TestMetadata("dataClassToString.test") public void testDataClassToString() throws Exception { runTest("testData/navigation/gotoDeclaration/dataClassToString.test"); diff --git a/plugins/kotlin/idea/tests/testData/navigation/gotoDeclaration/annotationCallWithMissedTypeArgs.test b/plugins/kotlin/idea/tests/testData/navigation/gotoDeclaration/annotationCallWithMissedTypeArgs.test new file mode 100644 index 000000000000..c42a49d171c4 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/navigation/gotoDeclaration/annotationCallWithMissedTypeArgs.test @@ -0,0 +1,8 @@ +// FILE: before.kt +annotation class B +@B +class A +// FILE: after.kt +annotation class B +@B +class A \ No newline at end of file From 3725d06675b54bf7a6bb1acecba4161a012d7c60 Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Thu, 27 Jul 2023 16:40:26 +0300 Subject: [PATCH 059/165] [kotlin] K2: fix insertion of classes in context receivers with no owner declaration ^KTIJ-26426 Fixed GitOrigin-RevId: 1af76ebae4509aa12c7887b0e1f34b133c0a7583 --- .../factories/ClassLookupElementFactory.kt | 14 ++++++++++ .../contextReceivers/WithoutDeclaration.kt | 5 ++++ .../WithoutDeclaration.kt.after | 7 +++++ .../WithoutDeclarationNestedClass.kt | 12 ++++++++ .../WithoutDeclarationNestedClass.kt.after | 12 ++++++++ ...thoutDeclarationNestedClass2.dependency.kt | 5 ++++ .../WithoutDeclarationNestedClass2.kt | 6 ++++ .../WithoutDeclarationNestedClass2.kt.after | 8 ++++++ .../WithoutDeclarationTypeArgument.kt | 5 ++++ .../WithoutDeclarationTypeArgument.kt.after | 7 +++++ .../BasicCompletionHandlerTestGenerated.java | 28 +++++++++++++++++++ ...elBasicCompletionHandlerTestGenerated.java | 28 +++++++++++++++++++ ...ceBasicCompletionHandlerTestGenerated.java | 28 +++++++++++++++++++ 13 files changed, 165 insertions(+) create mode 100644 plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclaration.kt create mode 100644 plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclaration.kt.after create mode 100644 plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt create mode 100644 plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt.after create mode 100644 plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.dependency.kt create mode 100644 plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt create mode 100644 plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt.after create mode 100644 plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt create mode 100644 plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt.after diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/factories/ClassLookupElementFactory.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/factories/ClassLookupElementFactory.kt index 9c9fdcc392f4..ee71b3e80f71 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/factories/ClassLookupElementFactory.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/factories/ClassLookupElementFactory.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement import com.intellij.psi.util.elementType +import com.intellij.psi.util.parentOfType import com.intellij.refactoring.suggested.endOffset import com.intellij.refactoring.suggested.startOffset import org.jetbrains.kotlin.idea.completion.lookups.* @@ -24,6 +25,9 @@ import org.jetbrains.kotlin.kdoc.psi.impl.KDocName import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtCallableDeclaration +import org.jetbrains.kotlin.psi.KtContextReceiver +import org.jetbrains.kotlin.psi.KtContextReceiverList +import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNameReferenceExpression import org.jetbrains.kotlin.renderer.render @@ -70,6 +74,9 @@ private object ClassifierInsertionHandler : QuotedNamesAwareInsertionHandler() { // add temporary suffix for type in the receiver type position, in order for it to be resolved and shortened correctly token?.isCallableDeclarationIdentifier() == true -> "" to ".f" + // if a context receiver has no owner declaration then its type reference is not resolved and therefore cannot be shortened + token?.isContextReceiverWithoutOwnerDeclaration() == true -> "" to ") fun" + // if there is no reference in the current context and the position is not receiver type position, // add temporary prefix and suffix token?.parent !is KtNameReferenceExpression -> "$;val v:" to "$" @@ -107,4 +114,11 @@ private object ClassifierInsertionHandler : QuotedNamesAwareInsertionHandler() { private fun PsiElement.isCallableDeclarationIdentifier(): Boolean = elementType == KtTokens.IDENTIFIER && parent is KtCallableDeclaration + + private fun PsiElement.isContextReceiverWithoutOwnerDeclaration(): Boolean { + val contextReceiver = parentOfType() + val contextReceiverList = contextReceiver?.parent as? KtContextReceiverList ?: return false + + return contextReceiverList.parent !is KtDeclaration + } } diff --git a/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclaration.kt b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclaration.kt new file mode 100644 index 000000000000..551fb48e39d3 --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclaration.kt @@ -0,0 +1,5 @@ +context(Fil) + +// ELEMENT: File +// FIR_COMPARISON +// FIR_IDENTICAL \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclaration.kt.after b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclaration.kt.after new file mode 100644 index 000000000000..a027af3656a2 --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclaration.kt.after @@ -0,0 +1,7 @@ +import java.io.File + +context(File) + +// ELEMENT: File +// FIR_COMPARISON +// FIR_IDENTICAL \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt new file mode 100644 index 000000000000..53dbe231f743 --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt @@ -0,0 +1,12 @@ +package test + +class A { + class Nested +} + +context(Neste) + +// ELEMENT: Nested +// FIR_COMPARISON +// FIR_IDENTICAL +// IGNORE_FE10 \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt.after b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt.after new file mode 100644 index 000000000000..d46b03fa9a16 --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt.after @@ -0,0 +1,12 @@ +package test + +class A { + class Nested +} + +context(A.Nested) + +// ELEMENT: Nested +// FIR_COMPARISON +// FIR_IDENTICAL +// IGNORE_FE10 \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.dependency.kt b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.dependency.kt new file mode 100644 index 000000000000..60236d433a7b --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.dependency.kt @@ -0,0 +1,5 @@ +package dependency + +class A { + class Nested +} \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt new file mode 100644 index 000000000000..d9c12ffc6b51 --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt @@ -0,0 +1,6 @@ +context(Neste) + +// ELEMENT: Nested +// FIR_COMPARISON +// FIR_IDENTICAL +// IGNORE_FE10 \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt.after b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt.after new file mode 100644 index 000000000000..b1bff2970256 --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt.after @@ -0,0 +1,8 @@ +import dependency.A + +context(A.Nested) + +// ELEMENT: Nested +// FIR_COMPARISON +// FIR_IDENTICAL +// IGNORE_FE10 \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt new file mode 100644 index 000000000000..5ed40fe4b043 --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt @@ -0,0 +1,5 @@ +context(LisT>) + +// ELEMENT: File +// FIR_COMPARISON +// FIR_IDENTICAL \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt.after b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt.after new file mode 100644 index 000000000000..06a4fa42c7bd --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt.after @@ -0,0 +1,7 @@ +import java.io.File + +context(LisT>) + +// ELEMENT: File +// FIR_COMPARISON +// FIR_IDENTICAL \ No newline at end of file diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java index cf31987c1e18..a1925be2a29b 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java @@ -153,6 +153,34 @@ public abstract class BasicCompletionHandlerTestGenerated extends AbstractBasicC } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../testData/handlers/basic/contextReceivers") + public static class ContextReceivers extends AbstractBasicCompletionHandlerTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("WithoutDeclaration.kt") + public void testWithoutDeclaration() throws Exception { + runTest("../testData/handlers/basic/contextReceivers/WithoutDeclaration.kt"); + } + + @TestMetadata("WithoutDeclarationNestedClass.kt") + public void testWithoutDeclarationNestedClass() throws Exception { + runTest("../testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt"); + } + + @TestMetadata("WithoutDeclarationNestedClass2.kt") + public void testWithoutDeclarationNestedClass2() throws Exception { + runTest("../testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt"); + } + + @TestMetadata("WithoutDeclarationTypeArgument.kt") + public void testWithoutDeclarationTypeArgument() throws Exception { + runTest("../testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/handlers/basic/defaultImports") public static class DefaultImports extends AbstractBasicCompletionHandlerTest { diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/test/handlers/HighLevelBasicCompletionHandlerTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/test/handlers/HighLevelBasicCompletionHandlerTestGenerated.java index f6d8eda2c9df..a49e2e732136 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/test/handlers/HighLevelBasicCompletionHandlerTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/test/handlers/HighLevelBasicCompletionHandlerTestGenerated.java @@ -155,6 +155,34 @@ public abstract class HighLevelBasicCompletionHandlerTestGenerated extends Abstr } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../completion/testData/handlers/basic/contextReceivers") + public static class ContextReceivers extends AbstractHighLevelBasicCompletionHandlerTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("WithoutDeclaration.kt") + public void testWithoutDeclaration() throws Exception { + runTest("../completion/testData/handlers/basic/contextReceivers/WithoutDeclaration.kt"); + } + + @TestMetadata("WithoutDeclarationNestedClass.kt") + public void testWithoutDeclarationNestedClass() throws Exception { + runTest("../completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt"); + } + + @TestMetadata("WithoutDeclarationNestedClass2.kt") + public void testWithoutDeclarationNestedClass2() throws Exception { + runTest("../completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt"); + } + + @TestMetadata("WithoutDeclarationTypeArgument.kt") + public void testWithoutDeclarationTypeArgument() throws Exception { + runTest("../completion/testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/handlers/basic/defaultImports") public static class DefaultImports extends AbstractHighLevelBasicCompletionHandlerTest { diff --git a/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceBasicCompletionHandlerTestGenerated.java b/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceBasicCompletionHandlerTestGenerated.java index 9932d2e25db5..6c7f0330abf2 100644 --- a/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceBasicCompletionHandlerTestGenerated.java +++ b/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceBasicCompletionHandlerTestGenerated.java @@ -153,6 +153,34 @@ public abstract class PerformanceBasicCompletionHandlerTestGenerated extends Abs } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../completion/testData/handlers/basic/contextReceivers") + public static class ContextReceivers extends AbstractPerformanceBasicCompletionHandlerTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doPerfTest, this, testDataFilePath); + } + + @TestMetadata("WithoutDeclaration.kt") + public void testWithoutDeclaration() throws Exception { + runTest("../completion/testData/handlers/basic/contextReceivers/WithoutDeclaration.kt"); + } + + @TestMetadata("WithoutDeclarationNestedClass.kt") + public void testWithoutDeclarationNestedClass() throws Exception { + runTest("../completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass.kt"); + } + + @TestMetadata("WithoutDeclarationNestedClass2.kt") + public void testWithoutDeclarationNestedClass2() throws Exception { + runTest("../completion/testData/handlers/basic/contextReceivers/WithoutDeclarationNestedClass2.kt"); + } + + @TestMetadata("WithoutDeclarationTypeArgument.kt") + public void testWithoutDeclarationTypeArgument() throws Exception { + runTest("../completion/testData/handlers/basic/contextReceivers/WithoutDeclarationTypeArgument.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/handlers/basic/defaultImports") public static class DefaultImports extends AbstractPerformanceBasicCompletionHandlerTest { From 769ef0c5145cf5c702a7431148f62a57aaa6ebaa Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Thu, 27 Jul 2023 17:38:46 +0300 Subject: [PATCH 060/165] [kotlin] K2: add test data for KTIJ-26384 GitOrigin-RevId: d893ed55faadd7c7fa30bd53b501ad94a5ad020f --- .../basic/common/extensions/ContextReceiverType.kt | 10 ++++++++++ .../common/extensions/ContextReceiverType2.kt | 14 ++++++++++++++ .../test/JSBasicCompletionTestGenerated.java | 10 ++++++++++ .../test/JvmBasicCompletionTestGenerated.java | 10 ++++++++++ .../HighLevelJvmBasicCompletionTestGenerated.java | 10 ++++++++++ 5 files changed, 54 insertions(+) create mode 100644 plugins/kotlin/completion/testData/basic/common/extensions/ContextReceiverType.kt create mode 100644 plugins/kotlin/completion/testData/basic/common/extensions/ContextReceiverType2.kt diff --git a/plugins/kotlin/completion/testData/basic/common/extensions/ContextReceiverType.kt b/plugins/kotlin/completion/testData/basic/common/extensions/ContextReceiverType.kt new file mode 100644 index 000000000000..930f7382bafd --- /dev/null +++ b/plugins/kotlin/completion/testData/basic/common/extensions/ContextReceiverType.kt @@ -0,0 +1,10 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +context(String) +fun test() { + ba +} + +fun String.bar() {} + +// EXIST: bar \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/basic/common/extensions/ContextReceiverType2.kt b/plugins/kotlin/completion/testData/basic/common/extensions/ContextReceiverType2.kt new file mode 100644 index 000000000000..3276f8625eeb --- /dev/null +++ b/plugins/kotlin/completion/testData/basic/common/extensions/ContextReceiverType2.kt @@ -0,0 +1,14 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +class A + +class B { + fun A.bar() {} +} + +context(A, B) +fun test() { + ba +} + +// EXIST: bar \ No newline at end of file diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index 1c2df46b89bd..69b0a6aba207 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -780,6 +780,16 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp runTest("../testData/basic/common/extensions/ComplexCapture2.kt"); } + @TestMetadata("ContextReceiverType.kt") + public void testContextReceiverType() throws Exception { + runTest("../testData/basic/common/extensions/ContextReceiverType.kt"); + } + + @TestMetadata("ContextReceiverType2.kt") + public void testContextReceiverType2() throws Exception { + runTest("../testData/basic/common/extensions/ContextReceiverType2.kt"); + } + @TestMetadata("ExtensionInExtendedClass.kt") public void testExtensionInExtendedClass() throws Exception { runTest("../testData/basic/common/extensions/ExtensionInExtendedClass.kt"); diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index f656e81cd119..a68e770b1ffc 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -780,6 +780,16 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo runTest("../testData/basic/common/extensions/ComplexCapture2.kt"); } + @TestMetadata("ContextReceiverType.kt") + public void testContextReceiverType() throws Exception { + runTest("../testData/basic/common/extensions/ContextReceiverType.kt"); + } + + @TestMetadata("ContextReceiverType2.kt") + public void testContextReceiverType2() throws Exception { + runTest("../testData/basic/common/extensions/ContextReceiverType2.kt"); + } + @TestMetadata("ExtensionInExtendedClass.kt") public void testExtensionInExtendedClass() throws Exception { runTest("../testData/basic/common/extensions/ExtensionInExtendedClass.kt"); diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java index f10b23cac1a9..6c58f2a07b65 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java @@ -780,6 +780,16 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH runTest("../completion/testData/basic/common/extensions/ComplexCapture2.kt"); } + @TestMetadata("ContextReceiverType.kt") + public void testContextReceiverType() throws Exception { + runTest("../completion/testData/basic/common/extensions/ContextReceiverType.kt"); + } + + @TestMetadata("ContextReceiverType2.kt") + public void testContextReceiverType2() throws Exception { + runTest("../completion/testData/basic/common/extensions/ContextReceiverType2.kt"); + } + @TestMetadata("ExtensionInExtendedClass.kt") public void testExtensionInExtendedClass() throws Exception { runTest("../completion/testData/basic/common/extensions/ExtensionInExtendedClass.kt"); From c368f2b6c522de3c274e4d787ff06d00d4480495 Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Fri, 28 Jul 2023 10:27:34 +0300 Subject: [PATCH 061/165] [kotlin] K2: add braces when completing `context` keyword ^KTIJ-26433 Fixed GitOrigin-RevId: 5690ab6d7de3a52fad3811e19b7d658cf2fcf407 --- .../idea/completion/implCommon/KeywordCompletion.kt | 3 ++- .../completion/testData/handlers/keywords/Context.kt | 7 +++++++ .../testData/handlers/keywords/Context.kt.after | 7 +++++++ .../handlers/keywords/ContextWithoutDeclaration.kt | 6 ++++++ .../keywords/ContextWithoutDeclaration.kt.after | 6 ++++++ .../KeywordCompletionHandlerTestGenerated.java | 10 ++++++++++ .../FirKeywordCompletionHandlerTestGenerated.java | 10 ++++++++++ ...rformanceKeywordCompletionHandlerTestGenerated.java | 10 ++++++++++ 8 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 plugins/kotlin/completion/testData/handlers/keywords/Context.kt create mode 100644 plugins/kotlin/completion/testData/handlers/keywords/Context.kt.after create mode 100644 plugins/kotlin/completion/testData/handlers/keywords/ContextWithoutDeclaration.kt create mode 100644 plugins/kotlin/completion/testData/handlers/keywords/ContextWithoutDeclaration.kt.after diff --git a/plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/KeywordCompletion.kt b/plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/KeywordCompletion.kt index 5b35cf75b18b..f926dfebc7f3 100644 --- a/plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/KeywordCompletion.kt +++ b/plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/KeywordCompletion.kt @@ -105,7 +105,8 @@ class KeywordCompletion(private val languageVersionSettingProvider: LanguageVers 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)" + CONSTRUCTOR_KEYWORD to "class C { constructor(caret)", + CONTEXT_KEYWORD to "context(caret)", ) private val NO_SPACE_AFTER = listOf( diff --git a/plugins/kotlin/completion/testData/handlers/keywords/Context.kt b/plugins/kotlin/completion/testData/handlers/keywords/Context.kt new file mode 100644 index 000000000000..048db0c5f102 --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/keywords/Context.kt @@ -0,0 +1,7 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +// COMPILER_ARGUMENTS: -XXLanguage:+ContextReceivers +conte +fun test() {} + +// ELEMENT: context \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/keywords/Context.kt.after b/plugins/kotlin/completion/testData/handlers/keywords/Context.kt.after new file mode 100644 index 000000000000..9e5a8e164a40 --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/keywords/Context.kt.after @@ -0,0 +1,7 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +// COMPILER_ARGUMENTS: -XXLanguage:+ContextReceivers +context() +fun test() {} + +// ELEMENT: context \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/keywords/ContextWithoutDeclaration.kt b/plugins/kotlin/completion/testData/handlers/keywords/ContextWithoutDeclaration.kt new file mode 100644 index 000000000000..efaeb0fe667f --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/keywords/ContextWithoutDeclaration.kt @@ -0,0 +1,6 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +// COMPILER_ARGUMENTS: -XXLanguage:+ContextReceivers +conte + +// ELEMENT: context \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/keywords/ContextWithoutDeclaration.kt.after b/plugins/kotlin/completion/testData/handlers/keywords/ContextWithoutDeclaration.kt.after new file mode 100644 index 000000000000..a0782daec3f2 --- /dev/null +++ b/plugins/kotlin/completion/testData/handlers/keywords/ContextWithoutDeclaration.kt.after @@ -0,0 +1,6 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +// COMPILER_ARGUMENTS: -XXLanguage:+ContextReceivers +context() + +// ELEMENT: context \ No newline at end of file diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/handlers/KeywordCompletionHandlerTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/handlers/KeywordCompletionHandlerTestGenerated.java index 24e24145cb7f..ddadd11f554c 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/handlers/KeywordCompletionHandlerTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/handlers/KeywordCompletionHandlerTestGenerated.java @@ -113,6 +113,16 @@ public class KeywordCompletionHandlerTestGenerated extends AbstractKeywordComple runTest("../testData/handlers/keywords/ConstructorPrimary.kt"); } + @TestMetadata("Context.kt") + public void testContext() throws Exception { + runTest("../testData/handlers/keywords/Context.kt"); + } + + @TestMetadata("ContextWithoutDeclaration.kt") + public void testContextWithoutDeclaration() throws Exception { + runTest("../testData/handlers/keywords/ContextWithoutDeclaration.kt"); + } + @TestMetadata("Do.kt") public void testDo() throws Exception { runTest("../testData/handlers/keywords/Do.kt"); diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/test/handlers/FirKeywordCompletionHandlerTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/test/handlers/FirKeywordCompletionHandlerTestGenerated.java index d70f2d478475..d44319feafe6 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/test/handlers/FirKeywordCompletionHandlerTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/test/handlers/FirKeywordCompletionHandlerTestGenerated.java @@ -113,6 +113,16 @@ public class FirKeywordCompletionHandlerTestGenerated extends AbstractFirKeyword runTest("../completion/testData/handlers/keywords/ConstructorPrimary.kt"); } + @TestMetadata("Context.kt") + public void testContext() throws Exception { + runTest("../completion/testData/handlers/keywords/Context.kt"); + } + + @TestMetadata("ContextWithoutDeclaration.kt") + public void testContextWithoutDeclaration() throws Exception { + runTest("../completion/testData/handlers/keywords/ContextWithoutDeclaration.kt"); + } + @TestMetadata("Do.kt") public void testDo() throws Exception { runTest("../completion/testData/handlers/keywords/Do.kt"); diff --git a/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceKeywordCompletionHandlerTestGenerated.java b/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceKeywordCompletionHandlerTestGenerated.java index 40db1babb1c9..97109604f2fa 100644 --- a/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceKeywordCompletionHandlerTestGenerated.java +++ b/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceKeywordCompletionHandlerTestGenerated.java @@ -113,6 +113,16 @@ public class PerformanceKeywordCompletionHandlerTestGenerated extends AbstractPe runTest("../completion/testData/handlers/keywords/ConstructorPrimary.kt"); } + @TestMetadata("Context.kt") + public void testContext() throws Exception { + runTest("../completion/testData/handlers/keywords/Context.kt"); + } + + @TestMetadata("ContextWithoutDeclaration.kt") + public void testContextWithoutDeclaration() throws Exception { + runTest("../completion/testData/handlers/keywords/ContextWithoutDeclaration.kt"); + } + @TestMetadata("Do.kt") public void testDo() throws Exception { runTest("../completion/testData/handlers/keywords/Do.kt"); From fd3c64a4a22bff75202463a24c524d095b467d95 Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Fri, 30 Jun 2023 13:42:21 +0300 Subject: [PATCH 062/165] [kotlin] Enable `IGNORE_FE10` in basic completion tests GitOrigin-RevId: 16086a6b701e62cead76617fa871e520fc603d53 --- .../test/AbstractK1JSBasicCompletionTest.kt | 12 +++ .../test/AbstractK1JvmBasicCompletionTest.kt | 12 +++ ... => K1JSBasicCompletionTestGenerated.java} | 82 ++++++++--------- ...=> K1JvmBasicCompletionTestGenerated.java} | 90 +++++++++---------- ...ava => K1KDocCompletionTestGenerated.java} | 2 +- ...=> AbstractJSBasicCompletionTestBase.java} | 2 +- .../test/AbstractJava8BasicCompletionTest.kt | 7 +- ... => AbstractJvmBasicCompletionTestBase.kt} | 2 +- .../KotlinFixtureCompletionBaseTestCase.kt | 3 +- ...AbstractHighLevelJvmBasicCompletionTest.kt | 4 +- .../AbstractCodeFragmentCompletionTest.kt | 4 +- .../CodeFragmentCompletionInLibraryTest.kt | 4 +- .../fe10/testGenerator/Fe10GenerateTests.kt | 6 +- 13 files changed, 125 insertions(+), 105 deletions(-) create mode 100644 plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/AbstractK1JSBasicCompletionTest.kt create mode 100644 plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/AbstractK1JvmBasicCompletionTest.kt rename plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/{JSBasicCompletionTestGenerated.java => K1JSBasicCompletionTestGenerated.java} (98%) rename plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/{JvmBasicCompletionTestGenerated.java => K1JvmBasicCompletionTestGenerated.java} (98%) rename plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/{KDocCompletionTestGenerated.java => K1KDocCompletionTestGenerated.java} (98%) rename plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/{AbstractJSBasicCompletionTest.java => AbstractJSBasicCompletionTestBase.java} (90%) rename plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/{AbstractJvmBasicCompletionTest.kt => AbstractJvmBasicCompletionTestBase.kt} (95%) diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/AbstractK1JSBasicCompletionTest.kt b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/AbstractK1JSBasicCompletionTest.kt new file mode 100644 index 000000000000..275f06c90ad5 --- /dev/null +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/AbstractK1JSBasicCompletionTest.kt @@ -0,0 +1,12 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.completion.test + +import org.jetbrains.kotlin.test.utils.IgnoreTests + +abstract class AbstractK1JSBasicCompletionTest : AbstractJSBasicCompletionTestBase() { + override fun executeTest(test: () -> Unit) { + IgnoreTests.runTestIfNotDisabledByFileDirective(dataFile().toPath(), IgnoreTests.DIRECTIVES.IGNORE_FE10) { + super.executeTest(test) + } + } +} \ No newline at end of file diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/AbstractK1JvmBasicCompletionTest.kt b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/AbstractK1JvmBasicCompletionTest.kt new file mode 100644 index 000000000000..22916aaba5bf --- /dev/null +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/AbstractK1JvmBasicCompletionTest.kt @@ -0,0 +1,12 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.completion.test + +import org.jetbrains.kotlin.test.utils.IgnoreTests + +abstract class AbstractK1JvmBasicCompletionTest : AbstractJvmBasicCompletionTestBase() { + override fun executeTest(test: () -> Unit) { + IgnoreTests.runTestIfNotDisabledByFileDirective(dataFile().toPath(), IgnoreTests.DIRECTIVES.IGNORE_FE10) { + super.executeTest(test) + } + } +} \ No newline at end of file diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java similarity index 98% rename from plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java rename to plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java index 69b0a6aba207..b0ed9db7eb0c 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java @@ -17,13 +17,13 @@ import org.junit.runner.RunWith; @TestRoot("completion/tests-k1") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTest { +public abstract class K1JSBasicCompletionTestGenerated extends AbstractK1JSBasicCompletionTest { @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common") - public abstract static class Common extends AbstractJSBasicCompletionTest { + public abstract static class Common extends AbstractK1JSBasicCompletionTest { @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/annotations") - public static class Annotations extends AbstractJSBasicCompletionTest { + public static class Annotations extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -236,7 +236,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/autoPopup") - public static class AutoPopup extends AbstractJSBasicCompletionTest { + public static class AutoPopup extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -334,7 +334,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/backticked") - public static class Backticked extends AbstractJSBasicCompletionTest { + public static class Backticked extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -357,7 +357,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/boldOrGrayed") - public static class BoldOrGrayed extends AbstractJSBasicCompletionTest { + public static class BoldOrGrayed extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -465,7 +465,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/callableReference") - public static class CallableReference extends AbstractJSBasicCompletionTest { + public static class CallableReference extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -533,7 +533,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/dslMarker") - public static class DslMarker extends AbstractJSBasicCompletionTest { + public static class DslMarker extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -576,7 +576,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/extensionDeclarations") - public static class ExtensionDeclarations extends AbstractJSBasicCompletionTest { + public static class ExtensionDeclarations extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -639,7 +639,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/extensionFunctionTypeValues") - public static class ExtensionFunctionTypeValues extends AbstractJSBasicCompletionTest { + public static class ExtensionFunctionTypeValues extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -672,7 +672,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/extensionMethodInObject") - public static class ExtensionMethodInObject extends AbstractJSBasicCompletionTest { + public static class ExtensionMethodInObject extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -765,7 +765,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/extensions") - public static class Extensions extends AbstractJSBasicCompletionTest { + public static class Extensions extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -928,7 +928,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/fromSmart") - public static class FromSmart extends AbstractJSBasicCompletionTest { + public static class FromSmart extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1001,7 +1001,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/fromUnresolvedNames") - public static class FromUnresolvedNames extends AbstractJSBasicCompletionTest { + public static class FromUnresolvedNames extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1079,7 +1079,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/getOperator") - public static class GetOperator extends AbstractJSBasicCompletionTest { + public static class GetOperator extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1102,7 +1102,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/highOrderFunctions") - public static class HighOrderFunctions extends AbstractJSBasicCompletionTest { + public static class HighOrderFunctions extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1160,7 +1160,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/inInitBlock") - public static class InInitBlock extends AbstractJSBasicCompletionTest { + public static class InInitBlock extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1178,7 +1178,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/inStringLiterals") - public static class InStringLiterals extends AbstractJSBasicCompletionTest { + public static class InStringLiterals extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1216,7 +1216,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/inSuperTypes") - public static class InSuperTypes extends AbstractJSBasicCompletionTest { + public static class InSuperTypes extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1239,7 +1239,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/inTypeAlias") - public static class InTypeAlias extends AbstractJSBasicCompletionTest { + public static class InTypeAlias extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1257,7 +1257,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/lambdaAndTypeParams") - public static class LambdaAndTypeParams extends AbstractJSBasicCompletionTest { + public static class LambdaAndTypeParams extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1290,7 +1290,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/lambdaSignature") - public static class LambdaSignature extends AbstractJSBasicCompletionTest { + public static class LambdaSignature extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1348,7 +1348,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/namedArguments") - public static class NamedArguments extends AbstractJSBasicCompletionTest { + public static class NamedArguments extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1476,7 +1476,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/noCompletion") - public static class NoCompletion extends AbstractJSBasicCompletionTest { + public static class NoCompletion extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1519,7 +1519,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/objects") - public static class Objects extends AbstractJSBasicCompletionTest { + public static class Objects extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1542,7 +1542,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/operatorNames") - public static class OperatorNames extends AbstractJSBasicCompletionTest { + public static class OperatorNames extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1565,7 +1565,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/override") - public static class Override extends AbstractJSBasicCompletionTest { + public static class Override extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1633,7 +1633,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/parameterNameAndType") - public static class ParameterNameAndType extends AbstractJSBasicCompletionTest { + public static class ParameterNameAndType extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1821,7 +1821,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/primaryConstructor") - public static class PrimaryConstructor extends AbstractJSBasicCompletionTest { + public static class PrimaryConstructor extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1844,7 +1844,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/primitiveCompletion") - public static class PrimitiveCompletion extends AbstractJSBasicCompletionTest { + public static class PrimitiveCompletion extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2032,7 +2032,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/shadowing") - public static class Shadowing extends AbstractJSBasicCompletionTest { + public static class Shadowing extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2175,7 +2175,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/smartCast") - public static class SmartCast extends AbstractJSBasicCompletionTest { + public static class SmartCast extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2223,7 +2223,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/staticMembers") - public static class StaticMembers extends AbstractJSBasicCompletionTest { + public static class StaticMembers extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2276,7 +2276,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/substitutedSignature") - public static class SubstitutedSignature extends AbstractJSBasicCompletionTest { + public static class SubstitutedSignature extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2319,7 +2319,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/super") - public static class Super extends AbstractJSBasicCompletionTest { + public static class Super extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2377,7 +2377,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/typeAliasTypes") - public static class TypeAliasTypes extends AbstractJSBasicCompletionTest { + public static class TypeAliasTypes extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2395,7 +2395,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/typeArgsOrNot") - public static class TypeArgsOrNot extends AbstractJSBasicCompletionTest { + public static class TypeArgsOrNot extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2448,7 +2448,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common") - public static class Uncategorized extends AbstractJSBasicCompletionTest { + public static class Uncategorized extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3246,7 +3246,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/variableNameAndType") - public static class VariableNameAndType extends AbstractJSBasicCompletionTest { + public static class VariableNameAndType extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3269,7 +3269,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/visibility") - public static class Visibility extends AbstractJSBasicCompletionTest { + public static class Visibility extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3386,7 +3386,7 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/js") - public static class Js extends AbstractJSBasicCompletionTest { + public static class Js extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java similarity index 98% rename from plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java rename to plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java index a68e770b1ffc..15dbc6d936bd 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java @@ -17,13 +17,13 @@ import org.junit.runner.RunWith; @TestRoot("completion/tests-k1") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionTest { +public abstract class K1JvmBasicCompletionTestGenerated extends AbstractK1JvmBasicCompletionTest { @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common") - public abstract static class Common extends AbstractJvmBasicCompletionTest { + public abstract static class Common extends AbstractK1JvmBasicCompletionTest { @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/annotations") - public static class Annotations extends AbstractJvmBasicCompletionTest { + public static class Annotations extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -236,7 +236,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/autoPopup") - public static class AutoPopup extends AbstractJvmBasicCompletionTest { + public static class AutoPopup extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -334,7 +334,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/backticked") - public static class Backticked extends AbstractJvmBasicCompletionTest { + public static class Backticked extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -357,7 +357,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/boldOrGrayed") - public static class BoldOrGrayed extends AbstractJvmBasicCompletionTest { + public static class BoldOrGrayed extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -465,7 +465,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/callableReference") - public static class CallableReference extends AbstractJvmBasicCompletionTest { + public static class CallableReference extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -533,7 +533,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/dslMarker") - public static class DslMarker extends AbstractJvmBasicCompletionTest { + public static class DslMarker extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -576,7 +576,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/extensionDeclarations") - public static class ExtensionDeclarations extends AbstractJvmBasicCompletionTest { + public static class ExtensionDeclarations extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -639,7 +639,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/extensionFunctionTypeValues") - public static class ExtensionFunctionTypeValues extends AbstractJvmBasicCompletionTest { + public static class ExtensionFunctionTypeValues extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -672,7 +672,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/extensionMethodInObject") - public static class ExtensionMethodInObject extends AbstractJvmBasicCompletionTest { + public static class ExtensionMethodInObject extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -765,7 +765,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/extensions") - public static class Extensions extends AbstractJvmBasicCompletionTest { + public static class Extensions extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -928,7 +928,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/fromSmart") - public static class FromSmart extends AbstractJvmBasicCompletionTest { + public static class FromSmart extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1001,7 +1001,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/fromUnresolvedNames") - public static class FromUnresolvedNames extends AbstractJvmBasicCompletionTest { + public static class FromUnresolvedNames extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1079,7 +1079,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/getOperator") - public static class GetOperator extends AbstractJvmBasicCompletionTest { + public static class GetOperator extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1102,7 +1102,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/highOrderFunctions") - public static class HighOrderFunctions extends AbstractJvmBasicCompletionTest { + public static class HighOrderFunctions extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1160,7 +1160,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/inInitBlock") - public static class InInitBlock extends AbstractJvmBasicCompletionTest { + public static class InInitBlock extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1178,7 +1178,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/inStringLiterals") - public static class InStringLiterals extends AbstractJvmBasicCompletionTest { + public static class InStringLiterals extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1216,7 +1216,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/inSuperTypes") - public static class InSuperTypes extends AbstractJvmBasicCompletionTest { + public static class InSuperTypes extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1239,7 +1239,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/inTypeAlias") - public static class InTypeAlias extends AbstractJvmBasicCompletionTest { + public static class InTypeAlias extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1257,7 +1257,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/lambdaAndTypeParams") - public static class LambdaAndTypeParams extends AbstractJvmBasicCompletionTest { + public static class LambdaAndTypeParams extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1290,7 +1290,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/lambdaSignature") - public static class LambdaSignature extends AbstractJvmBasicCompletionTest { + public static class LambdaSignature extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1348,7 +1348,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/namedArguments") - public static class NamedArguments extends AbstractJvmBasicCompletionTest { + public static class NamedArguments extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1476,7 +1476,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/noCompletion") - public static class NoCompletion extends AbstractJvmBasicCompletionTest { + public static class NoCompletion extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1519,7 +1519,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/objects") - public static class Objects extends AbstractJvmBasicCompletionTest { + public static class Objects extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1542,7 +1542,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/operatorNames") - public static class OperatorNames extends AbstractJvmBasicCompletionTest { + public static class OperatorNames extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1565,7 +1565,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/override") - public static class Override extends AbstractJvmBasicCompletionTest { + public static class Override extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1633,7 +1633,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/parameterNameAndType") - public static class ParameterNameAndType extends AbstractJvmBasicCompletionTest { + public static class ParameterNameAndType extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1821,7 +1821,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/primaryConstructor") - public static class PrimaryConstructor extends AbstractJvmBasicCompletionTest { + public static class PrimaryConstructor extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1844,7 +1844,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/primitiveCompletion") - public static class PrimitiveCompletion extends AbstractJvmBasicCompletionTest { + public static class PrimitiveCompletion extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2032,7 +2032,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/shadowing") - public static class Shadowing extends AbstractJvmBasicCompletionTest { + public static class Shadowing extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2175,7 +2175,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/smartCast") - public static class SmartCast extends AbstractJvmBasicCompletionTest { + public static class SmartCast extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2223,7 +2223,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/staticMembers") - public static class StaticMembers extends AbstractJvmBasicCompletionTest { + public static class StaticMembers extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2276,7 +2276,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/substitutedSignature") - public static class SubstitutedSignature extends AbstractJvmBasicCompletionTest { + public static class SubstitutedSignature extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2319,7 +2319,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/super") - public static class Super extends AbstractJvmBasicCompletionTest { + public static class Super extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2377,7 +2377,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/typeAliasTypes") - public static class TypeAliasTypes extends AbstractJvmBasicCompletionTest { + public static class TypeAliasTypes extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2395,7 +2395,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/typeArgsOrNot") - public static class TypeArgsOrNot extends AbstractJvmBasicCompletionTest { + public static class TypeArgsOrNot extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2448,7 +2448,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common") - public static class Uncategorized extends AbstractJvmBasicCompletionTest { + public static class Uncategorized extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3246,7 +3246,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/variableNameAndType") - public static class VariableNameAndType extends AbstractJvmBasicCompletionTest { + public static class VariableNameAndType extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3269,7 +3269,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/visibility") - public static class Visibility extends AbstractJvmBasicCompletionTest { + public static class Visibility extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3386,10 +3386,10 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/java") - public abstract static class Java extends AbstractJvmBasicCompletionTest { + public abstract static class Java extends AbstractK1JvmBasicCompletionTest { @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/java/boldOrGrayed") - public static class BoldOrGrayed extends AbstractJvmBasicCompletionTest { + public static class BoldOrGrayed extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3422,7 +3422,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/java/importAliases") - public static class ImportAliases extends AbstractJvmBasicCompletionTest { + public static class ImportAliases extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3475,7 +3475,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/java/syntheticExtensions") - public static class SyntheticExtensions extends AbstractJvmBasicCompletionTest { + public static class SyntheticExtensions extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3543,7 +3543,7 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/java") - public static class Uncategorized extends AbstractJvmBasicCompletionTest { + public static class Uncategorized extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/KDocCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1KDocCompletionTestGenerated.java similarity index 98% rename from plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/KDocCompletionTestGenerated.java rename to plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1KDocCompletionTestGenerated.java index 89fdc164b948..9df649a49658 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/KDocCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1KDocCompletionTestGenerated.java @@ -18,7 +18,7 @@ import org.junit.runner.RunWith; @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/kdoc") -public class KDocCompletionTestGenerated extends AbstractJvmBasicCompletionTest { +public class K1KDocCompletionTestGenerated extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } diff --git a/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJSBasicCompletionTest.java b/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJSBasicCompletionTestBase.java similarity index 90% rename from plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJSBasicCompletionTest.java rename to plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJSBasicCompletionTestBase.java index ea0fd9fca9cf..d4cee64d6bc0 100644 --- a/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJSBasicCompletionTest.java +++ b/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJSBasicCompletionTestBase.java @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.idea.test.KotlinStdJSProjectDescriptor; import org.jetbrains.kotlin.platform.TargetPlatform; import org.jetbrains.kotlin.platform.js.JsPlatforms; -public abstract class AbstractJSBasicCompletionTest extends KotlinFixtureCompletionBaseTestCase { +public abstract class AbstractJSBasicCompletionTestBase extends KotlinFixtureCompletionBaseTestCase { @NotNull @Override protected LightProjectDescriptor getProjectDescriptor() { diff --git a/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJava8BasicCompletionTest.kt b/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJava8BasicCompletionTest.kt index ab5b9f8b3f24..6215d6bb4b3e 100644 --- a/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJava8BasicCompletionTest.kt +++ b/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJava8BasicCompletionTest.kt @@ -2,9 +2,4 @@ package org.jetbrains.kotlin.idea.completion.test -import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor -import org.jetbrains.kotlin.platform.TargetPlatform -import org.jetbrains.kotlin.platform.jvm.JvmPlatforms - -abstract class AbstractJava8BasicCompletionTest : AbstractJvmBasicCompletionTest() \ No newline at end of file +abstract class AbstractJava8BasicCompletionTest : AbstractJvmBasicCompletionTestBase() \ No newline at end of file diff --git a/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJvmBasicCompletionTest.kt b/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJvmBasicCompletionTestBase.kt similarity index 95% rename from plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJvmBasicCompletionTest.kt rename to plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJvmBasicCompletionTestBase.kt index 00ae383deac3..7d8d54f28975 100644 --- a/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJvmBasicCompletionTest.kt +++ b/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/AbstractJvmBasicCompletionTestBase.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.idea.test.KotlinJdkAndLibraryProjectDescriptor import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.platform.jvm.JvmPlatforms -abstract class AbstractJvmBasicCompletionTest : KotlinFixtureCompletionBaseTestCase() { +abstract class AbstractJvmBasicCompletionTestBase : KotlinFixtureCompletionBaseTestCase() { override fun getProjectDescriptor(): LightProjectDescriptor = KotlinJdkAndLibraryProjectDescriptorOnJdk8 override fun getPlatform() = JvmPlatforms.jvm8 diff --git a/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/KotlinFixtureCompletionBaseTestCase.kt b/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/KotlinFixtureCompletionBaseTestCase.kt index ebbcbe0c027a..5e7c4a318424 100644 --- a/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/KotlinFixtureCompletionBaseTestCase.kt +++ b/plugins/kotlin/completion/tests-shared/test/org/jetbrains/kotlin/idea/completion/test/KotlinFixtureCompletionBaseTestCase.kt @@ -42,7 +42,8 @@ abstract class KotlinFixtureCompletionBaseTestCase : KotlinLightCodeInsightFixtu defaultCompletionType(), defaultInvocationCount(), ignoreProperties = ignoreProperties, - additionalValidDirectives = CompilerTestDirectives.ALL_COMPILER_TEST_DIRECTIVES + IgnoreTests.DIRECTIVES.FIR_IDENTICAL + additionalValidDirectives = CompilerTestDirectives.ALL_COMPILER_TEST_DIRECTIVES + + listOf(IgnoreTests.DIRECTIVES.FIR_IDENTICAL, IgnoreTests.DIRECTIVES.IGNORE_FE10) + listOf(CONFIGURE_LIBRARY_PREFIX, "WITH_STDLIB") ) } diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractHighLevelJvmBasicCompletionTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractHighLevelJvmBasicCompletionTest.kt index 09f130e445bc..d29a0f8aaadc 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractHighLevelJvmBasicCompletionTest.kt +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractHighLevelJvmBasicCompletionTest.kt @@ -3,13 +3,13 @@ package org.jetbrains.kotlin.idea.fir.completion import com.intellij.testFramework.common.runAll -import org.jetbrains.kotlin.idea.completion.test.AbstractJvmBasicCompletionTest +import org.jetbrains.kotlin.idea.completion.test.AbstractJvmBasicCompletionTestBase import org.jetbrains.kotlin.idea.completion.test.ExpectedCompletionUtils import org.jetbrains.kotlin.idea.completion.test.firFileName import org.jetbrains.kotlin.idea.fir.invalidateCaches import org.jetbrains.kotlin.test.utils.IgnoreTests -abstract class AbstractHighLevelJvmBasicCompletionTest : AbstractJvmBasicCompletionTest() { +abstract class AbstractHighLevelJvmBasicCompletionTest : AbstractJvmBasicCompletionTestBase() { override val captureExceptions: Boolean = false override fun isFirPlugin(): Boolean = true diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractCodeFragmentCompletionTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractCodeFragmentCompletionTest.kt index 091801aa0443..9f293585ce3a 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractCodeFragmentCompletionTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractCodeFragmentCompletionTest.kt @@ -2,9 +2,9 @@ package org.jetbrains.kotlin.idea.debugger.evaluate -import org.jetbrains.kotlin.idea.completion.test.AbstractJvmBasicCompletionTest +import org.jetbrains.kotlin.idea.completion.test.AbstractJvmBasicCompletionTestBase -abstract class AbstractCodeFragmentCompletionTest : AbstractJvmBasicCompletionTest() { +abstract class AbstractCodeFragmentCompletionTest : AbstractJvmBasicCompletionTestBase() { override fun configureFixture(testPath: String) { myFixture.configureByCodeFragment(testPath) } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionInLibraryTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionInLibraryTest.kt index 8babf345c56f..bd76740d76b8 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionInLibraryTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionInLibraryTest.kt @@ -7,7 +7,7 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiManager import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.ThrowableRunnable -import org.jetbrains.kotlin.idea.completion.test.AbstractJvmBasicCompletionTest +import org.jetbrains.kotlin.idea.completion.test.AbstractJvmBasicCompletionTestBase import org.jetbrains.kotlin.idea.completion.test.COMPLETION_TEST_DATA_BASE import org.jetbrains.kotlin.idea.completion.test.testCompletion import org.jetbrains.kotlin.idea.debugger.core.getContextElement @@ -22,7 +22,7 @@ import org.junit.runner.RunWith @RunWith(JUnit38ClassRunner::class) -class CodeFragmentCompletionInLibraryTest : AbstractJvmBasicCompletionTest() { +class CodeFragmentCompletionInLibraryTest : AbstractJvmBasicCompletionTestBase() { companion object { private val LIBRARY_SRC = COMPLETION_TEST_DATA_BASE.resolve("codeFragmentInLibrarySource/customLibrary/") } diff --git a/plugins/kotlin/util/test-generator-fe10/test/org/jetbrains/kotlin/fe10/testGenerator/Fe10GenerateTests.kt b/plugins/kotlin/util/test-generator-fe10/test/org/jetbrains/kotlin/fe10/testGenerator/Fe10GenerateTests.kt index 2f7b4de6f437..e4d147900556 100644 --- a/plugins/kotlin/util/test-generator-fe10/test/org/jetbrains/kotlin/fe10/testGenerator/Fe10GenerateTests.kt +++ b/plugins/kotlin/util/test-generator-fe10/test/org/jetbrains/kotlin/fe10/testGenerator/Fe10GenerateTests.kt @@ -1155,12 +1155,12 @@ private fun assembleWorkspace(): TWorkspace = workspace { model("weighers/smart", pattern = KT_OR_KTS_WITHOUT_DOTS) } - testClass { + testClass { model("basic/common", pattern = KT_WITHOUT_FIR_PREFIX) model("basic/js", pattern = KT_WITHOUT_FIR_PREFIX) } - testClass { + testClass { model("basic/common", pattern = KT_WITHOUT_FIR_PREFIX) model("basic/java", pattern = KT_WITHOUT_FIR_PREFIX) } @@ -1205,7 +1205,7 @@ private fun assembleWorkspace(): TWorkspace = workspace { model("smartMultiFile", pattern = DIRECTORY, isRecursive = false) } - testClass("org.jetbrains.kotlin.idea.completion.test.KDocCompletionTestGenerated") { + testClass("org.jetbrains.kotlin.idea.completion.test.K1KDocCompletionTestGenerated") { model("kdoc", pattern = KT_WITHOUT_DOT_AND_FIR_PREFIX) } From f984087e849df91d5e66951a9fd542f452e0f264 Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Fri, 30 Jun 2023 13:44:24 +0300 Subject: [PATCH 063/165] [kotlin] Rename `AbstractHighLevelJvmBasicCompletionTest` to `AbstractK2JvmBasicCompletionTest` GitOrigin-RevId: 6cc79e0826920ae805469180920d8c40beba3260 --- ...kt => AbstractK2JvmBasicCompletionTest.kt} | 2 +- ...BasicCompletionTestWithResolveExtension.kt | 2 +- ...=> K2JvmBasicCompletionTestGenerated.java} | 92 +++++++++---------- ...ava => K2KDocCompletionTestGenerated.java} | 2 +- .../fir/testGenerator/FirGenerateTests.kt | 4 +- 5 files changed, 51 insertions(+), 51 deletions(-) rename plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/{AbstractHighLevelJvmBasicCompletionTest.kt => AbstractK2JvmBasicCompletionTest.kt} (93%) rename plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/{HighLevelJvmBasicCompletionTestGenerated.java => K2JvmBasicCompletionTestGenerated.java} (98%) rename plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/{HighLevelKDocCompletionTestGenerated.java => K2KDocCompletionTestGenerated.java} (98%) diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractHighLevelJvmBasicCompletionTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractK2JvmBasicCompletionTest.kt similarity index 93% rename from plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractHighLevelJvmBasicCompletionTest.kt rename to plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractK2JvmBasicCompletionTest.kt index d29a0f8aaadc..499752c875ac 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractHighLevelJvmBasicCompletionTest.kt +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractK2JvmBasicCompletionTest.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.idea.completion.test.firFileName import org.jetbrains.kotlin.idea.fir.invalidateCaches import org.jetbrains.kotlin.test.utils.IgnoreTests -abstract class AbstractHighLevelJvmBasicCompletionTest : AbstractJvmBasicCompletionTestBase() { +abstract class AbstractK2JvmBasicCompletionTest : AbstractJvmBasicCompletionTestBase() { override val captureExceptions: Boolean = false override fun isFirPlugin(): Boolean = true diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractK2JvmBasicCompletionTestWithResolveExtension.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractK2JvmBasicCompletionTestWithResolveExtension.kt index c1bf0ac1443d..e15c1ff2dab8 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractK2JvmBasicCompletionTestWithResolveExtension.kt +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/AbstractK2JvmBasicCompletionTestWithResolveExtension.kt @@ -7,7 +7,7 @@ import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionPr import org.jetbrains.kotlin.idea.fir.extensions.KtResolveExtensionProviderForTests import org.jetbrains.kotlin.idea.fir.invalidateCaches -abstract class AbstractK2JvmBasicCompletionTestWithResolveExtension : AbstractHighLevelJvmBasicCompletionTest() { +abstract class AbstractK2JvmBasicCompletionTestWithResolveExtension : AbstractK2JvmBasicCompletionTest() { override fun setUp() { super.setUp() myFixture.addFileToProject("data.xml", diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java similarity index 98% rename from plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java rename to plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java index 6c58f2a07b65..52c5ad3405f1 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelJvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java @@ -17,13 +17,13 @@ import org.junit.runner.RunWith; @TestRoot("fir") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJvmBasicCompletionTest { +public abstract class K2JvmBasicCompletionTestGenerated extends AbstractK2JvmBasicCompletionTest { @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common") - public abstract static class Common extends AbstractHighLevelJvmBasicCompletionTest { + public abstract static class Common extends AbstractK2JvmBasicCompletionTest { @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/annotations") - public static class Annotations extends AbstractHighLevelJvmBasicCompletionTest { + public static class Annotations extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -236,7 +236,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/autoPopup") - public static class AutoPopup extends AbstractHighLevelJvmBasicCompletionTest { + public static class AutoPopup extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -334,7 +334,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/backticked") - public static class Backticked extends AbstractHighLevelJvmBasicCompletionTest { + public static class Backticked extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -357,7 +357,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/boldOrGrayed") - public static class BoldOrGrayed extends AbstractHighLevelJvmBasicCompletionTest { + public static class BoldOrGrayed extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -465,7 +465,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/callableReference") - public static class CallableReference extends AbstractHighLevelJvmBasicCompletionTest { + public static class CallableReference extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -533,7 +533,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/dslMarker") - public static class DslMarker extends AbstractHighLevelJvmBasicCompletionTest { + public static class DslMarker extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -576,7 +576,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/extensionDeclarations") - public static class ExtensionDeclarations extends AbstractHighLevelJvmBasicCompletionTest { + public static class ExtensionDeclarations extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -639,7 +639,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/extensionFunctionTypeValues") - public static class ExtensionFunctionTypeValues extends AbstractHighLevelJvmBasicCompletionTest { + public static class ExtensionFunctionTypeValues extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -672,7 +672,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/extensionMethodInObject") - public static class ExtensionMethodInObject extends AbstractHighLevelJvmBasicCompletionTest { + public static class ExtensionMethodInObject extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -765,7 +765,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/extensions") - public static class Extensions extends AbstractHighLevelJvmBasicCompletionTest { + public static class Extensions extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -928,7 +928,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/fromSmart") - public static class FromSmart extends AbstractHighLevelJvmBasicCompletionTest { + public static class FromSmart extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1001,7 +1001,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/fromUnresolvedNames") - public static class FromUnresolvedNames extends AbstractHighLevelJvmBasicCompletionTest { + public static class FromUnresolvedNames extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1079,7 +1079,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/getOperator") - public static class GetOperator extends AbstractHighLevelJvmBasicCompletionTest { + public static class GetOperator extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1102,7 +1102,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/highOrderFunctions") - public static class HighOrderFunctions extends AbstractHighLevelJvmBasicCompletionTest { + public static class HighOrderFunctions extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1160,7 +1160,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/inInitBlock") - public static class InInitBlock extends AbstractHighLevelJvmBasicCompletionTest { + public static class InInitBlock extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1178,7 +1178,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/inStringLiterals") - public static class InStringLiterals extends AbstractHighLevelJvmBasicCompletionTest { + public static class InStringLiterals extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1216,7 +1216,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/inSuperTypes") - public static class InSuperTypes extends AbstractHighLevelJvmBasicCompletionTest { + public static class InSuperTypes extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1239,7 +1239,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/inTypeAlias") - public static class InTypeAlias extends AbstractHighLevelJvmBasicCompletionTest { + public static class InTypeAlias extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1257,7 +1257,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/lambdaAndTypeParams") - public static class LambdaAndTypeParams extends AbstractHighLevelJvmBasicCompletionTest { + public static class LambdaAndTypeParams extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1290,7 +1290,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/lambdaSignature") - public static class LambdaSignature extends AbstractHighLevelJvmBasicCompletionTest { + public static class LambdaSignature extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1348,7 +1348,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/namedArguments") - public static class NamedArguments extends AbstractHighLevelJvmBasicCompletionTest { + public static class NamedArguments extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1476,7 +1476,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/noCompletion") - public static class NoCompletion extends AbstractHighLevelJvmBasicCompletionTest { + public static class NoCompletion extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1519,7 +1519,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/objects") - public static class Objects extends AbstractHighLevelJvmBasicCompletionTest { + public static class Objects extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1542,7 +1542,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/operatorNames") - public static class OperatorNames extends AbstractHighLevelJvmBasicCompletionTest { + public static class OperatorNames extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1565,7 +1565,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/override") - public static class Override extends AbstractHighLevelJvmBasicCompletionTest { + public static class Override extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1633,7 +1633,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/parameterNameAndType") - public static class ParameterNameAndType extends AbstractHighLevelJvmBasicCompletionTest { + public static class ParameterNameAndType extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1821,7 +1821,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/primaryConstructor") - public static class PrimaryConstructor extends AbstractHighLevelJvmBasicCompletionTest { + public static class PrimaryConstructor extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -1844,7 +1844,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/primitiveCompletion") - public static class PrimitiveCompletion extends AbstractHighLevelJvmBasicCompletionTest { + public static class PrimitiveCompletion extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2032,7 +2032,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/shadowing") - public static class Shadowing extends AbstractHighLevelJvmBasicCompletionTest { + public static class Shadowing extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2175,7 +2175,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/smartCast") - public static class SmartCast extends AbstractHighLevelJvmBasicCompletionTest { + public static class SmartCast extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2223,7 +2223,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/staticMembers") - public static class StaticMembers extends AbstractHighLevelJvmBasicCompletionTest { + public static class StaticMembers extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2276,7 +2276,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/substitutedSignature") - public static class SubstitutedSignature extends AbstractHighLevelJvmBasicCompletionTest { + public static class SubstitutedSignature extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2319,7 +2319,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/super") - public static class Super extends AbstractHighLevelJvmBasicCompletionTest { + public static class Super extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2377,7 +2377,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/typeAliasTypes") - public static class TypeAliasTypes extends AbstractHighLevelJvmBasicCompletionTest { + public static class TypeAliasTypes extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2395,7 +2395,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/typeArgsOrNot") - public static class TypeArgsOrNot extends AbstractHighLevelJvmBasicCompletionTest { + public static class TypeArgsOrNot extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -2448,7 +2448,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common") - public static class Uncategorized extends AbstractHighLevelJvmBasicCompletionTest { + public static class Uncategorized extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3246,7 +3246,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/variableNameAndType") - public static class VariableNameAndType extends AbstractHighLevelJvmBasicCompletionTest { + public static class VariableNameAndType extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3269,7 +3269,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/visibility") - public static class Visibility extends AbstractHighLevelJvmBasicCompletionTest { + public static class Visibility extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3386,10 +3386,10 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/java") - public abstract static class Java extends AbstractHighLevelJvmBasicCompletionTest { + public abstract static class Java extends AbstractK2JvmBasicCompletionTest { @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/java/boldOrGrayed") - public static class BoldOrGrayed extends AbstractHighLevelJvmBasicCompletionTest { + public static class BoldOrGrayed extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3422,7 +3422,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/java/importAliases") - public static class ImportAliases extends AbstractHighLevelJvmBasicCompletionTest { + public static class ImportAliases extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3475,7 +3475,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/java/syntheticExtensions") - public static class SyntheticExtensions extends AbstractHighLevelJvmBasicCompletionTest { + public static class SyntheticExtensions extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3543,7 +3543,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/java") - public static class Uncategorized extends AbstractHighLevelJvmBasicCompletionTest { + public static class Uncategorized extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -3672,7 +3672,7 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../idea-fir/testData/completion/basic/common") - public abstract static class CommonFir extends AbstractHighLevelJvmBasicCompletionTest { + public abstract static class CommonFir extends AbstractK2JvmBasicCompletionTest { } } diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelKDocCompletionTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2KDocCompletionTestGenerated.java similarity index 98% rename from plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelKDocCompletionTestGenerated.java rename to plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2KDocCompletionTestGenerated.java index 083ab10f9a14..9c75313aa949 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/HighLevelKDocCompletionTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2KDocCompletionTestGenerated.java @@ -18,7 +18,7 @@ import org.junit.runner.RunWith; @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/kdoc") -public class HighLevelKDocCompletionTestGenerated extends AbstractHighLevelJvmBasicCompletionTest { +public class K2KDocCompletionTestGenerated extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt index d5858963d7ee..c68b9382660f 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/FirGenerateTests.kt @@ -212,13 +212,13 @@ private fun assembleWorkspace(): TWorkspace = workspace { } testGroup("fir", testDataPath = "../completion/testData") { - testClass { + testClass { model("basic/common", pattern = KT_WITHOUT_FIR_PREFIX) model("basic/java", pattern = KT_WITHOUT_FIR_PREFIX) model("../../idea-fir/testData/completion/basic/common", testClassName = "CommonFir") } - testClass("org.jetbrains.kotlin.idea.fir.completion.HighLevelKDocCompletionTestGenerated") { + testClass("org.jetbrains.kotlin.idea.fir.completion.K2KDocCompletionTestGenerated") { model("kdoc", pattern = KT_WITHOUT_FIR_PREFIX) } From 7d801566b6f2cadc7c0199f30d3c1376ef23275b Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Fri, 30 Jun 2023 14:31:28 +0300 Subject: [PATCH 064/165] [kotlin] K2: Generate missing tests GitOrigin-RevId: 9d64176662b53e8abd007a28fb546a43417a6fc3 --- .../basic/common/SuperWithQualifier.kt} | 1 + .../basic/common/when/enumInEmptyWhen.kt | 2 + .../testData}/basic/common/when/enumInWhen.kt | 2 + .../when/enumInWhenWithOtherConditions.kt | 2 + .../common/when/enumInWhenWithPackage.kt | 2 + .../common/when/nestedSealedClassInWhen.kt | 2 + .../nestedSealedClassInWhenWithPackage.kt | 2 + .../basic/common/when/nonSealedClassInWhen.kt | 4 + .../common/when/nonSealedClassWithTypeArgs.kt | 3 + .../basic/common/when/nullableEnumInWhen.kt | 2 + .../common/when/nullableSealedClassInWhen.kt | 2 + .../basic/common/when/sealedClassInWhen.kt | 2 + .../sealedClassInWhenWithOtherConditions.kt | 2 + ...sealedClassWithAbstractInheritorsInWhen.kt | 3 + .../common/when/sealedClassWithTypeArgs.kt | 2 + .../common/when/sealedInterfaceInWhen.kt | 2 + .../where/noCompletionAfterDotInWhen.kt | 2 + .../basic/common/where/whereInClass.kt | 2 + .../basic/common/where/whereInFunction.kt | 2 + .../K1JSBasicCompletionTestGenerated.java | 105 +++++++++++++++++- .../K1JvmBasicCompletionTestGenerated.java | 105 +++++++++++++++++- .../K2JvmBasicCompletionTestGenerated.java | 105 +++++++++++++++++- 22 files changed, 353 insertions(+), 3 deletions(-) rename plugins/kotlin/{fir/testData/completion/keywords/superWithQualifier.kt => completion/testData/basic/common/SuperWithQualifier.kt} (92%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/enumInEmptyWhen.kt (87%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/enumInWhen.kt (87%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/enumInWhenWithOtherConditions.kt (85%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/enumInWhenWithPackage.kt (88%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/nestedSealedClassInWhen.kt (90%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/nestedSealedClassInWhenWithPackage.kt (90%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/nonSealedClassInWhen.kt (86%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/nonSealedClassWithTypeArgs.kt (87%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/nullableEnumInWhen.kt (88%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/nullableSealedClassInWhen.kt (89%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/sealedClassInWhen.kt (89%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/sealedClassInWhenWithOtherConditions.kt (89%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/sealedClassWithAbstractInheritorsInWhen.kt (85%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/sealedClassWithTypeArgs.kt (91%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/when/sealedInterfaceInWhen.kt (89%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/where/noCompletionAfterDotInWhen.kt (67%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/where/whereInClass.kt (73%) rename plugins/kotlin/{fir/testData/completion => completion/testData}/basic/common/where/whereInFunction.kt (73%) diff --git a/plugins/kotlin/fir/testData/completion/keywords/superWithQualifier.kt b/plugins/kotlin/completion/testData/basic/common/SuperWithQualifier.kt similarity index 92% rename from plugins/kotlin/fir/testData/completion/keywords/superWithQualifier.kt rename to plugins/kotlin/completion/testData/basic/common/SuperWithQualifier.kt index a33254010d70..a66cbdcb8797 100644 --- a/plugins/kotlin/fir/testData/completion/keywords/superWithQualifier.kt +++ b/plugins/kotlin/completion/testData/basic/common/SuperWithQualifier.kt @@ -1,3 +1,4 @@ +// IGNORE_FE10 // FIR_IDENTICAL // FIR_COMPARISON class X: List, Comparable { diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/enumInEmptyWhen.kt b/plugins/kotlin/completion/testData/basic/common/when/enumInEmptyWhen.kt similarity index 87% rename from plugins/kotlin/fir/testData/completion/basic/common/when/enumInEmptyWhen.kt rename to plugins/kotlin/completion/testData/basic/common/when/enumInEmptyWhen.kt index 284973853dfd..04dad437da2b 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/enumInEmptyWhen.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/enumInEmptyWhen.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 enum class ENUM { AAAA, BBBB, CCCC } diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/enumInWhen.kt b/plugins/kotlin/completion/testData/basic/common/when/enumInWhen.kt similarity index 87% rename from plugins/kotlin/fir/testData/completion/basic/common/when/enumInWhen.kt rename to plugins/kotlin/completion/testData/basic/common/when/enumInWhen.kt index ae32b8dbdd49..1c6d530faf5b 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/enumInWhen.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/enumInWhen.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 enum class ENUM { AAAA, BBBB, CCCC } diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/enumInWhenWithOtherConditions.kt b/plugins/kotlin/completion/testData/basic/common/when/enumInWhenWithOtherConditions.kt similarity index 85% rename from plugins/kotlin/fir/testData/completion/basic/common/when/enumInWhenWithOtherConditions.kt rename to plugins/kotlin/completion/testData/basic/common/when/enumInWhenWithOtherConditions.kt index 603133b8e448..c24b1cc03eb2 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/enumInWhenWithOtherConditions.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/enumInWhenWithOtherConditions.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 enum class ENUM { AAAA, BBBB, CCCC } diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/enumInWhenWithPackage.kt b/plugins/kotlin/completion/testData/basic/common/when/enumInWhenWithPackage.kt similarity index 88% rename from plugins/kotlin/fir/testData/completion/basic/common/when/enumInWhenWithPackage.kt rename to plugins/kotlin/completion/testData/basic/common/when/enumInWhenWithPackage.kt index cfd394f5734c..38e053ca7bfb 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/enumInWhenWithPackage.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/enumInWhenWithPackage.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 package a.b.c enum class ENUM { diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/nestedSealedClassInWhen.kt b/plugins/kotlin/completion/testData/basic/common/when/nestedSealedClassInWhen.kt similarity index 90% rename from plugins/kotlin/fir/testData/completion/basic/common/when/nestedSealedClassInWhen.kt rename to plugins/kotlin/completion/testData/basic/common/when/nestedSealedClassInWhen.kt index a14d1f7cf9ce..b649310e0bbe 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/nestedSealedClassInWhen.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/nestedSealedClassInWhen.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 sealed class SEALED { class AAAA: SEALED() object BBBB: SEALED() diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/nestedSealedClassInWhenWithPackage.kt b/plugins/kotlin/completion/testData/basic/common/when/nestedSealedClassInWhenWithPackage.kt similarity index 90% rename from plugins/kotlin/fir/testData/completion/basic/common/when/nestedSealedClassInWhenWithPackage.kt rename to plugins/kotlin/completion/testData/basic/common/when/nestedSealedClassInWhenWithPackage.kt index 9635859bf7e5..31e80338d550 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/nestedSealedClassInWhenWithPackage.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/nestedSealedClassInWhenWithPackage.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 package a.b.c sealed class SEALED { diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/nonSealedClassInWhen.kt b/plugins/kotlin/completion/testData/basic/common/when/nonSealedClassInWhen.kt similarity index 86% rename from plugins/kotlin/fir/testData/completion/basic/common/when/nonSealedClassInWhen.kt rename to plugins/kotlin/completion/testData/basic/common/when/nonSealedClassInWhen.kt index 072755a6191a..36ff7bccff66 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/nonSealedClassInWhen.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/nonSealedClassInWhen.kt @@ -1,3 +1,7 @@ +// FIR_IDENTICAL +// FIR_COMPARISON +// IGNORE_FE10 + abstract class SEALED class AAAA: SEALED() object BBBB: SEALED() diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/nonSealedClassWithTypeArgs.kt b/plugins/kotlin/completion/testData/basic/common/when/nonSealedClassWithTypeArgs.kt similarity index 87% rename from plugins/kotlin/fir/testData/completion/basic/common/when/nonSealedClassWithTypeArgs.kt rename to plugins/kotlin/completion/testData/basic/common/when/nonSealedClassWithTypeArgs.kt index b35e9122620f..9c0671dc2920 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/nonSealedClassWithTypeArgs.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/nonSealedClassWithTypeArgs.kt @@ -1,3 +1,6 @@ +// FIR_IDENTICAL +// FIR_COMPARISON +// IGNORE_FE10 class NON_SEALED class AAAA: NON_SEALED() object BBBB: NON_SEALED() diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/nullableEnumInWhen.kt b/plugins/kotlin/completion/testData/basic/common/when/nullableEnumInWhen.kt similarity index 88% rename from plugins/kotlin/fir/testData/completion/basic/common/when/nullableEnumInWhen.kt rename to plugins/kotlin/completion/testData/basic/common/when/nullableEnumInWhen.kt index 2677b4d720a9..6cdb8f15ca83 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/nullableEnumInWhen.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/nullableEnumInWhen.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 enum class ENUM { AAAA, BBBB, CCCC } diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/nullableSealedClassInWhen.kt b/plugins/kotlin/completion/testData/basic/common/when/nullableSealedClassInWhen.kt similarity index 89% rename from plugins/kotlin/fir/testData/completion/basic/common/when/nullableSealedClassInWhen.kt rename to plugins/kotlin/completion/testData/basic/common/when/nullableSealedClassInWhen.kt index 9ba28df4f655..f3a70d964f1e 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/nullableSealedClassInWhen.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/nullableSealedClassInWhen.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 sealed class SEALED class AAAA: SEALED() object BBBB: SEALED() diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassInWhen.kt b/plugins/kotlin/completion/testData/basic/common/when/sealedClassInWhen.kt similarity index 89% rename from plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassInWhen.kt rename to plugins/kotlin/completion/testData/basic/common/when/sealedClassInWhen.kt index e5048afe7749..74516b7fcda0 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassInWhen.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/sealedClassInWhen.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 sealed class SEALED class AAAA: SEALED() object BBBB: SEALED() diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassInWhenWithOtherConditions.kt b/plugins/kotlin/completion/testData/basic/common/when/sealedClassInWhenWithOtherConditions.kt similarity index 89% rename from plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassInWhenWithOtherConditions.kt rename to plugins/kotlin/completion/testData/basic/common/when/sealedClassInWhenWithOtherConditions.kt index d0fbe10592b0..37233ad1f125 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassInWhenWithOtherConditions.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/sealedClassInWhenWithOtherConditions.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 sealed class SEALED class AAAA: SEALED() object BBBB: SEALED() diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassWithAbstractInheritorsInWhen.kt b/plugins/kotlin/completion/testData/basic/common/when/sealedClassWithAbstractInheritorsInWhen.kt similarity index 85% rename from plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassWithAbstractInheritorsInWhen.kt rename to plugins/kotlin/completion/testData/basic/common/when/sealedClassWithAbstractInheritorsInWhen.kt index f12155b93d6c..c8f56a5a3f0d 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassWithAbstractInheritorsInWhen.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/sealedClassWithAbstractInheritorsInWhen.kt @@ -1,3 +1,6 @@ +// FIR_IDENTICAL +// FIR_COMPARISON +// IGNORE_FE10 sealed class SEALED class AAAA: SEALED() object BBBB: SEALED() diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassWithTypeArgs.kt b/plugins/kotlin/completion/testData/basic/common/when/sealedClassWithTypeArgs.kt similarity index 91% rename from plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassWithTypeArgs.kt rename to plugins/kotlin/completion/testData/basic/common/when/sealedClassWithTypeArgs.kt index bde6d30ae28c..4c5d23fde10f 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/sealedClassWithTypeArgs.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/sealedClassWithTypeArgs.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 sealed class SEALED class AAAA: SEALED() object BBBB: SEALED() diff --git a/plugins/kotlin/fir/testData/completion/basic/common/when/sealedInterfaceInWhen.kt b/plugins/kotlin/completion/testData/basic/common/when/sealedInterfaceInWhen.kt similarity index 89% rename from plugins/kotlin/fir/testData/completion/basic/common/when/sealedInterfaceInWhen.kt rename to plugins/kotlin/completion/testData/basic/common/when/sealedInterfaceInWhen.kt index 41ab70f8a895..75b40a25bfdc 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/when/sealedInterfaceInWhen.kt +++ b/plugins/kotlin/completion/testData/basic/common/when/sealedInterfaceInWhen.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 sealed interface SEALED class AAAA: SEALED() object BBBB: SEALED() diff --git a/plugins/kotlin/fir/testData/completion/basic/common/where/noCompletionAfterDotInWhen.kt b/plugins/kotlin/completion/testData/basic/common/where/noCompletionAfterDotInWhen.kt similarity index 67% rename from plugins/kotlin/fir/testData/completion/basic/common/where/noCompletionAfterDotInWhen.kt rename to plugins/kotlin/completion/testData/basic/common/where/noCompletionAfterDotInWhen.kt index 2b011750b74a..252dbbcc78d4 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/where/noCompletionAfterDotInWhen.kt +++ b/plugins/kotlin/completion/testData/basic/common/where/noCompletionAfterDotInWhen.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 fun foo() where T. // NOTHING_ELSE diff --git a/plugins/kotlin/fir/testData/completion/basic/common/where/whereInClass.kt b/plugins/kotlin/completion/testData/basic/common/where/whereInClass.kt similarity index 73% rename from plugins/kotlin/fir/testData/completion/basic/common/where/whereInClass.kt rename to plugins/kotlin/completion/testData/basic/common/where/whereInClass.kt index dab56ab5b039..96f03f6ae432 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/where/whereInClass.kt +++ b/plugins/kotlin/completion/testData/basic/common/where/whereInClass.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 class X() where diff --git a/plugins/kotlin/fir/testData/completion/basic/common/where/whereInFunction.kt b/plugins/kotlin/completion/testData/basic/common/where/whereInFunction.kt similarity index 73% rename from plugins/kotlin/fir/testData/completion/basic/common/where/whereInFunction.kt rename to plugins/kotlin/completion/testData/basic/common/where/whereInFunction.kt index fd6c5294d504..c64634e1832c 100644 --- a/plugins/kotlin/fir/testData/completion/basic/common/where/whereInFunction.kt +++ b/plugins/kotlin/completion/testData/basic/common/where/whereInFunction.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL +// IGNORE_FE10 fun foo() where diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java index b0ed9db7eb0c..002ac4018d39 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java @@ -3168,6 +3168,11 @@ public abstract class K1JSBasicCompletionTestGenerated extends AbstractK1JSBasic runTest("../testData/basic/common/SuperMembers4.kt"); } + @TestMetadata("SuperWithQualifier.kt") + public void testSuperWithQualifier() throws Exception { + runTest("../testData/basic/common/SuperWithQualifier.kt"); + } + @TestMetadata("SuspendCanBePrefixSelectedInParameterTypeCompletion.kt") public void testSuspendCanBePrefixSelectedInParameterTypeCompletion() throws Exception { runTest("../testData/basic/common/SuspendCanBePrefixSelectedInParameterTypeCompletion.kt"); @@ -3362,11 +3367,86 @@ public abstract class K1JSBasicCompletionTestGenerated extends AbstractK1JSBasic @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/when") - public static class When extends AbstractJSBasicCompletionTest { + public static class When extends AbstractK1JSBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("enumInEmptyWhen.kt") + public void testEnumInEmptyWhen() throws Exception { + runTest("../testData/basic/common/when/enumInEmptyWhen.kt"); + } + + @TestMetadata("enumInWhen.kt") + public void testEnumInWhen() throws Exception { + runTest("../testData/basic/common/when/enumInWhen.kt"); + } + + @TestMetadata("enumInWhenWithOtherConditions.kt") + public void testEnumInWhenWithOtherConditions() throws Exception { + runTest("../testData/basic/common/when/enumInWhenWithOtherConditions.kt"); + } + + @TestMetadata("enumInWhenWithPackage.kt") + public void testEnumInWhenWithPackage() throws Exception { + runTest("../testData/basic/common/when/enumInWhenWithPackage.kt"); + } + + @TestMetadata("nestedSealedClassInWhen.kt") + public void testNestedSealedClassInWhen() throws Exception { + runTest("../testData/basic/common/when/nestedSealedClassInWhen.kt"); + } + + @TestMetadata("nestedSealedClassInWhenWithPackage.kt") + public void testNestedSealedClassInWhenWithPackage() throws Exception { + runTest("../testData/basic/common/when/nestedSealedClassInWhenWithPackage.kt"); + } + + @TestMetadata("nonSealedClassInWhen.kt") + public void testNonSealedClassInWhen() throws Exception { + runTest("../testData/basic/common/when/nonSealedClassInWhen.kt"); + } + + @TestMetadata("nonSealedClassWithTypeArgs.kt") + public void testNonSealedClassWithTypeArgs() throws Exception { + runTest("../testData/basic/common/when/nonSealedClassWithTypeArgs.kt"); + } + + @TestMetadata("nullableEnumInWhen.kt") + public void testNullableEnumInWhen() throws Exception { + runTest("../testData/basic/common/when/nullableEnumInWhen.kt"); + } + + @TestMetadata("nullableSealedClassInWhen.kt") + public void testNullableSealedClassInWhen() throws Exception { + runTest("../testData/basic/common/when/nullableSealedClassInWhen.kt"); + } + + @TestMetadata("sealedClassInWhen.kt") + public void testSealedClassInWhen() throws Exception { + runTest("../testData/basic/common/when/sealedClassInWhen.kt"); + } + + @TestMetadata("sealedClassInWhenWithOtherConditions.kt") + public void testSealedClassInWhenWithOtherConditions() throws Exception { + runTest("../testData/basic/common/when/sealedClassInWhenWithOtherConditions.kt"); + } + + @TestMetadata("sealedClassWithAbstractInheritorsInWhen.kt") + public void testSealedClassWithAbstractInheritorsInWhen() throws Exception { + runTest("../testData/basic/common/when/sealedClassWithAbstractInheritorsInWhen.kt"); + } + + @TestMetadata("sealedClassWithTypeArgs.kt") + public void testSealedClassWithTypeArgs() throws Exception { + runTest("../testData/basic/common/when/sealedClassWithTypeArgs.kt"); + } + + @TestMetadata("sealedInterfaceInWhen.kt") + public void testSealedInterfaceInWhen() throws Exception { + runTest("../testData/basic/common/when/sealedInterfaceInWhen.kt"); + } + @TestMetadata("smartCast.kt") public void testSmartCast() throws Exception { runTest("../testData/basic/common/when/smartCast.kt"); @@ -3382,6 +3462,29 @@ public abstract class K1JSBasicCompletionTestGenerated extends AbstractK1JSBasic runTest("../testData/basic/common/when/smartCast3.kt"); } } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../testData/basic/common/where") + public static class Where extends AbstractK1JSBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("noCompletionAfterDotInWhen.kt") + public void testNoCompletionAfterDotInWhen() throws Exception { + runTest("../testData/basic/common/where/noCompletionAfterDotInWhen.kt"); + } + + @TestMetadata("whereInClass.kt") + public void testWhereInClass() throws Exception { + runTest("../testData/basic/common/where/whereInClass.kt"); + } + + @TestMetadata("whereInFunction.kt") + public void testWhereInFunction() throws Exception { + runTest("../testData/basic/common/where/whereInFunction.kt"); + } + } } @RunWith(JUnit3RunnerWithInners.class) diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java index 15dbc6d936bd..394179491101 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java @@ -3168,6 +3168,11 @@ public abstract class K1JvmBasicCompletionTestGenerated extends AbstractK1JvmBas runTest("../testData/basic/common/SuperMembers4.kt"); } + @TestMetadata("SuperWithQualifier.kt") + public void testSuperWithQualifier() throws Exception { + runTest("../testData/basic/common/SuperWithQualifier.kt"); + } + @TestMetadata("SuspendCanBePrefixSelectedInParameterTypeCompletion.kt") public void testSuspendCanBePrefixSelectedInParameterTypeCompletion() throws Exception { runTest("../testData/basic/common/SuspendCanBePrefixSelectedInParameterTypeCompletion.kt"); @@ -3362,11 +3367,86 @@ public abstract class K1JvmBasicCompletionTestGenerated extends AbstractK1JvmBas @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/basic/common/when") - public static class When extends AbstractJvmBasicCompletionTest { + public static class When extends AbstractK1JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("enumInEmptyWhen.kt") + public void testEnumInEmptyWhen() throws Exception { + runTest("../testData/basic/common/when/enumInEmptyWhen.kt"); + } + + @TestMetadata("enumInWhen.kt") + public void testEnumInWhen() throws Exception { + runTest("../testData/basic/common/when/enumInWhen.kt"); + } + + @TestMetadata("enumInWhenWithOtherConditions.kt") + public void testEnumInWhenWithOtherConditions() throws Exception { + runTest("../testData/basic/common/when/enumInWhenWithOtherConditions.kt"); + } + + @TestMetadata("enumInWhenWithPackage.kt") + public void testEnumInWhenWithPackage() throws Exception { + runTest("../testData/basic/common/when/enumInWhenWithPackage.kt"); + } + + @TestMetadata("nestedSealedClassInWhen.kt") + public void testNestedSealedClassInWhen() throws Exception { + runTest("../testData/basic/common/when/nestedSealedClassInWhen.kt"); + } + + @TestMetadata("nestedSealedClassInWhenWithPackage.kt") + public void testNestedSealedClassInWhenWithPackage() throws Exception { + runTest("../testData/basic/common/when/nestedSealedClassInWhenWithPackage.kt"); + } + + @TestMetadata("nonSealedClassInWhen.kt") + public void testNonSealedClassInWhen() throws Exception { + runTest("../testData/basic/common/when/nonSealedClassInWhen.kt"); + } + + @TestMetadata("nonSealedClassWithTypeArgs.kt") + public void testNonSealedClassWithTypeArgs() throws Exception { + runTest("../testData/basic/common/when/nonSealedClassWithTypeArgs.kt"); + } + + @TestMetadata("nullableEnumInWhen.kt") + public void testNullableEnumInWhen() throws Exception { + runTest("../testData/basic/common/when/nullableEnumInWhen.kt"); + } + + @TestMetadata("nullableSealedClassInWhen.kt") + public void testNullableSealedClassInWhen() throws Exception { + runTest("../testData/basic/common/when/nullableSealedClassInWhen.kt"); + } + + @TestMetadata("sealedClassInWhen.kt") + public void testSealedClassInWhen() throws Exception { + runTest("../testData/basic/common/when/sealedClassInWhen.kt"); + } + + @TestMetadata("sealedClassInWhenWithOtherConditions.kt") + public void testSealedClassInWhenWithOtherConditions() throws Exception { + runTest("../testData/basic/common/when/sealedClassInWhenWithOtherConditions.kt"); + } + + @TestMetadata("sealedClassWithAbstractInheritorsInWhen.kt") + public void testSealedClassWithAbstractInheritorsInWhen() throws Exception { + runTest("../testData/basic/common/when/sealedClassWithAbstractInheritorsInWhen.kt"); + } + + @TestMetadata("sealedClassWithTypeArgs.kt") + public void testSealedClassWithTypeArgs() throws Exception { + runTest("../testData/basic/common/when/sealedClassWithTypeArgs.kt"); + } + + @TestMetadata("sealedInterfaceInWhen.kt") + public void testSealedInterfaceInWhen() throws Exception { + runTest("../testData/basic/common/when/sealedInterfaceInWhen.kt"); + } + @TestMetadata("smartCast.kt") public void testSmartCast() throws Exception { runTest("../testData/basic/common/when/smartCast.kt"); @@ -3382,6 +3462,29 @@ public abstract class K1JvmBasicCompletionTestGenerated extends AbstractK1JvmBas runTest("../testData/basic/common/when/smartCast3.kt"); } } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../testData/basic/common/where") + public static class Where extends AbstractK1JvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("noCompletionAfterDotInWhen.kt") + public void testNoCompletionAfterDotInWhen() throws Exception { + runTest("../testData/basic/common/where/noCompletionAfterDotInWhen.kt"); + } + + @TestMetadata("whereInClass.kt") + public void testWhereInClass() throws Exception { + runTest("../testData/basic/common/where/whereInClass.kt"); + } + + @TestMetadata("whereInFunction.kt") + public void testWhereInFunction() throws Exception { + runTest("../testData/basic/common/where/whereInFunction.kt"); + } + } } @RunWith(JUnit3RunnerWithInners.class) diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java index 52c5ad3405f1..27711eb34ce1 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java @@ -3168,6 +3168,11 @@ public abstract class K2JvmBasicCompletionTestGenerated extends AbstractK2JvmBas runTest("../completion/testData/basic/common/SuperMembers4.kt"); } + @TestMetadata("SuperWithQualifier.kt") + public void testSuperWithQualifier() throws Exception { + runTest("../completion/testData/basic/common/SuperWithQualifier.kt"); + } + @TestMetadata("SuspendCanBePrefixSelectedInParameterTypeCompletion.kt") public void testSuspendCanBePrefixSelectedInParameterTypeCompletion() throws Exception { runTest("../completion/testData/basic/common/SuspendCanBePrefixSelectedInParameterTypeCompletion.kt"); @@ -3362,11 +3367,86 @@ public abstract class K2JvmBasicCompletionTestGenerated extends AbstractK2JvmBas @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../completion/testData/basic/common/when") - public static class When extends AbstractHighLevelJvmBasicCompletionTest { + public static class When extends AbstractK2JvmBasicCompletionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("enumInEmptyWhen.kt") + public void testEnumInEmptyWhen() throws Exception { + runTest("../completion/testData/basic/common/when/enumInEmptyWhen.kt"); + } + + @TestMetadata("enumInWhen.kt") + public void testEnumInWhen() throws Exception { + runTest("../completion/testData/basic/common/when/enumInWhen.kt"); + } + + @TestMetadata("enumInWhenWithOtherConditions.kt") + public void testEnumInWhenWithOtherConditions() throws Exception { + runTest("../completion/testData/basic/common/when/enumInWhenWithOtherConditions.kt"); + } + + @TestMetadata("enumInWhenWithPackage.kt") + public void testEnumInWhenWithPackage() throws Exception { + runTest("../completion/testData/basic/common/when/enumInWhenWithPackage.kt"); + } + + @TestMetadata("nestedSealedClassInWhen.kt") + public void testNestedSealedClassInWhen() throws Exception { + runTest("../completion/testData/basic/common/when/nestedSealedClassInWhen.kt"); + } + + @TestMetadata("nestedSealedClassInWhenWithPackage.kt") + public void testNestedSealedClassInWhenWithPackage() throws Exception { + runTest("../completion/testData/basic/common/when/nestedSealedClassInWhenWithPackage.kt"); + } + + @TestMetadata("nonSealedClassInWhen.kt") + public void testNonSealedClassInWhen() throws Exception { + runTest("../completion/testData/basic/common/when/nonSealedClassInWhen.kt"); + } + + @TestMetadata("nonSealedClassWithTypeArgs.kt") + public void testNonSealedClassWithTypeArgs() throws Exception { + runTest("../completion/testData/basic/common/when/nonSealedClassWithTypeArgs.kt"); + } + + @TestMetadata("nullableEnumInWhen.kt") + public void testNullableEnumInWhen() throws Exception { + runTest("../completion/testData/basic/common/when/nullableEnumInWhen.kt"); + } + + @TestMetadata("nullableSealedClassInWhen.kt") + public void testNullableSealedClassInWhen() throws Exception { + runTest("../completion/testData/basic/common/when/nullableSealedClassInWhen.kt"); + } + + @TestMetadata("sealedClassInWhen.kt") + public void testSealedClassInWhen() throws Exception { + runTest("../completion/testData/basic/common/when/sealedClassInWhen.kt"); + } + + @TestMetadata("sealedClassInWhenWithOtherConditions.kt") + public void testSealedClassInWhenWithOtherConditions() throws Exception { + runTest("../completion/testData/basic/common/when/sealedClassInWhenWithOtherConditions.kt"); + } + + @TestMetadata("sealedClassWithAbstractInheritorsInWhen.kt") + public void testSealedClassWithAbstractInheritorsInWhen() throws Exception { + runTest("../completion/testData/basic/common/when/sealedClassWithAbstractInheritorsInWhen.kt"); + } + + @TestMetadata("sealedClassWithTypeArgs.kt") + public void testSealedClassWithTypeArgs() throws Exception { + runTest("../completion/testData/basic/common/when/sealedClassWithTypeArgs.kt"); + } + + @TestMetadata("sealedInterfaceInWhen.kt") + public void testSealedInterfaceInWhen() throws Exception { + runTest("../completion/testData/basic/common/when/sealedInterfaceInWhen.kt"); + } + @TestMetadata("smartCast.kt") public void testSmartCast() throws Exception { runTest("../completion/testData/basic/common/when/smartCast.kt"); @@ -3382,6 +3462,29 @@ public abstract class K2JvmBasicCompletionTestGenerated extends AbstractK2JvmBas runTest("../completion/testData/basic/common/when/smartCast3.kt"); } } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../completion/testData/basic/common/where") + public static class Where extends AbstractK2JvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("noCompletionAfterDotInWhen.kt") + public void testNoCompletionAfterDotInWhen() throws Exception { + runTest("../completion/testData/basic/common/where/noCompletionAfterDotInWhen.kt"); + } + + @TestMetadata("whereInClass.kt") + public void testWhereInClass() throws Exception { + runTest("../completion/testData/basic/common/where/whereInClass.kt"); + } + + @TestMetadata("whereInFunction.kt") + public void testWhereInFunction() throws Exception { + runTest("../completion/testData/basic/common/where/whereInFunction.kt"); + } + } } @RunWith(JUnit3RunnerWithInners.class) From 20249c9c8f7b69955275086e5ba51a870552404f Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Fri, 30 Jun 2023 14:49:17 +0300 Subject: [PATCH 065/165] [kotlin] K2: fix missing completion suggestions - members of enum aliases ^KTIJ-23719 Fixed GitOrigin-RevId: 45834a9afd77497987412dd03a07a65dee90accd --- .../FirCallableCompletionContributor.kt | 4 ++-- .../helpers/CallableMetadataProvider.kt | 4 ++-- .../k2/contributors/helpers/symbolUtils.kt | 19 +++++++++++++++---- .../EnumItemsThroughChainedTypeAlias.kt | 4 +++- .../common/EnumItemsThroughSingleTypeAlias.kt | 4 +++- .../ReferenceThroughChainedTypeAlias.kt | 18 ++++++++++++++++++ .../K1JSBasicCompletionTestGenerated.java | 5 +++++ .../K1JvmBasicCompletionTestGenerated.java | 5 +++++ .../K2JvmBasicCompletionTestGenerated.java | 5 +++++ 9 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 plugins/kotlin/completion/testData/basic/common/ReferenceThroughChainedTypeAlias.kt diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirCallableCompletionContributor.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirCallableCompletionContributor.kt index 198a45b0030c..ea659aa15209 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirCallableCompletionContributor.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirCallableCompletionContributor.kt @@ -251,7 +251,7 @@ internal open class FirCallableCompletionContributor( ): Sequence { explicitReceiver as KtExpression - val symbol = explicitReceiver.reference()?.resolveToSymbol() + val symbol = explicitReceiver.reference()?.resolveToExpandedSymbol() return when { symbol is KtPackageSymbol -> collectDotCompletionForPackageReceiver(symbol, visibilityChecker, sessionParameters) @@ -649,7 +649,7 @@ internal class FirCallableReferenceCompletionContributor( ): Sequence { explicitReceiver as KtExpression - return when (val symbol = explicitReceiver.reference()?.resolveToSymbol()) { + return when (val symbol = explicitReceiver.reference()?.resolveToExpandedSymbol()) { is KtPackageSymbol -> emptySequence() is KtNamedClassOrObjectSymbol -> sequence { val type = symbol.buildSelfClassType() diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/helpers/CallableMetadataProvider.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/helpers/CallableMetadataProvider.kt index 796c400addb5..26f69be25317 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/helpers/CallableMetadataProvider.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/helpers/CallableMetadataProvider.kt @@ -177,8 +177,8 @@ internal object CallableMetadataProvider { val callableReferenceExpression = explicitReceiver.getParentOfType(strict = true) ?: return null if (callableReferenceExpression.lhs != explicitReceiver) return null val symbol = when (explicitReceiver) { - is KtDotQualifiedExpression -> explicitReceiver.selectorExpression?.mainReference?.resolveToSymbol() - is KtNameReferenceExpression -> explicitReceiver.mainReference.resolveToSymbol() + is KtDotQualifiedExpression -> explicitReceiver.selectorExpression?.mainReference?.resolveToExpandedSymbol() + is KtNameReferenceExpression -> explicitReceiver.mainReference.resolveToExpandedSymbol() else -> return null } if (symbol !is KtClassLikeSymbol) return null diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/helpers/symbolUtils.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/helpers/symbolUtils.kt index 7a8afb322978..9014a9ef1807 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/helpers/symbolUtils.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/helpers/symbolUtils.kt @@ -4,17 +4,22 @@ package org.jetbrains.kotlin.idea.completion.contributors.helpers import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.components.KtScopeKind +import org.jetbrains.kotlin.analysis.api.components.KtScopeWithKind import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion -import org.jetbrains.kotlin.analysis.api.components.KtScopeWithKind import org.jetbrains.kotlin.analysis.api.signatures.KtCallableSignature import org.jetbrains.kotlin.analysis.api.symbols.KtClassifierSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPackageSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtTypeAliasSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers import org.jetbrains.kotlin.idea.references.KtReference +/** + * Resolves [reference] to symbol and returns static scope for the obtained symbol. Note that if the symbol is [KtTypeAliasSymbol], + * `null` is returned. See KT-34281 for more details. + */ context(KtAnalysisSession) internal fun getStaticScopes(reference: KtReference): List { val scopeIndex = CompletionSymbolOrigin.SCOPE_OUTSIDE_TOWER_INDEX @@ -28,10 +33,16 @@ internal fun getStaticScopes(reference: KtReference): List { } } +context(KtAnalysisSession) +internal fun KtReference.resolveToExpandedSymbol(): KtSymbol? = when (val symbol = resolveToSymbol()) { + is KtTypeAliasSymbol -> symbol.expandedType.expandedClassSymbol + else -> symbol +} + internal data class KtClassifierSymbolWithContainingScopeKind( private val _symbol: KtClassifierSymbol, val scopeKind: KtScopeKind -): KtLifetimeOwner { +) : KtLifetimeOwner { override val token: KtLifetimeToken get() = _symbol.token val symbol: KtClassifierSymbol get() = withValidityAssertion { _symbol } @@ -40,7 +51,7 @@ internal data class KtClassifierSymbolWithContainingScopeKind( internal data class KtCallableSignatureWithContainingScopeKind( private val _signature: KtCallableSignature<*>, val scopeKind: KtScopeKind -): KtLifetimeOwner { +) : KtLifetimeOwner { override val token: KtLifetimeToken get() = _signature.token val signature: KtCallableSignature<*> get() = withValidityAssertion { _signature } @@ -49,7 +60,7 @@ internal data class KtCallableSignatureWithContainingScopeKind( internal data class KtSymbolWithOrigin( private val _symbol: KtSymbol, val origin: CompletionSymbolOrigin, -): KtLifetimeOwner { +) : KtLifetimeOwner { override val token: KtLifetimeToken get() = _symbol.token val symbol: KtSymbol get() = withValidityAssertion { _symbol } diff --git a/plugins/kotlin/completion/testData/basic/common/EnumItemsThroughChainedTypeAlias.kt b/plugins/kotlin/completion/testData/basic/common/EnumItemsThroughChainedTypeAlias.kt index deab54e74c15..d6b1b6aed569 100644 --- a/plugins/kotlin/completion/testData/basic/common/EnumItemsThroughChainedTypeAlias.kt +++ b/plugins/kotlin/completion/testData/basic/common/EnumItemsThroughChainedTypeAlias.kt @@ -1,6 +1,8 @@ +// FIR_COMPARISON +// FIR_IDENTICAL enum class A { ONE; - class B // Not allowed to resolve through typealiases + class B // Not allowed to resolve through typealiases, see KT-34281 } typealias AA = A diff --git a/plugins/kotlin/completion/testData/basic/common/EnumItemsThroughSingleTypeAlias.kt b/plugins/kotlin/completion/testData/basic/common/EnumItemsThroughSingleTypeAlias.kt index aa6f21eb38be..b02fda4cae17 100644 --- a/plugins/kotlin/completion/testData/basic/common/EnumItemsThroughSingleTypeAlias.kt +++ b/plugins/kotlin/completion/testData/basic/common/EnumItemsThroughSingleTypeAlias.kt @@ -1,6 +1,8 @@ +// FIR_COMPARISON +// FIR_IDENTICAL enum class A { ONE; - class B // Not allowed to resolve through typealiases + class B // Not allowed to resolve through typealiases, see KT-34281 } typealias AA = A diff --git a/plugins/kotlin/completion/testData/basic/common/ReferenceThroughChainedTypeAlias.kt b/plugins/kotlin/completion/testData/basic/common/ReferenceThroughChainedTypeAlias.kt new file mode 100644 index 000000000000..e372cbb78b95 --- /dev/null +++ b/plugins/kotlin/completion/testData/basic/common/ReferenceThroughChainedTypeAlias.kt @@ -0,0 +1,18 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +// IGNORE_FE10 + +class A(val xxx: Int) { + class Nested +} + +typealias AA = A +typealias AAA = AA + +fun usage() { + AAA:: +} + +// EXIST: xxx +// ABSENT: Nested +/* Access to nested classes through typealias isn't supported currently, see KT-34281 */ \ No newline at end of file diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java index 002ac4018d39..8d07a2e1f039 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java @@ -3118,6 +3118,11 @@ public abstract class K1JSBasicCompletionTestGenerated extends AbstractK1JSBasic runTest("../testData/basic/common/RecieverMembersFromExtFun.kt"); } + @TestMetadata("ReferenceThroughChainedTypeAlias.kt") + public void testReferenceThroughChainedTypeAlias() throws Exception { + runTest("../testData/basic/common/ReferenceThroughChainedTypeAlias.kt"); + } + @TestMetadata("SecondTypeArg.kt") public void testSecondTypeArg() throws Exception { runTest("../testData/basic/common/SecondTypeArg.kt"); diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java index 394179491101..66aa0c9940bc 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java @@ -3118,6 +3118,11 @@ public abstract class K1JvmBasicCompletionTestGenerated extends AbstractK1JvmBas runTest("../testData/basic/common/RecieverMembersFromExtFun.kt"); } + @TestMetadata("ReferenceThroughChainedTypeAlias.kt") + public void testReferenceThroughChainedTypeAlias() throws Exception { + runTest("../testData/basic/common/ReferenceThroughChainedTypeAlias.kt"); + } + @TestMetadata("SecondTypeArg.kt") public void testSecondTypeArg() throws Exception { runTest("../testData/basic/common/SecondTypeArg.kt"); diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java index 27711eb34ce1..a70549997007 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java @@ -3118,6 +3118,11 @@ public abstract class K2JvmBasicCompletionTestGenerated extends AbstractK2JvmBas runTest("../completion/testData/basic/common/RecieverMembersFromExtFun.kt"); } + @TestMetadata("ReferenceThroughChainedTypeAlias.kt") + public void testReferenceThroughChainedTypeAlias() throws Exception { + runTest("../completion/testData/basic/common/ReferenceThroughChainedTypeAlias.kt"); + } + @TestMetadata("SecondTypeArg.kt") public void testSecondTypeArg() throws Exception { runTest("../completion/testData/basic/common/SecondTypeArg.kt"); From 6919feda8c499cedf4e8a084cb80e56178080150 Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Fri, 30 Jun 2023 15:12:50 +0300 Subject: [PATCH 066/165] [kotlin] K2: don't suggest branch that is already processed with type alias in when condition ^KTIJ-26093 Fixed GitOrigin-RevId: 47256805e0935d2b87d8c656156c2202a4a8a881 --- .../FirWhenWithSubjectConditionContributor.kt | 3 ++- .../testData/basic/common/when/typealias.kt | 17 +++++++++++++++++ .../test/K1JSBasicCompletionTestGenerated.java | 5 +++++ .../test/K1JvmBasicCompletionTestGenerated.java | 5 +++++ .../K2JvmBasicCompletionTestGenerated.java | 5 +++++ 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 plugins/kotlin/completion/testData/basic/common/when/typealias.kt diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirWhenWithSubjectConditionContributor.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirWhenWithSubjectConditionContributor.kt index 36ce16017310..f85f7fe772c7 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirWhenWithSubjectConditionContributor.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirWhenWithSubjectConditionContributor.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.completion.contributors.helpers.FirClassifierPr import org.jetbrains.kotlin.idea.completion.contributors.helpers.addTypeArguments import org.jetbrains.kotlin.idea.completion.contributors.helpers.createStarTypeArgumentsList import org.jetbrains.kotlin.idea.completion.contributors.helpers.insertString +import org.jetbrains.kotlin.idea.completion.contributors.helpers.resolveToExpandedSymbol import org.jetbrains.kotlin.idea.completion.createKeywordElement import org.jetbrains.kotlin.idea.completion.lookups.KotlinLookupObject import org.jetbrains.kotlin.idea.completion.weighers.WeighingContext @@ -181,7 +182,7 @@ internal class FirWhenWithSubjectConditionContributor( is KtWhenConditionIsPattern -> (condition.typeReference?.typeElement as? KtUserType)?.referenceExpression?.reference() else -> null } - val resolvesTo = reference?.resolveToSymbol() as? KtNamedClassOrObjectSymbol + val resolvesTo = reference?.resolveToExpandedSymbol() as? KtNamedClassOrObjectSymbol resolvesTo?.classIdIfNonLocal } diff --git a/plugins/kotlin/completion/testData/basic/common/when/typealias.kt b/plugins/kotlin/completion/testData/basic/common/when/typealias.kt new file mode 100644 index 000000000000..e1417f9386ff --- /dev/null +++ b/plugins/kotlin/completion/testData/basic/common/when/typealias.kt @@ -0,0 +1,17 @@ +// IGNORE_FE10 +// FIR_COMPARISON +// FIR_IDENTICAL +sealed class SS + +class AA: SS() +class BB: SS() + +typealias TT = AA + +fun test(ss: SS) = when (ss) { + is TT -> {} + +} + +// EXIST: is BB +// ABSENT: is AA \ No newline at end of file diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java index 8d07a2e1f039..c802d86825cb 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JSBasicCompletionTestGenerated.java @@ -3466,6 +3466,11 @@ public abstract class K1JSBasicCompletionTestGenerated extends AbstractK1JSBasic public void testSmartCast3() throws Exception { runTest("../testData/basic/common/when/smartCast3.kt"); } + + @TestMetadata("typealias.kt") + public void testTypealias() throws Exception { + runTest("../testData/basic/common/when/typealias.kt"); + } } @RunWith(JUnit3RunnerWithInners.class) diff --git a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java index 66aa0c9940bc..32c1a3f00f03 100644 --- a/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/completion/tests-k1/test/org/jetbrains/kotlin/idea/completion/test/K1JvmBasicCompletionTestGenerated.java @@ -3466,6 +3466,11 @@ public abstract class K1JvmBasicCompletionTestGenerated extends AbstractK1JvmBas public void testSmartCast3() throws Exception { runTest("../testData/basic/common/when/smartCast3.kt"); } + + @TestMetadata("typealias.kt") + public void testTypealias() throws Exception { + runTest("../testData/basic/common/when/typealias.kt"); + } } @RunWith(JUnit3RunnerWithInners.class) diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java index a70549997007..d2207b833960 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/K2JvmBasicCompletionTestGenerated.java @@ -3466,6 +3466,11 @@ public abstract class K2JvmBasicCompletionTestGenerated extends AbstractK2JvmBas public void testSmartCast3() throws Exception { runTest("../completion/testData/basic/common/when/smartCast3.kt"); } + + @TestMetadata("typealias.kt") + public void testTypealias() throws Exception { + runTest("../completion/testData/basic/common/when/typealias.kt"); + } } @RunWith(JUnit3RunnerWithInners.class) From 2b2bd92221ab2f567ee8325c5856900911031d90 Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Thu, 6 Jul 2023 16:02:45 +0300 Subject: [PATCH 067/165] [kotlin] K2: fix missing completion suggestions: type aliases ^KTIJ-24486 Fixed GitOrigin-RevId: c10d8ad818158573a00665b31ea6c782c524e175 --- .../api/utils/KtSymbolFromIndexProvider.kt | 96 +++++++++---------- ...ParameterNameAndTypeForNotImportedAlias.kt | 1 + .../multifile/TypeAliases/TypeAliases.kt | 2 + .../multifile/NotImportedTypeAlias-1.kt | 2 + .../multifile/NotImportedTypeAlias.kt.after | 2 + .../idea/quickfix/fixes/ImportQuickFix.kt | 14 +-- .../autoImports/typeAliasImport.after.kt | 2 - .../typeAliasImport.before.Main.kt | 2 - 8 files changed, 61 insertions(+), 60 deletions(-) diff --git a/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/KtSymbolFromIndexProvider.kt b/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/KtSymbolFromIndexProvider.kt index 46b807266f71..f5144e18865b 100644 --- a/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/KtSymbolFromIndexProvider.kt +++ b/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/KtSymbolFromIndexProvider.kt @@ -10,11 +10,7 @@ import com.intellij.psi.search.PsiShortNamesCache import com.intellij.util.SmartList import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.analyze -import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol -import org.jetbrains.kotlin.analysis.api.symbols.getSymbolOfTypeSafe -import org.jetbrains.kotlin.analysis.api.symbols.receiverType +import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability @@ -22,56 +18,58 @@ import org.jetbrains.kotlin.idea.base.psi.isExpectDeclaration import org.jetbrains.kotlin.idea.stubindex.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.isCommon -import org.jetbrains.kotlin.psi.KtCallableDeclaration -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.utils.yieldIfNotNull class KtSymbolFromIndexProvider private constructor(private val project: Project, private val scope: GlobalSearchScope) { context(KtAnalysisSession) fun getKotlinClassesByName( name: Name, - psiFilter: (KtClassOrObject) -> Boolean = { true }, - ): Sequence { + psiFilter: (KtClassLikeDeclaration) -> Boolean = { true }, + ): Sequence { val isCommon = useSiteModule.platform.isCommon() - val values = KotlinClassShortNameIndex.getAllElements( - name.asString(), - project, - scope - ) { - (isCommon || !it.isExpectDeclaration()) && psiFilter(it) - } - return sequence { - for (value in values) { - value.getNamedClassOrObjectSymbol()?.let { yield(it) } - } - yieldAll( - getResolveExtensionScopeWithTopLevelDeclarations().getClassifierSymbols(name).filterIsInstance() - ) - } + + val valueFilter: (KtClassLikeDeclaration) -> Boolean = { (isCommon || !it.isExpectDeclaration()) && psiFilter(it) } + val resolveExtensionScope = getResolveExtensionScopeWithTopLevelDeclarations() + + return getClassLikeSymbols( + classDeclarations = KotlinClassShortNameIndex.getAllElements(name.asString(), project, scope, valueFilter), + typeAliasDeclarations = KotlinTypeAliasShortNameIndex.getAllElements(name.asString(), project, scope, valueFilter), + declarationsFromExtension = resolveExtensionScope.getClassifierSymbols(name).filterIsInstance(), + ) } context(KtAnalysisSession) fun getKotlinClassesByNameFilter( nameFilter: (Name) -> Boolean, - psiFilter: (KtClassOrObject) -> Boolean = { true }, - ): Sequence { + psiFilter: (KtClassLikeDeclaration) -> Boolean = { true }, + ): Sequence { val isCommon = useSiteModule.platform.isCommon() - val values = KotlinFullClassNameIndex.getAllElements( - project, - scope, - keyFilter = { nameFilter(getShortName(it)) }, - valueFilter = { (isCommon || !it.isExpectDeclaration()) && psiFilter(it) } + + val keyFilter: (String) -> Boolean = { nameFilter(getShortName(it)) } + val valueFilter: (KtClassLikeDeclaration) -> Boolean = { (isCommon || !it.isExpectDeclaration()) && psiFilter(it) } + val resolveExtensionScope = getResolveExtensionScopeWithTopLevelDeclarations() + + return getClassLikeSymbols( + classDeclarations = KotlinFullClassNameIndex.getAllElements(project, scope, keyFilter, valueFilter), + typeAliasDeclarations = KotlinTypeAliasShortNameIndex.getAllElements(project, scope, keyFilter, valueFilter), + declarationsFromExtension = resolveExtensionScope.getClassifierSymbols(nameFilter).filterIsInstance(), ) - return sequence { - for (ktClassOrObject in values) { - ktClassOrObject.getNamedClassOrObjectSymbol()?.let { yield(it) } - } - yieldAll( - getResolveExtensionScopeWithTopLevelDeclarations().getClassifierSymbols(nameFilter).filterIsInstance() - ) + } + + context(KtAnalysisSession) + private fun getClassLikeSymbols( + classDeclarations: List, + typeAliasDeclarations: List, + declarationsFromExtension: Sequence + ): Sequence = sequence { + for (ktClassOrObject in classDeclarations) { + yieldIfNotNull(ktClassOrObject.getNamedClassOrObjectSymbol()) } + for (typeAlias in typeAliasDeclarations) { + yield(typeAlias.getTypeAliasSymbol()) + } + yieldAll(declarationsFromExtension) } context(KtAnalysisSession) @@ -130,7 +128,7 @@ class KtSymbolFromIndexProvider private constructor(private val project: Project return sequence { for (callableDeclaration in values) { - callableDeclaration.getSymbolOfTypeSafe()?.let { yield(it) } + yieldIfNotNull(callableDeclaration.getSymbolOfTypeSafe()) } yieldAll( getResolveExtensionScopeWithTopLevelDeclarations().getCallableSymbols(name) @@ -174,7 +172,7 @@ class KtSymbolFromIndexProvider private constructor(private val project: Project return sequence { for (callableDeclaration in values) { - callableDeclaration.getSymbolOfTypeSafe()?.let { yield(it) } + yieldIfNotNull(callableDeclaration.getSymbolOfTypeSafe()) } yieldAll( getResolveExtensionScopeWithTopLevelDeclarations().getCallableSymbols(nameFilter).filter { !it.isExtension } @@ -197,10 +195,10 @@ class KtSymbolFromIndexProvider private constructor(private val project: Project return sequence { for (extension in values) { - extension.getSymbolOfTypeSafe()?.let { yield(it) } + yieldIfNotNull(extension.getSymbolOfTypeSafe()) } - val extensionScope = getResolveExtensionScopeWithTopLevelDeclarations() - yieldAll(extensionScope.getCallableSymbols(name).filterExtensionsByReceiverTypes(receiverTypes)) + val resolveExtensionScope = getResolveExtensionScopeWithTopLevelDeclarations() + yieldAll(resolveExtensionScope.getCallableSymbols(name).filterExtensionsByReceiverTypes(receiverTypes)) } } @@ -223,10 +221,10 @@ class KtSymbolFromIndexProvider private constructor(private val project: Project return sequence { for (extension in values) { - extension.getSymbolOfTypeSafe()?.let { yield(it) } + yieldIfNotNull(extension.getSymbolOfTypeSafe()) } - val extensionScope = getResolveExtensionScopeWithTopLevelDeclarations() - yieldAll(extensionScope.getCallableSymbols(nameFilter).filterExtensionsByReceiverTypes(receiverTypes)) + val resolveExtensionScope = getResolveExtensionScopeWithTopLevelDeclarations() + yieldAll(resolveExtensionScope.getCallableSymbols(nameFilter).filterExtensionsByReceiverTypes(receiverTypes)) } } diff --git a/plugins/kotlin/completion/testData/basic/multifile/ParameterNameAndTypeForNotImportedAlias/ParameterNameAndTypeForNotImportedAlias.kt b/plugins/kotlin/completion/testData/basic/multifile/ParameterNameAndTypeForNotImportedAlias/ParameterNameAndTypeForNotImportedAlias.kt index d489a4a31972..2cf081f93210 100644 --- a/plugins/kotlin/completion/testData/basic/multifile/ParameterNameAndTypeForNotImportedAlias/ParameterNameAndTypeForNotImportedAlias.kt +++ b/plugins/kotlin/completion/testData/basic/multifile/ParameterNameAndTypeForNotImportedAlias/ParameterNameAndTypeForNotImportedAlias.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package test2 fun foo(ali) diff --git a/plugins/kotlin/completion/testData/basic/multifile/TypeAliases/TypeAliases.kt b/plugins/kotlin/completion/testData/basic/multifile/TypeAliases/TypeAliases.kt index 6126cde3cc4d..a904f4b28d08 100644 --- a/plugins/kotlin/completion/testData/basic/multifile/TypeAliases/TypeAliases.kt +++ b/plugins/kotlin/completion/testData/basic/multifile/TypeAliases/TypeAliases.kt @@ -1,3 +1,5 @@ +// FIR_COMPARISON +// FIR_IDENTICAL package test typealias MySameFileAlias = (String) -> Int diff --git a/plugins/kotlin/completion/testData/handlers/multifile/NotImportedTypeAlias-1.kt b/plugins/kotlin/completion/testData/handlers/multifile/NotImportedTypeAlias-1.kt index 2c0eb3156c03..6eb32c93b64d 100644 --- a/plugins/kotlin/completion/testData/handlers/multifile/NotImportedTypeAlias-1.kt +++ b/plugins/kotlin/completion/testData/handlers/multifile/NotImportedTypeAlias-1.kt @@ -1 +1,3 @@ fun foo(): MyAl + +// FIR_COMPARISON \ No newline at end of file diff --git a/plugins/kotlin/completion/testData/handlers/multifile/NotImportedTypeAlias.kt.after b/plugins/kotlin/completion/testData/handlers/multifile/NotImportedTypeAlias.kt.after index a27c3f6b9e53..bfa93bff0e58 100644 --- a/plugins/kotlin/completion/testData/handlers/multifile/NotImportedTypeAlias.kt.after +++ b/plugins/kotlin/completion/testData/handlers/multifile/NotImportedTypeAlias.kt.after @@ -1,3 +1,5 @@ import test.MyAlias fun foo(): MyAlias + +// FIR_COMPARISON \ No newline at end of file diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ImportQuickFix.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ImportQuickFix.kt index 2b7629958e25..5128dfbfcad4 100644 --- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ImportQuickFix.kt +++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ImportQuickFix.kt @@ -338,7 +338,7 @@ class ImportQuickFix( val firFile = element.containingKtFile.getFileSymbol() val isVisible: (KtSymbol) -> Boolean = - { it !is KtSymbolWithVisibility || isVisible(it, firFile, null, element) } + { it !is KtSymbolWithVisibility || isVisible(it, firFile, receiverExpression = null, element) } val candidateSymbols = buildList { addAll(collectCallableCandidates(indexProvider, element, unresolvedName, isVisible)) @@ -358,8 +358,8 @@ class ImportQuickFix( val firFile = element.containingKtFile.getFileSymbol() val unresolvedName = element.typeName ?: return null - val isVisible: (KtNamedClassOrObjectSymbol) -> Boolean = - { isVisible(it, firFile, null, element) } + val isVisible: (KtClassLikeSymbol) -> Boolean = + { it is KtSymbolWithVisibility && isVisible(it, firFile, receiverExpression = null, element) } return createImportFix(element, collectTypesCandidates(indexProvider, unresolvedName, isVisible)) } @@ -399,8 +399,8 @@ class ImportQuickFix( private fun collectTypesCandidates( indexProvider: KtSymbolFromIndexProvider, unresolvedName: Name, - isVisible: (KtNamedClassOrObjectSymbol) -> Boolean - ): List { + isVisible: (KtClassLikeSymbol) -> Boolean + ): List { val classesCandidates = indexProvider.getKotlinClassesByName(unresolvedName) { it.canBeImported() } + indexProvider.getJavaClassesByName(unresolvedName) { it.canBeImported() } @@ -424,8 +424,8 @@ private fun KtDeclaration.canBeImported(): Boolean { return when (this) { is KtProperty -> isTopLevel || containingClassOrObject is KtObjectDeclaration is KtNamedFunction -> isTopLevel || containingClassOrObject is KtObjectDeclaration - is KtClassOrObject -> - getClassId() != null && parentsOfType(withSelf = true).none { it.hasModifier(KtTokens.INNER_KEYWORD) } + is KtClassLikeDeclaration -> + getClassId() != null && parentsOfType(withSelf = true).none { it.hasModifier(KtTokens.INNER_KEYWORD) } else -> false } diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/typeAliasImport.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/typeAliasImport.after.kt index 108e60256c18..c1868c121b1d 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/typeAliasImport.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/typeAliasImport.after.kt @@ -6,5 +6,3 @@ import dependency.TestAlias fun test() { val a = TestAlias } - -/* IGNORE_FIR */ \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/typeAliasImport.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/typeAliasImport.before.Main.kt index 726f1bf7a98b..34116ab4525a 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/typeAliasImport.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/typeAliasImport.before.Main.kt @@ -4,5 +4,3 @@ fun test() { val a = TestAlias } - -/* IGNORE_FIR */ \ No newline at end of file From 4fdd9dcfed24d51176f2ad944f9817dd0b2ad5e8 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Mon, 31 Jul 2023 18:39:56 +0200 Subject: [PATCH 068/165] [kotlin] KT-58257 Fix compilation after move of `analyzeInModalWindow` GitOrigin-RevId: d7356a0af08ccc3dd3aad2e7a71b54fce4a87297 --- .../kotlin.base.fir.analysis-api-providers.iml | 1 + .../sessions/CyclicDependenciesSymbolResolutionTest.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/kotlin.base.fir.analysis-api-providers.iml b/plugins/kotlin/base/fir/analysis-api-providers/kotlin.base.fir.analysis-api-providers.iml index 4a0994051955..63e7aed8d843 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/kotlin.base.fir.analysis-api-providers.iml +++ b/plugins/kotlin/base/fir/analysis-api-providers/kotlin.base.fir.analysis-api-providers.iml @@ -45,6 +45,7 @@ + diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/CyclicDependenciesSymbolResolutionTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/CyclicDependenciesSymbolResolutionTest.kt index 8814b5602493..f05c8fe2fd29 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/CyclicDependenciesSymbolResolutionTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/sessions/CyclicDependenciesSymbolResolutionTest.kt @@ -2,7 +2,7 @@ package org.jetbrains.kotlin.idea.fir.analysis.providers.sessions import org.jetbrains.kotlin.analysis.api.KtAnalysisSession -import org.jetbrains.kotlin.analysis.api.analyzeInModalWindow +import org.jetbrains.kotlin.idea.base.analysis.api.utils.analyzeInModalWindow import org.jetbrains.kotlin.analysis.api.calls.successfulFunctionCallOrNull import org.jetbrains.kotlin.analysis.api.calls.symbol import org.jetbrains.kotlin.analysis.api.types.KtType From 081aa36eb110a26124180e9a15d2be5e4c8ba992 Mon Sep 17 00:00:00 2001 From: Bart van Helvert Date: Mon, 31 Jul 2023 18:40:31 +0200 Subject: [PATCH 069/165] [kotlin] Fix K2 bind to element generated test GitOrigin-RevId: c115e405776a4286b231f22b48814d6833cf43f5 --- .../K2BindToElementTestGenerated.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java index 67e34ffdc2fe..ab9ee0c8dafa 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java @@ -175,6 +175,19 @@ public abstract class K2BindToElementTestGenerated extends AbstractK2BindToEleme } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/importReference") + public static class ImportReference extends AbstractK2BindToElementTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("ImportReference.kt") + public void testImportReference() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/propertyTypeReference") public static class PropertyTypeReference extends AbstractK2BindToElementTest { @@ -279,17 +292,4 @@ public abstract class K2BindToElementTestGenerated extends AbstractK2BindToEleme runTest("../../idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt"); } } - - @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/importReference") - public static class ImportReference extends AbstractK2BindToElementTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); - } - - @TestMetadata("ImportReference.kt") - public void testImportReference() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/importReference/ImportReference.kt"); - } - } } From 36a99aaaba76f823ea56278e07a93ed240e2a189 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 1 Aug 2023 11:11:34 +0200 Subject: [PATCH 070/165] [kotlin] convert expression body to block: fix for nullable Nothing (KTIJ-26468) GitOrigin-RevId: c324a1f7246a1ddfa6b8f2e377b0937126c97e7d --- .../idea/k2/intentions/tests/K2IntentionTestGenerated.java | 5 +++++ .../kotlin/idea/codeinsight/utils/ConvertToBlockBodyUtils.kt | 4 ++-- .../kotlin/idea/intentions/K1IntentionTestGenerated.java | 5 +++++ .../intentions/convertToBlockBody/nullableNothing.kt | 1 + .../intentions/convertToBlockBody/nullableNothing.kt.after | 3 +++ 5 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertToBlockBody/nullableNothing.kt create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertToBlockBody/nullableNothing.kt.after diff --git a/plugins/kotlin/code-insight/intentions-k2/tests/test/org/jetbrains/kotlin/idea/k2/intentions/tests/K2IntentionTestGenerated.java b/plugins/kotlin/code-insight/intentions-k2/tests/test/org/jetbrains/kotlin/idea/k2/intentions/tests/K2IntentionTestGenerated.java index 60279ccde550..c9b56312c3b8 100644 --- a/plugins/kotlin/code-insight/intentions-k2/tests/test/org/jetbrains/kotlin/idea/k2/intentions/tests/K2IntentionTestGenerated.java +++ b/plugins/kotlin/code-insight/intentions-k2/tests/test/org/jetbrains/kotlin/idea/k2/intentions/tests/K2IntentionTestGenerated.java @@ -1588,6 +1588,11 @@ public abstract class K2IntentionTestGenerated extends AbstractK2IntentionTest { runTest("../../../idea/tests/testData/intentions/convertToBlockBody/nothingFun.kt"); } + @TestMetadata("nullableNothing.kt") + public void testNullableNothing() throws Exception { + runTest("../../../idea/tests/testData/intentions/convertToBlockBody/nullableNothing.kt"); + } + @TestMetadata("overrideWithPlatformType.kt") public void testOverrideWithPlatformType() throws Exception { runTest("../../../idea/tests/testData/intentions/convertToBlockBody/overrideWithPlatformType.kt"); diff --git a/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/ConvertToBlockBodyUtils.kt b/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/ConvertToBlockBodyUtils.kt index 37f64de0ca8c..d0423f487ef8 100644 --- a/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/ConvertToBlockBodyUtils.kt +++ b/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/ConvertToBlockBodyUtils.kt @@ -46,10 +46,10 @@ object ConvertToBlockBodyUtils { return ConvertToBlockBodyContext( returnTypeIsUnit = returnType.isUnit, - returnTypeIsNothing = returnType.isNothing, + returnTypeIsNothing = returnType.isNothing && !returnType.isMarkedNullable, returnTypeString = returnType.render(position = Variance.OUT_VARIANCE), bodyTypeIsUnit = bodyType.isUnit, - bodyTypeIsNothing = bodyType.isNothing, + bodyTypeIsNothing = bodyType.isNothing && !bodyType.isMarkedNullable, reformat = reformat, shortenReferences = shortenReferences ) diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/K1IntentionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/K1IntentionTestGenerated.java index 291c069f4428..18569435a83c 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/K1IntentionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/K1IntentionTestGenerated.java @@ -8302,6 +8302,11 @@ public abstract class K1IntentionTestGenerated extends AbstractK1IntentionTest { runTest("testData/intentions/convertToBlockBody/nothingFun.kt"); } + @TestMetadata("nullableNothing.kt") + public void testNullableNothing() throws Exception { + runTest("testData/intentions/convertToBlockBody/nullableNothing.kt"); + } + @TestMetadata("overrideWithPlatformType.kt") public void testOverrideWithPlatformType() throws Exception { runTest("testData/intentions/convertToBlockBody/overrideWithPlatformType.kt"); diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertToBlockBody/nullableNothing.kt b/plugins/kotlin/idea/tests/testData/intentions/convertToBlockBody/nullableNothing.kt new file mode 100644 index 000000000000..5b8f2b61a500 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/convertToBlockBody/nullableNothing.kt @@ -0,0 +1 @@ +fun foo() = null \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertToBlockBody/nullableNothing.kt.after b/plugins/kotlin/idea/tests/testData/intentions/convertToBlockBody/nullableNothing.kt.after new file mode 100644 index 000000000000..589152a61248 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/convertToBlockBody/nullableNothing.kt.after @@ -0,0 +1,3 @@ +fun foo(): Nothing? { + return null +} From 8631b689f0bfe35bf185148ec0d3e38f411e4fd9 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Sat, 29 Jul 2023 22:08:02 +0200 Subject: [PATCH 071/165] [kotlin] Do not highlight the entire return statement if it is a complex construction #KTIJ-26413 Fixed GitOrigin-RevId: 46acfe66c618876e472d65cda7f42d5c4724f192 --- ...KotlinHighlightExitPointsHandlerFactory.kt | 59 +++++++++++++++---- .../K2HighlightExitPointsTestGenerated.java | 15 +++++ .../HighlightExitPointsTestGenerated.java | 15 +++++ .../testData/exitPoints/returnIfStatement.kt | 14 +++++ .../testData/exitPoints/returnTryStatement.kt | 20 +++++++ .../exitPoints/returnWhenStatement.kt | 20 +++++++ 6 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/exitPoints/returnIfStatement.kt create mode 100644 plugins/kotlin/idea/tests/testData/exitPoints/returnTryStatement.kt create mode 100644 plugins/kotlin/idea/tests/testData/exitPoints/returnWhenStatement.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt b/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt index 50911325d93e..7be0def69832 100644 --- a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt +++ b/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt @@ -130,7 +130,7 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages if (relevantFunction is KtFunctionLiteral || (relevantFunction is KtNamedFunction && relevantFunction.bodyBlockExpression == null) ) { - val lastStatementStatements = mutableSetOf(relevantFunction) + val lastStatements = mutableSetOf(relevantFunction) relevantFunction.acceptChildren(object : KtVisitorVoid() { override fun visitKtElement(element: KtElement) { ProgressIndicatorProvider.checkCanceled() @@ -140,29 +140,29 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages override fun visitExpression(expression: KtExpression) { when(expression) { is KtBinaryExpression -> { - lastStatementStatements.addIfNotNullAndNotBlock(expression.left) - lastStatementStatements.addIfNotNullAndNotBlock(expression.right) + lastStatements.addIfNotNullAndNotBlock(expression.left) + lastStatements.addIfNotNullAndNotBlock(expression.right) } is KtCallExpression -> { - lastStatementStatements.addIfNotNullAndNotBlock(expression.calleeExpression) + lastStatements.addIfNotNullAndNotBlock(expression.calleeExpression) } - is KtBlockExpression -> lastStatementStatements.addIfNotNullAndNotBlock(expression.lastStatementOrNull()) + is KtBlockExpression -> lastStatements.addIfNotNullAndNotBlock(expression.lastStatementOrNull()) is KtIfExpression -> { - lastStatementStatements.addIfNotNullAndNotBlock(expression.then) - lastStatementStatements.addIfNotNullAndNotBlock(expression.`else`) + lastStatements.addIfNotNullAndNotBlock(expression.then) + lastStatements.addIfNotNullAndNotBlock(expression.`else`) } is KtWhenExpression -> expression.entries.map { it.expression }.forEach { - lastStatementStatements.addIfNotNullAndNotBlock(it) + lastStatements.addIfNotNullAndNotBlock(it) } } super.visitExpression(expression) } }) - if (target !in lastStatementStatements) { + if (target !in lastStatements) { return } - lastStatementStatements + lastStatements } else { emptySet() } @@ -214,7 +214,44 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages private fun visitReturnOrThrow(expression: KtExpression) { if (getRelevantDeclaration(expression) == relevantFunction) { - addOccurrence(expression) + if (expression is KtThrowExpression) { + addOccurrence(expression) + } else { + val returnExpression = expression as KtReturnExpression + when (returnExpression.returnedExpression ) { + is KtIfExpression, is KtWhenExpression, is KtTryExpression -> { + addOccurrence(expression.returnKeyword) + returnExpression.acceptChildren(object : KtVisitorVoid() { + override fun visitKtElement(element: KtElement) { + ProgressIndicatorProvider.checkCanceled() + element.acceptChildren(this) + } + + override fun visitExpression(expression: KtExpression) { + when(expression) { + is KtBlockExpression -> expression.lastStatementOrNull()?.let { visitExpression(it) } + is KtIfExpression -> { + expression.then?.let { visitExpression(it) } + expression.`else`?.let { visitExpression(it) } + } + is KtTryExpression -> { + expression.tryBlock.lastStatementOrNull()?.let { visitExpression(it) } + expression.catchClauses.forEach { catchClause -> + catchClause.catchBody?.let { visitExpression(it) } + } + } + is KtWhenExpression -> + expression.entries.forEach { whenEntry -> + whenEntry.expression?.let { visitExpression(it) } + } + else -> addOccurrence(expression) + } + } + }) + } + else -> addOccurrence(expression) + } + } } } diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java b/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java index f0b03302a235..c679b22e1d0b 100644 --- a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java +++ b/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java @@ -188,6 +188,21 @@ public class K2HighlightExitPointsTestGenerated extends AbstractK2HighlightExitP runTest("../idea/tests/testData/exitPoints/notReturnedLabeledExpression.kt"); } + @TestMetadata("returnIfStatement.kt") + public void testReturnIfStatement() throws Exception { + runTest("../idea/tests/testData/exitPoints/returnIfStatement.kt"); + } + + @TestMetadata("returnTryStatement.kt") + public void testReturnTryStatement() throws Exception { + runTest("../idea/tests/testData/exitPoints/returnTryStatement.kt"); + } + + @TestMetadata("returnWhenStatement.kt") + public void testReturnWhenStatement() throws Exception { + runTest("../idea/tests/testData/exitPoints/returnWhenStatement.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("../idea/tests/testData/exitPoints/simple.kt"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java index a98be9a8c8bd..a7c2adab290a 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java @@ -188,6 +188,21 @@ public class HighlightExitPointsTestGenerated extends AbstractHighlightExitPoint runTest("testData/exitPoints/notReturnedLabeledExpression.kt"); } + @TestMetadata("returnIfStatement.kt") + public void testReturnIfStatement() throws Exception { + runTest("testData/exitPoints/returnIfStatement.kt"); + } + + @TestMetadata("returnTryStatement.kt") + public void testReturnTryStatement() throws Exception { + runTest("testData/exitPoints/returnTryStatement.kt"); + } + + @TestMetadata("returnWhenStatement.kt") + public void testReturnWhenStatement() throws Exception { + runTest("testData/exitPoints/returnWhenStatement.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("testData/exitPoints/simple.kt"); diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/returnIfStatement.kt b/plugins/kotlin/idea/tests/testData/exitPoints/returnIfStatement.kt new file mode 100644 index 000000000000..db37118452c3 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/exitPoints/returnIfStatement.kt @@ -0,0 +1,14 @@ +fun f(a: Int): Int { + return if (a < 5) { + val q = 1 + 1 + } + else { + 2 + } +} + +//HIGHLIGHTED: return +//HIGHLIGHTED: f +//HIGHLIGHTED: 1 +//HIGHLIGHTED: 2 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/returnTryStatement.kt b/plugins/kotlin/idea/tests/testData/exitPoints/returnTryStatement.kt new file mode 100644 index 000000000000..c76f7eba1c3e --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/exitPoints/returnTryStatement.kt @@ -0,0 +1,20 @@ +fun yy(): Int = 5 + +fun f(a: Int): Int { + return try { + val q = a * a + q + } catch (e: Exception) { + 0 + } catch (e: Throwable) { + -1 + } finally { + println() + } +} + +//HIGHLIGHTED: return +//HIGHLIGHTED: f +//HIGHLIGHTED: 0 +//HIGHLIGHTED: q +//HIGHLIGHTED: -1 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/returnWhenStatement.kt b/plugins/kotlin/idea/tests/testData/exitPoints/returnWhenStatement.kt new file mode 100644 index 000000000000..e4c68ef8be8d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/exitPoints/returnWhenStatement.kt @@ -0,0 +1,20 @@ +fun yy(): Int = 5 + +fun f(a: Int): Int { + return when { + a < 0 -> { + val q = 1 + 2 * 2 + } + a > 0 -> { + 2 * (2 + 2) + } + else -> yy() + } +} + +//HIGHLIGHTED: return +//HIGHLIGHTED: f +//HIGHLIGHTED: 2 * (2 + 2) +//HIGHLIGHTED: 2 * 2 +//HIGHLIGHTED: yy() \ No newline at end of file From d94e00e8a3874035b99425718b1298b0c532f1f4 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Sat, 29 Jul 2023 22:56:57 +0200 Subject: [PATCH 072/165] [kotlin] Highlight exit points from caret on a `fun` keyword #KTIJ-26412 GitOrigin-RevId: c3f5dfa2c62a89b9d00720673bc40674ac0efdea --- ...KotlinHighlightExitPointsHandlerFactory.kt | 92 +++++++++---------- .../AbstractUsageHighlightingTest.kt | 19 ++-- .../UsageHighlightingTestGenerated.java | 5 + .../functionNameIdentifier.kt | 7 ++ 4 files changed, 71 insertions(+), 52 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/usageHighlighter/functionNameIdentifier.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt b/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt index 7be0def69832..855643fa8e44 100644 --- a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt +++ b/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.idea.base.highlighting import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerBase import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerFactoryBase +import com.intellij.lang.ASTNode import com.intellij.openapi.editor.Editor import com.intellij.openapi.progress.ProgressIndicatorProvider import com.intellij.psi.PsiElement @@ -22,7 +23,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsagesHandlerFactoryBase() { private fun getOnReturnOrThrowUsageHandler(editor: Editor, file: PsiFile, target: PsiElement): HighlightUsagesHandlerBase<*>? { val expression = when (val parent = target.parent) { - is KtNamedFunction -> parent + is KtNamedFunction -> parent.takeIf { (target as? ASTNode)?.elementType == KtTokens.FUN_KEYWORD } is KtPropertyAccessor -> parent is KtReturnExpression, is KtThrowExpression -> parent is KtLabelReferenceExpression -> @@ -31,7 +32,7 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages )?.takeUnless { it is KtFunction } else -> null } as? KtExpression ?: return null - return OnExitUsagesHandler(editor, file, expression) + return OnExitUsagesHandler(editor, file, expression, false) } private fun getOnLambdaCallUsageHandler(editor: Editor, file: PsiFile, target: PsiElement): HighlightUsagesHandlerBase<*>? { @@ -42,7 +43,7 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages } val literal = (target.parent as? KtNameReferenceExpression).asFunctionLiteral() ?: return null - return OnExitUsagesHandler(editor, file, literal, highlightReferences = true) + return OnExitUsagesHandler(editor, file, literal, true) } private fun KtNameReferenceExpression?.asFunctionLiteral(): KtFunctionLiteral? { @@ -87,7 +88,7 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages return expression.parents.filterIsInstance().firstOrNull() } - private inner class OnExitUsagesHandler(editor: Editor, file: PsiFile, val target: KtExpression, val highlightReferences: Boolean = false) : + private inner class OnExitUsagesHandler(editor: Editor, file: PsiFile, val target: KtExpression, val highlightReferences: Boolean) : HighlightUsagesHandlerBase(editor, file) { override fun getTargets() = listOf(target) @@ -108,7 +109,7 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages var targetOccurrenceAdded = false if (target is KtReturnExpression || target is KtThrowExpression || target is KtNamedFunction || target is KtPropertyAccessor) { when (relevantFunction) { - is KtNamedFunction -> (relevantFunction.nameIdentifier ?: relevantFunction.funKeyword)?.let { + is KtNamedFunction -> relevantFunction.funKeyword?.let { targetOccurrenceAdded = true addOccurrence(it) } @@ -179,7 +180,7 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages if (!targetOccurrenceAdded) { when (relevantFunction) { is KtFunctionLiteral -> relevantFunction.parentOfTypes(KtCallExpression::class)?.calleeExpression - is KtNamedFunction -> relevantFunction.nameIdentifier + is KtNamedFunction -> relevantFunction.funKeyword else -> null }?.let { targetOccurrenceAdded = true @@ -212,60 +213,59 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages return true } - private fun visitReturnOrThrow(expression: KtExpression) { - if (getRelevantDeclaration(expression) == relevantFunction) { - if (expression is KtThrowExpression) { - addOccurrence(expression) - } else { - val returnExpression = expression as KtReturnExpression - when (returnExpression.returnedExpression ) { - is KtIfExpression, is KtWhenExpression, is KtTryExpression -> { - addOccurrence(expression.returnKeyword) - returnExpression.acceptChildren(object : KtVisitorVoid() { - override fun visitKtElement(element: KtElement) { - ProgressIndicatorProvider.checkCanceled() - element.acceptChildren(this) + private fun isRelevantFunction(expression: KtExpression): Boolean = getRelevantDeclaration(expression) == relevantFunction + + override fun visitReturnExpression(expression: KtReturnExpression) { + if (!isRelevantFunction(expression)) return + + when (expression.returnedExpression) { + is KtIfExpression, is KtWhenExpression, is KtTryExpression -> { + addOccurrence(expression.returnKeyword) + expression.acceptChildren(object : KtVisitorVoid() { + override fun visitKtElement(element: KtElement) { + ProgressIndicatorProvider.checkCanceled() + element.acceptChildren(this) + } + + override fun visitExpression(expression: KtExpression) { + when (expression) { + is KtBlockExpression -> expression.lastStatementOrNull()?.let { visitExpression(it) } + is KtIfExpression -> { + expression.then?.let { visitExpression(it) } + expression.`else`?.let { visitExpression(it) } } - override fun visitExpression(expression: KtExpression) { - when(expression) { - is KtBlockExpression -> expression.lastStatementOrNull()?.let { visitExpression(it) } - is KtIfExpression -> { - expression.then?.let { visitExpression(it) } - expression.`else`?.let { visitExpression(it) } - } - is KtTryExpression -> { - expression.tryBlock.lastStatementOrNull()?.let { visitExpression(it) } - expression.catchClauses.forEach { catchClause -> - catchClause.catchBody?.let { visitExpression(it) } - } - } - is KtWhenExpression -> - expression.entries.forEach { whenEntry -> - whenEntry.expression?.let { visitExpression(it) } - } - else -> addOccurrence(expression) + is KtTryExpression -> { + expression.tryBlock.lastStatementOrNull()?.let { visitExpression(it) } + expression.catchClauses.forEach { catchClause -> + catchClause.catchBody?.let { visitExpression(it) } } } - }) + + is KtWhenExpression -> + expression.entries.forEach { whenEntry -> + whenEntry.expression?.let { visitExpression(it) } + } + + else -> addOccurrence(expression) + } } - else -> addOccurrence(expression) - } + }) } + + else -> addOccurrence(expression) } } - override fun visitReturnExpression(expression: KtReturnExpression) { - visitReturnOrThrow(expression) - } - override fun visitThrowExpression(expression: KtThrowExpression) { - visitReturnOrThrow(expression) + if (!isRelevantFunction(expression)) return + + addOccurrence(expression) } }) } - override fun highlightReferences() = highlightReferences + override fun highlightReferences(): Boolean = highlightReferences } private fun MutableSet.addIfNotNullAndNotBlock(element: PsiElement?) { diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/AbstractUsageHighlightingTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/AbstractUsageHighlightingTest.kt index 5e1b7edc2d72..63a53b40d667 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/AbstractUsageHighlightingTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/AbstractUsageHighlightingTest.kt @@ -4,11 +4,13 @@ package org.jetbrains.kotlin.idea.highlighter import com.intellij.codeInsight.daemon.impl.HighlightInfo import com.intellij.codeInsight.daemon.impl.HighlightInfoType +import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPass import com.intellij.codeInsight.highlighting.HighlightUsagesHandler import com.intellij.openapi.editor.colors.EditorColors import com.intellij.openapi.editor.colors.EditorColorsManager import com.intellij.openapi.editor.markup.RangeHighlighter import com.intellij.openapi.editor.markup.TextAttributes +import com.intellij.refactoring.suggested.range import com.intellij.testFramework.ExpectedHighlightingData import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.extractMarkerOffset @@ -30,13 +32,18 @@ abstract class AbstractUsageHighlightingTest : KotlinLightCodeInsightFixtureTest editor.caretModel.moveToOffset(caret) HighlightUsagesHandler.invoke(project, editor, myFixture.file) - val highlighters = myFixture.editor.markupModel.allHighlighters - val infos = highlighters - .filter { isUsageHighlighting(it) } - .map { highlighter -> - var startOffset = highlighter.startOffset - var endOffset = highlighter.endOffset + val ranges = + myFixture.editor.markupModel.allHighlighters.filter { isUsageHighlighting(it) }.mapNotNull { it.range } + + (myFixture.file.findElementAt(myFixture.editor.caretModel.offset - 1)?.parent?.let { + val usages = IdentifierHighlighterPass.getUsages(it, myFixture.file, false) + usages + } ?: emptyList()) + + val infos = ranges.toHashSet() + .map { + var startOffset = it.startOffset + var endOffset = it.endOffset if (startOffset > caret) startOffset += CARET_TAG.length if (endOffset > caret) endOffset += CARET_TAG.length diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/UsageHighlightingTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/UsageHighlightingTestGenerated.java index 06795a3555e8..f9ab1b0efc20 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/UsageHighlightingTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/UsageHighlightingTestGenerated.java @@ -43,6 +43,11 @@ public class UsageHighlightingTestGenerated extends AbstractUsageHighlightingTes runTest("testData/usageHighlighter/destructingDeclarationLambdaParams.kt"); } + @TestMetadata("functionNameIdentifier.kt") + public void testFunctionNameIdentifier() throws Exception { + runTest("testData/usageHighlighter/functionNameIdentifier.kt"); + } + @TestMetadata("implicitIt.kt") public void testImplicitIt() throws Exception { runTest("testData/usageHighlighter/implicitIt.kt"); diff --git a/plugins/kotlin/idea/tests/testData/usageHighlighter/functionNameIdentifier.kt b/plugins/kotlin/idea/tests/testData/usageHighlighter/functionNameIdentifier.kt new file mode 100644 index 000000000000..1002a3c77b31 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/usageHighlighter/functionNameIdentifier.kt @@ -0,0 +1,7 @@ +fun test~(s: String?): Int { + if (s != null) { + return@test 1 + } + return 0 +} +val q = test("") From d42fa786794969e08ae90d577f00eef74ddcd76c Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Mon, 31 Jul 2023 22:11:27 +0200 Subject: [PATCH 073/165] [kotlin] Update test data to make highlighted elements more clear #KTIJ-26412 GitOrigin-RevId: 1eb177e94ae74eded69a02fadb6b93135da6aa3b --- .../K2HighlightExitPointsTestGenerated.java | 29 +++++++----- .../AbstractHighlightExitPointsTest.kt | 47 +++++++++++++++---- .../HighlightExitPointsTestGenerated.java | 29 +++++++----- .../testData/exitPoints/anonymousFunction.kt | 9 ++-- .../testData/exitPoints/anonymousFunction2.kt | 9 ++-- .../tests/testData/exitPoints/funKeyword.kt | 6 +++ .../tests/testData/exitPoints/funKeyword2.kt | 4 ++ ...ctionNameIdentifier3.kt => funKeyword3.kt} | 2 +- ...ionNameIdentifier31.kt => funKeyword31.kt} | 2 +- .../idea/tests/testData/exitPoints/funName.kt | 6 +++ .../exitPoints/functionNameIdentifier.kt | 10 ---- .../exitPoints/functionNameIdentifier2.kt | 8 ---- .../idea/tests/testData/exitPoints/getter.kt | 12 ++--- .../idea/tests/testData/exitPoints/getter2.kt | 9 ++-- .../idea/tests/testData/exitPoints/getter3.kt | 9 ++-- .../tests/testData/exitPoints/inLambda.kt | 12 ++--- .../tests/testData/exitPoints/inLambda1.kt | 11 ++--- .../tests/testData/exitPoints/inLambda2.kt | 2 +- .../exitPoints/inLambdaLastStatement1.kt | 2 +- .../exitPoints/inLambdaLastStatement2.kt | 2 +- .../exitPoints/inLambdaLastStatement3.kt | 2 +- .../exitPoints/inLambdaLastStatement4.kt | 2 +- .../exitPoints/inLambdaLastStatement5.kt | 8 ++-- .../idea/tests/testData/exitPoints/inline1.kt | 12 ++--- .../idea/tests/testData/exitPoints/inline2.kt | 12 ++--- .../idea/tests/testData/exitPoints/inline3.kt | 12 ++--- .../testData/exitPoints/inlineLocalReturn1.kt | 9 ++-- .../testData/exitPoints/inlineLocalReturn2.kt | 9 ++-- .../testData/exitPoints/inlineLocalReturn3.kt | 12 ++--- .../exitPoints/inlineWithNoInlineParam.kt | 9 ++-- .../testData/exitPoints/invalidReturn.kt | 2 +- .../tests/testData/exitPoints/invalidThrow.kt | 2 +- .../testData/exitPoints/localFunction1.kt | 9 ++-- .../testData/exitPoints/localFunction2.kt | 12 ++--- .../testData/exitPoints/localFunctionThrow.kt | 12 ++--- .../tests/testData/exitPoints/notInline1.kt | 9 ++-- .../tests/testData/exitPoints/notInline2.kt | 12 ++--- .../tests/testData/exitPoints/notInline3.kt | 12 ++--- .../notReturnedLabeledExpression.kt | 2 +- .../testData/exitPoints/returnIfStatement.kt | 15 ++---- .../testData/exitPoints/returnTryStatement.kt | 16 ++----- .../exitPoints/returnWhenStatement.kt | 18 +++---- .../idea/tests/testData/exitPoints/simple.kt | 12 ++--- .../idea/tests/testData/exitPoints/throw1.kt | 12 ++--- .../idea/tests/testData/exitPoints/throw2.kt | 12 ++--- .../functionNameIdentifier.kt | 2 +- 46 files changed, 200 insertions(+), 266 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/exitPoints/funKeyword.kt create mode 100644 plugins/kotlin/idea/tests/testData/exitPoints/funKeyword2.kt rename plugins/kotlin/idea/tests/testData/exitPoints/{functionNameIdentifier3.kt => funKeyword3.kt} (92%) rename plugins/kotlin/idea/tests/testData/exitPoints/{functionNameIdentifier31.kt => funKeyword31.kt} (73%) create mode 100644 plugins/kotlin/idea/tests/testData/exitPoints/funName.kt delete mode 100644 plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier.kt delete mode 100644 plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier2.kt diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java b/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java index c679b22e1d0b..73039bfee0fd 100644 --- a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java +++ b/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java @@ -33,24 +33,29 @@ public class K2HighlightExitPointsTestGenerated extends AbstractK2HighlightExitP runTest("../idea/tests/testData/exitPoints/anonymousFunction2.kt"); } - @TestMetadata("functionNameIdentifier.kt") - public void testFunctionNameIdentifier() throws Exception { - runTest("../idea/tests/testData/exitPoints/functionNameIdentifier.kt"); + @TestMetadata("funKeyword.kt") + public void testFunKeyword() throws Exception { + runTest("../idea/tests/testData/exitPoints/funKeyword.kt"); } - @TestMetadata("functionNameIdentifier2.kt") - public void testFunctionNameIdentifier2() throws Exception { - runTest("../idea/tests/testData/exitPoints/functionNameIdentifier2.kt"); + @TestMetadata("funKeyword2.kt") + public void testFunKeyword2() throws Exception { + runTest("../idea/tests/testData/exitPoints/funKeyword2.kt"); } - @TestMetadata("functionNameIdentifier3.kt") - public void testFunctionNameIdentifier3() throws Exception { - runTest("../idea/tests/testData/exitPoints/functionNameIdentifier3.kt"); + @TestMetadata("funKeyword3.kt") + public void testFunKeyword3() throws Exception { + runTest("../idea/tests/testData/exitPoints/funKeyword3.kt"); } - @TestMetadata("functionNameIdentifier31.kt") - public void testFunctionNameIdentifier31() throws Exception { - runTest("../idea/tests/testData/exitPoints/functionNameIdentifier31.kt"); + @TestMetadata("funKeyword31.kt") + public void testFunKeyword31() throws Exception { + runTest("../idea/tests/testData/exitPoints/funKeyword31.kt"); + } + + @TestMetadata("funName.kt") + public void testFunName() throws Exception { + runTest("../idea/tests/testData/exitPoints/funName.kt"); } @TestMetadata("getter.kt") diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/AbstractHighlightExitPointsTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/AbstractHighlightExitPointsTest.kt index 5352d56794a1..c18353b805c2 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/AbstractHighlightExitPointsTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/AbstractHighlightExitPointsTest.kt @@ -2,24 +2,41 @@ package org.jetbrains.kotlin.idea.highlighter +import com.intellij.codeInsight.daemon.impl.HighlightInfo +import com.intellij.codeInsight.daemon.impl.HighlightInfoType import com.intellij.codeInsight.highlighting.HighlightUsagesHandler import com.intellij.codeInsight.highlighting.highlightUsages import com.intellij.openapi.application.ReadAction import com.intellij.openapi.editor.colors.EditorColors -import com.intellij.openapi.editor.colors.EditorColorsManager import com.intellij.openapi.project.DumbService import com.intellij.psi.PsiElement +import com.intellij.refactoring.suggested.range +import com.intellij.testFramework.ExpectedHighlightingData import com.intellij.util.concurrency.AppExecutorUtil -import org.jetbrains.kotlin.idea.test.InTextDirectivesUtils import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.test.extractMarkerOffset import java.util.concurrent.Callable abstract class AbstractHighlightExitPointsTest : KotlinLightCodeInsightFixtureTestCase() { + companion object { + // Not standard to leave it in text after configureByFile and remove manually after collecting highlighting information + const val CARET_TAG = "~" + } + open fun doTest(unused: String) { myFixture.configureByFile(fileName()) val editor = myFixture.editor + + val document = myFixture.editor.document + val data = ExpectedHighlightingData(document, false, false, true, false) + data.init() + + val caret = document.extractMarkerOffset(project, CARET_TAG) + assert(caret != -1) { "Caret marker '${CARET_TAG}' expected" } + editor.caretModel.moveToOffset(caret) + val customHandler = HighlightUsagesHandler.createCustomHandler(editor, myFixture.file) @@ -34,13 +51,23 @@ abstract class AbstractHighlightExitPointsTest : KotlinLightCodeInsightFixtureTe }) } - val text = myFixture.file.text - val expectedToBeHighlighted = InTextDirectivesUtils.findLinesWithPrefixesRemoved(text, "//HIGHLIGHTED:") - val searchResultsTextAttributes = - EditorColorsManager.getInstance().globalScheme.getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES) - val highlighters = editor.markupModel.allHighlighters - .filter { it.textAttributes == searchResultsTextAttributes } - val actual = highlighters.map { text.substring(it.startOffset, it.endOffset) } - assertEquals(expectedToBeHighlighted, actual) + val ranges = editor.markupModel.allHighlighters + .filter { it.textAttributesKey == EditorColors.SEARCH_RESULT_ATTRIBUTES } + .mapNotNull { it.range } + + val infos = ranges.toHashSet() + .map { + var startOffset = it.startOffset + var endOffset = it.endOffset + + if (startOffset > caret) startOffset += CARET_TAG.length + if (endOffset > caret) endOffset += CARET_TAG.length + + HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION) + .range(startOffset, endOffset) + .create() + } + + data.checkResult(myFixture.file, infos, StringBuilder(document.text).insert(caret, CARET_TAG).toString()) } } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java index a7c2adab290a..9e804281ca90 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java @@ -33,24 +33,29 @@ public class HighlightExitPointsTestGenerated extends AbstractHighlightExitPoint runTest("testData/exitPoints/anonymousFunction2.kt"); } - @TestMetadata("functionNameIdentifier.kt") - public void testFunctionNameIdentifier() throws Exception { - runTest("testData/exitPoints/functionNameIdentifier.kt"); + @TestMetadata("funKeyword.kt") + public void testFunKeyword() throws Exception { + runTest("testData/exitPoints/funKeyword.kt"); } - @TestMetadata("functionNameIdentifier2.kt") - public void testFunctionNameIdentifier2() throws Exception { - runTest("testData/exitPoints/functionNameIdentifier2.kt"); + @TestMetadata("funKeyword2.kt") + public void testFunKeyword2() throws Exception { + runTest("testData/exitPoints/funKeyword2.kt"); } - @TestMetadata("functionNameIdentifier3.kt") - public void testFunctionNameIdentifier3() throws Exception { - runTest("testData/exitPoints/functionNameIdentifier3.kt"); + @TestMetadata("funKeyword3.kt") + public void testFunKeyword3() throws Exception { + runTest("testData/exitPoints/funKeyword3.kt"); } - @TestMetadata("functionNameIdentifier31.kt") - public void testFunctionNameIdentifier31() throws Exception { - runTest("testData/exitPoints/functionNameIdentifier31.kt"); + @TestMetadata("funKeyword31.kt") + public void testFunKeyword31() throws Exception { + runTest("testData/exitPoints/funKeyword31.kt"); + } + + @TestMetadata("funName.kt") + public void testFunName() throws Exception { + runTest("testData/exitPoints/funName.kt"); } @TestMetadata("getter.kt") diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/anonymousFunction.kt b/plugins/kotlin/idea/tests/testData/exitPoints/anonymousFunction.kt index fb63e568ca82..adcfb292c51f 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/anonymousFunction.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/anonymousFunction.kt @@ -1,10 +1,7 @@ fun foo() { - listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) { - if (value == 3) return + listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) { + if (value == 3) ~return print(value) }) print(" done with anonymous function") -} - -//HIGHLIGHTED: fun -//HIGHLIGHTED: return +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/anonymousFunction2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/anonymousFunction2.kt index efb538fc325c..9a0fd34b00e2 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/anonymousFunction2.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/anonymousFunction2.kt @@ -1,10 +1,7 @@ fun foo() { - listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) { - if (value == 3) return@forEach + listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) { + if (value == 3) return@~forEach print(value) }) print(" done with anonymous function") -} - -//HIGHLIGHTED: fun -//HIGHLIGHTED: return@forEach +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/funKeyword.kt b/plugins/kotlin/idea/tests/testData/exitPoints/funKeyword.kt new file mode 100644 index 000000000000..daa57303c0e9 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/exitPoints/funKeyword.kt @@ -0,0 +1,6 @@ +~fun test(s: String?): Int { + if (s != null) { + return@test 1 + } + return 0 +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/funKeyword2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/funKeyword2.kt new file mode 100644 index 000000000000..cddc9b567890 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/exitPoints/funKeyword2.kt @@ -0,0 +1,4 @@ +fun~ test(s: String?): Int = + if (s != null) { + 1 + } else 0 diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier3.kt b/plugins/kotlin/idea/tests/testData/exitPoints/funKeyword3.kt similarity index 92% rename from plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier3.kt rename to plugins/kotlin/idea/tests/testData/exitPoints/funKeyword3.kt index 87c4523b43d4..96a61ce3a95b 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier3.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/funKeyword3.kt @@ -1,6 +1,6 @@ fun test(s: String?): Int = if (s != null) { - 1 + 1~ } else 0 // no exit point highlighting as to KTIJ-26395: we should not highlight exit points on the latest statement as it interferes with variable/call/type highlighting \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier31.kt b/plugins/kotlin/idea/tests/testData/exitPoints/funKeyword31.kt similarity index 73% rename from plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier31.kt rename to plugins/kotlin/idea/tests/testData/exitPoints/funKeyword31.kt index fe8de5644e28..0a41887107a9 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier31.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/funKeyword31.kt @@ -1,5 +1,5 @@ fun test(s: String?): Int = if (s != null) { - val q = 0 + val q = 0~ 1 } else 0 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/funName.kt b/plugins/kotlin/idea/tests/testData/exitPoints/funName.kt new file mode 100644 index 000000000000..73597f2486e0 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/exitPoints/funName.kt @@ -0,0 +1,6 @@ +fun ~test(s: String?): Int { + if (s != null) { + return@test 1 + } + return 0 +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier.kt b/plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier.kt deleted file mode 100644 index 68705837c5e4..000000000000 --- a/plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier.kt +++ /dev/null @@ -1,10 +0,0 @@ -fun test(s: String?): Int { - if (s != null) { - return@test 1 - } - return 0 -} - -//HIGHLIGHTED: return@test 1 -//HIGHLIGHTED: test -//HIGHLIGHTED: return 0 diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier2.kt deleted file mode 100644 index 9a382d23bb5b..000000000000 --- a/plugins/kotlin/idea/tests/testData/exitPoints/functionNameIdentifier2.kt +++ /dev/null @@ -1,8 +0,0 @@ -fun test(s: String?): Int = - if (s != null) { - 1 - } else 0 - -//HIGHLIGHTED: 1 -//HIGHLIGHTED: test -//HIGHLIGHTED: 0 diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/getter.kt b/plugins/kotlin/idea/tests/testData/exitPoints/getter.kt index 28a6ec32037a..f6f2cd72ff4e 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/getter.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/getter.kt @@ -1,13 +1,9 @@ val Any?.foo: Int - get() { + get() { this?.let { - return 1 + ~return 1 } - return 2 + return 2 } -public inline fun T.let(block: (T) -> Unit) {} - -//HIGHLIGHTED: return 1 -//HIGHLIGHTED: get -//HIGHLIGHTED: return 2 \ No newline at end of file +public inline fun T.let(block: (T) -> Unit) {} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/getter2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/getter2.kt index 755015a05400..50d214c80fea 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/getter2.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/getter2.kt @@ -1,9 +1,6 @@ val Any?.foo: Int - get() { - return 42 + get() { + return~ 42 } -public inline fun T.let(block: (T) -> Unit) {} - -//HIGHLIGHTED: get -//HIGHLIGHTED: return 42 +public inline fun T.let(block: (T) -> Unit) {} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/getter3.kt b/plugins/kotlin/idea/tests/testData/exitPoints/getter3.kt index 9cf1bcd089de..b24aa9e437b7 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/getter3.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/getter3.kt @@ -1,9 +1,6 @@ val Any?.foo: Int - get() { - return 42 + get~() { + return 42 } -public inline fun T.let(block: (T) -> Unit) {} - -//HIGHLIGHTED: get -//HIGHLIGHTED: return 42 +public inline fun T.let(block: (T) -> Unit) {} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inLambda.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inLambda.kt index f0ba7cb1470c..1c4ca0cfa797 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inLambda.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inLambda.kt @@ -1,13 +1,9 @@ fun foo(f: (String?) -> Int) {} fun test() { - foo { - if (it == null) return@foo 1 + foo { + if (it == null) return@~foo 1 (1+1) - if (it == "a") 2 else 0 + if (it == "a") 2 else 0 } -} -//HIGHLIGHTED: return@foo 1 -//HIGHLIGHTED: foo -//HIGHLIGHTED: 2 -//HIGHLIGHTED: 0 \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inLambda1.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inLambda1.kt index 43f2354f1723..846424a5028a 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inLambda1.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inLambda1.kt @@ -1,11 +1,8 @@ fun foo(f: (String?) -> Int) {} fun test() { - foo { - if (it == null) return@foo 1 - 0 + foo { + if (it == null) return@~foo 1 + 0 } -} -//HIGHLIGHTED: return@foo 1 -//HIGHLIGHTED: foo -//HIGHLIGHTED: 0 \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inLambda2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inLambda2.kt index 7cf248a7bc53..6d34dcc48839 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inLambda2.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inLambda2.kt @@ -3,7 +3,7 @@ fun foo(f: (String?) -> Int) {} fun test() { foo { if (it != null) return@foo 1 - (1+1) + ~(1+1) 0 } } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement1.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement1.kt index 4ad2b2cf60e8..fcc0d1dbd272 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement1.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement1.kt @@ -3,7 +3,7 @@ fun foo(f: (String?) -> Int) {} fun test() { foo { if (it != null) return@foo 1 - 0 + 0~ } } // no exit point highlighting as to KTIJ-26395: we should not highlight exit points on the latest statement as it interferes with variable/call/type highlighting diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement2.kt index fd65c4b6433b..1853e4da8b61 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement2.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement2.kt @@ -3,7 +3,7 @@ fun foo(f: (String?) -> Int) {} fun test() { foo { if (it == null) return@foo 1 - if (it == "a") 2 else 0 + if (it == "a") 2~ else 0 } } // no exit point highlighting as to KTIJ-26395: we should not highlight exit points on the latest statement as it interferes with variable/call/type highlighting \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement3.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement3.kt index 605874d3c175..8926737e96c7 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement3.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement3.kt @@ -3,6 +3,6 @@ fun foo(f: (String?) -> Int) {} fun test() { foo { if (it == null) return@foo 1 - if (it == "a") 2 else 0 + if (it == "a") 2 e~lse 0 } } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement4.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement4.kt index 376e212cefb6..d3b16f0cf11d 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement4.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement4.kt @@ -4,7 +4,7 @@ fun test() { foo { if (it != null) return@foo 1 if (it == "a") { - val q = 1 + val q = 1~ 2 } else { 0 diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement5.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement5.kt index b9aa29ed6154..993b923cecc4 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement5.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement5.kt @@ -1,16 +1,14 @@ fun foo(f: (String?) -> Int) {} -fun y(): Int = 11 +fun y(): Int = 11 fun test() { foo { if (it != null) return@foo 1 if (it == "a") { - if (it == "aa") y() else 2 + if (it == "aa") y~() else 2 } else { 0 } } } -// no exit point highlighting as to KTIJ-26395: we should not highlight exit points on the latest statement as it interferes with variable/call/type highlighting -//HIGHLIGHTED: y -//HIGHLIGHTED: y \ No newline at end of file +// no exit point highlighting as to KTIJ-26395: we should not highlight exit points on the latest statement as it interferes with variable/call/type highlighting \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inline1.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inline1.kt index ecaecfddf003..d0ce228c35d4 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inline1.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inline1.kt @@ -1,16 +1,12 @@ -fun f(a: Int): Int { +fun f(a: Int): Int { if (a < 5) { run { - return 1 + ~return 1 } } else { - return 2 + return 2 } } -inline public fun run(f: () -> T): T { } - -//HIGHLIGHTED: return 1 -//HIGHLIGHTED: f -//HIGHLIGHTED: return 2 \ No newline at end of file +inline public fun run(f: () -> T): T { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inline2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inline2.kt index c2be493befe4..b7feb7ae93a9 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inline2.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inline2.kt @@ -1,16 +1,12 @@ -fun f(a: Int): Int { +fun f(a: Int): Int { if (a < 5) { run { - return 1 + return 1 } } else { - return 2 + ~return 2 } } -inline public fun run(f: () -> T): T { } - -//HIGHLIGHTED: return 1 -//HIGHLIGHTED: f -//HIGHLIGHTED: return 2 \ No newline at end of file +inline public fun run(f: () -> T): T { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inline3.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inline3.kt index cbe26c078307..b11e72714baf 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inline3.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inline3.kt @@ -1,12 +1,8 @@ -fun Any?.foo(): Int { +fun Any?.foo(): Int { this?.let { - return 1 + ~return 1 } - return 2 + return 2 } -public inline fun T.let(block: (T) -> Unit) {} - -//HIGHLIGHTED: return 1 -//HIGHLIGHTED: foo -//HIGHLIGHTED: return 2 \ No newline at end of file +public inline fun T.let(block: (T) -> Unit) {} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn1.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn1.kt index 6da49d5977ae..a1180b999022 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn1.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn1.kt @@ -1,7 +1,7 @@ fun f(a: Int): Int { if (a < 5) { - run { - return@run 1 + run { + ~return@run 1 } } else { @@ -9,7 +9,4 @@ fun f(a: Int): Int { } } -inline public fun run(f: () -> T): T { } - -//HIGHLIGHTED: run -//HIGHLIGHTED: return@run 1 +inline public fun run(f: () -> T): T { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn2.kt index ff050d238ac9..26fd611b40cf 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn2.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn2.kt @@ -1,15 +1,12 @@ -fun f(a: Int): Int { +fun f(a: Int): Int { if (a < 5) { run { return@run 1 } } else { - return 2 + ~return 2 } } -inline public fun run(f: () -> T): T { } - -//HIGHLIGHTED: f -//HIGHLIGHTED: return 2 \ No newline at end of file +inline public fun run(f: () -> T): T { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn3.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn3.kt index dd9d044300e4..de8108af77e0 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn3.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inlineLocalReturn3.kt @@ -1,12 +1,8 @@ fun foo(x: Int): Int { if (x == 1) return 1 - listOf(1, 2, 3).map { - if (it == 2) return@map 2 - return@map 3 + listOf(1, 2, 3).map { + if (it == 2) return@map 2 + return@~map 3 } return 4 -} - -//HIGHLIGHTED: return@map 2 -//HIGHLIGHTED: map -//HIGHLIGHTED: return@map 3 \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inlineWithNoInlineParam.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inlineWithNoInlineParam.kt index 9576fcdd5285..15a3d21a5d13 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/inlineWithNoInlineParam.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inlineWithNoInlineParam.kt @@ -1,13 +1,10 @@ fun f(a: Int): Int { if (a < 5) { - run1(fun (): Int { - return 1 + run1(fun (): Int { + ~return 1 }) } return 2 } -inline public fun run1(noinline f: () -> T): T { } - -//HIGHLIGHTED: fun -//HIGHLIGHTED: return 1 +inline public fun run1(noinline f: () -> T): T { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/invalidReturn.kt b/plugins/kotlin/idea/tests/testData/exitPoints/invalidReturn.kt index ea2fc1423380..2e5581761d4c 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/invalidReturn.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/invalidReturn.kt @@ -1,4 +1,4 @@ // KT-8042 ISE at KotlinHighlightExitPointsHandlerFactory.createHighlightUsagesHandler() on typing a function name starting with `throw` // EA-68157 -fun return \ No newline at end of file +fun return~ \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/invalidThrow.kt b/plugins/kotlin/idea/tests/testData/exitPoints/invalidThrow.kt index 20527152e1a2..2e4dd44747cd 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/invalidThrow.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/invalidThrow.kt @@ -1,4 +1,4 @@ // KT-8042 ISE at KotlinHighlightExitPointsHandlerFactory.createHighlightUsagesHandler() on typing a function name starting with `throw` // EA-68157 -fun throw \ No newline at end of file +fun throw~ \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/localFunction1.kt b/plugins/kotlin/idea/tests/testData/exitPoints/localFunction1.kt index 4b3df694d415..6abe7356cb65 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/localFunction1.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/localFunction1.kt @@ -1,6 +1,6 @@ fun f(a: Int): Int { - fun localFun() { - return + fun localFun() { + ~return } if (a < 5) { @@ -9,7 +9,4 @@ fun f(a: Int): Int { else { return 2 } -} - -//HIGHLIGHTED: localFun -//HIGHLIGHTED: return +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/localFunction2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/localFunction2.kt index 011a5c376722..32c443d1a4c7 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/localFunction2.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/localFunction2.kt @@ -1,16 +1,12 @@ -fun f(a: Int): Int { +fun f(a: Int): Int { fun localFun() { return } if (a < 5) { - return 1 + return 1 } else { - return 2 + ~return 2 } -} - -//HIGHLIGHTED: return 1 -//HIGHLIGHTED: f -//HIGHLIGHTED: return 2 +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/localFunctionThrow.kt b/plugins/kotlin/idea/tests/testData/exitPoints/localFunctionThrow.kt index 74b1e8838f2f..cc912626e28d 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/localFunctionThrow.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/localFunctionThrow.kt @@ -1,9 +1,9 @@ fun f(a: Int): Int { - fun localFun() { + fun localFun() { if (a > 5) { - return + return } - throw Error() + ~throw Error() } if (a < 5) { @@ -12,8 +12,4 @@ fun f(a: Int): Int { else { throw Exception() } -} - -//HIGHLIGHTED: return -//HIGHLIGHTED: localFun -//HIGHLIGHTED: throw Error() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/notInline1.kt b/plugins/kotlin/idea/tests/testData/exitPoints/notInline1.kt index 2b8adc83251b..eca95820e070 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/notInline1.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/notInline1.kt @@ -2,15 +2,12 @@ import javax.swing.SwingUtilities fun f(a: Int): Int { if (a < 5) { - SwingUtilities.invokeLater(fun (): Unit { - return + SwingUtilities.invokeLater(fun (): Unit { + ~return }) return 1 } else { return 2 } -} - -//HIGHLIGHTED: fun -//HIGHLIGHTED: return +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/notInline2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/notInline2.kt index e6e15ee87aed..9a9dd9769bf1 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/notInline2.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/notInline2.kt @@ -1,17 +1,13 @@ import javax.swing.SwingUtilities -fun f(a: Int): Int { +fun f(a: Int): Int { if (a < 5) { SwingUtilities.invokeLater(fun (): Unit { return }) - return 1 + ~return 1 } else { - return 2 + return 2 } -} - -//HIGHLIGHTED: return 1 -//HIGHLIGHTED: f -//HIGHLIGHTED: return 2 +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/notInline3.kt b/plugins/kotlin/idea/tests/testData/exitPoints/notInline3.kt index 98ccd002471d..739bd99160f7 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/notInline3.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/notInline3.kt @@ -1,12 +1,8 @@ -fun foo(x: Int): Int { - if (x == 1) return 1 +fun foo(x: Int): Int { + if (x == 1) return 1 listOf(1, 2, 3).map { if (it == 2) return@map 2 return@map 3 } - return 4 -} - -//HIGHLIGHTED: return 1 -//HIGHLIGHTED: foo -//HIGHLIGHTED: return 4 \ No newline at end of file + ~return 4 +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/notReturnedLabeledExpression.kt b/plugins/kotlin/idea/tests/testData/exitPoints/notReturnedLabeledExpression.kt index d597ff137cd1..c2a1e5a3d0ee 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/notReturnedLabeledExpression.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/notReturnedLabeledExpression.kt @@ -4,6 +4,6 @@ fun List<*>.func(function: List<*>.()-> Unit) { fun test() { return listOf(1, 2, 3).func { - this@func + this@func~ } } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/returnIfStatement.kt b/plugins/kotlin/idea/tests/testData/exitPoints/returnIfStatement.kt index db37118452c3..57d6b3d0d028 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/returnIfStatement.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/returnIfStatement.kt @@ -1,14 +1,9 @@ -fun f(a: Int): Int { - return if (a < 5) { +fun f(a: Int): Int { + return~ if (a < 5) { val q = 1 - 1 + 1 } else { - 2 + 2 } -} - -//HIGHLIGHTED: return -//HIGHLIGHTED: f -//HIGHLIGHTED: 1 -//HIGHLIGHTED: 2 \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/returnTryStatement.kt b/plugins/kotlin/idea/tests/testData/exitPoints/returnTryStatement.kt index c76f7eba1c3e..a1abd1160349 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/returnTryStatement.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/returnTryStatement.kt @@ -1,20 +1,14 @@ fun yy(): Int = 5 -fun f(a: Int): Int { - return try { +fun f(a: Int): Int { + return~ try { val q = a * a - q + q } catch (e: Exception) { - 0 + 0 } catch (e: Throwable) { - -1 + -1 } finally { println() } } - -//HIGHLIGHTED: return -//HIGHLIGHTED: f -//HIGHLIGHTED: 0 -//HIGHLIGHTED: q -//HIGHLIGHTED: -1 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/returnWhenStatement.kt b/plugins/kotlin/idea/tests/testData/exitPoints/returnWhenStatement.kt index e4c68ef8be8d..50353d407943 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/returnWhenStatement.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/returnWhenStatement.kt @@ -1,20 +1,14 @@ fun yy(): Int = 5 -fun f(a: Int): Int { - return when { +fun f(a: Int): Int { + return~ when { a < 0 -> { val q = 1 - 2 * 2 + 2 * 2 } a > 0 -> { - 2 * (2 + 2) + 2 * (2 + 2) } - else -> yy() + else -> yy() } -} - -//HIGHLIGHTED: return -//HIGHLIGHTED: f -//HIGHLIGHTED: 2 * (2 + 2) -//HIGHLIGHTED: 2 * 2 -//HIGHLIGHTED: yy() \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/simple.kt b/plugins/kotlin/idea/tests/testData/exitPoints/simple.kt index 8c43f5d81d66..c1762b4dffc1 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/simple.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/simple.kt @@ -1,12 +1,8 @@ -fun f(a: Int): Int { +fun f(a: Int): Int { if (a < 5) { - return 1 + ~return 1 } else { - return 2 + return 2 } -} - -//HIGHLIGHTED: return 1 -//HIGHLIGHTED: f -//HIGHLIGHTED: return 2 \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/throw1.kt b/plugins/kotlin/idea/tests/testData/exitPoints/throw1.kt index 2765c8552584..315606262424 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/throw1.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/throw1.kt @@ -1,12 +1,8 @@ -fun f(a: Int): Int { +fun f(a: Int): Int { if (a < 5) { - return 1 + return 1 } else { - throw Error() + ~throw Error() } -} - -//HIGHLIGHTED: return 1 -//HIGHLIGHTED: f -//HIGHLIGHTED: throw Error() \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/throw2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/throw2.kt index e956c36a542c..1e697b8ed973 100644 --- a/plugins/kotlin/idea/tests/testData/exitPoints/throw2.kt +++ b/plugins/kotlin/idea/tests/testData/exitPoints/throw2.kt @@ -1,12 +1,8 @@ -fun f(a: Int): Int { +fun f(a: Int): Int { if (a < 5) { - return 1 + ~return 1 } else { - throw Error() + throw Error() } -} - -//HIGHLIGHTED: return 1 -//HIGHLIGHTED: f -//HIGHLIGHTED: throw Error() \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/usageHighlighter/functionNameIdentifier.kt b/plugins/kotlin/idea/tests/testData/usageHighlighter/functionNameIdentifier.kt index 1002a3c77b31..cb616704a932 100644 --- a/plugins/kotlin/idea/tests/testData/usageHighlighter/functionNameIdentifier.kt +++ b/plugins/kotlin/idea/tests/testData/usageHighlighter/functionNameIdentifier.kt @@ -1,4 +1,4 @@ -fun test~(s: String?): Int { +fun~ test(s: String?): Int { if (s != null) { return@test 1 } From 76fdb311c7e4189f32d0c5e099e48f23729d9a38 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Tue, 1 Aug 2023 10:20:31 +0200 Subject: [PATCH 074/165] [kotlin] Fixed the latest statement in lambda exit-points highlighting #KTIJ-26395 GitOrigin-RevId: aa43f778bccf6d7ff83b34625dcd7b93bcf1ca97 --- ...KotlinHighlightExitPointsHandlerFactory.kt | 48 ++++++++++++++----- .../K2HighlightExitPointsTestGenerated.java | 5 ++ .../HighlightExitPointsTestGenerated.java | 5 ++ .../exitPoints/inLambdaLastStatement6.kt | 9 ++++ 4 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement6.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt b/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt index 855643fa8e44..aae19678aa4d 100644 --- a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt +++ b/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt @@ -141,26 +141,48 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages override fun visitExpression(expression: KtExpression) { when(expression) { is KtBinaryExpression -> { - lastStatements.addIfNotNullAndNotBlock(expression.left) - lastStatements.addIfNotNullAndNotBlock(expression.right) + expression.left?.let { + lastStatements.addIfNotNullAndNotBlock(it) + visitExpression(it) + } + expression.right?.let { + lastStatements.addIfNotNullAndNotBlock(it) + visitExpression(it) + } } is KtCallExpression -> { - lastStatements.addIfNotNullAndNotBlock(expression.calleeExpression) - } - is KtBlockExpression -> lastStatements.addIfNotNullAndNotBlock(expression.lastStatementOrNull()) - is KtIfExpression -> { - lastStatements.addIfNotNullAndNotBlock(expression.then) - lastStatements.addIfNotNullAndNotBlock(expression.`else`) - } - is KtWhenExpression -> - expression.entries.map { it.expression }.forEach { + expression.calleeExpression?.let { lastStatements.addIfNotNullAndNotBlock(it) + visitExpression(it) } + } + is KtBlockExpression -> { + expression.lastStatementOrNull()?.let { + lastStatements.addIfNotNullAndNotBlock(it) + visitExpression(it) + } + } + is KtIfExpression -> { + expression.then?.let { + lastStatements.addIfNotNullAndNotBlock(it) + visitExpression(it) + } + expression.`else`?.let{ + lastStatements.addIfNotNullAndNotBlock(it) + visitExpression(it) + } + } + is KtWhenExpression -> { + expression.entries.mapNotNull { it.expression }.forEach { + lastStatements.addIfNotNullAndNotBlock(it) + visitExpression(it) + } + } + else -> super.visitExpression(expression) } - super.visitExpression(expression) } }) - if (target !in lastStatements) { + if (target !is KtReturnExpression && target !is KtThrowExpression && target !in lastStatements) { return } lastStatements diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java b/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java index 73039bfee0fd..e0dca5e710ee 100644 --- a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java +++ b/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java @@ -113,6 +113,11 @@ public class K2HighlightExitPointsTestGenerated extends AbstractK2HighlightExitP runTest("../idea/tests/testData/exitPoints/inLambdaLastStatement5.kt"); } + @TestMetadata("inLambdaLastStatement6.kt") + public void testInLambdaLastStatement6() throws Exception { + runTest("../idea/tests/testData/exitPoints/inLambdaLastStatement6.kt"); + } + @TestMetadata("inline1.kt") public void testInline1() throws Exception { runTest("../idea/tests/testData/exitPoints/inline1.kt"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java index 9e804281ca90..8293f7a73901 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java @@ -113,6 +113,11 @@ public class HighlightExitPointsTestGenerated extends AbstractHighlightExitPoint runTest("testData/exitPoints/inLambdaLastStatement5.kt"); } + @TestMetadata("inLambdaLastStatement6.kt") + public void testInLambdaLastStatement6() throws Exception { + runTest("testData/exitPoints/inLambdaLastStatement6.kt"); + } + @TestMetadata("inline1.kt") public void testInline1() throws Exception { runTest("testData/exitPoints/inline1.kt"); diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement6.kt b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement6.kt new file mode 100644 index 000000000000..25bec058426b --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/exitPoints/inLambdaLastStatement6.kt @@ -0,0 +1,9 @@ +fun some(a: Int, b: Int) { + val q = run~ { + val y = if (a == 1) 0 else 1 + + y + } +} + +fun T.run(block: T.() -> R): R = block() \ No newline at end of file From 212b4c1a47eab7bd5cde9bd553194487c7e37631 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Wed, 2 Aug 2023 09:43:51 +0200 Subject: [PATCH 075/165] [kotlin] Regroup highlighting modules GitOrigin-RevId: 85a48fd2aec4fb321cec2d0c24d032274dc98b28 --- .../all-tests-fir/kotlin.fir-all-tests.iml | 2 +- .../kotlin.base.fe10.highlighting.iml | 2 +- .../kotlin.code-insight.inspections-k2.iml | 5 +- ...tlin.code-insight.inspections-k2.tests.iml | 2 +- .../kotlin.code-insight.line-markers-k2.iml | 4 +- ...lin.code-insight.live-templates-shared.iml | 2 +- plugins/kotlin/core/kotlin.core.iml | 2 +- plugins/kotlin/fir/kotlin.fir.iml | 2 +- .../kotlin.fir.frontend-independent.iml | 2 +- .../kotlin.highlighting.k1.iml} | 13 ++- .../KotlinChangeLocalityDetector.kt | 0 .../kotlin.highlighting.k2.iml} | 2 +- .../resources/kotlin.highlighting.xml | 0 .../KotlinCallHighlighterExtension.kt | 0 .../KotlinDiagnosticHighlightVisitor.kt | 0 ...KotlinHighlightExitPointsHandlerFactory.kt | 0 .../KotlinSemanticHighlightingPass.kt | 0 .../KotlinUnusedHighlightingVisitor.kt | 0 .../AnnotationEntryHighlightingVisitor.kt | 0 .../DeclarationHighlightingVisitor.kt | 0 .../highlighters/AfterResolveHighlighter.kt | 0 .../highlighters/DslHighlighter.kt | 0 .../ExpressionsSmartcastHighlighter.kt | 0 .../highlighters/FunctionCallHighlighter.kt | 0 .../highlighters/TypeHighlighter.kt | 0 .../VariableReferenceHighlighter.kt | 0 ...CompilerPluginsHighlightingMetaInfoTest.kt | 0 .../AbstractK2HighlightExitPointsTest.kt | 0 .../AbstractK2HighlightingMetaInfoTest.kt | 0 ...K2HighlightingMetaInfoWithExtensionTest.kt | 0 .../AbstractOutsiderHighlightingTest.kt | 0 ...ginsHighlightingMetaInfoTestGenerated.java | 14 +-- .../K2HighlightExitPointsTestGenerated.java | 86 +++++++------- .../K2HighlightingMetaInfoTestGenerated.java | 110 +++++++++--------- ...ingMetaInfoWithExtensionTestGenerated.java | 6 +- .../K2HighlightingOutsideSourceSetTest.kt | 0 .../OrphanOutsiderHighlightingTest.kt | 0 .../OutsiderHighlightingTestGenerated.java | 2 +- .../testData/outsider/badDiff/diff/main.kt | 0 .../testData/outsider/badDiff/src/lib.kt | 0 .../testData/outsider/badDiff/src/main.kt | 0 .../testData/outsider/badSource/diff/main.kt | 0 .../testData/outsider/badSource/src/lib.kt | 0 .../testData/outsider/badSource/src/main.kt | 0 .../outsider/badSourceDiff/diff/main.kt | 0 .../outsider/badSourceDiff/src/lib.kt | 0 .../outsider/badSourceDiff/src/main.kt | 0 .../outsider/circularDependency/diff/main.kt | 0 .../outsider/circularDependency/diff/other.kt | 0 .../outsider/circularDependency/src/lib.kt | 0 .../outsider/circularDependency/src/main.kt | 0 .../outsider/circularDependency/src/other.kt | 0 .../kotlin.highlighting.shared.iml | 46 ++++++++ .../KotlinBaseHighlightingBundle.properties | 0 ...KotlinHighlightExitPointsHandlerFactory.kt | 0 .../base/highlighting/HighlightingFactory.kt | 0 .../KotlinBaseHighlightingBundle.kt | 0 .../KotlinBeforeResolveHighlightingPass.kt | 0 .../KotlinHighlighterAttributeUtils.kt | 0 .../highlighting/KotlinHighlightingUtils.kt | 0 .../KotlinSyntaxHighlighterFactory.kt | 0 .../base/highlighting/dsl/DslStyleUtils.kt | 0 .../visitor/AbstractHighlightingVisitor.kt | 0 .../AbstractHighlightingPassBase.kt | 0 .../BeforeResolveHighlightingVisitor.kt | 0 .../highlighter/KotlinColorSettingsPage.kt | 0 .../KotlinHighlightInfoTypeSemanticNames.kt | 0 .../idea/highlighter/KotlinHighlighter.java | 0 .../highlighter/KotlinHighlightingColors.java | 0 .../highlighter/KotlinHighlightingLexer.java | 0 .../KotlinProblemHighlightFilter.kt | 0 plugins/kotlin/idea/kotlin.idea.iml | 2 +- .../kotlin/idea/tests/kotlin.idea.tests.iml | 3 +- .../intellij.kotlin.plugin.community.main.iml | 5 +- plugins/kotlin/jvm/kotlin.jvm.iml | 2 +- .../kotlin.k2.fe10-bindings.iml | 2 +- plugins/kotlin/plugin/k1/kotlin.plugin.k1.iml | 3 +- plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml | 4 +- .../jvm/kotlin.run-configurations.jvm.iml | 2 +- .../kotlin.scripting-support.iml | 2 +- .../kotlin.util.test-generator-fir.iml | 2 +- .../GenerateK2HighlighterTests.kt | 4 +- 82 files changed, 195 insertions(+), 138 deletions(-) rename plugins/kotlin/{base/highlighting/kotlin.base.highlighting.iml => highlighting/highlighting-k1/kotlin.highlighting.k1.iml} (73%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-k1}/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinChangeLocalityDetector.kt (100%) rename plugins/kotlin/highlighting/{kotlin.highlighting.iml => highlighting-k2/kotlin.highlighting.k2.iml} (97%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/resources/kotlin.highlighting.xml (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/KotlinCallHighlighterExtension.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/KotlinDiagnosticHighlightVisitor.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/KotlinHighlightExitPointsHandlerFactory.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/KotlinSemanticHighlightingPass.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/KotlinUnusedHighlightingVisitor.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/beforeResolve/AnnotationEntryHighlightingVisitor.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/beforeResolve/DeclarationHighlightingVisitor.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/highlighters/AfterResolveHighlighter.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/highlighters/DslHighlighter.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/highlighters/ExpressionsSmartcastHighlighter.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/highlighters/FunctionCallHighlighter.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/highlighters/TypeHighlighter.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/src/org/jetbrains/kotlin/idea/highlighting/highlighters/VariableReferenceHighlighter.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2BundledCompilerPluginsHighlightingMetaInfoTest.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightExitPointsTest.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightingMetaInfoTest.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightingMetaInfoWithExtensionTest.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractOutsiderHighlightingTest.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/K2BundledCompilerPluginsHighlightingMetaInfoTestGenerated.java (68%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java (62%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java (61%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoWithExtensionTestGenerated.java (83%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingOutsideSourceSetTest.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/OrphanOutsiderHighlightingTest.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/test/org/jetbrains/kotlin/idea/k2/highlighting/OutsiderHighlightingTestGenerated.java (96%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/badDiff/diff/main.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/badDiff/src/lib.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/badDiff/src/main.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/badSource/diff/main.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/badSource/src/lib.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/badSource/src/main.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/badSourceDiff/diff/main.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/badSourceDiff/src/lib.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/badSourceDiff/src/main.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/circularDependency/diff/main.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/circularDependency/diff/other.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/circularDependency/src/lib.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/circularDependency/src/main.kt (100%) rename plugins/kotlin/highlighting/{ => highlighting-k2}/testData/outsider/circularDependency/src/other.kt (100%) create mode 100644 plugins/kotlin/highlighting/highlighting-shared/kotlin.highlighting.shared.iml rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/resources/messages/KotlinBaseHighlightingBundle.properties (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/base/highlighting/HighlightingFactory.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinBaseHighlightingBundle.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinBeforeResolveHighlightingPass.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinHighlighterAttributeUtils.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinHighlightingUtils.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinSyntaxHighlighterFactory.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/base/highlighting/dsl/DslStyleUtils.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/base/highlighting/visitor/AbstractHighlightingVisitor.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/highlighter/AbstractHighlightingPassBase.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/highlighter/BeforeResolveHighlightingVisitor.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/highlighter/KotlinColorSettingsPage.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightInfoTypeSemanticNames.kt (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlighter.java (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingColors.java (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingLexer.java (100%) rename plugins/kotlin/{base/highlighting => highlighting/highlighting-shared}/src/org/jetbrains/kotlin/idea/highlighter/KotlinProblemHighlightFilter.kt (100%) diff --git a/plugins/kotlin/all-tests-fir/kotlin.fir-all-tests.iml b/plugins/kotlin/all-tests-fir/kotlin.fir-all-tests.iml index 2561c1e5ebc9..60ee0e02de75 100644 --- a/plugins/kotlin/all-tests-fir/kotlin.fir-all-tests.iml +++ b/plugins/kotlin/all-tests-fir/kotlin.fir-all-tests.iml @@ -39,7 +39,7 @@ - + diff --git a/plugins/kotlin/base/fe10/highlighting/kotlin.base.fe10.highlighting.iml b/plugins/kotlin/base/fe10/highlighting/kotlin.base.fe10.highlighting.iml index b445991be916..59338247544c 100644 --- a/plugins/kotlin/base/fe10/highlighting/kotlin.base.fe10.highlighting.iml +++ b/plugins/kotlin/base/fe10/highlighting/kotlin.base.fe10.highlighting.iml @@ -18,7 +18,7 @@ - + diff --git a/plugins/kotlin/code-insight/inspections-k2/kotlin.code-insight.inspections-k2.iml b/plugins/kotlin/code-insight/inspections-k2/kotlin.code-insight.inspections-k2.iml index 5ae409020ec8..0501d6cc3980 100644 --- a/plugins/kotlin/code-insight/inspections-k2/kotlin.code-insight.inspections-k2.iml +++ b/plugins/kotlin/code-insight/inspections-k2/kotlin.code-insight.inspections-k2.iml @@ -50,7 +50,8 @@ - - + + + \ No newline at end of file diff --git a/plugins/kotlin/code-insight/inspections-k2/tests/kotlin.code-insight.inspections-k2.tests.iml b/plugins/kotlin/code-insight/inspections-k2/tests/kotlin.code-insight.inspections-k2.tests.iml index edcf41d70ad6..d80d527e43f3 100644 --- a/plugins/kotlin/code-insight/inspections-k2/tests/kotlin.code-insight.inspections-k2.tests.iml +++ b/plugins/kotlin/code-insight/inspections-k2/tests/kotlin.code-insight.inspections-k2.tests.iml @@ -37,7 +37,7 @@ - + diff --git a/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml b/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml index 0d6cffb100f4..54ceb23dfc15 100644 --- a/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml +++ b/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml @@ -44,8 +44,8 @@ - - + + diff --git a/plugins/kotlin/code-insight/live-templates-shared/kotlin.code-insight.live-templates-shared.iml b/plugins/kotlin/code-insight/live-templates-shared/kotlin.code-insight.live-templates-shared.iml index 97ad29425ac6..9078fa8069b1 100644 --- a/plugins/kotlin/code-insight/live-templates-shared/kotlin.code-insight.live-templates-shared.iml +++ b/plugins/kotlin/code-insight/live-templates-shared/kotlin.code-insight.live-templates-shared.iml @@ -32,7 +32,7 @@ - + diff --git a/plugins/kotlin/core/kotlin.core.iml b/plugins/kotlin/core/kotlin.core.iml index 24906556965a..8629ece1537f 100644 --- a/plugins/kotlin/core/kotlin.core.iml +++ b/plugins/kotlin/core/kotlin.core.iml @@ -36,7 +36,7 @@ - + diff --git a/plugins/kotlin/fir/kotlin.fir.iml b/plugins/kotlin/fir/kotlin.fir.iml index 5d5b7cc88772..c1ca3ee8949e 100644 --- a/plugins/kotlin/fir/kotlin.fir.iml +++ b/plugins/kotlin/fir/kotlin.fir.iml @@ -52,7 +52,7 @@ - + diff --git a/plugins/kotlin/frontend-independent/kotlin.fir.frontend-independent.iml b/plugins/kotlin/frontend-independent/kotlin.fir.frontend-independent.iml index bb7a55b7c09d..7d0e4433d4f0 100644 --- a/plugins/kotlin/frontend-independent/kotlin.fir.frontend-independent.iml +++ b/plugins/kotlin/frontend-independent/kotlin.fir.frontend-independent.iml @@ -17,7 +17,7 @@ - + diff --git a/plugins/kotlin/base/highlighting/kotlin.base.highlighting.iml b/plugins/kotlin/highlighting/highlighting-k1/kotlin.highlighting.k1.iml similarity index 73% rename from plugins/kotlin/base/highlighting/kotlin.base.highlighting.iml rename to plugins/kotlin/highlighting/highlighting-k1/kotlin.highlighting.k1.iml index 3874bcbd6e14..7007cb111342 100644 --- a/plugins/kotlin/base/highlighting/kotlin.base.highlighting.iml +++ b/plugins/kotlin/highlighting/highlighting-k1/kotlin.highlighting.k1.iml @@ -8,17 +8,15 @@ + - - - @@ -27,5 +25,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinChangeLocalityDetector.kt b/plugins/kotlin/highlighting/highlighting-k1/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinChangeLocalityDetector.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinChangeLocalityDetector.kt rename to plugins/kotlin/highlighting/highlighting-k1/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinChangeLocalityDetector.kt diff --git a/plugins/kotlin/highlighting/kotlin.highlighting.iml b/plugins/kotlin/highlighting/highlighting-k2/kotlin.highlighting.k2.iml similarity index 97% rename from plugins/kotlin/highlighting/kotlin.highlighting.iml rename to plugins/kotlin/highlighting/highlighting-k2/kotlin.highlighting.k2.iml index da4967b22830..2aa9c5ae09d1 100644 --- a/plugins/kotlin/highlighting/kotlin.highlighting.iml +++ b/plugins/kotlin/highlighting/highlighting-k2/kotlin.highlighting.k2.iml @@ -29,7 +29,7 @@ - + diff --git a/plugins/kotlin/highlighting/resources/kotlin.highlighting.xml b/plugins/kotlin/highlighting/highlighting-k2/resources/kotlin.highlighting.xml similarity index 100% rename from plugins/kotlin/highlighting/resources/kotlin.highlighting.xml rename to plugins/kotlin/highlighting/highlighting-k2/resources/kotlin.highlighting.xml diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/KotlinCallHighlighterExtension.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinCallHighlighterExtension.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/KotlinCallHighlighterExtension.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinCallHighlighterExtension.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/KotlinDiagnosticHighlightVisitor.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinDiagnosticHighlightVisitor.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/KotlinDiagnosticHighlightVisitor.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinDiagnosticHighlightVisitor.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/KotlinHighlightExitPointsHandlerFactory.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinHighlightExitPointsHandlerFactory.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/KotlinHighlightExitPointsHandlerFactory.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinHighlightExitPointsHandlerFactory.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/KotlinSemanticHighlightingPass.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinSemanticHighlightingPass.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/KotlinSemanticHighlightingPass.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinSemanticHighlightingPass.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/KotlinUnusedHighlightingVisitor.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinUnusedHighlightingVisitor.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/KotlinUnusedHighlightingVisitor.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinUnusedHighlightingVisitor.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/beforeResolve/AnnotationEntryHighlightingVisitor.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/beforeResolve/AnnotationEntryHighlightingVisitor.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/beforeResolve/AnnotationEntryHighlightingVisitor.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/beforeResolve/AnnotationEntryHighlightingVisitor.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/beforeResolve/DeclarationHighlightingVisitor.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/beforeResolve/DeclarationHighlightingVisitor.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/beforeResolve/DeclarationHighlightingVisitor.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/beforeResolve/DeclarationHighlightingVisitor.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/AfterResolveHighlighter.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/AfterResolveHighlighter.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/AfterResolveHighlighter.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/AfterResolveHighlighter.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/DslHighlighter.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/DslHighlighter.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/DslHighlighter.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/DslHighlighter.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/ExpressionsSmartcastHighlighter.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/ExpressionsSmartcastHighlighter.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/ExpressionsSmartcastHighlighter.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/ExpressionsSmartcastHighlighter.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/FunctionCallHighlighter.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/FunctionCallHighlighter.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/FunctionCallHighlighter.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/FunctionCallHighlighter.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/TypeHighlighter.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/TypeHighlighter.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/TypeHighlighter.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/TypeHighlighter.kt diff --git a/plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/VariableReferenceHighlighter.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/VariableReferenceHighlighter.kt similarity index 100% rename from plugins/kotlin/highlighting/src/org/jetbrains/kotlin/idea/highlighting/highlighters/VariableReferenceHighlighter.kt rename to plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/highlighters/VariableReferenceHighlighter.kt diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2BundledCompilerPluginsHighlightingMetaInfoTest.kt b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2BundledCompilerPluginsHighlightingMetaInfoTest.kt similarity index 100% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2BundledCompilerPluginsHighlightingMetaInfoTest.kt rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2BundledCompilerPluginsHighlightingMetaInfoTest.kt diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightExitPointsTest.kt b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightExitPointsTest.kt similarity index 100% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightExitPointsTest.kt rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightExitPointsTest.kt diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightingMetaInfoTest.kt b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightingMetaInfoTest.kt similarity index 100% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightingMetaInfoTest.kt rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightingMetaInfoTest.kt diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightingMetaInfoWithExtensionTest.kt b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightingMetaInfoWithExtensionTest.kt similarity index 100% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightingMetaInfoWithExtensionTest.kt rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractK2HighlightingMetaInfoWithExtensionTest.kt diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractOutsiderHighlightingTest.kt b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractOutsiderHighlightingTest.kt similarity index 100% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractOutsiderHighlightingTest.kt rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/AbstractOutsiderHighlightingTest.kt diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2BundledCompilerPluginsHighlightingMetaInfoTestGenerated.java b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2BundledCompilerPluginsHighlightingMetaInfoTestGenerated.java similarity index 68% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2BundledCompilerPluginsHighlightingMetaInfoTestGenerated.java rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2BundledCompilerPluginsHighlightingMetaInfoTestGenerated.java index 04846a10c932..94b88e7b4bb3 100644 --- a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2BundledCompilerPluginsHighlightingMetaInfoTestGenerated.java +++ b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2BundledCompilerPluginsHighlightingMetaInfoTestGenerated.java @@ -14,10 +14,10 @@ import org.junit.runner.RunWith; * DO NOT MODIFY MANUALLY. */ @SuppressWarnings("all") -@TestRoot("highlighting") +@TestRoot("highlighting/highlighting-k2") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -@TestMetadata("../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins") +@TestMetadata("../../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins") public class K2BundledCompilerPluginsHighlightingMetaInfoTestGenerated extends AbstractK2BundledCompilerPluginsHighlightingMetaInfoTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); @@ -25,26 +25,26 @@ public class K2BundledCompilerPluginsHighlightingMetaInfoTestGenerated extends A @TestMetadata("allOpen.kt") public void testAllOpen() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins/allOpen.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins/allOpen.kt"); } @TestMetadata("lombok.kt") public void testLombok() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins/lombok.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins/lombok.kt"); } @TestMetadata("parcelize.kt") public void testParcelize() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins/parcelize.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins/parcelize.kt"); } @TestMetadata("samWithReceiver.kt") public void testSamWithReceiver() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins/samWithReceiver.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins/samWithReceiver.kt"); } @TestMetadata("serialize.kt") public void testSerialize() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins/serialize.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfoWithBundledCompilerPlugins/serialize.kt"); } } diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java similarity index 62% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java index e0dca5e710ee..4bf1b603f640 100644 --- a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java +++ b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java @@ -14,10 +14,10 @@ import org.junit.runner.RunWith; * DO NOT MODIFY MANUALLY. */ @SuppressWarnings("all") -@TestRoot("highlighting") +@TestRoot("highlighting/highlighting-k2") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -@TestMetadata("../idea/tests/testData/exitPoints") +@TestMetadata("../../idea/tests/testData/exitPoints") public class K2HighlightExitPointsTestGenerated extends AbstractK2HighlightExitPointsTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); @@ -25,206 +25,206 @@ public class K2HighlightExitPointsTestGenerated extends AbstractK2HighlightExitP @TestMetadata("anonymousFunction.kt") public void testAnonymousFunction() throws Exception { - runTest("../idea/tests/testData/exitPoints/anonymousFunction.kt"); + runTest("../../idea/tests/testData/exitPoints/anonymousFunction.kt"); } @TestMetadata("anonymousFunction2.kt") public void testAnonymousFunction2() throws Exception { - runTest("../idea/tests/testData/exitPoints/anonymousFunction2.kt"); + runTest("../../idea/tests/testData/exitPoints/anonymousFunction2.kt"); } @TestMetadata("funKeyword.kt") public void testFunKeyword() throws Exception { - runTest("../idea/tests/testData/exitPoints/funKeyword.kt"); + runTest("../../idea/tests/testData/exitPoints/funKeyword.kt"); } @TestMetadata("funKeyword2.kt") public void testFunKeyword2() throws Exception { - runTest("../idea/tests/testData/exitPoints/funKeyword2.kt"); + runTest("../../idea/tests/testData/exitPoints/funKeyword2.kt"); } @TestMetadata("funKeyword3.kt") public void testFunKeyword3() throws Exception { - runTest("../idea/tests/testData/exitPoints/funKeyword3.kt"); + runTest("../../idea/tests/testData/exitPoints/funKeyword3.kt"); } @TestMetadata("funKeyword31.kt") public void testFunKeyword31() throws Exception { - runTest("../idea/tests/testData/exitPoints/funKeyword31.kt"); + runTest("../../idea/tests/testData/exitPoints/funKeyword31.kt"); } @TestMetadata("funName.kt") public void testFunName() throws Exception { - runTest("../idea/tests/testData/exitPoints/funName.kt"); + runTest("../../idea/tests/testData/exitPoints/funName.kt"); } @TestMetadata("getter.kt") public void testGetter() throws Exception { - runTest("../idea/tests/testData/exitPoints/getter.kt"); + runTest("../../idea/tests/testData/exitPoints/getter.kt"); } @TestMetadata("getter2.kt") public void testGetter2() throws Exception { - runTest("../idea/tests/testData/exitPoints/getter2.kt"); + runTest("../../idea/tests/testData/exitPoints/getter2.kt"); } @TestMetadata("getter3.kt") public void testGetter3() throws Exception { - runTest("../idea/tests/testData/exitPoints/getter3.kt"); + runTest("../../idea/tests/testData/exitPoints/getter3.kt"); } @TestMetadata("inLambda.kt") public void testInLambda() throws Exception { - runTest("../idea/tests/testData/exitPoints/inLambda.kt"); + runTest("../../idea/tests/testData/exitPoints/inLambda.kt"); } @TestMetadata("inLambda1.kt") public void testInLambda1() throws Exception { - runTest("../idea/tests/testData/exitPoints/inLambda1.kt"); + runTest("../../idea/tests/testData/exitPoints/inLambda1.kt"); } @TestMetadata("inLambda2.kt") public void testInLambda2() throws Exception { - runTest("../idea/tests/testData/exitPoints/inLambda2.kt"); + runTest("../../idea/tests/testData/exitPoints/inLambda2.kt"); } @TestMetadata("inLambdaLastStatement1.kt") public void testInLambdaLastStatement1() throws Exception { - runTest("../idea/tests/testData/exitPoints/inLambdaLastStatement1.kt"); + runTest("../../idea/tests/testData/exitPoints/inLambdaLastStatement1.kt"); } @TestMetadata("inLambdaLastStatement2.kt") public void testInLambdaLastStatement2() throws Exception { - runTest("../idea/tests/testData/exitPoints/inLambdaLastStatement2.kt"); + runTest("../../idea/tests/testData/exitPoints/inLambdaLastStatement2.kt"); } @TestMetadata("inLambdaLastStatement3.kt") public void testInLambdaLastStatement3() throws Exception { - runTest("../idea/tests/testData/exitPoints/inLambdaLastStatement3.kt"); + runTest("../../idea/tests/testData/exitPoints/inLambdaLastStatement3.kt"); } @TestMetadata("inLambdaLastStatement4.kt") public void testInLambdaLastStatement4() throws Exception { - runTest("../idea/tests/testData/exitPoints/inLambdaLastStatement4.kt"); + runTest("../../idea/tests/testData/exitPoints/inLambdaLastStatement4.kt"); } @TestMetadata("inLambdaLastStatement5.kt") public void testInLambdaLastStatement5() throws Exception { - runTest("../idea/tests/testData/exitPoints/inLambdaLastStatement5.kt"); + runTest("../../idea/tests/testData/exitPoints/inLambdaLastStatement5.kt"); } @TestMetadata("inLambdaLastStatement6.kt") public void testInLambdaLastStatement6() throws Exception { - runTest("../idea/tests/testData/exitPoints/inLambdaLastStatement6.kt"); + runTest("../../idea/tests/testData/exitPoints/inLambdaLastStatement6.kt"); } @TestMetadata("inline1.kt") public void testInline1() throws Exception { - runTest("../idea/tests/testData/exitPoints/inline1.kt"); + runTest("../../idea/tests/testData/exitPoints/inline1.kt"); } @TestMetadata("inline2.kt") public void testInline2() throws Exception { - runTest("../idea/tests/testData/exitPoints/inline2.kt"); + runTest("../../idea/tests/testData/exitPoints/inline2.kt"); } @TestMetadata("inline3.kt") public void testInline3() throws Exception { - runTest("../idea/tests/testData/exitPoints/inline3.kt"); + runTest("../../idea/tests/testData/exitPoints/inline3.kt"); } @TestMetadata("inlineLocalReturn1.kt") public void testInlineLocalReturn1() throws Exception { - runTest("../idea/tests/testData/exitPoints/inlineLocalReturn1.kt"); + runTest("../../idea/tests/testData/exitPoints/inlineLocalReturn1.kt"); } @TestMetadata("inlineLocalReturn2.kt") public void testInlineLocalReturn2() throws Exception { - runTest("../idea/tests/testData/exitPoints/inlineLocalReturn2.kt"); + runTest("../../idea/tests/testData/exitPoints/inlineLocalReturn2.kt"); } @TestMetadata("inlineLocalReturn3.kt") public void testInlineLocalReturn3() throws Exception { - runTest("../idea/tests/testData/exitPoints/inlineLocalReturn3.kt"); + runTest("../../idea/tests/testData/exitPoints/inlineLocalReturn3.kt"); } @TestMetadata("inlineWithNoInlineParam.kt") public void testInlineWithNoInlineParam() throws Exception { - runTest("../idea/tests/testData/exitPoints/inlineWithNoInlineParam.kt"); + runTest("../../idea/tests/testData/exitPoints/inlineWithNoInlineParam.kt"); } @TestMetadata("invalidReturn.kt") public void testInvalidReturn() throws Exception { - runTest("../idea/tests/testData/exitPoints/invalidReturn.kt"); + runTest("../../idea/tests/testData/exitPoints/invalidReturn.kt"); } @TestMetadata("invalidThrow.kt") public void testInvalidThrow() throws Exception { - runTest("../idea/tests/testData/exitPoints/invalidThrow.kt"); + runTest("../../idea/tests/testData/exitPoints/invalidThrow.kt"); } @TestMetadata("localFunction1.kt") public void testLocalFunction1() throws Exception { - runTest("../idea/tests/testData/exitPoints/localFunction1.kt"); + runTest("../../idea/tests/testData/exitPoints/localFunction1.kt"); } @TestMetadata("localFunction2.kt") public void testLocalFunction2() throws Exception { - runTest("../idea/tests/testData/exitPoints/localFunction2.kt"); + runTest("../../idea/tests/testData/exitPoints/localFunction2.kt"); } @TestMetadata("localFunctionThrow.kt") public void testLocalFunctionThrow() throws Exception { - runTest("../idea/tests/testData/exitPoints/localFunctionThrow.kt"); + runTest("../../idea/tests/testData/exitPoints/localFunctionThrow.kt"); } @TestMetadata("notInline1.kt") public void testNotInline1() throws Exception { - runTest("../idea/tests/testData/exitPoints/notInline1.kt"); + runTest("../../idea/tests/testData/exitPoints/notInline1.kt"); } @TestMetadata("notInline2.kt") public void testNotInline2() throws Exception { - runTest("../idea/tests/testData/exitPoints/notInline2.kt"); + runTest("../../idea/tests/testData/exitPoints/notInline2.kt"); } @TestMetadata("notInline3.kt") public void testNotInline3() throws Exception { - runTest("../idea/tests/testData/exitPoints/notInline3.kt"); + runTest("../../idea/tests/testData/exitPoints/notInline3.kt"); } @TestMetadata("notReturnedLabeledExpression.kt") public void testNotReturnedLabeledExpression() throws Exception { - runTest("../idea/tests/testData/exitPoints/notReturnedLabeledExpression.kt"); + runTest("../../idea/tests/testData/exitPoints/notReturnedLabeledExpression.kt"); } @TestMetadata("returnIfStatement.kt") public void testReturnIfStatement() throws Exception { - runTest("../idea/tests/testData/exitPoints/returnIfStatement.kt"); + runTest("../../idea/tests/testData/exitPoints/returnIfStatement.kt"); } @TestMetadata("returnTryStatement.kt") public void testReturnTryStatement() throws Exception { - runTest("../idea/tests/testData/exitPoints/returnTryStatement.kt"); + runTest("../../idea/tests/testData/exitPoints/returnTryStatement.kt"); } @TestMetadata("returnWhenStatement.kt") public void testReturnWhenStatement() throws Exception { - runTest("../idea/tests/testData/exitPoints/returnWhenStatement.kt"); + runTest("../../idea/tests/testData/exitPoints/returnWhenStatement.kt"); } @TestMetadata("simple.kt") public void testSimple() throws Exception { - runTest("../idea/tests/testData/exitPoints/simple.kt"); + runTest("../../idea/tests/testData/exitPoints/simple.kt"); } @TestMetadata("throw1.kt") public void testThrow1() throws Exception { - runTest("../idea/tests/testData/exitPoints/throw1.kt"); + runTest("../../idea/tests/testData/exitPoints/throw1.kt"); } @TestMetadata("throw2.kt") public void testThrow2() throws Exception { - runTest("../idea/tests/testData/exitPoints/throw2.kt"); + runTest("../../idea/tests/testData/exitPoints/throw2.kt"); } } diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java similarity index 61% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java index a1db93b9184a..94a93eb3a87e 100644 --- a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java +++ b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java @@ -14,13 +14,13 @@ import org.junit.runner.RunWith; * DO NOT MODIFY MANUALLY. */ @SuppressWarnings("all") -@TestRoot("highlighting") +@TestRoot("highlighting/highlighting-k2") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -@TestMetadata("../idea/tests/testData/highlighterMetaInfo") +@TestMetadata("../../idea/tests/testData/highlighterMetaInfo") public abstract class K2HighlightingMetaInfoTestGenerated extends AbstractK2HighlightingMetaInfoTest { @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../idea/tests/testData/highlighterMetaInfo/diagnostics") + @TestMetadata("../../idea/tests/testData/highlighterMetaInfo/diagnostics") public static class Diagnostics extends AbstractK2HighlightingMetaInfoTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); @@ -28,22 +28,22 @@ public abstract class K2HighlightingMetaInfoTestGenerated extends AbstractK2High @TestMetadata("classRedeclaration.kt") public void testClassRedeclaration() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt"); } @TestMetadata("javaCodeInKotlinFile1.kt") public void testJavaCodeInKotlinFile1() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt"); } @TestMetadata("mppIsNotEnabled.kt") public void testMppIsNotEnabled() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt"); } } @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../idea/tests/testData/highlighterMetaInfo/dsl") + @TestMetadata("../../idea/tests/testData/highlighterMetaInfo/dsl") public static class Dsl extends AbstractK2HighlightingMetaInfoTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); @@ -51,37 +51,37 @@ public abstract class K2HighlightingMetaInfoTestGenerated extends AbstractK2High @TestMetadata("AnnotatedTypeParameter.kt") public void testAnnotatedTypeParameter() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/dsl/AnnotatedTypeParameter.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/dsl/AnnotatedTypeParameter.kt"); } @TestMetadata("AnnotatedTypeSpecifier.kt") public void testAnnotatedTypeSpecifier() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/dsl/AnnotatedTypeSpecifier.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/dsl/AnnotatedTypeSpecifier.kt"); } @TestMetadata("ImplementsDslInterface.kt") public void testImplementsDslInterface() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/dsl/ImplementsDslInterface.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/dsl/ImplementsDslInterface.kt"); } @TestMetadata("NestedReceivers.kt") public void testNestedReceivers() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/dsl/NestedReceivers.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/dsl/NestedReceivers.kt"); } @TestMetadata("RegularDsl.kt") public void testRegularDsl() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/dsl/RegularDsl.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/dsl/RegularDsl.kt"); } @TestMetadata("SubclassOfDslClass.kt") public void testSubclassOfDslClass() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/dsl/SubclassOfDslClass.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/dsl/SubclassOfDslClass.kt"); } } @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../idea/tests/testData/highlighterMetaInfo/smartCasts") + @TestMetadata("../../idea/tests/testData/highlighterMetaInfo/smartCasts") public static class SmartCasts extends AbstractK2HighlightingMetaInfoTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); @@ -89,47 +89,47 @@ public abstract class K2HighlightingMetaInfoTestGenerated extends AbstractK2High @TestMetadata("Explicit.kt") public void testExplicit() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/smartCasts/Explicit.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/smartCasts/Explicit.kt"); } @TestMetadata("Explicit_qualifiedCalls.kt") public void testExplicit_qualifiedCalls() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/smartCasts/Explicit_qualifiedCalls.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/smartCasts/Explicit_qualifiedCalls.kt"); } @TestMetadata("Explicit_withInvokeCall.kt") public void testExplicit_withInvokeCall() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/smartCasts/Explicit_withInvokeCall.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/smartCasts/Explicit_withInvokeCall.kt"); } @TestMetadata("ImplicitAndExplicit_functions.kt") public void testImplicitAndExplicit_functions() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/smartCasts/ImplicitAndExplicit_functions.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/smartCasts/ImplicitAndExplicit_functions.kt"); } @TestMetadata("ImplicitAndExplicit_operators.kt") public void testImplicitAndExplicit_operators() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/smartCasts/ImplicitAndExplicit_operators.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/smartCasts/ImplicitAndExplicit_operators.kt"); } @TestMetadata("ImplicitAndExplicit_properties.kt") public void testImplicitAndExplicit_properties() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/smartCasts/ImplicitAndExplicit_properties.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/smartCasts/ImplicitAndExplicit_properties.kt"); } @TestMetadata("Implicit_stable.kt") public void testImplicit_stable() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/smartCasts/Implicit_stable.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/smartCasts/Implicit_stable.kt"); } @TestMetadata("Invokes.kt") public void testInvokes() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/smartCasts/Invokes.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/smartCasts/Invokes.kt"); } } @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../idea/tests/testData/highlighterMetaInfo") + @TestMetadata("../../idea/tests/testData/highlighterMetaInfo") public static class Uncategorized extends AbstractK2HighlightingMetaInfoTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); @@ -137,147 +137,147 @@ public abstract class K2HighlightingMetaInfoTestGenerated extends AbstractK2High @TestMetadata("Annotations.kt") public void testAnnotations() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/Annotations.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/Annotations.kt"); } @TestMetadata("AutoCreatedItParameter.kt") public void testAutoCreatedItParameter() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/AutoCreatedItParameter.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/AutoCreatedItParameter.kt"); } @TestMetadata("deprecation.kt") public void testDeprecation() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/deprecation.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/deprecation.kt"); } @TestMetadata("Destructuring.kt") public void testDestructuring() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/Destructuring.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/Destructuring.kt"); } @TestMetadata("Enums.kt") public void testEnums() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/Enums.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/Enums.kt"); } @TestMetadata("ExplicitInvokeCall.kt") public void testExplicitInvokeCall() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/ExplicitInvokeCall.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/ExplicitInvokeCall.kt"); } @TestMetadata("Field.kt") public void testField() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/Field.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/Field.kt"); } @TestMetadata("Functions.kt") public void testFunctions() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/Functions.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/Functions.kt"); } @TestMetadata("InvokeCall.kt") public void testInvokeCall() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/InvokeCall.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/InvokeCall.kt"); } @TestMetadata("javaFields.kt") public void testJavaFields() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/javaFields.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/javaFields.kt"); } @TestMetadata("JavaRecord.kt") public void testJavaRecord() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/JavaRecord.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/JavaRecord.kt"); } @TestMetadata("javaStaticFields.kt") public void testJavaStaticFields() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/javaStaticFields.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/javaStaticFields.kt"); } @TestMetadata("JavaTypes.kt") public void testJavaTypes() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/JavaTypes.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/JavaTypes.kt"); } @TestMetadata("KDoc.kt") public void testKDoc() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/KDoc.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/KDoc.kt"); } @TestMetadata("KotlinAnnotationsInJava.kt") public void testKotlinAnnotationsInJava() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/KotlinAnnotationsInJava.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/KotlinAnnotationsInJava.kt"); } @TestMetadata("KotlinInjection.kt") public void testKotlinInjection() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/KotlinInjection.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/KotlinInjection.kt"); } @TestMetadata("Labels.kt") public void testLabels() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/Labels.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/Labels.kt"); } @TestMetadata("NamedArguments.kt") public void testNamedArguments() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/NamedArguments.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/NamedArguments.kt"); } @TestMetadata("NonNullAssertion.kt") public void testNonNullAssertion() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/NonNullAssertion.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/NonNullAssertion.kt"); } @TestMetadata("Object.kt") public void testObject() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/Object.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/Object.kt"); } @TestMetadata("PropertiesWithPropertyDeclarations.kt") public void testPropertiesWithPropertyDeclarations() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/PropertiesWithPropertyDeclarations.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/PropertiesWithPropertyDeclarations.kt"); } @TestMetadata("Suspend.kt") public void testSuspend() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/Suspend.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/Suspend.kt"); } @TestMetadata("SyntheticExtensionProperty.kt") public void testSyntheticExtensionProperty() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/SyntheticExtensionProperty.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/SyntheticExtensionProperty.kt"); } @TestMetadata("Todo.kt") public void testTodo() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/Todo.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/Todo.kt"); } @TestMetadata("TypeAlias.kt") public void testTypeAlias() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/TypeAlias.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/TypeAlias.kt"); } @TestMetadata("TypesAndAnnotations.kt") public void testTypesAndAnnotations() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/TypesAndAnnotations.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/TypesAndAnnotations.kt"); } @TestMetadata("Variables.kt") public void testVariables() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/Variables.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/Variables.kt"); } @TestMetadata("VariablesAsFunctions.kt") public void testVariablesAsFunctions() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/VariablesAsFunctions.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/VariablesAsFunctions.kt"); } } @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("../idea/tests/testData/highlighterMetaInfo/unresolved") + @TestMetadata("../../idea/tests/testData/highlighterMetaInfo/unresolved") public static class Unresolved extends AbstractK2HighlightingMetaInfoTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); @@ -285,17 +285,17 @@ public abstract class K2HighlightingMetaInfoTestGenerated extends AbstractK2High @TestMetadata("unresolvedImport.kt") public void testUnresolvedImport() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/unresolved/unresolvedImport.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/unresolved/unresolvedImport.kt"); } @TestMetadata("unresolvedLabel.kt") public void testUnresolvedLabel() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/unresolved/unresolvedLabel.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/unresolved/unresolvedLabel.kt"); } @TestMetadata("unresolvedReference.kt") public void testUnresolvedReference() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfo/unresolved/unresolvedReference.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfo/unresolved/unresolvedReference.kt"); } } } diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoWithExtensionTestGenerated.java b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoWithExtensionTestGenerated.java similarity index 83% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoWithExtensionTestGenerated.java rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoWithExtensionTestGenerated.java index 5a3b88a8f7ee..6c2e66aeae5c 100644 --- a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoWithExtensionTestGenerated.java +++ b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoWithExtensionTestGenerated.java @@ -14,10 +14,10 @@ import org.junit.runner.RunWith; * DO NOT MODIFY MANUALLY. */ @SuppressWarnings("all") -@TestRoot("highlighting") +@TestRoot("highlighting/highlighting-k2") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -@TestMetadata("../idea/tests/testData/highlighterMetaInfoWithExtension") +@TestMetadata("../../idea/tests/testData/highlighterMetaInfoWithExtension") public class K2HighlightingMetaInfoWithExtensionTestGenerated extends AbstractK2HighlightingMetaInfoWithExtensionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); @@ -25,6 +25,6 @@ public class K2HighlightingMetaInfoWithExtensionTestGenerated extends AbstractK2 @TestMetadata("Functions.kt") public void testFunctions() throws Exception { - runTest("../idea/tests/testData/highlighterMetaInfoWithExtension/Functions.kt"); + runTest("../../idea/tests/testData/highlighterMetaInfoWithExtension/Functions.kt"); } } diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingOutsideSourceSetTest.kt b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingOutsideSourceSetTest.kt similarity index 100% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingOutsideSourceSetTest.kt rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingOutsideSourceSetTest.kt diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/OrphanOutsiderHighlightingTest.kt b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/OrphanOutsiderHighlightingTest.kt similarity index 100% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/OrphanOutsiderHighlightingTest.kt rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/OrphanOutsiderHighlightingTest.kt diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/OutsiderHighlightingTestGenerated.java b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/OutsiderHighlightingTestGenerated.java similarity index 96% rename from plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/OutsiderHighlightingTestGenerated.java rename to plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/OutsiderHighlightingTestGenerated.java index 3f77a9267787..c753a959b691 100644 --- a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/OutsiderHighlightingTestGenerated.java +++ b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/OutsiderHighlightingTestGenerated.java @@ -13,7 +13,7 @@ import org.junit.runner.RunWith; * DO NOT MODIFY MANUALLY. */ @SuppressWarnings("all") -@TestRoot("highlighting") +@TestRoot("highlighting/highlighting-k2") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("testData/outsider") diff --git a/plugins/kotlin/highlighting/testData/outsider/badDiff/diff/main.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badDiff/diff/main.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/badDiff/diff/main.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badDiff/diff/main.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/badDiff/src/lib.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badDiff/src/lib.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/badDiff/src/lib.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badDiff/src/lib.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/badDiff/src/main.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badDiff/src/main.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/badDiff/src/main.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badDiff/src/main.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/badSource/diff/main.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSource/diff/main.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/badSource/diff/main.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSource/diff/main.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/badSource/src/lib.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSource/src/lib.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/badSource/src/lib.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSource/src/lib.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/badSource/src/main.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSource/src/main.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/badSource/src/main.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSource/src/main.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/badSourceDiff/diff/main.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSourceDiff/diff/main.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/badSourceDiff/diff/main.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSourceDiff/diff/main.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/badSourceDiff/src/lib.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSourceDiff/src/lib.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/badSourceDiff/src/lib.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSourceDiff/src/lib.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/badSourceDiff/src/main.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSourceDiff/src/main.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/badSourceDiff/src/main.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/badSourceDiff/src/main.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/circularDependency/diff/main.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/circularDependency/diff/main.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/circularDependency/diff/main.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/circularDependency/diff/main.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/circularDependency/diff/other.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/circularDependency/diff/other.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/circularDependency/diff/other.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/circularDependency/diff/other.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/circularDependency/src/lib.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/circularDependency/src/lib.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/circularDependency/src/lib.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/circularDependency/src/lib.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/circularDependency/src/main.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/circularDependency/src/main.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/circularDependency/src/main.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/circularDependency/src/main.kt diff --git a/plugins/kotlin/highlighting/testData/outsider/circularDependency/src/other.kt b/plugins/kotlin/highlighting/highlighting-k2/testData/outsider/circularDependency/src/other.kt similarity index 100% rename from plugins/kotlin/highlighting/testData/outsider/circularDependency/src/other.kt rename to plugins/kotlin/highlighting/highlighting-k2/testData/outsider/circularDependency/src/other.kt diff --git a/plugins/kotlin/highlighting/highlighting-shared/kotlin.highlighting.shared.iml b/plugins/kotlin/highlighting/highlighting-shared/kotlin.highlighting.shared.iml new file mode 100644 index 000000000000..971834542d02 --- /dev/null +++ b/plugins/kotlin/highlighting/highlighting-shared/kotlin.highlighting.shared.iml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/kotlin/base/highlighting/resources/messages/KotlinBaseHighlightingBundle.properties b/plugins/kotlin/highlighting/highlighting-shared/resources/messages/KotlinBaseHighlightingBundle.properties similarity index 100% rename from plugins/kotlin/base/highlighting/resources/messages/KotlinBaseHighlightingBundle.properties rename to plugins/kotlin/highlighting/highlighting-shared/resources/messages/KotlinBaseHighlightingBundle.properties diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/HighlightingFactory.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/HighlightingFactory.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/HighlightingFactory.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/HighlightingFactory.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinBaseHighlightingBundle.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinBaseHighlightingBundle.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinBaseHighlightingBundle.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinBaseHighlightingBundle.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinBeforeResolveHighlightingPass.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinBeforeResolveHighlightingPass.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinBeforeResolveHighlightingPass.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinBeforeResolveHighlightingPass.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinHighlighterAttributeUtils.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinHighlighterAttributeUtils.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinHighlighterAttributeUtils.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinHighlighterAttributeUtils.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinHighlightingUtils.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinHighlightingUtils.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinHighlightingUtils.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinHighlightingUtils.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinSyntaxHighlighterFactory.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinSyntaxHighlighterFactory.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinSyntaxHighlighterFactory.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/KotlinSyntaxHighlighterFactory.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/dsl/DslStyleUtils.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/dsl/DslStyleUtils.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/dsl/DslStyleUtils.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/dsl/DslStyleUtils.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/visitor/AbstractHighlightingVisitor.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/visitor/AbstractHighlightingVisitor.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/base/highlighting/visitor/AbstractHighlightingVisitor.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/visitor/AbstractHighlightingVisitor.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/AbstractHighlightingPassBase.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/AbstractHighlightingPassBase.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/AbstractHighlightingPassBase.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/AbstractHighlightingPassBase.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/BeforeResolveHighlightingVisitor.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/BeforeResolveHighlightingVisitor.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/BeforeResolveHighlightingVisitor.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/BeforeResolveHighlightingVisitor.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinColorSettingsPage.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinColorSettingsPage.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinColorSettingsPage.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinColorSettingsPage.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightInfoTypeSemanticNames.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightInfoTypeSemanticNames.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightInfoTypeSemanticNames.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightInfoTypeSemanticNames.kt diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlighter.java b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlighter.java similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlighter.java rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlighter.java diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingColors.java b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingColors.java similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingColors.java rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingColors.java diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingLexer.java b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingLexer.java similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingLexer.java rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingLexer.java diff --git a/plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinProblemHighlightFilter.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinProblemHighlightFilter.kt similarity index 100% rename from plugins/kotlin/base/highlighting/src/org/jetbrains/kotlin/idea/highlighter/KotlinProblemHighlightFilter.kt rename to plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/highlighter/KotlinProblemHighlightFilter.kt diff --git a/plugins/kotlin/idea/kotlin.idea.iml b/plugins/kotlin/idea/kotlin.idea.iml index 8f32cdf6a845..9d30831dd91c 100644 --- a/plugins/kotlin/idea/kotlin.idea.iml +++ b/plugins/kotlin/idea/kotlin.idea.iml @@ -54,7 +54,7 @@ - + diff --git a/plugins/kotlin/idea/tests/kotlin.idea.tests.iml b/plugins/kotlin/idea/tests/kotlin.idea.tests.iml index aa37d7b2fca5..16cd71857d9b 100644 --- a/plugins/kotlin/idea/tests/kotlin.idea.tests.iml +++ b/plugins/kotlin/idea/tests/kotlin.idea.tests.iml @@ -27,7 +27,7 @@ - + @@ -134,5 +134,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/intellij.kotlin.plugin.community.main.iml b/plugins/kotlin/intellij.kotlin.plugin.community.main.iml index dbe52f8d8698..8d99f0fb3f57 100644 --- a/plugins/kotlin/intellij.kotlin.plugin.community.main.iml +++ b/plugins/kotlin/intellij.kotlin.plugin.community.main.iml @@ -24,7 +24,6 @@ - @@ -156,7 +155,9 @@ - + + + diff --git a/plugins/kotlin/jvm/kotlin.jvm.iml b/plugins/kotlin/jvm/kotlin.jvm.iml index af12b87da7ce..2f4126c9a6aa 100644 --- a/plugins/kotlin/jvm/kotlin.jvm.iml +++ b/plugins/kotlin/jvm/kotlin.jvm.iml @@ -25,7 +25,7 @@ - + diff --git a/plugins/kotlin/k2-fe10-bindings/kotlin.k2.fe10-bindings.iml b/plugins/kotlin/k2-fe10-bindings/kotlin.k2.fe10-bindings.iml index 43edd9aff6f6..19039435dd5e 100644 --- a/plugins/kotlin/k2-fe10-bindings/kotlin.k2.fe10-bindings.iml +++ b/plugins/kotlin/k2-fe10-bindings/kotlin.k2.fe10-bindings.iml @@ -53,6 +53,6 @@ - + \ No newline at end of file diff --git a/plugins/kotlin/plugin/k1/kotlin.plugin.k1.iml b/plugins/kotlin/plugin/k1/kotlin.plugin.k1.iml index 8ef5588d3540..6a38d2feb3c9 100644 --- a/plugins/kotlin/plugin/k1/kotlin.plugin.k1.iml +++ b/plugins/kotlin/plugin/k1/kotlin.plugin.k1.iml @@ -29,7 +29,8 @@ - + + diff --git a/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml b/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml index be823a0c8345..361cfae30465 100644 --- a/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml +++ b/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml @@ -17,7 +17,7 @@ - + @@ -94,7 +94,7 @@ - + diff --git a/plugins/kotlin/run-configurations/jvm/kotlin.run-configurations.jvm.iml b/plugins/kotlin/run-configurations/jvm/kotlin.run-configurations.jvm.iml index 217dc38933bd..a62575df0917 100644 --- a/plugins/kotlin/run-configurations/jvm/kotlin.run-configurations.jvm.iml +++ b/plugins/kotlin/run-configurations/jvm/kotlin.run-configurations.jvm.iml @@ -22,7 +22,7 @@ - + diff --git a/plugins/kotlin/scripting-support/kotlin.scripting-support.iml b/plugins/kotlin/scripting-support/kotlin.scripting-support.iml index 2640f74e9e7a..66ac4023f27f 100644 --- a/plugins/kotlin/scripting-support/kotlin.scripting-support.iml +++ b/plugins/kotlin/scripting-support/kotlin.scripting-support.iml @@ -19,7 +19,7 @@ - + diff --git a/plugins/kotlin/util/test-generator-fir/kotlin.util.test-generator-fir.iml b/plugins/kotlin/util/test-generator-fir/kotlin.util.test-generator-fir.iml index 85be85f195ce..fdd71ec796d7 100644 --- a/plugins/kotlin/util/test-generator-fir/kotlin.util.test-generator-fir.iml +++ b/plugins/kotlin/util/test-generator-fir/kotlin.util.test-generator-fir.iml @@ -66,7 +66,7 @@ - + diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2HighlighterTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2HighlighterTests.kt index d5a72977373b..3b44a605c25a 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2HighlighterTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2HighlighterTests.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.idea.k2.highlighting.AbstractOutsiderHighlightingTes import org.jetbrains.kotlin.testGenerator.model.* internal fun MutableTWorkspace.generateK2HighlighterTests() { - testGroup("highlighting", testDataPath = "../idea/tests/testData") { + testGroup("highlighting/highlighting-k2", testDataPath = "../../idea/tests/testData") { testClass { model("highlighterMetaInfo") } @@ -27,7 +27,7 @@ internal fun MutableTWorkspace.generateK2HighlighterTests() { } } - testGroup("highlighting") { + testGroup("highlighting/highlighting-k2", testDataPath = "testData") { testClass { model("outsider", pattern = Patterns.DIRECTORY, isRecursive = false, passTestDataPath = false) } From b74c8c3892998858cde02a5647f8665c27a99d93 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 31 Jul 2023 15:23:33 +0200 Subject: [PATCH 076/165] [kotlin] k2: show implementations: use container text instead of repeated function name KTIJ-24626, KTIJ-15012 GitOrigin-RevId: 61a7fcda32d7cafdb947953b7ed82e852a34ef95 --- .../kotlin.code-insight.line-markers-k2.xml | 1 + .../KotlinGotoTargetPresentationProvider.kt | 50 +++++++++++++++++++ .../AbstractHLImplementationSearcherTest.kt | 25 ++++------ ...HLImplementationSearcherTestGenerated.java | 20 ++++++++ .../classes/classObjectInStaticNestedClass.kt | 12 +++++ .../classObjectInStaticNestedClass.result.kt | 1 + .../methods/EnumEntryFunction.kt | 7 +++ .../methods/EnumEntryFunction.result.kt | 2 + .../methods/inLocalClass.result.kt | 2 +- .../methods/inObjectLiteral.kt | 11 ++++ .../methods/inObjectLiteral.result.kt | 2 + ...ideMethodWithoutOverrideModifier.result.kt | 2 +- .../methods/singleSuperMethod.result.kt | 2 +- .../properties/inConstructorParam.kt | 6 +++ .../properties/inConstructorParam.result.kt | 2 + .../properties/inLocalClass.result.kt | 2 +- ...ePropertyWithoutOverrideModifier.result.kt | 2 +- .../properties/singleSuperProperty.result.kt | 2 +- 18 files changed, 131 insertions(+), 20 deletions(-) create mode 100644 plugins/kotlin/code-insight/line-markers/src/org/jetbrains/kotlin/idea/codeInsight/lineMarkers/KotlinGotoTargetPresentationProvider.kt create mode 100644 plugins/kotlin/fir/testData/search/implementations/classes/classObjectInStaticNestedClass.kt create mode 100644 plugins/kotlin/fir/testData/search/implementations/classes/classObjectInStaticNestedClass.result.kt create mode 100644 plugins/kotlin/fir/testData/search/implementations/methods/EnumEntryFunction.kt create mode 100644 plugins/kotlin/fir/testData/search/implementations/methods/EnumEntryFunction.result.kt create mode 100644 plugins/kotlin/fir/testData/search/implementations/methods/inObjectLiteral.kt create mode 100644 plugins/kotlin/fir/testData/search/implementations/methods/inObjectLiteral.result.kt create mode 100644 plugins/kotlin/fir/testData/search/implementations/properties/inConstructorParam.kt create mode 100644 plugins/kotlin/fir/testData/search/implementations/properties/inConstructorParam.result.kt diff --git a/plugins/kotlin/code-insight/line-markers/resources/kotlin.code-insight.line-markers-k2.xml b/plugins/kotlin/code-insight/line-markers/resources/kotlin.code-insight.line-markers-k2.xml index 5673c571dfc6..044b3bf831fa 100644 --- a/plugins/kotlin/code-insight/line-markers/resources/kotlin.code-insight.line-markers-k2.xml +++ b/plugins/kotlin/code-insight/line-markers/resources/kotlin.code-insight.line-markers-k2.xml @@ -17,6 +17,7 @@ + (true) ?: return null + val targetPresentation = getTargetPresentation(declaration) ?: return null + return TargetPresentation.builder(KotlinBundle.message("presentation.text.object.in.container", targetPresentation.presentableText)) + .icon(KotlinIcons.OBJECT) + .locationText(targetPresentation.locationText, targetPresentation.locationIcon) + .containerText(targetPresentation.containerText) + .presentation() + } + return getTargetPresentation(container) + } + + fun getTargetPresentation(declaration: KtNamedDeclaration): TargetPresentation? { + val presentation = declaration.presentation ?: return null + val presentableText = presentation.presentableText ?: return null + val ktFile = declaration.containingKtFile + val moduleTextWithIcon = PsiElementListCellRenderer.getModuleTextWithIcon(declaration) + return TargetPresentation.builder(presentableText) + .icon(presentation.getIcon(true)) + .locationText(moduleTextWithIcon?.text, moduleTextWithIcon?.icon) + .containerText(ktFile.packageFqName.asString()) + .presentation() + } +} \ No newline at end of file diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/search/AbstractHLImplementationSearcherTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/search/AbstractHLImplementationSearcherTest.kt index b2947dc8fc67..9bee57e00761 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/search/AbstractHLImplementationSearcherTest.kt +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/search/AbstractHLImplementationSearcherTest.kt @@ -1,19 +1,19 @@ // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.fir.search +import com.intellij.codeInsight.navigation.GotoTargetHandler.computePresentationInBackground +import com.intellij.codeInsight.navigation.ItemWithPresentation import com.intellij.openapi.actionSystem.ex.ActionUtil import com.intellij.psi.PsiElement -import com.intellij.psi.PsiNameIdentifierOwner +import com.intellij.psi.PsiNamedElement import com.intellij.psi.search.searches.DefinitionsScopedSearch import com.intellij.psi.util.parentOfType -import org.jetbrains.kotlin.idea.base.psi.kotlinFqName import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor import org.jetbrains.kotlin.idea.test.KotlinTestUtils import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtNamedDeclaration import java.nio.file.Paths abstract class AbstractHLImplementationSearcherTest : KotlinLightCodeInsightFixtureTestCase() { @@ -29,20 +29,17 @@ abstract class AbstractHLImplementationSearcherTest : KotlinLightCodeInsightFixt ?: error("No declaration found at caret") val result = ActionUtil.underModalProgress(project, "") { DefinitionsScopedSearch.search(declarationAtCaret).toList() } - val actual = render(result) + val hasDifferentNames = result.mapNotNull { (it as? PsiNamedElement)?.name }.distinct().size > 1 + val presentations = computePresentationInBackground(project, result.toTypedArray(), hasDifferentNames) + val actual = render(presentations) KotlinTestUtils.assertEqualsToSibling(Paths.get(testFilePath), ".result.kt", actual) } - private fun render(declarations: List): String = buildList { - for (declaration in declarations) { - val name = declaration.kotlinFqName ?: declaration.declarationName() - add(declaration::class.simpleName!! + ": " + name) + private fun render(presentations: List): String = buildList { + for (presentation in presentations) { + val element = presentation.dereference() ?: error("Unable to restore") + val name = presentation.presentation.presentableText + add(element::class.simpleName!! + ": " + name) } }.sorted().joinToString(separator = "\n") - - private fun PsiElement.declarationName() = when (this) { - is KtNamedDeclaration -> nameAsSafeName.asString() - is PsiNameIdentifierOwner -> nameIdentifier?.text ?: "" - else -> error("Unknown declaration ${this::class.simpleName}") - } } \ No newline at end of file diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/search/HLImplementationSearcherTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/search/HLImplementationSearcherTestGenerated.java index 67c3682ec53a..29b07f8880f9 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/search/HLImplementationSearcherTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/search/HLImplementationSearcherTestGenerated.java @@ -42,6 +42,11 @@ public abstract class HLImplementationSearcherTestGenerated extends AbstractHLIm KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("classObjectInStaticNestedClass.kt") + public void testClassObjectInStaticNestedClass() throws Exception { + runTest("testData/search/implementations/classes/classObjectInStaticNestedClass.kt"); + } + @TestMetadata("classWithDeepHeiarchy.kt") public void testClassWithDeepHeiarchy() throws Exception { runTest("testData/search/implementations/classes/classWithDeepHeiarchy.kt"); @@ -92,11 +97,21 @@ public abstract class HLImplementationSearcherTestGenerated extends AbstractHLIm KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("EnumEntryFunction.kt") + public void testEnumEntryFunction() throws Exception { + runTest("testData/search/implementations/methods/EnumEntryFunction.kt"); + } + @TestMetadata("inLocalClass.kt") public void testInLocalClass() throws Exception { runTest("testData/search/implementations/methods/inLocalClass.kt"); } + @TestMetadata("inObjectLiteral.kt") + public void testInObjectLiteral() throws Exception { + runTest("testData/search/implementations/methods/inObjectLiteral.kt"); + } + @TestMetadata("singleSuperMethod.kt") public void testSingleSuperMethod() throws Exception { runTest("testData/search/implementations/methods/singleSuperMethod.kt"); @@ -127,6 +142,11 @@ public abstract class HLImplementationSearcherTestGenerated extends AbstractHLIm KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("inConstructorParam.kt") + public void testInConstructorParam() throws Exception { + runTest("testData/search/implementations/properties/inConstructorParam.kt"); + } + @TestMetadata("inLocalClass.kt") public void testInLocalClass() throws Exception { runTest("testData/search/implementations/properties/inLocalClass.kt"); diff --git a/plugins/kotlin/fir/testData/search/implementations/classes/classObjectInStaticNestedClass.kt b/plugins/kotlin/fir/testData/search/implementations/classes/classObjectInStaticNestedClass.kt new file mode 100644 index 000000000000..86f197269f68 --- /dev/null +++ b/plugins/kotlin/fir/testData/search/implementations/classes/classObjectInStaticNestedClass.kt @@ -0,0 +1,12 @@ +interface TestInterface { + fun test() +} + +class A { + class B { + companion object : TestInterface { + override fun test() { + } + } + } +} \ No newline at end of file diff --git a/plugins/kotlin/fir/testData/search/implementations/classes/classObjectInStaticNestedClass.result.kt b/plugins/kotlin/fir/testData/search/implementations/classes/classObjectInStaticNestedClass.result.kt new file mode 100644 index 000000000000..c7b4eadba0e8 --- /dev/null +++ b/plugins/kotlin/fir/testData/search/implementations/classes/classObjectInStaticNestedClass.result.kt @@ -0,0 +1 @@ +KtNamedFunction: Companion diff --git a/plugins/kotlin/fir/testData/search/implementations/methods/EnumEntryFunction.kt b/plugins/kotlin/fir/testData/search/implementations/methods/EnumEntryFunction.kt new file mode 100644 index 000000000000..6bcad066de85 --- /dev/null +++ b/plugins/kotlin/fir/testData/search/implementations/methods/EnumEntryFunction.kt @@ -0,0 +1,7 @@ +enum class SampleEnum { + V1 { + override fun any() { super.any() } + }; + + open fun any() {} +} diff --git a/plugins/kotlin/fir/testData/search/implementations/methods/EnumEntryFunction.result.kt b/plugins/kotlin/fir/testData/search/implementations/methods/EnumEntryFunction.result.kt new file mode 100644 index 000000000000..8486c55b892f --- /dev/null +++ b/plugins/kotlin/fir/testData/search/implementations/methods/EnumEntryFunction.result.kt @@ -0,0 +1,2 @@ +KtNamedFunction: V1 +SymbolLightSimpleMethod: Enum constant 'V1' in 'SampleEnum' diff --git a/plugins/kotlin/fir/testData/search/implementations/methods/inLocalClass.result.kt b/plugins/kotlin/fir/testData/search/implementations/methods/inLocalClass.result.kt index 8982d4c89ed8..42a064634cf4 100644 --- a/plugins/kotlin/fir/testData/search/implementations/methods/inLocalClass.result.kt +++ b/plugins/kotlin/fir/testData/search/implementations/methods/inLocalClass.result.kt @@ -1 +1 @@ -KtNamedFunction: foo +KtNamedFunction: B diff --git a/plugins/kotlin/fir/testData/search/implementations/methods/inObjectLiteral.kt b/plugins/kotlin/fir/testData/search/implementations/methods/inObjectLiteral.kt new file mode 100644 index 000000000000..f3fe9e3e9e14 --- /dev/null +++ b/plugins/kotlin/fir/testData/search/implementations/methods/inObjectLiteral.kt @@ -0,0 +1,11 @@ +open class A { + open fun foo() {} +} + +val o = object : A() { + override fun foo() {} +} + +class B: A() { + override fun foo() {} +} \ No newline at end of file diff --git a/plugins/kotlin/fir/testData/search/implementations/methods/inObjectLiteral.result.kt b/plugins/kotlin/fir/testData/search/implementations/methods/inObjectLiteral.result.kt new file mode 100644 index 000000000000..1939673d7b36 --- /dev/null +++ b/plugins/kotlin/fir/testData/search/implementations/methods/inObjectLiteral.result.kt @@ -0,0 +1,2 @@ +KtNamedFunction: B +KtNamedFunction: object in o diff --git a/plugins/kotlin/fir/testData/search/implementations/methods/incorrectCode/overideMethodWithoutOverrideModifier.result.kt b/plugins/kotlin/fir/testData/search/implementations/methods/incorrectCode/overideMethodWithoutOverrideModifier.result.kt index 0e01eefcdb2e..42a064634cf4 100644 --- a/plugins/kotlin/fir/testData/search/implementations/methods/incorrectCode/overideMethodWithoutOverrideModifier.result.kt +++ b/plugins/kotlin/fir/testData/search/implementations/methods/incorrectCode/overideMethodWithoutOverrideModifier.result.kt @@ -1 +1 @@ -KtNamedFunction: B.foo +KtNamedFunction: B diff --git a/plugins/kotlin/fir/testData/search/implementations/methods/singleSuperMethod.result.kt b/plugins/kotlin/fir/testData/search/implementations/methods/singleSuperMethod.result.kt index 0e01eefcdb2e..42a064634cf4 100644 --- a/plugins/kotlin/fir/testData/search/implementations/methods/singleSuperMethod.result.kt +++ b/plugins/kotlin/fir/testData/search/implementations/methods/singleSuperMethod.result.kt @@ -1 +1 @@ -KtNamedFunction: B.foo +KtNamedFunction: B diff --git a/plugins/kotlin/fir/testData/search/implementations/properties/inConstructorParam.kt b/plugins/kotlin/fir/testData/search/implementations/properties/inConstructorParam.kt new file mode 100644 index 000000000000..8eb050926560 --- /dev/null +++ b/plugins/kotlin/fir/testData/search/implementations/properties/inConstructorParam.kt @@ -0,0 +1,6 @@ +interface I1 { + val s: String +} + +class A1(override val s: String): I1 +class B1(override val s: String): I1 diff --git a/plugins/kotlin/fir/testData/search/implementations/properties/inConstructorParam.result.kt b/plugins/kotlin/fir/testData/search/implementations/properties/inConstructorParam.result.kt new file mode 100644 index 000000000000..d51657db162e --- /dev/null +++ b/plugins/kotlin/fir/testData/search/implementations/properties/inConstructorParam.result.kt @@ -0,0 +1,2 @@ +KtParameter: A1(String) +KtParameter: B1(String) diff --git a/plugins/kotlin/fir/testData/search/implementations/properties/inLocalClass.result.kt b/plugins/kotlin/fir/testData/search/implementations/properties/inLocalClass.result.kt index d366329d9bec..38f9aec69888 100644 --- a/plugins/kotlin/fir/testData/search/implementations/properties/inLocalClass.result.kt +++ b/plugins/kotlin/fir/testData/search/implementations/properties/inLocalClass.result.kt @@ -1 +1 @@ -KtProperty: foo \ No newline at end of file +KtProperty: B diff --git a/plugins/kotlin/fir/testData/search/implementations/properties/incorrectCode/overidePropertyWithoutOverrideModifier.result.kt b/plugins/kotlin/fir/testData/search/implementations/properties/incorrectCode/overidePropertyWithoutOverrideModifier.result.kt index 79222c19d86e..38f9aec69888 100644 --- a/plugins/kotlin/fir/testData/search/implementations/properties/incorrectCode/overidePropertyWithoutOverrideModifier.result.kt +++ b/plugins/kotlin/fir/testData/search/implementations/properties/incorrectCode/overidePropertyWithoutOverrideModifier.result.kt @@ -1 +1 @@ -KtProperty: B.foo +KtProperty: B diff --git a/plugins/kotlin/fir/testData/search/implementations/properties/singleSuperProperty.result.kt b/plugins/kotlin/fir/testData/search/implementations/properties/singleSuperProperty.result.kt index 79222c19d86e..38f9aec69888 100644 --- a/plugins/kotlin/fir/testData/search/implementations/properties/singleSuperProperty.result.kt +++ b/plugins/kotlin/fir/testData/search/implementations/properties/singleSuperProperty.result.kt @@ -1 +1 @@ -KtProperty: B.foo +KtProperty: B From ac091a69907018ea61db47a0a5e05e4c44331c43 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 31 Jul 2023 10:32:34 +0200 Subject: [PATCH 077/165] [codeInspection] fix NPE in getTool GitOrigin-RevId: f1a98b575f4de90f078eece1e74091061606aab0 --- ...nToolsSettingsInSuppressedPlaceIntention.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/EditInspectionToolsSettingsInSuppressedPlaceIntention.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/EditInspectionToolsSettingsInSuppressedPlaceIntention.java index ad9daa584ce8..de18439737be 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/EditInspectionToolsSettingsInSuppressedPlaceIntention.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/EditInspectionToolsSettingsInSuppressedPlaceIntention.java @@ -17,7 +17,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class EditInspectionToolsSettingsInSuppressedPlaceIntention implements IntentionAction { - private String myId; private String myDisplayName; @Override @@ -61,25 +60,26 @@ public class EditInspectionToolsSettingsInSuppressedPlaceIntention implements In @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - myId = getSuppressedId(editor, file); - if (myId != null) { - InspectionToolWrapper toolWrapper = getTool(project, file); + String suppressedId = getSuppressedId(editor, file); + if (suppressedId != null) { + InspectionToolWrapper toolWrapper = getTool(project, file, suppressedId); if (toolWrapper == null) return false; myDisplayName = toolWrapper.getDisplayName(); } - return myId != null; + return suppressedId != null; } @Nullable - private InspectionToolWrapper getTool(final Project project, final PsiFile file) { + private static InspectionToolWrapper getTool(final Project project, final PsiFile file, final String suppressId) { + if (suppressId == null) return null; final InspectionProjectProfileManager projectProfileManager = InspectionProjectProfileManager.getInstance(project); final InspectionProfileImpl inspectionProfile = projectProfileManager.getCurrentProfile(); - return inspectionProfile.getToolById(myId, file); + return inspectionProfile.getToolById(suppressId, file); } @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - InspectionToolWrapper toolWrapper = getTool(project, file); + InspectionToolWrapper toolWrapper = getTool(project, file, getSuppressedId(editor, file)); if (toolWrapper == null) return; final InspectionProjectProfileManager projectProfileManager = InspectionProjectProfileManager.getInstance(project); final InspectionProfileImpl inspectionProfile = projectProfileManager.getCurrentProfile(); From bec9bded820d206ed3fbec3de14f697f793e3b26 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Wed, 2 Aug 2023 11:31:59 +0200 Subject: [PATCH 078/165] [kotlin] Fix project structure after regrouping highlighting modules GitOrigin-RevId: fa9150f20e1963b1708f5f3046a8ca268b1bfec1 --- .../jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt | 5 +++-- plugins/kotlin/highlighting/highlighting-k1/resources/dummy | 0 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 plugins/kotlin/highlighting/highlighting-k1/resources/dummy diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt index 1cbbafcb75b3..1f1fc527ca3b 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt @@ -47,7 +47,6 @@ object KotlinPluginBuilder { "kotlin.base.scripting", "kotlin.base.analysis-api-providers", "kotlin.base.analysis", - "kotlin.base.highlighting", "kotlin.base.code-insight", "kotlin.base.jps", "kotlin.base.analysis-api.utils", @@ -183,7 +182,9 @@ object KotlinPluginBuilder { "kotlin.fir", "kotlin.searching.k2", "kotlin.searching.base", - "kotlin.highlighting", + "kotlin.highlighting.shared", + "kotlin.highlighting.k1", + "kotlin.highlighting.k2", "kotlin.uast.uast-kotlin-fir", "kotlin.uast.uast-kotlin-idea-fir", "kotlin.fir.fir-low-level-api-ide-impl", diff --git a/plugins/kotlin/highlighting/highlighting-k1/resources/dummy b/plugins/kotlin/highlighting/highlighting-k1/resources/dummy new file mode 100644 index 000000000000..e69de29bb2d1 From 006ce28687c9013488f14e2f5161b1d371b0c318 Mon Sep 17 00:00:00 2001 From: Bart van Helvert Date: Tue, 1 Aug 2023 19:51:05 +0200 Subject: [PATCH 079/165] [kotlin] K2 better support for top level declarations in bindToElement Cleans up bind to element implementation and adds more tests for top level function calls and top level properties. GitOrigin-RevId: e451f8c3b5033c2530d6242c7d6092f88305c589 --- .../topLevelFunctionCall/Qualified.kt | 17 ++++++ .../topLevelFunctionCall/Qualified.kt.after | 10 ++++ .../topLevelFunctionCall/RootPkg.kt | 8 +++ .../topLevelFunctionCall/RootPkg.kt.after | 8 +++ ...TopLevelFunctionCall.kt => UnQualified.kt} | 2 +- ...tionCall.kt.after => UnQualified.kt.after} | 2 +- .../topLevelProperty/Qualified.kt | 17 ++++++ .../topLevelProperty/Qualified.kt.after | 10 ++++ .../bindToElement/topLevelProperty/RootPkg.kt | 8 +++ .../topLevelProperty/RootPkg.kt.after | 8 +++ .../topLevelProperty/UnQualified.kt | 19 +++++++ .../topLevelProperty/UnQualified.kt.after | 11 ++++ .../refactoring/K2ReferenceMutateService.kt | 55 ++++++++++++------- .../safeDelete/AbstractK2BindToElementTest.kt | 4 +- .../K2BindToElementTestGenerated.java | 39 ++++++++++++- 15 files changed, 191 insertions(+), 27 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/Qualified.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/Qualified.kt.after create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/RootPkg.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/RootPkg.kt.after rename plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/{TopLevelFunctionCall.kt => UnQualified.kt} (86%) rename plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/{TopLevelFunctionCall.kt.after => UnQualified.kt.after} (74%) create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/Qualified.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/Qualified.kt.after create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/RootPkg.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/RootPkg.kt.after create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/UnQualified.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/UnQualified.kt.after diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/Qualified.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/Qualified.kt new file mode 100644 index 000000000000..6d068fd7c57d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/Qualified.kt @@ -0,0 +1,17 @@ +// FILE: test/Qualified.kt +// BIND_TO test.bar.fooBar +package test + +fun foo() { + test.foo.fooBar() +} + +// FILE: test/foo/Test.kt +package test.foo + +fun fooBar() { } + +// FILE: test/bar/Test.kt +package test.bar + +fun fooBar() { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/Qualified.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/Qualified.kt.after new file mode 100644 index 000000000000..1fce80d344ad --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/Qualified.kt.after @@ -0,0 +1,10 @@ +// FILE: test/Qualified.kt +// BIND_TO test.bar.fooBar +package test + +import test.bar.fooBar + +fun foo() { + fooBar() +} + diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/RootPkg.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/RootPkg.kt new file mode 100644 index 000000000000..ff9af11b44cc --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/RootPkg.kt @@ -0,0 +1,8 @@ +// BIND_TO barFoo +fun foo() { + fooBar() +} + +fun fooBar() { } + +fun barFoo() { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/RootPkg.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/RootPkg.kt.after new file mode 100644 index 000000000000..53579e6f3872 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/RootPkg.kt.after @@ -0,0 +1,8 @@ +// BIND_TO barFoo +fun foo() { + barFoo() +} + +fun fooBar() { } + +fun barFoo() { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/UnQualified.kt similarity index 86% rename from plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt rename to plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/UnQualified.kt index 940c4324c341..aa73af95b890 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/UnQualified.kt @@ -1,4 +1,4 @@ -// FILE: test/TopLevelFunction.kt +// FILE: test/UnQualified.kt // BIND_TO test.bar.fooBar package test diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/UnQualified.kt.after similarity index 74% rename from plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt.after rename to plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/UnQualified.kt.after index b79d7b4ae0d7..60dbbf09bc3f 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt.after +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/UnQualified.kt.after @@ -1,4 +1,4 @@ -// FILE: test/TopLevelFunction.kt +// FILE: test/UnQualified.kt // BIND_TO test.bar.fooBar package test diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/Qualified.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/Qualified.kt new file mode 100644 index 000000000000..1fb073a90d0a --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/Qualified.kt @@ -0,0 +1,17 @@ +// FILE: test/Qualified.kt +// BIND_TO test.bar.fooBar +package test + +fun foo() { + val x = test.foo.fooBar +} + +// FILE: test/foo/Test.kt +package test.foo + +val fooBar = 0 + +// FILE: test/bar/Test.kt +package test.bar + +val fooBar = 0 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/Qualified.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/Qualified.kt.after new file mode 100644 index 000000000000..3c4281eaea50 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/Qualified.kt.after @@ -0,0 +1,10 @@ +// FILE: test/Qualified.kt +// BIND_TO test.bar.fooBar +package test + +import test.bar.fooBar + +fun foo() { + val x = fooBar +} + diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/RootPkg.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/RootPkg.kt new file mode 100644 index 000000000000..3c072a620587 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/RootPkg.kt @@ -0,0 +1,8 @@ +// BIND_TO barFoo +fun foo() { + val x = fooBar +} + +val fooBar = 0 + +val barFoo = 0 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/RootPkg.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/RootPkg.kt.after new file mode 100644 index 000000000000..14b94fc2229e --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/RootPkg.kt.after @@ -0,0 +1,8 @@ +// BIND_TO barFoo +fun foo() { + val x = barFoo +} + +val fooBar = 0 + +val barFoo = 0 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/UnQualified.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/UnQualified.kt new file mode 100644 index 000000000000..c3cd5f5ba14a --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/UnQualified.kt @@ -0,0 +1,19 @@ +// FILE: test/UnQualified.kt +// BIND_TO test.bar.fooBar +package test + +import test.foo.fooBar + +fun foo() { + val x = fooBar +} + +// FILE: test/foo/Test.kt +package test.foo + +val fooBar = 0 + +// FILE: test/bar/Test.kt +package test.bar + +val fooBar = 0 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/UnQualified.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/UnQualified.kt.after new file mode 100644 index 000000000000..62bff3680dba --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/topLevelProperty/UnQualified.kt.after @@ -0,0 +1,11 @@ +// FILE: test/UnQualified.kt +// BIND_TO test.bar.fooBar +package test + + +import test.bar.fooBar + +fun foo() { + val x = fooBar +} + diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt index f5ea31f0e3d7..692914f1217e 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt @@ -101,30 +101,43 @@ internal class K2ReferenceMutateService : KtReferenceMutateServiceBase() { return replaced(newReference) } - private fun KtCallExpression.replaceWith(fqName: FqName): KtExpression { - val psiFactory = KtPsiFactory(project) - val newName = psiFactory.createSimpleName(fqName.shortName().asString()) - calleeExpression?.replace(newName) - val parentFqName = fqName.parent() - if (parentFqName.isRoot) return this - val packageName = fqName.parent().asString() - val newQualifiedExpression = psiFactory.createExpression("$packageName.${text}") - return replaced(newQualifiedExpression) - } - - private fun KtSimpleNameExpression.replaceWith(fqName: FqName): KtExpression { - val newNameExpression = KtPsiFactory(project).createExpression(fqName.asString()) - return replaced(newNameExpression) - } - private fun KtDotQualifiedExpression.replaceWith(fqName: FqName): KtExpression? { val selectorExpression = selectorExpression ?: return null val newExpression = when (selectorExpression) { - is KtSimpleNameExpression -> selectorExpression.replaceWith(fqName) - is KtCallExpression -> selectorExpression.replaceWith(fqName) - else -> return null - } - return replaced(newExpression) + is KtSimpleNameExpression -> selectorExpression.replaceShortName(fqName) + is KtCallExpression -> selectorExpression.replaceShortName(fqName) + else -> null + } ?: return null + return replaceWithQualified(fqName, newExpression) + } + + private fun KtExpression.replaceWithQualified(fqName: FqName, selectorExpression: KtExpression): KtExpression { + val parentFqName = fqName.parent() + if (parentFqName.isRoot) return selectorExpression + val packageName = fqName.parent().asString() + val newQualifiedExpression = KtPsiFactory(project).createExpression("$packageName.${selectorExpression.text}") + return replaced(newQualifiedExpression) + } + + private fun KtCallExpression.replaceWith(fqName: FqName): KtExpression? { + val newCall = replaceShortName(fqName) ?: return null + return newCall.replaceWithQualified(fqName, newCall) + } + + private fun KtCallExpression.replaceShortName(fqName: FqName): KtExpression? { + val psiFactory = KtPsiFactory(project) + val newName = psiFactory.createSimpleName(fqName.shortName().asString()) + return calleeExpression?.replace(newName)?.parentOfType() + } + + private fun KtSimpleNameExpression.replaceWith(fqName: FqName): KtExpression { + val newNameExpr = replaceShortName(fqName) + return newNameExpr.replaceWithQualified(fqName, newNameExpr) + } + + private fun KtSimpleNameExpression.replaceShortName(fqName: FqName): KtExpression { + val newNameExpression = KtPsiFactory(project).createExpression(fqName.shortName().asString()) + return replaced(newNameExpression) } override fun KtSimpleReference.suggestVariableName( diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/AbstractK2BindToElementTest.kt b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/AbstractK2BindToElementTest.kt index 88e231585703..36ea481d3fd2 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/AbstractK2BindToElementTest.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/AbstractK2BindToElementTest.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex +import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelPropertyFqnNameIndex import org.jetbrains.kotlin.idea.test.* import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.kdoc.psi.impl.KDocName @@ -41,7 +42,8 @@ abstract class AbstractK2BindToElementTest : KotlinMultiFileLightCodeInsightFixt val nameToBind = InTextDirectivesUtils.findStringWithPrefixes(file.text, BIND_TO) ?: return null val projectScope = GlobalSearchScope.allScope(myFixture.project) return JavaPsiFacade.getInstance(myFixture.project).findClass(nameToBind, projectScope) - ?: KotlinTopLevelFunctionFqnNameIndex[nameToBind, myFixture.project, projectScope].firstOrNull() + ?: KotlinTopLevelFunctionFqnNameIndex[nameToBind, myFixture.project, projectScope].firstOrNull() + ?: KotlinTopLevelPropertyFqnNameIndex[nameToBind, myFixture.project, projectScope].firstOrNull() } private companion object { diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java index ab9ee0c8dafa..e9711c3b0058 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java @@ -287,9 +287,42 @@ public abstract class K2BindToElementTestGenerated extends AbstractK2BindToEleme KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } - @TestMetadata("TopLevelFunctionCall.kt") - public void testTopLevelFunctionCall() throws Exception { - runTest("../../idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/TopLevelFunctionCall.kt"); + @TestMetadata("Qualified.kt") + public void testQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/Qualified.kt"); + } + + @TestMetadata("RootPkg.kt") + public void testRootPkg() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/RootPkg.kt"); + } + + @TestMetadata("UnQualified.kt") + public void testUnQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/topLevelFunctionCall/UnQualified.kt"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/topLevelProperty") + public static class TopLevelProperty extends AbstractK2BindToElementTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("Qualified.kt") + public void testQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/topLevelProperty/Qualified.kt"); + } + + @TestMetadata("RootPkg.kt") + public void testRootPkg() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/topLevelProperty/RootPkg.kt"); + } + + @TestMetadata("UnQualified.kt") + public void testUnQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/topLevelProperty/UnQualified.kt"); } } } From fca0d5ca5ec1bef8efcc3a126c1a2b8175f3fc7e Mon Sep 17 00:00:00 2001 From: Bart van Helvert Date: Wed, 2 Aug 2023 12:10:39 +0200 Subject: [PATCH 080/165] [kotlin] Remove redundant parentOfType GitOrigin-RevId: b8261473e7077ab2d207767cc1604edc3e8c58b6 --- .../idea/k2/refactoring/K2ReferenceMutateService.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt index 692914f1217e..86926fe6c57c 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt @@ -119,15 +119,16 @@ internal class K2ReferenceMutateService : KtReferenceMutateServiceBase() { return replaced(newQualifiedExpression) } - private fun KtCallExpression.replaceWith(fqName: FqName): KtExpression? { - val newCall = replaceShortName(fqName) ?: return null + private fun KtCallExpression.replaceWith(fqName: FqName): KtExpression { + val newCall = replaceShortName(fqName) return newCall.replaceWithQualified(fqName, newCall) } - private fun KtCallExpression.replaceShortName(fqName: FqName): KtExpression? { + private fun KtCallExpression.replaceShortName(fqName: FqName): KtExpression { val psiFactory = KtPsiFactory(project) val newName = psiFactory.createSimpleName(fqName.shortName().asString()) - return calleeExpression?.replace(newName)?.parentOfType() + calleeExpression?.replace(newName) + return this } private fun KtSimpleNameExpression.replaceWith(fqName: FqName): KtExpression { From 467733c04b407d7c940ecef3f52fbc48d2898593 Mon Sep 17 00:00:00 2001 From: Bart van Helvert Date: Thu, 3 Aug 2023 10:47:22 +0200 Subject: [PATCH 081/165] [kotlin] Use `createSimpleName` for creating short name in bindToElement GitOrigin-RevId: eb1392504f4849f2671d69e76171ca4b0680c3cc --- .../kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt index 86926fe6c57c..c0fe5163bbd8 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt @@ -137,7 +137,7 @@ internal class K2ReferenceMutateService : KtReferenceMutateServiceBase() { } private fun KtSimpleNameExpression.replaceShortName(fqName: FqName): KtExpression { - val newNameExpression = KtPsiFactory(project).createExpression(fqName.shortName().asString()) + val newNameExpression = KtPsiFactory(project).createSimpleName(fqName.shortName().asString()) return replaced(newNameExpression) } From 92be92456c94fbd13f767d06ab63eac9b1205fa3 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 3 Aug 2023 10:15:13 +0200 Subject: [PATCH 082/165] [change signature] don't leak change info in undo manager; simplify kotlin GitOrigin-RevId: 6d48a7e5be1fa7d6443b9f3c5b4c2d6ddc2f5e29 --- .../ChangeSignatureProcessorBase.java | 14 +++++-- .../KotlinChangeInfoWrapper.kt | 37 ------------------- .../KotlinChangeSignatureConflictSearcher.kt | 2 +- .../KotlinChangeSignatureProcessor.kt | 23 +++++------- .../KotlinChangeSignatureUsageProcessor.kt | 10 +++-- .../changeSignature/changeSignatureUtils.kt | 8 ---- .../KotlinChangeSignatureTest.kt | 4 +- 7 files changed, 28 insertions(+), 70 deletions(-) delete mode 100644 plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeInfoWrapper.kt diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessorBase.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessorBase.java index be75a82bc89f..fb6cbccb39b4 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessorBase.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessorBase.java @@ -12,6 +12,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiManager; +import com.intellij.psi.SmartPointerManager; +import com.intellij.psi.SmartPsiElementPointer; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.listeners.RefactoringElementListener; @@ -156,14 +158,19 @@ public abstract class ChangeSignatureProcessorBase extends BaseRefactoringProces protected void performRefactoring(UsageInfo @NotNull [] usages) { RefactoringTransaction transaction = getTransaction(); final ChangeInfo changeInfo = myChangeInfo; - final RefactoringElementListener elementListener = transaction == null ? null : transaction.getElementListener(changeInfo.getMethod()); - final String fqn = CopyReferenceAction.elementToFqn(changeInfo.getMethod()); + PsiElement method = changeInfo.getMethod(); + final RefactoringElementListener elementListener = transaction == null ? null : transaction.getElementListener(method); + final String fqn = CopyReferenceAction.elementToFqn(method); if (fqn != null) { + SmartPsiElementPointer pointer = SmartPointerManager.createPointer(method); UndoableAction action = new BasicUndoableAction() { @Override public void undo() { if (elementListener instanceof UndoRefactoringElementListener) { - ((UndoRefactoringElementListener)elementListener).undoElementMovedOrRenamed(changeInfo.getMethod(), fqn); + PsiElement element = pointer.getElement(); + if (element != null) { + ((UndoRefactoringElementListener)elementListener).undoElementMovedOrRenamed(element, fqn); + } } } @@ -175,7 +182,6 @@ public abstract class ChangeSignatureProcessorBase extends BaseRefactoringProces } try { doChangeSignature(changeInfo, usages); - final PsiElement method = changeInfo.getMethod(); LOG.assertTrue(method.isValid()); if (elementListener != null && changeInfo.isNameChanged()) { elementListener.elementRenamed(method); diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeInfoWrapper.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeInfoWrapper.kt deleted file mode 100644 index b0c7221b9522..000000000000 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeInfoWrapper.kt +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - -package org.jetbrains.kotlin.idea.refactoring.changeSignature - -import com.intellij.refactoring.changeSignature.ChangeInfo - -class KotlinChangeInfoWrapper(delegate: KotlinChangeInfo) : ChangeInfo { - var delegate: KotlinChangeInfo? = delegate - private set - - private val method = delegate.method - - override fun getMethod() = method - - override fun isGenerateDelegate() = delegate!!.isGenerateDelegate - - override fun getNewName() = delegate!!.newName - - override fun isParameterTypesChanged() = delegate!!.isParameterTypesChanged - - override fun getNewParameters() = delegate!!.newParameters - - override fun isParameterSetOrOrderChanged() = delegate!!.isParameterSetOrOrderChanged - - override fun isReturnTypeChanged() = delegate!!.isReturnTypeChanged - - override fun isParameterNamesChanged() = delegate!!.isParameterNamesChanged - - override fun isNameChanged() = delegate!!.isNameChanged - - override fun getLanguage() = delegate!!.language - - // Only getMethod() may be called after invalidate() - fun invalidate() { - delegate = null - } -} \ No newline at end of file diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureConflictSearcher.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureConflictSearcher.kt index 5dd4de9d4cdb..31004161254f 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureConflictSearcher.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureConflictSearcher.kt @@ -55,7 +55,7 @@ class KotlinChangeSignatureConflictSearcher( refUsages.set(adjustedUsages.toTypedArray()) } - changeInfo = originalInfo.asKotlinChangeInfo ?: return result + changeInfo = originalInfo as? KotlinChangeInfo ?: return result doFindConflicts() diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureProcessor.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureProcessor.kt index 10770bf8a514..b8cf6dc11c6a 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureProcessor.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureProcessor.kt @@ -32,15 +32,12 @@ class KotlinChangeSignatureProcessor( project: Project, changeInfo: KotlinChangeInfo, @NlsContexts.Command private val commandName: String -) : ChangeSignatureProcessorBase(project, KotlinChangeInfoWrapper(changeInfo)) { +) : ChangeSignatureProcessorBase(project, changeInfo) { init { // we must force collecting references to other parameters now before the signature is changed changeInfo.newParameters.forEach { it.defaultValueParameterReferences } } - val ktChangeInfo: KotlinChangeInfo - get() = changeInfo.delegate!! - override fun setPrepareSuccessfulSwingThreadCallback(callback: Runnable?) { val actualCallback = if (callback != null) { Runnable { @@ -52,7 +49,7 @@ class KotlinChangeSignatureProcessor( } override fun createUsageViewDescriptor(usages: Array): UsageViewDescriptor { - val subject = if (ktChangeInfo.kind.isConstructor) + val subject = if (changeInfo.kind.isConstructor) KotlinBundle.message("text.constructor") else KotlinBundle.message("text.function") @@ -60,12 +57,12 @@ class KotlinChangeSignatureProcessor( return KotlinUsagesViewDescriptor(myChangeInfo.method, RefactoringBundle.message("0.to.change.signature", subject)) } - override fun getChangeInfo(): KotlinChangeInfoWrapper = super.getChangeInfo() as KotlinChangeInfoWrapper + override fun getChangeInfo(): KotlinChangeInfo = super.getChangeInfo() as KotlinChangeInfo override fun findUsages(): Array { val allUsages = ArrayList() val javaUsages = mutableSetOf() - ktChangeInfo.getOrCreateJavaChangeInfos()?.let { javaChangeInfos -> + changeInfo.getOrCreateJavaChangeInfos()?.let { javaChangeInfos -> val javaProcessor = JavaChangeSignatureUsageProcessor() javaChangeInfos.mapNotNullTo(allUsages) { javaChangeInfo -> val javaUsagesForKtChange = javaProcessor.findUsages(javaChangeInfo) @@ -74,11 +71,11 @@ class KotlinChangeSignatureProcessor( }.ifEmpty { return@mapNotNullTo null } javaUsages.addAll(uniqueJavaUsagesForKtChange) - KotlinWrapperForJavaUsageInfos(ktChangeInfo, javaChangeInfo, uniqueJavaUsagesForKtChange.toTypedArray(), changeInfo.method) + KotlinWrapperForJavaUsageInfos(changeInfo, javaChangeInfo, uniqueJavaUsagesForKtChange.toTypedArray(), changeInfo.method) } } - val primaryConstructor = ktChangeInfo.method as? KtPrimaryConstructor + val primaryConstructor = changeInfo.method as? KtPrimaryConstructor if (primaryConstructor != null) { findConstructorPropertyUsages(primaryConstructor, allUsages) } @@ -94,7 +91,7 @@ class KotlinChangeSignatureProcessor( for ((index, parameter) in primaryConstructor.valueParameters.withIndex()) { if (!parameter.isOverridable) continue - val parameterInfo = ktChangeInfo.newParameters.find { it.originalIndex == index } ?: continue + val parameterInfo = changeInfo.newParameters.find { it.originalIndex == index } ?: continue val descriptor = parameter.resolveToDescriptorIfAny() as? PropertyDescriptor ?: continue val methodDescriptor = KotlinChangeSignatureData( descriptor, @@ -109,7 +106,7 @@ class KotlinChangeSignatureProcessor( context = parameter, ) - ktChangeInfo.registerInnerChangeInfo(propertyChangeInfo) + changeInfo.registerInnerChangeInfo(propertyChangeInfo) KotlinChangeSignatureProcessor(myProject, propertyChangeInfo, commandName).findUsages().mapNotNullTo(allUsages) { if (it is KotlinWrapperForJavaUsageInfos) return@mapNotNullTo it @@ -157,7 +154,7 @@ class KotlinChangeSignatureProcessor( override fun getCommandName() = commandName - override fun performRefactoring(usages: Array) = try { + override fun performRefactoring(usages: Array) { super.performRefactoring(usages) usages.forEach { val callExpression = it.element as? KtCallExpression ?: return@forEach @@ -166,8 +163,6 @@ class KotlinChangeSignatureProcessor( } } performDelayedRefactoringRequests(myProject) - } finally { - changeInfo.invalidate() } override fun doRun() = try { diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureUsageProcessor.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureUsageProcessor.kt index db0235430c0a..af88764a112b 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureUsageProcessor.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureUsageProcessor.kt @@ -99,7 +99,7 @@ class KotlinChangeSignatureUsageProcessor : ChangeSignatureUsageProcessor { result.add(OriginalJavaMethodDescriptorWrapper(info.method)) - val kotlinChangeInfo = info.asKotlinChangeInfo + val kotlinChangeInfo = info as? KotlinChangeInfo if (kotlinChangeInfo != null) { findAllMethodUsages(kotlinChangeInfo, result) } else { @@ -114,7 +114,9 @@ class KotlinChangeSignatureUsageProcessor : ChangeSignatureUsageProcessor { return result.toTypedArray() } - private fun canHandle(changeInfo: ChangeInfo) = changeInfo.asKotlinChangeInfo is KotlinChangeInfo || changeInfo is JavaChangeInfo + private fun canHandle(changeInfo: ChangeInfo): Boolean { + return changeInfo is KotlinChangeInfo || changeInfo is JavaChangeInfo + } private fun findAllMethodUsages(changeInfo: KotlinChangeInfo, result: MutableSet) { loop@ for (functionUsageInfo in changeInfo.getAffectedCallables()) { @@ -738,7 +740,7 @@ class KotlinChangeSignatureUsageProcessor : ChangeSignatureUsageProcessor { @Suppress("UNCHECKED_CAST") val kotlinUsageInfo = usageInfo as? KotlinUsageInfo - val ktChangeInfo = changeInfo.asKotlinChangeInfo + val ktChangeInfo = changeInfo as? KotlinChangeInfo return ktChangeInfo != null && kotlinUsageInfo != null && kotlinUsageInfo.processUsage( ktChangeInfo, element, @@ -771,7 +773,7 @@ class KotlinChangeSignatureUsageProcessor : ChangeSignatureUsageProcessor { changeInfo.updateMethod(method) } } else { - changeInfo.asKotlinChangeInfo ?: return false + changeInfo as? KotlinChangeInfo ?: return false } for (primaryFunction in ktChangeInfo.methodDescriptor.primaryCallables) { diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/changeSignatureUtils.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/changeSignatureUtils.kt index b960a7e1617a..ae0854a32f20 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/changeSignatureUtils.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/changeSignatureUtils.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.idea.refactoring.changeSignature import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import com.intellij.refactoring.changeSignature.CallerUsageInfo -import com.intellij.refactoring.changeSignature.ChangeInfo import com.intellij.refactoring.changeSignature.OverriderUsageInfo import com.intellij.usageView.UsageInfo import org.jetbrains.kotlin.builtins.isFunctionType @@ -134,13 +133,6 @@ fun suggestReceiverNames(project: Project, descriptor: CallableDescriptor): List return Fe10KotlinNameSuggester.suggestNamesByType(receiverType, validator, "receiver") } -internal val ChangeInfo.asKotlinChangeInfo: KotlinChangeInfo? - get() = when (this) { - is KotlinChangeInfo -> this - is KotlinChangeInfoWrapper -> delegate - else -> null - } - fun KotlinTypeInfo.getReceiverTypeText(): String { val text = render() return when { diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureTest.kt index f80e4da46613..cfb8e8e3dbb9 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureTest.kt @@ -361,7 +361,7 @@ class KotlinChangeSignatureTest : KotlinLightCodeInsightFixtureTestCase() { val adjustedDescriptor = kotlinChangeSignature.adjustDescriptor(declarations)!! val processor = kotlinChangeSignature.createSilentRefactoringProcessor(adjustedDescriptor) as KotlinChangeSignatureProcessor - processor.ktChangeInfo.also { it.checkUsedParameters = true } + processor.changeInfo.also { it.checkUsedParameters = true } processor.run() compareEditorsWithExpectedData() @@ -1610,5 +1610,5 @@ fun createChangeInfo( val declarations = callableDescriptor.safeAs()?.getDeepestSuperDeclarations() ?: listOf(callableDescriptor) val adjustedDescriptor = kotlinChangeSignature.adjustDescriptor(declarations) ?: return null val processor = kotlinChangeSignature.createSilentRefactoringProcessor(adjustedDescriptor) as KotlinChangeSignatureProcessor - return processor.ktChangeInfo.also { it.checkUsedParameters = true } + return processor.changeInfo.also { it.checkUsedParameters = true } } From eda301be2735645b7d64c4872fa38a06e1c1f8a3 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 3 Aug 2023 13:34:15 +0200 Subject: [PATCH 083/165] [kotlin] introduce: fix highlighted container GitOrigin-RevId: fee7b7638e0f16e4cd594e093eac3d08cdabcbca --- .../idea/refactoring/chooseContainer/chooseContainerUtil.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/chooseContainer/chooseContainerUtil.kt b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/chooseContainer/chooseContainerUtil.kt index a1379f954383..bdf04cc2cddc 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/chooseContainer/chooseContainerUtil.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/chooseContainer/chooseContainerUtil.kt @@ -145,9 +145,9 @@ private fun getPsiElementPopup( .presentationProvider(presentationProvider) .builderConsumer { builder -> builder - .setItemChosenCallback { presentation -> + .setItemSelectedCallback() { presentation -> highlighter?.dropHighlight() - val psiElement = (presentation?.item as? SmartPsiElementPointer<*>)?.element ?: return@setItemChosenCallback + val psiElement = (presentation?.item as? SmartPsiElementPointer<*>)?.element ?: return@setItemSelectedCallback highlighter?.highlight(psiElement) } .setItemChosenCallback { From 41e443d56c1abe58599f5ba529748f1a4b658324 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 23 Jun 2023 12:27:29 +0200 Subject: [PATCH 084/165] [Kotlin] Use stdlib-js.klib GitOrigin-RevId: 16395bfba8630bf2aca037985d0e58b48eca82a3 --- .../idea/base/plugin/artifacts/KotlinArtifactNames.kt | 2 +- .../kotlin/idea/artifacts/TestKotlinArtifacts.kt | 8 +++++++- .../kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt | 6 +++--- .../testData/multiplatform/useCorrectBuiltIns/js/js.kt | 5 ++--- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/plugins/kotlin/base/plugin/src/org/jetbrains/kotlin/idea/base/plugin/artifacts/KotlinArtifactNames.kt b/plugins/kotlin/base/plugin/src/org/jetbrains/kotlin/idea/base/plugin/artifacts/KotlinArtifactNames.kt index f268d4b86718..c6798fa0fa99 100644 --- a/plugins/kotlin/base/plugin/src/org/jetbrains/kotlin/idea/base/plugin/artifacts/KotlinArtifactNames.kt +++ b/plugins/kotlin/base/plugin/src/org/jetbrains/kotlin/idea/base/plugin/artifacts/KotlinArtifactNames.kt @@ -13,7 +13,7 @@ object KotlinArtifactNames { const val KOTLIN_STDLIB_JDK8 = "kotlin-stdlib-jdk8.jar" const val KOTLIN_STDLIB_JDK8_SOURCES = "kotlin-stdlib-jdk8-sources.jar" const val KOTLIN_REFLECT = "kotlin-reflect.jar" - const val KOTLIN_STDLIB_JS = "kotlin-stdlib-js.jar" + const val KOTLIN_STDLIB_JS = "kotlin-stdlib-js.klib" const val KOTLIN_TEST = "kotlin-test.jar" const val KOTLIN_TEST_JUNIT = "kotlin-test-junit.jar" const val KOTLIN_TEST_JS = "kotlin-test-js.jar" diff --git a/plugins/kotlin/base/plugin/test/org/jetbrains/kotlin/idea/artifacts/TestKotlinArtifacts.kt b/plugins/kotlin/base/plugin/test/org/jetbrains/kotlin/idea/artifacts/TestKotlinArtifacts.kt index 9913c0c89e3c..00c02b6ca9bb 100644 --- a/plugins/kotlin/base/plugin/test/org/jetbrains/kotlin/idea/artifacts/TestKotlinArtifacts.kt +++ b/plugins/kotlin/base/plugin/test/org/jetbrains/kotlin/idea/artifacts/TestKotlinArtifacts.kt @@ -57,7 +57,13 @@ object TestKotlinArtifacts { @JvmStatic val kotlinStdlibJdk7Sources: File by lazy { getSourcesJar("kotlin-stdlib-jdk7") } @JvmStatic val kotlinStdlibJdk8: File by lazy { getJar("kotlin-stdlib-jdk8") } @JvmStatic val kotlinStdlibJdk8Sources: File by lazy { getSourcesJar("kotlin-stdlib-jdk8") } - @JvmStatic val kotlinStdlibJs: File by lazy { getJar("kotlin-stdlib-js") } + @JvmStatic val kotlinStdlibJs: File by lazy { + downloadOrReportUnavailability( + "kotlin-stdlib-js", + KotlinMavenUtils.findLibraryVersion(kotlincStdlibFileName), + ".klib" + ) + } @JvmStatic val kotlinStdlibWasm: File by lazy { downloadOrReportUnavailability( "kotlin-stdlib-wasm", diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt index f4c47306fc21..99b64f70b2c7 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt @@ -2215,9 +2215,9 @@ class IdeaModuleInfoTest8 : JavaModuleTestCase() { private fun stdlibJvm(): LibraryEx = projectLibrary("kotlin-stdlib", TestKotlinArtifacts.kotlinStdlib.jarRoot) private fun stdlibJs(): LibraryEx = projectLibrary( - "kotlin-stdlib-js", - TestKotlinArtifacts.kotlinStdlibJs.jarRoot, - kind = KotlinJavaScriptLibraryKind + "kotlin-stdlib-js", + LocalFileSystem.getInstance().refreshAndFindFileByIoFile(TestKotlinArtifacts.kotlinStdlibJs), + kind = KotlinJavaScriptLibraryKind ) private fun stdlibWasm(): LibraryEx = projectLibrary( diff --git a/plugins/kotlin/idea/tests/testData/multiplatform/useCorrectBuiltIns/js/js.kt b/plugins/kotlin/idea/tests/testData/multiplatform/useCorrectBuiltIns/js/js.kt index 3025f2b21298..1ff11366f2c6 100644 --- a/plugins/kotlin/idea/tests/testData/multiplatform/useCorrectBuiltIns/js/js.kt +++ b/plugins/kotlin/idea/tests/testData/multiplatform/useCorrectBuiltIns/js/js.kt @@ -1,7 +1,6 @@ // !DIAGNOSTICS: -UNUSED_VARIABLE -import kotlinx.browser.window -import kotlinx.cinterop.CPointed +import kotlinx.cinterop.CPointed fun jvmSpecific(args: Array) { val x: Cloneable? = null @@ -13,5 +12,5 @@ fun nativeSpecific() { } fun jsSpecific() { - val windowClosed = window.closed + console.log("Hello") } \ No newline at end of file From 73190bc8412b95990f3846a48017fba1924ce603 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 23 Jun 2023 20:42:48 +0200 Subject: [PATCH 085/165] [Kotlin] stdlib.klib in js stdlib detection GitOrigin-RevId: 06265491c6503311e3ba62e41ab14d9ddeb3d904 --- .../platforms/KotlinJavaScriptStdlibDetectorFacility.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/kotlin/base/platforms/src/org/jetbrains/kotlin/idea/base/platforms/KotlinJavaScriptStdlibDetectorFacility.kt b/plugins/kotlin/base/platforms/src/org/jetbrains/kotlin/idea/base/platforms/KotlinJavaScriptStdlibDetectorFacility.kt index d1d5ee90da12..6eea2d0db29e 100644 --- a/plugins/kotlin/base/platforms/src/org/jetbrains/kotlin/idea/base/platforms/KotlinJavaScriptStdlibDetectorFacility.kt +++ b/plugins/kotlin/base/platforms/src/org/jetbrains/kotlin/idea/base/platforms/KotlinJavaScriptStdlibDetectorFacility.kt @@ -11,10 +11,12 @@ import org.jetbrains.kotlin.idea.base.plugin.artifacts.KotlinArtifactNames import org.jetbrains.kotlin.utils.LibraryUtils import org.jetbrains.kotlin.utils.PathUtil import java.io.File +import java.util.regex.Pattern @ApiStatus.Internal object KotlinJavaScriptStdlibDetectorFacility : StdlibDetectorFacility() { private val IS_JS_LIBRARY_STD_LIB = Key.create("IS_JS_LIBRARY_STD_LIB") + private val KOTLIN_JS_LIBRARY_KLIB_PATTERN = Pattern.compile("kotlin-stdlib-js.*\\.klib") override val supportedLibraryKind: KotlinLibraryKind get() = KotlinJavaScriptLibraryKind @@ -28,11 +30,13 @@ object KotlinJavaScriptStdlibDetectorFacility : StdlibDetectorFacility() { || name == "kotlin-jslib.jar" // Outdated JS stdlib name || PathUtil.KOTLIN_STDLIB_JS_JAR_PATTERN.matcher(name).matches() || PathUtil.KOTLIN_JS_LIBRARY_JAR_PATTERN.matcher(name).matches() + || KOTLIN_JS_LIBRARY_KLIB_PATTERN.matcher(name).matches() ) { val jar = VfsUtilCore.getVirtualFileForJar(root) ?: continue var isJSStdLib = jar.getUserData(IS_JS_LIBRARY_STD_LIB) if (isJSStdLib == null) { - isJSStdLib = LibraryUtils.isKotlinJavascriptStdLibrary(File(jar.path)) + isJSStdLib = KOTLIN_JS_LIBRARY_KLIB_PATTERN.matcher(name).matches() + || LibraryUtils.isKotlinJavascriptStdLibrary(File(jar.path)) jar.putUserData(IS_JS_LIBRARY_STD_LIB, isJSStdLib) } From a3abca4c959c82b73e76b95ac4e8d49a5211bba4 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Wed, 19 Jul 2023 15:24:58 +0200 Subject: [PATCH 086/165] Fix several tests that depend on exact sources layout in stdlib GitOrigin-RevId: cb4a39017a091fc71037e2000a45617a829e6cc0 --- .../tests/testData/codeInsight/hints/lambda/ImplicitIt.kt | 2 +- .../testData/codeInsight/hints/lambda/ImplicitThisAndIt.kt | 2 +- .../hints/lambda/ImplicitThisAndNamedSingleParameter.kt | 2 +- .../testData/codeInsight/hints/types/AnonymousObject.kt | 6 +++--- .../types/ConstructorWithoutExplicitTypeParametersType.kt | 2 +- .../codeInsight/hints/types/DefinitelyNonNullTypes.kt | 2 +- .../testData/codeInsight/hints/types/DestructingType.kt | 2 +- .../testData/codeInsight/hints/types/ExpandedTypeAlias.kt | 2 +- .../tests/testData/codeInsight/hints/types/JavaFQName.kt | 2 +- .../tests/testData/codeInsight/hints/types/LocalVariable.kt | 2 +- .../tests/testData/codeInsight/hints/types/LoopParameter.kt | 2 +- .../testData/codeInsight/hints/types/NestedClassImports.kt | 2 +- .../codeInsight/hints/types/NestedClassWithoutImport.kt | 2 +- .../tests/testData/codeInsight/hints/types/ParameterType.kt | 2 +- .../tests/testData/codeInsight/hints/types/PropertyType.kt | 2 +- .../testData/codeInsight/hints/types/UnitLocalVariable2.kt | 2 +- .../testData/codeInsight/hints/types/UnitLocalVariable3.kt | 2 +- .../idea/tests/testData/codeInsight/hints/types/When.kt | 2 +- .../projectView/AnnotationFromStdlibWithSources.txt | 2 +- .../tests/testData/projectView/ArraysJVMWithSources.txt | 2 +- .../idea/tests/testData/projectView/_ArraysWithSources.txt | 2 +- .../testData/projectView/_ArraysWithSourcesMembers.txt | 2 +- .../tests/testData/projectView/___ArraysJvmWithSources.txt | 2 +- .../maven/NavigateToMultiplatformJvmStdlibSourcesTest.kt | 2 +- 24 files changed, 26 insertions(+), 26 deletions(-) diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitIt.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitIt.kt index f8f7af46023c..8520fb42d381 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitIt.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitIt.kt @@ -1,4 +1,4 @@ // MODE: receivers_params -val x = listOf("").filter {/*<# [it: [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:618]String] #>*/ +val x = listOf("").filter {/*<# [it: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:618]String] #>*/ it.startsWith("") } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitThisAndIt.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitThisAndIt.kt index b162433c9ecb..7064f12e0752 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitThisAndIt.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitThisAndIt.kt @@ -1,5 +1,5 @@ // MODE: receivers_params -val x = foo {/*<# [[this: [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:618]String] [it: [jar://kotlin-stdlib-sources.jar!/kotlin/Primitives.kt:21054]Int]] #>*/ +val x = foo {/*<# [[this: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:618]String] [it: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Primitives.kt:21054]Int]] #>*/ } diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitThisAndNamedSingleParameter.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitThisAndNamedSingleParameter.kt index ef1151fc4fd0..558d0c6f3311 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitThisAndNamedSingleParameter.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/lambda/ImplicitThisAndNamedSingleParameter.kt @@ -1,5 +1,5 @@ // MODE: receivers_params -val x = foo {/*<# [this: [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:618]String] #>*/ props -> +val x = foo {/*<# [this: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:618]String] #>*/ props -> } diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/AnonymousObject.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/AnonymousObject.kt index a9adaf620f39..bf5b48f230f9 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/AnonymousObject.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/AnonymousObject.kt @@ -1,7 +1,7 @@ // MODE: function_return val o = object : Iterable { - override fun iterator()/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Iterator.kt:*]Iterator < [jar://kotlin-stdlib-sources.jar!/kotlin/Primitives.kt:*]Int >] #>*/ = object : Iterator { - override fun next()/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Primitives.kt:*]Int] #>*/ = 1 - override fun hasNext()/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Boolean.kt:*]Boolean] #>*/ = true + override fun iterator()/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Iterator.kt:*]Iterator < [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Primitives.kt:*]Int >] #>*/ = object : Iterator { + override fun next()/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Primitives.kt:*]Int] #>*/ = 1 + override fun hasNext()/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Boolean.kt:*]Boolean] #>*/ = true } } diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ConstructorWithoutExplicitTypeParametersType.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ConstructorWithoutExplicitTypeParametersType.kt index 527a39bc59f8..4cfb0727e677 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ConstructorWithoutExplicitTypeParametersType.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ConstructorWithoutExplicitTypeParametersType.kt @@ -1,2 +1,2 @@ // MODE: property -class Bar(val t: T); val a/*<# [: [temp:///src/KotlinReferencesTypeHintsProvider.kt:0]Bar < [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:*]String >] #>*/ = Bar("") \ No newline at end of file +class Bar(val t: T); val a/*<# [: [temp:///src/KotlinReferencesTypeHintsProvider.kt:0]Bar < [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:*]String >] #>*/ = Bar("") \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/DefinitelyNonNullTypes.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/DefinitelyNonNullTypes.kt index b543adf843fd..73c826e7a6a3 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/DefinitelyNonNullTypes.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/DefinitelyNonNullTypes.kt @@ -2,4 +2,4 @@ fun inlayHint(x: T & Any)/*<# [: []T & Any] #>*/ = x fun takeFun(f: (T & Any) -> Unit) {} -fun inlayHint2()/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Unit.kt:*]Unit] #>*/ = takeFun { it/*<# [: []T & Any] #>*/ -> println(it)} +fun inlayHint2()/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Unit.kt:*]Unit] #>*/ = takeFun { it/*<# [: []T & Any] #>*/ -> println(it)} diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/DestructingType.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/DestructingType.kt index 21f4c4caaca0..3821a1aea777 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/DestructingType.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/DestructingType.kt @@ -1,2 +1,2 @@ // MODE: local_variable -fun foo() { val (i/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Primitives.kt:*]Int] #>*/, s/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:*]String] #>*/) = 1 to "" } \ No newline at end of file +fun foo() { val (i/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Primitives.kt:*]Int] #>*/, s/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:*]String] #>*/) = 1 to "" } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ExpandedTypeAlias.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ExpandedTypeAlias.kt index 9c180a26e30d..f662686da6a7 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ExpandedTypeAlias.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ExpandedTypeAlias.kt @@ -1,2 +1,2 @@ // MODE: property -val x/*<# [: [jar://kotlin-stdlib-common-sources.jar!/kotlin/collections/ArrayList.kt:*]ArrayList < [jar://kotlin-stdlib-sources.jar!/kotlin/Primitives.kt:*]Int >] #>*/ = arrayListOf(1) +val x/*<# [: [jar://kotlin-stdlib-sources.jar!/commonMain/kotlin/collections/ArrayList.kt:*]ArrayList < [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Primitives.kt:*]Int >] #>*/ = arrayListOf(1) diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/JavaFQName.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/JavaFQName.kt index d0d84997ef02..ce2efcbd360f 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/JavaFQName.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/JavaFQName.kt @@ -1,3 +1,3 @@ // MODE: all val x = java.util.ArrayList() -val q/*<# [: [jar://rt.jar!/java/util/ArrayList.class:*]ArrayList < [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:*]String >] #>*/ = x \ No newline at end of file +val q/*<# [: [jar://rt.jar!/java/util/ArrayList.class:*]ArrayList < [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:*]String >] #>*/ = x \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/LocalVariable.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/LocalVariable.kt index 7e9640f98f4c..9b6ae5d7ad7d 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/LocalVariable.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/LocalVariable.kt @@ -1,2 +1,2 @@ // MODE: local_variable -fun foo() { val a/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Collections.kt:*]List < [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:*]String >] #>*/ = listOf("a") } \ No newline at end of file +fun foo() { val a/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Collections.kt:*]List < [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:*]String >] #>*/ = listOf("a") } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/LoopParameter.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/LoopParameter.kt index 987b19449c14..a65388e1c8f9 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/LoopParameter.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/LoopParameter.kt @@ -1,2 +1,2 @@ // MODE: local_variable -fun foo() { for (x/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:*]String] #>*/ in listOf("a")) { } } \ No newline at end of file +fun foo() { for (x/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:*]String] #>*/ in listOf("a")) { } } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/NestedClassImports.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/NestedClassImports.kt index 25122ba0a975..1ea661dc9f2d 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/NestedClassImports.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/NestedClassImports.kt @@ -1,3 +1,3 @@ // MODE: property import kotlin.collections.Map.Entry -val entries/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Collections.kt:*]Set < [jar://kotlin-stdlib-sources.jar!/kotlin/Collections.kt:*]Entry < [jar://kotlin-stdlib-sources.jar!/kotlin/Primitives.kt:*]Int , [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:*]String >>] #>*/ = mapOf(1 to "1").entries \ No newline at end of file +val entries/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Collections.kt:*]Set < [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Collections.kt:*]Entry < [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Primitives.kt:*]Int , [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:*]String >>] #>*/ = mapOf(1 to "1").entries \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/NestedClassWithoutImport.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/NestedClassWithoutImport.kt index 8854e835d9be..415a663fe764 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/NestedClassWithoutImport.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/NestedClassWithoutImport.kt @@ -1,2 +1,2 @@ // MODE: property -val entries/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Collections.kt:*]Set < [jar://kotlin-stdlib-sources.jar!/kotlin/Collections.kt:*]Map.Entry < [jar://kotlin-stdlib-sources.jar!/kotlin/Primitives.kt:*]Int , [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:*]String >>] #>*/ = mapOf(1 to "1").entries \ No newline at end of file +val entries/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Collections.kt:*]Set < [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Collections.kt:*]Map.Entry < [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Primitives.kt:*]Int , [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:*]String >>] #>*/ = mapOf(1 to "1").entries \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ParameterType.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ParameterType.kt index 118206f66695..42b04ef51dda 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ParameterType.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/ParameterType.kt @@ -1,7 +1,7 @@ // MODE: parameter fun T.wrap(lambda: (T) -> T) {} fun foo() { - 12.wrap { elem/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Primitives.kt:*]Int] #>*/ -> + 12.wrap { elem/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Primitives.kt:*]Int] #>*/ -> elem } } diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/PropertyType.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/PropertyType.kt index cb5e840815d8..be5a53d00ded 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/PropertyType.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/PropertyType.kt @@ -1,2 +1,2 @@ // MODE: property -val a/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Collections.kt:*]List < [jar://kotlin-stdlib-sources.jar!/kotlin/String.kt:*]String >] #>*/ = listOf("a") +val a/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Collections.kt:*]List < [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/String.kt:*]String >] #>*/ = listOf("a") diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/UnitLocalVariable2.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/UnitLocalVariable2.kt index 3c272be46d20..20c06da2fb85 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/UnitLocalVariable2.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/UnitLocalVariable2.kt @@ -1,5 +1,5 @@ // MODE: all fun foo() { - val x/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Unit.kt:*]Unit] #>*/ = + val x/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Unit.kt:*]Unit] #>*/ = println("Foo") // indent differs } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/UnitLocalVariable3.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/UnitLocalVariable3.kt index 5e1db4a10127..e70a461e52c1 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/UnitLocalVariable3.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/UnitLocalVariable3.kt @@ -1,4 +1,4 @@ // MODE: local_variable fun foo() { - val x/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Unit.kt:*]Unit] #>*/ = println("Foo") + val x/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Unit.kt:*]Unit] #>*/ = println("Foo") } diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/When.kt b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/When.kt index 14254e62c265..b5df2cef5a81 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/When.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/hints/types/When.kt @@ -1,5 +1,5 @@ // MODE: all -val x/*<# [: [jar://kotlin-stdlib-sources.jar!/kotlin/Primitives.kt:*]Int] #>*/ = run { +val x/*<# [: [jar://kotlin-stdlib-sources.jar!/jvmMain/kotlin/Primitives.kt:*]Int] #>*/ = run { when (true) { true -> 1 false -> 0 diff --git a/plugins/kotlin/idea/tests/testData/projectView/AnnotationFromStdlibWithSources.txt b/plugins/kotlin/idea/tests/testData/projectView/AnnotationFromStdlibWithSources.txt index 796a5f40ddd0..41f64935cfa8 100644 --- a/plugins/kotlin/idea/tests/testData/projectView/AnnotationFromStdlibWithSources.txt +++ b/plugins/kotlin/idea/tests/testData/projectView/AnnotationFromStdlibWithSources.txt @@ -7,7 +7,7 @@ Value file: kotlin-stdlib.jar!/kotlin/annotation/AnnotationTarget.class Navigation item #0: CLASS Navigation item file #0: kotlin-stdlib.jar!/kotlin/annotation/AnnotationTarget.class Navigation item #1: CLASS -Navigation item file #1: kotlin-stdlib-sources.jar!/kotlin/annotation/Annotations.kt +Navigation item file #1: kotlin-stdlib-sources.jar!/jvmMain/kotlin/annotation/Annotations.kt -Project diff --git a/plugins/kotlin/idea/tests/testData/projectView/ArraysJVMWithSources.txt b/plugins/kotlin/idea/tests/testData/projectView/ArraysJVMWithSources.txt index 3ce69eeb3712..b83bb84e2ebc 100644 --- a/plugins/kotlin/idea/tests/testData/projectView/ArraysJVMWithSources.txt +++ b/plugins/kotlin/idea/tests/testData/projectView/ArraysJVMWithSources.txt @@ -5,7 +5,7 @@ Value: KtLightClassForDecompiledDeclaration of PsiFile:ArraysKt__ArraysJVMKt.cla Value file: kotlin-stdlib.jar!/kotlin/collections/ArraysKt__ArraysJVMKt.class Navigation item #0: KtFile: ArraysJVM.kt -Navigation item file #0: kotlin-stdlib-sources.jar!/kotlin/collections/ArraysJVM.kt +Navigation item file #0: kotlin-stdlib-sources.jar!/jvmMain/kotlin/collections/ArraysJVM.kt -Project diff --git a/plugins/kotlin/idea/tests/testData/projectView/_ArraysWithSources.txt b/plugins/kotlin/idea/tests/testData/projectView/_ArraysWithSources.txt index f23ca0d37fd5..283cb53e7a92 100644 --- a/plugins/kotlin/idea/tests/testData/projectView/_ArraysWithSources.txt +++ b/plugins/kotlin/idea/tests/testData/projectView/_ArraysWithSources.txt @@ -5,7 +5,7 @@ Value: KtLightClassForDecompiledDeclaration of PsiFile:ArraysKt___ArraysKt.class Value file: kotlin-stdlib.jar!/kotlin/collections/ArraysKt___ArraysKt.class Navigation item #0: KtFile: _Arrays.kt -Navigation item file #0: kotlin-stdlib-common-sources.jar!/generated/_Arrays.kt +Navigation item file #0: kotlin-stdlib-sources.jar!/commonMain/generated/_Arrays.kt -Project diff --git a/plugins/kotlin/idea/tests/testData/projectView/_ArraysWithSourcesMembers.txt b/plugins/kotlin/idea/tests/testData/projectView/_ArraysWithSourcesMembers.txt index ddd722080428..5af032da39d9 100644 --- a/plugins/kotlin/idea/tests/testData/projectView/_ArraysWithSourcesMembers.txt +++ b/plugins/kotlin/idea/tests/testData/projectView/_ArraysWithSourcesMembers.txt @@ -5,7 +5,7 @@ Value: KtLightClassForDecompiledDeclaration of PsiFile:ArraysKt___ArraysKt.class Value file: kotlin-stdlib.jar!/kotlin/collections/ArraysKt___ArraysKt.class Navigation item #0: KtFile: _Arrays.kt -Navigation item file #0: kotlin-stdlib-common-sources.jar!/generated/_Arrays.kt +Navigation item file #0: kotlin-stdlib-sources.jar!/commonMain/generated/_Arrays.kt -Project diff --git a/plugins/kotlin/idea/tests/testData/projectView/___ArraysJvmWithSources.txt b/plugins/kotlin/idea/tests/testData/projectView/___ArraysJvmWithSources.txt index d33f12c02f9f..28deb9439b4d 100644 --- a/plugins/kotlin/idea/tests/testData/projectView/___ArraysJvmWithSources.txt +++ b/plugins/kotlin/idea/tests/testData/projectView/___ArraysJvmWithSources.txt @@ -5,7 +5,7 @@ Value: KtLightClassForDecompiledDeclaration of PsiFile:ArraysKt___ArraysJvmKt.cl Value file: kotlin-stdlib.jar!/kotlin/collections/ArraysKt___ArraysJvmKt.class Navigation item #0: KtFile: _ArraysJvm.kt -Navigation item file #0: kotlin-stdlib-sources.jar!/generated/_ArraysJvm.kt +Navigation item file #0: kotlin-stdlib-sources.jar!/jvmMain/generated/_ArraysJvm.kt -Project diff --git a/plugins/kotlin/maven/tests/test/org/jetbrains/kotlin/idea/maven/NavigateToMultiplatformJvmStdlibSourcesTest.kt b/plugins/kotlin/maven/tests/test/org/jetbrains/kotlin/idea/maven/NavigateToMultiplatformJvmStdlibSourcesTest.kt index 11b8d01b153f..c11eb6f067b0 100644 --- a/plugins/kotlin/maven/tests/test/org/jetbrains/kotlin/idea/maven/NavigateToMultiplatformJvmStdlibSourcesTest.kt +++ b/plugins/kotlin/maven/tests/test/org/jetbrains/kotlin/idea/maven/NavigateToMultiplatformJvmStdlibSourcesTest.kt @@ -29,7 +29,7 @@ class NavigateToMultipartJvmStdlibSourcesTest : LightJavaCodeInsightFixtureTestC mapOf("" to "").mapNotNull { } } """.trimIndent()) - assertEquals("", stdlibCommonElement?.moduleInfo?.name.toString()) + assertEquals("", stdlibCommonElement?.moduleInfo?.name.toString()) val stdlibJvmElement = configureAndResolve(""" fun bar() { From 082b2a9014edd709ecbb2dd8ad7e082c17ab46dc Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Wed, 2 Aug 2023 18:59:38 +0300 Subject: [PATCH 087/165] [kotlin] fix a test after a k2 change ^KT-59901 GitOrigin-RevId: 51bb20975357839d38d23cf1c0c9b6f792de4726 --- .../kotlin/findTypeAliasUsages/classAlias.fir.results.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.fir.results.txt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.fir.results.txt index 57ca5ef0fc98..b13de724d422 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.fir.results.txt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.fir.results.txt @@ -1,6 +1,5 @@ Function return types 26 fun f2(par: Alias, par2: OOO) : Alias { Local variable declaration 28 val a: Alias -Nested class/object 35 Alias.CONST //not found in K1, found in K2 Parameter type 26 fun f2(par: Alias, par2: OOO) : Alias { Supertype 15 class Child : Alias() { Target type of 'is' operation 38 if (par2 is Alias) {} From 215e085b3dccf54b6722d5d2f306a0f39c4a8801 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 4 Aug 2023 15:43:03 +0200 Subject: [PATCH 088/165] [kotlin] [rename] accept implicit primary constructor as rename target KTIJ-26529 GitOrigin-RevId: c569cd2afb76e5481a6ba0fd050b84e8571767d1 --- .../idea/refactoring/rename/RenameTestGenerated.java | 5 +++++ .../renameKotlinClassByConstructorRef/before/test.kt | 2 +- .../after/test.kt | 8 ++++++++ .../before/test.kt | 8 ++++++++ .../kotlinClass.test | 7 +++++++ .../RenameSyntheticDeclarationByReferenceHandler.kt | 3 ++- .../k2/refactoring/rename/FirRenameTestGenerated.java | 5 +++++ 7 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/after/test.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/before/test.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/kotlinClass.test diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java index e1fbad6755cd..63bd9f0206c1 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java @@ -753,6 +753,11 @@ public class RenameTestGenerated extends AbstractRenameTest { runTest("testData/refactoring/rename/renameKotlinClassByConstructorRef/kotlinClass.test"); } + @TestMetadata("renameKotlinClassByImplicitConstructorRef/kotlinClass.test") + public void testRenameKotlinClassByImplicitConstructorRef_KotlinClass() throws Exception { + runTest("testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/kotlinClass.test"); + } + @TestMetadata("renameKotlinClassConstructor/renameKotlinConstructor.test") public void testRenameKotlinClassConstructor_RenameKotlinConstructor() throws Exception { runTest("testData/refactoring/rename/renameKotlinClassConstructor/renameKotlinConstructor.test"); diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByConstructorRef/before/test.kt b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByConstructorRef/before/test.kt index 98e3d1bb817b..98041d62f67d 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByConstructorRef/before/test.kt +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByConstructorRef/before/test.kt @@ -1,6 +1,6 @@ package testing.rename -public open class A() { +public open class A { } fun test() { diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/after/test.kt b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/after/test.kt new file mode 100644 index 000000000000..13becc38b4dd --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/after/test.kt @@ -0,0 +1,8 @@ +package testing.rename + +public open class B() { +} + +fun test() { + B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/before/test.kt b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/before/test.kt new file mode 100644 index 000000000000..98e3d1bb817b --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/before/test.kt @@ -0,0 +1,8 @@ +package testing.rename + +public open class A() { +} + +fun test() { + /*rename*/A() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/kotlinClass.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/kotlinClass.test new file mode 100644 index 000000000000..f433352d5e08 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/kotlinClass.test @@ -0,0 +1,7 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "B", + "byRef": "true", + "enabledInK2": true +} \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameSyntheticDeclarationByReferenceHandler.kt b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameSyntheticDeclarationByReferenceHandler.kt index 350df0b8698d..82ab0b0a1a87 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameSyntheticDeclarationByReferenceHandler.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameSyntheticDeclarationByReferenceHandler.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.idea.refactoring.rename.handlers import com.intellij.openapi.util.NlsContexts.DialogMessage import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.symbols.KtConstructorSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin import org.jetbrains.kotlin.idea.base.resources.KotlinBundle @@ -10,7 +11,7 @@ import org.jetbrains.kotlin.idea.base.resources.KotlinBundle internal class RenameSyntheticDeclarationByReferenceHandler : AbstractForbidRenamingSymbolByReferenceHandler() { context(KtAnalysisSession) override fun shouldForbidRenaming(symbol: KtSymbol): Boolean { - return symbol.origin == KtSymbolOrigin.SOURCE_MEMBER_GENERATED + return symbol.origin == KtSymbolOrigin.SOURCE_MEMBER_GENERATED && !(symbol is KtConstructorSymbol && symbol.isPrimary) } override fun getErrorMessage(): @DialogMessage String { diff --git a/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/FirRenameTestGenerated.java b/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/FirRenameTestGenerated.java index b68573f36341..0b83bbc0ff10 100644 --- a/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/FirRenameTestGenerated.java +++ b/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/FirRenameTestGenerated.java @@ -753,6 +753,11 @@ public class FirRenameTestGenerated extends AbstractFirRenameTest { runTest("../../idea/tests/testData/refactoring/rename/renameKotlinClassByConstructorRef/kotlinClass.test"); } + @TestMetadata("renameKotlinClassByImplicitConstructorRef/kotlinClass.test") + public void testRenameKotlinClassByImplicitConstructorRef_KotlinClass() throws Exception { + runTest("../../idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/kotlinClass.test"); + } + @TestMetadata("renameKotlinClassConstructor/renameKotlinConstructor.test") public void testRenameKotlinClassConstructor_RenameKotlinConstructor() throws Exception { runTest("../../idea/tests/testData/refactoring/rename/renameKotlinClassConstructor/renameKotlinConstructor.test"); From 856faddc6bbe32a409d8c68580d8b163606beae0 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 4 Aug 2023 15:51:34 +0200 Subject: [PATCH 089/165] [kotlin] k2: allow analyze under write action KTIJ-26538 GitOrigin-RevId: 419a4020951e19b8dc6345c0f605a72d9dc8f05d --- .../SymbolBasedAbstractKotlinVariableMacro.kt | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/plugins/kotlin/code-insight/live-templates-k2/src/org/jetbrains/kotlin/idea/liveTemplates/k2/macro/SymbolBasedAbstractKotlinVariableMacro.kt b/plugins/kotlin/code-insight/live-templates-k2/src/org/jetbrains/kotlin/idea/liveTemplates/k2/macro/SymbolBasedAbstractKotlinVariableMacro.kt index df4fb713e673..6891fa459370 100644 --- a/plugins/kotlin/code-insight/live-templates-k2/src/org/jetbrains/kotlin/idea/liveTemplates/k2/macro/SymbolBasedAbstractKotlinVariableMacro.kt +++ b/plugins/kotlin/code-insight/live-templates-k2/src/org/jetbrains/kotlin/idea/liveTemplates/k2/macro/SymbolBasedAbstractKotlinVariableMacro.kt @@ -7,10 +7,12 @@ import com.intellij.codeInsight.template.ExpressionContext import com.intellij.codeInsight.template.Result import com.intellij.codeInsight.template.TextResult import com.intellij.psi.PsiDocumentManager +import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisFromWriteAction import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.components.KtScopeKind +import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisFromWriteAction import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.idea.base.codeInsight.ExpectedExpressionMatcherProvider @@ -64,18 +66,21 @@ abstract class SymbolBasedAbstractKotlinVariableMacro : KotlinMacro() { val contextElement = targetElement.getNonStrictParentOfType() ?: return null allowAnalysisOnEdt { - analyze(contextElement) { - val matcher = with (ExpectedExpressionMatcherProvider) { - if (filterByExpectedType) get(contextElement) else null + @OptIn(KtAllowAnalysisFromWriteAction::class) + allowAnalysisFromWriteAction { + analyze(contextElement) { + val matcher = with (ExpectedExpressionMatcherProvider) { + if (filterByExpectedType) get(contextElement) else null + } + + val scope = file.getScopeContextForPosition(contextElement).getCompositeScope { it !is KtScopeKind.ImportingScope } + val variables = scope.getCallableSymbols() + .filterIsInstance() + .filter { !it.name.isSpecial && shouldDisplayVariable(it, file) } + .filter { matcher == null || matcher. match(it.returnType) } + + return mapper(this@analyze, file, variables) } - - val scope = file.getScopeContextForPosition(contextElement).getCompositeScope { it !is KtScopeKind.ImportingScope } - val variables = scope.getCallableSymbols() - .filterIsInstance() - .filter { !it.name.isSpecial && shouldDisplayVariable(it, file) } - .filter { matcher == null || matcher. match(it.returnType) } - - return mapper(this@analyze, file, variables) } } } From b67a4f2f123f8745dab4a9d304af6d7c7e8917cb Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Fri, 4 Aug 2023 18:51:16 +0200 Subject: [PATCH 090/165] [kotlin] [rename] Adjust testdata Fixup for c569cd2afb76e5481a6ba0fd050b84e8571767d1 GitOrigin-RevId: 768abcb9d8b417525c7672f591ebb44767d77c71 --- .../rename/renameKotlinClassByConstructorRef/before/test.kt | 2 +- .../renameKotlinClassByImplicitConstructorRef/after/test.kt | 2 +- .../renameKotlinClassByImplicitConstructorRef/before/test.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByConstructorRef/before/test.kt b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByConstructorRef/before/test.kt index 98041d62f67d..98e3d1bb817b 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByConstructorRef/before/test.kt +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByConstructorRef/before/test.kt @@ -1,6 +1,6 @@ package testing.rename -public open class A { +public open class A() { } fun test() { diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/after/test.kt b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/after/test.kt index 13becc38b4dd..5db915c9bf32 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/after/test.kt +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/after/test.kt @@ -1,6 +1,6 @@ package testing.rename -public open class B() { +public open class B { } fun test() { diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/before/test.kt b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/before/test.kt index 98e3d1bb817b..98041d62f67d 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/before/test.kt +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/renameKotlinClassByImplicitConstructorRef/before/test.kt @@ -1,6 +1,6 @@ package testing.rename -public open class A() { +public open class A { } fun test() { From ff6f4ef03b28710290fa84a9a9058b5fe6afd5db Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Fri, 4 Aug 2023 17:18:03 +0200 Subject: [PATCH 091/165] [kotlin][uast] avoid expensive implicitReturn call We can avoid resolve in many cases by PSI checks. Before this change, any getParent for statements inside a lambda led to resolve ^KTIJ-26541 Fixed GitOrigin-RevId: 70db1b191990afceea1729c4d9cfb941c0683c82 --- .../uast/kotlin/kotlinConvertParentUtils.kt | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/kotlinConvertParentUtils.kt b/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/kotlinConvertParentUtils.kt index 7ab4a67a64f0..898038751253 100644 --- a/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/kotlinConvertParentUtils.kt +++ b/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/kotlinConvertParentUtils.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.psi.psiUtil.isPropertyParameter import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments @@ -227,17 +228,23 @@ internal fun convertParentImpl( }.expressions.single() } - if (result is KotlinULambdaExpression.Body - && element is UExpression - && element.sourcePsi != null - && result.implicitReturn?.returnExpression?.sourcePsi == element.sourcePsi - ) { - return result.implicitReturn!! + if (result is KotlinULambdaExpression.Body && element is UExpression && element.sourcePsi?.canBeImplicitReturnIn(result) == true) { + result.implicitReturn?.takeIf { it.returnExpression.sourcePsi == element.sourcePsi }?.let { return it } } return result } +private fun PsiElement.canBeImplicitReturnIn(body: KotlinULambdaExpression.Body): Boolean { + val lastStatement = body.sourcePsi.statements.lastOrNull() ?: return false + // It is _explicit_ return so we skip + if (lastStatement is KtReturnExpression) return false + + // We can't be sure that lastStatement after transformations will contain exactly the last statement element, + // so we play safe here + return lastStatement.isAncestor(this, strict = false) +} + private fun isInConditionBranch(element: UElement, result: USwitchClauseExpressionWithBody) = element.psi?.parentsWithSelf?.takeWhile { it !== result.psi }?.any { it is KtWhenCondition } ?: false From b3b0bf0997fe4187e39dd54f5026b52f6aa61e97 Mon Sep 17 00:00:00 2001 From: "Alexander.Danilov" Date: Tue, 1 Aug 2023 11:23:52 +0200 Subject: [PATCH 092/165] Add line markers tests to K2: main, run, method separators (cherry picked from commit c0e80fb61a8d78c54842e99b432d00d0e47009de) GitOrigin-RevId: 14a53d7fc8da22e0a543a6acdf15e790a2b529e8 --- .../kotlin.code-insight.line-markers-k2.iml | 2 + .../test/AbstractLineMarkerTest.kt | 39 +++++++++----- .../test/LineMarkerTestGenerated.java | 52 +++++++++++++++++++ .../codeInsight/LineMarkersTestGenerated.java | 26 +++++----- .../MethodSeparators.kt | 3 ++ .../codeinsight/GenerateK2LineMarkerTests.kt | 4 ++ 6 files changed, 101 insertions(+), 25 deletions(-) rename plugins/kotlin/idea/tests/testData/codeInsight/lineMarker/{ => methodSeparators}/MethodSeparators.kt (96%) diff --git a/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml b/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml index 54ceb23dfc15..9fae6e2bfe3f 100644 --- a/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml +++ b/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml @@ -39,6 +39,8 @@ + + diff --git a/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkerTest.kt b/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkerTest.kt index 75dc4201e902..347630da4701 100644 --- a/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkerTest.kt +++ b/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkerTest.kt @@ -1,6 +1,7 @@ // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.k2.codeInsight.lineMarkers.test +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings import com.intellij.codeInsight.daemon.GutterIconDescriptor import com.intellij.codeInsight.daemon.LineMarkerSettings import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl @@ -11,29 +12,34 @@ import org.jetbrains.kotlin.idea.base.test.KotlinExpectedHighlightingData import org.jetbrains.kotlin.idea.base.test.KotlinJvmLightProjectDescriptor import org.jetbrains.kotlin.idea.base.test.NewLightKotlinCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.highlighter.markers.KotlinLineMarkerOptions +import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import org.jetbrains.kotlin.test.InTextDirectivesUtils -import java.nio.file.Paths +import org.jetbrains.kotlin.test.utils.IgnoreTests abstract class AbstractLineMarkerTest : NewLightKotlinCodeInsightFixtureTestCase() { override val pluginKind: KotlinPluginKind get() = KotlinPluginKind.FIR_PLUGIN - protected fun performTest() { + private fun checkLineMarkers() { myFixture.configureDependencies() myFixture.configureByDefaultFile() val file = testRootPath.resolve(testMethodPath).toFile() val fileText = FileUtil.loadFile(file) + ConfigLibraryUtil.configureLibrariesByDirective(myFixture.module, fileText) + InTextDirectivesUtils.findStringWithPrefixes(fileText, "METHOD_SEPARATORS")?.let { + DaemonCodeAnalyzerSettings.getInstance().SHOW_METHOD_SEPARATORS = true + } val disabledOptions = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, "// OPTION: ") - .mapNotNull { - if (it.startsWith("-")) { - val optionName = it.substring(1) - val field = KotlinLineMarkerOptions::class.java.getDeclaredField(optionName) - field.isAccessible = true - field.get(KotlinLineMarkerOptions) as GutterIconDescriptor - } else { - null - } - } + .mapNotNull { + if (it.startsWith("-")) { + val optionName = it.substring(1) + val field = KotlinLineMarkerOptions::class.java.getDeclaredField(optionName) + field.isAccessible = true + field.get(KotlinLineMarkerOptions) as GutterIconDescriptor + } else { + null + } + } disabledOptions.forEach { LineMarkerSettings.getSettings().setEnabled(it, false) } @@ -48,11 +54,20 @@ abstract class AbstractLineMarkerTest : NewLightKotlinCodeInsightFixtureTestCase try { ActionUtil.underModalProgress(myFixture.project, "") { data.checkLineMarkers(myFixture.file, lineMarkers, document.text) } } finally { + ConfigLibraryUtil.unconfigureLibrariesByDirective(module, fileText) + DaemonCodeAnalyzerSettings.getInstance().SHOW_METHOD_SEPARATORS = false disabledOptions.forEach { LineMarkerSettings.getSettings().setEnabled(it, true) } } } + protected fun performTest() { + IgnoreTests.runTestIfNotDisabledByFileDirective(testRootPath.resolve(testMethodPath), IgnoreTests.DIRECTIVES.IGNORE_FIR) { + checkLineMarkers() + } + + } + override fun getProjectDescriptor() = KotlinJvmLightProjectDescriptor.DEFAULT } \ No newline at end of file diff --git a/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/LineMarkerTestGenerated.java b/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/LineMarkerTestGenerated.java index 155375d3776e..73baaeab5f70 100644 --- a/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/LineMarkerTestGenerated.java +++ b/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/LineMarkerTestGenerated.java @@ -387,4 +387,56 @@ public abstract class LineMarkerTestGenerated extends AbstractLineMarkerTest { performTest(); } } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/codeInsight/lineMarker/main") + public static class Main extends AbstractLineMarkerTest { + @TestMetadata("main.kt") + public void testMain() throws Exception { + performTest(); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/codeInsight/lineMarker/runMarkers") + public static class RunMarkers extends AbstractLineMarkerTest { + @TestMetadata("jUnit3TestFile.kt") + public void testJUnit3TestFile() throws Exception { + performTest(); + } + + @TestMetadata("jUnit3TestFileWithJUnit4.kt") + public void testJUnit3TestFileWithJUnit4() throws Exception { + performTest(); + } + + @TestMetadata("jUnit4TestFile.kt") + public void testJUnit4TestFile() throws Exception { + performTest(); + } + + @TestMetadata("jUnit5TestFile.kt") + public void testJUnit5TestFile() throws Exception { + performTest(); + } + + @TestMetadata("jUnitTestClassWithSubclasses.kt") + public void testJUnitTestClassWithSubclasses() throws Exception { + performTest(); + } + + @TestMetadata("testNGTestClassWithSubclasses.kt") + public void testTestNGTestClassWithSubclasses() throws Exception { + performTest(); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/codeInsight/lineMarker/methodSeparators") + public static class MethodSeparators extends AbstractLineMarkerTest { + @TestMetadata("MethodSeparators.kt") + public void testMethodSeparators() throws Exception { + performTest(); + } + } } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java index 9008a726adbd..d918946d0500 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java @@ -45,6 +45,19 @@ public abstract class LineMarkersTestGenerated extends AbstractLineMarkersTest { } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("testData/codeInsight/lineMarker/methodSeparators") + public static class MethodSeparators extends AbstractLineMarkersTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("MethodSeparators.kt") + public void testMethodSeparators() throws Exception { + runTest("testData/codeInsight/lineMarker/methodSeparators/MethodSeparators.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("testData/codeInsight/lineMarker/overrideImplement") public static class OverrideImplement extends AbstractLineMarkersTest { @@ -396,17 +409,4 @@ public abstract class LineMarkersTestGenerated extends AbstractLineMarkersTest { runTest("testData/codeInsight/lineMarker/suspendCall/suspendIteration.kt"); } } - - @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("testData/codeInsight/lineMarker") - public static class Uncategorized extends AbstractLineMarkersTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); - } - - @TestMetadata("MethodSeparators.kt") - public void testMethodSeparators() throws Exception { - runTest("testData/codeInsight/lineMarker/MethodSeparators.kt"); - } - } } diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/lineMarker/MethodSeparators.kt b/plugins/kotlin/idea/tests/testData/codeInsight/lineMarker/methodSeparators/MethodSeparators.kt similarity index 96% rename from plugins/kotlin/idea/tests/testData/codeInsight/lineMarker/MethodSeparators.kt rename to plugins/kotlin/idea/tests/testData/codeInsight/lineMarker/methodSeparators/MethodSeparators.kt index a63ddc5e07c2..8f87df7b2248 100644 --- a/plugins/kotlin/idea/tests/testData/codeInsight/lineMarker/MethodSeparators.kt +++ b/plugins/kotlin/idea/tests/testData/codeInsight/lineMarker/methodSeparators/MethodSeparators.kt @@ -1,5 +1,8 @@ // METHOD_SEPARATORS +// KTIJ-26470 +// IGNORE_FIR + class Foo { object BarObj { } diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2LineMarkerTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2LineMarkerTests.kt index 890040153172..db81e9b31237 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2LineMarkerTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2LineMarkerTests.kt @@ -11,6 +11,10 @@ internal fun MutableTWorkspace.generateK2LineMarkerTests() { model("suspend", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) model("../../../idea/tests/testData/codeInsight/lineMarker/overrideImplement", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) model("../../../idea/tests/testData/codeInsight/lineMarker/dslMarker", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) + model("../../../idea/tests/testData/codeInsight/lineMarker/main", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) + model("../../../idea/tests/testData/codeInsight/lineMarker/runMarkers", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) + model("../../../idea/tests/testData/codeInsight/lineMarker/methodSeparators", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) + } } } \ No newline at end of file From e45a32f7ae307a49513833367338370ec1391cc8 Mon Sep 17 00:00:00 2001 From: "Alexander.Danilov" Date: Wed, 2 Aug 2023 23:43:51 +0200 Subject: [PATCH 093/165] [kotlin] [search] Place inside read-action ^KTIJ-26505 fixed (cherry picked from commit 18a53f771255856ba2d24f0cd8777a3521dd83a9) GitOrigin-RevId: 3fabf64ad90c32543f52e14cf4920c737cdd6bce --- .../searching/inheritors/KotlinFirDefinitionsSearcher.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/inheritors/KotlinFirDefinitionsSearcher.kt b/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/inheritors/KotlinFirDefinitionsSearcher.kt index d29938d208d1..d8e4ee41321f 100644 --- a/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/inheritors/KotlinFirDefinitionsSearcher.kt +++ b/plugins/kotlin/kotlin.searching/src/org/jetbrains/kotlin/idea/searching/inheritors/KotlinFirDefinitionsSearcher.kt @@ -93,11 +93,10 @@ class KotlinFirDefinitionsSearcher : QueryExecutor ): Boolean { // workaround for IDEA optimization that uses Java PSI traversal to locate inheritors in local search scope - val virtualFiles = runReadAction { - searchScope.scope.mapTo(HashSet()) { it.containingFile.virtualFile } + val globalScope = runReadAction { + val virtualFiles = searchScope.scope.mapTo(HashSet()) { it.containingFile.virtualFile } + GlobalSearchScope.filesScope(ktClass.project, virtualFiles) } - - val globalScope = GlobalSearchScope.filesScope(ktClass.project, virtualFiles) return ktClass.findAllInheritors(globalScope).all { candidate -> val candidateOrigin = candidate.unwrapped ?: candidate val inScope = runReadAction { candidateOrigin in searchScope } From a9ac8b5fad87f5d1d725e7250ddaa70f747eaefb Mon Sep 17 00:00:00 2001 From: "Alexander.Danilov" Date: Fri, 4 Aug 2023 00:11:22 +0200 Subject: [PATCH 094/165] [kotlin] run line markers test with navigation in K2, remove obsolete usages of assertNavigationElements (cherry picked from commit 33ca73be67a6ef43b79c038a44b96d9bd4f6ab1d) GitOrigin-RevId: ddc072038ac406cf76f8d34e26d1748e0cf5f8b5 --- .../kotlin.code-insight.line-markers-k2.iml | 4 + .../test/AbstractLineMarkerTest.kt | 73 ------- .../test/AbstractLineMarkersK2Test.kt | 72 +++++++ ...d.java => LineMarkersK2TestGenerated.java} | 203 ++++++++++-------- .../AbstractMultiModuleHighlightingTest.kt | 14 -- .../codeInsight/AbstractLineMarkersTest.kt | 186 ++++++++-------- .../idea/scratch/ScratchLineMarkersTest.kt | 7 +- .../codeinsight/GenerateK2LineMarkerTests.kt | 18 +- 8 files changed, 301 insertions(+), 276 deletions(-) delete mode 100644 plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkerTest.kt create mode 100644 plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkersK2Test.kt rename plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/{LineMarkerTestGenerated.java => LineMarkersK2TestGenerated.java} (56%) diff --git a/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml b/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml index 9fae6e2bfe3f..99abff17660a 100644 --- a/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml +++ b/plugins/kotlin/code-insight/line-markers/kotlin.code-insight.line-markers-k2.iml @@ -41,6 +41,10 @@ + + + + diff --git a/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkerTest.kt b/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkerTest.kt deleted file mode 100644 index 347630da4701..000000000000 --- a/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkerTest.kt +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.kotlin.idea.k2.codeInsight.lineMarkers.test - -import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings -import com.intellij.codeInsight.daemon.GutterIconDescriptor -import com.intellij.codeInsight.daemon.LineMarkerSettings -import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl -import com.intellij.openapi.actionSystem.ex.ActionUtil -import com.intellij.openapi.util.io.FileUtil -import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginKind -import org.jetbrains.kotlin.idea.base.test.KotlinExpectedHighlightingData -import org.jetbrains.kotlin.idea.base.test.KotlinJvmLightProjectDescriptor -import org.jetbrains.kotlin.idea.base.test.NewLightKotlinCodeInsightFixtureTestCase -import org.jetbrains.kotlin.idea.highlighter.markers.KotlinLineMarkerOptions -import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil -import org.jetbrains.kotlin.test.InTextDirectivesUtils -import org.jetbrains.kotlin.test.utils.IgnoreTests - -abstract class AbstractLineMarkerTest : NewLightKotlinCodeInsightFixtureTestCase() { - override val pluginKind: KotlinPluginKind - get() = KotlinPluginKind.FIR_PLUGIN - - private fun checkLineMarkers() { - myFixture.configureDependencies() - myFixture.configureByDefaultFile() - val file = testRootPath.resolve(testMethodPath).toFile() - val fileText = FileUtil.loadFile(file) - ConfigLibraryUtil.configureLibrariesByDirective(myFixture.module, fileText) - InTextDirectivesUtils.findStringWithPrefixes(fileText, "METHOD_SEPARATORS")?.let { - DaemonCodeAnalyzerSettings.getInstance().SHOW_METHOD_SEPARATORS = true - } - val disabledOptions = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, "// OPTION: ") - .mapNotNull { - if (it.startsWith("-")) { - val optionName = it.substring(1) - val field = KotlinLineMarkerOptions::class.java.getDeclaredField(optionName) - field.isAccessible = true - field.get(KotlinLineMarkerOptions) as GutterIconDescriptor - } else { - null - } - } - disabledOptions.forEach { - LineMarkerSettings.getSettings().setEnabled(it, false) - } - val document = editor.document - val data = KotlinExpectedHighlightingData(document) - data.init() - - myFixture.doHighlighting() - - - val lineMarkers = DaemonCodeAnalyzerImpl.getLineMarkers(document, project) - try { - ActionUtil.underModalProgress(myFixture.project, "") { data.checkLineMarkers(myFixture.file, lineMarkers, document.text) } - } finally { - ConfigLibraryUtil.unconfigureLibrariesByDirective(module, fileText) - DaemonCodeAnalyzerSettings.getInstance().SHOW_METHOD_SEPARATORS = false - disabledOptions.forEach { - LineMarkerSettings.getSettings().setEnabled(it, true) - } - } - } - - protected fun performTest() { - IgnoreTests.runTestIfNotDisabledByFileDirective(testRootPath.resolve(testMethodPath), IgnoreTests.DIRECTIVES.IGNORE_FIR) { - checkLineMarkers() - } - - } - - override fun getProjectDescriptor() = KotlinJvmLightProjectDescriptor.DEFAULT -} \ No newline at end of file diff --git a/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkersK2Test.kt b/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkersK2Test.kt new file mode 100644 index 000000000000..91f157eff3db --- /dev/null +++ b/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/AbstractLineMarkersK2Test.kt @@ -0,0 +1,72 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.k2.codeInsight.lineMarkers.test + +import com.intellij.codeInsight.daemon.LineMarkerInfo +import com.intellij.codeInsight.daemon.impl.InheritorsLineMarkerNavigator +import com.intellij.codeInsight.navigation.GotoImplementationHandler +import com.intellij.testFramework.UsefulTestCase +import com.intellij.util.ThrowableRunnable +import org.jetbrains.kotlin.idea.codeInsight.AbstractLineMarkersTest +import org.jetbrains.kotlin.idea.codeInsight.lineMarkers.SuperDeclarationPopupHandler +import org.jetbrains.kotlin.idea.fir.invalidateCaches +import org.jetbrains.kotlin.idea.k2.codeinsight.KotlinGoToSuperDeclarationsHandler +import org.jetbrains.kotlin.idea.navigation.NavigationTestUtils +import org.jetbrains.kotlin.idea.test.runAll +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.test.util.renderAsGotoImplementation +import org.jetbrains.kotlin.test.utils.IgnoreTests +import org.junit.Assert +import kotlin.io.path.Path + +abstract class AbstractLineMarkersK2Test : AbstractLineMarkersTest() { + override fun doTest(path: String) { + IgnoreTests.runTestIfNotDisabledByFileDirective(Path(path), IgnoreTests.DIRECTIVES.IGNORE_FIR) { + super.doTest(path) + } + } + + override fun getActualNavigationDataAndCompare(lineMarker: LineMarkerInfo<*>, navigationComment: String) { + when (val handler = lineMarker.navigationHandler) { + is InheritorsLineMarkerNavigator -> { + val gotoData = + GotoImplementationHandler().createDataForSourceForTests(editor, lineMarker.element!!.parent!!) + val targets = gotoData.targets.toMutableList().sortedBy { + it.renderAsGotoImplementation() + } + val actualNavigationData = NavigationTestUtils.getNavigateElementsText(project, targets) + + UsefulTestCase.assertSameLines(getExpectedNavigationText(navigationComment), actualNavigationData) + + } + + is SuperDeclarationPopupHandler -> { + val ktDeclaration = lineMarker.element!!.getParentOfType(false)!! + + val superDeclarations = + KotlinGoToSuperDeclarationsHandler.findSuperDeclarations(ktDeclaration)!!.items.map { it.declaration.element } + + val actualNavigationData = NavigationTestUtils.getNavigateElementsText(project, superDeclarations) + + UsefulTestCase.assertSameLines(getExpectedNavigationText(navigationComment), actualNavigationData) + + } + + else -> { + Assert.fail("${handler} is not supported for navigate check") + } + } + } + + override fun isFirPlugin(): Boolean { + return true + } + + override fun tearDown() { + runAll( + ThrowableRunnable { project.invalidateCaches() }, + ThrowableRunnable { super.tearDown() } + ) + } + +} \ No newline at end of file diff --git a/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/LineMarkerTestGenerated.java b/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/LineMarkersK2TestGenerated.java similarity index 56% rename from plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/LineMarkerTestGenerated.java rename to plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/LineMarkersK2TestGenerated.java index 73baaeab5f70..9737c04de304 100644 --- a/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/LineMarkerTestGenerated.java +++ b/plugins/kotlin/code-insight/line-markers/test/org/jetbrains/kotlin/idea/k2/codeInsight/lineMarkers/test/LineMarkersK2TestGenerated.java @@ -4,6 +4,7 @@ package org.jetbrains.kotlin.idea.k2.codeInsight.lineMarkers.test; import com.intellij.testFramework.TestDataPath; import org.jetbrains.kotlin.idea.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.idea.test.KotlinTestUtils; import org.jetbrains.kotlin.test.TestMetadata; import org.jetbrains.kotlin.idea.base.test.TestRoot; import org.junit.runner.RunWith; @@ -16,427 +17,455 @@ import org.junit.runner.RunWith; @TestRoot("code-insight/line-markers") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -public abstract class LineMarkerTestGenerated extends AbstractLineMarkerTest { +public abstract class LineMarkersK2TestGenerated extends AbstractLineMarkersK2Test { @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("testData/recursive") - public static class Recursive extends AbstractLineMarkerTest { + public static class Recursive extends AbstractLineMarkersK2Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + @TestMetadata("backticksInName.kt") public void testBackticksInName() throws Exception { - performTest(); + runTest("testData/recursive/backticksInName.kt"); } @TestMetadata("callableReference.kt") public void testCallableReference() throws Exception { - performTest(); + runTest("testData/recursive/callableReference.kt"); } @TestMetadata("companionInvoke.kt") public void testCompanionInvoke() throws Exception { - performTest(); + runTest("testData/recursive/companionInvoke.kt"); } @TestMetadata("conventions.kt") public void testConventions() throws Exception { - performTest(); + runTest("testData/recursive/conventions.kt"); } @TestMetadata("defaultValue.kt") public void testDefaultValue() throws Exception { - performTest(); + runTest("testData/recursive/defaultValue.kt"); } @TestMetadata("dispatchExtensionReceivers.kt") public void testDispatchExtensionReceivers() throws Exception { - performTest(); + runTest("testData/recursive/dispatchExtensionReceivers.kt"); } @TestMetadata("dispatchReceiver.kt") public void testDispatchReceiver() throws Exception { - performTest(); + runTest("testData/recursive/dispatchReceiver.kt"); } @TestMetadata("extensionReceiver.kt") public void testExtensionReceiver() throws Exception { - performTest(); + runTest("testData/recursive/extensionReceiver.kt"); } @TestMetadata("functionLiteral.kt") public void testFunctionLiteral() throws Exception { - performTest(); + runTest("testData/recursive/functionLiteral.kt"); } @TestMetadata("generic.kt") public void testGeneric() throws Exception { - performTest(); + runTest("testData/recursive/generic.kt"); } @TestMetadata("inlineLambda.kt") public void testInlineLambda() throws Exception { - performTest(); + runTest("testData/recursive/inlineLambda.kt"); } @TestMetadata("insideLambda.kt") public void testInsideLambda() throws Exception { - performTest(); + runTest("testData/recursive/insideLambda.kt"); } @TestMetadata("localClass.kt") public void testLocalClass() throws Exception { - performTest(); + runTest("testData/recursive/localClass.kt"); } @TestMetadata("localFunction.kt") public void testLocalFunction() throws Exception { - performTest(); + runTest("testData/recursive/localFunction.kt"); } @TestMetadata("propertyAccessors.kt") public void testPropertyAccessors() throws Exception { - performTest(); + runTest("testData/recursive/propertyAccessors.kt"); } @TestMetadata("sameLine.kt") public void testSameLine() throws Exception { - performTest(); + runTest("testData/recursive/sameLine.kt"); } @TestMetadata("simple.kt") public void testSimple() throws Exception { - performTest(); + runTest("testData/recursive/simple.kt"); } @TestMetadata("super.kt") public void testSuper() throws Exception { - performTest(); + runTest("testData/recursive/super.kt"); } @TestMetadata("with.kt") public void testWith() throws Exception { - performTest(); + runTest("testData/recursive/with.kt"); } } @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("testData/suspend") - public static class Suspend extends AbstractLineMarkerTest { + public static class Suspend extends AbstractLineMarkersK2Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + @TestMetadata("callChain.kt") public void testCallChain() throws Exception { - performTest(); + runTest("testData/suspend/callChain.kt"); } @TestMetadata("callableReference.kt") public void testCallableReference() throws Exception { - performTest(); + runTest("testData/suspend/callableReference.kt"); } @TestMetadata("coroutineContext.kt") public void testCoroutineContext() throws Exception { - performTest(); + runTest("testData/suspend/coroutineContext.kt"); } @TestMetadata("forLoop.kt") public void testForLoop() throws Exception { - performTest(); + runTest("testData/suspend/forLoop.kt"); } @TestMetadata("implicitReceiver.kt") public void testImplicitReceiver() throws Exception { - performTest(); + runTest("testData/suspend/implicitReceiver.kt"); } @TestMetadata("import.kt") public void testImport() throws Exception { - performTest(); + runTest("testData/suspend/import.kt"); } @TestMetadata("infix.kt") public void testInfix() throws Exception { - performTest(); + runTest("testData/suspend/infix.kt"); } @TestMetadata("insideSuspendLambda.kt") public void testInsideSuspendLambda() throws Exception { - performTest(); + runTest("testData/suspend/insideSuspendLambda.kt"); } @TestMetadata("invalidCall.kt") public void testInvalidCall() throws Exception { - performTest(); + runTest("testData/suspend/invalidCall.kt"); } @TestMetadata("notSuspend.kt") public void testNotSuspend() throws Exception { - performTest(); + runTest("testData/suspend/notSuspend.kt"); } @TestMetadata("parameter.kt") public void testParameter() throws Exception { - performTest(); + runTest("testData/suspend/parameter.kt"); } @TestMetadata("plusOperator.kt") public void testPlusOperator() throws Exception { - performTest(); + runTest("testData/suspend/plusOperator.kt"); } @TestMetadata("simple.kt") public void testSimple() throws Exception { - performTest(); + runTest("testData/suspend/simple.kt"); } @TestMetadata("variable.kt") public void testVariable() throws Exception { - performTest(); + runTest("testData/suspend/variable.kt"); } } @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement") - public static class OverrideImplement extends AbstractLineMarkerTest { + public static class OverrideImplement extends AbstractLineMarkersK2Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + @TestMetadata("AbstractClass.kt") public void testAbstractClass() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/AbstractClass.kt"); } @TestMetadata("BadCodeNoExceptions.kt") public void testBadCodeNoExceptions() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/BadCodeNoExceptions.kt"); } @TestMetadata("Class.kt") public void testClass() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/Class.kt"); } @TestMetadata("ClassAndProperties.kt") public void testClassAndProperties() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/ClassAndProperties.kt"); } @TestMetadata("ClassObjectInStaticNestedClass.kt") public void testClassObjectInStaticNestedClass() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/ClassObjectInStaticNestedClass.kt"); } @TestMetadata("DelegatedFun.kt") public void testDelegatedFun() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/DelegatedFun.kt"); } @TestMetadata("DelegatedProperty.kt") public void testDelegatedProperty() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/DelegatedProperty.kt"); } @TestMetadata("EnumEntry.kt") public void testEnumEntry() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/EnumEntry.kt"); } @TestMetadata("FakeOverrideForClasses.kt") public void testFakeOverrideForClasses() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/FakeOverrideForClasses.kt"); } @TestMetadata("FakeOverrideFun.kt") public void testFakeOverrideFun() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/FakeOverrideFun.kt"); } @TestMetadata("FakeOverrideFunWithMostRelevantImplementation.kt") public void testFakeOverrideFunWithMostRelevantImplementation() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/FakeOverrideFunWithMostRelevantImplementation.kt"); } @TestMetadata("FakeOverrideProperty.kt") public void testFakeOverrideProperty() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/FakeOverrideProperty.kt"); } @TestMetadata("FakeOverrideToStringInInterface.kt") public void testFakeOverrideToStringInInterface() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/FakeOverrideToStringInInterface.kt"); } @TestMetadata("FakeOverridesForInterfaceFunWithImpl.kt") public void testFakeOverridesForInterfaceFunWithImpl() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/FakeOverridesForInterfaceFunWithImpl.kt"); } @TestMetadata("ImplementedAndOverriddenPropertiesInCtr.kt") public void testImplementedAndOverriddenPropertiesInCtr() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/ImplementedAndOverriddenPropertiesInCtr.kt"); } @TestMetadata("Interface.kt") public void testInterface() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/Interface.kt"); } @TestMetadata("InterfaceDisabledImplOption.kt") public void testInterfaceDisabledImplOption() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/InterfaceDisabledImplOption.kt"); } @TestMetadata("NavigateFromPrivateAbstractClass.kt") public void testNavigateFromPrivateAbstractClass() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/NavigateFromPrivateAbstractClass.kt"); } @TestMetadata("NavigateToSeveralSuperElements.kt") public void testNavigateToSeveralSuperElements() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/NavigateToSeveralSuperElements.kt"); } @TestMetadata("NoOverridingMarkerOnDefaultInterfaceImpl.kt") public void testNoOverridingMarkerOnDefaultInterfaceImpl() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/NoOverridingMarkerOnDefaultInterfaceImpl.kt"); } @TestMetadata("Overloads.kt") public void testOverloads() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/Overloads.kt"); } @TestMetadata("OverrideFunction.kt") public void testOverrideFunction() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/OverrideFunction.kt"); } @TestMetadata("OverrideFunctionInJava.kt") public void testOverrideFunctionInJava() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/OverrideFunctionInJava.kt"); } @TestMetadata("OverrideIconForOverloadMethodBug.kt") public void testOverrideIconForOverloadMethodBug() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/OverrideIconForOverloadMethodBug.kt"); } @TestMetadata("OverrideMemberOfAbstractClass.kt") public void testOverrideMemberOfAbstractClass() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/OverrideMemberOfAbstractClass.kt"); } @TestMetadata("OverridenInterfaceDeclarations.kt") public void testOverridenInterfaceDeclarations() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/OverridenInterfaceDeclarations.kt"); } @TestMetadata("OverridingTooltipOnDefaultInterfaceImpl.kt") public void testOverridingTooltipOnDefaultInterfaceImpl() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/OverridingTooltipOnDefaultInterfaceImpl.kt"); } @TestMetadata("PrimaryConstructorOpen.kt") public void testPrimaryConstructorOpen() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOpen.kt"); } @TestMetadata("PrimaryConstructorOverride.kt") public void testPrimaryConstructorOverride() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOverride.kt"); } @TestMetadata("PropertiesImplementedInCtr.kt") public void testPropertiesImplementedInCtr() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/PropertiesImplementedInCtr.kt"); } @TestMetadata("PropertiesOverriddenInCtr.kt") public void testPropertiesOverriddenInCtr() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/PropertiesOverriddenInCtr.kt"); } @TestMetadata("PropertyOverride.kt") public void testPropertyOverride() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/PropertyOverride.kt"); } @TestMetadata("SealedClass.kt") public void testSealedClass() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/SealedClass.kt"); } @TestMetadata("ToStringInInterface.kt") public void testToStringInInterface() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/ToStringInInterface.kt"); } @TestMetadata("WithJavaAnonymousInheritor.kt") public void testWithJavaAnonymousInheritor() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/WithJavaAnonymousInheritor.kt"); } @TestMetadata("WithJavaInheritor.kt") public void testWithJavaInheritor() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/WithJavaInheritor.kt"); } @TestMetadata("WithJavaInheritorProperty.kt") public void testWithJavaInheritorProperty() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/overrideImplement/WithJavaInheritorProperty.kt"); } } @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/codeInsight/lineMarker/dslMarker") - public static class DslMarker extends AbstractLineMarkerTest { + public static class DslMarker extends AbstractLineMarkersK2Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + @TestMetadata("markerAnnotationDeclaration.kt") public void testMarkerAnnotationDeclaration() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/dslMarker/markerAnnotationDeclaration.kt"); } } @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/codeInsight/lineMarker/main") - public static class Main extends AbstractLineMarkerTest { + public static class Main extends AbstractLineMarkersK2Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + @TestMetadata("main.kt") public void testMain() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/main/main.kt"); } } @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/codeInsight/lineMarker/runMarkers") - public static class RunMarkers extends AbstractLineMarkerTest { + public static class RunMarkers extends AbstractLineMarkersK2Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + @TestMetadata("jUnit3TestFile.kt") public void testJUnit3TestFile() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/runMarkers/jUnit3TestFile.kt"); } @TestMetadata("jUnit3TestFileWithJUnit4.kt") public void testJUnit3TestFileWithJUnit4() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/runMarkers/jUnit3TestFileWithJUnit4.kt"); } @TestMetadata("jUnit4TestFile.kt") public void testJUnit4TestFile() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/runMarkers/jUnit4TestFile.kt"); } @TestMetadata("jUnit5TestFile.kt") public void testJUnit5TestFile() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/runMarkers/jUnit5TestFile.kt"); } @TestMetadata("jUnitTestClassWithSubclasses.kt") public void testJUnitTestClassWithSubclasses() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/runMarkers/jUnitTestClassWithSubclasses.kt"); } @TestMetadata("testNGTestClassWithSubclasses.kt") public void testTestNGTestClassWithSubclasses() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/runMarkers/testNGTestClassWithSubclasses.kt"); } } @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/codeInsight/lineMarker/methodSeparators") - public static class MethodSeparators extends AbstractLineMarkerTest { + public static class MethodSeparators extends AbstractLineMarkersK2Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + @TestMetadata("MethodSeparators.kt") public void testMethodSeparators() throws Exception { - performTest(); + runTest("../../idea/tests/testData/codeInsight/lineMarker/methodSeparators/MethodSeparators.kt"); } } } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleHighlightingTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleHighlightingTest.kt index d3d951a24e6b..e9372daed0a3 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleHighlightingTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleHighlightingTest.kt @@ -2,30 +2,16 @@ package org.jetbrains.kotlin.idea.caches.resolve -import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl import com.intellij.psi.PsiFile -import org.jetbrains.kotlin.idea.codeInsight.AbstractLineMarkersTest import org.jetbrains.kotlin.idea.multiplatform.setupMppProjectFromDirStructure import org.jetbrains.kotlin.idea.stubs.AbstractMultiHighlightingTest import org.jetbrains.kotlin.idea.test.IDEA_TEST_DATA_DIR import org.jetbrains.kotlin.idea.test.allJavaFiles import org.jetbrains.kotlin.idea.test.allKotlinFiles -import org.jetbrains.kotlin.psi.KtFile import java.io.File abstract class AbstractMultiModuleHighlightingTest : AbstractMultiHighlightingTest() { - protected open fun checkLineMarkersInProject( - findFiles: () -> List = { project.allKotlinFiles().excludeByDirective() } - ) { - checkFiles(findFiles) { - checkHighlighting(myEditor, true, false) - - val markers = DaemonCodeAnalyzerImpl.getLineMarkers(getDocument(file), project) - AbstractLineMarkersTest.assertNavigationElements(project, myFile as KtFile, myEditor, markers) - } - } - protected open fun checkHighlightingInProject( findFiles: () -> List = { project.allKotlinFiles().excludeByDirective() } ) { diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/AbstractLineMarkersTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/AbstractLineMarkersTest.kt index 53724a01e4cd..34cfafd94ad9 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/AbstractLineMarkersTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/AbstractLineMarkersTest.kt @@ -9,8 +9,8 @@ import com.intellij.codeInsight.daemon.LineMarkerSettings import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl import com.intellij.codeInsight.daemon.impl.InheritorsLineMarkerNavigator import com.intellij.codeInsight.navigation.GotoImplementationHandler +import com.intellij.openapi.actionSystem.ex.ActionUtil import com.intellij.openapi.editor.Document -import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.openapi.util.io.FileUtil import com.intellij.psi.PsiDocumentManager @@ -38,7 +38,7 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase() return KotlinWithJdkAndRuntimeLightProjectDescriptor.getInstance() } - fun doTest(path: String) = doTest(path) {} + protected open fun doTest(path: String) = doTest(path) {} protected fun doAndCheckHighlighting( psiFile: PsiFile, @@ -48,7 +48,7 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase() ): List> { myFixture.doHighlighting() - return checkHighlighting(psiFile, documentToAnalyze, expectedHighlighting, expectedFile) + return checkHighlighting(project, psiFile, documentToAnalyze, expectedHighlighting, expectedFile) } fun doTest(@Suppress("UNUSED_PARAMETER") unused: String, additionalCheck: () -> Unit) { @@ -93,7 +93,7 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase() val markers = doAndCheckHighlighting(ktFile, document, data, dataFile()) - assertNavigationElements(myFixture.project, ktFile, myFixture.editor, markers) + assertNavigationElements(markers) additionalCheck() } catch (exc: Exception) { throw RuntimeException(exc) @@ -104,7 +104,97 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase() LineMarkerSettings.getSettings().setEnabled(it, true) } } + } + private fun assertNavigationElements(markers: List>) { + val navigationDataComments = KotlinTestUtils.getLastCommentsInFile( + myFixture.file as KtFile, KotlinTestUtils.CommentType.BLOCK_COMMENT, false + ) + if (navigationDataComments.isEmpty()) return + val markerCodeMetaInfos = markers.map { InnerLineMarkerCodeMetaInfo(InnerLineMarkerConfiguration.configuration, it) } + + for ((navigationCommentIndex, navigationComment) in navigationDataComments.reversed().withIndex()) { + val description = getLineMarkerDescription(navigationComment) + val navigateMarkers = ActionUtil.underModalProgress(project, "") { + markerCodeMetaInfos.filter { it.asString() == description } + } + val navigateMarker = navigateMarkers.singleOrNull() ?: navigateMarkers.getOrNull(navigationCommentIndex) + + TestCase.assertNotNull( + String.format("Can't find marker for navigation check with description \"%s\"\n\navailable: \n\n%s", + description, + ActionUtil.underModalProgress(project, "") { + markerCodeMetaInfos.joinToString("\n\n") { it.asString() } + }), + navigateMarker + ) + + val lineMarker = navigateMarker!!.lineMarker + + getActualNavigationDataAndCompare(lineMarker, navigationComment) + } + } + + open fun getActualNavigationDataAndCompare(lineMarker: LineMarkerInfo<*>, navigationComment: String) { + when (val handler = lineMarker.navigationHandler) { + is InheritorsLineMarkerNavigator -> { + val gotoData = + GotoImplementationHandler().createDataForSourceForTests(editor, lineMarker.element!!.parent!!) + val targets = gotoData.targets.toMutableList().sortedBy { + it.renderAsGotoImplementation() + } + val actualNavigationData = NavigationTestUtils.getNavigateElementsText(project, targets) + + UsefulTestCase.assertSameLines(getExpectedNavigationText(navigationComment), actualNavigationData) + + } + + is TestableLineMarkerNavigator -> { + val navigateElements = handler.getTargetsPopupDescriptor(lineMarker.element)?.targets?.sortedBy { + it.renderAsGotoImplementation() + } + val actualNavigationData = NavigationTestUtils.getNavigateElementsText(project, navigateElements) + + UsefulTestCase.assertSameLines(getExpectedNavigationText(navigationComment), actualNavigationData) + } + + else -> { + Assert.fail("Only TestableLineMarkerNavigator are supported in navigate check") + } + } + } + + private fun getLineMarkerDescription(navigationComment: String): String { + val firstLineEnd = navigationComment.indexOf("\n") + TestCase.assertTrue( + "The first line in block comment must contain description of marker for navigation check", firstLineEnd != -1 + ) + + var navigationMarkerText = navigationComment.substring(0, firstLineEnd) + + TestCase.assertTrue( + String.format("Add %s directive in first line of comment", LINE_MARKER_PREFIX), + navigationMarkerText.startsWith(LINE_MARKER_PREFIX) + ) + + navigationMarkerText = navigationMarkerText.substring(LINE_MARKER_PREFIX.length) + + return navigationMarkerText.trim { it <= ' ' } + } + + fun getExpectedNavigationText(navigationComment: String): String { + val firstLineEnd = navigationComment.indexOf("\n") + + var expectedNavigationText = navigationComment.substring(firstLineEnd + 1) + + TestCase.assertTrue( + String.format("Marker %s is expected before navigation data", TARGETS_PREFIX), + expectedNavigationText.startsWith(TARGETS_PREFIX) + ) + + expectedNavigationText = expectedNavigationText.substring(expectedNavigationText.indexOf("\n") + 1) + + return expectedNavigationText } companion object { @@ -113,90 +203,8 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase() private const val LINE_MARKER_PREFIX = "LINEMARKER:" private const val TARGETS_PREFIX = "TARGETS" - fun assertNavigationElements(project: Project, file: KtFile, editor : Editor, markers: List>) { - val navigationDataComments = KotlinTestUtils.getLastCommentsInFile( - file, KotlinTestUtils.CommentType.BLOCK_COMMENT, false - ) - if (navigationDataComments.isEmpty()) return - val markerCodeMetaInfos = markers.map { InnerLineMarkerCodeMetaInfo(InnerLineMarkerConfiguration.configuration, it) } - - for ((navigationCommentIndex, navigationComment) in navigationDataComments.reversed().withIndex()) { - val description = getLineMarkerDescription(navigationComment) - val navigateMarkers = markerCodeMetaInfos.filter { it.asString() == description } - val navigateMarker = navigateMarkers.singleOrNull() ?: navigateMarkers.getOrNull(navigationCommentIndex) - - TestCase.assertNotNull( - String.format("Can't find marker for navigation check with description \"%s\"\n\navailable: \n\n%s", - description, - markerCodeMetaInfos.joinToString("\n\n") { it.asString() }), - navigateMarker - ) - - val lineMarker = navigateMarker!!.lineMarker - - when (val handler = lineMarker.navigationHandler) { - is InheritorsLineMarkerNavigator -> { - val gotoData = - GotoImplementationHandler().createDataForSourceForTests(editor, lineMarker.element!!.parent!!) - val targets = gotoData.targets.toMutableList().sortedBy { - it.renderAsGotoImplementation() - } - val actualNavigationData = NavigationTestUtils.getNavigateElementsText(project, targets) - - UsefulTestCase.assertSameLines(getExpectedNavigationText(navigationComment), actualNavigationData) - - } - - is TestableLineMarkerNavigator -> { - val navigateElements = handler.getTargetsPopupDescriptor(lineMarker.element)?.targets?.sortedBy { - it.renderAsGotoImplementation() - } - val actualNavigationData = NavigationTestUtils.getNavigateElementsText(project, navigateElements) - - UsefulTestCase.assertSameLines(getExpectedNavigationText(navigationComment), actualNavigationData) - } - - else -> { - Assert.fail("Only TestableLineMarkerNavigator are supported in navigate check") - } - } - } - } - - private fun getLineMarkerDescription(navigationComment: String): String { - val firstLineEnd = navigationComment.indexOf("\n") - TestCase.assertTrue( - "The first line in block comment must contain description of marker for navigation check", firstLineEnd != -1 - ) - - var navigationMarkerText = navigationComment.substring(0, firstLineEnd) - - TestCase.assertTrue( - String.format("Add %s directive in first line of comment", LINE_MARKER_PREFIX), - navigationMarkerText.startsWith(LINE_MARKER_PREFIX) - ) - - navigationMarkerText = navigationMarkerText.substring(LINE_MARKER_PREFIX.length) - - return navigationMarkerText.trim { it <= ' ' } - } - - private fun getExpectedNavigationText(navigationComment: String): String { - val firstLineEnd = navigationComment.indexOf("\n") - - var expectedNavigationText = navigationComment.substring(firstLineEnd + 1) - - TestCase.assertTrue( - String.format("Marker %s is expected before navigation data", TARGETS_PREFIX), - expectedNavigationText.startsWith(TARGETS_PREFIX) - ) - - expectedNavigationText = expectedNavigationText.substring(expectedNavigationText.indexOf("\n") + 1) - - return expectedNavigationText - } - fun checkHighlighting( + project: Project, psiFile: PsiFile, documentToAnalyze: Document, expectedHighlighting: ExpectedHighlightingData, @@ -205,7 +213,9 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase() val markers = DaemonCodeAnalyzerImpl.getLineMarkers(documentToAnalyze, psiFile.project) try { - expectedHighlighting.checkLineMarkers(psiFile, markers, documentToAnalyze.text) + ActionUtil.underModalProgress(project, "") { + expectedHighlighting.checkLineMarkers(psiFile, markers, documentToAnalyze.text) + } // This is a workaround for sad bug in ExpectedHighlightingData: // the latter doesn't throw assertion error when some line markers are expected, but none are present. diff --git a/plugins/kotlin/scripting-support/test/org/jetbrains/kotlin/idea/scratch/ScratchLineMarkersTest.kt b/plugins/kotlin/scripting-support/test/org/jetbrains/kotlin/idea/scratch/ScratchLineMarkersTest.kt index 01a244b2d12b..d2cb5d500789 100644 --- a/plugins/kotlin/scripting-support/test/org/jetbrains/kotlin/idea/scratch/ScratchLineMarkersTest.kt +++ b/plugins/kotlin/scripting-support/test/org/jetbrains/kotlin/idea/scratch/ScratchLineMarkersTest.kt @@ -19,7 +19,6 @@ import org.jetbrains.kotlin.idea.codeInsight.AbstractLineMarkersTest import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager import org.jetbrains.kotlin.idea.scratch.AbstractScratchRunActionTest.Companion.configureOptions import org.jetbrains.kotlin.idea.test.runAll -import org.jetbrains.kotlin.psi.KtFile import java.io.File abstract class AbstractScratchLineMarkersTest : FileEditorManagerTestCase() { @@ -54,9 +53,7 @@ abstract class AbstractScratchLineMarkersTest : FileEditorManagerTestCase() { PsiDocumentManager.getInstance(project).commitAllDocuments() - val markers = doAndCheckHighlighting(document, data, File(path)) - - AbstractLineMarkersTest.assertNavigationElements(myFixture.project, myFixture.file as KtFile, myFixture.editor, markers) + doAndCheckHighlighting(document, data, File(path)) } override fun tearDown() { @@ -75,7 +72,7 @@ abstract class AbstractScratchLineMarkersTest : FileEditorManagerTestCase() { ): List> { myFixture.doHighlighting() - return AbstractLineMarkersTest.checkHighlighting(myFixture.file, documentToAnalyze, expectedHighlighting, expectedFile) + return AbstractLineMarkersTest.checkHighlighting(project, myFixture.file, documentToAnalyze, expectedHighlighting, expectedFile) } } diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2LineMarkerTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2LineMarkerTests.kt index db81e9b31237..712911cb85ed 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2LineMarkerTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2LineMarkerTests.kt @@ -1,19 +1,19 @@ // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.fir.testGenerator.codeinsight -import org.jetbrains.kotlin.idea.k2.codeInsight.lineMarkers.test.AbstractLineMarkerTest +import org.jetbrains.kotlin.idea.k2.codeInsight.lineMarkers.test.AbstractLineMarkersK2Test import org.jetbrains.kotlin.testGenerator.model.* internal fun MutableTWorkspace.generateK2LineMarkerTests() { testGroup("code-insight/line-markers") { - testClass { - model("recursive", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) - model("suspend", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) - model("../../../idea/tests/testData/codeInsight/lineMarker/overrideImplement", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) - model("../../../idea/tests/testData/codeInsight/lineMarker/dslMarker", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) - model("../../../idea/tests/testData/codeInsight/lineMarker/main", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) - model("../../../idea/tests/testData/codeInsight/lineMarker/runMarkers", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) - model("../../../idea/tests/testData/codeInsight/lineMarker/methodSeparators", pattern = Patterns.KT_WITHOUT_DOTS, passTestDataPath = false) + testClass { + model("recursive", pattern = Patterns.KT_WITHOUT_DOTS) + model("suspend", pattern = Patterns.KT_WITHOUT_DOTS) + model("../../../idea/tests/testData/codeInsight/lineMarker/overrideImplement", pattern = Patterns.KT_WITHOUT_DOTS) + model("../../../idea/tests/testData/codeInsight/lineMarker/dslMarker", pattern = Patterns.KT_WITHOUT_DOTS) + model("../../../idea/tests/testData/codeInsight/lineMarker/main", pattern = Patterns.KT_WITHOUT_DOTS) + model("../../../idea/tests/testData/codeInsight/lineMarker/runMarkers", pattern = Patterns.KT_WITHOUT_DOTS) + model("../../../idea/tests/testData/codeInsight/lineMarker/methodSeparators", pattern = Patterns.KT_WITHOUT_DOTS) } } From 5e067cd8a6a7bd355efff250db17311ddfaa6574 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 4 Aug 2023 20:08:32 +0200 Subject: [PATCH 095/165] [kotlin] extract frontend independent formatter to `formatter` module KTIJ-26147 GitOrigin-RevId: 3712d105faff744c027edee0f192f2cfc2a555b6 --- .../analysis-api-utils/kotlin.base.analysis-api.utils.iml | 2 ++ .../kotlin/idea/base/psi/imports/ImportInsertion.kt | 0 .../idea/base/psi/imports/KotlinImportPathComparator.kt | 0 plugins/kotlin/base/psi/kotlin.base.psi.iml | 1 - .../impl-base/kotlin.code-insight.impl-base.iml | 1 + .../idea/formatter/TrailingCommaPostFormatProcessor.kt | 0 plugins/kotlin/formatter/kotlin.formatter.iml | 8 ++++++++ .../kotlin/idea/formatter/BaseKotlinImportLayoutPanel.kt | 0 .../kotlin/idea/formatter/ImportSettingsPanel.kt | 0 .../org/jetbrains/kotlin/idea/formatter/KotlinBlock.kt | 0 .../formatter/KotlinCodeStyleGenerationConfigurable.kt | 0 .../kotlin/idea/formatter/KotlinCodeStylePanel.kt | 0 .../idea/formatter/KotlinCodeStylePropertyAccessor.kt | 0 .../kotlin/idea/formatter/KotlinFormattingModelBuilder.kt | 0 .../formatter/KotlinLanguageCodeStyleSettingsProvider.kt | 0 .../kotlin/idea/formatter/KotlinLineIndentProvider.kt | 0 .../kotlin/idea/formatter/KotlinOtherSettingsPanel.kt | 0 .../idea/formatter/KotlinPackageEntryTableAccessor.kt | 0 .../kotlin/idea/formatter/KotlinPreFormatProcessor.kt | 0 .../kotlin/idea/formatter/KotlinSaveStylePanel.kt | 0 .../kotlin/idea/formatter/NodeAlignmentStrategy.java | 0 plugins/kotlin/idea/kotlin.idea.iml | 1 + 22 files changed, 12 insertions(+), 1 deletion(-) rename plugins/kotlin/base/{psi => analysis-api/analysis-api-utils}/src/org/jetbrains/kotlin/idea/base/psi/imports/ImportInsertion.kt (100%) rename plugins/kotlin/base/{psi => analysis-api/analysis-api-utils}/src/org/jetbrains/kotlin/idea/base/psi/imports/KotlinImportPathComparator.kt (100%) rename plugins/kotlin/{idea => code-insight/impl-base}/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/BaseKotlinImportLayoutPanel.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/ImportSettingsPanel.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinBlock.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStyleGenerationConfigurable.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStylePanel.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStylePropertyAccessor.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinFormattingModelBuilder.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinOtherSettingsPanel.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinPackageEntryTableAccessor.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinPreFormatProcessor.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinSaveStylePanel.kt (100%) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/NodeAlignmentStrategy.java (100%) diff --git a/plugins/kotlin/base/analysis-api/analysis-api-utils/kotlin.base.analysis-api.utils.iml b/plugins/kotlin/base/analysis-api/analysis-api-utils/kotlin.base.analysis-api.utils.iml index b3cd34085245..f5dea847af41 100644 --- a/plugins/kotlin/base/analysis-api/analysis-api-utils/kotlin.base.analysis-api.utils.iml +++ b/plugins/kotlin/base/analysis-api/analysis-api-utils/kotlin.base.analysis-api.utils.iml @@ -36,5 +36,7 @@ + + \ No newline at end of file diff --git a/plugins/kotlin/base/psi/src/org/jetbrains/kotlin/idea/base/psi/imports/ImportInsertion.kt b/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/psi/imports/ImportInsertion.kt similarity index 100% rename from plugins/kotlin/base/psi/src/org/jetbrains/kotlin/idea/base/psi/imports/ImportInsertion.kt rename to plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/psi/imports/ImportInsertion.kt diff --git a/plugins/kotlin/base/psi/src/org/jetbrains/kotlin/idea/base/psi/imports/KotlinImportPathComparator.kt b/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/psi/imports/KotlinImportPathComparator.kt similarity index 100% rename from plugins/kotlin/base/psi/src/org/jetbrains/kotlin/idea/base/psi/imports/KotlinImportPathComparator.kt rename to plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/psi/imports/KotlinImportPathComparator.kt diff --git a/plugins/kotlin/base/psi/kotlin.base.psi.iml b/plugins/kotlin/base/psi/kotlin.base.psi.iml index 67c4cfffb9e9..5c3dd38f7007 100644 --- a/plugins/kotlin/base/psi/kotlin.base.psi.iml +++ b/plugins/kotlin/base/psi/kotlin.base.psi.iml @@ -17,7 +17,6 @@ - \ No newline at end of file diff --git a/plugins/kotlin/code-insight/impl-base/kotlin.code-insight.impl-base.iml b/plugins/kotlin/code-insight/impl-base/kotlin.code-insight.impl-base.iml index 1e6ba4af0d52..0a1f4e0814c3 100644 --- a/plugins/kotlin/code-insight/impl-base/kotlin.code-insight.impl-base.iml +++ b/plugins/kotlin/code-insight/impl-base/kotlin.code-insight.impl-base.iml @@ -45,5 +45,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt b/plugins/kotlin/code-insight/impl-base/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt rename to plugins/kotlin/code-insight/impl-base/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt diff --git a/plugins/kotlin/formatter/kotlin.formatter.iml b/plugins/kotlin/formatter/kotlin.formatter.iml index eedbd7216bb9..2dbaa230fbf1 100644 --- a/plugins/kotlin/formatter/kotlin.formatter.iml +++ b/plugins/kotlin/formatter/kotlin.formatter.iml @@ -15,5 +15,13 @@ + + + + + + + + \ No newline at end of file diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/BaseKotlinImportLayoutPanel.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/BaseKotlinImportLayoutPanel.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/BaseKotlinImportLayoutPanel.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/BaseKotlinImportLayoutPanel.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/ImportSettingsPanel.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/ImportSettingsPanel.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/ImportSettingsPanel.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/ImportSettingsPanel.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinBlock.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinBlock.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinBlock.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinBlock.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStyleGenerationConfigurable.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStyleGenerationConfigurable.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStyleGenerationConfigurable.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStyleGenerationConfigurable.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStylePanel.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStylePanel.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStylePanel.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStylePanel.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStylePropertyAccessor.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStylePropertyAccessor.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStylePropertyAccessor.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCodeStylePropertyAccessor.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormattingModelBuilder.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinFormattingModelBuilder.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormattingModelBuilder.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinFormattingModelBuilder.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinOtherSettingsPanel.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinOtherSettingsPanel.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinOtherSettingsPanel.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinOtherSettingsPanel.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinPackageEntryTableAccessor.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinPackageEntryTableAccessor.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinPackageEntryTableAccessor.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinPackageEntryTableAccessor.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinPreFormatProcessor.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinPreFormatProcessor.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinPreFormatProcessor.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinPreFormatProcessor.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinSaveStylePanel.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinSaveStylePanel.kt similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinSaveStylePanel.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinSaveStylePanel.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/NodeAlignmentStrategy.java b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeAlignmentStrategy.java similarity index 100% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/NodeAlignmentStrategy.java rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeAlignmentStrategy.java diff --git a/plugins/kotlin/idea/kotlin.idea.iml b/plugins/kotlin/idea/kotlin.idea.iml index 9d30831dd91c..abd1ce4dcf51 100644 --- a/plugins/kotlin/idea/kotlin.idea.iml +++ b/plugins/kotlin/idea/kotlin.idea.iml @@ -126,5 +126,6 @@ + \ No newline at end of file From 80e5fd5ce9b7dabe6cdcb6f859b2f28ecd1b8867 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 7 Aug 2023 09:16:44 +0200 Subject: [PATCH 096/165] [kotlin] inline and deprecate as ERROR old api GitOrigin-RevId: 6967e1658ae3b6768c5ffc6c79627dfadb8ec8c3 --- .../idea/src/org/jetbrains/kotlin/idea/formatter/Utils.kt | 3 ++- .../CoroutineBlockingCallInspectionUtils.kt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/Utils.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/Utils.kt index d220af17b0e3..6a4210df70d4 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/Utils.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/Utils.kt @@ -7,6 +7,7 @@ import org.jetbrains.kotlin.idea.codeinsight.utils.commitAndUnblockDocument as _ @Deprecated( "Please use `org.jetbrains.kotlin.idea.codeinsight.utils.commitAndUnblockDocument` instead", - ReplaceWith("commitAndUnblockDocument()", "org.jetbrains.kotlin.idea.codeinsight.utils.commitAndUnblockDocument") + ReplaceWith("commitAndUnblockDocument()", "org.jetbrains.kotlin.idea.codeinsight.utils.commitAndUnblockDocument"), + level = DeprecationLevel.ERROR ) fun PsiFile.commitAndUnblockDocument(): Boolean = _commitAndUnblockDocument() \ No newline at end of file diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/blockingCallsDetection/CoroutineBlockingCallInspectionUtils.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/blockingCallsDetection/CoroutineBlockingCallInspectionUtils.kt index 962b5e05bd1d..71c7e36d598c 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/blockingCallsDetection/CoroutineBlockingCallInspectionUtils.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/blockingCallsDetection/CoroutineBlockingCallInspectionUtils.kt @@ -12,8 +12,8 @@ import org.jetbrains.kotlin.builtins.isSuspendFunctionType import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.idea.base.util.reformatted import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall +import org.jetbrains.kotlin.idea.codeinsight.utils.commitAndUnblockDocument import org.jetbrains.kotlin.idea.core.ShortenReferences -import org.jetbrains.kotlin.idea.formatter.commitAndUnblockDocument import org.jetbrains.kotlin.idea.inspections.collections.isCalling import org.jetbrains.kotlin.idea.intentions.receiverType import org.jetbrains.kotlin.idea.refactoring.fqName.fqName From 1c0d05d3f3277dec414a181acf741444373c6cf0 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 7 Aug 2023 09:43:16 +0200 Subject: [PATCH 097/165] [kotlin] k2: report formatter statistics (KTIJ-26548) GitOrigin-RevId: cbf0d7776d78fad3af52ee4aa33223e51a7d1b79 --- plugins/kotlin/formatter/kotlin.formatter.iml | 1 + .../kotlin/idea/formatter/KotlinFormatterUsageCollector.kt | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename plugins/kotlin/{idea => formatter}/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt (96%) diff --git a/plugins/kotlin/formatter/kotlin.formatter.iml b/plugins/kotlin/formatter/kotlin.formatter.iml index 2dbaa230fbf1..2d130190926e 100644 --- a/plugins/kotlin/formatter/kotlin.formatter.iml +++ b/plugins/kotlin/formatter/kotlin.formatter.iml @@ -23,5 +23,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt similarity index 96% rename from plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt rename to plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt index 6b133d19553e..330a6d0422a2 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt +++ b/plugins/kotlin/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt @@ -7,14 +7,13 @@ import com.intellij.internal.statistic.beans.MetricEvent import com.intellij.internal.statistic.eventLog.EventLogGroup import com.intellij.internal.statistic.eventLog.events.EventFields import com.intellij.internal.statistic.service.fus.collectors.ProjectUsagesCollector -import com.intellij.internal.statistic.utils.getPluginInfoById +import com.intellij.internal.statistic.utils.getPluginInfo import com.intellij.openapi.project.Project import com.intellij.psi.codeStyle.CodeStyleSettings import com.intellij.psi.codeStyle.CodeStyleSettingsManager import org.jetbrains.kotlin.idea.base.util.KotlinPlatformUtils import org.jetbrains.kotlin.idea.base.util.containsNonScriptKotlinFile import org.jetbrains.kotlin.idea.base.util.runReadActionInSmartMode -import org.jetbrains.kotlin.idea.compiler.configuration.KotlinIdePlugin import org.jetbrains.kotlin.idea.formatter.KotlinFormatterUsageCollector.KotlinFormatterKind.* class KotlinFormatterUsageCollector : ProjectUsagesCollector() { @@ -30,7 +29,7 @@ class KotlinFormatterUsageCollector : ProjectUsagesCollector() { return setOf( settingsEvent.metric( value1 = getKotlinFormatterKind(project), - value2 = getPluginInfoById(KotlinIdePlugin.id), + value2 = getPluginInfo(KotlinFormatterUsageCollector::class.java), ) ) } From 66edb410abd2303191578b3c3406a99cb65b4f23 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 7 Aug 2023 11:21:10 +0200 Subject: [PATCH 098/165] [kotlin] k2: fix enum entity navigation (KTIJ-26546) GitOrigin-RevId: 9a45b130fe2f34f88261473ed8e2c219602caba4 --- ...tlinAnalysisApiBasedDeclarationNavigationPolicyImpl.kt | 8 ++++++++ .../AbstractKotlinNavigationToLibrarySourceTest.kt | 2 +- .../KotlinNavigationToLibrarySourceTestGenerated.java | 5 +++++ .../resolveToStdlib/classfiers/enumEntry.kt | 6 ++++++ 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 plugins/kotlin/navigation/tests/testData/navigationToLibrarySourcePolicy/resolveToStdlib/classfiers/enumEntry.kt diff --git a/plugins/kotlin/navigation/src/org/jetbrains/kotlin/idea/navigation/KotlinAnalysisApiBasedDeclarationNavigationPolicyImpl.kt b/plugins/kotlin/navigation/src/org/jetbrains/kotlin/idea/navigation/KotlinAnalysisApiBasedDeclarationNavigationPolicyImpl.kt index 742e12adbaa4..17611e892bd2 100644 --- a/plugins/kotlin/navigation/src/org/jetbrains/kotlin/idea/navigation/KotlinAnalysisApiBasedDeclarationNavigationPolicyImpl.kt +++ b/plugins/kotlin/navigation/src/org/jetbrains/kotlin/idea/navigation/KotlinAnalysisApiBasedDeclarationNavigationPolicyImpl.kt @@ -68,12 +68,20 @@ internal class KotlinAnalysisApiBasedDeclarationNavigationPolicyImpl : KotlinDec correspondingOwner.typeParameters.firstOrNull { it.name == declaration.name } } + is KtEnumEntry -> getCorrespondingEnumEntry(declaration, scope, project) is KtClassLikeDeclaration -> getCorrespondingClassLikeDeclaration(declaration, scope, project) is KtCallableDeclaration -> getCorrespondingCallableDeclaration(declaration, scope, project) else -> null } } + private fun getCorrespondingEnumEntry(declaration: KtEnumEntry, scope: GlobalSearchScope, project: Project): KtEnumEntry? { + val enumClass = declaration.containingClassOrObject ?: return null + val classLikeDeclaration = getCorrespondingClassLikeDeclaration(enumClass, scope, project) as? KtClass ?: return null + val enumEntryName = declaration.name + return classLikeDeclaration.declarations.firstOrNull { it is KtEnumEntry && it.name == enumEntryName } as? KtEnumEntry + } + private fun getCorrespondingClassLikeDeclaration( declaration: KtClassLikeDeclaration, scope: GlobalSearchScope, diff --git a/plugins/kotlin/navigation/tests/test/org/jetbrains/kotlin/idea/k2/navigation/AbstractKotlinNavigationToLibrarySourceTest.kt b/plugins/kotlin/navigation/tests/test/org/jetbrains/kotlin/idea/k2/navigation/AbstractKotlinNavigationToLibrarySourceTest.kt index f45317b4d006..3eaca8b5bbf9 100644 --- a/plugins/kotlin/navigation/tests/test/org/jetbrains/kotlin/idea/k2/navigation/AbstractKotlinNavigationToLibrarySourceTest.kt +++ b/plugins/kotlin/navigation/tests/test/org/jetbrains/kotlin/idea/k2/navigation/AbstractKotlinNavigationToLibrarySourceTest.kt @@ -45,7 +45,7 @@ abstract class AbstractKotlinNavigationToLibrarySourceTest : AbstractReferenceRe } private fun KtNamedDeclaration.signatureText(): String { - val firstElement = children.first { it !is PsiComment && it !is PsiWhiteSpace } + val firstElement = children.firstOrNull { it !is PsiComment && it !is PsiWhiteSpace } ?: return nameAsSafeName.asString() val endOffset = when (this) { is KtNamedFunction -> typeReference ?: valueParameterList?.rightParenthesis is KtProperty -> typeReference ?: equalsToken?.getPrevSiblingIgnoringWhitespace() diff --git a/plugins/kotlin/navigation/tests/test/org/jetbrains/kotlin/idea/k2/navigation/KotlinNavigationToLibrarySourceTestGenerated.java b/plugins/kotlin/navigation/tests/test/org/jetbrains/kotlin/idea/k2/navigation/KotlinNavigationToLibrarySourceTestGenerated.java index 60a725775e1e..a8ffcb402864 100644 --- a/plugins/kotlin/navigation/tests/test/org/jetbrains/kotlin/idea/k2/navigation/KotlinNavigationToLibrarySourceTestGenerated.java +++ b/plugins/kotlin/navigation/tests/test/org/jetbrains/kotlin/idea/k2/navigation/KotlinNavigationToLibrarySourceTestGenerated.java @@ -49,6 +49,11 @@ public abstract class KotlinNavigationToLibrarySourceTestGenerated extends Abstr runTest("testData/navigationToLibrarySourcePolicy/resolveToStdlib/classfiers/class.kt"); } + @TestMetadata("enumEntry.kt") + public void testEnumEntry() throws Exception { + runTest("testData/navigationToLibrarySourcePolicy/resolveToStdlib/classfiers/enumEntry.kt"); + } + @TestMetadata("unnamedCompanion.kt") public void testUnnamedCompanion() throws Exception { runTest("testData/navigationToLibrarySourcePolicy/resolveToStdlib/classfiers/unnamedCompanion.kt"); diff --git a/plugins/kotlin/navigation/tests/testData/navigationToLibrarySourcePolicy/resolveToStdlib/classfiers/enumEntry.kt b/plugins/kotlin/navigation/tests/testData/navigationToLibrarySourcePolicy/resolveToStdlib/classfiers/enumEntry.kt new file mode 100644 index 000000000000..3552083b3020 --- /dev/null +++ b/plugins/kotlin/navigation/tests/testData/navigationToLibrarySourcePolicy/resolveToStdlib/classfiers/enumEntry.kt @@ -0,0 +1,6 @@ +@Deprecated( + "deprecated message", + level = DeprecationLevel.ERROR +) +val p = 0 +// REF: (kotlin.DeprecationLevel.ERROR) ERROR From 6ead6bf330528bad75fc3bef9392ba6004a19e25 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 7 Aug 2023 11:52:52 +0200 Subject: [PATCH 099/165] [kotlin] k2: narrow highlighting scope for elvis can be equals inspection (KTIJ-26553) GitOrigin-RevId: 676b80b6b6b304ab41db746022cb4b67380563db --- .../inspections/NullableBooleanElvisInspection.kt | 6 ++++-- .../testData/inspectionsLocal/nullableBooleanElvis/inIf3.kt | 2 +- .../inspectionsLocal/nullableBooleanElvis/notInIf.kt | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/NullableBooleanElvisInspection.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/NullableBooleanElvisInspection.kt index d1dad824787d..da3981806e5f 100644 --- a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/NullableBooleanElvisInspection.kt +++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/NullableBooleanElvisInspection.kt @@ -8,7 +8,7 @@ import org.jetbrains.kotlin.idea.base.psi.replaced import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.codeinsight.api.applicable.inspections.AbstractKotlinApplicableInspection import org.jetbrains.kotlin.idea.codeinsight.api.applicators.KotlinApplicabilityRange -import org.jetbrains.kotlin.idea.codeinsights.impl.base.applicators.ApplicabilityRanges +import org.jetbrains.kotlin.idea.codeinsight.api.applicators.applicabilityRange import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* @@ -24,7 +24,9 @@ internal class NullableBooleanElvisInspection : AbstractKotlinApplicableInspecti override fun getProblemDescription(element: KtBinaryExpression): String = KotlinBundle.message("inspection.nullable.boolean.elvis.display.name") override fun getActionFamilyName(): String = KotlinBundle.message("inspection.nullable.boolean.elvis.action.name") - override fun getApplicabilityRange(): KotlinApplicabilityRange = ApplicabilityRanges.SELF + override fun getApplicabilityRange(): KotlinApplicabilityRange = applicabilityRange { expr -> + (expr as? KtBinaryExpression)?.operationReference?.textRangeInParent + } override fun isApplicableByPsi(element: KtBinaryExpression): Boolean = element.isTargetOfNullableBooleanElvisInspection() diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/nullableBooleanElvis/inIf3.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/nullableBooleanElvis/inIf3.kt index c3bdf0024608..4634dd57625b 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/nullableBooleanElvis/inIf3.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/nullableBooleanElvis/inIf3.kt @@ -1,7 +1,7 @@ fun foo() { var a: Boolean? = null var b: Boolean? = null - if (a ?: false || !(b ?: true)) { + if (a ?: false || !(b ?: true)) { } } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt index 759ad185a074..f5ff4b7994a5 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/nullableBooleanElvis/notInIf.kt @@ -1,4 +1,4 @@ fun foo() { var a: Boolean? = null - val x = a ?: false + val x = a ?: false } \ No newline at end of file From 9f152a6dddbc8a9f66726bf3686258cb129f1316 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 3 Aug 2023 22:21:38 +0200 Subject: [PATCH 100/165] [kotlin] KTIJ-26376 Provide collective dependents for `KtLibraryModule`s based on `LibraryInfo` Summary: - If a `LibraryInfo` comprises multiple, deduplicated `LibraryEx`s, `IdeKotlinModuleDependentsProvider` only provided the dependents of the anchor library. - The solution is to consider `LibraryInfo`s as a collection of `LibraryEx`s and to provide a union of *all* dependents. This solution leads to improved session invalidation consistency as well. #### Problem Consider the following `KtModule` structure with `M1` being a `KtLibraryModule` based on a `LibraryInfo` `I1` with anchor library `L2`: ``` M1 / \ L2 / \ L3 / \ M2 M3 ``` Let's say `L3`'s roots are replaced and `KotlinModuleStateModificationService`'s workspace listener notices it. Then `invalidateLibraryModule` fetches `I1` from the library info cache and publishes a modification event for `M1`. Currently, the invalidation service will find only `M2` as a dependent, because `IdeKotlinModuleDependentsProvider` returns dependents only for the library info's anchor library. `M3` is not recognized as a dependent, even though the original dependency link via `L3` is from `M1` to `M3`. An idea to fix this was to have multiple `LibraryInfo`s which are equal to each other, but contain the original `LibraryEx` instances with which they were created (so one library info based on `L2`, and another one based on `L3`). This would allow `KotlinModuleStateModificationService` to get only `M3` as a dependent of `L3`, because `LibraryInfoCache` would return a `LibraryInfo` for `L3` which contains `L3` as its anchor library instead of `L2`, while still being equal to the library info of `L2` (as we would want to keep the property that libraries with the same roots share the same session, for example). However, it would not be correct to only invalidate `M3`'s session either. Because a modification event is published for `M1`, its session is cleared. Symbols from that session cannot only be referenced from `M3`'s session, but also from `M2`'s session. So effectively *both* sessions need to be invalidated. This example illustrates the nature of `LibraryInfo`s well. As long as we want different `LibraryEx` instances with the same roots to share the same library sessions and have the same entries in caches (such as `LibraryDependenciesCache`), we have to treat such libraries as a *collection* and `LibraryInfo` is such a collection. A `KtLibraryModule` refers to a specific `LibraryInfo`, not a specific `LibraryEx`. The dependents computed by `IdeKotlinModuleDependentsProvider` must be the dependents of the `LibraryInfo`, not a single `LibraryEx`, and these are the dependents of *all* associated `LibraryEx` instances. This is also how `LibraryDependenciesCache` sees it, because `computeLibrariesAndSdksUsedWithNoFilter` gets all dependent modules via the library info, so all dependent modules of all `LibraryEx`s are mushed together in the dependent module set of the "combining" `LibraryInfo`. #### Solution We need a solution which works with the caching of (transitive) dependents. We cannot just get all deduplicated libraries from `LibraryInfoCache`, because the libraries are added as they are requested and the cache in `IdeKotlinModuleDependentsProvider` is not cleared when a new deduplicated library is added to `LibraryInfoCache`. (Nor should it, because the deduplication cache is an implementation detail of `LibraryInfoCache`.) Instead, we can use `LibraryUsageIndex` which `LibraryDependenciesCache` already relies on to find the dependent modules for some `LibraryInfo`, with full support for deduplicated libraries. This information is stable because it relies on module order entries. Given that `LibraryUsageIndex` is properly cleared on project structure changes, as is `IdeKotlinModuleDependentsProvider`'s cache, there should be no caching issues with this approach. #### Selective `LibraryEx` invalidation is messy Another possible solution for invalidation in the example above is to not invalidate `M1`'s session, but instead to only invalidate `M3`'s session. This would be legal because `L2` didn't change at all, and we just need some new session for `L3`. However, this comes with a few issues: 1. It breaks the simple consistency of *always* invalidating at least the session for which a modification event was published. The special handling of `LibraryInfo`s breaks conceptual boundaries in the Analysis API. 2. The session for `M1` does eventually need to be removed when the last `LibraryEx` has been removed/replaced, which increases complexity. 3. We would need to introduce special handling for anchor libraries (if still applicable), because a library info is removed when its anchor library is removed/replaced. So we wouldn't be able to keep `M1`'s session in that case, because we need to lose the reference to the invalid `LibraryInfo`. 4. We'd need to implement some way to get the dependents of specific `LibraryEx`s like `L3` via the `LibraryInfo`/`KtLibraryModule` interface, which does not fit into the conceptual model of `LibraryInfo` as a combined view on a collection of `LibraryEx`. ^KTIJ-26376 fixed GitOrigin-RevId: 72baaff8d9e8c62d40bd7b6be4a3cb1a60a1c8ad --- .../base/analysis/LibraryDependenciesCache.kt | 49 +----------- .../libraries/LibraryUsageIndexImpl.kt | 60 +++++++++++++++ .../IdeKotlinModuleDependentsProvider.kt | 77 ++++++++++--------- .../projectStructure/LibraryUsageIndex.kt | 17 ++++ .../ProjectModuleByModuleInfo.kt | 12 ++- .../common/resources/META-INF/caches.xml | 3 + 6 files changed, 128 insertions(+), 90 deletions(-) create mode 100644 plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/base/analysis/libraries/LibraryUsageIndexImpl.kt create mode 100644 plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/LibraryUsageIndex.kt diff --git a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/base/analysis/LibraryDependenciesCache.kt b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/base/analysis/LibraryDependenciesCache.kt index ebf7d5620425..09d5ed4e5a25 100644 --- a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/base/analysis/LibraryDependenciesCache.kt +++ b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/base/analysis/LibraryDependenciesCache.kt @@ -3,25 +3,18 @@ package org.jetbrains.kotlin.idea.base.analysis import com.intellij.ProjectTopics -import com.intellij.java.library.JavaLibraryModificationTracker import com.intellij.openapi.Disposable import com.intellij.openapi.application.assertReadAccessAllowed -import com.intellij.openapi.application.runReadAction import com.intellij.openapi.components.service import com.intellij.openapi.module.Module -import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.progress.ProgressManager.checkCanceled import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.ProjectJdkTable import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.* import com.intellij.openapi.roots.impl.libraries.LibraryEx -import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.util.Disposer -import com.intellij.psi.util.CachedValueProvider -import com.intellij.psi.util.CachedValuesManager import com.intellij.util.concurrency.annotations.RequiresReadLock -import com.intellij.util.containers.MultiMap import com.intellij.platform.backend.workspace.WorkspaceModelChangeListener import com.intellij.platform.backend.workspace.WorkspaceModelTopics import com.intellij.workspaceModel.ide.impl.legacyBridge.module.findModule @@ -29,7 +22,6 @@ import com.intellij.platform.workspace.storage.EntityStorage import com.intellij.platform.workspace.storage.VersionedStorageChange import com.intellij.platform.workspace.jps.entities.ModuleEntity import org.jetbrains.kotlin.idea.base.analysis.libraries.LibraryDependencyCandidate -import org.jetbrains.kotlin.idea.base.facet.isHMPPEnabled import org.jetbrains.kotlin.idea.base.projectStructure.* import org.jetbrains.kotlin.idea.base.projectStructure.LibraryDependenciesCache.LibraryDependencies import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.LibraryInfo @@ -39,7 +31,6 @@ import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.checkValidity import org.jetbrains.kotlin.idea.base.util.caching.ModuleEntityChangeListener import org.jetbrains.kotlin.idea.base.util.caching.SynchronizedFineGrainedEntityCache import org.jetbrains.kotlin.idea.caches.project.* -import org.jetbrains.kotlin.idea.caches.trackers.ModuleModificationTracker import org.jetbrains.kotlin.idea.configuration.isMavenized import org.jetbrains.kotlin.platform.jvm.isJvm import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -161,8 +152,7 @@ class LibraryDependenciesCacheImpl(private val project: Project) : LibraryDepend private fun computeLibrariesAndSdksUsedWithNoFilter(libraryInfo: LibraryInfo): LibraryDependencyCandidatesAndSdkInfos { val libraryDependencyCandidatesAndSdkInfos = LibraryDependencyCandidatesAndSdkInfosBuilder() - val modulesLibraryIsUsedIn = - getLibraryUsageIndex().getModulesLibraryIsUsedIn(libraryInfo) + val modulesLibraryIsUsedIn = project.service().getDependentModules(libraryInfo) for (module in modulesLibraryIsUsedIn) { checkCanceled() @@ -200,15 +190,6 @@ class LibraryDependenciesCacheImpl(private val project: Project) : LibraryDepend } } - private fun getLibraryUsageIndex(): LibraryUsageIndex = - CachedValuesManager.getManager(project).getCachedValue(project) { - CachedValueProvider.Result( - LibraryUsageIndex(), - ModuleModificationTracker.getInstance(project), - JavaLibraryModificationTracker.getInstance(project) - ) - }!! - private inner class LibraryDependenciesInnerCache : SynchronizedFineGrainedEntityCache(project, doSelfInitialization = false, cleanOnLowMemory = true), LibraryInfoListener, @@ -542,32 +523,4 @@ class LibraryDependenciesCacheImpl(private val project: Project) : LibraryDepend ) } } - - private inner class LibraryUsageIndex { - private val modulesLibraryIsUsedIn: MultiMap = runReadAction { - val map: MultiMap = MultiMap.createSet() - val libraryCache = LibraryInfoCache.getInstance(project) - for (module in ModuleManager.getInstance(project).modules) { - checkCanceled() - for (entry in ModuleRootManager.getInstance(module).orderEntries) { - if (entry !is LibraryOrderEntry) continue - val library = entry.library ?: continue - val keyLibrary = libraryCache.deduplicatedLibrary(library) - map.putValue(keyLibrary, module) - } - } - - map - } - - fun getModulesLibraryIsUsedIn(libraryInfo: LibraryInfo) = sequence { - val ideaModelInfosCache = getIdeaModelInfosCache(project) - for (module in modulesLibraryIsUsedIn[libraryInfo.library]) { - val mappedModuleInfos = ideaModelInfosCache.getModuleInfosForModule(module) - if (mappedModuleInfos.any { it.platform.canDependOn(libraryInfo, module.isHMPPEnabled) }) { - yield(module) - } - } - } - } } diff --git a/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/base/analysis/libraries/LibraryUsageIndexImpl.kt b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/base/analysis/libraries/LibraryUsageIndexImpl.kt new file mode 100644 index 000000000000..c0c128492740 --- /dev/null +++ b/plugins/kotlin/base/analysis/src/org/jetbrains/kotlin/idea/base/analysis/libraries/LibraryUsageIndexImpl.kt @@ -0,0 +1,60 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.base.analysis.libraries + +import com.intellij.java.library.JavaLibraryModificationTracker +import com.intellij.openapi.application.runReadAction +import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.project.Project +import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.LibraryOrderEntry +import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.roots.libraries.Library +import com.intellij.psi.util.CachedValue +import com.intellij.psi.util.CachedValueProvider +import org.jetbrains.kotlin.idea.base.facet.isHMPPEnabled +import com.intellij.psi.util.CachedValuesManager +import com.intellij.util.containers.MultiMap +import org.jetbrains.kotlin.idea.base.projectStructure.LibraryInfoCache +import org.jetbrains.kotlin.idea.base.projectStructure.LibraryUsageIndex +import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.LibraryInfo +import org.jetbrains.kotlin.idea.caches.project.canDependOn +import org.jetbrains.kotlin.idea.caches.project.getIdeaModelInfosCache +import org.jetbrains.kotlin.idea.caches.trackers.ModuleModificationTracker +import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus.checkCanceled + +class LibraryUsageIndexImpl(private val project: Project) : LibraryUsageIndex { + private val moduleDependentsByLibrary: CachedValue> = + CachedValuesManager.getManager(project).createCachedValue { + CachedValueProvider.Result( + computeLibraryModuleDependents(), + ModuleModificationTracker.getInstance(project), + JavaLibraryModificationTracker.getInstance(project), + ) + } + + override fun getDependentModules(libraryInfo: LibraryInfo): Sequence = sequence { + val ideaModelInfosCache = getIdeaModelInfosCache(project) + for (module in moduleDependentsByLibrary.value[libraryInfo.library]) { + val mappedModuleInfos = ideaModelInfosCache.getModuleInfosForModule(module) + if (mappedModuleInfos.any { it.platform.canDependOn(libraryInfo, module.isHMPPEnabled) }) { + yield(module) + } + } + } + + private fun computeLibraryModuleDependents(): MultiMap = runReadAction { + val moduleDependentsByLibrary = MultiMap.createSet() + val libraryCache = LibraryInfoCache.getInstance(project) + for (module in ModuleManager.getInstance(project).modules) { + checkCanceled() + for (entry in ModuleRootManager.getInstance(module).orderEntries) { + if (entry !is LibraryOrderEntry) continue + val library = entry.library ?: continue + val keyLibrary = libraryCache.deduplicatedLibrary(library) + moduleDependentsByLibrary.putValue(keyLibrary, module) + } + } + + moduleDependentsByLibrary + } +} diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt index 4324466ad06c..38c62b15ae75 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/IdeKotlinModuleDependentsProvider.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.idea.base.projectStructure import com.github.benmanes.caffeine.cache.Cache import com.github.benmanes.caffeine.cache.Caffeine +import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.openapi.roots.ProjectRootModificationTracker import com.intellij.platform.backend.workspace.WorkspaceModel @@ -20,6 +21,7 @@ import org.jetbrains.kotlin.analysis.project.structure.KtScriptModule import org.jetbrains.kotlin.analysis.project.structure.KtSdkModule import org.jetbrains.kotlin.analysis.project.structure.impl.KotlinModuleDependentsProviderBase import org.jetbrains.kotlin.idea.base.projectStructure.libraryToSourceAnalysis.ResolutionAnchorCacheService +import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.LibraryInfo import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.ModuleProductionSourceInfo import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.ModuleSourceInfo import org.jetbrains.kotlin.idea.base.projectStructure.util.getTransitiveLibraryDependencyInfos @@ -27,60 +29,45 @@ import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments import org.jetbrains.kotlin.utils.addIfNotNull /** - * [IdeKotlinModuleDependentsProvider] provides [KtModule] dependents by querying the workspace model. + * [IdeKotlinModuleDependentsProvider] provides [KtModule] dependents by querying the workspace model and Kotlin plugin indices/caches. */ internal class IdeKotlinModuleDependentsProvider(private val project: Project) : KotlinModuleDependentsProviderBase() { override fun getDirectDependents(module: KtModule): Set { - val symbolicId = when (module) { - is KtSourceModuleByModuleInfo -> module.moduleId - is KtLibraryModuleByModuleInfo -> module.libraryId ?: return emptySet() - is KtLibrarySourceModuleByModuleInfo -> return getDirectDependents(module.binaryLibrary) + return when (module) { + is KtSourceModuleByModuleInfo -> getDirectDependentsForSourceModule(module) + is KtLibraryModuleByModuleInfo -> getDirectDependentsForLibraryModule(module) + is KtLibrarySourceModuleByModuleInfo -> getDirectDependents(module.binaryLibrary) // No dependents need to be provided for `KtSdkModule` and `KtBuiltinsModule` (see `KotlinModuleDependentsProvider`). - is KtSdkModule -> return emptySet() - is KtBuiltinsModule -> return emptySet() + is KtSdkModule -> emptySet() + is KtBuiltinsModule -> emptySet() // Script modules are not supported yet (see KTIJ-25620). - is KtScriptModule, is KtScriptDependencyModule -> return emptySet() + is KtScriptModule, is KtScriptDependencyModule -> emptySet() - is NotUnderContentRootModuleByModuleInfo -> return emptySet() + is NotUnderContentRootModuleByModuleInfo -> emptySet() else -> throw KotlinExceptionWithAttachments("Unexpected ${KtModule::class.simpleName}").withAttachment("module.txt", module) } - - val directDependents = mutableSetOf() - directDependents.addFriendDependents(module) - directDependents.addWorkspaceModelDependents(symbolicId) - directDependents.addAnchorModuleDependents(module) - - return directDependents } - private fun MutableSet.addFriendDependents(module: KtModule) { + private fun getDirectDependentsForSourceModule(module: KtSourceModuleByModuleInfo): Set = + mutableSetOf().apply { + addFriendDependentsForSourceModule(module) + addWorkspaceModelDependents(module.moduleId) + addAnchorModuleDependents(module) + } + + private fun MutableSet.addFriendDependentsForSourceModule(module: KtSourceModuleByModuleInfo) { // The only friend dependency that currently exists in the IDE is the dependency of an IDEA module's test sources on its production // sources. Hence, a test source `KtModule` is a direct dependent of its production source `KtModule`. - if (module is KtSourceModuleByModuleInfo && module.ideaModuleInfo is ModuleProductionSourceInfo) { + if (module.ideaModuleInfo is ModuleProductionSourceInfo) { addIfNotNull(module.ideaModule.testSourceInfo?.toKtModule()) } } - private fun MutableSet.addWorkspaceModelDependents(symbolicId: SymbolicEntityId) { - val snapshot = WorkspaceModel.getInstance(project).currentSnapshot - snapshot - .referrers(symbolicId, ModuleEntity::class.java) - .forEach { moduleEntity -> - // The set of dependents should not include `module` itself. - if (moduleEntity.symbolicId == symbolicId) return@forEach - - // We can skip the module entity if `findModule` returns `null` because the module won't have been added to the project - // model yet and thus cannot be a proper `KtModule`. If there is a production source `KtModule`, we only need to add that - // because the test source `KtModule` will be a direct friend dependent of the production source `KtModule`. - addIfNotNull(moduleEntity.findModule(snapshot)?.productionOrTestSourceModuleInfo?.toKtModule()) - } - } - - private fun MutableSet.addAnchorModuleDependents(module: KtModule) { - val moduleInfo = (module as? KtSourceModuleByModuleInfo)?.ideaModuleInfo as? ModuleSourceInfo ?: return + private fun MutableSet.addAnchorModuleDependents(module: KtSourceModuleByModuleInfo) { + val moduleInfo = module.ideaModuleInfo as? ModuleSourceInfo ?: return // If `module` is an anchor module, it has library dependents in the form of anchoring libraries. See // `ResolutionAnchorCacheService` for additional documentation. @@ -103,6 +90,26 @@ internal class IdeKotlinModuleDependentsProvider(private val project: Project) : } } + private fun getDirectDependentsForLibraryModule(module: KtLibraryModuleByModuleInfo): Set = + project.service() + .getDependentModules(module.libraryInfo) + .mapNotNullTo(mutableSetOf()) { it.productionOrTestSourceModuleInfo?.toKtModule() } + + private fun MutableSet.addWorkspaceModelDependents(symbolicId: SymbolicEntityId) { + val snapshot = WorkspaceModel.getInstance(project).currentSnapshot + snapshot + .referrers(symbolicId, ModuleEntity::class.java) + .forEach { moduleEntity -> + // The set of dependents should not include `module` itself. + if (moduleEntity.symbolicId == symbolicId) return@forEach + + // We can skip the module entity if `findModule` returns `null` because the module won't have been added to the project + // model yet and thus cannot be a proper `KtModule`. If there is a production source `KtModule`, we only need to add that + // because the test source `KtModule` will be a direct friend dependent of the production source `KtModule`. + addIfNotNull(moduleEntity.findModule(snapshot)?.productionOrTestSourceModuleInfo?.toKtModule()) + } + } + /** * Caching transitive dependents is crucial. [getTransitiveDependents] will frequently be called by session invalidation when typing in * a Kotlin file. Large projects might have core modules with over a hundred or even a thousand transitive dependents. At the same time, diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/LibraryUsageIndex.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/LibraryUsageIndex.kt new file mode 100644 index 000000000000..a4b5db746e5e --- /dev/null +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/LibraryUsageIndex.kt @@ -0,0 +1,17 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.base.projectStructure + +import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.libraries.Library +import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.LibraryInfo + +/** + * For each [LibraryInfo], [LibraryUsageIndex] contains all [Module]s which depend on that library info. The index supports deduplicated + * libraries: if a [LibraryInfo] comprises two [Library] instances with the same roots, [getDependentModules] will return the union of both + * [Library]'s dependents. + * + * The resulting dependents are stable and do not depend on the state of [LibraryInfoCache], as they are computed from the project model. + */ +interface LibraryUsageIndex { + fun getDependentModules(libraryInfo: LibraryInfo): Sequence +} diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectModuleByModuleInfo.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectModuleByModuleInfo.kt index 515c004a0ca9..0ecdb1a2e6e8 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectModuleByModuleInfo.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ProjectModuleByModuleInfo.kt @@ -159,22 +159,20 @@ private object DependencyKeys { val TEST_MODULE_DEPENDENCIES_IGNORED = Key.create>>("TEST_MODULE_DEPENDENCIES_IGNORED") } -internal class KtLibraryModuleByModuleInfo(private val moduleInfo: LibraryInfo) : KtModuleByModuleInfoBase(moduleInfo), KtLibraryModule { +internal class KtLibraryModuleByModuleInfo(val libraryInfo: LibraryInfo) : KtModuleByModuleInfoBase(libraryInfo), KtLibraryModule { override val libraryName: String - get() = moduleInfo.library.name ?: "Unnamed library" - - val libraryId: LibraryId? get() = (moduleInfo.library as? LibraryBridge)?.libraryId + get() = libraryInfo.library.name ?: "Unnamed library" override val librarySources: KtLibrarySourceModule - get() = moduleInfo.sourcesModuleInfo.toKtModuleOfType() + get() = libraryInfo.sourcesModuleInfo.toKtModuleOfType() override fun getBinaryRoots(): Collection { - return moduleInfo.getLibraryRoots().map(Paths::get) + return libraryInfo.getLibraryRoots().map(Paths::get) } override val contentScope: GlobalSearchScope get() = ideaModuleInfo.contentScope - override val project: Project get() = moduleInfo.project + override val project: Project get() = libraryInfo.project } internal class SdkKtModuleByModuleInfo(private val moduleInfo: SdkInfo) : KtModuleByModuleInfoBase(moduleInfo), KtSdkModule { diff --git a/plugins/kotlin/plugin/common/resources/META-INF/caches.xml b/plugins/kotlin/plugin/common/resources/META-INF/caches.xml index ce5642a73d34..08683a21dadf 100644 --- a/plugins/kotlin/plugin/common/resources/META-INF/caches.xml +++ b/plugins/kotlin/plugin/common/resources/META-INF/caches.xml @@ -25,6 +25,9 @@ + From 94d693e30b7c1ec999cc2290456fed470dba25cf Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 3 Aug 2023 22:22:29 +0200 Subject: [PATCH 101/165] [kotlin] Add documentation to `LibraryInfo` about deduplication GitOrigin-RevId: 4e39e63fbae3169c523cc9a977175cf295514846 --- .../projectStructure/moduleInfo/LibraryInfo.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/moduleInfo/LibraryInfo.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/moduleInfo/LibraryInfo.kt index df434d3d66d5..d46601a0394e 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/moduleInfo/LibraryInfo.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/moduleInfo/LibraryInfo.kt @@ -22,7 +22,19 @@ import org.jetbrains.kotlin.platform.* import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices /** - * @see [org.jetbrains.kotlin.idea.base.projectStructure.LibraryInfoCache] + * [LibraryInfo] is the Kotlin plugin's view on a [LibraryEx]. + * + * Multiple different [LibraryEx]s with the same content may be mapped to a single [LibraryInfo]. For example, two different module-level + * libraries with the same roots will have the same [LibraryInfo]. Such libraries are called *deduplicated*. The deduplication is performed + * by [LibraryInfoCache]. This avoids keeping multiple, duplicate cache entries for [LibraryEx]s with effectively the same content. + * + * The dependencies and dependents of a [LibraryInfo] are calculated from *all* [LibraryEx]s associated with it. In that sense, a + * [LibraryInfo] is a *collection* of [LibraryEx]s. + * + * @param library The *anchor library* which acts as the content reference for the [LibraryInfo]. It is sometimes used as a cache key in + * deduplication contexts. It is *not* necessarily the only [LibraryEx] associated with this [LibraryInfo]. + * + * @see LibraryInfoCache */ abstract class LibraryInfo internal constructor( override val project: Project, From 9933c7be1ab5e4ad891e184fa3c6fcc13ec4f837 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 3 Aug 2023 22:25:26 +0200 Subject: [PATCH 102/165] [kotlin] Support library roots in `AbstractProjectStructureTest`s - Library roots configuration can be used to add test cases with deduplicated libraries. If two libraries have the same roots, they will both map to the same library info. GitOrigin-RevId: 71da2c73bff7cde0515e83fcabcce445dc978454 --- .../providers/AbstractProjectStructureTest.kt | 16 +++++++++++++--- .../testProjectStructure/TestProjectStructure.kt | 14 ++++++++++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt index 5abca5f644e9..23ecc5907345 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/AbstractProjectStructureTest.kt @@ -3,12 +3,15 @@ package org.jetbrains.kotlin.idea.fir.analysis.providers import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.testFramework.PsiTestUtil +import com.intellij.util.io.jarFile import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.TestProjectStructureReader import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil +import org.jetbrains.kotlin.idea.test.addRoot import org.jetbrains.kotlin.test.util.addDependency import java.nio.file.Paths @@ -25,8 +28,17 @@ abstract class AbstractProjectStructureTest : Abstract testProjectStructureParser = parser, ) + val jarFilesByRootLabel = testStructure.libraries + .flatMapTo(mutableSetOf()) { it.roots } + .associate { it to jarFile { }.generateInTempDir().toFile() } + val projectLibrariesByName = testStructure.libraries.associate { libraryData -> - libraryData.name to createProjectLibrary(libraryData.name) + libraryData.name to ConfigLibraryUtil.addProjectLibrary(project, libraryData.name) { + libraryData.roots.forEach { rootLabel -> + addRoot(jarFilesByRootLabel.getValue(rootLabel), OrderRootType.CLASSES) + } + commit() + } } val modulesByName = testStructure.modules.associate { moduleData -> @@ -50,8 +62,6 @@ abstract class AbstractProjectStructureTest : Abstract return Triple(testStructure, projectLibrariesByName, modulesByName) } - private fun createProjectLibrary(name: String): Library = ConfigLibraryUtil.addProjectLibraryWithClassesRoot(project, name) - private fun createEmptyModule(name: String): Module { val tmpDir = createTempDirectory().toPath() val module: Module = createModule("$tmpDir/$name", moduleType) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt index 600daeb29604..dfdb096ffa8d 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/testProjectStructure/TestProjectStructure.kt @@ -6,6 +6,7 @@ import com.google.gson.JsonElement import com.google.gson.JsonObject import org.jetbrains.kotlin.idea.fir.analysis.providers.testProjectStructure.getAsStringList import org.jetbrains.kotlin.idea.jsonUtils.getString +import java.util.UUID interface TestProjectStructure { /** @@ -24,12 +25,21 @@ fun interface TestProjectStructureParser { fun parse(libraries: List, modules: List, json: JsonObject): S } -data class TestProjectLibrary(val name: String) +/** + * @param roots A list of labels for the library's roots. The test infrastructure generates a unique, temporary JAR file for each such + * label. This allows adding the same root to multiple libraries without having to wrangle JAR files in the test data. + * The property is optional in `structure.json`. If absent, the library receives a single, unique root which won't be shared + * with other libraries. + */ +data class TestProjectLibrary(val name: String, val roots: List) object TestProjectLibraryParser { + private const val ROOTS_FIELD = "roots" + fun parse(json: JsonElement): TestProjectLibrary { require(json is JsonObject) - return TestProjectLibrary(json.getString("name")) + val roots = json.getAsStringList(ROOTS_FIELD) ?: listOf(UUID.randomUUID().toString()) + return TestProjectLibrary(json.getString("name"), roots) } } From 1f7bc8e7755227594ac55424e70800c80489871a Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Thu, 3 Aug 2023 22:27:29 +0200 Subject: [PATCH 103/165] [kotlin] KTIJ-26376 Add module dependents test for deduplicated libraries GitOrigin-RevId: 066de225bdfc7b502b7f1a0928117754b2b9836d --- .../ModuleDependentsTestGenerated.java | 5 ++++ .../deduplicatedLibraries/description.md | 7 +++++ .../deduplicatedLibraries/structure.json | 29 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/deduplicatedLibraries/description.md create mode 100644 plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/deduplicatedLibraries/structure.json diff --git a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java index d7983e8914ce..21f740a5e630 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java +++ b/plugins/kotlin/base/fir/analysis-api-providers/test/org/jetbrains/kotlin/idea/fir/analysis/providers/dependents/ModuleDependentsTestGenerated.java @@ -43,6 +43,11 @@ public class ModuleDependentsTestGenerated extends AbstractModuleDependentsTest runTest("testData/moduleDependents/cyclicalWithOutsideDependency/"); } + @TestMetadata("deduplicatedLibraries") + public void testDeduplicatedLibraries() throws Exception { + runTest("testData/moduleDependents/deduplicatedLibraries/"); + } + @TestMetadata("linear") public void testLinear() throws Exception { runTest("testData/moduleDependents/linear/"); diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/deduplicatedLibraries/description.md b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/deduplicatedLibraries/description.md new file mode 100644 index 000000000000..51f11cd9b074 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/deduplicatedLibraries/description.md @@ -0,0 +1,7 @@ +Different libraries with the same roots are deduplicated by `LibraryInfoCache` into the same `LibraryInfo`. As explained in `LibraryInfo`'s +documentation, a library info and by extension a `KtLibraryModule` should be considered a *collection* of `LibraryEx`s. This test ensures +that `IdeKotlinModuleDependentsProvider` provides the correct dependents for such "collective" `LibraryInfo`s. It is a bit unintuitive that +`L1` and `L2` have the same dependents, but it's the correct result when viewing `LibraryInfo`s as a collection. + +Furthermore, the test ensures that another library `L3` with partially matching roots is not considered in the calculation of the dependents +of `L1` and `L2`. diff --git a/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/deduplicatedLibraries/structure.json b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/deduplicatedLibraries/structure.json new file mode 100644 index 000000000000..73110e49b670 --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/testData/moduleDependents/deduplicatedLibraries/structure.json @@ -0,0 +1,29 @@ +{ + "libraries": [ + { "name": "L1", "roots": ["R1", "R2"] }, + { "name": "L2", "roots": ["R1", "R2"] }, + { "name": "L3", "roots": ["R1", "R3"] } + ], + "modules": [ + { "name": "A", "dependsOn": ["L1", "L3"] }, + { "name": "B", "dependsOn": ["L2"] }, + { "name": "C", "dependsOn": ["L3"] } + ], + "targets": [ + { + "library": "L1", + "directDependents": ["A", "B"], + "transitiveDependents": ["A", "B"] + }, + { + "library": "L2", + "directDependents": ["A", "B"], + "transitiveDependents": ["A", "B"] + }, + { + "library": "L3", + "directDependents": ["A", "C"], + "transitiveDependents": ["A", "C"] + } + ] +} From edbeaeb1880d02edf36808774260049bc544bb98 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Fri, 4 Aug 2023 17:03:10 +0200 Subject: [PATCH 104/165] [kotlin] KTIJ-26369 Add module state listeners for external file changes and dynamic plugin loads/unloads - `fileWithNoDocumentChanged` is a bit of a complex case: - Changes to the `.idea/workspace.xml` file are currently propagated to `fileWithNoDocumentChanged`, so we have to filter it out. Otherwise, we'd publish a global module state modification event on possibly every workspace model change, which completely defeats the purpose of granular, module-level module state modification events. - It's not documented well that `FileDocumentManagerListener` is project-independent. So our `FileDocumentListener` has to consult the project index first. Otherwise, no-document changes to another project's file, even changes to another project's `workspace.xml` (because the `project.workspaceFile` check only covers the *current* project), will cause a global module state modification event in the unrelated project. ^KTIJ-26369 fixed GitOrigin-RevId: e5851dc3e93de14531f61149a2347a99bedfa774 --- .../kotlin.base.analysis-api-providers.iml | 1 + .../KotlinModuleStateModificationService.kt | 35 +++++++++++++++++++ ...kotlin.base.fir.analysis-api-providers.xml | 4 +++ 3 files changed, 40 insertions(+) diff --git a/plugins/kotlin/base/analysis-api-providers/kotlin.base.analysis-api-providers.iml b/plugins/kotlin/base/analysis-api-providers/kotlin.base.analysis-api-providers.iml index 970709a0b33d..70b1f4692aa3 100644 --- a/plugins/kotlin/base/analysis-api-providers/kotlin.base.analysis-api-providers.iml +++ b/plugins/kotlin/base/analysis-api-providers/kotlin.base.analysis-api-providers.iml @@ -25,5 +25,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 6633c5bfdc9d..182a2cc84d58 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -1,8 +1,11 @@ // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.base.analysisApiProviders +import com.intellij.ide.plugins.DynamicPluginListener +import com.intellij.ide.plugins.IdeaPluginDescriptor import com.intellij.java.workspace.entities.JavaSourceRootPropertiesEntity import com.intellij.openapi.Disposable +import com.intellij.openapi.fileEditor.FileDocumentManagerListener import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.ProjectJdkTable @@ -10,6 +13,7 @@ import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ModuleRootEvent import com.intellij.openapi.roots.ModuleRootListener +import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.StandardFileSystems @@ -134,6 +138,37 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab } } + internal class FileDocumentListener(private val project: Project) : FileDocumentManagerListener { + override fun fileWithNoDocumentChanged(file: VirtualFile) { + // `FileDocumentManagerListener` may receive events from other projects via `FileDocumentManagerImpl`'s `AsyncFileListener`. + if (!ProjectFileIndex.getInstance(project).isInContent(file)) { + return + } + + // Workspace model changes are already handled by `KotlinModuleStateModificationService`, so we shouldn't publish a module state + // modification event when the `workspace.xml` is changed by the IDE. + if (file == project.workspaceFile) { + return + } + + // "No document" means no pomModel change. If the file's PSI was not loaded, then a modification event would be published via + // the `PsiTreeChangeEvent.PROP_UNLOADED_PSI` event. If the PSI was loaded, then `FileManagerImpl.reloadPsiAfterTextChange` is + // fired which doesn't provide any explicit changes, so we need to publish a global modification event because the file's + // content may have been changed externally. + KotlinGlobalModificationService.getInstance(project).publishGlobalModuleStateModification() + } + } + + internal class MyDynamicPluginListener(private val project: Project) : DynamicPluginListener { + override fun beforePluginUnload(pluginDescriptor: IdeaPluginDescriptor, isUpdate: Boolean) { + KotlinGlobalModificationService.getInstance(project).publishGlobalModuleStateModification() + } + + override fun pluginLoaded(pluginDescriptor: IdeaPluginDescriptor) { + KotlinGlobalModificationService.getInstance(project).publishGlobalModuleStateModification() + } + } + @ApiStatus.Internal fun beforeWorkspaceModelChanged(event: VersionedStorageChange) { handleLibraryChanges(event) diff --git a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml index 9ce80aec079f..d010f0be7d6d 100644 --- a/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml +++ b/plugins/kotlin/base/fir/analysis-api-providers/resources/kotlin.base.fir.analysis-api-providers.xml @@ -24,6 +24,10 @@ topic="com.intellij.openapi.projectRoots.ProjectJdkTable$Listener"/> + + From ffb9ff00d5cd365900db8fe1055df5b5534566a3 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Fri, 4 Aug 2023 17:08:43 +0200 Subject: [PATCH 105/165] [kotlin] Make `KotlinModuleStateModificationService` listeners internal - They should only be registered in the XML configuration and not used anywhere else. GitOrigin-RevId: a2b31db150c34b1ccbb7204e8e2f3b4ae0d408d2 --- .../KotlinModuleStateModificationService.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt index 182a2cc84d58..5fef3d284b05 100644 --- a/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt +++ b/plugins/kotlin/base/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/analysisApiProviders/KotlinModuleStateModificationService.kt @@ -82,7 +82,7 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab * A global out-of-block modification event will be published by `FirIdeOutOfBlockPsiTreeChangePreprocessor` when a Kotlin file is * moved, but we still need this listener to publish a module state modification event specifically. */ - class SingleFileModuleModificationListener(private val project: Project) : AbstractSingleFileModuleBeforeFileEventListener(project) { + internal class SingleFileModuleModificationListener(private val project: Project) : AbstractSingleFileModuleBeforeFileEventListener(project) { override fun isRelevantEvent(event: VFileEvent, file: VirtualFile): Boolean = event is VFileMoveEvent || event is VFileDeleteEvent override fun processEvent(event: VFileEvent, module: KtModule) { @@ -94,7 +94,7 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab } } - class LibraryUpdatesListener(private val project: Project) : BulkFileListener { + internal class LibraryUpdatesListener(private val project: Project) : BulkFileListener { val index = ProjectRootManager.getInstance(project).fileIndex private val moduleStateModificationService: KotlinModuleStateModificationService get() = getInstance(project) @@ -118,7 +118,7 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab } } - class JdkListener(private val project: Project) : ProjectJdkTable.Listener { + internal class JdkListener(private val project: Project) : ProjectJdkTable.Listener { override fun jdkRemoved(jdk: Sdk) { // Most modules will depend on an SDK, so its removal constitutes global module state modification. We cannot be more // fine-grained here because `KtSdkModules`s aren't supported by `IdeKotlinModuleDependentsProvider`, so invalidation based on @@ -127,7 +127,7 @@ open class KotlinModuleStateModificationService(val project: Project) : Disposab } } - class NonWorkspaceModuleRootListener(private val project: Project) : ModuleRootListener { + internal class NonWorkspaceModuleRootListener(private val project: Project) : ModuleRootListener { override fun beforeRootsChange(event: ModuleRootEvent) { if (event.isCausedByWorkspaceModelChangesOnly) return From d92eddb8e05239eab9ddd8f64fd81a2773eda9ce Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Mon, 7 Aug 2023 09:35:10 +0200 Subject: [PATCH 106/165] [kotlin] Migrate method separators to K2 #KTIJ-26470 Fixed GitOrigin-RevId: 1f3c398d50da28272e7c8f8f4ca99d72d48bedba --- ...otlin.code-insight.line-markers-shared.iml | 1 + .../KotlinLineMarkersSharedBundle.properties | 3 +- .../AbstractKotlinLineMarkerProvider.kt | 75 +++++++++++++++++++ .../kotlin.code-insight.line-markers-k2.iml | 1 + .../lineMarkers/KotlinLineMarkerProvider.kt | 17 +---- .../markers/KotlinLineMarkerProvider.kt | 64 +++------------- .../methodSeparators/MethodSeparators.kt | 7 +- 7 files changed, 98 insertions(+), 70 deletions(-) create mode 100644 plugins/kotlin/code-insight/line-markers-shared/src/org/jetbrains/kotlin/idea/codeInsight/lineMarkers/shared/AbstractKotlinLineMarkerProvider.kt diff --git a/plugins/kotlin/code-insight/line-markers-shared/kotlin.code-insight.line-markers-shared.iml b/plugins/kotlin/code-insight/line-markers-shared/kotlin.code-insight.line-markers-shared.iml index 6509bb0da6b0..0c64fe6b7bb2 100644 --- a/plugins/kotlin/code-insight/line-markers-shared/kotlin.code-insight.line-markers-shared.iml +++ b/plugins/kotlin/code-insight/line-markers-shared/kotlin.code-insight.line-markers-shared.iml @@ -18,5 +18,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/code-insight/line-markers-shared/resources/messages/KotlinLineMarkersSharedBundle.properties b/plugins/kotlin/code-insight/line-markers-shared/resources/messages/KotlinLineMarkersSharedBundle.properties index 3175cb50660f..f31d7869b3dd 100644 --- a/plugins/kotlin/code-insight/line-markers-shared/resources/messages/KotlinLineMarkersSharedBundle.properties +++ b/plugins/kotlin/code-insight/line-markers-shared/resources/messages/KotlinLineMarkersSharedBundle.properties @@ -1,4 +1,5 @@ highlighter.title.actuals.for=Actuals for {0} highlighter.title.choose.actual.for=Choose Actual For {0} highlighter.title.choose.expected.for=Choose Expected For {0} -highlighter.title.expected.for=Expected for {0} \ No newline at end of file +highlighter.title.expected.for=Expected for {0} +highlighter.name.kotlin.line.markers=Kotlin line markers \ No newline at end of file diff --git a/plugins/kotlin/code-insight/line-markers-shared/src/org/jetbrains/kotlin/idea/codeInsight/lineMarkers/shared/AbstractKotlinLineMarkerProvider.kt b/plugins/kotlin/code-insight/line-markers-shared/src/org/jetbrains/kotlin/idea/codeInsight/lineMarkers/shared/AbstractKotlinLineMarkerProvider.kt new file mode 100644 index 000000000000..892f180d25eb --- /dev/null +++ b/plugins/kotlin/code-insight/line-markers-shared/src/org/jetbrains/kotlin/idea/codeInsight/lineMarkers/shared/AbstractKotlinLineMarkerProvider.kt @@ -0,0 +1,75 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.codeInsight.lineMarkers.shared + +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings +import com.intellij.codeInsight.daemon.LineMarkerInfo +import com.intellij.codeInsight.daemon.LineMarkerProviderDescriptor +import com.intellij.openapi.editor.colors.CodeInsightColors +import com.intellij.openapi.editor.colors.EditorColorsManager +import com.intellij.openapi.editor.markup.SeparatorPlacement +import com.intellij.openapi.project.DumbService +import com.intellij.openapi.util.text.StringUtil +import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.idea.base.projectStructure.RootKindFilter +import org.jetbrains.kotlin.idea.base.projectStructure.matches +import org.jetbrains.kotlin.idea.highlighter.markers.KotlinLineMarkerOptions +import org.jetbrains.kotlin.psi.KtClassInitializer +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.psi.KtObjectDeclaration +import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments + +typealias LineMarkerInfos = MutableCollection> + +abstract class AbstractKotlinLineMarkerProvider : LineMarkerProviderDescriptor() { + override fun getName() = KotlinLineMarkersSharedBundle.message("highlighter.name.kotlin.line.markers") + + override fun getOptions(): Array