diff --git a/.idea/dependencyResolver.xml b/.idea/dependencyResolver.xml new file mode 100644 index 000000000000..f4a28cc180f1 --- /dev/null +++ b/.idea/dependencyResolver.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/libraries/ASM.xml b/.idea/libraries/ASM.xml index a80b1151b4fa..f90ce93004ad 100644 --- a/.idea/libraries/ASM.xml +++ b/.idea/libraries/ASM.xml @@ -1,6 +1,12 @@ - + + + + a1b68c71e5c72ff41fefea29f8d1c2499f2e31278acf8e312249df349b263fbe + + + @@ -9,4 +15,4 @@ - + \ No newline at end of file diff --git a/.idea/libraries/CGLIB.xml b/.idea/libraries/CGLIB.xml index b11851fd8719..1b58dc389c2a 100644 --- a/.idea/libraries/CGLIB.xml +++ b/.idea/libraries/CGLIB.xml @@ -1,6 +1,12 @@ - + + + + 3366d2c88fb576e486d830f521184e8f1839f8c15dcd2151a3f6e1f62b0b37a0 + + + diff --git a/.idea/libraries/Gradle.xml b/.idea/libraries/Gradle.xml index fa32959c1b11..5935da711e0c 100644 --- a/.idea/libraries/Gradle.xml +++ b/.idea/libraries/Gradle.xml @@ -1,6 +1,21 @@ - + + + + 2754fb93e0ea6e7d7e20c6b8c3e3dc51e723ce9be156f00a60038d605d19c20a + + + eee1cbe2bffb08863dd879a37d17539bbd7188b762153fa5c94ce5888d218a3e + + + 5c9a1a6f50b4f8c0264b1ac69013bef9f8363733275fafa56c70c84be3276bb8 + + + 8ffd8aa02fd30adf36a6d5fa0b00a3c67e9e26577cb81ea3915853a5bf970ac7 + + + diff --git a/.idea/libraries/Guava.xml b/.idea/libraries/Guava.xml index de38fdcdb241..1561fcc1e0a2 100644 --- a/.idea/libraries/Guava.xml +++ b/.idea/libraries/Guava.xml @@ -1,6 +1,17 @@ + + + a42edc9cab792e39fe39bb94f3fca655ed157ff87a8af78e1d6ba5b07c4a00ab + + + a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26 + + + 21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b + + diff --git a/.idea/libraries/HdrHistogram.xml b/.idea/libraries/HdrHistogram.xml index 9ecd82732ce5..118d877bc6e5 100644 --- a/.idea/libraries/HdrHistogram.xml +++ b/.idea/libraries/HdrHistogram.xml @@ -1,6 +1,12 @@ - + + + + 9b47fbae444feaac4b7e04f0ea294569e4bc282bc69d8c2ce2ac3f23577281e2 + + + diff --git a/.idea/libraries/JUnit3.xml b/.idea/libraries/JUnit3.xml index 390c432608f1..35803d8ce65e 100644 --- a/.idea/libraries/JUnit3.xml +++ b/.idea/libraries/JUnit3.xml @@ -1,6 +1,12 @@ - + + + + b58e459509e190bed737f3592bc1950485322846cf10e78ded1d065153012d70 + + + diff --git a/.idea/libraries/JUnit4.xml b/.idea/libraries/JUnit4.xml index 9b6761f44afe..a0a4fc6a750e 100644 --- a/.idea/libraries/JUnit4.xml +++ b/.idea/libraries/JUnit4.xml @@ -1,6 +1,15 @@ - + + + + 8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3 + + + 66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9 + + + diff --git a/.idea/libraries/JUnit5.xml b/.idea/libraries/JUnit5.xml index 52d1a9e84ac4..859323ad4ef8 100644 --- a/.idea/libraries/JUnit5.xml +++ b/.idea/libraries/JUnit5.xml @@ -1,6 +1,21 @@ - + + + + 5d2fe4d719dffb25a95d77e9c7a34893cbbb1b4cc6c86f2726af7e0fb7035b2f + + + 58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2 + + + a8e82d510bbbce5fe1777b2ecf7bc68401e9ae8327009e029b2db5798403d25e + + + b509448ac506d607319f182537f0b35d71007582ec741832a1f111e5b5b70b38 + + + @@ -15,4 +30,4 @@ - + \ No newline at end of file diff --git a/.idea/libraries/JUnit5Jupiter.xml b/.idea/libraries/JUnit5Jupiter.xml index 8af4f6ae6435..a34d7b8873c3 100644 --- a/.idea/libraries/JUnit5Jupiter.xml +++ b/.idea/libraries/JUnit5Jupiter.xml @@ -1,6 +1,12 @@ - + + + + 8bbc506b4f603ede1f6bafd8eee69a9cc43de0c26a0ee8d40d583d3feeedc2e9 + + + @@ -9,4 +15,4 @@ - + \ No newline at end of file diff --git a/.idea/libraries/JUnit5Launcher.xml b/.idea/libraries/JUnit5Launcher.xml index 25b70bff31b9..dec7c05dd172 100644 --- a/.idea/libraries/JUnit5Launcher.xml +++ b/.idea/libraries/JUnit5Launcher.xml @@ -1,6 +1,14 @@ + + + 5fb50ef56168358892e1bd0a080e2e5bb74dc882b2ecc2a9bad0eadb5a6a449e + + + f59c3a67087f2b9bbb17a9c06dd416697989b2c53b38843874ebbbbcb0afc23f + + @@ -17,4 +25,4 @@ - + \ No newline at end of file diff --git a/.idea/libraries/JUnit5Params.xml b/.idea/libraries/JUnit5Params.xml index 5a25d8770a5b..207ffe868634 100644 --- a/.idea/libraries/JUnit5Params.xml +++ b/.idea/libraries/JUnit5Params.xml @@ -1,6 +1,12 @@ - + + + + 30157f26d857ba4f84c0d84d156f55f056e80dc09b4281affa8b1ed4d3205c08 + + + @@ -9,4 +15,4 @@ - + \ No newline at end of file diff --git a/.idea/libraries/JUnit5Suites.xml b/.idea/libraries/JUnit5Suites.xml index 55fdb66bd4dc..fa018b75cd36 100644 --- a/.idea/libraries/JUnit5Suites.xml +++ b/.idea/libraries/JUnit5Suites.xml @@ -1,6 +1,20 @@ + + + a21d4de7695ecabaff20b21a641d8f1e35bb2f3e57e752fd94f2209d87f06228 + + + f49e2a8983a52e2e5566a16828d634a02592ab8bf51d23c5c091214bc15e57b4 + + + e7b7ee49332764acaa64f88cfe4c624e4d69b15d04cacbf98103ed91d027e06c + + + 8279775f6a9b075e394a888b8ab1226307c86fb925b4414270be9518cf07377c + + @@ -22,4 +36,4 @@ - + \ No newline at end of file diff --git a/.idea/libraries/JUnit5Vintage.xml b/.idea/libraries/JUnit5Vintage.xml index 295759dc7c6b..1ecfba04b7d9 100644 --- a/.idea/libraries/JUnit5Vintage.xml +++ b/.idea/libraries/JUnit5Vintage.xml @@ -1,6 +1,12 @@ - + + + + b97de493877c9ba5e4f03b44bd348a53e5fc9df2df5b1a048923e0204f7d7178 + + + diff --git a/.idea/libraries/Java_Compatibility.xml b/.idea/libraries/Java_Compatibility.xml index a213f15ad1f5..ac6b3559e364 100644 --- a/.idea/libraries/Java_Compatibility.xml +++ b/.idea/libraries/Java_Compatibility.xml @@ -1,6 +1,12 @@ - + + + + 1f799c9e7691a4dcddb1cb3e28e8517d5e6b27c2ac75093f39714afdc9216950 + + + diff --git a/.idea/libraries/Jaxen.xml b/.idea/libraries/Jaxen.xml index 42538dbb007d..881cb66f11a6 100644 --- a/.idea/libraries/Jaxen.xml +++ b/.idea/libraries/Jaxen.xml @@ -1,6 +1,12 @@ - + + + + 70feef9dd75ad064def05a3ce8975aeba515ee7d1be146d12199c8828a64174c + + + diff --git a/.idea/libraries/Kryo5.xml b/.idea/libraries/Kryo5.xml index b280297c9e39..ee0ac30498a6 100644 --- a/.idea/libraries/Kryo5.xml +++ b/.idea/libraries/Kryo5.xml @@ -1,6 +1,12 @@ - + + + + 5dab506f91ab06adad1acb5fe904e587c2781593a7930f003e84f6597622f3b2 + + + diff --git a/.idea/libraries/Log4J.xml b/.idea/libraries/Log4J.xml index 93be12e18578..f9f3cd1f71ff 100644 --- a/.idea/libraries/Log4J.xml +++ b/.idea/libraries/Log4J.xml @@ -1,6 +1,12 @@ - + + + + 0a7e032bf5bcdd5b2bf8bf2e5cf02c5646f2aa6fee66933b8150dbe84e651e8a + + + diff --git a/.idea/libraries/NanoXML.xml b/.idea/libraries/NanoXML.xml index 998d209e7eb5..ddd231d40874 100644 --- a/.idea/libraries/NanoXML.xml +++ b/.idea/libraries/NanoXML.xml @@ -1,6 +1,12 @@ - + + + + 76f5f1fb2193f186d699f6cf396505d63e4dc8c14f8e7517f763845fa87a88bf + + + diff --git a/.idea/libraries/Objenesis.xml b/.idea/libraries/Objenesis.xml index 3e0e6ac09b72..aad7e9806dec 100644 --- a/.idea/libraries/Objenesis.xml +++ b/.idea/libraries/Objenesis.xml @@ -1,6 +1,12 @@ - + + + + 03d960bd5aef03c653eb000413ada15eb77cdd2b8e4448886edf5692805e35f3 + + + diff --git a/.idea/libraries/OroMatcher.xml b/.idea/libraries/OroMatcher.xml index b641664b693c..d8482cc86932 100644 --- a/.idea/libraries/OroMatcher.xml +++ b/.idea/libraries/OroMatcher.xml @@ -1,6 +1,12 @@ - + + + + e00ccdad5df7eb43fdee44232ef64602bf63807c2d133a7be83ba09fd49af26e + + + diff --git a/.idea/libraries/SSHJ.xml b/.idea/libraries/SSHJ.xml index bfb2b86a781c..2cb09cc47fbd 100644 --- a/.idea/libraries/SSHJ.xml +++ b/.idea/libraries/SSHJ.xml @@ -1,6 +1,17 @@ + + + d3b3d71f3e834c7e52d022036c2e96c2b21c8ec7baa20270965c4d59e2e4d86e + + + e4f70fd92849b52240048b8ebace0c9a17d3bb7b9c882b3c7778cec3458495f5 + + + 4dda1120db856640dbec04140ed23242215a075fe127bdefa0dcfa29fb31267d + + diff --git a/.idea/libraries/Slf4j.xml b/.idea/libraries/Slf4j.xml index 79f8d0c5b1c6..875f421d0dd3 100644 --- a/.idea/libraries/Slf4j.xml +++ b/.idea/libraries/Slf4j.xml @@ -1,6 +1,11 @@ + + + d3ef575e3e4979678dc01bf1dcce51021493b4d11fb7f1be8ad982877c16a1c0 + + diff --git a/.idea/libraries/StreamEx.xml b/.idea/libraries/StreamEx.xml index bb5c96e41170..73e154ee1b19 100644 --- a/.idea/libraries/StreamEx.xml +++ b/.idea/libraries/StreamEx.xml @@ -1,6 +1,12 @@ - + + + + 84dbfa4730565134504d65cdd823341c8b2ee655e2d1c5f004cf95bff0180655 + + + diff --git a/.idea/libraries/TestNG.xml b/.idea/libraries/TestNG.xml index 7b496bffcda1..bc855045d987 100644 --- a/.idea/libraries/TestNG.xml +++ b/.idea/libraries/TestNG.xml @@ -1,6 +1,17 @@ + + + 7c686ba8696f8206473b1b78e7e4947191b2aa4891c57b184b44ad4e052d2c08 + + + deeac157c8de6822878d85d0c7bc8467a19cc8484d37788f7804f039dde280b1 + + + da2381fbee4799631ba44d1f4d6487b886b22450c7fc85842c5fdfa03429b817 + + diff --git a/.idea/libraries/Velocity.xml b/.idea/libraries/Velocity.xml index 38d287f784b6..49628da23cc2 100644 --- a/.idea/libraries/Velocity.xml +++ b/.idea/libraries/Velocity.xml @@ -1,6 +1,12 @@ - + + + + b086cee8fd8183e240b4afcf54fe38ec33dd8eb0da414636e5bf7aa4d9856629 + + + diff --git a/.idea/libraries/XStream.xml b/.idea/libraries/XStream.xml index dbec2554df9e..89d16d07a764 100644 --- a/.idea/libraries/XStream.xml +++ b/.idea/libraries/XStream.xml @@ -1,6 +1,18 @@ - + + + + 87df0f0be57c92037d0110fbb225a30b651702dc275653d285afcfef31bc2e81 + + + aeeee23a3303d811bca8790ea7f25b534314861c03cff36dafdcc2180969eb97 + + + 34e08ee62116071cbb69c0ed70d15a7a5b208d62798c59f2120bb8929324cb63 + + + diff --git a/.idea/libraries/Xerces.xml b/.idea/libraries/Xerces.xml index b359a1564d5f..46466d3ca003 100644 --- a/.idea/libraries/Xerces.xml +++ b/.idea/libraries/Xerces.xml @@ -1,6 +1,12 @@ - + + + + 6fc991829af1708d15aea50c66f0beadcd2cfeb6968e0b2f55c1b0909883fe16 + + + diff --git a/.idea/libraries/XmlRPC.xml b/.idea/libraries/XmlRPC.xml index 19655b61ad1e..eb1f71bf93e6 100644 --- a/.idea/libraries/XmlRPC.xml +++ b/.idea/libraries/XmlRPC.xml @@ -1,6 +1,12 @@ - + + + + 36efda6efee96e83602c9ba246db19bf4c5e733324390d2fa8213417d6b681e7 + + + diff --git a/.idea/libraries/aalto_xml.xml b/.idea/libraries/aalto_xml.xml index ae2855fd9d3d..36e0c6a2d262 100644 --- a/.idea/libraries/aalto_xml.xml +++ b/.idea/libraries/aalto_xml.xml @@ -1,6 +1,15 @@ - + + + + dcf2d5f453056c3ce848caff4179021bfb83b5efb3a3d779433c5bd70976068b + + + badf6081a0bb526fd2c01951dfefad91b6846b6dd0eb0048587e30d1dd334e68 + + + diff --git a/.idea/libraries/aapt_proto.xml b/.idea/libraries/aapt_proto.xml index 413f0c2db0b0..9ade8ef923ae 100644 --- a/.idea/libraries/aapt_proto.xml +++ b/.idea/libraries/aapt_proto.xml @@ -1,6 +1,12 @@ - + + + + a503219b89b0aaf7b7c6c9b3b17d69e655a6c619072b684a1ea4fbf1d7dc49da + + + diff --git a/.idea/libraries/aia_proto.xml b/.idea/libraries/aia_proto.xml index aed7467adfed..39865c9bce59 100644 --- a/.idea/libraries/aia_proto.xml +++ b/.idea/libraries/aia_proto.xml @@ -1,6 +1,12 @@ - + + + + fc56d0846f53f85b3cb443f3bbf13405b3361ff48cb74ec03d226a7b55e1f90c + + + diff --git a/.idea/libraries/android_test_plugin_host_device_info_proto.xml b/.idea/libraries/android_test_plugin_host_device_info_proto.xml index 69a84bc47a3f..bf0889499e86 100644 --- a/.idea/libraries/android_test_plugin_host_device_info_proto.xml +++ b/.idea/libraries/android_test_plugin_host_device_info_proto.xml @@ -1,6 +1,12 @@ - + + + + b6e1c5f2f773dad73e0b9f3f774db4100d275e818b1a53c1358ec94f881ca605 + + + diff --git a/.idea/libraries/ap_validation.xml b/.idea/libraries/ap_validation.xml index a6baeffbb4cc..2cd4993e1307 100644 --- a/.idea/libraries/ap_validation.xml +++ b/.idea/libraries/ap_validation.xml @@ -1,6 +1,14 @@ + + + 3d2123e0a17edd77776f083d04b2465fdb30d07484be658db0304587bd54ba07 + + + 2d931e26e6632f608a6dab0fb60d27fae075260bf4532bb6ba8828d81bd167b3 + + diff --git a/.idea/libraries/asm_tools.xml b/.idea/libraries/asm_tools.xml index a171c45c9a28..d5e31e60a60f 100644 --- a/.idea/libraries/asm_tools.xml +++ b/.idea/libraries/asm_tools.xml @@ -1,6 +1,18 @@ - + + + + 37fd5392bb2cf4c15f202ffefd46d0e92bb34ff848c549f30d426a60d6b29495 + + + ae629c2609f39681ef8d140a42a23800464a94f2d23e36d8f25cd10d5e4caff4 + + + 1263369b59e29c943918de11d6d6152e2ec6085ce63e5710516f8c67d368e4bc + + + diff --git a/.idea/libraries/assertJ.xml b/.idea/libraries/assertJ.xml index 048fb124e919..1897494b4985 100644 --- a/.idea/libraries/assertJ.xml +++ b/.idea/libraries/assertJ.xml @@ -1,6 +1,15 @@ - + + + + df3d0b348f1fe806bdddcb10fa4ae63c6679e9888d4bc7055f09848517976aa3 + + + f6f45c2237a7f132c16745ad2a52c4cdde58028b11ee80b09f0d422f4930d685 + + + diff --git a/.idea/libraries/assertj_swing.xml b/.idea/libraries/assertj_swing.xml index 456ac94cb73d..91b126642a3b 100644 --- a/.idea/libraries/assertj_swing.xml +++ b/.idea/libraries/assertj_swing.xml @@ -1,6 +1,12 @@ - + + + + e36445438d72d83cc48015dcb3f14d9a97eaa42c4663a9826db2bb50e4c7713b + + + diff --git a/.idea/libraries/automaton.xml b/.idea/libraries/automaton.xml index ab7db01cd958..e7c9bafbf820 100644 --- a/.idea/libraries/automaton.xml +++ b/.idea/libraries/automaton.xml @@ -1,6 +1,12 @@ - + + + + d75c864362cb9fdb741809c2317a4dcfa7433c9043d773269b4a7b1b1c2234f9 + + + diff --git a/.idea/libraries/baksmali.xml b/.idea/libraries/baksmali.xml index 60ec1a95a68d..5538aad721ac 100644 --- a/.idea/libraries/baksmali.xml +++ b/.idea/libraries/baksmali.xml @@ -1,21 +1,29 @@ + + + d74a3c71bc2cd5786a960a546221ad44abd05506067f1aa7ae50f041ff859e1e + + + 7008f8d3fb63920d044e7d1f387a0ccff6a7e328ff252a90554d7a0e4c7f8014 + + - - - - + + + + - - + + - + - - + + \ No newline at end of file diff --git a/.idea/libraries/blockmap.xml b/.idea/libraries/blockmap.xml index bc36376d3688..c4990b3d4b8c 100644 --- a/.idea/libraries/blockmap.xml +++ b/.idea/libraries/blockmap.xml @@ -1,6 +1,11 @@ + + + ea4e6f77856806c2c79916c194e85c558d23623fac661ca307da2e8775676a9c + + diff --git a/.idea/libraries/bouncy_castle_pgp.xml b/.idea/libraries/bouncy_castle_pgp.xml index 40db01dbe514..d132de9fb81f 100644 --- a/.idea/libraries/bouncy_castle_pgp.xml +++ b/.idea/libraries/bouncy_castle_pgp.xml @@ -1,6 +1,12 @@ - + + + + dd6efbd826f0d3aed3a1193acf1d81dd6044c585b90ddf88adca4e1fb41a0984 + + + diff --git a/.idea/libraries/bouncy_castle_provider.xml b/.idea/libraries/bouncy_castle_provider.xml index 7b064847c08e..260d27ae5a95 100644 --- a/.idea/libraries/bouncy_castle_provider.xml +++ b/.idea/libraries/bouncy_castle_provider.xml @@ -1,6 +1,18 @@ - + + + + 9487164ba018f2211fcc0f989d6f4ea25b7d48fc6031501c3c7e3a17b164d860 + + + ad3ae628f4459a8fecb5c1a142b5525ce5118817414f97efd92f5448a69180ff + + + 0b70292c36cfe08ac00a71f5cc5af4c412ceedbc8c0f0a22995dbacfaf25dd42 + + + diff --git a/.idea/libraries/caffeine.xml b/.idea/libraries/caffeine.xml index 6e191c21d484..fdb75f19e09d 100644 --- a/.idea/libraries/caffeine.xml +++ b/.idea/libraries/caffeine.xml @@ -1,6 +1,12 @@ - + + + + 0311f9d5d9750aa2a1c11cbdba5a5cb7fec91c8870d6f179f324b3f5295b87dd + + + diff --git a/.idea/libraries/classgraph.xml b/.idea/libraries/classgraph.xml index 5f6b22ee6b74..b2c55403683d 100644 --- a/.idea/libraries/classgraph.xml +++ b/.idea/libraries/classgraph.xml @@ -1,6 +1,12 @@ - + + + + fb99167dc45bf34f9e40141069f68583a53104c45ffca410642255d1ca81343f + + + diff --git a/.idea/libraries/cli_parser.xml b/.idea/libraries/cli_parser.xml index 8003aaa04cfe..6e972cc83e20 100644 --- a/.idea/libraries/cli_parser.xml +++ b/.idea/libraries/cli_parser.xml @@ -1,6 +1,12 @@ - + + + + 436143bc3b925a1af4d0b8c9c7c53ac5c937f0f7aa32e4d97a24ce0a301ede27 + + + diff --git a/.idea/libraries/cloud_config_client.xml b/.idea/libraries/cloud_config_client.xml index 15eeb62ad391..a0309d6b3fee 100644 --- a/.idea/libraries/cloud_config_client.xml +++ b/.idea/libraries/cloud_config_client.xml @@ -1,6 +1,12 @@ - + + + + f2246f96f74545e025787f281a8bef2920601d55f7251d9d7a449744083e3265 + + + diff --git a/.idea/libraries/commons_cli.xml b/.idea/libraries/commons_cli.xml index e7dce3b568de..f60f920d367e 100644 --- a/.idea/libraries/commons_cli.xml +++ b/.idea/libraries/commons_cli.xml @@ -1,6 +1,12 @@ - + + + + bc8bb01fc0fad250385706e20f927ddcff6173f6339b387dc879237752567ac6 + + + diff --git a/.idea/libraries/commons_codec.xml b/.idea/libraries/commons_codec.xml index 9870fdd01ab2..1d44af082a06 100644 --- a/.idea/libraries/commons_codec.xml +++ b/.idea/libraries/commons_codec.xml @@ -1,6 +1,12 @@ - + + + + b3e9f6d63a790109bf0d056611fbed1cf69055826defeb9894a71369d246ed63 + + + diff --git a/.idea/libraries/commons_collections.xml b/.idea/libraries/commons_collections.xml index 03ad469a82f0..779b88fc7d08 100644 --- a/.idea/libraries/commons_collections.xml +++ b/.idea/libraries/commons_collections.xml @@ -1,6 +1,12 @@ - + + + + eeeae917917144a68a741d4c0dff66aa5c5c5fd85593ff217bced3fc8ca783b8 + + + diff --git a/.idea/libraries/commons_compress.xml b/.idea/libraries/commons_compress.xml index 8d1f9dd7f081..09dbd160257c 100644 --- a/.idea/libraries/commons_compress.xml +++ b/.idea/libraries/commons_compress.xml @@ -1,6 +1,12 @@ - + + + + c267f17160e9ef662b4d78b7f29dca7c82b15c5cff2cb6a9865ef4ab3dd5b787 + + + diff --git a/.idea/libraries/commons_imaging.xml b/.idea/libraries/commons_imaging.xml index f4e4fcf1677a..44bd97222c48 100644 --- a/.idea/libraries/commons_imaging.xml +++ b/.idea/libraries/commons_imaging.xml @@ -1,6 +1,12 @@ - + + + + ba1cb46e5494286940b016da372ae94a60d2dbc411b6dac5db1e40128725d501 + + + diff --git a/.idea/libraries/commons_io.xml b/.idea/libraries/commons_io.xml index efcb4433316d..a380ea499bad 100644 --- a/.idea/libraries/commons_io.xml +++ b/.idea/libraries/commons_io.xml @@ -1,6 +1,12 @@ - + + + + 961b2f6d87dbacc5d54abf45ab7a6e2495f89b75598962d8c723cea9bc210908 + + + diff --git a/.idea/libraries/commons_lang.xml b/.idea/libraries/commons_lang.xml index 22bd9909d49b..3219c2880ed9 100644 --- a/.idea/libraries/commons_lang.xml +++ b/.idea/libraries/commons_lang.xml @@ -1,6 +1,12 @@ - + + + + 50f11b09f877c294d56f24463f47d28f929cf5044f648661c0f0cfbae9a2f49c + + + diff --git a/.idea/libraries/commons_lang3.xml b/.idea/libraries/commons_lang3.xml index 843dc1bcebac..d99e1e475538 100644 --- a/.idea/libraries/commons_lang3.xml +++ b/.idea/libraries/commons_lang3.xml @@ -1,6 +1,12 @@ - + + + + d919d904486c037f8d193412da0c92e22a9fa24230b9d67a57855c5c31c7e94e + + + diff --git a/.idea/libraries/commons_logging.xml b/.idea/libraries/commons_logging.xml index 7e82563dc962..89dd626af9b6 100644 --- a/.idea/libraries/commons_logging.xml +++ b/.idea/libraries/commons_logging.xml @@ -1,6 +1,12 @@ - + + + + daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636 + + + diff --git a/.idea/libraries/compile_testing.xml b/.idea/libraries/compile_testing.xml index 8525210cdab4..48363f4e31d1 100644 --- a/.idea/libraries/compile_testing.xml +++ b/.idea/libraries/compile_testing.xml @@ -1,6 +1,12 @@ - + + + + 55746fa706fb051a53f61d205eb66ee31e33ed1936d92b323c7001df18ad3acb + + + diff --git a/.idea/libraries/cucumber_core.xml b/.idea/libraries/cucumber_core.xml index 953b6701808d..e76ad037e7ab 100644 --- a/.idea/libraries/cucumber_core.xml +++ b/.idea/libraries/cucumber_core.xml @@ -1,6 +1,14 @@ + + + 424f81cb5ce84386bd310d572f8edd91723cde58abd52f65db5888e0b38eb8f5 + + + 0a5ebc0506ab1e4a08af1ca150f797304ff53b953c5b1f6fcf1f81551d964aad + + diff --git a/.idea/libraries/cucumber_core_2_0_1.xml b/.idea/libraries/cucumber_core_2_0_1.xml index 340fdfb91d2b..c4dea165f7f1 100644 --- a/.idea/libraries/cucumber_core_2_0_1.xml +++ b/.idea/libraries/cucumber_core_2_0_1.xml @@ -1,6 +1,24 @@ - + + + + ac0f343d6fc0dca4c93f8b6a6266b3bf4cb4d61913b8a4cd2b3abf50025268cf + + + e2167e99bdb018576cce9cc0aad154ad995fe67a4b0c36c63344f743865f96e7 + + + d1c2cc901dd702eb77a2258c0d1446e4a302d28da0d4b49cd11ff3d5929281fa + + + e35cfa4a16204bf59fa167bb6d45be0717d6b7cfba1c30f156d8f21cde2f4065 + + + e5a0a71fb846752900c0e5a99aa13e5a1bbc3ec97e7faf26803648fa45215584 + + + diff --git a/.idea/libraries/cucumber_testing.xml b/.idea/libraries/cucumber_testing.xml index 847f9d4f9c51..98b970098a42 100644 --- a/.idea/libraries/cucumber_testing.xml +++ b/.idea/libraries/cucumber_testing.xml @@ -1,6 +1,12 @@ - + + + + 2a4e84a51defe9108579b3c0a86bb41e54f04e9042e83adf4348a974dcf1dee6 + + + diff --git a/.idea/libraries/decentxml.xml b/.idea/libraries/decentxml.xml index 633e3a0b8c8f..c44bf0c6a986 100644 --- a/.idea/libraries/decentxml.xml +++ b/.idea/libraries/decentxml.xml @@ -1,6 +1,12 @@ - + + + + fe671ff552a8d724710e37fdb224b19c9aaf16ed3ce8dc8bbc694788f79edd41 + + + diff --git a/.idea/libraries/download_pgp_verifier.xml b/.idea/libraries/download_pgp_verifier.xml index d770b60f8a61..4913652d38a3 100644 --- a/.idea/libraries/download_pgp_verifier.xml +++ b/.idea/libraries/download_pgp_verifier.xml @@ -1,6 +1,12 @@ - + + + + 81110da550181e2f8d90c7161f71fb8e9f8777632e75c37fbed5fbf3a0feacb4 + + + diff --git a/.idea/libraries/easymock.xml b/.idea/libraries/easymock.xml index 8152b56fd39a..32036fead075 100644 --- a/.idea/libraries/easymock.xml +++ b/.idea/libraries/easymock.xml @@ -1,6 +1,12 @@ - + + + + c230864c8b11636aaa6bb49eee00a4342d3e016d860b4f80b89068fd056d1404 + + + diff --git a/.idea/libraries/ec4j_core.xml b/.idea/libraries/ec4j_core.xml index 86426f70816d..a87e559afe38 100644 --- a/.idea/libraries/ec4j_core.xml +++ b/.idea/libraries/ec4j_core.xml @@ -1,6 +1,12 @@ - + + + + cadef0207077074b11a12be442f89ab6cf93fbc2f848702d9371a9611414d558 + + + diff --git a/.idea/libraries/emulator_proto.xml b/.idea/libraries/emulator_proto.xml index 84adfaeb79fa..121e3a337e3b 100644 --- a/.idea/libraries/emulator_proto.xml +++ b/.idea/libraries/emulator_proto.xml @@ -1,6 +1,12 @@ - + + + + 3638a1709a24d0a09956257ea10487b12c90dbaba478b2a06b02f1eafab5d467 + + + diff --git a/.idea/libraries/equalsverifier.xml b/.idea/libraries/equalsverifier.xml index 4dee321891bc..897c64c22569 100644 --- a/.idea/libraries/equalsverifier.xml +++ b/.idea/libraries/equalsverifier.xml @@ -1,6 +1,12 @@ - + + + + 23d9184d69c939cfee78981b53e84a257bfd5e9e902c1c0af2cced97f16a2e85 + + + diff --git a/.idea/libraries/error_prone_annotations.xml b/.idea/libraries/error_prone_annotations.xml index e92019380602..b6ccea68b32e 100644 --- a/.idea/libraries/error_prone_annotations.xml +++ b/.idea/libraries/error_prone_annotations.xml @@ -1,6 +1,12 @@ - + + + + 2668536a354cda63d19885fcabdecd8d6298aec4260cdfdf34b722e964d60396 + + + diff --git a/.idea/libraries/fastutil_min.xml b/.idea/libraries/fastutil_min.xml index 1239fd030f08..aa1533ee4045 100644 --- a/.idea/libraries/fastutil_min.xml +++ b/.idea/libraries/fastutil_min.xml @@ -1,6 +1,12 @@ - + + + + 1d36e528b8fa8e878ec4bf28e7c6acc374a89336b96e9bed7ebf735b1787febd + + + diff --git a/.idea/libraries/ffmpeg.xml b/.idea/libraries/ffmpeg.xml index 30db986be496..8e9d94b93176 100644 --- a/.idea/libraries/ffmpeg.xml +++ b/.idea/libraries/ffmpeg.xml @@ -1,6 +1,12 @@ - + + + + 37d53454b3c704bea04d7b8388b6e4c6789a57152f63cee0c414b3dd730d3464 + + + diff --git a/.idea/libraries/ffmpeg_javacpp.xml b/.idea/libraries/ffmpeg_javacpp.xml index 30bf7a652211..0713b135383b 100644 --- a/.idea/libraries/ffmpeg_javacpp.xml +++ b/.idea/libraries/ffmpeg_javacpp.xml @@ -1,6 +1,12 @@ - + + + + 27d5eaf8f4433f6404aae0ad34cdbbfac75174e244c11d38222e0d075af33863 + + + diff --git a/.idea/libraries/ffmpeg_platform.xml b/.idea/libraries/ffmpeg_platform.xml index 9b571b67519b..8de29ec8f716 100644 --- a/.idea/libraries/ffmpeg_platform.xml +++ b/.idea/libraries/ffmpeg_platform.xml @@ -1,6 +1,42 @@ - + + + + 83b925c8dade91b7ae1e6a44f142266bdcc31b30a727cac2d75744cca784efcf + + + 37d53454b3c704bea04d7b8388b6e4c6789a57152f63cee0c414b3dd730d3464 + + + 5761863f13760b5609ff85ce7780dcdb71c8b8256c1c6b817ece4e5c86ea7f5b + + + 64b7c4ccebe0475d0121717fa76218392a77b3c39da77f681d58c48689edddf4 + + + 85f1cb19db3c9c642aed219fed2954390fc368c489f0701b6966207fb3e5dd7c + + + ce354e994754311bb590ed38da0289cad55c68948b44d6b313cf32690246c40e + + + 27d5eaf8f4433f6404aae0ad34cdbbfac75174e244c11d38222e0d075af33863 + + + 36b78057cdcc5fa0dc950e29271a58c0a6efc5573bd9bd2845b99cccbb3116a7 + + + c605748036b7158edca0128c3febce6bae7c4b297406563ebae2a0dcbc591261 + + + 6c4f0bf404787c5a374c573b2445d5d6d8ce620f7c9ef41b2c601d1fe3836d6a + + + 1bb08194d76780cd885fbfd27ed24dfb1ca088ee0b7a8aea25a836cb1506eedc + + + diff --git a/.idea/libraries/flexmark.xml b/.idea/libraries/flexmark.xml index 04b2124a57e6..b75d8733595d 100644 --- a/.idea/libraries/flexmark.xml +++ b/.idea/libraries/flexmark.xml @@ -1,6 +1,182 @@ + + + 6211a32328f27888527c4bfe7809ae9a56cb56008a6173459cee9a91bbad3139 + + + 2eaaa51313ee2f5dce1e04ddbf793496b790a8e5ffb9841d7f52a8520eb6b753 + + + 00a3a6b59343f71c04b0771a596684f970ad4b6b264875e68d60128fccaebb71 + + + 29cb23d79b9099f6714377db8c7a3f0ca99cb6c73ec51549692072b6cf0c310b + + + 2faf1daeee5f083080861360ec713da200827ba4e8a3a75d4986e25742a74a34 + + + e8f949d6328c4aa6cb2682f4f41c18cc6ae46d9b9c793e6db1b6db68e136dfdc + + + 30196af44231431e129292f51ff1a2871149eef834cc5bdddd5886e0b4c838ad + + + 768dd44a59df0823d61e2d824403c83ccb85625519ffaa0acb07371f3cbb18cd + + + 9f6e086420030922367bebaeef109bc6814ccdfff032a123a385c882a74a061e + + + a80be030f6386f18111cad9161c0b6983157352a1b59a59e6002172f0d321c04 + + + 977629f9065b9a6d84c4cb065f206740cb4be9c112aa9ce369ba5e9103d99391 + + + 40bb90895ce19ceef5b1d9d4402c252cf44a1707454d9e617060ac3d81316702 + + + 1c25bdccea3f3bcb5f263cdb97e5b471e54d2d5c8130bf3d5daee221b3b52861 + + + 3ebdc04e6af19c0a98a4347817fb55d25dd9cec77a280e1aea59efdbce29921d + + + 5308e869da67621d8b2252c192498d545c9c17427ef45603606248fb77744c71 + + + 7b2a6a4570966b9b651565b57c309f690144d93cb48eb03f02aacd58700dd92b + + + 503a073ab4b1dbd2576497a597eb51f1361902fb7b294c605e898485ab91db2c + + + eb469f3b48b4f1b4cbfa127410d9c55120ca761eaa675a03210c6052b9bdcb99 + + + 43c52ebaf42d1852ced4605c5e8d53e1cdf5bc4a03753816aaebea0b23346fdf + + + d608dffefafd1c4cdb9cc7cba07be462f72e22c9b0fedc96fd578a42f1fc4e90 + + + 9205baa5c0851e6a4784aa20ea29aa75c1942c0e1b2448c5925a3769e0c3ad93 + + + 79209b1ca5cf7b1a9b9940aec061046f957ee661d72b89e2480aaec253cf7e60 + + + 81d563c08d793b10fa72f3001d97a4d8c9d474b17441e496f65e15e969c6faa4 + + + 85f569f477b98fd1fbb0c0b5705c7bc4e2ca0434a0a92a7ccd6ec8b2617456af + + + 89b482f01fe4c05237d510117c69228c43e8896d1dd4d2fbea148eae04fe6713 + + + 357eff83842e0a38f64c3c9b3d07d10f88539d7360cfaccd922d5a6a8cbb3e4b + + + f602762ea5e695b624020c76b97be077932a324ec88babf01fd19b966dd0a750 + + + 66422167fd4651d11f79aee9ec4e42da89822d817e4574cfd2d333b6fb32833e + + + 44ebd9975b9a9f6ca3639385012bfd0a25a7e44e81db7d72ceb0023c658cb013 + + + 7510fb997d81002e953d70579129fd3f492acbd5ea36b6363a29d1a2e26c12eb + + + 49cd84ea5e07944e895951053272dd67c69a6f10af4a2a77fffea85b0b9289ea + + + 6bd7d9d9d6e47f8a1df4b805afb0d0204fa68ec776d349c8d7b5f062a617e6f0 + + + c34a9c0b128c75af842c31f92ba1750f355f3319505f36c428515192d9bc7a74 + + + a66d48a36afd5679cf722445f318cac25bd1ae67d74f5604473f83210f89386e + + + 8daa944ae51847913a5ed0e9746fa3c8dfa11379039a91b3f6bbc35f31b36114 + + + 324edeb333d711e3b82a0975164eb35c5ab1f1f8bf084c0c4ed68d51a70402bb + + + 6b486b6a78717e768b3df56e91df30a7f9257f74366fd870afb204f3bc0970ac + + + 3e6fd2250d833d500b7cd48b7a896700d0c33bd9f77a219e820493b01566eda3 + + + 7de90df1b3ecf84e6f0daf808d724c11142007a2f22bff1936479bf17251d31a + + + 3c2c0553ec0e7533c490b4c952e1af113621de5275af6e380e11d0d9a0a4f3d6 + + + 2e8c0a569a90b04734fbc0c805d77f4ec03f98c11f5705055ccd7718c1953d68 + + + 27383df2285b9e228c39f2c755adeebbef774793d33c4f20f0dc99e9ebaaf673 + + + 37f8f387395f96c214ac44f7475c7a2e1f832dfc1de289a3610e0ffbf728f679 + + + 5675c0b56d613b15446f9d0922d89781af48f05331326a87bdb3d1775c703215 + + + eb7ba2f2d6a59479ae3f04e3b844c9efe5c7a5fb55579602b70232fcd351287b + + + cbeca04fd93dec035ff4b85deffa976a0a1f25b5c374ad482750b2b8682f211b + + + d7ca1d1f027457a5fecd0b4e0dd360d888f4b335bed809c1046fa75466ae96dc + + + 2218cd239254472e73e98fc3f4ee82880419409816bbb5857956da7cc8ea70fe + + + 5f68e6da2785071000c9be8e1ea6968f306d8e1457370cc060e9ff7974e5f89f + + + 40613e94469e43d91d3a853f4c63f97e3e1be891cd64bed6e2a7f6338e7f6024 + + + 94abc1de6ae49473c9397ead4344f55daaed39b3081943451178b789e5eb5650 + + + a4cd2efe840a133fe408a2bfabc92a21d84402d9af9e829e052a745102e8f28c + + + ae188a5588e18b37256bbaa1b314731ffc07d691704124458465193081da53d7 + + + 166fffb18e34b4ae80a1893aad10e1f7bed37a17a93abcef3d2e4177cd666e38 + + + 64966403e3b865c7936eb63e7815a19a726b854e45b8173a8a13f7d01bb81b1d + + + 55d942bf79d27c1d351c6f54872c734153ccc8952a5dd5256b7cc716c9af875c + + + cb6256b9565a89ed08648547657b0c9b9f28bf37c25c545e431ede10fb5cda35 + + + 30ef9467bc9f9dd30b1f5cd9da5989aaf25f32a7bb1ab4ae3d944d391a2a1f9b + + diff --git a/.idea/libraries/git_learning_project.xml b/.idea/libraries/git_learning_project.xml index 61173ef4df85..de44e154d447 100644 --- a/.idea/libraries/git_learning_project.xml +++ b/.idea/libraries/git_learning_project.xml @@ -1,6 +1,12 @@ - + + + + 648eaffe833416e2accea4bf82b980f0e91ae51ef065f5bc74fa3481c373e9fd + + + diff --git a/.idea/libraries/google_dexlib2.xml b/.idea/libraries/google_dexlib2.xml index 2dc1e360074c..f3f607c222ed 100644 --- a/.idea/libraries/google_dexlib2.xml +++ b/.idea/libraries/google_dexlib2.xml @@ -1,6 +1,12 @@ - + + + + 9a0812a700e617f0d3aeec68aa085ff81fcd18a45597d41f862468dd1b53ae02 + + + diff --git a/.idea/libraries/grpc_core.xml b/.idea/libraries/grpc_core.xml index 45d0b9965fdd..79dee1f0c62e 100644 --- a/.idea/libraries/grpc_core.xml +++ b/.idea/libraries/grpc_core.xml @@ -1,6 +1,26 @@ + + + 0077b9ff9a3b1a6ba3fad2e559c821e8f5176981068a6923647c7486b598aa03 + + + a86967728b17b4edf3c02dbd5011b2e7e323c0b7dd1de899925ca06543467625 + + + 2a6431b5e7bca085b5abd844e30f1270e070c1a179d06b2ea3f83d5f60cc251a + + + ba734e1e84c09d615af6a09d33034b4f0442f8772dec120efb376d86a565ae15 + + + 2f25841c937e24959a57b630e2c4b8525b3d0f536f2e511c9b2bed30b1651d54 + + + 2044542933fcdf40ad18441bec37646d150c491871157f288847e29cb81de4cb + + diff --git a/.idea/libraries/grpc_kotlin_stub.xml b/.idea/libraries/grpc_kotlin_stub.xml index c0f885782c41..b8b57f4cad40 100644 --- a/.idea/libraries/grpc_kotlin_stub.xml +++ b/.idea/libraries/grpc_kotlin_stub.xml @@ -1,6 +1,12 @@ - + + + + 7183d216466b6147cc08f46c6d80ec5764a26cdb2dea2202089ad0912ea74222 + + + diff --git a/.idea/libraries/grpc_netty_shaded.xml b/.idea/libraries/grpc_netty_shaded.xml index 6e9fcdd7f5aa..98b4e25621b5 100644 --- a/.idea/libraries/grpc_netty_shaded.xml +++ b/.idea/libraries/grpc_netty_shaded.xml @@ -1,6 +1,14 @@ + + + 516f3879970d5526af4651d220d2b776f370ecdeb0bd9f6badbe4be88692fea2 + + + 1494e24e7bd5496e7d6f705169dddd46081cefb882ea4fc60b4a58ca50767f34 + + diff --git a/.idea/libraries/grpc_protobuf.xml b/.idea/libraries/grpc_protobuf.xml index 24b5de43b2d5..dbc35efb2411 100644 --- a/.idea/libraries/grpc_protobuf.xml +++ b/.idea/libraries/grpc_protobuf.xml @@ -1,6 +1,17 @@ + + + eb3c2107f6a6397d9c09179e814e2c6ebc5ff901d67bbf76588e8ef5bb51ca05 + + + 0d830380ec66bd7e25eee63aa0a5a08578e46ad187fb72d99b44d9ba22827f91 + + + 0e0b234188894ae282f770f85f717f3a2376b5afb5f80c00d664de22fa6cdaa8 + + diff --git a/.idea/libraries/grpc_stub.xml b/.idea/libraries/grpc_stub.xml index 25ac835248b8..5a4d804d13b1 100644 --- a/.idea/libraries/grpc_stub.xml +++ b/.idea/libraries/grpc_stub.xml @@ -1,6 +1,12 @@ - + + + + f69f8819dd26266e0d8ef62a0f1473894fbdbab9ea459f977037dbc3bc9cf6e4 + + + diff --git a/.idea/libraries/gson.xml b/.idea/libraries/gson.xml index 27afff44c182..ac1474c0a5d4 100644 --- a/.idea/libraries/gson.xml +++ b/.idea/libraries/gson.xml @@ -1,6 +1,12 @@ - + + + + 4241c14a7727c34feea6507ec801318a3d4a90f070e4525681079fb94ee4c593 + + + diff --git a/.idea/libraries/guava_testlib.xml b/.idea/libraries/guava_testlib.xml index d6abac5168cd..41e68002ea70 100644 --- a/.idea/libraries/guava_testlib.xml +++ b/.idea/libraries/guava_testlib.xml @@ -1,6 +1,12 @@ - + + + + aadc71b10d5c3ac474dd16be84cfb18d257e584d1e0a59f8cab64ef4376226ce + + + diff --git a/.idea/libraries/hamcrest.xml b/.idea/libraries/hamcrest.xml index 4f4c42fe2c41..79565d03de2f 100644 --- a/.idea/libraries/hamcrest.xml +++ b/.idea/libraries/hamcrest.xml @@ -1,6 +1,12 @@ - + + + + 711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c + + + diff --git a/.idea/libraries/hash4j.xml b/.idea/libraries/hash4j.xml index 396f413e8c34..c548d40c256a 100644 --- a/.idea/libraries/hash4j.xml +++ b/.idea/libraries/hash4j.xml @@ -1,6 +1,12 @@ - + + + + d6aa5066620ebf8451cc1f80ccbe30f7c7612bc0084049dd5012159fd93d6670 + + + diff --git a/.idea/libraries/http_client.xml b/.idea/libraries/http_client.xml index aadf24c0c5bd..8d48fe3020cf 100644 --- a/.idea/libraries/http_client.xml +++ b/.idea/libraries/http_client.xml @@ -1,6 +1,17 @@ + + + d401243d5c6eae928a37121b6e819158c8c32ea0584793e7285bb489ab2a3d17 + + + c8bc7e1c51a6d4ce72f40d2ebbabf1c4b68bfe76e732104b04381b493478e9d6 + + + 6c9b3dd142a09dc468e23ad39aad6f75a0f2b85125104469f026e52a474e464f + + diff --git a/.idea/libraries/icu4j.xml b/.idea/libraries/icu4j.xml index e63737fe21fb..719acdba6fe0 100644 --- a/.idea/libraries/icu4j.xml +++ b/.idea/libraries/icu4j.xml @@ -1,6 +1,12 @@ - + + + + e51fda26a50667aa6e5e7c752301203867dc36bbf82cb9f8f1008aded3798a5e + + + diff --git a/.idea/libraries/imgscalr.xml b/.idea/libraries/imgscalr.xml index 017b0c1a734e..1d219be29131 100644 --- a/.idea/libraries/imgscalr.xml +++ b/.idea/libraries/imgscalr.xml @@ -1,6 +1,12 @@ - + + + + 6f128a71c5e87a16f810513a73ad3c77d0ee0bb622ee0ce1ead115bccbc76d0a + + + diff --git a/.idea/libraries/ini4j.xml b/.idea/libraries/ini4j.xml index a141a36481ab..fe97a2044bdf 100644 --- a/.idea/libraries/ini4j.xml +++ b/.idea/libraries/ini4j.xml @@ -1,6 +1,12 @@ - + + + + 6d342a8599aed6e2871c638c87e2533647d6a32aec1e0feaa871133ae21517a4 + + + diff --git a/.idea/libraries/intellij_coverage.xml b/.idea/libraries/intellij_coverage.xml index d616c21ef786..9172659d75fd 100644 --- a/.idea/libraries/intellij_coverage.xml +++ b/.idea/libraries/intellij_coverage.xml @@ -1,6 +1,12 @@ - + + + + 1aed2e845e76dc04612ffd45aa68ff21ca1131a1ae6ebe0957ef0d22c449a300 + + + diff --git a/.idea/libraries/intellij_test_discovery.xml b/.idea/libraries/intellij_test_discovery.xml index 541be395c526..d4314030dc1b 100644 --- a/.idea/libraries/intellij_test_discovery.xml +++ b/.idea/libraries/intellij_test_discovery.xml @@ -1,6 +1,12 @@ - + + + + 2e12686a4a5938bd5697141c7bf8abd44da0a33509babf372a4e9b66cab10fd0 + + + diff --git a/.idea/libraries/ion.xml b/.idea/libraries/ion.xml index 73245c69db05..a4d4cb1f25f0 100644 --- a/.idea/libraries/ion.xml +++ b/.idea/libraries/ion.xml @@ -1,6 +1,12 @@ - + + + + d7e6ae22a82bf0c99bb3cfbf5090f112d94acf6bc5353c90414428f4b9b854d9 + + + diff --git a/.idea/libraries/jackson.xml b/.idea/libraries/jackson.xml index 55100d13195b..9ced8236b863 100644 --- a/.idea/libraries/jackson.xml +++ b/.idea/libraries/jackson.xml @@ -1,6 +1,12 @@ - + + + + 5b483f68fa9dd6aa37da37d1f79dd5c4b9464238f4f0660a242cb6b5c724950c + + + diff --git a/.idea/libraries/jackson_databind.xml b/.idea/libraries/jackson_databind.xml index 66e84354edb9..2388792bc625 100644 --- a/.idea/libraries/jackson_databind.xml +++ b/.idea/libraries/jackson_databind.xml @@ -1,6 +1,14 @@ + + + 00c5a5d5ae71ac8e8d5b8da606841e2251c806355939cb5d51c4cdc6b644a0dc + + + 91adcd3dcf5fd9a16499934e7536a23d456692a0093e3d4fd52f138c3936348c + + diff --git a/.idea/libraries/jackson_dataformat_yaml.xml b/.idea/libraries/jackson_dataformat_yaml.xml index 994ca160b5a7..92c314dba0cd 100644 --- a/.idea/libraries/jackson_dataformat_yaml.xml +++ b/.idea/libraries/jackson_dataformat_yaml.xml @@ -1,6 +1,12 @@ - + + + + 691a0a605de15ea610180317331957fe6f7e91f45471ee45cbf9832d74291c31 + + + diff --git a/.idea/libraries/jackson_datatype_joda.xml b/.idea/libraries/jackson_datatype_joda.xml index baccd4acb49f..63d00013dc73 100644 --- a/.idea/libraries/jackson_datatype_joda.xml +++ b/.idea/libraries/jackson_datatype_joda.xml @@ -1,6 +1,14 @@ + + + 294155c0a30238c2d5dd39d6802b33506b349065e2f55985e64d5beeb706e20b + + + d65b4f127d36cf52b9b7b439552db22f3de92b892014512870cb3c98a3cf505e + + diff --git a/.idea/libraries/jackson_jr_objects.xml b/.idea/libraries/jackson_jr_objects.xml index 104e67a702ce..69fd8e486676 100644 --- a/.idea/libraries/jackson_jr_objects.xml +++ b/.idea/libraries/jackson_jr_objects.xml @@ -1,6 +1,12 @@ - + + + + a296cc5cba5aa3dbd8c7ce482c2a1f55ef181671cf27ccdfba2c5c3fb47da74a + + + diff --git a/.idea/libraries/jackson_module_kotlin.xml b/.idea/libraries/jackson_module_kotlin.xml index b4ec6da5f4fa..41981f6be810 100644 --- a/.idea/libraries/jackson_module_kotlin.xml +++ b/.idea/libraries/jackson_module_kotlin.xml @@ -1,6 +1,12 @@ - + + + + a8f728e2b8da5cd679ed940138a684891a165c7fdd95aede85e95aa0a004cb1e + + + diff --git a/.idea/libraries/javaslang.xml b/.idea/libraries/javaslang.xml index 95279b46616b..5f9f0b38d910 100644 --- a/.idea/libraries/javaslang.xml +++ b/.idea/libraries/javaslang.xml @@ -1,7 +1,15 @@ - - + + + + b92286634df04984ce524e659fcfc270632ff2997190c48a0f7d671c3300568e + + + 15a73eba2858834ad08ca2cd1c39b35b02940fd22a7d5a22de998b8b318d400b + + + diff --git a/.idea/libraries/javax_activation.xml b/.idea/libraries/javax_activation.xml index 889ede00bfb5..213c929e3a55 100644 --- a/.idea/libraries/javax_activation.xml +++ b/.idea/libraries/javax_activation.xml @@ -1,6 +1,12 @@ - + + + + 993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce + + + diff --git a/.idea/libraries/javax_annotation_api.xml b/.idea/libraries/javax_annotation_api.xml index a6ce2842bdaf..45365e7c0ee6 100644 --- a/.idea/libraries/javax_annotation_api.xml +++ b/.idea/libraries/javax_annotation_api.xml @@ -1,6 +1,12 @@ - + + + + e04ba5195bcd555dc95650f7cc614d151e4bcd52d29a10b8aa2197f3ab89ab9b + + + diff --git a/.idea/libraries/javax_inject.xml b/.idea/libraries/javax_inject.xml index 18c7290c5f79..bd03ccb94845 100644 --- a/.idea/libraries/javax_inject.xml +++ b/.idea/libraries/javax_inject.xml @@ -1,6 +1,12 @@ - + + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + diff --git a/.idea/libraries/jaxb_api.xml b/.idea/libraries/jaxb_api.xml index e5ca99fc8f75..fb18deacebd7 100644 --- a/.idea/libraries/jaxb_api.xml +++ b/.idea/libraries/jaxb_api.xml @@ -1,6 +1,11 @@ + + + 88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06 + + diff --git a/.idea/libraries/jaxb_runtime.xml b/.idea/libraries/jaxb_runtime.xml index c3397735820c..7419438668ff 100644 --- a/.idea/libraries/jaxb_runtime.xml +++ b/.idea/libraries/jaxb_runtime.xml @@ -1,6 +1,23 @@ + + + 45fecfa5c8217ce1f3652ab95179790ec8cc0dec0384bca51cbeb94a293d9f2f + + + 34975dde1c6920f1a39791142235689bc3cd357e24d05edd8ff93b885bd68d60 + + + 6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf + + + 95b05d9590af4154c6513b9c5dc1fb2e55b539972ba0a9ef28e9a0c01d83ad77 + + + 785861db11ca1bd0d1956682b974ad73eb19cd3e01a4b3fa82d62eca97210aec + + diff --git a/.idea/libraries/jb_jdi.xml b/.idea/libraries/jb_jdi.xml index a75c11519c1b..4597b21dd948 100644 --- a/.idea/libraries/jb_jdi.xml +++ b/.idea/libraries/jb_jdi.xml @@ -1,6 +1,12 @@ - + + + + b924a7f4bae430ca1a07fdb33cd96660033833d99b55bc987080b3babe0a7f13 + + + diff --git a/.idea/libraries/jbr_api.xml b/.idea/libraries/jbr_api.xml index 16b3a4eb7b5e..84472935fc82 100644 --- a/.idea/libraries/jbr_api.xml +++ b/.idea/libraries/jbr_api.xml @@ -1,6 +1,12 @@ - + + + + e10be02f30a530ec6599d9570912b54d0e426b3c1ebd4902441d9d0b31785251 + + + diff --git a/.idea/libraries/jcef.xml b/.idea/libraries/jcef.xml index a9718fac5247..3ec051215d3e 100644 --- a/.idea/libraries/jcef.xml +++ b/.idea/libraries/jcef.xml @@ -1,6 +1,12 @@ - + + + + 505a0f8e8ebdb4a05490eb542832ced74eb498d26e47de8309790be7e52c0aa1 + + + diff --git a/.idea/libraries/jcip.xml b/.idea/libraries/jcip.xml index c94066f05891..32018dc950dc 100644 --- a/.idea/libraries/jcip.xml +++ b/.idea/libraries/jcip.xml @@ -1,6 +1,12 @@ - + + + + be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0 + + + diff --git a/.idea/libraries/jediterm_core.xml b/.idea/libraries/jediterm_core.xml index 8fc7ff608874..6da743aa1530 100644 --- a/.idea/libraries/jediterm_core.xml +++ b/.idea/libraries/jediterm_core.xml @@ -1,6 +1,12 @@ - + + + + 5a9d21f069348e36a8973a9045820866fc9d8f22b9ba52fef4e50b52f3a2773f + + + diff --git a/.idea/libraries/jediterm_ui.xml b/.idea/libraries/jediterm_ui.xml index f07976978821..f072d0a63229 100644 --- a/.idea/libraries/jediterm_ui.xml +++ b/.idea/libraries/jediterm_ui.xml @@ -1,6 +1,12 @@ - + + + + 9eb5504f23ed56e2de77ff033cedc0a6200a56c9dc537b155e03c0bff1432bf3 + + + diff --git a/.idea/libraries/jetCheck.xml b/.idea/libraries/jetCheck.xml index f77b4c6be9ec..08ba4ab1aa47 100644 --- a/.idea/libraries/jetCheck.xml +++ b/.idea/libraries/jetCheck.xml @@ -1,6 +1,12 @@ - + + + + c5f95c97171311066a13eb750a6bb999fa7eeb43c1394705034926336c0b7b0f + + + diff --git a/.idea/libraries/jetbrains_annotations.xml b/.idea/libraries/jetbrains_annotations.xml index 3afcb1c380b7..f197195e41a9 100644 --- a/.idea/libraries/jetbrains_annotations.xml +++ b/.idea/libraries/jetbrains_annotations.xml @@ -1,6 +1,12 @@ - + + + + ff112f54ce874b8ae899cfd68f0315d96c9f406a338b8eca80c76d10e2e5a2f7 + + + diff --git a/.idea/libraries/jetbrains_annotations_java5.xml b/.idea/libraries/jetbrains_annotations_java5.xml index 6d077e7a8c0e..a2c5b02fdc58 100644 --- a/.idea/libraries/jetbrains_annotations_java5.xml +++ b/.idea/libraries/jetbrains_annotations_java5.xml @@ -1,6 +1,12 @@ - + + + + 2d033590350f9e936a787bfa407ecae221a80220762c9cf56c0066ff5e52fd10 + + + diff --git a/.idea/libraries/jetbrains_markdown.xml b/.idea/libraries/jetbrains_markdown.xml index c7b77f872f23..3e7e3deafc8b 100644 --- a/.idea/libraries/jetbrains_markdown.xml +++ b/.idea/libraries/jetbrains_markdown.xml @@ -1,6 +1,11 @@ + + + b2e2430c91c0815d45e52dfd4d1e392d00cde9270cbb3ba865e5ba1b99c9899e + + diff --git a/.idea/libraries/jgoodies_common.xml b/.idea/libraries/jgoodies_common.xml index 9f61581b7d53..4a74a9ebb3ae 100644 --- a/.idea/libraries/jgoodies_common.xml +++ b/.idea/libraries/jgoodies_common.xml @@ -1,6 +1,12 @@ - + + + + efd986ec851c3a5cd57907e72f27d1af9c1e5b1874b07a8b778588646d71d9fc + + + diff --git a/.idea/libraries/jgoodies_forms.xml b/.idea/libraries/jgoodies_forms.xml index 001aeed8c1c5..a0cab31eec1d 100644 --- a/.idea/libraries/jgoodies_forms.xml +++ b/.idea/libraries/jgoodies_forms.xml @@ -1,6 +1,12 @@ - + + + + 26b0fc745ea051b57462be22a150c7600dbac6716b24cc60a5ecc0e8085c41a0 + + + diff --git a/.idea/libraries/jimfs.xml b/.idea/libraries/jimfs.xml index aed21902a59b..1a45a870f2da 100644 --- a/.idea/libraries/jimfs.xml +++ b/.idea/libraries/jimfs.xml @@ -1,6 +1,12 @@ - + + + + c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd + + + diff --git a/.idea/libraries/jmh_core.xml b/.idea/libraries/jmh_core.xml index 402bc1ddd412..f29ebbed56b3 100644 --- a/.idea/libraries/jmh_core.xml +++ b/.idea/libraries/jmh_core.xml @@ -1,6 +1,18 @@ - + + + + f90974e37d0da8886b5c05e6e3e7e20556900d747c5a41c1023b47c3301ea73c + + + df26cc58f235f477db07f753ba5a3ab243ebe5789d9f89ecf68dd62ea9a66c28 + + + 6268a9a0ea3e769fc493a21446664c0ef668e48c93d126791f6f3f757978fee2 + + + diff --git a/.idea/libraries/jmh_generator_annprocess.xml b/.idea/libraries/jmh_generator_annprocess.xml index 84bcac6e8e0a..051912c3c61c 100644 --- a/.idea/libraries/jmh_generator_annprocess.xml +++ b/.idea/libraries/jmh_generator_annprocess.xml @@ -1,6 +1,12 @@ - + + + + c2a88cf8be1eb0870732a7b2e669972efc7f33a145998f568096137f16b20d79 + + + diff --git a/.idea/libraries/jmock.xml b/.idea/libraries/jmock.xml index a1d36e3baa44..2bd20b0ca87e 100644 --- a/.idea/libraries/jmock.xml +++ b/.idea/libraries/jmock.xml @@ -1,6 +1,12 @@ - + + + + d96425f4bab28798162e59fffbe7e16ea6c2aab303ee8dfb0a2ec38a5a4e2f36 + + + diff --git a/.idea/libraries/jmock_junit4.xml b/.idea/libraries/jmock_junit4.xml index 62ea94123f7d..8791d7317dbb 100644 --- a/.idea/libraries/jmock_junit4.xml +++ b/.idea/libraries/jmock_junit4.xml @@ -1,6 +1,12 @@ - + + + + c53b16b999d3b2f1aa273bf5c560273d23e1fa21ce493ba7cbf5243118386b88 + + + diff --git a/.idea/libraries/jmock_legacy.xml b/.idea/libraries/jmock_legacy.xml index b233f9b6a217..4a877c14f44e 100644 --- a/.idea/libraries/jmock_legacy.xml +++ b/.idea/libraries/jmock_legacy.xml @@ -1,6 +1,12 @@ - + + + + 0c8d23755cd08d23c3ea194773a08b2c322d2b70cc8c86ac02b424d8a50c9118 + + + diff --git a/.idea/libraries/jna.xml b/.idea/libraries/jna.xml index 255d59b66e8c..ce9bd0742e05 100644 --- a/.idea/libraries/jna.xml +++ b/.idea/libraries/jna.xml @@ -1,6 +1,15 @@ - + + + + 8ce969116cac95bd61b07a8d5e07174b352e63301473caac72c395e3c08488d2 + + + 91a814ac4f40d60dee91d842e1a8ad874c62197984403d0e3c30d39e55cf53b3 + + + diff --git a/.idea/libraries/joni.xml b/.idea/libraries/joni.xml index 5300a3c182cd..da3b187dd971 100644 --- a/.idea/libraries/joni.xml +++ b/.idea/libraries/joni.xml @@ -1,6 +1,15 @@ - + + + + 41cb16ce177877aae3d98aa2024486973702b66306024c683d89819ee978a529 + + + e2f85def67d6848a7a41c648248645689e3990d17ab8f253ab2fd7e69407df67 + + + diff --git a/.idea/libraries/jps_javac_extension.xml b/.idea/libraries/jps_javac_extension.xml index 05a692eab732..b99753eeb9ad 100644 --- a/.idea/libraries/jps_javac_extension.xml +++ b/.idea/libraries/jps_javac_extension.xml @@ -1,6 +1,12 @@ - + + + + 742fc253d719293c2188adc7ec3dfc3fc6562dea06258ec8b345d23d0d6c24ad + + + diff --git a/.idea/libraries/jsch_agent_proxy.xml b/.idea/libraries/jsch_agent_proxy.xml index 507d7b042f10..1ce58b54df81 100644 --- a/.idea/libraries/jsch_agent_proxy.xml +++ b/.idea/libraries/jsch_agent_proxy.xml @@ -1,6 +1,26 @@ + + + 30fffe206fc598b464b255ae0300b1088fb9b47501e0266831c0167d36639884 + + + 0ccda6cd8ec515bee1fef22d7737b52ac52d1c64c075d4d988136b60125a1eff + + + a5a0f8d3c1c5fb2df2abc4cb68d79b38e71fb37fc2a84d898d2f775150f43a5f + + + eab73aaf832a88c39c7e86559cacc6e7938948ce6f8e8c0e44811ef062ac9e63 + + + 10a27a381f10b5efc33acd4f4200dda9fc9e70d304c8aad52e713064ee6f4655 + + + 737ad86ce82b56152f4f463fc00fb5b4b1dab9dab095e356bcc488c49cfc32a8 + + diff --git a/.idea/libraries/jsch_agent_proxy_sshj.xml b/.idea/libraries/jsch_agent_proxy_sshj.xml index d548a9b63d94..4674938aee3c 100644 --- a/.idea/libraries/jsch_agent_proxy_sshj.xml +++ b/.idea/libraries/jsch_agent_proxy_sshj.xml @@ -1,6 +1,12 @@ - + + + + 9a513fbf41d640df36a105e2e50e0ac6f99a9adf04ed4c72db55dfd93da8ef36 + + + diff --git a/.idea/libraries/json_schema_validator.xml b/.idea/libraries/json_schema_validator.xml index 18e0303d4170..6c74ea922400 100644 --- a/.idea/libraries/json_schema_validator.xml +++ b/.idea/libraries/json_schema_validator.xml @@ -1,6 +1,12 @@ - + + + + 260647c459cc7de269b2a8f576e5693e434df888fd4801e92365fe18b9992cbc + + + diff --git a/.idea/libraries/jsonpath.xml b/.idea/libraries/jsonpath.xml index 027113349cc2..b2f5316fea29 100644 --- a/.idea/libraries/jsonpath.xml +++ b/.idea/libraries/jsonpath.xml @@ -1,6 +1,17 @@ + + + 9601707e95cd79fb98570a01ea8cfb857b5cde948744d6e0edf733c11002c95b + + + 70cab5e9488630dc631b1fc6e7fa550d95cddd19ba14db39ceca7cabfbd4e5ae + + + accdd5c7ac4c49b155890aaea1ffca2a9ccd5826b562dd95a99fc1887003e031 + + diff --git a/.idea/libraries/jsoup.xml b/.idea/libraries/jsoup.xml index 312226fa40db..900fbc261845 100644 --- a/.idea/libraries/jsoup.xml +++ b/.idea/libraries/jsoup.xml @@ -1,6 +1,12 @@ - + + + + 1f115726540ddf71958c14bc517ebfc49cf481e91cd917b0face84f01272e901 + + + diff --git a/.idea/libraries/jsr305.xml b/.idea/libraries/jsr305.xml index 9c5752ca1f00..0745fb4e3f51 100644 --- a/.idea/libraries/jsr305.xml +++ b/.idea/libraries/jsr305.xml @@ -1,6 +1,12 @@ - + + + + 766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7 + + + diff --git a/.idea/libraries/jsvg.xml b/.idea/libraries/jsvg.xml index e5e70e30c29d..a3f775a81f24 100644 --- a/.idea/libraries/jsvg.xml +++ b/.idea/libraries/jsvg.xml @@ -1,6 +1,12 @@ - + + + + 0c10b4ccca2c0a9aa6a82ffa12324d587de7e277a619239566bbdb7413558ce6 + + + diff --git a/.idea/libraries/jvm_native_trusted_roots.xml b/.idea/libraries/jvm_native_trusted_roots.xml index 10ad8046d9c3..09fe6085088d 100644 --- a/.idea/libraries/jvm_native_trusted_roots.xml +++ b/.idea/libraries/jvm_native_trusted_roots.xml @@ -1,6 +1,12 @@ - + + + + ef5c463e0764ea10d06302e2231ba0f95ad4e2beef527759304c8cd87775e986 + + + diff --git a/.idea/libraries/kotlin_gradle_plugin_idea.xml b/.idea/libraries/kotlin_gradle_plugin_idea.xml index 2328a8b16283..d56d05d23154 100644 --- a/.idea/libraries/kotlin_gradle_plugin_idea.xml +++ b/.idea/libraries/kotlin_gradle_plugin_idea.xml @@ -1,6 +1,12 @@ - + + + + 49c2a0c474dea959fb797c06cbdb6f049d0ef592c8f8256e74b2d38b93bab5e0 + + + diff --git a/.idea/libraries/kotlin_gradle_plugin_idea_proto.xml b/.idea/libraries/kotlin_gradle_plugin_idea_proto.xml index 2b74ae5ce6e6..13e0bf5c5ed7 100644 --- a/.idea/libraries/kotlin_gradle_plugin_idea_proto.xml +++ b/.idea/libraries/kotlin_gradle_plugin_idea_proto.xml @@ -1,6 +1,12 @@ - + + + + 911f4da2a752a559acf63d96ea2d1a3bdf5e5a175c4fecc69d79cca2d303c62d + + + diff --git a/.idea/libraries/kotlin_project_model.xml b/.idea/libraries/kotlin_project_model.xml index d5d6d261574b..e99c7f5af0be 100644 --- a/.idea/libraries/kotlin_project_model.xml +++ b/.idea/libraries/kotlin_project_model.xml @@ -1,6 +1,12 @@ - + + + + 38135d3f995fc505d604aed2e82ac5ba858b2a6a3e476899c3b8be47fd222b68 + + + diff --git a/.idea/libraries/kotlin_reflect.xml b/.idea/libraries/kotlin_reflect.xml index 48f7e5cb6d93..1ba8c9282c72 100644 --- a/.idea/libraries/kotlin_reflect.xml +++ b/.idea/libraries/kotlin_reflect.xml @@ -1,6 +1,11 @@ + + + 531e3c3f9b0c45f9a21f1642174453066a1066bec0190254a6331b331814ab8b + + diff --git a/.idea/libraries/kotlin_script_runtime.xml b/.idea/libraries/kotlin_script_runtime.xml index ccf42add50e6..b0896249ba81 100644 --- a/.idea/libraries/kotlin_script_runtime.xml +++ b/.idea/libraries/kotlin_script_runtime.xml @@ -1,6 +1,12 @@ - + + + + 4bddc06cad20bb843fbd24094b1dc3c31f55508c6918885e8b548f2ebaa8a93e + + + diff --git a/.idea/libraries/kotlin_stdlib.xml b/.idea/libraries/kotlin_stdlib.xml index 7b7997c0c984..d66ca45e3930 100644 --- a/.idea/libraries/kotlin_stdlib.xml +++ b/.idea/libraries/kotlin_stdlib.xml @@ -1,6 +1,14 @@ + + + 4395647b1961d9fb730a34e8dbe56c293157bc0759004cca63d9b5ee6653e5c7 + + + fa20188abaa8ecf1d0035e93a969b071f10e45a1c8378c314521eade73f75fd5 + + diff --git a/.idea/libraries/kotlin_test.xml b/.idea/libraries/kotlin_test.xml index cb2a38ce8d5b..91a1f010062a 100644 --- a/.idea/libraries/kotlin_test.xml +++ b/.idea/libraries/kotlin_test.xml @@ -1,6 +1,11 @@ + + + bf0f686171c7587c564478c504a58f9c03bac48c29824688328da9ae8fe5caa1 + + diff --git a/.idea/libraries/kotlin_test_junit.xml b/.idea/libraries/kotlin_test_junit.xml index c0dad8f57de5..b7bc2eba47da 100644 --- a/.idea/libraries/kotlin_test_junit.xml +++ b/.idea/libraries/kotlin_test_junit.xml @@ -1,6 +1,11 @@ + + + ff6b34d504322539d36bea362f7e542e25c5e0770e9f27125b129df430270f0e + + diff --git a/.idea/libraries/kotlin_tooling_core.xml b/.idea/libraries/kotlin_tooling_core.xml index fbdcdc8c8473..3e4644f22af3 100644 --- a/.idea/libraries/kotlin_tooling_core.xml +++ b/.idea/libraries/kotlin_tooling_core.xml @@ -1,6 +1,12 @@ - + + + + 7a412677e73a59588cdad4cb9c7f8e3bb70bae5db66933b4b3f3ece0071b4cad + + + diff --git a/.idea/libraries/kotlinc_allopen_compiler_plugin.xml b/.idea/libraries/kotlinc_allopen_compiler_plugin.xml index 7aa23c481922..40508068338c 100644 --- a/.idea/libraries/kotlinc_allopen_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_allopen_compiler_plugin.xml @@ -1,12 +1,18 @@ - + + + + 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 80f327dc7f19..6e3a92612582 100644 --- a/.idea/libraries/kotlinc_analysis_api_providers.xml +++ b/.idea/libraries/kotlinc_analysis_api_providers.xml @@ -1,12 +1,18 @@ - + + + + fa57d9e567d17165c2c891cdf69e38f3714eb74049977d4a3d4acedf50b05f64 + + + - + - + \ 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 13ed5dd73907..d06414b6a975 100644 --- a/.idea/libraries/kotlinc_analysis_project_structure.xml +++ b/.idea/libraries/kotlinc_analysis_project_structure.xml @@ -1,12 +1,18 @@ - + + + + c495bead969c9e0826a25767cd727c58eae35614a695e9458f37916164c2a9ce + + + - + - + \ 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 204449116884..a18911d3959a 100644 --- a/.idea/libraries/kotlinc_android_extensions_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_android_extensions_compiler_plugin.xml @@ -1,12 +1,18 @@ - + + + + 0182e2c65dd016057b1b065e2b02f83ca127e321e60cadf781722f0f9cb5377a + + + - + - + \ 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 09bb1f00ce59..6170ad2870d8 100644 --- a/.idea/libraries/kotlinc_assignment_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_assignment_compiler_plugin.xml @@ -1,12 +1,18 @@ - + + + + 8eda4da851b83c3ed0c2ffaa3c62195a32dc34af49668299d09dd395a976745b + + + - + - + \ 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 aa74b92eac0f..b32545409edf 100644 --- a/.idea/libraries/kotlinc_high_level_api.xml +++ b/.idea/libraries/kotlinc_high_level_api.xml @@ -1,12 +1,18 @@ - + + + + 00ed6dc51b9bb3aebf16dbddde4e36766fe2cdc58ef565b8cc2502b27664ce02 + + + - + - + \ 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 854c3f382a25..2cbe4c698205 100644 --- a/.idea/libraries/kotlinc_high_level_api_fe10.xml +++ b/.idea/libraries/kotlinc_high_level_api_fe10.xml @@ -1,12 +1,18 @@ - + + + + 02e8949b3ef6702d76836f3f53d6fbf34b37aad9bc6f8ff30cccdec92a550cd3 + + + - + - + \ 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 33cc21ac4fd1..893d443ee5c0 100644 --- a/.idea/libraries/kotlinc_high_level_api_fir.xml +++ b/.idea/libraries/kotlinc_high_level_api_fir.xml @@ -1,12 +1,18 @@ - + + + + 47e24dfd3f02c2e4fa7b425d690f6450de5b810cf2aab983d0ce608049c24593 + + + - + - + \ 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 a74cb6316fb5..13cdc1724336 100644 --- a/.idea/libraries/kotlinc_high_level_api_fir_tests.xml +++ b/.idea/libraries/kotlinc_high_level_api_fir_tests.xml @@ -1,12 +1,18 @@ - + + + + 6caebca5162023eab609fff7602459d7df8c429d4a67a070135ef2060a9a3964 + + + - + - + \ 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 936b2649f0a6..1fa68da9c5b9 100644 --- a/.idea/libraries/kotlinc_high_level_api_impl_base.xml +++ b/.idea/libraries/kotlinc_high_level_api_impl_base.xml @@ -1,12 +1,18 @@ - + + + + 718c75be6ded485a244be9e8f4dde44d96636c404694bdc4914aef2e72c42402 + + + - + - + \ 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 3ee2c1f93a6a..86b58c9ca3fe 100644 --- a/.idea/libraries/kotlinc_high_level_api_impl_base_tests.xml +++ b/.idea/libraries/kotlinc_high_level_api_impl_base_tests.xml @@ -1,12 +1,18 @@ - + + + + 44eda4351becc3eac489d7040d6f3a8b8b9d120a72934e83e2c45272577e877d + + + - + - + \ 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 7f636a1c2f7d..a63c67edc4fd 100644 --- a/.idea/libraries/kotlinc_incremental_compilation_impl_tests.xml +++ b/.idea/libraries/kotlinc_incremental_compilation_impl_tests.xml @@ -1,12 +1,18 @@ - + + + + d32d4db10d151501a9608c0fe577643ee5a0fddb212c11b9922355b9a81655d7 + + + - + - + \ 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 85604bf3a2f2..b8e0020c3877 100644 --- a/.idea/libraries/kotlinc_kotlin_build_common_tests.xml +++ b/.idea/libraries/kotlinc_kotlin_build_common_tests.xml @@ -1,12 +1,18 @@ - + + + + 6c5adc7ab8b9f5b7b9745b95fbfad9471a242241a88652339285f71895e4725d + + + - + - + \ 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 577d368c21ae..a5ccdad31b1a 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_cli.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_cli.xml @@ -1,12 +1,18 @@ - + + + + e90513b939abe557870c9dedc869b82d4b4aeab5aa9d9fd83b9e9b3e4ab981a7 + + + - + - + \ 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 cc3b0dcb5584..4e83ca24caf9 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_common.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_common.xml @@ -1,12 +1,18 @@ - + + + + 7b7ff7610e13b8fcd2555b97f18c4f526792aa7fac3d4928e6e0e406e3d677b9 + + + - + - + \ 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 2d016a9019d4..d7cc72707e38 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_fe10.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_fe10.xml @@ -1,12 +1,18 @@ - + + + + 6a8087e8fac9bc271395381224804214313c4c5c2232bd5760e7628629c5ccaa + + + - + - + \ 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 4c22a671bbb3..090f0071a3c8 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_fir.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_fir.xml @@ -1,12 +1,18 @@ - + + + + cab21e924889eb86f73f4cc6f0bcd2e29b5037000c5ad25d32491d1ff9511ae4 + + + - + - + \ 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 bf2badc4fd62..c4d95e07c768 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_ir.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_ir.xml @@ -1,12 +1,18 @@ - + + + + 619b0cc5412a5ffad6be7b13a21ca4e4151b5bb8b9e0835ef9de84695b8efcab + + + - + - + \ 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 02bbf51dabed..b75dd710ef69 100644 --- a/.idea/libraries/kotlinc_kotlin_compiler_tests.xml +++ b/.idea/libraries/kotlinc_kotlin_compiler_tests.xml @@ -1,12 +1,18 @@ - + + + + 7a464bc2a45f3b17c7c22e89da2dcec8b6f432b1b9fc8c4f2621f0436d001f62 + + + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_dist.xml b/.idea/libraries/kotlinc_kotlin_dist.xml index 6432b0d0713f..3117e5de4ca6 100644 --- a/.idea/libraries/kotlinc_kotlin_dist.xml +++ b/.idea/libraries/kotlinc_kotlin_dist.xml @@ -1,6 +1,12 @@ - + + + + 620b6b9869be28eec26ba231cf4952929ec4bccc4b7ee93bc3f2934af94cf1ad + + + diff --git a/.idea/libraries/kotlinc_kotlin_gradle_statistics.xml b/.idea/libraries/kotlinc_kotlin_gradle_statistics.xml index e317550b04c7..fb320db62fdb 100644 --- a/.idea/libraries/kotlinc_kotlin_gradle_statistics.xml +++ b/.idea/libraries/kotlinc_kotlin_gradle_statistics.xml @@ -1,12 +1,18 @@ - + + + + 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 6a5cfb013dc2..1a47f2ba62a9 100644 --- a/.idea/libraries/kotlinc_kotlin_jps_common.xml +++ b/.idea/libraries/kotlinc_kotlin_jps_common.xml @@ -1,12 +1,18 @@ - + + + + 704a1119fb9d230dd1df129adeb81ddf549e48fbd33ff1c417636a218050b2de + + + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_jps_plugin_classpath.xml b/.idea/libraries/kotlinc_kotlin_jps_plugin_classpath.xml index 452b62a5f532..ac01ca9b2079 100644 --- a/.idea/libraries/kotlinc_kotlin_jps_plugin_classpath.xml +++ b/.idea/libraries/kotlinc_kotlin_jps_plugin_classpath.xml @@ -1,6 +1,12 @@ - + + + + 3f1aa8f4aa89f18be946552fc75b9c62cc00651560bbc1a9e2685c5ddde247a3 + + + diff --git a/.idea/libraries/kotlinc_kotlin_jps_plugin_tests.xml b/.idea/libraries/kotlinc_kotlin_jps_plugin_tests.xml index 30ebd86b51d5..a87300ce75eb 100644 --- a/.idea/libraries/kotlinc_kotlin_jps_plugin_tests.xml +++ b/.idea/libraries/kotlinc_kotlin_jps_plugin_tests.xml @@ -1,6 +1,12 @@ - + + + + e30ddef4e4c3d1d21088cf5722befb8745a3da84ef794fc9f998f069b3897881 + + + diff --git a/.idea/libraries/kotlinc_kotlin_script_runtime.xml b/.idea/libraries/kotlinc_kotlin_script_runtime.xml index a9456b3cbaae..437a285e00be 100644 --- a/.idea/libraries/kotlinc_kotlin_script_runtime.xml +++ b/.idea/libraries/kotlinc_kotlin_script_runtime.xml @@ -1,12 +1,18 @@ - + + + + 46937a2a278340912a93b7929a644225460dc23f2a4724bb076dfe3d1f544659 + + + - + - + \ 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 a43c9d8a0785..0d7bf331e3a8 100644 --- a/.idea/libraries/kotlinc_kotlin_scripting_common.xml +++ b/.idea/libraries/kotlinc_kotlin_scripting_common.xml @@ -1,12 +1,18 @@ - + + + + b3fcec43e0e7a23428d39d97e4dd814cd86a6306aa19e3be0e84c06eb476f694 + + + - + - + \ 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 ebc7ae7f1530..ca70f632db48 100644 --- a/.idea/libraries/kotlinc_kotlin_scripting_compiler_impl.xml +++ b/.idea/libraries/kotlinc_kotlin_scripting_compiler_impl.xml @@ -1,12 +1,18 @@ - + + + + 6fb2161774b30ca2cde9aac3b173e471cbf970a0112708e7228577527140660d + + + - + - + \ 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 632009d36428..69d02164333c 100644 --- a/.idea/libraries/kotlinc_kotlin_scripting_jvm.xml +++ b/.idea/libraries/kotlinc_kotlin_scripting_jvm.xml @@ -1,12 +1,18 @@ - + + + + 2e5b3c10ff5ed92163bd3edd9a205cbf0b39c4476840af7c48bd44f7eeb2f257 + + + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinc_kotlin_stdlib.xml b/.idea/libraries/kotlinc_kotlin_stdlib.xml index cd57486e8d27..acdaa8104ceb 100644 --- a/.idea/libraries/kotlinc_kotlin_stdlib.xml +++ b/.idea/libraries/kotlinc_kotlin_stdlib.xml @@ -1,6 +1,20 @@ - + + + + 4c9f55c8ebdf26d01684fb7ca78b0c8eb18dab85cae4c0b3da5f2688b59f59a8 + + + e1e4217a6785b00767fa99c68ce1a635353323f35daaf3bc774828edde38a871 + + + 374a97b2d7ebdd93fee5d5a32f7f0439f47b82b28cae6897fd2c28abf7393285 + + + 88356eccc9cd822214154fcf0d3f835b9e1b2e7a12d428405937db069c938193 + + @@ -9,17 +23,17 @@ - - - - + + + + - - - - + + + + \ 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 73ecca995b36..cfa193bf6fb5 100644 --- a/.idea/libraries/kotlinc_kotlin_stdlib_minimal_for_test.xml +++ b/.idea/libraries/kotlinc_kotlin_stdlib_minimal_for_test.xml @@ -1,12 +1,18 @@ - + + + + 0aaeafdc18a4718c7e1a68091e366d344cce4937b55875bbd8e6062d8cfce4e7 + + + - + - + \ 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 e70b7e91bb2c..63a098a327e8 100644 --- a/.idea/libraries/kotlinc_kotlinx_serialization_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_kotlinx_serialization_compiler_plugin.xml @@ -1,12 +1,18 @@ - + + + + 276dece8f5d30638a77bb461d58a4156e2152d9a6f067214fa1bfd494a3c89aa + + + - + - + \ 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 5015783151e7..e4275086e282 100644 --- a/.idea/libraries/kotlinc_lombok_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_lombok_compiler_plugin.xml @@ -1,12 +1,18 @@ - + + + + 2a70f03e95819dff996ca48911bda9bcf2a46e9181b0a03382dc9856bac79e3d + + + - + - + \ 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 d4ba528fa926..299dd5249f51 100644 --- a/.idea/libraries/kotlinc_low_level_api_fir.xml +++ b/.idea/libraries/kotlinc_low_level_api_fir.xml @@ -1,12 +1,18 @@ - + + + + 4047368b7e4c3a94c10e580fcd5fd6093189b676bfb963b9624ef07c96daab4c + + + - + - + \ 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 f293be5c3df4..8d898aa42709 100644 --- a/.idea/libraries/kotlinc_noarg_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_noarg_compiler_plugin.xml @@ -1,12 +1,18 @@ - + + + + 67f11ebe46169882a1b5a21a0d98179a3e77376cfea23bad128cf3902cf3642a + + + - + - + \ 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 9aa15c304e29..ace98a664b13 100644 --- a/.idea/libraries/kotlinc_parcelize_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_parcelize_compiler_plugin.xml @@ -1,12 +1,18 @@ - + + + + 8bfecc1b2814c79c4a87b07f364b7a0bbebaeddfd8961bde873ed73040c60a9d + + + - + - + \ 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 346ba70a74ec..2ab904fdf281 100644 --- a/.idea/libraries/kotlinc_sam_with_receiver_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_sam_with_receiver_compiler_plugin.xml @@ -1,12 +1,18 @@ - + + + + 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 2f254fc4e874..c7f9a1e44300 100644 --- a/.idea/libraries/kotlinc_scripting_compiler_plugin.xml +++ b/.idea/libraries/kotlinc_scripting_compiler_plugin.xml @@ -1,12 +1,18 @@ - + + + + 13e97bc228b2409a2f8691a6810c5a5bd20450f5eb757326df619ffafc78c55b + + + - + - + \ 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 6870481c8f55..fcd85ea87674 100644 --- a/.idea/libraries/kotlinc_symbol_light_classes.xml +++ b/.idea/libraries/kotlinc_symbol_light_classes.xml @@ -1,12 +1,18 @@ - + + + + a40186e511867fca3ae48b89b4efd666e631a49a21caa0771af1982e12084963 + + + - + - + \ No newline at end of file diff --git a/.idea/libraries/kotlinx_collections_immutable.xml b/.idea/libraries/kotlinx_collections_immutable.xml index 0f289e403119..303052c47b1a 100644 --- a/.idea/libraries/kotlinx_collections_immutable.xml +++ b/.idea/libraries/kotlinx_collections_immutable.xml @@ -1,6 +1,12 @@ - + + + + 0cc458268187e86241854ae85bfa35accf9bd7a650fbe57015347287bf7e6b66 + + + diff --git a/.idea/libraries/kotlinx_coroutines_core.xml b/.idea/libraries/kotlinx_coroutines_core.xml index bb72d03827dd..e43937f17dcd 100644 --- a/.idea/libraries/kotlinx_coroutines_core.xml +++ b/.idea/libraries/kotlinx_coroutines_core.xml @@ -1,6 +1,12 @@ - + + + + 7496cffdd3eb10109acdda1c3212f6ac7815789e09380dc9e2ccdec496dba3fc + + + diff --git a/.idea/libraries/kotlinx_coroutines_debug.xml b/.idea/libraries/kotlinx_coroutines_debug.xml index e1df1ccad124..d3ec3a10d54f 100644 --- a/.idea/libraries/kotlinx_coroutines_debug.xml +++ b/.idea/libraries/kotlinx_coroutines_debug.xml @@ -1,6 +1,12 @@ - + + + + 5333cbb9a17fd45642f3f05ff124006cd6743549413c2f53a35cf9acd1141e91 + + + diff --git a/.idea/libraries/kotlinx_coroutines_guava.xml b/.idea/libraries/kotlinx_coroutines_guava.xml index 21256f00e717..690da862ce4d 100644 --- a/.idea/libraries/kotlinx_coroutines_guava.xml +++ b/.idea/libraries/kotlinx_coroutines_guava.xml @@ -1,6 +1,12 @@ - + + + + be7ac4726a9d356d03be71c76ceb083e4f4653e2668c0be4af9198e424d7ffd6 + + + diff --git a/.idea/libraries/kotlinx_coroutines_slf4j.xml b/.idea/libraries/kotlinx_coroutines_slf4j.xml index 3b316294ad9f..1fcc7bb0336e 100644 --- a/.idea/libraries/kotlinx_coroutines_slf4j.xml +++ b/.idea/libraries/kotlinx_coroutines_slf4j.xml @@ -1,6 +1,12 @@ - + + + + fbb40ca7e55a78017feac897180be64f562a2eb781c6a3f6c9bb2ff88d92223f + + + diff --git a/.idea/libraries/kotlinx_coroutines_test.xml b/.idea/libraries/kotlinx_coroutines_test.xml index 0de1db788ad2..4a92bbc5d1b3 100644 --- a/.idea/libraries/kotlinx_coroutines_test.xml +++ b/.idea/libraries/kotlinx_coroutines_test.xml @@ -1,6 +1,12 @@ - + + + + bf88e8f0a8d88033d961d93435a132caf88fe35cee266bf71c48689eceddc72d + + + diff --git a/.idea/libraries/kotlinx_datetime_jvm.xml b/.idea/libraries/kotlinx_datetime_jvm.xml index bf0a4c9c2f39..d6452a7a69c0 100644 --- a/.idea/libraries/kotlinx_datetime_jvm.xml +++ b/.idea/libraries/kotlinx_datetime_jvm.xml @@ -1,6 +1,12 @@ - + + + + 075ca75a16e356484c07de3cc7bce79da9e4adbc670bbcf23c5e13f4e12ee6e7 + + + diff --git a/.idea/libraries/kotlinx_html_jvm.xml b/.idea/libraries/kotlinx_html_jvm.xml index 747601e8b55c..01366037731e 100644 --- a/.idea/libraries/kotlinx_html_jvm.xml +++ b/.idea/libraries/kotlinx_html_jvm.xml @@ -1,6 +1,12 @@ - + + + + 98bda1c78a5028a134ceb25b63f5c130c89349730d35fd47ef7490b6bf0b63b3 + + + diff --git a/.idea/libraries/kotlinx_serialization_core.xml b/.idea/libraries/kotlinx_serialization_core.xml index 3e73314cc6b4..c873a5bf4fe7 100644 --- a/.idea/libraries/kotlinx_serialization_core.xml +++ b/.idea/libraries/kotlinx_serialization_core.xml @@ -1,6 +1,12 @@ - + + + + a4053a35abeb59bf707d7948245556fe8dc379e9cfed088aec08134c899605d4 + + + diff --git a/.idea/libraries/kotlinx_serialization_json.xml b/.idea/libraries/kotlinx_serialization_json.xml index 133e0de6ca3c..01e2e4ab9289 100644 --- a/.idea/libraries/kotlinx_serialization_json.xml +++ b/.idea/libraries/kotlinx_serialization_json.xml @@ -1,6 +1,12 @@ - + + + + 6fc10b056e1006963abb2b9fc393dcd4e38425358b6f16285e8f63d3429ffd21 + + + diff --git a/.idea/libraries/kotlinx_serialization_protobuf.xml b/.idea/libraries/kotlinx_serialization_protobuf.xml index b89607d913c7..3e906aa6388c 100644 --- a/.idea/libraries/kotlinx_serialization_protobuf.xml +++ b/.idea/libraries/kotlinx_serialization_protobuf.xml @@ -1,6 +1,12 @@ - + + + + 3b8d778997709effc92f4d9e95204787b873279c6e145913bbd55065912be58c + + + diff --git a/.idea/libraries/ktor_client.xml b/.idea/libraries/ktor_client.xml index e2c945cfc840..5c825cf7d479 100644 --- a/.idea/libraries/ktor_client.xml +++ b/.idea/libraries/ktor_client.xml @@ -1,6 +1,32 @@ + + + 9c8707aac68e30900326933f9044fbedb4797ef18aa127dd2ec9cd74b5100153 + + + a116d91b9de823384e157c9ddae8c7dd34592253cea03a812cb4c430f941914e + + + 11f01ec6bc4a139852bec08e2346046a96ae636bb3d7643a14c109332692a447 + + + e4fc6eafdd18cdc95ee7e090b586b932a35d992660ae70fb18ba64b737427bcf + + + c0fa2f2829e6ca47ce812a6fe35e65b634673aafcff2170b2cd07cf555981492 + + + 37f83ea9cab8a2e56c80d0bd0e461b6f4de0a7e4d97c3d26b38b091fbb0d2a49 + + + dbb254d2f1eea8a9f97d77f1c6783b1aedb01563da0aba886bcfa89f973c3783 + + + 1412d2331f6951dc0b6c99e0a88fdb56ff50943e720191b25cdcdf715dab5c49 + + diff --git a/.idea/libraries/ktor_client_auth.xml b/.idea/libraries/ktor_client_auth.xml index c95ebb664519..ce2bcfb80256 100644 --- a/.idea/libraries/ktor_client_auth.xml +++ b/.idea/libraries/ktor_client_auth.xml @@ -1,6 +1,12 @@ - + + + + a33acc9111d4299d2d89ad7a43f5fbfaad1bc5bdade31e10989241c9f97df854 + + + diff --git a/.idea/libraries/ktor_client_cio.xml b/.idea/libraries/ktor_client_cio.xml index 2ec5e9b141bc..51bc02f6dcbd 100644 --- a/.idea/libraries/ktor_client_cio.xml +++ b/.idea/libraries/ktor_client_cio.xml @@ -1,6 +1,38 @@ + + + 78b8897621c0993c0a2358dd79331e35f2d8cd11ef7d6a65e01b9db8d0d26348 + + + 9c8707aac68e30900326933f9044fbedb4797ef18aa127dd2ec9cd74b5100153 + + + a116d91b9de823384e157c9ddae8c7dd34592253cea03a812cb4c430f941914e + + + c0fa2f2829e6ca47ce812a6fe35e65b634673aafcff2170b2cd07cf555981492 + + + 258b3fc2ffc4682e826f9604ac52e0e1ec85b07f050e3ce4e3cbe8cc35bea03a + + + 17b85d910c882b8c33073f7888275b610739ac04faecb4f43f94bf757572c391 + + + 1412d2331f6951dc0b6c99e0a88fdb56ff50943e720191b25cdcdf715dab5c49 + + + 9720bb29ebd4b035e38082dbb11620bdcc8b57e4988d8f3206fb4bf307fdf9f5 + + + 11f01ec6bc4a139852bec08e2346046a96ae636bb3d7643a14c109332692a447 + + + e4fc6eafdd18cdc95ee7e090b586b932a35d992660ae70fb18ba64b737427bcf + + diff --git a/.idea/libraries/ktor_client_content_negotiation.xml b/.idea/libraries/ktor_client_content_negotiation.xml index 52820c73ff55..d3f0dbe1081b 100644 --- a/.idea/libraries/ktor_client_content_negotiation.xml +++ b/.idea/libraries/ktor_client_content_negotiation.xml @@ -1,6 +1,35 @@ + + + c821b07bbccb3a52ddef83959bd1ff6c0451b71ba9059d549f3e1984613baaf6 + + + 9c8707aac68e30900326933f9044fbedb4797ef18aa127dd2ec9cd74b5100153 + + + a116d91b9de823384e157c9ddae8c7dd34592253cea03a812cb4c430f941914e + + + 11f01ec6bc4a139852bec08e2346046a96ae636bb3d7643a14c109332692a447 + + + e4fc6eafdd18cdc95ee7e090b586b932a35d992660ae70fb18ba64b737427bcf + + + c0fa2f2829e6ca47ce812a6fe35e65b634673aafcff2170b2cd07cf555981492 + + + 37f83ea9cab8a2e56c80d0bd0e461b6f4de0a7e4d97c3d26b38b091fbb0d2a49 + + + dbb254d2f1eea8a9f97d77f1c6783b1aedb01563da0aba886bcfa89f973c3783 + + + 1412d2331f6951dc0b6c99e0a88fdb56ff50943e720191b25cdcdf715dab5c49 + + diff --git a/.idea/libraries/ktor_client_encoding.xml b/.idea/libraries/ktor_client_encoding.xml index 7832312fe80c..15687d9202eb 100644 --- a/.idea/libraries/ktor_client_encoding.xml +++ b/.idea/libraries/ktor_client_encoding.xml @@ -1,6 +1,12 @@ - + + + + d1dce069a7cea7a2aee8c2f3a852aedb6f2b693784819e19b95ae41c2fa6c3cc + + + diff --git a/.idea/libraries/ktor_client_logging.xml b/.idea/libraries/ktor_client_logging.xml index ccba37f25f1e..497f44e74403 100644 --- a/.idea/libraries/ktor_client_logging.xml +++ b/.idea/libraries/ktor_client_logging.xml @@ -1,6 +1,35 @@ + + + 8431bdd42fd24b7f564cd37f44890bc9c2cabf5b20280044dfa4099b9ffd289d + + + 9c8707aac68e30900326933f9044fbedb4797ef18aa127dd2ec9cd74b5100153 + + + a116d91b9de823384e157c9ddae8c7dd34592253cea03a812cb4c430f941914e + + + 11f01ec6bc4a139852bec08e2346046a96ae636bb3d7643a14c109332692a447 + + + e4fc6eafdd18cdc95ee7e090b586b932a35d992660ae70fb18ba64b737427bcf + + + c0fa2f2829e6ca47ce812a6fe35e65b634673aafcff2170b2cd07cf555981492 + + + 37f83ea9cab8a2e56c80d0bd0e461b6f4de0a7e4d97c3d26b38b091fbb0d2a49 + + + dbb254d2f1eea8a9f97d77f1c6783b1aedb01563da0aba886bcfa89f973c3783 + + + 1412d2331f6951dc0b6c99e0a88fdb56ff50943e720191b25cdcdf715dab5c49 + + diff --git a/.idea/libraries/ktor_client_mock.xml b/.idea/libraries/ktor_client_mock.xml index ff7045d9e9cf..831b8808fdf0 100644 --- a/.idea/libraries/ktor_client_mock.xml +++ b/.idea/libraries/ktor_client_mock.xml @@ -1,6 +1,35 @@ + + + a4717dd09bb5b13897c4d3b09406f66eed303d44c84a63d96b82a92c13d047b0 + + + a116d91b9de823384e157c9ddae8c7dd34592253cea03a812cb4c430f941914e + + + 11f01ec6bc4a139852bec08e2346046a96ae636bb3d7643a14c109332692a447 + + + e4fc6eafdd18cdc95ee7e090b586b932a35d992660ae70fb18ba64b737427bcf + + + 9c8707aac68e30900326933f9044fbedb4797ef18aa127dd2ec9cd74b5100153 + + + c0fa2f2829e6ca47ce812a6fe35e65b634673aafcff2170b2cd07cf555981492 + + + 37f83ea9cab8a2e56c80d0bd0e461b6f4de0a7e4d97c3d26b38b091fbb0d2a49 + + + dbb254d2f1eea8a9f97d77f1c6783b1aedb01563da0aba886bcfa89f973c3783 + + + 1412d2331f6951dc0b6c99e0a88fdb56ff50943e720191b25cdcdf715dab5c49 + + diff --git a/.idea/libraries/ktor_network_tls.xml b/.idea/libraries/ktor_network_tls.xml index a9b038725e09..f986bc600371 100644 --- a/.idea/libraries/ktor_network_tls.xml +++ b/.idea/libraries/ktor_network_tls.xml @@ -1,6 +1,20 @@ + + + 9720bb29ebd4b035e38082dbb11620bdcc8b57e4988d8f3206fb4bf307fdf9f5 + + + 17b85d910c882b8c33073f7888275b610739ac04faecb4f43f94bf757572c391 + + + 11f01ec6bc4a139852bec08e2346046a96ae636bb3d7643a14c109332692a447 + + + e4fc6eafdd18cdc95ee7e090b586b932a35d992660ae70fb18ba64b737427bcf + + diff --git a/.idea/libraries/ktor_serialization_kotlinx_json.xml b/.idea/libraries/ktor_serialization_kotlinx_json.xml index caf6c7ad3fa3..cc9bf8db908a 100644 --- a/.idea/libraries/ktor_serialization_kotlinx_json.xml +++ b/.idea/libraries/ktor_serialization_kotlinx_json.xml @@ -1,6 +1,29 @@ + + + 34130cfb69365342f4c2a0a192edaf8cc3f0374206b42d97280f59a6a4a2978c + + + a116d91b9de823384e157c9ddae8c7dd34592253cea03a812cb4c430f941914e + + + 11f01ec6bc4a139852bec08e2346046a96ae636bb3d7643a14c109332692a447 + + + e4fc6eafdd18cdc95ee7e090b586b932a35d992660ae70fb18ba64b737427bcf + + + f0c870a7cbf616287b76991c7786f655fd7690073b112c0c427eea98e9c10a88 + + + dbb254d2f1eea8a9f97d77f1c6783b1aedb01563da0aba886bcfa89f973c3783 + + + 1412d2331f6951dc0b6c99e0a88fdb56ff50943e720191b25cdcdf715dab5c49 + + diff --git a/.idea/libraries/kxml2.xml b/.idea/libraries/kxml2.xml index 91585f821fa5..8f7f99c604e3 100644 --- a/.idea/libraries/kxml2.xml +++ b/.idea/libraries/kxml2.xml @@ -1,6 +1,12 @@ - + + + + f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2 + + + diff --git a/.idea/libraries/layoutinspector_skia_proto.xml b/.idea/libraries/layoutinspector_skia_proto.xml index 1347be701c4e..d5789c408385 100644 --- a/.idea/libraries/layoutinspector_skia_proto.xml +++ b/.idea/libraries/layoutinspector_skia_proto.xml @@ -1,6 +1,12 @@ - + + + + 57a5b14934f746e0910e7a69104ce918af769c6ea821a8c193e51661f45ab2a4 + + + diff --git a/.idea/libraries/layoutinspector_view_proto.xml b/.idea/libraries/layoutinspector_view_proto.xml index b7a6d5dd4a76..bedd20acddd8 100644 --- a/.idea/libraries/layoutinspector_view_proto.xml +++ b/.idea/libraries/layoutinspector_view_proto.xml @@ -1,6 +1,21 @@ - + + + + 646ec119025d94f8f154caaca82433dfdd67f411e1dbac64e791c8221454c9a1 + + + e919843d85b1b7d8252fbefd8ef1bb2a838fe112136ae5d23dc56be17a65216b + + + b5acbacd2efe23a13e523e982a4af48ea0e789da9cac4612192edaac80ce3aa7 + + + 124d5d061c4f4e20b2f45e9315f3e2700a4849b25456c4a446ec4432c0be0251 + + + diff --git a/.idea/libraries/layoutlib.xml b/.idea/libraries/layoutlib.xml index 7cd1eac1ba88..1816c1a77adc 100644 --- a/.idea/libraries/layoutlib.xml +++ b/.idea/libraries/layoutlib.xml @@ -1,6 +1,12 @@ - + + + + c119161aa752e5a03eca2b64ebf23116169750ad86872e014292d4b83d8c100c + + + diff --git a/.idea/libraries/libam_instrumentation_data_proto.xml b/.idea/libraries/libam_instrumentation_data_proto.xml index 3b0eb5f04652..2c2e142fac39 100644 --- a/.idea/libraries/libam_instrumentation_data_proto.xml +++ b/.idea/libraries/libam_instrumentation_data_proto.xml @@ -1,6 +1,12 @@ - + + + + 9e74dde675290902f77b42ebfae08d2f20b1e30e1449098e8f56b8e0d47afc05 + + + diff --git a/.idea/libraries/libapp_processes_proto.xml b/.idea/libraries/libapp_processes_proto.xml index 3fe90a3b0c1f..5d9b4eecadd2 100644 --- a/.idea/libraries/libapp_processes_proto.xml +++ b/.idea/libraries/libapp_processes_proto.xml @@ -1,6 +1,12 @@ - + + + + 3faf2936c9d2f1da49ec915dc086b98981661084bf52e69b42bc8b0e94115f8e + + + diff --git a/.idea/libraries/libthrift.xml b/.idea/libraries/libthrift.xml index 5d4c15400a22..58ea561edce8 100644 --- a/.idea/libraries/libthrift.xml +++ b/.idea/libraries/libthrift.xml @@ -1,6 +1,12 @@ - + + + + f261ec1cfb7452e25c584cb4440389dffce59a6d38dfe91d12ec790594629b6e + + + diff --git a/.idea/libraries/lucene_analysis_common.xml b/.idea/libraries/lucene_analysis_common.xml index f3b5c40fe7e1..dfe0ec866bee 100644 --- a/.idea/libraries/lucene_analysis_common.xml +++ b/.idea/libraries/lucene_analysis_common.xml @@ -1,6 +1,12 @@ - + + + + f2f0d724c99440f4ab9304c06e7966653d088e872a2bbd709605dff547e5a494 + + + diff --git a/.idea/libraries/lucene_codecs.xml b/.idea/libraries/lucene_codecs.xml index 563dca8e45a5..adbd5f0ef420 100644 --- a/.idea/libraries/lucene_codecs.xml +++ b/.idea/libraries/lucene_codecs.xml @@ -1,6 +1,12 @@ - + + + + 371100cb3d39fb47a1f00846fe9114ec643bc41525102aec853b6ecfdf08571e + + + diff --git a/.idea/libraries/lucene_core.xml b/.idea/libraries/lucene_core.xml index 6e056248c5af..a346582b2190 100644 --- a/.idea/libraries/lucene_core.xml +++ b/.idea/libraries/lucene_core.xml @@ -1,6 +1,12 @@ - + + + + 43c3905ecc0c41b77694202b5249e538f3988d1c452bb75decdfb5fdb149dd51 + + + diff --git a/.idea/libraries/lucene_highlighter.xml b/.idea/libraries/lucene_highlighter.xml index c54980b9b97b..d0521e1d7f24 100644 --- a/.idea/libraries/lucene_highlighter.xml +++ b/.idea/libraries/lucene_highlighter.xml @@ -1,6 +1,12 @@ - + + + + dd9ddcb93ba9e5c19d4de5b9b77530a0d4eceb5e2e8f31ac17e905e314a349ce + + + diff --git a/.idea/libraries/lucene_memory.xml b/.idea/libraries/lucene_memory.xml index 3232a612a9a6..83a98e5b2570 100644 --- a/.idea/libraries/lucene_memory.xml +++ b/.idea/libraries/lucene_memory.xml @@ -1,6 +1,12 @@ - + + + + 99fd1e7c06867d2f21e2c86143f774df2009222f76e7379902e87577584e63a7 + + + diff --git a/.idea/libraries/lucene_queries.xml b/.idea/libraries/lucene_queries.xml index 6dd0678eea58..7093dc5445b4 100644 --- a/.idea/libraries/lucene_queries.xml +++ b/.idea/libraries/lucene_queries.xml @@ -1,6 +1,12 @@ - + + + + 7c3d67d2450fabde77e550e11b4ed75a27cf13b3fffe6ec51df4482742107b25 + + + diff --git a/.idea/libraries/lucene_queryparser.xml b/.idea/libraries/lucene_queryparser.xml index 731ea639be9e..026bb3e73cd0 100644 --- a/.idea/libraries/lucene_queryparser.xml +++ b/.idea/libraries/lucene_queryparser.xml @@ -1,6 +1,12 @@ - + + + + 83f4c46f9e5ac7ec3a9aad5fdb05d336c0c4f520528d28a676b65d57508b87f3 + + + diff --git a/.idea/libraries/lucene_sandbox.xml b/.idea/libraries/lucene_sandbox.xml index 9086d9ea4668..ed2adf6183e1 100644 --- a/.idea/libraries/lucene_sandbox.xml +++ b/.idea/libraries/lucene_sandbox.xml @@ -1,6 +1,12 @@ - + + + + aa240762a4639bf21c599e82c1c6ff16097d6aad619785772db159ed60169b43 + + + diff --git a/.idea/libraries/lucene_suggest.xml b/.idea/libraries/lucene_suggest.xml index d60b6461000b..83a9b39023eb 100644 --- a/.idea/libraries/lucene_suggest.xml +++ b/.idea/libraries/lucene_suggest.xml @@ -1,6 +1,12 @@ - + + + + 0ddf5f5b0cf06af1bc5f8ab9c8fc404b6d0006d369eadb15745ad78bb24b38c4 + + + diff --git a/.idea/libraries/lz4_java.xml b/.idea/libraries/lz4_java.xml index 21628e5b704d..57f3fceed91c 100644 --- a/.idea/libraries/lz4_java.xml +++ b/.idea/libraries/lz4_java.xml @@ -1,6 +1,12 @@ - + + + + d74a3334fb35195009b338a951f918203d6bbca3d1d359033dc33edd1cadc9ef + + + diff --git a/.idea/libraries/maven_resolver_provider.xml b/.idea/libraries/maven_resolver_provider.xml index fddd9ffcece6..8a8992182269 100644 --- a/.idea/libraries/maven_resolver_provider.xml +++ b/.idea/libraries/maven_resolver_provider.xml @@ -1,6 +1,44 @@ + + + 4b9f827efb393696431978dc0354651f1a95d4c52ba07c92d830efe5dc9b1012 + + + 7c9eeb30ac1941ea9bdf76c08c162ed98c005913e5bff66de3f1027a304546dc + + + 6bcd688b4700bc0d9046c531c316e75674f53b345d4432d6a7f62812b2424bef + + + b3b5412ce17889103ea564bcdfcf9fb3dfa540344ffeac6b538a73c9d7182662 + + + 91172bc294d6eab02fc9f45f4ea01fd0e418962d128cf489abea7b6957d988ee + + + a205eaa76609ae0039bf38fe9a9c024c646eded05d176effbef524f04a2c2761 + + + c5994010bcdce1d2bd603a4d50c47191ddbd7875d1157b23aaa26d33c82fda13 + + + 24d89a1b23dc0427ac67895a741802fd23897bdf135d87fe586d718b38a3e924 + + + d0b28ed944058ba4f9be4b54c25d6d5269cc4f3f3c49aa450d4dc2f7e0d552f6 + + + 17441a39045ac19bc4a8068fb7284facebf6337754bf2bf8f26a76b5f98ed108 + + + cdcad9355b625743f40e4cead9a96353404e010c39c808d23b044be331afa251 + + + 17aaebe6e3e59df8cb5b4ec210196f7084637312b9bc4ff14cb77ad1ae3c381b + + diff --git a/.idea/libraries/memoryfilesystem.xml b/.idea/libraries/memoryfilesystem.xml index eea2603c7295..192eccd55df6 100644 --- a/.idea/libraries/memoryfilesystem.xml +++ b/.idea/libraries/memoryfilesystem.xml @@ -1,6 +1,12 @@ - + + + + 1e9ed24c5eb43d068a0e5ce5ea19aa75a44ee927024cc7715245e8aca7cd87a5 + + + diff --git a/.idea/libraries/microba.xml b/.idea/libraries/microba.xml index b74619475927..aa697fe78cce 100644 --- a/.idea/libraries/microba.xml +++ b/.idea/libraries/microba.xml @@ -1,6 +1,12 @@ - + + + + dad321d5c6e522ef41f427665b4c5277c8ae72541c7b9df2ba63cb75f2831be1 + + + diff --git a/.idea/libraries/miglayout_swing.xml b/.idea/libraries/miglayout_swing.xml index d818eaa48b24..c446ea0a7ce2 100644 --- a/.idea/libraries/miglayout_swing.xml +++ b/.idea/libraries/miglayout_swing.xml @@ -1,6 +1,15 @@ - + + + + 7aa9da079e0ed628a3672f8ddd1b6b05a5a3ec27639f82370956748943989ba6 + + + 812b9c8a8f326098a43eb9550229dd31100c49f81680eecdf6649da423f0be9f + + + diff --git a/.idea/libraries/mockito.xml b/.idea/libraries/mockito.xml index 349c4ef69e4e..3a7c7aa86644 100644 --- a/.idea/libraries/mockito.xml +++ b/.idea/libraries/mockito.xml @@ -1,6 +1,21 @@ - + + + + 37f4dbaed25ffa6bdedaba78746c449e224b105d56fcedee8755936642d992a8 + + + 7ae2b39ac230be9e3e09ce020406c017ff8ceba06eaf078c62a88c218a0ff2b4 + + + fbd1ab3db43c6c78b8804908cb95b656517f5c82e7fde8d255d8bdceef412d70 + + + 02dfd0b0439a5591e35b708ed2f5474eb0948f53abf74637e959b8e4ef69bfeb + + + diff --git a/.idea/libraries/mockito_kotlin.xml b/.idea/libraries/mockito_kotlin.xml index 75a2ab6e0c91..bb8330dcad01 100644 --- a/.idea/libraries/mockito_kotlin.xml +++ b/.idea/libraries/mockito_kotlin.xml @@ -1,6 +1,11 @@ + + + 2d095d500993bf99400dc8ae5d1936f00cf7220dbeda96261c232a258a539f50 + + diff --git a/.idea/libraries/netty_buffer.xml b/.idea/libraries/netty_buffer.xml index 19e535d2e7da..2917ed802962 100644 --- a/.idea/libraries/netty_buffer.xml +++ b/.idea/libraries/netty_buffer.xml @@ -1,6 +1,15 @@ - + + + + cc88941780b833a5fce6f4f203224b4138b6e2260b93d81889c25066af33890f + + + ae507ef1c97cb6293c05626777d501146369112fd6ce7ec6b8db6d169bf43390 + + + diff --git a/.idea/libraries/netty_codec_http.xml b/.idea/libraries/netty_codec_http.xml index ce816f1433ef..33f895e3bbfc 100644 --- a/.idea/libraries/netty_codec_http.xml +++ b/.idea/libraries/netty_codec_http.xml @@ -1,6 +1,29 @@ + + + 5f29d77c208427a382f3da16f7a98c6fd57e7f4158fa6b172d54abde647ff58f + + + 9cb5f94745be48c56bce3f3e3729188b62470a3f810ab215d59d567695b2fe10 + + + a6b8bacead85b88c0f423a017760eb0b796e0645ec37770f805158af357f6933 + + + df923f67bbafa986448506fa0c4f456397f6a18be86101c8d75128ff6bb43878 + + + 4ef5e6c419736ec2e24c9d2d29679a53eb6299d56b48e2b28def16d66810dd50 + + + 9a58ffe8807d25969cde351f2b8e6ea9f15c06c93ce263a9d75bff2d7866573c + + + e1806a0df6e5cdda968ebe34496b8287e100d29e0e3b6c6b8b9c3d462b16162a + + diff --git a/.idea/libraries/netty_handler_proxy.xml b/.idea/libraries/netty_handler_proxy.xml index 307104bde526..fc7be4762a26 100644 --- a/.idea/libraries/netty_handler_proxy.xml +++ b/.idea/libraries/netty_handler_proxy.xml @@ -1,6 +1,14 @@ + + + 60c736bec98087bc97fcd0097640966c57398d152f9aaa19e1a4618bbf74dbb9 + + + cdd0feff044cbf0f76b6925cb3e5a103f01e3577438538c8c640f069bf8c47e6 + + diff --git a/.idea/libraries/network_inspector_java_proto.xml b/.idea/libraries/network_inspector_java_proto.xml index 55a73eae965d..496d71bb1859 100644 --- a/.idea/libraries/network_inspector_java_proto.xml +++ b/.idea/libraries/network_inspector_java_proto.xml @@ -1,6 +1,12 @@ - + + + + a0211d0d4cef5ee99e407f7be1fe65ee708f4188b7e0a9ad42af178a24752fa9 + + + diff --git a/.idea/libraries/ngram_slp.xml b/.idea/libraries/ngram_slp.xml index 6c5ef66391b4..bdf1011b0845 100644 --- a/.idea/libraries/ngram_slp.xml +++ b/.idea/libraries/ngram_slp.xml @@ -1,6 +1,12 @@ - + + + + 4ac10d8fb7e6326e09179fd83e664610a3362dc1d661fb32e5b2a19bcb9fc867 + + + diff --git a/.idea/libraries/okhttp.xml b/.idea/libraries/okhttp.xml index 9767d4af2a7f..9d5e69bbeb17 100644 --- a/.idea/libraries/okhttp.xml +++ b/.idea/libraries/okhttp.xml @@ -1,6 +1,14 @@ + + + 506a1d3aba9f99b55570c7f8813cd79a44946531f29050d5b938474efdb4cf80 + + + b642baef4c570055de4cb3d1667b2b16dced901ff8066345a063691aa06025a4 + + diff --git a/.idea/libraries/opentelemetry.xml b/.idea/libraries/opentelemetry.xml index 080a3d5c371a..ad778ded5dba 100644 --- a/.idea/libraries/opentelemetry.xml +++ b/.idea/libraries/opentelemetry.xml @@ -1,6 +1,42 @@ - + + + + 039640fdc6fd01fdd44312c1677b96366d465e2ca1424be08da0a7bf48e96a8d + + + 000bd01ca7d67cb6542f0db8677f281d23ad87521b2afe7320484b54e1b7899b + + + 9d9888fcfc405efd32aa28ed9eb156d6afbbe21772fff87b215b60ff37e30454 + + + 04207cb8d82e01a42386ebe967c53d789eb01ee17e9756c17fdc6460ce502efc + + + b57721963af36e72f10d7f882bb247b775f8d182777cfe8b1907b40282ff47eb + + + 70a518c0f54e416964aaaa0a20f26ce038729fc7300c6e9aabba0a360c9f889d + + + 95c0db72d3856553fddc1a313c326ac0b13e284d85660029fc7bc5ba39e5d362 + + + 59ddecd684fd8e009050dc29b5a6d115f49bbcb1270f3076dcf56f378617e91d + + + 52e0e4d7c8bff90846dc16f77c1a6ab09615234e4291f1597e1da869f4b35dda + + + 2561627dac2620e4ac6c3db01d1324d9db3aac1e089ba3186f4563cda2322f1d + + + f3e6a91a45fd872471a6f42441b924c196b83f475b759c14eea702da0911a79c + + + diff --git a/.idea/libraries/opentelemetry_exporter_otlp_common.xml b/.idea/libraries/opentelemetry_exporter_otlp_common.xml index eaf39901018a..23d0b628c582 100644 --- a/.idea/libraries/opentelemetry_exporter_otlp_common.xml +++ b/.idea/libraries/opentelemetry_exporter_otlp_common.xml @@ -1,6 +1,14 @@ + + + bf4cfd6c368ee3837a1431430a67e6a9657df99e74ab3a475cd257f5625f5b00 + + + 330fa4f1ff7a59506ae53b649a8085cca8f9d50f3279857545e871287e17f080 + + diff --git a/.idea/libraries/opentelemetry_extension_kotlin.xml b/.idea/libraries/opentelemetry_extension_kotlin.xml index 3479ce9035e0..9489aa62b135 100644 --- a/.idea/libraries/opentelemetry_extension_kotlin.xml +++ b/.idea/libraries/opentelemetry_extension_kotlin.xml @@ -1,6 +1,12 @@ - + + + + 9ffcb7ee71f360dca89f6be3acbd9fd4cf39a42283cd4ddee242f32288f53d30 + + + diff --git a/.idea/libraries/org_codehaus_groovy_groovy.xml b/.idea/libraries/org_codehaus_groovy_groovy.xml index 11d85d0045d0..53f93f1537c3 100644 --- a/.idea/libraries/org_codehaus_groovy_groovy.xml +++ b/.idea/libraries/org_codehaus_groovy_groovy.xml @@ -1,6 +1,12 @@ - + + + + 044569c20b1438263470585627da1b2c9722f1fb8d89f94e78c0ff219abd0146 + + + diff --git a/.idea/libraries/org_codehaus_groovy_groovy_ant.xml b/.idea/libraries/org_codehaus_groovy_groovy_ant.xml index c25e9093e830..56c6ea1a80de 100644 --- a/.idea/libraries/org_codehaus_groovy_groovy_ant.xml +++ b/.idea/libraries/org_codehaus_groovy_groovy_ant.xml @@ -1,6 +1,12 @@ - + + + + 6b98dcf1309448d48b5a9762e94073fbee17cc45ff2b91b3d74a34b4945517c7 + + + diff --git a/.idea/libraries/org_codehaus_groovy_groovy_json.xml b/.idea/libraries/org_codehaus_groovy_groovy_json.xml index cde1ba06142e..421ac4c0203b 100644 --- a/.idea/libraries/org_codehaus_groovy_groovy_json.xml +++ b/.idea/libraries/org_codehaus_groovy_groovy_json.xml @@ -1,6 +1,12 @@ - + + + + 921972defd8a89a5ab442f5ae57b1760755d7fe339dce46fe140e79a6e63e066 + + + diff --git a/.idea/libraries/org_codehaus_groovy_groovy_jsr223.xml b/.idea/libraries/org_codehaus_groovy_groovy_jsr223.xml index bba33c29178d..09cd7e483f6b 100644 --- a/.idea/libraries/org_codehaus_groovy_groovy_jsr223.xml +++ b/.idea/libraries/org_codehaus_groovy_groovy_jsr223.xml @@ -1,6 +1,12 @@ - + + + + d834f8d0e07fa73f5a59f700903180c1d834acde8ca03dd79641ef1460c82a4e + + + diff --git a/.idea/libraries/org_codehaus_groovy_groovy_templates.xml b/.idea/libraries/org_codehaus_groovy_groovy_templates.xml index 4ff9e855dff0..2c5c8729cbcf 100644 --- a/.idea/libraries/org_codehaus_groovy_groovy_templates.xml +++ b/.idea/libraries/org_codehaus_groovy_groovy_templates.xml @@ -1,6 +1,12 @@ - + + + + abfb7190631a35fc96e023bfcd4658f3f7d4ae76c488ef1b972a54b29809ddc2 + + + diff --git a/.idea/libraries/org_codehaus_groovy_groovy_xml.xml b/.idea/libraries/org_codehaus_groovy_groovy_xml.xml index ef5a01ee41b9..91c7f7d4915d 100644 --- a/.idea/libraries/org_codehaus_groovy_groovy_xml.xml +++ b/.idea/libraries/org_codehaus_groovy_groovy_xml.xml @@ -1,6 +1,12 @@ - + + + + 8faea983f0d871bd2d2f28150747edf9047dd4d716700a0276eaa905a5cd0816 + + + diff --git a/.idea/libraries/package_search_api_models.xml b/.idea/libraries/package_search_api_models.xml index cb6fc9cdd8bd..13a6c9860c92 100644 --- a/.idea/libraries/package_search_api_models.xml +++ b/.idea/libraries/package_search_api_models.xml @@ -1,6 +1,12 @@ - + + + + 5cbd054ec28f66e9ababfc46ed3129cdcdbb0174dfc3d9c50ab8784b1b2dffcb + + + diff --git a/.idea/libraries/package_search_version_utils.xml b/.idea/libraries/package_search_version_utils.xml index 4e411da52ee6..1af1941aeba0 100644 --- a/.idea/libraries/package_search_version_utils.xml +++ b/.idea/libraries/package_search_version_utils.xml @@ -1,6 +1,12 @@ - + + + + 08e4b76769ca0ab8bbc3f33498eb09df352e467e7cd55606ebc627a387d1c3b8 + + + diff --git a/.idea/libraries/perfetto_proto.xml b/.idea/libraries/perfetto_proto.xml index 5334073aee9f..c8951d330593 100644 --- a/.idea/libraries/perfetto_proto.xml +++ b/.idea/libraries/perfetto_proto.xml @@ -1,6 +1,12 @@ - + + + + 831d4b76986f36918dee489b1d8b8b9469d6856f2b3abfe70b5c6d374bf34c72 + + + diff --git a/.idea/libraries/plexus_utils.xml b/.idea/libraries/plexus_utils.xml index d473f087da4b..8462ae13b201 100644 --- a/.idea/libraries/plexus_utils.xml +++ b/.idea/libraries/plexus_utils.xml @@ -1,6 +1,12 @@ - + + + + 86e0255d4c879c61b4833ed7f13124e8bb679df47debb127326e7db7dd49a07b + + + diff --git a/.idea/libraries/protobuf.xml b/.idea/libraries/protobuf.xml index d373d607f3ac..22a3674d8420 100644 --- a/.idea/libraries/protobuf.xml +++ b/.idea/libraries/protobuf.xml @@ -1,6 +1,12 @@ - + + + + 6a9a2dff91dcf71f85be71ae971f6164b5a631dcd34bff08f0618535ca44ad02 + + + diff --git a/.idea/libraries/proxy_vole.xml b/.idea/libraries/proxy_vole.xml index 7cced09d497c..e25546efffc6 100644 --- a/.idea/libraries/proxy_vole.xml +++ b/.idea/libraries/proxy_vole.xml @@ -1,6 +1,14 @@ + + + 4a5cc62f3430f53cc79596fcd3b81561c3899ae5fbeda1fcd3a7af595aaa8b99 + + + e287824b39907a21ee8dfc5a0c738be110fb256374d5dd87dbd8c0ad6d8ac44d + + diff --git a/.idea/libraries/pty4j.xml b/.idea/libraries/pty4j.xml index 03be4db8981e..2243c648e040 100644 --- a/.idea/libraries/pty4j.xml +++ b/.idea/libraries/pty4j.xml @@ -1,6 +1,14 @@ + + + 8cae0b647c734dcd3ed5974bb596518f351d752e335a60084fcebab5da108c0d + + + 31c048a86057e07272429aa26e90713edbde96af9747362f27470d8e86a398a3 + + diff --git a/.idea/libraries/rd_core.xml b/.idea/libraries/rd_core.xml index 1c012b2627a2..43e9a8d5fe42 100644 --- a/.idea/libraries/rd_core.xml +++ b/.idea/libraries/rd_core.xml @@ -1,6 +1,12 @@ - + + + + 6d61b6d7aced9550265364e77977c4d32cc10217024fc5b96de045ace3932067 + + + diff --git a/.idea/libraries/rd_framework.xml b/.idea/libraries/rd_framework.xml index 234ddcf09fe1..1d1d2071065e 100644 --- a/.idea/libraries/rd_framework.xml +++ b/.idea/libraries/rd_framework.xml @@ -1,6 +1,12 @@ - + + + + 1ba96a7a60fabd476c8ff1a04d8777ec67392134a807b571a21d1cd73f9e48c0 + + + diff --git a/.idea/libraries/rd_gen.xml b/.idea/libraries/rd_gen.xml index f7cfc0af315a..8b61202ec3ee 100644 --- a/.idea/libraries/rd_gen.xml +++ b/.idea/libraries/rd_gen.xml @@ -1,6 +1,12 @@ - + + + + 27e596ac9d4502ab354b6a6f8240610daaffb39c50d08d0c621d7c506b9e5862 + + + diff --git a/.idea/libraries/rd_swing.xml b/.idea/libraries/rd_swing.xml index 1b869df0ef7d..364d3efb9525 100644 --- a/.idea/libraries/rd_swing.xml +++ b/.idea/libraries/rd_swing.xml @@ -1,6 +1,12 @@ - + + + + 5175eb67912c5d4676cf1f92183b1efcc2eb1859f24e4ed260ea9ae24d8049d2 + + + diff --git a/.idea/libraries/rd_text.xml b/.idea/libraries/rd_text.xml index c4d27537c9a8..10fc2104c723 100644 --- a/.idea/libraries/rd_text.xml +++ b/.idea/libraries/rd_text.xml @@ -1,6 +1,12 @@ - + + + + 41b0ba599ce429cd7d91c8e8cd5a7539d002a5afc64f3aabc97d743a7f6b62ff + + + diff --git a/.idea/libraries/rhino.xml b/.idea/libraries/rhino.xml index abb8ae2139da..6b1e8a513fc3 100644 --- a/.idea/libraries/rhino.xml +++ b/.idea/libraries/rhino.xml @@ -1,6 +1,12 @@ - + + + + 8708d7502734391957d93773fff77914397b69f4302e6ef5a641164c6e9c971d + + + diff --git a/.idea/libraries/slf4j_jdk14.xml b/.idea/libraries/slf4j_jdk14.xml index 208566b7d9da..65abf0fdf3e5 100644 --- a/.idea/libraries/slf4j_jdk14.xml +++ b/.idea/libraries/slf4j_jdk14.xml @@ -1,6 +1,11 @@ + + + 5bf64690af4e59876b8902bb0db3dd39c686a40abfed97d3837eeeec7a2922ac + + diff --git a/.idea/libraries/snakeyaml.xml b/.idea/libraries/snakeyaml.xml index 20f88de5a3e6..4848127f52b6 100644 --- a/.idea/libraries/snakeyaml.xml +++ b/.idea/libraries/snakeyaml.xml @@ -1,6 +1,12 @@ - + + + + 880c9d896e4b74a06c549c15ca496450165d6909fa15d7e662bee8f6a66d7afa + + + diff --git a/.idea/libraries/snakeyaml_engine.xml b/.idea/libraries/snakeyaml_engine.xml index fae7c664cb7e..0959ac14803e 100644 --- a/.idea/libraries/snakeyaml_engine.xml +++ b/.idea/libraries/snakeyaml_engine.xml @@ -1,6 +1,12 @@ - + + + + 2652199af40c9aa2f1782400d2dfbbf4e5226208c4e05ddd4059c3d6d9cd1505 + + + diff --git a/.idea/libraries/sqlite.xml b/.idea/libraries/sqlite.xml index 2942a90dd67c..a47b474ec5f7 100644 --- a/.idea/libraries/sqlite.xml +++ b/.idea/libraries/sqlite.xml @@ -1,6 +1,12 @@ - + + + + e3a1b909787b33bb37e04f252f37e4ab47a489e1c1d45a809a0982c379445c10 + + + diff --git a/.idea/libraries/sqlite_inspector_proto.xml b/.idea/libraries/sqlite_inspector_proto.xml index bce9da4151fd..299c723c25db 100644 --- a/.idea/libraries/sqlite_inspector_proto.xml +++ b/.idea/libraries/sqlite_inspector_proto.xml @@ -1,6 +1,12 @@ - + + + + 1e52e915de03952a6bc72736125da70e0eb8a89583d31a4157bea609c3ebe8b9 + + + diff --git a/.idea/libraries/sqlite_native.xml b/.idea/libraries/sqlite_native.xml index bb9b972a2450..2fee7dcb71e1 100644 --- a/.idea/libraries/sqlite_native.xml +++ b/.idea/libraries/sqlite_native.xml @@ -1,6 +1,12 @@ - + + + + 491c4ae84a1bad34c85624682a80def4f3a3a0fb9d517121d05c2dfeb94966f8 + + + diff --git a/.idea/libraries/studio_analytics_proto.xml b/.idea/libraries/studio_analytics_proto.xml index 67da8c490e94..9dedc1054ae5 100644 --- a/.idea/libraries/studio_analytics_proto.xml +++ b/.idea/libraries/studio_analytics_proto.xml @@ -1,6 +1,12 @@ - + + + + 9d65977b9f93c7dc44f5618eed39217edc40061756f72657f8b17f97010268ca + + + diff --git a/.idea/libraries/studio_grpc.xml b/.idea/libraries/studio_grpc.xml index 8810efe4fabc..6143f765919a 100644 --- a/.idea/libraries/studio_grpc.xml +++ b/.idea/libraries/studio_grpc.xml @@ -1,6 +1,12 @@ - + + + + dafde19d7d30a439291282fa107faf1c74167179eac56cd10373a2d1b5a28cd3 + + + diff --git a/.idea/libraries/studio_proto.xml b/.idea/libraries/studio_proto.xml index acabeca45802..f6c3e6fa902c 100644 --- a/.idea/libraries/studio_proto.xml +++ b/.idea/libraries/studio_proto.xml @@ -1,6 +1,12 @@ - + + + + 263170a91b4cddea11a586fbddc290c56a9c8ce19c1e6596430de455d671a032 + + + diff --git a/.idea/libraries/swingx.xml b/.idea/libraries/swingx.xml index 223866db78d1..325b19e2a5e2 100644 --- a/.idea/libraries/swingx.xml +++ b/.idea/libraries/swingx.xml @@ -1,6 +1,12 @@ - + + + + 0df80935d9bc3b3841bc621c6fef6615c93aaf80393ccaa196db11bf97784f18 + + + diff --git a/.idea/libraries/tcServiceMessages.xml b/.idea/libraries/tcServiceMessages.xml index 498c8d6bf6ff..52f8cc46d7b2 100644 --- a/.idea/libraries/tcServiceMessages.xml +++ b/.idea/libraries/tcServiceMessages.xml @@ -1,6 +1,12 @@ - + + + + 8bfad3bc663424b7143fde7399e278e6c8202e021863937918314cf6e45a1251 + + + diff --git a/.idea/libraries/test_discovery_plugin_base.xml b/.idea/libraries/test_discovery_plugin_base.xml index 78467904c5b0..79b18447b2d3 100644 --- a/.idea/libraries/test_discovery_plugin_base.xml +++ b/.idea/libraries/test_discovery_plugin_base.xml @@ -1,6 +1,12 @@ - + + + + 5ed74de192bd48546a6bc6e1c9f8f508663d8506ad9ef257aebbd6e829fdea36 + + + diff --git a/.idea/libraries/testcontainers.xml b/.idea/libraries/testcontainers.xml index ce2b9716e0f1..88cae4e4e0b0 100644 --- a/.idea/libraries/testcontainers.xml +++ b/.idea/libraries/testcontainers.xml @@ -1,6 +1,23 @@ + + + b87e3bd3d005683ca5dcac70f431b633e407d8f63e3754a867112c631dcf683e + + + 31cef12ddec979d1f86d7cf708c41a17da523d05c685fd6642e9d0b2addb7240 + + + f810d8c76637991990d17282be226feb7c8d74056147dc79f0d9d2a6e201aecc + + + 3f76f8eb0332607c145d69f27ad8aa6941b5448e745823641d3867ba3746f0f7 + + + 778c35c0557cd3ba4f1c9f64fb942f77ca7e390c5daae4471854150f4ee8d87d + + diff --git a/.idea/libraries/tips_pycharm_community.xml b/.idea/libraries/tips_pycharm_community.xml index 73d27f65abba..c718d3564722 100644 --- a/.idea/libraries/tips_pycharm_community.xml +++ b/.idea/libraries/tips_pycharm_community.xml @@ -1,6 +1,12 @@ - + + + + 9d6ba2bb12f36e6f39ae685956140a542c547387bac26c655246485543902a58 + + + diff --git a/.idea/libraries/transport_proto.xml b/.idea/libraries/transport_proto.xml index c4960533b973..514c0863cbda 100644 --- a/.idea/libraries/transport_proto.xml +++ b/.idea/libraries/transport_proto.xml @@ -1,6 +1,12 @@ - + + + + a27d48e4ae35e6e22742c0871d180aa9eb5cbc52d6aa004a7d3905ac8cb3a49e + + + diff --git a/.idea/libraries/truth.xml b/.idea/libraries/truth.xml index 040b5633ec14..c4e367aab988 100644 --- a/.idea/libraries/truth.xml +++ b/.idea/libraries/truth.xml @@ -1,6 +1,14 @@ + + + dd652bdf0c4427c59848ac0340fd6b6d20c2cbfaa3c569a8366604dbcda5214c + + + 61ba4dc49adca95243beaa0569adc2a23aedb5292ae78aa01186fa782ebdc5c2 + + diff --git a/.idea/libraries/utp_core_proto_jarjar.xml b/.idea/libraries/utp_core_proto_jarjar.xml index 44a54aaf9b1f..2425698c1970 100644 --- a/.idea/libraries/utp_core_proto_jarjar.xml +++ b/.idea/libraries/utp_core_proto_jarjar.xml @@ -1,6 +1,12 @@ - + + + + 17106e8b6a1333c0101f4d25d675fa23705c0298c2b5e64d7ebc2942f78445d2 + + + diff --git a/.idea/libraries/winp.xml b/.idea/libraries/winp.xml index dd160cde27d8..cf3a94e57207 100644 --- a/.idea/libraries/winp.xml +++ b/.idea/libraries/winp.xml @@ -1,6 +1,12 @@ - + + + + 9e2d7a23a1d3921861939509108606ad1cf6b10c64d65ac91958a62043cfa253 + + + diff --git a/.idea/libraries/workspace_model_codegen.xml b/.idea/libraries/workspace_model_codegen.xml index 8e389f76808f..afb96d35ef26 100644 --- a/.idea/libraries/workspace_model_codegen.xml +++ b/.idea/libraries/workspace_model_codegen.xml @@ -1,6 +1,12 @@ - + + + + 46f3dc4e4ecba738122df9868a4d457e750efdb5ff59ee9e1cb4af9f5aa39fc9 + + + diff --git a/.idea/libraries/xml_resolver.xml b/.idea/libraries/xml_resolver.xml index af02984e84a7..66082ae2e9ed 100644 --- a/.idea/libraries/xml_resolver.xml +++ b/.idea/libraries/xml_resolver.xml @@ -1,6 +1,12 @@ - + + + + 47dcde8986019314ef78ae7280a94973a21d2ed95075a40a000b42da956429e1 + + + diff --git a/.idea/libraries/xz.xml b/.idea/libraries/xz.xml index 2cb6f977ccd6..64d392d81701 100644 --- a/.idea/libraries/xz.xml +++ b/.idea/libraries/xz.xml @@ -1,6 +1,12 @@ - + + + + 211b306cfc44f8f96df3a0a3ddaf75ba8c5289eed77d60d72f889bb855f535e5 + + + diff --git a/.idea/libraries/zip_signer.xml b/.idea/libraries/zip_signer.xml index 30ed692da1ae..8d21bfd66a91 100644 --- a/.idea/libraries/zip_signer.xml +++ b/.idea/libraries/zip_signer.xml @@ -1,6 +1,12 @@ - + + + + 826d4d3e21b6584dd9a74f12ef35a2285fe9514fa0093618944666c0a3db194a + + + diff --git a/.idea/libraries/zstd_jni.xml b/.idea/libraries/zstd_jni.xml index c87883a372fc..e3d31dd960e0 100644 --- a/.idea/libraries/zstd_jni.xml +++ b/.idea/libraries/zstd_jni.xml @@ -1,6 +1,12 @@ - + + + + 0f8e64feaa068b8a02de45e9343f9b2fc401235b81e7fe3f80b2aeba001691b2 + + + diff --git a/.idea/libraries/zstd_jni_windows_aarch64.xml b/.idea/libraries/zstd_jni_windows_aarch64.xml index 6d38f15f7699..72e961c7304c 100644 --- a/.idea/libraries/zstd_jni_windows_aarch64.xml +++ b/.idea/libraries/zstd_jni_windows_aarch64.xml @@ -1,6 +1,12 @@ - + + + + 7d30221c057c04a1005990410677ace7920047e3e7111d036c3809c846c7aab5 + + + diff --git a/.idea/libraries/zxing_core.xml b/.idea/libraries/zxing_core.xml index df29de4dc4e9..8da010f132a9 100644 --- a/.idea/libraries/zxing_core.xml +++ b/.idea/libraries/zxing_core.xml @@ -1,6 +1,12 @@ - + + + + 1ba7c0fbb6c267e2fb74e1497d855adae633ccc98edc8c75163aa64bc08e3059 + + + diff --git a/aether-dependency-resolver/intellij.java.aetherDependencyResolver.iml b/aether-dependency-resolver/intellij.java.aetherDependencyResolver.iml index 0a9c739dacfc..e5ef836cff65 100644 --- a/aether-dependency-resolver/intellij.java.aetherDependencyResolver.iml +++ b/aether-dependency-resolver/intellij.java.aetherDependencyResolver.iml @@ -34,6 +34,11 @@ + + + e6842c1a2c9080e60fed7747d2375fedf7e51277a995b7c053426f68537bc9c3 + + @@ -52,6 +57,11 @@ + + + efe8d834e7b55c30e1e17a1a9171ffcf67915eb00c3b0f8a9b8f2bc8aa4752f8 + + @@ -75,6 +85,11 @@ + + + 273d2fe6bfe65986949d6e827794cf3ec43295af6dafe1d4186b6f3dd83c75a3 + + diff --git a/build/dependencies/dependencies.properties b/build/dependencies/dependencies.properties index 9d539e068338..5c8fb42fbeb3 100644 --- a/build/dependencies/dependencies.properties +++ b/build/dependencies/dependencies.properties @@ -1,7 +1,7 @@ # The file is automatically updated. Comments and empty lines will be removed. Entries are sorted by key. bundledMavenVersion=3.9.2 debuggerAgent=1.2 -gradleApiVersion=8.2-rc-2 +gradleApiVersion=8.2 jdkBuild=17.0.7b1014.3 launcherBuild=232.7593 nsisBuild=1 diff --git a/build/launch/src/com/intellij/tools/launch/Launcher.kt b/build/launch/src/com/intellij/tools/launch/Launcher.kt index 4ec0dd0e8c31..6d3b97ee461d 100644 --- a/build/launch/src/com/intellij/tools/launch/Launcher.kt +++ b/build/launch/src/com/intellij/tools/launch/Launcher.kt @@ -7,7 +7,6 @@ import org.jetbrains.intellij.build.dependencies.TeamCityHelper import java.io.File import java.net.InetAddress import java.net.ServerSocket -import java.nio.file.Files import java.util.logging.Logger object Launcher { @@ -33,7 +32,6 @@ object Launcher { val cmd = mutableListOf( paths.javaExecutable.canonicalPath, "-ea", - "-Dapple.laf.useScreenMenuBar=true", "-Dfus.internal.test.mode=true", "-Djb.privacy.policy.text=\"\"", "-Djb.consents.confirmation.enabled=false", diff --git a/community-resources/intellij.idea.community.resources.iml b/community-resources/intellij.idea.community.resources.iml index 911e5f2d74c9..74081b1dd74b 100644 --- a/community-resources/intellij.idea.community.resources.iml +++ b/community-resources/intellij.idea.community.resources.iml @@ -10,7 +10,13 @@ - + + + + 7bb5d2980f547b6c868abcbbfc50b4076b6675e0b1be7a888139242aaecaa83b + + + diff --git a/intellij.yaml b/intellij.yaml index bd2cd2c657fc..344a0e3f39a5 100644 --- a/intellij.yaml +++ b/intellij.yaml @@ -14,3 +14,9 @@ versionControl: sharedIndex: project: - url: https://index-cdn.jetbrains.com/v2/project/intellij-community + +repositoryLibrary: + displaySha256ChecksumUiSettings: true + sha256ChecksumAutoBuild: true + displayJarRepositoryBindingUi: true + jarRepositoryAutoBind: false diff --git a/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactAction.java b/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactAction.java index 2dc5ca18fb49..74a8f332999c 100644 --- a/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactAction.java +++ b/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactAction.java @@ -28,6 +28,7 @@ import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.impl.artifacts.ArtifactUtil; import com.intellij.packaging.impl.compiler.ArtifactsWorkspaceSettings; import com.intellij.task.ProjectTaskManager; +import com.intellij.task.impl.ProjectTaskManagerImpl; import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.EmptyIcon; @@ -117,6 +118,7 @@ public final class BuildArtifactAction extends DumbAwareAction { } private static void doBuild(@NotNull Project project, final @NotNull List items, boolean rebuild) { + ProjectTaskManagerImpl.putBuildOriginator(project, BuildArtifactAction.class); final Artifact[] artifacts = getArtifacts(items, project); if (rebuild) { ProjectTaskManager.getInstance(project).rebuild(artifacts); diff --git a/java/compiler/impl/src/com/intellij/compiler/actions/CompileActionBase.java b/java/compiler/impl/src/com/intellij/compiler/actions/CompileActionBase.java index 3a95bc371d30..496f3f9634bd 100644 --- a/java/compiler/impl/src/com/intellij/compiler/actions/CompileActionBase.java +++ b/java/compiler/impl/src/com/intellij/compiler/actions/CompileActionBase.java @@ -1,4 +1,4 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.compiler.actions; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; @@ -9,6 +9,7 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; +import com.intellij.task.impl.ProjectTaskManagerImpl; import org.jetbrains.annotations.NotNull; public abstract class CompileActionBase extends AnAction implements DumbAware { @@ -29,6 +30,7 @@ public abstract class CompileActionBase extends AnAction implements DumbAware { if (file != null && editor != null && !DumbService.getInstance(project).isDumb()) { DaemonCodeAnalyzer.getInstance(project).autoImportReferenceAtCursor(editor, file); //let autoimport complete } + ProjectTaskManagerImpl.putBuildOriginator(project, this.getClass()); doAction(e.getDataContext(), project); } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProviderBase.kt b/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProviderBase.kt index 218f0434abbd..141178e81071 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProviderBase.kt +++ b/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProviderBase.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.packaging.impl.run import com.intellij.execution.BeforeRunTaskProvider @@ -86,6 +86,7 @@ abstract class BuildArtifactsBeforeRunTaskProviderBase - + + + + b724610d5798f5dad9c86d7fd3771ce155a0601b6153741e75c4d86fab100d84 + + + diff --git a/java/debugger/impl/intellij.java.debugger.impl.iml b/java/debugger/impl/intellij.java.debugger.impl.iml index 7089c2f2ecc1..758ac3fadaa2 100644 --- a/java/debugger/impl/intellij.java.debugger.impl.iml +++ b/java/debugger/impl/intellij.java.debugger.impl.iml @@ -25,7 +25,13 @@ - + + + + eaee1397eb553601c29954945e6dafbd7b9a17983704da4088db4da65a156b21 + + + diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java index ca16396ba238..266705ce6705 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java @@ -24,6 +24,7 @@ import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.task.*; +import com.intellij.task.impl.ProjectTaskManagerImpl; import com.intellij.ui.UIBundle; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FileCollectionFactory; @@ -276,12 +277,14 @@ public final class HotSwapUIImpl extends HotSwapUI { @Nullable HotSwapStatusListener callback) { dontAskHotswapAfterThisCompilation(); if (compileBeforeHotswap) { - ProjectTaskManager projectTaskManager = ProjectTaskManager.getInstance(session.getProject()); + Project project = session.getProject(); + ProjectTaskManagerImpl.putBuildOriginator(project, this.getClass()); + ProjectTaskManager projectTaskManager = ProjectTaskManager.getInstance(project); if (callback == null) { projectTaskManager.buildAllModules(); } else { - ProjectTask buildProjectTask = projectTaskManager.createAllModulesBuildTask(true, session.getProject()); + ProjectTask buildProjectTask = projectTaskManager.createAllModulesBuildTask(true, project); ProjectTaskContext context = new ProjectTaskContext(callback).withUserData(HOT_SWAP_CALLBACK_KEY, callback); projectTaskManager.run(context, buildProjectTask); } @@ -299,7 +302,9 @@ public final class HotSwapUIImpl extends HotSwapUI { @Override public void compileAndReload(@NotNull DebuggerSession session, VirtualFile @NotNull ... files) { dontAskHotswapAfterThisCompilation(); - ProjectTaskManager.getInstance(session.getProject()).compile(files); + Project project = session.getProject(); + ProjectTaskManagerImpl.putBuildOriginator(project, this.getClass()); + ProjectTaskManager.getInstance(project).compile(files); // The control flow continues at MyCompilationStatusListener.finished. } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java index 74dcb6a46d5c..a7422f1ac620 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java @@ -252,7 +252,7 @@ public abstract class Breakpoint

implements protected void createOrWaitPrepare(final DebugProcessImpl debugProcess, @NotNull final SourcePosition classPosition) { debugProcess.getRequestsManager().callbackOnPrepareClasses(this, classPosition); - if (debugProcess.getVirtualMachineProxy().canBeModified()) { + if (debugProcess.getVirtualMachineProxy().canBeModified() && !isObsolete()) { processClassesPrepare(debugProcess, debugProcess.getPositionManager().getAllClasses(classPosition).stream().distinct()); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java index a1275a981dc3..12976f805c1d 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java @@ -119,7 +119,7 @@ public abstract class BreakpointWithHighlighter

- + + + + 8915bdd1d6afc9df4eb1003069f40b7d24794b869c7dd1c849e45c1eb98269d8 + + + diff --git a/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java b/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java index 788a32c6d6f3..ac7a3b3f40d7 100644 --- a/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java +++ b/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java @@ -27,6 +27,7 @@ import com.intellij.task.ProjectTask; import com.intellij.task.ProjectTaskContext; import com.intellij.task.ProjectTaskManager; import com.intellij.task.impl.EmptyCompileScopeBuildTaskImpl; +import com.intellij.task.impl.ProjectTaskManagerImpl; import com.intellij.util.concurrency.Semaphore; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -172,6 +173,7 @@ public class CompileStepBeforeRun extends BeforeRunTaskProvider { if ((!taskResult.hasErrors() || ignoreErrors) && !taskResult.isAborted()) { result.set(Boolean.TRUE); diff --git a/java/idea-ui/src/com/intellij/ide/starters/shared/StarterSettings.kt b/java/idea-ui/src/com/intellij/ide/starters/shared/StarterSettings.kt index 59404ab46966..77ae60477884 100644 --- a/java/idea-ui/src/com/intellij/ide/starters/shared/StarterSettings.kt +++ b/java/idea-ui/src/com/intellij/ide/starters/shared/StarterSettings.kt @@ -138,4 +138,6 @@ class DependencyUnavailable( val hint: String? = null ) : DependencyState() -object DependencyAvailable : DependencyState() \ No newline at end of file +object DependencyAvailable : DependencyState() + +object DefaultDependencyAvailable : DependencyState() \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AdaptExpressionTypeFixUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AdaptExpressionTypeFixUtil.java index 5e8fc108743c..e0f7de0dc1eb 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AdaptExpressionTypeFixUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AdaptExpressionTypeFixUtil.java @@ -233,7 +233,7 @@ final class AdaptExpressionTypeFixUtil { info.registerFix(action3, null, null, null, null); IntentionAction action2 = QUICK_FIX_FACTORY.createWrapWithOptionalFix(expectedType, expression); info.registerFix(action2, null, null, null, null); - IntentionAction action1 = new WrapExpressionFix(expectedType, expression, role); + var action1 = new WrapExpressionFix(expectedType, expression, role); info.registerFix(action1, null, null, null, null); PsiType castToType = suggestCastTo(expectedType, actualType); if (castToType != null) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index e5a1b891c6a8..9b74f96c9fb0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -2676,13 +2676,13 @@ public final class HighlightUtil { } HighlightInfo.Builder builder = createMemberReferencedError(resolvedName, expression.getTextRange()); - if (expression instanceof PsiReferenceExpression && PsiUtil.isInnerClass(parentClass)) { - String referenceName = ((PsiReferenceExpression)expression).getReferenceName(); + if (expression instanceof PsiReferenceExpression ref && PsiUtil.isInnerClass(parentClass)) { + String referenceName = ref.getReferenceName(); PsiClass containingClass = parentClass.getContainingClass(); LOG.assertTrue(containingClass != null); PsiField fieldInContainingClass = containingClass.findFieldByName(referenceName, true); - if (fieldInContainingClass != null && ((PsiReferenceExpression)expression).getQualifierExpression() == null) { - builder.registerFix(new QualifyWithThisFix(containingClass, expression), null, null, null, null); + if (fieldInContainingClass != null && ref.getQualifierExpression() == null) { + builder.registerFix(new QualifyWithThisFix(containingClass, ref), null, null, null, null); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java index 676b851b8119..b52734fd4a72 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java @@ -119,7 +119,7 @@ final class ModuleHighlightUtil { .descriptionAndTooltip(message); rootModuleInfos.stream().map(f -> PsiManager.getInstance(project).findFile(f)).filter(f -> f != file).findFirst().ifPresent( duplicate -> { - IntentionAction action = new GoToSymbolFix(duplicate, JavaErrorBundle + var action = new GoToSymbolFix(duplicate, JavaErrorBundle .message("module.open.duplicate.text")); info.registerFix(action, null, null, null, null); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ExtendsListFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ExtendsListFix.java index db73aae5b8e9..ed63a242c33b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ExtendsListFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ExtendsListFix.java @@ -5,7 +5,6 @@ import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.intention.impl.BaseIntentionAction; import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; import com.intellij.codeInspection.util.IntentionName; -import com.intellij.openapi.command.undo.UndoUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -97,7 +96,6 @@ public class ExtendsListFix extends LocalQuickFixAndIntentionActionOnPsiElement @NotNull PsiElement endElement) { final PsiClass myClass = (PsiClass)startElement; invokeImpl(myClass); - UndoUtil.markPsiFileForUndo(file); } protected void invokeImpl(PsiClass myClass) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GoToSymbolFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GoToSymbolFix.java index 4c8bc2e26371..4cbe4266bf75 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GoToSymbolFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GoToSymbolFix.java @@ -1,62 +1,36 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; -import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo; import com.intellij.codeInspection.util.IntentionName; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; +import com.intellij.modcommand.ModCommand; +import com.intellij.modcommand.ModNavigate; +import com.intellij.modcommand.PsiBasedModCommandAction; import com.intellij.psi.NavigatablePsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.SmartPointerManager; -import com.intellij.psi.SmartPsiElementPointer; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; -public class GoToSymbolFix implements IntentionAction { - private final SmartPsiElementPointer myPointer; +public class GoToSymbolFix extends PsiBasedModCommandAction { private final @IntentionName String myMessage; public GoToSymbolFix(@NotNull NavigatablePsiElement symbol, @NotNull @Nls String message) { - myPointer = SmartPointerManager.getInstance(symbol.getProject()).createSmartPsiElementPointer(symbol); + super(symbol); myMessage = message; } @NotNull @Override - public String getText() { + public String getFamilyName() { return myMessage; } - @NotNull @Override - public String getFamilyName() { - return getText(); + protected @NotNull ModCommand perform(@NotNull ActionContext context, @NotNull NavigatablePsiElement element) { + return new ModNavigate(element.getContainingFile().getVirtualFile(), 0, 0, 0); } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return myPointer.getElement() != null; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - NavigatablePsiElement e = myPointer.getElement(); - if (e != null && e.isValid()) { - e.navigate(true); - } - } - - @Override - public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { - NavigatablePsiElement element = myPointer.getElement(); - if (element == null) return IntentionPreviewInfo.EMPTY; + protected @NotNull IntentionPreviewInfo generatePreview(ActionContext context, NavigatablePsiElement element) { return IntentionPreviewInfo.navigate(element); } - - @Override - public boolean startInWriteAction() { - return false; - } } \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveParenthesisFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveParenthesisFix.java index 1112aff865e5..ccccbe43b168 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveParenthesisFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveParenthesisFix.java @@ -1,74 +1,51 @@ -// Copyright 2000-2021 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. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.daemon.impl.HighlightInfo; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.HighPriorityAction; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInsight.intention.impl.BaseIntentionAction; +import com.intellij.codeInsight.intention.PriorityAction; +import com.intellij.codeInspection.PsiUpdateModCommandAction; import com.intellij.codeInspection.util.IntentionFamilyName; -import com.intellij.codeInspection.util.IntentionName; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ArrayUtil; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.ObjectUtils; import com.siyeh.ig.psiutils.CommentTracker; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import org.jetbrains.annotations.NotNull; -import java.util.List; import java.util.Objects; -public final class MoveParenthesisFix implements IntentionAction, HighPriorityAction { - private final PsiCallExpression myCall; +public final class MoveParenthesisFix extends PsiUpdateModCommandAction { private final int myPos; private final int myShiftSize; public MoveParenthesisFix(PsiCallExpression call, int pos, int shiftSize) { - myCall = call; + super(call); myPos = pos; myShiftSize = shiftSize; } @Override - public @IntentionName @NotNull String getText() { + public @NotNull @IntentionFamilyName String getFamilyName() { return QuickFixBundle.message("intention.move.parenthesis.name"); } @Override - public @NotNull @IntentionFamilyName String getFamilyName() { - return getText(); + protected @NotNull Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiCallExpression element) { + return Presentation.of(getFamilyName()).withPriority(PriorityAction.Priority.HIGH); } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return !project.isDisposed() && myCall.isValid() && BaseIntentionAction.canModify(myCall); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - PsiCallExpression copy = copyWithShift(myCall, myPos, myShiftSize); + protected void invoke(@NotNull ActionContext context, @NotNull PsiCallExpression call, @NotNull ModPsiUpdater updater) { + PsiCallExpression copy = copyWithShift(call, myPos, myShiftSize); if (copy != null) { - new CommentTracker().replaceAndRestoreComments(myCall, copy); + new CommentTracker().replaceAndRestoreComments(call, copy); } } - - @Override - public boolean startInWriteAction() { - return true; - } - - @Override - public @NotNull FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new MoveParenthesisFix(PsiTreeUtil.findSameElementInCopy(myCall, target), myPos, myShiftSize); - } private static PsiCallExpression copyWithShift(PsiCallExpression parentCall, int pos, int shift) { PsiCallExpression parentCopy = (PsiCallExpression)parentCall.copy(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PermuteArgumentsFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PermuteArgumentsFix.java index 5f29ce9e693f..665d5cd9261d 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PermuteArgumentsFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PermuteArgumentsFix.java @@ -3,18 +3,14 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.daemon.impl.HighlightInfo; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.HighPriorityAction; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInsight.intention.impl.BaseIntentionAction; +import com.intellij.codeInsight.intention.PriorityAction; +import com.intellij.codeInspection.PsiUpdateModCommandAction; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.infos.MethodCandidateInfo; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ArrayUtil; @@ -25,47 +21,29 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -public final class PermuteArgumentsFix implements IntentionAction, HighPriorityAction { +public final class PermuteArgumentsFix extends PsiUpdateModCommandAction { private static final Logger LOG = Logger.getInstance(PermuteArgumentsFix.class); - private final PsiCall myCall; private final PsiCall myPermutation; private PermuteArgumentsFix(@NotNull PsiCall call, @NotNull PsiCall permutation) { - myCall = call; + super(call); myPermutation = permutation; } - @Override - public boolean startInWriteAction() { - return true; - } - - - @Override - @NotNull - public String getText() { - return QuickFixBundle.message("permute.arguments"); - } - - @Override - public @NotNull FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new PermuteArgumentsFix(PsiTreeUtil.findSameElementInCopy(myCall, target), myPermutation); - } - @Override @NotNull public String getFamilyName() { - return getText(); + return QuickFixBundle.message("permute.arguments"); } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return !project.isDisposed() && myCall.isValid() && BaseIntentionAction.canModify(myCall); + protected @NotNull Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiCall element) { + return Presentation.of(getFamilyName()).withPriority(PriorityAction.Priority.HIGH); } @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - Objects.requireNonNull(myCall.getArgumentList()).replace(Objects.requireNonNull(myPermutation.getArgumentList())); + protected void invoke(@NotNull ActionContext context, @NotNull PsiCall call, @NotNull ModPsiUpdater updater) { + Objects.requireNonNull(call.getArgumentList()).replace(Objects.requireNonNull(myPermutation.getArgumentList())); } public static boolean registerFix(@NotNull HighlightInfo.Builder info, PsiCall callExpression, final CandidateInfo[] candidates, final TextRange fixRange) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifySuperArgumentFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifySuperArgumentFix.java index 6e9813780467..fece1a7b4170 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifySuperArgumentFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifySuperArgumentFix.java @@ -1,43 +1,19 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.impl.HighlightInfo; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.RefactoringChangeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; public class QualifySuperArgumentFix extends QualifyThisOrSuperArgumentFix { private QualifySuperArgumentFix(@NotNull PsiExpression expression, @NotNull PsiClass psiClass) { super(expression, psiClass); } - @Override - public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new QualifySuperArgumentFix(PsiTreeUtil.findSameElementInCopy(myExpression, target), myPsiClass); - } - @Override protected String getQualifierText() { return PsiKeyword.SUPER; @@ -70,7 +46,7 @@ public class QualifySuperArgumentFix extends QualifyThisOrSuperArgumentFix { return; } if (method != null && !method.hasModifierProperty(PsiModifier.ABSTRACT)) { - IntentionAction action = new QualifySuperArgumentFix(expr, superClass); + var action = new QualifySuperArgumentFix(expr, superClass); highlightInfo.registerFix(action, null, null, null, null); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java index d0a7da932d5c..eb3215ade724 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java @@ -1,24 +1,8 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.impl.HighlightInfo; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; @@ -27,7 +11,6 @@ import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.refactoring.util.RefactoringChangeUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.HashSet; import java.util.Set; @@ -37,11 +20,6 @@ public class QualifyThisArgumentFix extends QualifyThisOrSuperArgumentFix{ super(expression, psiClass); } - @Override - public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new QualifyThisArgumentFix(PsiTreeUtil.findSameElementInCopy(myExpression, target), myPsiClass); - } - @Override protected String getQualifierText() { return PsiKeyword.THIS; @@ -92,7 +70,7 @@ public class QualifyThisArgumentFix extends QualifyThisOrSuperArgumentFix{ if (!TypeConversionUtil.isAssignable(parameterType, exprType)) { final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(parameterType); if (psiClass != null && containingClasses.contains(psiClass)) { - IntentionAction action = new QualifyThisArgumentFix(expression, psiClass); + var action = new QualifyThisArgumentFix(expression, psiClass); builder.registerFix(action, null, null, fixRange, null); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisOrSuperArgumentFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisOrSuperArgumentFix.java index 15ea96ade343..df4489ea0902 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisOrSuperArgumentFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisOrSuperArgumentFix.java @@ -1,74 +1,34 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInspection.util.IntentionName; +import com.intellij.codeInspection.PsiUpdateModCommandAction; import com.intellij.java.analysis.JavaAnalysisBundle; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -abstract class QualifyThisOrSuperArgumentFix implements IntentionAction { +abstract class QualifyThisOrSuperArgumentFix extends PsiUpdateModCommandAction { protected static final Logger LOG = Logger.getInstance(QualifyThisOrSuperArgumentFix.class); - protected final PsiExpression myExpression; protected final PsiClass myPsiClass; - private @IntentionName String myText; - QualifyThisOrSuperArgumentFix(@NotNull PsiExpression expression, @NotNull PsiClass psiClass) { - myExpression = expression; + super(expression); myPsiClass = psiClass; } - /** - * Must override in subclasses, as we store myExpression in the field, so default strategy won't work - */ - @Override - abstract public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target); - - @Override - public boolean startInWriteAction() { - return true; - } - - @NotNull - @Override - public String getText() { - return myText; - } - protected abstract String getQualifierText(); protected abstract PsiExpression getQualifier(PsiManager manager); - + @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - if (!myExpression.isValid()) return false; - if (!myPsiClass.isValid()) return false; - myText = JavaAnalysisBundle.message("intention.name.qualify.expression", getQualifierText(), myPsiClass.getQualifiedName()); - return true; + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiExpression element) { + if (!myPsiClass.isValid()) return null; + return Presentation.of( + JavaAnalysisBundle.message("intention.name.qualify.expression", getQualifierText(), myPsiClass.getQualifiedName())); } @NotNull @@ -78,7 +38,7 @@ abstract class QualifyThisOrSuperArgumentFix implements IntentionAction { } @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - myExpression.replace(getQualifier(PsiManager.getInstance(project))); + protected void invoke(@NotNull ActionContext context, @NotNull PsiExpression expression, @NotNull ModPsiUpdater updater) { + expression.replace(getQualifier(PsiManager.getInstance(context.project()))); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyWithThisFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyWithThisFix.java index 60dfba1ed4f2..0ecf0f7a3b8f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyWithThisFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyWithThisFix.java @@ -1,72 +1,40 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.PsiUpdateModCommandAction; import com.intellij.java.analysis.JavaAnalysisBundle; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.modcommand.ModPsiUpdater; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiReferenceExpression; +import com.intellij.psi.PsiThisExpression; import com.intellij.refactoring.util.RefactoringChangeUtil; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class QualifyWithThisFix implements IntentionAction { +public class QualifyWithThisFix extends PsiUpdateModCommandAction { private final PsiClass myContainingClass; - private final PsiElement myExpression; - public QualifyWithThisFix(@NotNull PsiClass containingClass, @NotNull PsiElement expression) { + public QualifyWithThisFix(@NotNull PsiClass containingClass, @NotNull PsiReferenceExpression expression) { + super(expression); myContainingClass = containingClass; - myExpression = expression; } @Override - public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new QualifyWithThisFix(myContainingClass, PsiTreeUtil.findSameElementInCopy(myExpression, target)); - } - - @NotNull - @Override - public String getText() { - return JavaAnalysisBundle.message("qualify.with.0.this", myContainingClass.getName()); + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiReferenceExpression element) { + return myContainingClass.isValid() ? Presentation.of(getFamilyName()) : null; } @NotNull @Override public String getFamilyName() { - return getText(); + return JavaAnalysisBundle.message("qualify.with.0.this", myContainingClass.getName()); } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return true; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + protected void invoke(@NotNull ActionContext context, @NotNull PsiReferenceExpression element, @NotNull ModPsiUpdater updater) { final PsiThisExpression thisExpression = - RefactoringChangeUtil.createThisExpression(PsiManager.getInstance(project), myContainingClass); - ((PsiReferenceExpression)myExpression).setQualifierExpression(thisExpression); - } - - @Override - public boolean startInWriteAction() { - return true; + RefactoringChangeUtil.createThisExpression(PsiManager.getInstance(context.project()), myContainingClass); + element.setQualifierExpression(thisExpression); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapExpressionFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapExpressionFix.java index b306100aa6ac..31fa87ab7711 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapExpressionFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapExpressionFix.java @@ -1,20 +1,15 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.daemon.impl.HighlightInfo; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInsight.intention.impl.BaseIntentionAction; +import com.intellij.codeInspection.PsiUpdateModCommandAction; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,33 +18,20 @@ import java.util.LinkedHashSet; import java.util.Objects; import java.util.Set; -public class WrapExpressionFix implements IntentionAction { +public class WrapExpressionFix extends PsiUpdateModCommandAction { private static final Logger LOG = Logger.getInstance(WrapExpressionFix.class); - private final PsiExpression myExpression; private final @Nullable String myRole; private final PsiClassType myExpectedType; private final boolean myPrimitiveExpected; private final String myMethodPresentation; public WrapExpressionFix(@NotNull PsiType expectedType, @NotNull PsiExpression expression, @Nullable String role) { - myExpression = expression; + super(expression); myRole = role; myExpectedType = getClassType(expectedType, expression); myPrimitiveExpected = expectedType instanceof PsiPrimitiveType; - myMethodPresentation = getMethodPresentation(myExpression, myExpectedType, myPrimitiveExpected); - } - - private WrapExpressionFix(PsiExpression expression, - PsiClassType expectedType, - boolean primitiveExpected, - String methodPresentation, - @Nullable String role) { - myExpression = expression; - myExpectedType = expectedType; - myPrimitiveExpected = primitiveExpected; - myMethodPresentation = methodPresentation; - myRole = role; + myMethodPresentation = getMethodPresentation(expression, myExpectedType, myPrimitiveExpected); } @Nullable @@ -63,13 +45,6 @@ public class WrapExpressionFix implements IntentionAction { return null; } - @Override - @NotNull - public String getText() { - return myRole == null ? QuickFixBundle.message("wrap.expression.using.static.accessor.text", myMethodPresentation) : - QuickFixBundle.message("wrap.expression.using.static.accessor.text.role", myMethodPresentation, myRole); - } - private static String getMethodPresentation(PsiExpression expression, PsiClassType expectedType, boolean primitiveExpected) { PsiType type = expression.getType(); if (expectedType != null && type != null) { @@ -127,43 +102,40 @@ public class WrapExpressionFix implements IntentionAction { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return myMethodPresentation != null - && myExpression.isValid() - && BaseIntentionAction.canModify(myExpression) + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiExpression myExpression) { + boolean available = myMethodPresentation != null && PsiImplUtil.getSwitchLabel(myExpression) == null && myExpectedType != null && myExpectedType.isValid() && myExpression.getType() != null && findWrapper(myExpression.getType(), myExpectedType, myPrimitiveExpected, myExpression) != null; + if (!available) return null; + String message = myRole == null ? QuickFixBundle.message("wrap.expression.using.static.accessor.text", myMethodPresentation) : + QuickFixBundle.message("wrap.expression.using.static.accessor.text.role", myMethodPresentation, myRole); + return Presentation.of(message); } + @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - PsiType type = myExpression.getType(); + protected void invoke(@NotNull ActionContext context, @NotNull PsiExpression expression, @NotNull ModPsiUpdater updater) { + PsiType type = expression.getType(); if (type == null) { LOG.error("Expression type is null"); return; } - PsiMethod wrapper = findWrapper(type, myExpectedType, myPrimitiveExpected, myExpression); + PsiMethod wrapper = findWrapper(type, myExpectedType, myPrimitiveExpected, expression); if (wrapper == null) { LOG.error("Wrapper not found; expectedType = " + myExpectedType.getCanonicalText() + "; primitiveExpected = " + myPrimitiveExpected); return; } - PsiElementFactory factory = JavaPsiFacade.getElementFactory(file.getProject()); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.project()); @NonNls String methodCallText = "Foo." + wrapper.getName() + "()"; - PsiMethodCallExpression call = (PsiMethodCallExpression)factory.createExpressionFromText(methodCallText, - null); - call.getArgumentList().add(myExpression); + PsiMethodCallExpression call = (PsiMethodCallExpression)factory.createExpressionFromText(methodCallText, null); + call.getArgumentList().add(expression); PsiReferenceExpression qualifier = (PsiReferenceExpression)Objects.requireNonNull(call.getMethodExpression().getQualifierExpression()); PsiClass wrapperClass = Objects.requireNonNull(wrapper.getContainingClass()); qualifier.bindToElement(wrapperClass); - myExpression.replace(call); - } - - @Override - public boolean startInWriteAction() { - return true; + expression.replace(call); } public static void registerWrapAction(JavaResolveResult[] candidates, @@ -208,17 +180,8 @@ public class WrapExpressionFix implements IntentionAction { } if (expectedType != null) { - IntentionAction action = new WrapExpressionFix(expectedType, expr, null); + var action = new WrapExpressionFix(expectedType, expr, null); highlightInfo.registerFix(action, null, null, fixRange, null); } } - - @Override - public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new WrapExpressionFix(PsiTreeUtil.findSameElementInCopy(myExpression, target), - myExpectedType, - myPrimitiveExpected, - myMethodPresentation, - myRole); - } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspectionBase.java index d29aa645ed75..8a7d88bf3b3a 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspectionBase.java @@ -100,7 +100,7 @@ public abstract class DeprecationInspectionBase extends LocalInspectionTool { if (deprecatedElement instanceof PsiMethod method && methodCall != null) { PsiMethod replacement = findReplacementInJavaDoc(method, methodCall); if (replacement != null) { - return new ReplaceMethodCallFix((PsiMethodCallExpression)elementToHighlight.getParent().getParent(), replacement); + return new ReplaceMethodCallFix((PsiMethodCallExpression)elementToHighlight.getParent().getParent(), replacement).asQuickFix(); } } if (deprecatedElement instanceof PsiField field) { @@ -108,7 +108,7 @@ public abstract class DeprecationInspectionBase extends LocalInspectionTool { if (referenceExpression != null) { PsiMember replacement = findReplacementInJavaDoc(field, referenceExpression); if (replacement != null) { - return new ReplaceFieldReferenceFix(referenceExpression, replacement); + return new ReplaceFieldReferenceFix(referenceExpression, replacement).asQuickFix(); } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/deprecationInspectionQuickFixes.kt b/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/deprecationInspectionQuickFixes.kt index 8eb252a33020..f154fec64707 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/deprecationInspectionQuickFixes.kt +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/deprecation/deprecationInspectionQuickFixes.kt @@ -1,23 +1,10 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInspection.deprecation -import com.intellij.codeInsight.intention.FileModifier.SafeFieldForPreview -import com.intellij.codeInspection.LocalQuickFixOnPsiElement -import com.intellij.openapi.project.Project +import com.intellij.codeInspection.PsiUpdateModCommandAction +import com.intellij.modcommand.ModCommandAction +import com.intellij.modcommand.ModCommandAction.Presentation +import com.intellij.modcommand.ModPsiUpdater import com.intellij.psi.* import com.intellij.psi.codeStyle.JavaCodeStyleManager import com.intellij.psi.util.PsiFormatUtil @@ -40,15 +27,15 @@ private fun generateQualifierText(expr: PsiReferenceExpression, } } -internal class ReplaceMethodCallFix(expr: PsiMethodCallExpression, replacementMethod: PsiMethod) : LocalQuickFixOnPsiElement(expr) { - @SafeFieldForPreview +internal class ReplaceMethodCallFix(expr: PsiMethodCallExpression, replacementMethod: PsiMethod) : + PsiUpdateModCommandAction(expr) { private val myReplacementMethodPointer = SmartPointerManager.getInstance(replacementMethod.project).createSmartPsiElementPointer(replacementMethod) private val myReplacementText = PsiFormatUtil.formatMethod(replacementMethod, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_CONTAINING_CLASS or PsiFormatUtilBase.SHOW_NAME, 0) - override fun getText(): String { - return InspectionGadgetsBundle.message("replace.method.call.fix.text", myReplacementText) + override fun getPresentation(context: ModCommandAction.ActionContext, element: PsiMethodCallExpression): Presentation { + return Presentation.of(InspectionGadgetsBundle.message("replace.method.call.fix.text", myReplacementText)) } @Nls @@ -56,12 +43,12 @@ internal class ReplaceMethodCallFix(expr: PsiMethodCallExpression, replacementMe return InspectionGadgetsBundle.message("replace.method.call.fix.family.name") } - override fun invoke(project: Project, file: PsiFile, startElement: PsiElement, endElement: PsiElement) { - val expr = (startElement as? PsiMethodCallExpression) ?: return + override fun invoke(context: ModCommandAction.ActionContext, expr: PsiMethodCallExpression, updater: ModPsiUpdater) { val replacementMethod = myReplacementMethodPointer.element ?: return val qualifierText = generateQualifierText(expr.methodExpression, replacementMethod) + val project = context.project val elementFactory = JavaPsiFacade.getElementFactory(project) val newMethodCall = elementFactory.createExpressionFromText(qualifierText + replacementMethod.name + expr.argumentList.text, expr) val replaced = expr.replace(newMethodCall) as PsiMethodCallExpression @@ -69,8 +56,8 @@ internal class ReplaceMethodCallFix(expr: PsiMethodCallExpression, replacementMe } } -internal class ReplaceFieldReferenceFix(expr: PsiReferenceExpression, replacementMember: PsiMember) : LocalQuickFixOnPsiElement(expr) { - @SafeFieldForPreview +internal class ReplaceFieldReferenceFix(expr: PsiReferenceExpression, replacementMember: PsiMember) : + PsiUpdateModCommandAction(expr) { private val myReplacementMemberPointer = SmartPointerManager.getInstance(replacementMember.project).createSmartPsiElementPointer(replacementMember) private val myReplacementText = @@ -87,16 +74,16 @@ internal class ReplaceFieldReferenceFix(expr: PsiReferenceExpression, replacemen return InspectionGadgetsBundle.message("replace.field.reference.fix.family.name") } - override fun getText(): String { - return InspectionGadgetsBundle.message("replace.field.reference.fix.text", myReplacementText) + override fun getPresentation(context: ModCommandAction.ActionContext, element: PsiReferenceExpression): Presentation { + return Presentation.of(InspectionGadgetsBundle.message("replace.field.reference.fix.text", myReplacementText)) } - override fun invoke(project: Project, file: PsiFile, startElement: PsiElement, endElement: PsiElement) { - val expr = (startElement as? PsiReferenceExpression) ?: return + override fun invoke(context: ModCommandAction.ActionContext, expr: PsiReferenceExpression, updater: ModPsiUpdater) { val replacementMember = myReplacementMemberPointer.element ?: return val qualifierText = generateQualifierText(expr, replacementMember) + val project = context.project val replaced = expr.replace(JavaPsiFacade.getElementFactory(project).createExpressionFromText( qualifierText + replacementMember.name + (if (replacementMember is PsiMethod) "()" else ""), expr)) JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java index b51d01d2945c..adcb011c7819 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java @@ -459,8 +459,9 @@ public final class RefJavaManagerImpl extends RefJavaManager { PsiModifierListOwner javaModifiersListOwner = ObjectUtils.tryCast(node.getJavaPsi(), PsiModifierListOwner.class); if (javaModifiersListOwner != null) { - PsiAnnotation externalAnnotation = myExternalAnnotationsManager.findExternalAnnotation(javaModifiersListOwner, - BatchSuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME); + PsiAnnotation externalAnnotation = + myExternalAnnotationsManager.findExternalAnnotation(javaModifiersListOwner, + BatchSuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME); UAnnotation uAnnotation = UastContextKt.toUElement(externalAnnotation, UAnnotation.class); if (uAnnotation != null) { retrieveSuppressions(uAnnotation, node); @@ -471,6 +472,7 @@ public final class RefJavaManagerImpl extends RefJavaManager { @Override public boolean visitExpression(@NotNull UExpression node) { + // for lambda expressions and method references RefElement refElement = myRefManager.getReference(node.getSourcePsi()); if (refElement != null) { myRefManager.buildReferences(refElement); @@ -544,7 +546,7 @@ public final class RefJavaManagerImpl extends RefJavaManager { } } - if (buf.length() > 0) { + if (!buf.isEmpty()) { String suppressId = buf.substring(1); element.addSuppression(suppressId); diff --git a/java/java-analysis-impl/src/messages/QuickFixBundle.properties b/java/java-analysis-impl/src/messages/QuickFixBundle.properties index 181c48217adc..9de1625e9175 100644 --- a/java/java-analysis-impl/src/messages/QuickFixBundle.properties +++ b/java/java-analysis-impl/src/messages/QuickFixBundle.properties @@ -179,7 +179,7 @@ change.inheritors.visibility.warning.text=Do you want to change inheritors' visi change.inheritors.visibility.warning.title=Change Inheritors move.class.in.extend.list.family=Move Class in Extend list move.bound.class.to.front.fix.text=Move bound ''{0}'' to the beginning of the bounds list of type parameter ''{1}'' -move.catch.up.family=Move Catch Up +move.catch.up.family=Move 'catch' up move.catch.up.text=Move catch for ''{0}'' before ''{1}'' move.class.to.separate.file.family=Move class to separate file move.class.to.separate.file.text=Move class ''{0}'' to ''{0}.java'' @@ -187,7 +187,7 @@ move.class.to.package.family=Move Class to Package move.class.to.package.text=Move to package ''{0}'' # change if (!a == b) ... => if (!(a == b)) ... -negation.broader.scope.family=Negation Broader Scope +negation.broader.scope.family=Negation broader scope negation.broader.scope.text=Change to ''!({0})'' optimize.imports.fix=Optimize imports diff --git a/java/java-impl-refactorings/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl-refactorings/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index 5a3b7a787a70..5b9f610313aa 100644 --- a/java/java-impl-refactorings/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl-refactorings/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -870,7 +870,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } } - abstract static class Processor { + abstract static class Processor { protected final @NotNull PsiElementFactory myFactory; protected final @NotNull Parent myParent; protected final @NotNull JavaChangeInfo myChangeInfo; @@ -946,14 +946,14 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } } - final static class RecordHeaderProcessor extends Processor { + final static class RecordHeaderProcessor extends Processor { RecordHeaderProcessor(@NotNull JavaChangeInfo changeInfo, @NotNull PsiElementFactory factory, @NotNull PsiRecordHeader header) { super(changeInfo, factory, header); } @Override - void processNew(JavaParameterInfo info, List result) { + void processNew(JavaParameterInfo info, List result) { PsiType newType = info.createType(myParent); if (newType != null) { String componentText = newType.getCanonicalText() + " " + info.getName(); @@ -961,23 +961,23 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr if (dummyComponents.length != 1) { throw new IncorrectOperationException(componentText + " is not a valid component"); } - result.add(new Variable(dummyComponents[0])); + result.add(new VariableWrapper(dummyComponents[0])); } } @Override - Variable getChild(int index) { - return new Variable(myParent.getRecordComponents()[index]); + VariableWrapper getChild(int index) { + return new VariableWrapper(myParent.getRecordComponents()[index]); } @Override - protected void process(@NotNull List newElements) { - final List newComponents = ContainerUtil.map(newElements, element -> (PsiRecordComponent)element.getElement()); + protected void process(@NotNull List newElements) { + final List newComponents = ContainerUtil.map(newElements, element -> (PsiRecordComponent)element.variable()); ChangeSignatureUtil.synchronizeList(myParent, newComponents, RecordHeader.INSTANCE, myChangeInfo.toRemoveParm()); } } - final static class MethodParamsProcessor extends Processor { + final static class MethodParamsProcessor extends Processor { private final @Nullable PsiElement myMethodBody; private final @NotNull PsiSubstitutor mySubstitutor; private final @Nullable PsiMethod myBaseMethod; @@ -995,20 +995,20 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } @Override - void processNew(JavaParameterInfo info, List result) { + void processNew(JavaParameterInfo info, List result) { PsiElement parent = myParent.getParent(); if (parent instanceof PsiLambdaExpression && !((PsiLambdaExpression)parent).hasFormalParameterTypes()) { PsiExpression dummyLambdaParam = myFactory.createExpressionFromText(info.getName() + "-> {}", myParent); - result.add(new Variable(((PsiLambdaExpression)dummyLambdaParam).getParameterList().getParameters()[0])); + result.add(new VariableWrapper(((PsiLambdaExpression)dummyLambdaParam).getParameterList().getParameters()[0])); } else { - result.add(new Variable(createNewParameter(myChangeInfo, info, mySubstitutor))); + result.add(new VariableWrapper(createNewParameter(myChangeInfo, info, mySubstitutor))); } } @Override - Variable getChild(int index) { - return new Variable(Objects.requireNonNull(myParent.getParameter(index))); + VariableWrapper getChild(int index) { + return new VariableWrapper(Objects.requireNonNull(myParent.getParameter(index))); } @Override @@ -1027,15 +1027,15 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } @Override - protected void process(@NotNull List newElements) { - final List newParameters = ContainerUtil.map(newElements, element -> (PsiParameter)element.getElement()); - final List newParameterNames = ContainerUtil.map(newElements, Variable::getName); + protected void process(@NotNull List newElements) { + final List newParameters = ContainerUtil.map(newElements, element -> (PsiParameter)element.variable()); + final List newParameterNames = ContainerUtil.map(newElements, VariableWrapper::getName); final boolean[] toRemove = myChangeInfo.toRemoveParm(); resolveVariableVsFieldsConflicts(newParameters, newParameterNames, myParent, toRemove, myMethodBody, ParameterList.INSTANCE); } } - final static class DeconstructionProcessor extends Processor { + final static class DeconstructionProcessor extends Processor { DeconstructionProcessor(@NotNull JavaChangeInfo changeInfo, @NotNull PsiElementFactory factory, @NotNull PsiDeconstructionList list) { @@ -1043,7 +1043,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } @Override - void processNew(JavaParameterInfo info, List result) { + void processNew(JavaParameterInfo info, List result) { PsiType newType = info.createType(myParent); if (newType != null) { String patternText = newType.getCanonicalText() + " " + info.getName(); @@ -1052,19 +1052,19 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr throw new IncorrectOperationException(patternText + " is not a valid pattern"); } PsiPattern pattern = instanceOfExpression.getPattern(); - result.add(new Pattern(Objects.requireNonNull(pattern))); + result.add(new PatternWrapper(Objects.requireNonNull(pattern))); } } @Override - Pattern getChild(int index) { - return new Pattern(myParent.getDeconstructionComponents()[index]); + PatternWrapper getChild(int index) { + return new PatternWrapper(myParent.getDeconstructionComponents()[index]); } @Override - protected void process(@NotNull List elements) { - final List newPatterns = ContainerUtil.map(elements, element -> (PsiPattern)element.getElement()); - final List newElementNames = ContainerUtil.map(elements, Pattern::getName); + protected void process(@NotNull List elements) { + final List newPatterns = ContainerUtil.map(elements, element -> element.pattern()); + final List newElementNames = ContainerUtil.map(elements, PatternWrapper::getName); resolveVariableVsFieldsConflicts(newPatterns, newElementNames, myParent, @@ -1577,75 +1577,54 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } } - interface ChildI { + sealed interface ChildWrapper permits VariableWrapper, PatternWrapper { @Nullable String getName(); @Nullable PsiElement getNameIdentifier(); @Nullable PsiTypeElement getTypeElement(); - @NotNull PsiElement getElement(); default void normalizeDeclaration() {} } - final static class Variable implements ChildI { - private final @NotNull PsiVariable myElement; - - Variable(@NotNull PsiVariable element) { - myElement = element; - } + record VariableWrapper(@NotNull PsiVariable variable) implements ChildWrapper { @Override public String getName() { - return myElement.getName(); + return variable.getName(); } @Override public @Nullable PsiElement getNameIdentifier() { - return myElement.getNameIdentifier(); + return variable.getNameIdentifier(); } @Override public PsiTypeElement getTypeElement() { - return myElement.getTypeElement(); - } - - @Override - public @NotNull PsiElement getElement() { - return myElement; + return variable.getTypeElement(); } @Override public void normalizeDeclaration() { - myElement.normalizeDeclaration(); + variable.normalizeDeclaration(); } } - final static class Pattern implements ChildI { - private final @NotNull PsiPattern myElement; - - Pattern(@NotNull PsiPattern element) { - myElement = element; - } + record PatternWrapper(@NotNull PsiPattern pattern) implements ChildWrapper { @Override @Nullable public String getName() { - final PsiPatternVariable variable = JavaPsiPatternUtil.getPatternVariable(myElement); + final PsiPatternVariable variable = JavaPsiPatternUtil.getPatternVariable(pattern); return variable != null ? variable.getName() : null; } @Override public @Nullable PsiElement getNameIdentifier() { - final PsiPatternVariable variable = JavaPsiPatternUtil.getPatternVariable(myElement); + final PsiPatternVariable variable = JavaPsiPatternUtil.getPatternVariable(pattern); return variable != null ? variable.getNameIdentifier() : null; } @Override public @Nullable PsiTypeElement getTypeElement() { - return JavaPsiPatternUtil.getPatternTypeElement(myElement); - } - - @Override - public @NotNull PsiElement getElement() { - return myElement; + return JavaPsiPatternUtil.getPatternTypeElement(pattern); } } } diff --git a/java/java-impl/intellij.java.impl.iml b/java/java-impl/intellij.java.impl.iml index 75294c26790d..d49e82ab303e 100644 --- a/java/java-impl/intellij.java.impl.iml +++ b/java/java-impl/intellij.java.impl.iml @@ -53,7 +53,13 @@ - + + + + e3dcfee71eb13467139a1385152bd28554c79c677738cb617a91a772ea6e9f87 + + + diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteCatchFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteCatchFix.java index 04a7067a822a..09eabc2167d3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteCatchFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteCatchFix.java @@ -1,35 +1,17 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.QuickFixBundle; -import com.intellij.codeInsight.daemon.impl.actions.IntentionActionWithFixAllOption; import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.impl.BaseIntentionAction; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; +import com.intellij.codeInspection.PsiUpdateModCommandAction; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.siyeh.ig.psiutils.ControlFlowUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class DeleteCatchFix implements IntentionActionWithFixAllOption { - private final PsiParameter myCatchParameter; +public class DeleteCatchFix extends PsiUpdateModCommandAction { private final String myTypeText; public DeleteCatchFix(@NotNull PsiParameter catchParameter) { @@ -37,16 +19,10 @@ public class DeleteCatchFix implements IntentionActionWithFixAllOption { } private DeleteCatchFix(@NotNull PsiParameter catchParameter, @NotNull String typeText) { - myCatchParameter = catchParameter; + super(catchParameter); myTypeText = typeText; } - @Override - @NotNull - public String getText() { - return QuickFixBundle.message("delete.catch.text", myTypeText); - } - @Override @NotNull public String getFamilyName() { @@ -54,27 +30,16 @@ public class DeleteCatchFix implements IntentionActionWithFixAllOption { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return myCatchParameter.isValid() && BaseIntentionAction.canModify(myCatchParameter); + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiParameter element) { + return Presentation.of(QuickFixBundle.message("delete.catch.text", myTypeText)); } @Override - public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new DeleteCatchFix(PsiTreeUtil.findSameElementInCopy(myCatchParameter, target)); - } - - @NotNull - @Override - public PsiElement getElementToMakeWritable(@NotNull PsiFile file) { - return myCatchParameter.getContainingFile(); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) { - PsiElement previousElement = deleteCatch(myCatchParameter); + protected void invoke(@NotNull ActionContext context, @NotNull PsiParameter catchParameter, @NotNull ModPsiUpdater updater) { + PsiElement previousElement = deleteCatch(catchParameter); if (previousElement != null) { //move caret to previous catch section - editor.getCaretModel().moveToOffset(previousElement.getTextRange().getEndOffset()); + updater.moveTo(previousElement.getTextRange().getEndOffset()); } } @@ -132,9 +97,4 @@ public class DeleteCatchFix implements IntentionActionWithFixAllOption { catchSection.delete(); return previousElement; } - - @Override - public boolean startInWriteAction() { - return true; - } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteElementFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteElementFix.java index 6c57fdd07967..018e6026c094 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteElementFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteElementFix.java @@ -1,19 +1,14 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.CommonQuickFixBundle; +import com.intellij.codeInspection.ModCommands; import com.intellij.codeInspection.PsiUpdateModCommandAction; -import com.intellij.codeInspection.util.IntentionName; +import com.intellij.modcommand.ModCommand; +import com.intellij.modcommand.ModCommandAction; import com.intellij.modcommand.ModPsiUpdater; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.psi.util.JavaElementKind; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import com.siyeh.ig.psiutils.CommentTracker; import org.jetbrains.annotations.Nls; @@ -50,7 +45,7 @@ public class DeleteElementFix extends PsiUpdateModCommandAction { new CommentTracker().deleteAndRestoreComments(element); } - public static final class DeleteMultiFix implements IntentionAction { + public static final class DeleteMultiFix implements ModCommandAction { private final @NotNull PsiElement @NotNull [] myElements; private @NotNull final @Nls String myMessage; @@ -65,8 +60,8 @@ public class DeleteElementFix extends PsiUpdateModCommandAction { } @Override - public @IntentionName @NotNull String getText() { - return myMessage; + public @NotNull Presentation getPresentation(@NotNull ActionContext context) { + return Presentation.of(myMessage); } @Override @@ -75,25 +70,12 @@ public class DeleteElementFix extends PsiUpdateModCommandAction { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return true; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - for (PsiElement element : myElements) { - new CommentTracker().deleteAndRestoreComments(element); - } - } - - @Override - public boolean startInWriteAction() { - return true; - } - - @Override - public @NotNull FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new DeleteMultiFix(ContainerUtil.map2Array(myElements, PsiElement.class, e -> PsiTreeUtil.findSameElementInCopy(e, target))); + public @NotNull ModCommand perform(@NotNull ActionContext context) { + return ModCommands.psiUpdate(context, updater -> { + for (PsiElement element : ContainerUtil.map(myElements, updater::getWritable)) { + new CommentTracker().deleteAndRestoreComments(element); + } + }); } } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveCatchUpFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveCatchUpFix.java index 8a239b1f3c92..a2168b63ed37 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveCatchUpFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveCatchUpFix.java @@ -1,37 +1,19 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.impl.BaseIntentionAction; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; +import com.intellij.codeInspection.ModCommands; +import com.intellij.modcommand.ModCommand; +import com.intellij.modcommand.ModCommandAction; import com.intellij.psi.PsiCatchSection; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.psi.PsiTryStatement; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class MoveCatchUpFix implements IntentionAction { +public class MoveCatchUpFix implements ModCommandAction { private final @NotNull PsiCatchSection myCatchSection; private final @NotNull PsiCatchSection myMoveBeforeSection; @@ -41,17 +23,22 @@ public class MoveCatchUpFix implements IntentionAction { } @Override - public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new MoveCatchUpFix(PsiTreeUtil.findSameElementInCopy(myCatchSection, target), - PsiTreeUtil.findSameElementInCopy(myMoveBeforeSection, target)); - } - - @Override - @NotNull - public String getText() { - return QuickFixBundle.message("move.catch.up.text", - JavaHighlightUtil.formatType(myCatchSection.getCatchType()), - JavaHighlightUtil.formatType(myMoveBeforeSection.getCatchType())); + public @Nullable Presentation getPresentation(@NotNull ActionContext context) { + if (myCatchSection.isValid() + && BaseIntentionAction.canModify(myCatchSection) + && myMoveBeforeSection.isValid() + && myCatchSection.getCatchType() != null + && PsiUtil.resolveClassInType(myCatchSection.getCatchType()) != null + && myMoveBeforeSection.getCatchType() != null + && PsiUtil.resolveClassInType(myMoveBeforeSection.getCatchType()) != null + && !myCatchSection.getManager().areElementsEquivalent( + PsiUtil.resolveClassInType(myCatchSection.getCatchType()), + PsiUtil.resolveClassInType(myMoveBeforeSection.getCatchType()))) { + return Presentation.of(QuickFixBundle.message("move.catch.up.text", + JavaHighlightUtil.formatType(myCatchSection.getCatchType()), + JavaHighlightUtil.formatType(myMoveBeforeSection.getCatchType()))); + } + return null; } @Override @@ -61,34 +48,13 @@ public class MoveCatchUpFix implements IntentionAction { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return myCatchSection.isValid() - && BaseIntentionAction.canModify(myCatchSection) - && myMoveBeforeSection.isValid() - && myCatchSection.getCatchType() != null - && PsiUtil.resolveClassInType(myCatchSection.getCatchType()) != null - && myMoveBeforeSection.getCatchType() != null - && PsiUtil.resolveClassInType(myMoveBeforeSection.getCatchType()) != null - && !myCatchSection.getManager().areElementsEquivalent( - PsiUtil.resolveClassInType(myCatchSection.getCatchType()), - PsiUtil.resolveClassInType(myMoveBeforeSection.getCatchType())); - } - - @NotNull - @Override - public PsiElement getElementToMakeWritable(@NotNull PsiFile file) { - return myCatchSection.getContainingFile(); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) { - PsiTryStatement statement = myCatchSection.getTryStatement(); - statement.addBefore(myCatchSection, myMoveBeforeSection); - myCatchSection.delete(); - } - - @Override - public boolean startInWriteAction() { - return true; + public @NotNull ModCommand perform(@NotNull ActionContext context) { + return ModCommands.psiUpdate(context, updater -> { + PsiCatchSection catchSection = updater.getWritable(myCatchSection); + PsiCatchSection moveBeforeSection = updater.getWritable(myMoveBeforeSection); + PsiTryStatement statement = catchSection.getTryStatement(); + statement.addBefore(catchSection, moveBeforeSection); + catchSection.delete(); + }); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveMemberIntoClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveMemberIntoClassFix.java index f47684393de3..3873e257fbfb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveMemberIntoClassFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveMemberIntoClassFix.java @@ -1,15 +1,13 @@ -// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.impl.analysis.MemberModel; import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo; -import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; +import com.intellij.codeInspection.PsiUpdateModCommandAction; import com.intellij.java.JavaBundle; import com.intellij.lang.jvm.JvmModifier; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; @@ -21,26 +19,26 @@ import org.jetbrains.annotations.Nullable; import java.util.Objects; -public class MoveMemberIntoClassFix extends LocalQuickFixAndIntentionActionOnPsiElement { +public class MoveMemberIntoClassFix extends PsiUpdateModCommandAction { - public MoveMemberIntoClassFix(@Nullable PsiErrorElement errorElement) { + public MoveMemberIntoClassFix(@NotNull PsiErrorElement errorElement) { super(errorElement); } @Override - public void invoke(@NotNull Project project, - @NotNull PsiFile file, - @Nullable Editor editor, - @NotNull PsiElement startElement, - @NotNull PsiElement endElement) { - Pair rangeAndMember = createMember(file); + protected void invoke(@NotNull ActionContext context, @NotNull PsiErrorElement element, @NotNull ModPsiUpdater updater) { + PsiFile file = element.getContainingFile(); + MemberInfo rangeAndMember = createMember(file, element); if (rangeAndMember == null) return; Document document = file.getViewProvider().getDocument(); - TextRange memberRange = rangeAndMember.getFirst(); - PsiMember member = rangeAndMember.getSecond(); + TextRange memberRange = rangeAndMember.range(); + PsiMember member = rangeAndMember.member(); PsiClass psiClass = getPsiClass(file, member); if (psiClass == null) return; - PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); + if (psiClass.getContainingFile() != file) { + psiClass = (PsiClass)file.add(psiClass); + } + PsiDocumentManager documentManager = PsiDocumentManager.getInstance(context.project()); documentManager.doPostponedOperationsAndUnblockDocument(document); SmartPsiElementPointer classPtr = SmartPointerManager.createPointer(psiClass); document.deleteString(memberRange.getStartOffset(), memberRange.getEndOffset()); @@ -61,12 +59,7 @@ public class MoveMemberIntoClassFix extends LocalQuickFixAndIntentionActionOnPsi PsiClass psiClass = ContainerUtil.find(javaFile.getClasses(), c -> className.equals(c.getName())); if (psiClass != null) return psiClass; PsiElementFactory factory = JavaPsiFacade.getElementFactory(file.getProject()); - return (PsiClass)file.add(createClass(factory, className, member)); - } - - @Override - public @NotNull String getText() { - return getFamilyName(); + return createClass(factory, className, member); } @Override @@ -86,25 +79,25 @@ public class MoveMemberIntoClassFix extends LocalQuickFixAndIntentionActionOnPsi } return factory.createInterface(className); } + + record MemberInfo(@NotNull TextRange range, @NotNull PsiMember member) {} - private @Nullable Pair<@NotNull TextRange, @NotNull PsiMember> createMember(@NotNull PsiFile file) { - PsiErrorElement errorElement = ObjectUtils.tryCast(getStartElement(), PsiErrorElement.class); - if (errorElement == null) return null; + private static @Nullable MemberInfo createMember(@NotNull PsiFile file, @NotNull PsiErrorElement errorElement) { MemberModel model = MemberModel.create(errorElement); if (model == null) return null; TextRange memberRange = model.textRange(); String memberText = memberRange.substring(file.getText()); PsiElementFactory factory = JavaPsiFacade.getElementFactory(file.getProject()); MemberModel.MemberType memberType = model.memberType(); - return Pair.create(memberRange, memberType.create(factory, memberText, file)); + return new MemberInfo(memberRange, memberType.create(factory, memberText, file)); } @Override - public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { - Pair member = createMember(file); - if (member == null || !(member.getSecond() instanceof PsiNamedElement)) return IntentionPreviewInfo.EMPTY; - PsiClass psiClass = getPsiClass(file, member.getSecond()); + protected @NotNull IntentionPreviewInfo generatePreview(ActionContext context, PsiErrorElement element) { + MemberInfo info = createMember(context.file(), element); + if (info == null || !(info.member() instanceof PsiNamedElement member)) return IntentionPreviewInfo.EMPTY; + PsiClass psiClass = getPsiClass(context.file(), info.member()); if (psiClass == null) return IntentionPreviewInfo.EMPTY; - return IntentionPreviewInfo.movePsi((PsiNamedElement)member.getSecond(), psiClass); + return IntentionPreviewInfo.movePsi(member, psiClass); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/NegationBroadScopeFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/NegationBroadScopeFix.java index 2526b043f072..fd46bff4b37f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/NegationBroadScopeFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/NegationBroadScopeFix.java @@ -2,56 +2,51 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.QuickFixBundle; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; +import com.intellij.codeInspection.PsiUpdateModCommandAction; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Objects; + /** * if (!a == b) ... => if (!(a == b)) ... */ -public class NegationBroadScopeFix implements IntentionAction { - private final PsiPrefixExpression myPrefixExpression; - +public class NegationBroadScopeFix extends PsiUpdateModCommandAction { public NegationBroadScopeFix(@NotNull PsiPrefixExpression prefixExpression) { - myPrefixExpression = prefixExpression; + super(prefixExpression); } @Override - public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new NegationBroadScopeFix(PsiTreeUtil.findSameElementInCopy(myPrefixExpression, target)); - } + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiPrefixExpression expression) { + PsiExpression operand = expression.getOperand(); + if (operand == null) return null; - @Override - @NotNull - public String getText() { - PsiExpression operand = myPrefixExpression.getOperand(); - String text = operand == null ? "" : operand.getText() + " "; - PsiElement parent = myPrefixExpression.getParent(); + PsiElement parent = expression.getParent(); + String text = operand.getText() + " "; String rop; - if (parent instanceof PsiInstanceOfExpression) { + if (parent instanceof PsiInstanceOfExpression instanceOf) { + if (instanceOf.getOperand() != expression) return null; text += PsiKeyword.INSTANCEOF + " "; - final PsiTypeElement typeElement = ((PsiInstanceOfExpression)parent).getCheckType(); + final PsiTypeElement typeElement = instanceOf.getCheckType(); rop = typeElement == null ? "" : typeElement.getText(); } - else if (parent instanceof PsiBinaryExpression) { - text += ((PsiBinaryExpression)parent).getOperationSign().getText() + " "; - final PsiExpression rOperand = ((PsiBinaryExpression)parent).getROperand(); + else if (parent instanceof PsiBinaryExpression binaryExpression) { + if (binaryExpression.getLOperand() != expression) return null; + if (!TypeConversionUtil.isBooleanType(binaryExpression.getType())) return null; + text += binaryExpression.getOperationSign().getText() + " "; + final PsiExpression rOperand = binaryExpression.getROperand(); rop = rOperand == null ? "" : rOperand.getText(); } else { - rop = ""; + return null; } text += rop; - return QuickFixBundle.message("negation.broader.scope.text", text); + return Presentation.of(QuickFixBundle.message("negation.broader.scope.text", text)); } @Override @@ -61,40 +56,15 @@ public class NegationBroadScopeFix implements IntentionAction { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - if (!myPrefixExpression.isValid() || myPrefixExpression.getOperand() == null) return false; - - PsiElement parent = myPrefixExpression.getParent(); - if (parent instanceof PsiInstanceOfExpression && ((PsiInstanceOfExpression)parent).getOperand() == myPrefixExpression) { - return true; - } - return parent instanceof PsiBinaryExpression binaryExpression && - binaryExpression.getLOperand() == myPrefixExpression && - TypeConversionUtil.isBooleanType(binaryExpression.getType()); - } - - @NotNull - @Override - public PsiElement getElementToMakeWritable(@NotNull PsiFile file) { - return myPrefixExpression.getContainingFile(); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - if (!isAvailable(project, editor, file)) return; - PsiExpression operand = myPrefixExpression.getOperand(); + protected void invoke(@NotNull ActionContext context, @NotNull PsiPrefixExpression myPrefixExpression, @NotNull ModPsiUpdater updater) { + PsiExpression operand = Objects.requireNonNull(myPrefixExpression.getOperand()); PsiElement unnegated = myPrefixExpression.replace(operand); PsiElement parent = unnegated.getParent(); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(file.getProject()); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.project()); PsiPrefixExpression negated = (PsiPrefixExpression)factory.createExpressionFromText("!(xxx)", parent); - PsiParenthesizedExpression parentheses = (PsiParenthesizedExpression)negated.getOperand(); - parentheses.getExpression().replace(parent.copy()); + PsiParenthesizedExpression parentheses = (PsiParenthesizedExpression)Objects.requireNonNull(negated.getOperand()); + Objects.requireNonNull(parentheses.getExpression()).replace(parent.copy()); parent.replace(negated); } - - @Override - public boolean startInWriteAction() { - return true; - } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassJava10Fix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassJava10Fix.java index d48f3579ad67..ca848a810f2f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassJava10Fix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassJava10Fix.java @@ -1,38 +1,33 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; -import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.QuickFixBundle; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.impl.BaseIntentionAction; +import com.intellij.codeInspection.PsiUpdateModCommandAction; import com.intellij.java.JavaBundle; -import com.intellij.openapi.editor.Editor; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.refactoring.rename.inplace.MemberInplaceRenamer; import com.intellij.util.CommonJavaRefactoringUtil; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.SmartList; import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.TypeUtils; +import com.siyeh.ig.psiutils.VariableNameGenerator; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; -import java.util.LinkedHashSet; import java.util.List; -import java.util.stream.Collectors; import static com.intellij.util.ObjectUtils.tryCast; import static java.util.Collections.emptyList; -public class VariableAccessFromInnerClassJava10Fix extends BaseIntentionAction { +public class VariableAccessFromInnerClassJava10Fix extends PsiUpdateModCommandAction { @NonNls private final static String[] NAMES = { "ref", "lambdaContext", @@ -40,15 +35,8 @@ public class VariableAccessFromInnerClassJava10Fix extends BaseIntentionAction { "rContext" }; - private final PsiElement myContext; - public VariableAccessFromInnerClassJava10Fix(PsiElement context) { - myContext = context; - } - - @Override - public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new VariableAccessFromInnerClassJava10Fix(PsiTreeUtil.findSameElementInCopy(myContext, target)); + super(context); } @Nls(capitalization = Nls.Capitalization.Sentence) @@ -59,30 +47,27 @@ public class VariableAccessFromInnerClassJava10Fix extends BaseIntentionAction { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - if (!PsiUtil.isLanguageLevel10OrHigher(file)) return false; - if (!myContext.isValid()) return false; - PsiReferenceExpression reference = tryCast(myContext, PsiReferenceExpression.class); - if (reference == null) return false; + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiElement element) { + if (!PsiUtil.isLanguageLevel10OrHigher(context.file())) return null; + PsiReferenceExpression reference = tryCast(element, PsiReferenceExpression.class); + if (reference == null) return null; PsiLocalVariable variable = tryCast(reference.resolve(), PsiLocalVariable.class); - if (variable == null) return false; + if (variable == null) return null; PsiDeclarationStatement declarationStatement = tryCast(variable.getParent(), PsiDeclarationStatement.class); - if (declarationStatement == null) return false; - if (declarationStatement.getDeclaredElements().length != 1) return false; + if (declarationStatement == null) return null; + if (declarationStatement.getDeclaredElements().length != 1) return null; String name = variable.getName(); PsiType type = variable.getType(); if (!PsiTypesUtil.isDenotableType(type, variable)) { - return false; + return null; } - setText(QuickFixBundle.message("convert.variable.to.field.in.anonymous.class.fix.name", name)); - return true; + return Presentation.of(QuickFixBundle.message("convert.variable.to.field.in.anonymous.class.fix.name", name)); } @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - if (!(myContext instanceof PsiReferenceExpression referenceExpression) || !myContext.isValid()) return; - if (!FileModificationService.getInstance().preparePsiElementsForWrite(myContext)) return; + protected void invoke(@NotNull ActionContext context, @NotNull PsiElement element, @NotNull ModPsiUpdater updater) { + if (!(element instanceof PsiReferenceExpression referenceExpression)) return; PsiLocalVariable variable = tryCast(referenceExpression.resolve(), PsiLocalVariable.class); if (variable == null) return; @@ -97,9 +82,10 @@ public class VariableAccessFromInnerClassJava10Fix extends BaseIntentionAction { return; } - - JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); - String boxName = codeStyleManager.suggestUniqueVariableName(NAMES[0], variable, true); + Project project = context.project(); + List suggestions = new VariableNameGenerator(variable, VariableKind.LOCAL_VARIABLE) + .byName(NAMES).generateAll(true); + String boxName = suggestions.get(0); String boxDeclarationText = "var " + boxName + " = new Object(){" + @@ -107,25 +93,11 @@ public class VariableAccessFromInnerClassJava10Fix extends BaseIntentionAction { "};"; PsiStatement boxDeclaration = JavaPsiFacade.getElementFactory(project).createStatementFromText(boxDeclarationText, variable); replaceReferences(variable, boxName); - if (editor == null) { - variable.replace(boxDeclaration); - return; - } PsiStatement statement = PsiTreeUtil.getParentOfType(variable, PsiStatement.class); if (statement == null) return; PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)statement.replace(boxDeclaration); PsiLocalVariable localVariable = (PsiLocalVariable)declarationStatement.getDeclaredElements()[0]; - SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project); - SmartPsiElementPointer pointer = smartPointerManager.createSmartPsiElementPointer(localVariable); - PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); - PsiLocalVariable varToChange = pointer.getElement(); - if (varToChange == null) return; - editor.getCaretModel().moveToOffset(varToChange.getTextOffset()); - editor.getSelectionModel().removeSelection(); - LinkedHashSet suggestions = Arrays.stream(NAMES) - .map(suggestion -> codeStyleManager.suggestUniqueVariableName(suggestion, varToChange, var -> var == varToChange)) - .collect(Collectors.toCollection(() -> new LinkedHashSet<>())); - new MemberInplaceRenamer(varToChange, varToChange, editor).performInplaceRefactoring(suggestions); + updater.rename(localVariable, suggestions); } private static void replaceReferences(PsiLocalVariable variable, String boxName) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapSwitchRuleStatementsIntoBlockFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapSwitchRuleStatementsIntoBlockFix.java index 072840874563..84b87e753d51 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapSwitchRuleStatementsIntoBlockFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapSwitchRuleStatementsIntoBlockFix.java @@ -1,17 +1,13 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.QuickFixBundle; -import com.intellij.codeInsight.daemon.impl.actions.IntentionActionWithFixAllOption; -import com.intellij.codeInsight.intention.FileModifier; -import com.intellij.codeInsight.intention.impl.BaseIntentionAction; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; +import com.intellij.codeInspection.PsiUpdateModCommandAction; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -19,17 +15,9 @@ import org.jetbrains.annotations.Nullable; import java.util.Objects; -public class WrapSwitchRuleStatementsIntoBlockFix extends BaseIntentionAction implements IntentionActionWithFixAllOption { - @NotNull - private final PsiSwitchLabeledRuleStatement myRuleStatement; - +public class WrapSwitchRuleStatementsIntoBlockFix extends PsiUpdateModCommandAction { public WrapSwitchRuleStatementsIntoBlockFix(@NotNull PsiSwitchLabeledRuleStatement ruleStatement) { - myRuleStatement = ruleStatement; - } - - @Override - public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) { - return new WrapSwitchRuleStatementsIntoBlockFix(PsiTreeUtil.findSameElementInCopy(myRuleStatement, target)); + super(ruleStatement); } @Nls(capitalization = Nls.Capitalization.Sentence) @@ -40,27 +28,23 @@ public class WrapSwitchRuleStatementsIntoBlockFix extends BaseIntentionAction im } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - if (!(file instanceof PsiJavaFile)) return false; - if (!myRuleStatement.isValid()) return false; - if (myRuleStatement.getBody() instanceof PsiBlockStatement) return false; - PsiStatement sibling = PsiTreeUtil.getNextSiblingOfType(myRuleStatement, PsiStatement.class); + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiSwitchLabeledRuleStatement ruleStatement) { + if (ruleStatement.getBody() instanceof PsiBlockStatement) return null; + PsiStatement sibling = PsiTreeUtil.getNextSiblingOfType(ruleStatement, PsiStatement.class); if (sibling == null || sibling instanceof PsiSwitchLabelStatementBase) { - setText(getFamilyName()); - } else { - setText(QuickFixBundle.message("wrap.with.block")); + return Presentation.of(getFamilyName()).withFixAllOption(this); } - return true; + return Presentation.of(QuickFixBundle.message("wrap.with.block")).withFixAllOption(this); } @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - if (!myRuleStatement.isValid()) return; - PsiCodeBlock parent = ObjectUtils.tryCast(myRuleStatement.getParent(), PsiCodeBlock.class); + protected void invoke(@NotNull ActionContext context, @NotNull PsiSwitchLabeledRuleStatement ruleStatement, @NotNull ModPsiUpdater updater) { + if (!ruleStatement.isValid()) return; + PsiCodeBlock parent = ObjectUtils.tryCast(ruleStatement.getParent(), PsiCodeBlock.class); if (parent == null) return; PsiJavaToken rBrace = parent.getRBrace(); PsiElement[] children = parent.getChildren(); - int index = ArrayUtil.indexOf(children, myRuleStatement); + int index = ArrayUtil.indexOf(children, ruleStatement); assert index >= 0; int nextIndex = index + 1; while (nextIndex < children.length && !(children[nextIndex] instanceof PsiSwitchLabelStatementBase) && children[nextIndex] != rBrace) { @@ -70,18 +54,18 @@ public class WrapSwitchRuleStatementsIntoBlockFix extends BaseIntentionAction im nextIndex--; } PsiElement oldBody = null; - if (myRuleStatement.getBody() != null) { - oldBody = myRuleStatement.getBody().copy(); - myRuleStatement.getBody().delete(); + if (ruleStatement.getBody() != null) { + oldBody = ruleStatement.getBody().copy(); + ruleStatement.getBody().delete(); } - for (PsiElement lastChild = myRuleStatement.getLastChild(); lastChild != null; lastChild = lastChild.getPrevSibling()) { + for (PsiElement lastChild = ruleStatement.getLastChild(); lastChild != null; lastChild = lastChild.getPrevSibling()) { if (PsiUtil.isJavaToken(lastChild, JavaTokenType.SEMICOLON)) { lastChild.delete(); break; } } - PsiSwitchLabeledRuleStatement newRule = (PsiSwitchLabeledRuleStatement)JavaPsiFacade.getElementFactory(project).createStatementFromText( - myRuleStatement.getText() + "{}", myRuleStatement); + PsiSwitchLabeledRuleStatement newRule = (PsiSwitchLabeledRuleStatement)JavaPsiFacade.getElementFactory(context.project()) + .createStatementFromText(ruleStatement.getText() + "{}", ruleStatement); PsiCodeBlock block = ((PsiBlockStatement)Objects.requireNonNull(newRule.getBody())).getCodeBlock(); if (oldBody != null) { block.add(oldBody); @@ -92,6 +76,6 @@ public class WrapSwitchRuleStatementsIntoBlockFix extends BaseIntentionAction im block.addRange(first, last); parent.deleteChildRange(first, last); } - myRuleStatement.replace(newRule); + ruleStatement.replace(newRule); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/documentation/JavaDocCommentFixer.java b/java/java-impl/src/com/intellij/codeInsight/documentation/JavaDocCommentFixer.java index d40011fcb97b..c0f51be8c393 100644 --- a/java/java-impl/src/com/intellij/codeInsight/documentation/JavaDocCommentFixer.java +++ b/java/java-impl/src/com/intellij/codeInsight/documentation/JavaDocCommentFixer.java @@ -12,6 +12,7 @@ import com.intellij.codeInspection.javaDoc.MissingJavadocInspection; import com.intellij.javadoc.JavadocNavigationDelegate; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; @@ -52,8 +53,7 @@ public class JavaDocCommentFixer implements DocCommentFixer { */ private static final Set CARET_ANCHOR_TAGS = ContainerUtil.newHashSet(PARAM_TAG, "@throws", "@return"); - private static final Comparator COMPARATOR = - (e1, e2) -> e2.getTextRange().getEndOffset() - e1.getTextRange().getEndOffset(); + private static final Comparator COMPARATOR = (e1, e2) -> e2.getEndOffset() - e1.getEndOffset(); @Override public void fixComment(@NotNull Project project, @NotNull Editor editor, @NotNull PsiComment comment) { @@ -144,9 +144,9 @@ public class JavaDocCommentFixer implements DocCommentFixer { private static void fixCommonProblems(@NotNull List problems, @NotNull PsiComment comment, @NotNull final Document document, - @NotNull Project project) - { - List toRemove = new ArrayList<>(); + @NotNull Project project) { + List toRemove = new ArrayList<>(); + List problemsToApply = new ArrayList<>(); for (ProblemDescriptor problem : problems) { PsiElement element = problem.getPsiElement(); if (element == null) { @@ -157,32 +157,36 @@ public class JavaDocCommentFixer implements DocCommentFixer { // Unnecessary element like '@return' at the void method's javadoc. for (PsiElement e = element; e != null; e = e.getParent()) { if (e instanceof PsiDocTag) { - toRemove.add(e); + toRemove.add(document.createRangeMarker(e.getTextRange())); break; } } } else { - // Problems like 'missing @param'. - QuickFix[] fixes = problem.getFixes(); - if (fixes != null && fixes.length > 0) { - fixes[0].applyFix(project, problem); - } + problemsToApply.add(problem); } } - if (toRemove.isEmpty()) { - return; - } - if (toRemove.size() > 1) { - toRemove.sort(COMPARATOR); + for (ProblemDescriptor problem : problemsToApply) { + // Problems like 'missing @param'. + QuickFix[] fixes = problem.getFixes(); + if (fixes != null && fixes.length > 0) { + fixes[0].applyFix(project, problem); + } } PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); + if (toRemove.isEmpty()) { + psiDocumentManager.commitDocument(document); + return; + } + psiDocumentManager.doPostponedOperationsAndUnblockDocument(document); CharSequence text = document.getCharsSequence(); - for (PsiElement element : toRemove) { - int startOffset = element.getTextRange().getStartOffset(); + List toDelete = new ArrayList<>(); + for (RangeMarker rangeMarker : toRemove) { + TextRange range = rangeMarker.getTextRange(); + int startOffset = range.getStartOffset(); int startLine = document.getLineNumber(startOffset); int i = CharArrayUtil.shiftBackward(text, startOffset - 1, " \t"); if (i >= 0) { @@ -195,14 +199,20 @@ public class JavaDocCommentFixer implements DocCommentFixer { startOffset = Math.max(i, document.getLineStartOffset(startLine) - 1); } - int endOffset = element.getTextRange().getEndOffset(); + int endOffset = range.getEndOffset(); // Javadoc PSI is awkward, it includes next line text before the next tag. That's why we need to strip it. i = CharArrayUtil.shiftBackward(text, endOffset - 1, " \t*"); if (i > 0 && text.charAt(i) == '\n') { endOffset = i; } - document.deleteString(startOffset, endOffset); + toDelete.add(new TextRange(startOffset, endOffset)); } + + toDelete.sort(COMPARATOR); + for (TextRange range : toDelete) { + document.deleteString(range.getStartOffset(), range.getEndOffset()); + } + psiDocumentManager.commitDocument(document); } diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ExtractSetFromComparisonChainAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ExtractSetFromComparisonChainAction.java index 654c14cd62cf..62131e977334 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ExtractSetFromComparisonChainAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ExtractSetFromComparisonChainAction.java @@ -1,32 +1,27 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.intention.impl; -import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.PsiEquivalenceUtil; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; -import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo; +import com.intellij.codeInspection.ModCommands; import com.intellij.codeInspection.RemoveRedundantTypeArgumentsUtil; import com.intellij.java.JavaBundle; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.application.WriteAction; -import com.intellij.openapi.editor.Editor; +import com.intellij.modcommand.ModChooseAction; +import com.intellij.modcommand.ModCommand; +import com.intellij.modcommand.ModCommandAction; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.SuggestedNameInfo; import com.intellij.psi.codeStyle.VariableKind; -import com.intellij.psi.search.LocalSearchScope; -import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.refactoring.rename.inplace.MemberInplaceRenamer; -import com.intellij.util.IncorrectOperationException; -import com.intellij.util.ThrowableRunnable; +import com.intellij.util.ThreeState; +import com.intellij.util.containers.ContainerUtil; import com.siyeh.ig.psiutils.ClassUtils; import com.siyeh.ig.psiutils.EqualityCheck; import com.siyeh.ig.psiutils.ExpressionUtils; @@ -42,7 +37,7 @@ import java.util.*; import static com.intellij.util.ObjectUtils.tryCast; -public class ExtractSetFromComparisonChainAction extends PsiElementBaseIntentionAction { +public class ExtractSetFromComparisonChainAction implements ModCommandAction { private static class Holder { private static final String GUAVA_IMMUTABLE_SET = "com.google.common.collect.ImmutableSet"; private static final String INITIALIZER_FORMAT_GUAVA = GUAVA_IMMUTABLE_SET + ".of({0})"; @@ -59,107 +54,60 @@ public class ExtractSetFromComparisonChainAction extends PsiElementBaseIntention CommonClassNames.JAVA_UTIL_COLLECTIONS + ".unmodifiableSet(" + "java.util.EnumSet.of({0}))"; } - @Override - public boolean startInWriteAction() { - return false; + + private final @NotNull ThreeState myProcessDuplicates; + + public ExtractSetFromComparisonChainAction() { + myProcessDuplicates = ThreeState.UNSURE; + } + + private ExtractSetFromComparisonChainAction(boolean processDuplicates) { + myProcessDuplicates = ThreeState.fromBoolean(processDuplicates); } @Override - public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { - PsiElement element = getElement(editor, file); - if (element == null) return IntentionPreviewInfo.EMPTY; - extract(project, editor, element); - return IntentionPreviewInfo.DIFF; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { - if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; - - PsiDocumentManager.getInstance(project).commitAllDocuments(); - - extract(project, editor, element); - } - - private void extract(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - boolean preview = !element.isPhysical(); + public @NotNull ModCommand perform(@NotNull ActionContext actionContext) { + PsiElement element = actionContext.findLeaf(); List comparisons = comparisons(element).toList(); - if (comparisons.size() < 2) return; + if (comparisons.size() < 2) return ModCommands.nop(); PsiClass containingClass = ClassUtils.getContainingStaticClass(element); - if (containingClass == null) return; - ExpressionToConstantReplacementContext context = new ExpressionToConstantReplacementContext(comparisons); - List copies = findCopies(comparisons, containingClass); - JavaCodeStyleManager manager = JavaCodeStyleManager.getInstance(project); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + if (containingClass == null) return ModCommands.nop(); + List copies = + myProcessDuplicates == ThreeState.NO ? List.of() : findCopies(comparisons, containingClass); + if (myProcessDuplicates == ThreeState.UNSURE && !copies.isEmpty()) { + return new ModChooseAction(JavaBundle.message("intention.extract.set.from.comparison.chain.popup.title"), + List.of(new ExtractSetFromComparisonChainAction(false), + new ExtractSetFromComparisonChainAction(true))); + } LinkedHashSet suggestions = getSuggestions(comparisons); - class Extractor implements ThrowableRunnable { - SmartPsiElementPointer resultPtr; - SmartPsiElementPointer fieldPtr; + return ModCommands.psiUpdate(containingClass, (cls, updater) -> { + Project project = cls.getProject(); + ExpressionToConstantReplacementContext context = new ExpressionToConstantReplacementContext(comparisons).getWritable(updater); + List writableCopies = ContainerUtil.map(copies, copy -> copy.getWritable(updater)); - @Override - public void run() { - if (!containingClass.isValid()) return; - String name = manager.suggestUniqueVariableName(suggestions.iterator().next(), containingClass, false); - String fieldInitializer = context.myInitializer; - PsiType elementType = context.myTypePtr.getType(); - if (elementType == null) return; - String pattern = getInitializer(elementType, containingClass); - String initializer = MessageFormat.format(pattern, fieldInitializer, elementType.getCanonicalText()); - String modifiers = containingClass.isInterface() ? "" : "private static final "; - String type = CommonClassNames.JAVA_UTIL_SET + - (PsiUtil.isLanguageLevel5OrHigher(containingClass) ? "<" + elementType.getCanonicalText() + ">" : ""); - PsiField field = factory.createFieldFromText(modifiers + type + " " + name + "=" + initializer + ";", containingClass); - field = (PsiField)containingClass.add(field); - RemoveRedundantTypeArgumentsUtil.removeRedundantTypeArguments(field); - CodeStyleManager.getInstance(project).reformat(manager.shortenClassReferences(field)); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + JavaCodeStyleManager manager = JavaCodeStyleManager.getInstance(project); + String name = manager.suggestUniqueVariableName(suggestions.iterator().next(), cls, false); + String fieldInitializer = context.myInitializer; + PsiType elementType = context.myType; + if (elementType == null) return; + String pattern = getInitializer(elementType, cls); + String initializer = MessageFormat.format(pattern, fieldInitializer, elementType.getCanonicalText()); + String modifiers = cls.isInterface() ? "" : "private static final "; + String type = CommonClassNames.JAVA_UTIL_SET + + (PsiUtil.isLanguageLevel5OrHigher(cls) ? "<" + elementType.getCanonicalText() + ">" : ""); + PsiField field = factory.createFieldFromText(modifiers + type + " " + name + "=" + initializer + ";", cls); + field = (PsiField)cls.add(field); + RemoveRedundantTypeArgumentsUtil.removeRedundantTypeArguments(field); + CodeStyleManager.getInstance(project).reformat(manager.shortenClassReferences(field)); - SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project); - PsiElement result = context.replace(field); - resultPtr = result == null ? null : smartPointerManager.createSmartPsiElementPointer(result); - fieldPtr = smartPointerManager.createSmartPsiElementPointer(field); + context.replace(field); + for (ExpressionToConstantReplacementContext copy : writableCopies) { + copy.replace(field); } - } - Extractor extractor = new Extractor(); - if (preview) { - extractor.run(); - } - else { - WriteAction.run(extractor); - } - PsiElement result = extractor.resultPtr == null ? null : extractor.resultPtr.getElement(); - if (result == null || !result.isValid()) return; - - if (!copies.isEmpty() && !preview) { - int answer = ApplicationManager.getApplication().isUnitTestMode() ? Messages.YES : - Messages.showYesNoDialog(project, - JavaBundle.message("intention.extract.set.from.comparison.chain.duplicates", - ApplicationNamesInfo.getInstance().getProductName(), - copies.size()), JavaBundle.message( - "dialog.title.process.duplicates"), - Messages.getQuestionIcon()); - if (answer == Messages.YES) { - WriteAction.run(() -> { - PsiField field = extractor.fieldPtr.getElement(); - if (field == null) return; - for (ExpressionToConstantReplacementContext copy : copies) { - copy.replace(field); - } - }); - } - } - - PsiField field = extractor.fieldPtr.getElement(); - result = extractor.resultPtr.getElement(); - if (result == null || field == null) return; - PsiReferenceExpression fieldRef = - tryCast(ReferencesSearch.search(field, new LocalSearchScope(result)).findFirst(), PsiReferenceExpression.class); - if (fieldRef == null) return; - - PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); - editor.getCaretModel().moveToOffset(fieldRef.getTextOffset()); - editor.getSelectionModel().removeSelection(); - new MemberInplaceRenamer(field, field, editor).performInplaceRefactoring(suggestions); + updater.rename(field, List.copyOf(suggestions)); + }); } private static List findCopies(@NotNull List comparisons, @@ -206,14 +154,27 @@ public class ExtractSetFromComparisonChainAction extends PsiElementBaseIntention } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - return comparisons(element).count() > 1; - } - - @NotNull - @Override - public String getText() { - return getFamilyName(); + public @Nullable Presentation getPresentation(@NotNull ActionContext actionContext) { + PsiElement element = actionContext.findLeaf(); + List comparisons = comparisons(element).toList(); + if (comparisons.size() <= 1) return null; + return switch (myProcessDuplicates) { + case UNSURE -> Presentation.of(getFamilyName()); + case YES -> { + PsiClass containingClass = ClassUtils.getContainingStaticClass(element); + if (containingClass == null) yield null; + ExpressionToConstantReplacementContext context = new ExpressionToConstantReplacementContext(comparisons); + List copies = findCopies(comparisons, containingClass); + TextRange[] ranges = + StreamEx.of(copies).append(context).map(ExpressionToConstantReplacementContext::range).toArray(TextRange.EMPTY_ARRAY); + yield Presentation.of(JavaBundle.message("intention.extract.set.from.comparison.chain.replace.all")).withHighlighting(ranges); + } + case NO -> { + ExpressionToConstantReplacementContext context = new ExpressionToConstantReplacementContext(comparisons); + yield Presentation.of(JavaBundle.message("intention.extract.set.from.comparison.chain.replace.only.this")) + .withHighlighting(context.range()); + } + }; } @Nls @@ -274,42 +235,54 @@ public class ExtractSetFromComparisonChainAction extends PsiElementBaseIntention } static final class ExpressionToConstantReplacementContext { - final SmartPsiElementPointer myExpressionPtr; - final SmartPsiElementPointer myFirstComparisonPtr; - final SmartPsiElementPointer myLastComparisonPtr; - final SmartTypePointer myTypePtr; + final @NotNull PsiExpression myExpression; + final @NotNull PsiExpression myFirstComparison; + final @NotNull PsiExpression myLastComparison; + final PsiType myType; final String myInitializer; ExpressionToConstantReplacementContext(List comparisons) { assert !comparisons.isEmpty(); - Project project = comparisons.get(0).myComparison.getProject(); - SmartPointerManager manager = SmartPointerManager.getInstance(project); - myExpressionPtr = manager.createSmartPsiElementPointer(comparisons.get(0).myExpression); - myFirstComparisonPtr = manager.createSmartPsiElementPointer(comparisons.get(0).myComparison); - myLastComparisonPtr = manager.createSmartPsiElementPointer(comparisons.get(comparisons.size() - 1).myComparison); - myTypePtr = SmartTypePointerManager.getInstance(project).createSmartTypePointer(comparisons.get(0).myType); + myExpression = comparisons.get(0).myExpression; + myFirstComparison = comparisons.get(0).myComparison; + myLastComparison = comparisons.get(comparisons.size() - 1).myComparison; + myType = comparisons.get(0).myType; myInitializer = StreamEx.of(comparisons).map(cmp -> cmp.myConstant.getText()).joining(","); } + private ExpressionToConstantReplacementContext(ExpressionToConstantReplacementContext context, ModPsiUpdater updater) { + myExpression = updater.getWritable(context.myExpression); + myFirstComparison = updater.getWritable(context.myFirstComparison); + myLastComparison = updater.getWritable(context.myLastComparison); + myType = context.myType; + myInitializer = context.myInitializer; + } + + @NotNull TextRange range() { + int start = myFirstComparison.getTextRange().getStartOffset(); + int end = myLastComparison.getTextRange().getEndOffset(); + return TextRange.create(start, end); + } + + @NotNull ExpressionToConstantReplacementContext getWritable(@NotNull ModPsiUpdater updater) { + return new ExpressionToConstantReplacementContext(this, updater); + } + @Nullable private PsiElement replace(@NotNull PsiField field) { Project project = field.getProject(); PsiClass containingClass = field.getContainingClass(); if (containingClass == null) return null; String name = field.getName(); - PsiExpression expression = myExpressionPtr.getElement(); - PsiExpression firstComparison = myFirstComparisonPtr.getElement(); - PsiExpression lastComparison = myLastComparisonPtr.getElement(); - if (expression == null || firstComparison == null || lastComparison == null) return null; - PsiExpression disjunction = tryCast(firstComparison.getParent(), PsiPolyadicExpression.class); + PsiExpression disjunction = tryCast(myFirstComparison.getParent(), PsiPolyadicExpression.class); if (disjunction == null) return null; - int startOffset = firstComparison.getStartOffsetInParent(); - int endOffset = lastComparison.getStartOffsetInParent() + lastComparison.getTextLength(); + int startOffset = myFirstComparison.getStartOffsetInParent(); + int endOffset = myLastComparison.getStartOffsetInParent() + myLastComparison.getTextLength(); String origText = disjunction.getText(); String fieldReference = PsiResolveHelper.getInstance(project).resolveReferencedVariable(name, disjunction) == field ? name : containingClass.getQualifiedName() + "." + name; String replacementText = origText.substring(0, startOffset) + - fieldReference + ".contains(" + expression.getText() + ")" + + fieldReference + ".contains(" + myExpression.getText() + ")" + origText.substring(endOffset); PsiExpression replacement = JavaPsiFacade.getElementFactory(project).createExpressionFromText(replacementText, disjunction); if (replacement instanceof PsiMethodCallExpression && disjunction.getParent() instanceof PsiParenthesizedExpression) { diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InlineStreamMapAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InlineStreamMapAction.java index 6b53808f1afb..106c0ca48395 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InlineStreamMapAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InlineStreamMapAction.java @@ -1,19 +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 com.intellij.codeInsight.intention.impl; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; -import com.intellij.codeInsight.intention.preview.IntentionPreviewUtils; +import com.intellij.codeInspection.PsiUpdateModCommandAction; import com.intellij.java.JavaBundle; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.impl.source.DummyHolder; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.LambdaRefactoringUtil; -import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.psiutils.CommentTracker; import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.ParenthesesUtils; @@ -25,7 +23,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Set; -public class InlineStreamMapAction extends PsiElementBaseIntentionAction { +public class InlineStreamMapAction extends PsiUpdateModCommandAction { private static final Logger LOG = Logger.getInstance(InlineStreamMapAction.class.getName()); public static final class Holder { private static final Set MAP_METHODS = @@ -35,21 +33,23 @@ public class InlineStreamMapAction extends PsiElementBaseIntentionAction { .of("flatMap", "flatMapToInt", "flatMapToLong", "flatMapToDouble", "forEach", "forEachOrdered", "anyMatch", "noneMatch", "allMatch") .append(MAP_METHODS).toSet(); } + + public InlineStreamMapAction() { + super(PsiIdentifier.class); + } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull final PsiElement element) { - if (!(element instanceof PsiIdentifier)) return false; + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiIdentifier element) { final PsiElement parent = element.getParent(); - if (!(parent instanceof PsiReferenceExpression)) return false; + if (!(parent instanceof PsiReferenceExpression)) return null; final PsiElement gParent = parent.getParent(); - if (!(gParent instanceof PsiMethodCallExpression curCall)) return false; - if (!isMapCall(curCall)) return false; + if (!(gParent instanceof PsiMethodCallExpression curCall)) return null; + if (!isMapCall(curCall)) return null; PsiMethodCallExpression nextCall = getNextExpressionToMerge(curCall); - if(nextCall == null) return false; + if(nextCall == null) return null; String key = curCall.getArgumentList().isEmpty() || nextCall.getArgumentList().isEmpty() ? "intention.inline.map.merge.text" : "intention.inline.map.inline.text"; - setText(JavaBundle.message(key, element.getText(), nextCall.getMethodExpression().getReferenceName())); - return true; + return Presentation.of(JavaBundle.message(key, element.getText(), nextCall.getMethodExpression().getReferenceName())); } private static boolean isMapCall(@NotNull PsiMethodCallExpression methodCallExpression) { @@ -165,7 +165,7 @@ public class InlineStreamMapAction extends PsiElementBaseIntentionAction { } @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { + protected void invoke(@NotNull ActionContext context, @NotNull PsiIdentifier element, @NotNull ModPsiUpdater updater) { PsiMethodCallExpression mapCall = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class); if(mapCall == null) return; @@ -190,7 +190,7 @@ public class InlineStreamMapAction extends PsiElementBaseIntentionAction { CommentTracker ct = new CommentTracker(); - if (!lambda.isPhysical() && !IntentionPreviewUtils.isPreviewElement(lambda)) { + if (lambda.getContainingFile() instanceof DummyHolder) { lambda = (PsiLambdaExpression)nextCall.getArgumentList().add(lambda); } PsiElement body = lambda.getBody(); @@ -201,7 +201,7 @@ public class InlineStreamMapAction extends PsiElementBaseIntentionAction { LOG.assertTrue(nextParameters.length == 1); PsiParameter[] prevParameters = previousLambda.getParameterList().getParameters(); LOG.assertTrue(prevParameters.length == 1); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.project()); for(PsiReferenceExpression ref : VariableAccessUtils.getVariableReferences(nextParameters[0], body)) { PsiExpression replacement = ct.markUnchanged(previousBody); if (ref.getParent() instanceof PsiExpression && @@ -221,7 +221,7 @@ public class InlineStreamMapAction extends PsiElementBaseIntentionAction { } else { ct.replaceAndRestoreComments(nextQualifier, prevQualifier); } - CodeStyleManager.getInstance(project).reformat(lambda); + CodeStyleManager.getInstance(context.project()).reformat(lambda); } @Nullable diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SortContentAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SortContentAction.java index 85075a9f3652..b3b2090b26d9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SortContentAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SortContentAction.java @@ -1,11 +1,11 @@ -// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.intention.impl; import com.google.common.collect.Comparators; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.codeInspection.PsiUpdateModCommandAction; import com.intellij.ide.highlighter.JavaFileType; import com.intellij.java.JavaBundle; -import com.intellij.openapi.editor.Editor; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; @@ -13,7 +13,6 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.ObjectUtils; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; @@ -27,9 +26,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.stream.Collectors; -public final class SortContentAction extends PsiElementBaseIntentionAction { +public final class SortContentAction extends PsiUpdateModCommandAction { public static final int MIN_ELEMENTS_COUNT = 3; private static final class Holder { @@ -51,6 +49,10 @@ public final class SortContentAction extends PsiElementBaseIntentionAction { ); } + public SortContentAction() { + super(PsiElement.class); + } + @Nls @NotNull @Override @@ -58,14 +60,8 @@ public final class SortContentAction extends PsiElementBaseIntentionAction { return JavaBundle.message("intention.family.sort.content"); } - @NotNull @Override - public String getText() { - return getFamilyName(); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { + protected void invoke(@NotNull ActionContext context, @NotNull PsiElement element, @NotNull ModPsiUpdater updater) { for (Sortable sortable : Holder.OUR_SORTABLES) { if (sortable.isAvailable(element)) { sortable.replaceWithSorted(element); @@ -74,11 +70,11 @@ public final class SortContentAction extends PsiElementBaseIntentionAction { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiElement element) { for (Sortable sortable : Holder.OUR_SORTABLES) { - if (sortable.isAvailable(element)) return true; + if (sortable.isAvailable(element)) return Presentation.of(getFamilyName()); } - return false; + return null; } private interface SortingStrategy { diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java index 46d4f16967dc..fec2f9998723 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java @@ -1,19 +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 com.intellij.codeInsight.intention.impl; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.codeInspection.PsiUpdateModCommandAction; import com.intellij.java.JavaBundle; -import com.intellij.lang.java.JavaLanguage; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; import com.siyeh.ig.psiutils.ExpressionUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -public class SplitDeclarationAction extends PsiElementBaseIntentionAction { +public class SplitDeclarationAction extends PsiUpdateModCommandAction { + public SplitDeclarationAction() { + super(PsiDeclarationStatement.class); + } + @Override @NotNull public String getFamilyName() { @@ -21,14 +24,13 @@ public class SplitDeclarationAction extends PsiElementBaseIntentionAction { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - if (element instanceof PsiCompiledElement) return false; - if (!canModify(element)) return false; - if (!element.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return false; - - final PsiDeclarationStatement - context = PsiTreeUtil.getParentOfType(element, PsiDeclarationStatement.class, false, PsiClass.class, PsiCodeBlock.class); - return context != null && isAvailableOnDeclarationStatement(context); + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiDeclarationStatement element) { + if (PsiTreeUtil.getParentOfType(context.findLeaf(), PsiDeclarationStatement.class, false, PsiClass.class, PsiCodeBlock.class) + != element) { + return null; + } + return isAvailableOnDeclarationStatement(element) ? + Presentation.of(JavaBundle.message("intention.split.declaration.assignment.text")) : null; } private boolean isAvailableOnDeclarationStatement(PsiDeclarationStatement decl) { @@ -65,16 +67,11 @@ public class SplitDeclarationAction extends PsiElementBaseIntentionAction { parent = parent.getNextSibling(); } } - setText(JavaBundle.message("intention.split.declaration.assignment.text")); return true; } @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - final PsiDeclarationStatement decl = PsiTreeUtil.getParentOfType(element, PsiDeclarationStatement.class); - - if (decl != null) { - ExpressionUtils.splitDeclaration(decl, project); - } + protected void invoke(@NotNull ActionContext context, @NotNull PsiDeclarationStatement decl, @NotNull ModPsiUpdater updater) { + ExpressionUtils.splitDeclaration(decl, context.project()); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitFilterAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitFilterAction.java index 4e4196448aca..9695673d755a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitFilterAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitFilterAction.java @@ -1,18 +1,17 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.intention.impl; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.codeInspection.PsiUpdateModCommandAction; import com.intellij.java.JavaBundle; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.JavaPsiPatternUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.psiutils.VariableAccessUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; @@ -21,25 +20,29 @@ import java.util.List; import static com.intellij.codeInsight.intention.impl.SplitConditionUtil.getLOperands; import static com.intellij.codeInsight.intention.impl.SplitConditionUtil.getROperands; -public class SplitFilterAction extends PsiElementBaseIntentionAction { +public class SplitFilterAction extends PsiUpdateModCommandAction { private static final Logger LOG = Logger.getInstance(SplitFilterAction.class.getName()); + public SplitFilterAction() { + super(PsiJavaToken.class); + } + @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiJavaToken element) { final PsiPolyadicExpression expression = SplitConditionUtil.findCondition(element, true, false); - if (expression == null || expression.getOperands().length < 2) return false; + if (expression == null || expression.getOperands().length < 2) return null; PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent()); - if (!(parent instanceof PsiLambdaExpression)) return false; - if (((PsiLambdaExpression)parent).getParameterList().getParametersCount() != 1) return false; + if (!(parent instanceof PsiLambdaExpression lambda)) return null; + if (lambda.getParameterList().getParametersCount() != 1) return null; parent = PsiUtil.skipParenthesizedExprUp(parent.getParent()); - if (!(parent instanceof PsiExpressionList)) return false; + if (!(parent instanceof PsiExpressionList)) return null; final PsiElement gParent = parent.getParent(); - if (!(gParent instanceof PsiMethodCallExpression)) return false; - - return MergeFilterChainAction.isFilterCall((PsiMethodCallExpression)gParent) && - !hasPatternVariablesUsedAfterSplit(expression, element); + if (!(gParent instanceof PsiMethodCallExpression call)) return null; + if (!MergeFilterChainAction.isFilterCall(call) || hasPatternVariablesUsedAfterSplit(expression, element)) return null; + + return Presentation.of(JavaBundle.message("intention.split.filter.text")); } private static boolean hasPatternVariablesUsedAfterSplit(@NotNull PsiPolyadicExpression expression, @NotNull PsiElement token) { @@ -61,12 +64,6 @@ public class SplitFilterAction extends PsiElementBaseIntentionAction { return false; } - @NotNull - @Override - public String getText() { - return JavaBundle.message("intention.split.filter.text"); - } - @Override @NotNull public String getFamilyName() { @@ -74,8 +71,7 @@ public class SplitFilterAction extends PsiElementBaseIntentionAction { } @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { - final PsiJavaToken token = (PsiJavaToken)element; + protected void invoke(@NotNull ActionContext context, @NotNull PsiJavaToken token, @NotNull ModPsiUpdater updater) { final PsiPolyadicExpression expression = SplitConditionUtil.findCondition(token, true, false); final PsiLambdaExpression originalLambdaExpression = PsiTreeUtil.getParentOfType(expression, PsiLambdaExpression.class); @@ -89,8 +85,8 @@ public class SplitFilterAction extends PsiElementBaseIntentionAction { final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression(); LOG.assertTrue(qualifierExpression != null); - final PsiMethodCallExpression newFilterCall = (PsiMethodCallExpression) - JavaPsiFacade.getElementFactory(project).createExpressionFromText("a.filter(" + lambdaParameterName + " -> x)", methodCallExpression); + final PsiMethodCallExpression newFilterCall = (PsiMethodCallExpression)JavaPsiFacade.getElementFactory(context.project()) + .createExpressionFromText("a.filter(" + lambdaParameterName + " -> x)", methodCallExpression); final PsiLambdaExpression newFilterLambda = (PsiLambdaExpression)newFilterCall.getArgumentList().getExpressions()[0]; final PsiExpression filterCallQualifier = newFilterCall.getMethodExpression().getQualifierExpression(); LOG.assertTrue(filterCallQualifier != null); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitSwitchBranchWithSeveralCaseValuesAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitSwitchBranchWithSeveralCaseValuesAction.java index 7d8537643711..b9bed2b53816 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitSwitchBranchWithSeveralCaseValuesAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitSwitchBranchWithSeveralCaseValuesAction.java @@ -1,14 +1,15 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.intention.impl; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.codeInspection.ModCommands; import com.intellij.java.JavaBundle; -import com.intellij.openapi.editor.Editor; +import com.intellij.modcommand.ModCommand; +import com.intellij.modcommand.ModCommandAction; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.ObjectUtils; import com.siyeh.ig.psiutils.SwitchUtils; import org.jetbrains.annotations.Contract; @@ -24,7 +25,7 @@ import static com.intellij.psi.util.PsiTreeUtil.getNextSiblingOfType; import static com.intellij.psi.util.PsiTreeUtil.getPrevSiblingOfType; import static com.siyeh.ig.psiutils.ControlFlowUtils.statementMayCompleteNormally; -public class SplitSwitchBranchWithSeveralCaseValuesAction extends PsiElementBaseIntentionAction { +public class SplitSwitchBranchWithSeveralCaseValuesAction implements ModCommandAction { @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull @@ -34,23 +35,23 @@ public class SplitSwitchBranchWithSeveralCaseValuesAction extends PsiElementBase } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - PsiSwitchLabelStatementBase labelStatement = findLabelStatement(editor, element); - if (labelStatement == null || labelStatement.getEnclosingSwitchBlock() == null) return false; + public @Nullable Presentation getPresentation(@NotNull ActionContext context) { + PsiElement element = context.findLeaf(); + if (element == null) return null; + PsiSwitchLabelStatementBase labelStatement = findLabelStatement(context, element); + if (labelStatement == null || labelStatement.getEnclosingSwitchBlock() == null) return null; if (labelStatement instanceof PsiSwitchLabelStatement) { if (isMultiValueCase(labelStatement)) { // mixed syntax "case 1, 2: some code" if (isAvailableForLabel(labelStatement)) { - setText(JavaBundle.message("intention.split.switch.branch.with.several.case.values.split.text")); - return true; + return Presentation.of(JavaBundle.message("intention.split.switch.branch.with.several.case.values.split.text")); } } else if (hasSiblingLabel(labelStatement)) { // traditional syntax "case 1: case 2: some code" PsiSwitchLabelStatement lastSiblingLabel = findLastSiblingLabel(labelStatement, false); if (isAvailableForLabel(lastSiblingLabel)) { - setText(JavaBundle.message("intention.split.switch.branch.with.several.case.values.copy.text")); - return true; + return Presentation.of(JavaBundle.message("intention.split.switch.branch.with.several.case.values.copy.text")); } } } @@ -59,12 +60,11 @@ public class SplitSwitchBranchWithSeveralCaseValuesAction extends PsiElementBase if (isMultiValueCase(labelStatement)) { PsiStatement body = ruleStatement.getBody(); if (body != null && element.getTextOffset() < body.getTextOffset()) { - setText(JavaBundle.message("intention.split.switch.branch.with.several.case.values.split.text")); - return true; + return Presentation.of(JavaBundle.message("intention.split.switch.branch.with.several.case.values.split.text")); } } } - return false; + return null; } private static boolean isAvailableForLabel(@Nullable PsiSwitchLabelStatementBase label) { @@ -87,25 +87,31 @@ public class SplitSwitchBranchWithSeveralCaseValuesAction extends PsiElementBase * Handle the case where the caret is on the right side of the element we're interested in */ @Nullable - private static PsiElement getPreviousElement(@NotNull Editor editor, @NotNull PsiElement element) { - PsiFile file = element.getContainingFile(); - int caretOffset = editor.getCaretModel().getOffset(); + private static PsiElement getPreviousElement(@NotNull ActionContext context, @NotNull PsiElement element) { + int caretOffset = context.offset(); int elementOffset = element.getTextRange().getStartOffset(); if (caretOffset == elementOffset && caretOffset > 0) { - return file.findElementAt(caretOffset - 1); + return context.findLeafOnTheLeft(); } return null; } @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { - PsiSwitchLabelStatementBase statement = findLabelStatement(editor, element); + public @NotNull ModCommand perform(@NotNull ActionContext context) { + return ModCommands.psiUpdate(context, updater -> invoke(context, updater)); + } + + private static void invoke(@NotNull ActionContext context, @NotNull ModPsiUpdater updater) { + context = context.withFile(updater.getWritable(context.file())); + PsiElement element = context.findLeaf(); + if (element == null) return; + PsiSwitchLabelStatementBase statement = findLabelStatement(context, element); PsiElement result = null; if (statement instanceof PsiSwitchLabelStatement labelStatement) { PsiCaseLabelElementList labelElementList = labelStatement.getCaseLabelElementList(); if (labelElementList != null && labelElementList.getElementCount() > 1) { - PsiCaseLabelElement labelElement = findLabelElement(element, labelElementList, editor); + PsiCaseLabelElement labelElement = findLabelElement(element, labelElementList, context); Branch branch = Branch.fromLabel(labelStatement); if (branch != null) { if (isInList(labelElement, labelElementList)) { @@ -132,7 +138,7 @@ public class SplitSwitchBranchWithSeveralCaseValuesAction extends PsiElementBase else if (statement instanceof PsiSwitchLabeledRuleStatement labeledRule) { PsiCaseLabelElementList labelElementList = labeledRule.getCaseLabelElementList(); if (labelElementList != null) { - PsiCaseLabelElement labelElement = findLabelElement(element, labelElementList, editor); + PsiCaseLabelElement labelElement = findLabelElement(element, labelElementList, context); if (isInList(labelElement, labelElementList)) { result = moveRuleAfter(labelElement, labeledRule); } @@ -142,16 +148,16 @@ public class SplitSwitchBranchWithSeveralCaseValuesAction extends PsiElementBase } } if (result != null) { - editor.getCaretModel().moveToOffset(result.getTextOffset()); + updater.moveTo(result); } } private static PsiCaseLabelElement findLabelElement(@NotNull PsiElement element, @NotNull PsiCaseLabelElementList labelElementList, - @NotNull Editor editor) { + @NotNull ActionContext context) { PsiCaseLabelElement labelElement = PsiTreeUtil.getNonStrictParentOfType(element, PsiCaseLabelElement.class); if (!isInList(labelElement, labelElementList)) { - PsiElement previousElement = getPreviousElement(editor, element); + PsiElement previousElement = getPreviousElement(context, element); labelElement = PsiTreeUtil.getNonStrictParentOfType(previousElement, PsiCaseLabelElement.class); } PsiElement caseLabel = PsiTreeUtil.findFirstParent(labelElement, parent -> @@ -166,14 +172,12 @@ public class SplitSwitchBranchWithSeveralCaseValuesAction extends PsiElementBase } @Nullable - private static PsiSwitchLabelStatementBase findLabelStatement(@NotNull Editor editor, - @NotNull PsiElement element) { - // Can't use BaseElementAtCaretIntentionAction, because there's ambiguity when the caret is after the list of case values before the arrow + private static PsiSwitchLabelStatementBase findLabelStatement(@NotNull ActionContext context, PsiElement element) { PsiStatement statement = PsiTreeUtil.getParentOfType(element, PsiStatement.class); if (statement instanceof PsiSwitchLabelStatementBase labelStatement) { return labelStatement; } - PsiElement previousElement = getPreviousElement(editor, element); + PsiElement previousElement = getPreviousElement(context, element); statement = PsiTreeUtil.getParentOfType(previousElement, PsiStatement.class); return ObjectUtils.tryCast(statement, PsiSwitchLabelStatementBase.class); } diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/WrapWithUnmodifiableAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/WrapWithUnmodifiableAction.java index 06d42f9b0fde..14ebe55ed03d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/WrapWithUnmodifiableAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/WrapWithUnmodifiableAction.java @@ -1,19 +1,17 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.intention.impl; +import com.intellij.codeInspection.PsiUpdateModCommandAction; import com.intellij.codeInspection.dataFlow.CommonDataflow; import com.intellij.codeInspection.dataFlow.Mutability; import com.intellij.codeInspection.dataFlow.types.DfType; import com.intellij.java.JavaBundle; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import com.siyeh.ig.psiutils.CommentTracker; import com.siyeh.ig.psiutils.ExpectedTypeUtils; @@ -28,7 +26,7 @@ import java.util.Set; import static com.intellij.psi.CommonClassNames.*; import static com.intellij.util.ObjectUtils.tryCast; -public class WrapWithUnmodifiableAction extends BaseIntentionAction { +public class WrapWithUnmodifiableAction extends PsiUpdateModCommandAction { private static final String JAVA_UTIL_SORTED_MAP = "java.util.SortedMap"; private static final Map CLASS_TO_METHOD = Map.of( @@ -38,42 +36,32 @@ public class WrapWithUnmodifiableAction extends BaseIntentionAction { JAVA_UTIL_SORTED_MAP, "unmodifiableSortedMap", JAVA_UTIL_MAP, "unmodifiableMap" ); + + public WrapWithUnmodifiableAction() { + super(PsiExpression.class); + } @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - if (editor == null || file == null || !canModify(file)) { - return; - } - PsiExpression expression = getParentExpression(editor, file); - if (expression != null) { - PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(expression.getType()); - if (psiClass != null) { + protected void invoke(@NotNull ActionContext context, @NotNull PsiExpression element, @NotNull ModPsiUpdater updater) { + PsiExpression expression = getParentExpression(element); + PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(expression.getType()); + if (psiClass != null) { - PsiClass expectedClass = PsiUtil.resolveClassInClassTypeOnly(getExpectedType(expression)); - if (expectedClass != null) { - String collectionClass = findSuperClass(psiClass, expectedClass, CLASS_TO_METHOD.keySet()); - if (collectionClass != null) { - String method = CLASS_TO_METHOD.get(collectionClass); - wrapWith(expression, method); - } + PsiClass expectedClass = PsiUtil.resolveClassInClassTypeOnly(getExpectedType(expression)); + if (expectedClass != null) { + String collectionClass = findSuperClass(psiClass, expectedClass, CLASS_TO_METHOD.keySet()); + if (collectionClass != null) { + String method = CLASS_TO_METHOD.get(collectionClass); + wrapWith(expression, method); } } } } - @Nullable - private static PsiExpression getParentExpression(@NotNull Editor editor, @NotNull PsiFile file) { - PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); - PsiExpression expression = PsiTreeUtil.getNonStrictParentOfType(element, PsiExpression.class); - if (expression == null) { - element = file.findElementAt(editor.getCaretModel().getOffset() - 1); - expression = PsiTreeUtil.getNonStrictParentOfType(element, PsiExpression.class); - } - if (expression != null) { - PsiMethodCallExpression methodCall = tryCast(expression.getParent(), PsiMethodCallExpression.class); - if (methodCall != null && methodCall.getMethodExpression() == expression) { - return methodCall; - } + private static @NotNull PsiExpression getParentExpression(@NotNull PsiExpression expression) { + PsiMethodCallExpression methodCall = tryCast(expression.getParent(), PsiMethodCallExpression.class); + if (methodCall != null && methodCall.getMethodExpression() == expression) { + return methodCall; } return expression; } @@ -86,32 +74,26 @@ public class WrapWithUnmodifiableAction extends BaseIntentionAction { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - if (editor == null || file == null || !canModify(file)) { - return false; - } - PsiExpression expression = getParentExpression(editor, file); - if (expression != null) { - if (PsiUtil.isOnAssignmentLeftHand(expression)) return false; - PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(expression.getType()); - if (psiClass != null) { - PsiClass expectedClass = PsiUtil.resolveClassInClassTypeOnly(getExpectedType(expression)); + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiExpression element) { + PsiExpression expression = getParentExpression(element); + if (PsiUtil.isOnAssignmentLeftHand(expression)) return null; + PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(expression.getType()); + if (psiClass != null) { + PsiClass expectedClass = PsiUtil.resolveClassInClassTypeOnly(getExpectedType(expression)); - if (expectedClass != null) { - String collectionClass = findSuperClass(psiClass, expectedClass, CLASS_TO_METHOD.keySet()); - if (collectionClass != null && !isUnmodifiable(expression)) { - String message = switch (collectionClass) { - case JAVA_UTIL_LIST -> "intention.wrap.with.unmodifiable.list"; - case JAVA_UTIL_SET, JAVA_UTIL_SORTED_SET -> "intention.wrap.with.unmodifiable.set"; - default -> "intention.wrap.with.unmodifiable.map"; - }; - setText(JavaBundle.message(message)); - return true; - } + if (expectedClass != null) { + String collectionClass = findSuperClass(psiClass, expectedClass, CLASS_TO_METHOD.keySet()); + if (collectionClass != null && !isUnmodifiable(expression)) { + String message = switch (collectionClass) { + case JAVA_UTIL_LIST -> "intention.wrap.with.unmodifiable.list"; + case JAVA_UTIL_SET, JAVA_UTIL_SORTED_SET -> "intention.wrap.with.unmodifiable.set"; + default -> "intention.wrap.with.unmodifiable.map"; + }; + return Presentation.of(JavaBundle.message(message)); } } } - return false; + return null; } private static PsiType getExpectedType(@NotNull PsiExpression expression) { diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java index 607b0a5dc545..ac0472575aee 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java @@ -277,7 +277,7 @@ public final class QuickFixFactoryImpl extends QuickFixFactory { @NotNull @Override public IntentionAction createDeleteCatchFix(@NotNull PsiParameter parameter) { - return new DeleteCatchFix(parameter); + return new DeleteCatchFix(parameter).asIntention(); } @NotNull @@ -295,7 +295,7 @@ public final class QuickFixFactoryImpl extends QuickFixFactory { @NotNull @Override public IntentionAction createNegationBroadScopeFix(@NotNull PsiPrefixExpression expr) { - return new NegationBroadScopeFix(expr); + return new NegationBroadScopeFix(expr).asIntention(); } @NotNull @@ -319,7 +319,7 @@ public final class QuickFixFactoryImpl extends QuickFixFactory { @NotNull @Override public IntentionAction createMoveCatchUpFix(@NotNull PsiCatchSection section, @NotNull PsiCatchSection section1) { - return new MoveCatchUpFix(section, section1); + return new MoveCatchUpFix(section, section1).asIntention(); } @NotNull @@ -780,7 +780,7 @@ public final class QuickFixFactoryImpl extends QuickFixFactory { @Override public @NotNull IntentionAction createDeleteFix(@NotNull PsiElement @NotNull ... elements) { - return new DeleteElementFix.DeleteMultiFix(elements); + return new DeleteElementFix.DeleteMultiFix(elements).asIntention(); } @NotNull @@ -1001,7 +1001,7 @@ public final class QuickFixFactoryImpl extends QuickFixFactory { @NotNull @Override public IntentionAction createWrapSwitchRuleStatementsIntoBlockFix(@NotNull PsiSwitchLabeledRuleStatement rule) { - return new WrapSwitchRuleStatementsIntoBlockFix(rule); + return new WrapSwitchRuleStatementsIntoBlockFix(rule).asIntention(); } @NotNull @@ -1061,7 +1061,7 @@ public final class QuickFixFactoryImpl extends QuickFixFactory { @Override public @NotNull IntentionAction createMoveMemberIntoClassFix(@NotNull PsiErrorElement errorElement) { - return new MoveMemberIntoClassFix(errorElement); + return new MoveMemberIntoClassFix(errorElement).asIntention(); } @Override @@ -1192,7 +1192,7 @@ public final class QuickFixFactoryImpl extends QuickFixFactory { @Override public @NotNull IntentionAction createSplitSwitchBranchWithSeveralCaseValuesAction() { - return new SplitSwitchBranchWithSeveralCaseValuesAction(); + return new SplitSwitchBranchWithSeveralCaseValuesAction().asIntention(); } @Override @@ -1202,6 +1202,6 @@ public final class QuickFixFactoryImpl extends QuickFixFactory { @Override public @NotNull IntentionAction createDeleteFix(@NotNull PsiElement @NotNull [] elements, @NotNull @Nls String text) { - return new DeleteElementFix.DeleteMultiFix(elements, text); + return new DeleteElementFix.DeleteMultiFix(elements, text).asIntention(); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java index 8a4e060b153d..430f2509ea84 100644 --- a/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java +++ b/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java @@ -247,7 +247,7 @@ public class VariableLookupItem extends LookupItem implements Typed if (fix != null) { ModCommandAction.ActionContext actionContext = ModCommandAction.ActionContext.from(context.getEditor(), context.getFile()); if (fix.getPresentation(actionContext) != null) { - ModCommandService.getInstance().executeInteractively(actionContext, fix.perform(actionContext)); + ModCommandService.getInstance().executeInteractively(actionContext, fix.perform(actionContext), context.getEditor()); } } } diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocBlankLinesInspection.java b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocBlankLinesInspection.java index 77bfe9c9429d..bbe366a3d010 100644 --- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocBlankLinesInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavadocBlankLinesInspection.java @@ -92,6 +92,12 @@ public class JavadocBlankLinesInspection extends LocalInspectionTool { return null; } + /** + * Check if the given text starts with an HTML block tag. + * + * @param text the text to check + * @return true if the text starts with an HTML block tag, false otherwise + */ private static boolean startsWithHtmlBlockTag(String text) { String startTag = HtmlUtil.getStartTag(text); if (startTag == null) return false; diff --git a/java/java-impl/src/com/intellij/internal/statistic/LibraryNameValidationRule.kt b/java/java-impl/src/com/intellij/internal/statistic/LibraryNameValidationRule.kt index 08f7a2ad0288..627208c9c947 100644 --- a/java/java-impl/src/com/intellij/internal/statistic/LibraryNameValidationRule.kt +++ b/java/java-impl/src/com/intellij/internal/statistic/LibraryNameValidationRule.kt @@ -12,7 +12,7 @@ import com.intellij.internal.statistic.libraryUsage.LibraryUsageDescriptors *
* See 'library-jar-statistics.xml' and 'library-usage-statistics.xml' files. */ -internal class LibraryNameValidationRule : CustomValidationRule() { +class LibraryNameValidationRule : CustomValidationRule() { override fun getRuleId(): String = "used_library_name" override fun doValidate(data: String, context: EventContext): ValidationResultType { diff --git a/java/java-impl/src/com/intellij/internal/statistic/libraryUsage/LibraryUsageDescriptors.kt b/java/java-impl/src/com/intellij/internal/statistic/libraryUsage/LibraryUsageDescriptors.kt index 6a9f12a556d7..3a429e27d51d 100644 --- a/java/java-impl/src/com/intellij/internal/statistic/libraryUsage/LibraryUsageDescriptors.kt +++ b/java/java-impl/src/com/intellij/internal/statistic/libraryUsage/LibraryUsageDescriptors.kt @@ -8,7 +8,7 @@ import com.intellij.util.xmlb.annotations.Property import com.intellij.util.xmlb.annotations.Tag import com.intellij.util.xmlb.annotations.XCollection -internal object LibraryUsageDescriptors { +object LibraryUsageDescriptors { private val descriptors: List = downloadLibraryDescriptors() private val libraryDescriptorFinder: LibraryLayer = LibraryLayer.create(downloadLibraryDescriptors()) diff --git a/java/java-runtime/intellij.java.rt.iml b/java/java-runtime/intellij.java.rt.iml index 0b01b18adbcb..0869ffe6bdd4 100644 --- a/java/java-runtime/intellij.java.rt.iml +++ b/java/java-runtime/intellij.java.rt.iml @@ -13,7 +13,16 @@ - + + + + ebe592c9af9fdb6c55f0e6c6fabc76f6e0eec8efdec535398e86c3a883687ebf + + + 25eb5926c975ac6f4126feeb9d004f53f9ebf07dc117f5db9958a6bfb3110783 + + + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinalJava10/afterInsideWhenExpression.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/afterInsideWhenExpression.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinalJava10/afterInsideWhenExpression.java rename to java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/afterInsideWhenExpression.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinalJava10/beforeInsideWhenExpression.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/beforeInsideWhenExpression.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinalJava10/beforeInsideWhenExpression.java rename to java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/beforeInsideWhenExpression.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/negationBroadScope/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/negationBroadScope/after1.java index 518a8eeb3e63..0ace2c15e091 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/negationBroadScope/after1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/negationBroadScope/after1.java @@ -1,6 +1,6 @@ // "Change to '!(1 == 1)'" "true-preview" public class Foo { void task() { - if (!(1 == 1)) {} + if (!(1 == 1)) {} } } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/CopyReferenceActionFilesTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInsight/CopyReferenceActionFilesTest.groovy deleted file mode 100644 index 4fb406199191..000000000000 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/CopyReferenceActionFilesTest.groovy +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.java.codeInsight - -import com.intellij.codeInsight.JavaCodeInsightTestCase -import com.intellij.ide.actions.CopyReferenceAction -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.module.JavaModuleType -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vfs.VirtualFileManager -import com.intellij.psi.PsiManager -import com.intellij.testFramework.PsiTestUtil -import groovy.transform.CompileStatic - -@CompileStatic -class CopyReferenceActionFilesTest extends JavaCodeInsightTestCase { - VirtualFile additionalRoot - - @Override - protected void setUp() throws Exception { - super.setUp() - getModule().setModuleType(JavaModuleType.getModuleType().getId()) - ApplicationManager.application.runWriteAction(new Runnable() { - @Override - void run() { - additionalRoot = VirtualFileManager.getInstance().findFileByUrl("temp:///").createChildDirectory(this, "newRoot") - } - }) - } - - @Override - protected void tearDown() throws Exception { - try { - ApplicationManager.application.runWriteAction(new Runnable() { - @Override - void run() { - additionalRoot.delete(this) - } - }) - } - finally { - super.tearDown() - } - } - - void testCopyFile_RegisteredAsSourceRoots_ShouldContainItsName() throws Exception { - // CPP-4315 "Edit | Copy Reference" result doesn't contain the file name - - VirtualFile dir - VirtualFile dir_subfile - VirtualFile file - - ApplicationManager.application.runWriteAction(new Runnable() { - @Override - void run() { - dir = additionalRoot.createChildDirectory(this, "dir") - dir_subfile = dir.createChildData(this, "dir_subfile.txt") - file = additionalRoot.createChildData(this, "file.txt") - - PsiTestUtil.addContentRoot(getModule(), additionalRoot) - PsiTestUtil.addSourceRoot(getModule(), dir) - PsiTestUtil.addSourceRoot(getModule(), file) - } - }) - - assertEquals("dir", CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findDirectory(dir))) - assertEquals("dir_subfile.txt", CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findFile(dir_subfile))) - assertEquals("file.txt", CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findFile(file))) - } - - void testCopyFile_RegisteredAsContentRoot_ShouldContainItsFullPath() throws Exception { - // IDEA-144300 Copy Reference for source folder/content root copies empty string - - VirtualFile dir - VirtualFile dir_subfile - VirtualFile file - - ApplicationManager.application.runWriteAction(new Runnable() { - @Override - void run() { - dir = additionalRoot.createChildDirectory(this, "dir") - dir_subfile = dir.createChildData(this, "dir_subfile.txt") - file = additionalRoot.createChildData(this, "file.txt") - - PsiTestUtil.addContentRoot(getModule(), dir) - PsiTestUtil.addContentRoot(getModule(), file) - } - }) - - assertEquals(dir.getPath(), CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findDirectory(dir))) - assertEquals("dir_subfile.txt", CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findFile(dir_subfile))) - assertEquals(file.getPath(), CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findFile(file))) - } - - void testCopyFile_RegisteredAsNestedContentRoot_ShouldContainPathFromOuterMostRoot() throws Exception { - // IDEA-144300 Copy Reference for source folder/content root copies empty string - - VirtualFile dir - VirtualFile dir_dir - VirtualFile dir_dir_file - - ApplicationManager.application.runWriteAction(new Runnable() { - @Override - void run() { - dir = additionalRoot.createChildDirectory(this, "dir") - dir_dir = dir.createChildDirectory(this, "dir_dir") - dir_dir_file = dir_dir.createChildData(this, "file.txt") - - PsiTestUtil.addContentRoot(getModule(), dir) - PsiTestUtil.addContentRoot(getModule(), dir_dir) - } - }) - - assertEquals(dir.getPath(), CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findDirectory(dir))) - assertEquals("dir_dir", CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findDirectory(dir_dir))) - assertEquals("dir_dir/file.txt", CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findFile(dir_dir_file))) - } - - void testCopyFile_UnderExcludeRoot_ShouldContainPathFromTheCorrespondingContentRoot() throws Exception { - // IDEA-144316 Copy Reference should work for excluded subfolders same way as it works for regular project subdirs - - VirtualFile dir - VirtualFile dir_dir - VirtualFile dir_dir_file - - ApplicationManager.application.runWriteAction(new Runnable() { - @Override - void run() { - dir = additionalRoot.createChildDirectory(this, "dir") - dir_dir = dir.createChildDirectory(this, "dir_dir") - dir_dir_file = dir_dir.createChildData(this, "file.txt") - - PsiTestUtil.addContentRoot(getModule(), dir) - PsiTestUtil.addExcludedRoot(getModule(), dir_dir) - } - }) - - assertEquals(dir.getPath(), CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findDirectory(dir))) - assertEquals("dir_dir", CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findDirectory(dir_dir))) - assertEquals("dir_dir/file.txt", CopyReferenceAction.elementToFqn(PsiManager.getInstance(project).findFile(dir_dir_file))) - } -} diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/CopyReferenceActionFilesTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInsight/CopyReferenceActionFilesTest.kt new file mode 100644 index 000000000000..927212bfef8b --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/CopyReferenceActionFilesTest.kt @@ -0,0 +1,151 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.java.codeInsight + +import com.intellij.ide.actions.CopyReferenceAction +import com.intellij.openapi.application.readAction +import com.intellij.openapi.application.writeAction +import com.intellij.openapi.module.JavaModuleType +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleTypeId +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiManager +import com.intellij.testFramework.PsiTestUtil +import com.intellij.testFramework.junit5.TestApplication +import com.intellij.testFramework.rules.ProjectModelExtension +import kotlinx.coroutines.runBlocking +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.RegisterExtension + +@TestApplication +class CopyReferenceActionFilesTest { + @JvmField + @RegisterExtension + val projectModel: ProjectModelExtension = ProjectModelExtension() + + lateinit var module: Module + lateinit var rootDir: VirtualFile + + private val psiManager: PsiManager + get() = PsiManager.getInstance(projectModel.project) + + @BeforeEach + fun setUp() = runBlocking { + writeAction { + rootDir = projectModel.baseProjectDir.newVirtualDirectory("root") + module = projectModel.createModule() + module.setModuleType(JavaModuleType.getModuleType().id) + } + } + + @Test + fun `reference to file registered as source root must contain its name`() = runBlocking { + // CPP-4315 "Edit | Copy Reference" result doesn't contain the file name + lateinit var dir: VirtualFile + lateinit var dirSubFile: VirtualFile + lateinit var file: VirtualFile + writeAction { + dir = rootDir.createChildDirectory(this, "dir") + dirSubFile = dir.createChildData(this, "dir_subfile.txt") + file = rootDir.createChildData(this, "file.txt") + PsiTestUtil.addContentRoot(module, rootDir) + PsiTestUtil.addSourceRoot(module, dir) + PsiTestUtil.addSourceRoot(module, file) + } + readAction { + assertEquals("dir", CopyReferenceAction.elementToFqn(psiManager.findDirectory(dir))) + assertEquals("dir_subfile.txt", CopyReferenceAction.elementToFqn(psiManager.findFile(dirSubFile))) + assertEquals("file.txt", CopyReferenceAction.elementToFqn(psiManager.findFile(file))) + } + } + + @Test + fun `reference to file under non-java source root must include path from content root`() = runBlocking { + lateinit var file: VirtualFile + writeAction { + module.setModuleType(ModuleTypeId.WEB_MODULE) + val sourceRoot = rootDir.createChildDirectory(this, "src") + PsiTestUtil.addContentRoot(module, rootDir) + PsiTestUtil.addSourceRoot(module, sourceRoot) + file = sourceRoot.createChildData(this, "file.txt") + } + readAction { + assertEquals("src/file.txt", CopyReferenceAction.elementToFqn(psiManager.findFile(file))) + } + } + + @Test + fun `reference to file registered as content root must contain its full path`() = runBlocking { + // IDEA-144300 Copy Reference for source folder/content root copies empty string + lateinit var dir: VirtualFile + lateinit var dirSubFile: VirtualFile + lateinit var file: VirtualFile + writeAction { + dir = rootDir.createChildDirectory(this, "dir") + dirSubFile = dir.createChildData(this, "dir_subfile.txt") + file = rootDir.createChildData(this, "file.txt") + PsiTestUtil.addContentRoot(module, dir) + PsiTestUtil.addContentRoot(module, file) + } + readAction { + assertEquals(dir.getPath(), CopyReferenceAction.elementToFqn(psiManager.findDirectory(dir))) + assertEquals("dir_subfile.txt", CopyReferenceAction.elementToFqn(psiManager.findFile(dirSubFile))) + assertEquals(file.getPath(), CopyReferenceAction.elementToFqn(psiManager.findFile(file))) + } + } + + @Test + fun `reference to file registered as nested content root must contain path from outer most root`() = runBlocking { + // IDEA-144300 Copy Reference for source folder/content root copies empty string + lateinit var dir: VirtualFile + lateinit var dirDir: VirtualFile + lateinit var dirDirFile: VirtualFile + writeAction { + dir = rootDir.createChildDirectory(this, "dir") + dirDir = dir.createChildDirectory(this, "dir_dir") + dirDirFile = dirDir.createChildData(this, "file.txt") + PsiTestUtil.addContentRoot(module, dir) + PsiTestUtil.addContentRoot(module, dirDir) + } + readAction { + assertEquals(dir.getPath(), CopyReferenceAction.elementToFqn(psiManager.findDirectory(dir))) + assertEquals("dir_dir", CopyReferenceAction.elementToFqn(psiManager.findDirectory(dirDir))) + assertEquals("dir_dir/file.txt", CopyReferenceAction.elementToFqn(psiManager.findFile(dirDirFile))) + } + } + + @Test + fun `reference to file under exclude root must contain path from the corresponding content root`() = runBlocking { + // IDEA-144316 Copy Reference should work for excluded subfolders same way as it works for regular project subdirs + lateinit var dir: VirtualFile + lateinit var dirDir: VirtualFile + lateinit var dirDirFile: VirtualFile + writeAction { + dir = rootDir.createChildDirectory(this, "dir") + dirDir = dir.createChildDirectory(this, "dir_dir") + dirDirFile = dirDir.createChildData(this, "file.txt") + PsiTestUtil.addContentRoot(module, dir) + PsiTestUtil.addExcludedRoot(module, dirDir) + } + readAction { + assertEquals(dir.getPath(), CopyReferenceAction.elementToFqn(psiManager.findDirectory(dir))) + assertEquals("dir_dir", CopyReferenceAction.elementToFqn(psiManager.findDirectory(dirDir))) + assertEquals("dir_dir/file.txt", CopyReferenceAction.elementToFqn(psiManager.findFile(dirDirFile))) + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/intention/SplitIfActionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/intention/SplitIfActionTest.java index 95df984cfd3e..9ffef309b922 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/intention/SplitIfActionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/intention/SplitIfActionTest.java @@ -97,6 +97,6 @@ public class SplitIfActionTest extends LightJavaCodeInsightTestCase { ModCommandAction.ActionContext context = ModCommandAction.ActionContext.from(getEditor(), getFile()); assertNotNull(action.getPresentation(context)); ModCommand command = action.perform(context); - ApplicationManager.getApplication().runWriteAction(() -> ModCommandService.getInstance().executeInteractively(context, command)); + ApplicationManager.getApplication().runWriteAction(() -> ModCommandService.getInstance().executeInteractively(context, command, getEditor())); } } diff --git a/java/openapi/resources/messages/JavaBundle.properties b/java/openapi/resources/messages/JavaBundle.properties index 21794e49c34a..f170946c2a05 100644 --- a/java/openapi/resources/messages/JavaBundle.properties +++ b/java/openapi/resources/messages/JavaBundle.properties @@ -820,8 +820,8 @@ intention.extract.if.condition.text=Extract if ({0}) intention.extract.map.step.family=Extract to separate mapping method intention.extract.map.step.text=Extract variable ''{0}'' to ''{1}'' operation intention.extract.method.text=Extract method -intention.extract.set.from.comparison.chain.duplicates={0} has detected {1} code {1,choice,1#fragment|2#fragments} in this class that can be replaced using newly created Set. Would you like to replace {1,choice,1#it|2#them}? intention.extract.set.from.comparison.chain.family=Extract Set from comparison chain +intention.extract.set.from.comparison.chain.popup.title=Extract Set from Comparison Chain intention.family.add.javadoc=Add Javadoc intention.family.copy.abstract.method.implementation=Copy abstract method implementation intention.family.create.a.class.in.package=Create a class in package @@ -1866,4 +1866,6 @@ delete.initializer.completely=Delete initializer completely delete.assignment.completely=Delete assignment completely popup.title.remove.unused.variable=Remove Unused Variable intention.family.name.extract.possible.side.effects=Extract possible side effects -intention.family.name.delete.possible.side.effects=Delete possible side effects \ No newline at end of file +intention.family.name.delete.possible.side.effects=Delete possible side effects +intention.extract.set.from.comparison.chain.replace.only.this=Replace only this occurrence +intention.extract.set.from.comparison.chain.replace.all=Replace all occurrences \ No newline at end of file diff --git a/java/performancePlugin/src/com/intellij/java/performancePlugin/BuildCommand.java b/java/performancePlugin/src/com/intellij/java/performancePlugin/BuildCommand.java index e008cfcc360d..b18b5b257626 100644 --- a/java/performancePlugin/src/com/intellij/java/performancePlugin/BuildCommand.java +++ b/java/performancePlugin/src/com/intellij/java/performancePlugin/BuildCommand.java @@ -1,3 +1,4 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.java.performancePlugin; import com.intellij.openapi.application.ApplicationManager; @@ -9,6 +10,7 @@ import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Ref; import com.intellij.task.ModuleBuildTask; import com.intellij.task.ProjectTaskManager; +import com.intellij.task.impl.ProjectTaskManagerImpl; import com.intellij.util.messages.MessageBusConnection; import com.jetbrains.performancePlugin.PerformanceTestSpan; import com.jetbrains.performancePlugin.PerformanceTestingBundle; @@ -71,6 +73,7 @@ public class BuildCommand extends AbstractCommand { }); ApplicationManager.getApplication().invokeLater(() -> { + ProjectTaskManagerImpl.putBuildOriginator(project, this.getClass()); ProjectTaskManager instance = ProjectTaskManager.getInstance(project); Promise promise = null; spanRef.set(span.startSpan()); diff --git a/java/performancePlugin/src/com/intellij/java/performancePlugin/CreateJavaFileCommand.kt b/java/performancePlugin/src/com/intellij/java/performancePlugin/CreateJavaFileCommand.kt index 19eacc569e37..5b1d537ccbb2 100644 --- a/java/performancePlugin/src/com/intellij/java/performancePlugin/CreateJavaFileCommand.kt +++ b/java/performancePlugin/src/com/intellij/java/performancePlugin/CreateJavaFileCommand.kt @@ -5,6 +5,7 @@ import com.intellij.core.JavaPsiBundle.message import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.guessProjectDir import com.intellij.openapi.ui.playback.PlaybackContext +import com.intellij.openapi.vfs.findDirectory import com.intellij.platform.diagnostic.telemetry.helpers.useWithScope import com.intellij.psi.JavaDirectoryService import com.intellij.psi.impl.file.PsiJavaDirectoryFactory @@ -38,8 +39,8 @@ class CreateJavaFileCommand(text: String, line: Int) : PerformanceCommandCorouti val directory = PsiJavaDirectoryFactory .getInstance(context.project) .createDirectory( - (context.project.guessProjectDir() ?: throw RuntimeException("'guessProjectDir' dir returned 'null'")) - .findFileByRelativePath(filePath) ?: throw RuntimeException("Can't find file $filePath") + (context.project.guessProjectDir() ?: throw RuntimeException("Root of the project was not found")) + .findDirectory(filePath) ?: throw RuntimeException("Can't find file $filePath") ) val templateName = POSSIBLE_FILE_TYPES[fileType.lowercase()] diff --git a/jps/jps-builders/intellij.platform.jps.build.iml b/jps/jps-builders/intellij.platform.jps.build.iml index b1a5c24def32..60638da7cf25 100644 --- a/jps/jps-builders/intellij.platform.jps.build.iml +++ b/jps/jps-builders/intellij.platform.jps.build.iml @@ -44,7 +44,13 @@ - + + + + c28db4602da9f3817a59de9be137c1f6083a9cb95fa1781f54eda75763a95c67 + + + diff --git a/json/src/com/intellij/json/intentions/JsonSortPropertiesIntention.kt b/json/src/com/intellij/json/intentions/JsonSortPropertiesIntention.kt index 2569ad189afe..efc785fb1923 100644 --- a/json/src/com/intellij/json/intentions/JsonSortPropertiesIntention.kt +++ b/json/src/com/intellij/json/intentions/JsonSortPropertiesIntention.kt @@ -1,10 +1,11 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.json.intentions +import com.intellij.codeInsight.intention.BaseElementAtCaretIntentionAction import com.intellij.codeInsight.intention.LowPriorityAction -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction import com.intellij.ide.lightEdit.LightEditCompatible import com.intellij.json.JsonBundle +import com.intellij.json.psi.JsonFile import com.intellij.json.psi.JsonObject import com.intellij.json.psi.JsonProperty import com.intellij.json.psi.impl.JsonRecursiveElementVisitor @@ -19,7 +20,7 @@ import com.intellij.refactoring.util.CommonRefactoringUtil import com.intellij.util.IncorrectOperationException import org.jetbrains.annotations.Nls -open class JsonSortPropertiesIntention : PsiElementBaseIntentionAction(), LowPriorityAction, LightEditCompatible, DumbAware { +open class JsonSortPropertiesIntention : BaseElementAtCaretIntentionAction(), LowPriorityAction, LightEditCompatible, DumbAware { override fun getText(): @Nls(capitalization = Nls.Capitalization.Sentence) String = JsonBundle.message("json.intention.sort.properties") override fun getFamilyName(): @Nls(capitalization = Nls.Capitalization.Sentence) String = @@ -65,9 +66,9 @@ open class JsonSortPropertiesIntention : PsiElementBaseIntentionAction(), LowPri } private fun collectObjects(rootObj: JsonObject): Set { - val result : MutableSet = LinkedHashSet() + val result: MutableSet = LinkedHashSet() if (selectionModel.hasSelection()) { - object: JsonRecursiveElementVisitor() { + object : JsonRecursiveElementVisitor() { override fun visitObject(o: JsonObject) { super.visitObject(o) if (o.textRange?.intersects(selectionModel.selectionStart, selectionModel.selectionEnd) == true) { @@ -81,7 +82,10 @@ open class JsonSortPropertiesIntention : PsiElementBaseIntentionAction(), LowPri } private fun findRootObject(): JsonObject? { - val initObj = PsiTreeUtil.getParentOfType(contextElement, JsonObject::class.java) + val initObj: JsonObject? = PsiTreeUtil.getParentOfType(contextElement, JsonObject::class.java) ?: run { + val jsonFile = contextElement.containingFile as? JsonFile ?: return@run null + return jsonFile.allTopLevelValues.filterIsInstance().firstOrNull() + } if (initObj == null || !selectionModel.hasSelection()) { return initObj } @@ -92,7 +96,7 @@ open class JsonSortPropertiesIntention : PsiElementBaseIntentionAction(), LowPri return obj } - fun hasUnsortedObjects() : Boolean = objects.any { !isSorted(it) } + fun hasUnsortedObjects(): Boolean = objects.any { !isSorted(it) } fun sort() { objects.forEach { @@ -101,9 +105,7 @@ open class JsonSortPropertiesIntention : PsiElementBaseIntentionAction(), LowPri } } } - } - companion object { private fun isSorted(obj: JsonObject): Boolean { return obj.propertyList.asSequence() .map { it.name } diff --git a/json/tests/test/com/intellij/json/intentions/JsonSortPropertiesIntentionTest.kt b/json/tests/test/com/intellij/json/intentions/JsonSortPropertiesIntentionTest.kt index befc914d4fe7..feacaad07d75 100644 --- a/json/tests/test/com/intellij/json/intentions/JsonSortPropertiesIntentionTest.kt +++ b/json/tests/test/com/intellij/json/intentions/JsonSortPropertiesIntentionTest.kt @@ -25,4 +25,8 @@ class JsonSortPropertiesIntentionTest : JsonTestCase() { fun testSortRecursively() { doTest() } + + fun testSortWhenCaretAfterLastSymbol() { + doTest() + } } \ No newline at end of file diff --git a/json/tests/testData/intention/SortWhenCaretAfterLastSymbol.json b/json/tests/testData/intention/SortWhenCaretAfterLastSymbol.json new file mode 100644 index 000000000000..5c589779d5af --- /dev/null +++ b/json/tests/testData/intention/SortWhenCaretAfterLastSymbol.json @@ -0,0 +1,7 @@ +{ + "version": "1.0.0", + "main": "index.js", + "name": "my-app", + "license": "MIT" +} + \ No newline at end of file diff --git a/json/tests/testData/intention/SortWhenCaretAfterLastSymbol_after.json b/json/tests/testData/intention/SortWhenCaretAfterLastSymbol_after.json new file mode 100644 index 000000000000..4d381a1ee713 --- /dev/null +++ b/json/tests/testData/intention/SortWhenCaretAfterLastSymbol_after.json @@ -0,0 +1,6 @@ +{ + "license": "MIT", + "main": "index.js", + "name": "my-app", + "version": "1.0.0" +} diff --git a/native/WinLauncher/WinLauncher.cpp b/native/WinLauncher/WinLauncher.cpp index 36519efdae1b..acbe05b70a0f 100644 --- a/native/WinLauncher/WinLauncher.cpp +++ b/native/WinLauncher/WinLauncher.cpp @@ -903,9 +903,6 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, if (!IsSupportedVersion()) return 1; - int exitCode = CheckSingleInstance(); - if (exitCode != -1) return exitCode; - std::string homeDir = GetHomeDir(); if (!LocateJVM(homeDir)) return 1; @@ -923,6 +920,10 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, SetPathVariable(L"APPDATA", FOLDERID_RoamingAppData); SetPathVariable(L"LOCALAPPDATA", FOLDERID_LocalAppData); + //it's OK to return 0 here, because the control is transferred to the first instance + int exitCode = CheckSingleInstance(); + if (exitCode != -1) return exitCode; + // Read current directory and pass it to JVM through environment variable. The real current directory will be changed // in LoadJVMLibrary. std::wstring currentDirectory = GetCurrentDirectoryAsString(); diff --git a/platform/analysis-api/src/com/intellij/codeInsight/intention/preview/IntentionPreviewUtils.java b/platform/analysis-api/src/com/intellij/codeInsight/intention/preview/IntentionPreviewUtils.java index 70d1956049bf..434d1a3261ae 100644 --- a/platform/analysis-api/src/com/intellij/codeInsight/intention/preview/IntentionPreviewUtils.java +++ b/platform/analysis-api/src/com/intellij/codeInsight/intention/preview/IntentionPreviewUtils.java @@ -181,9 +181,11 @@ public final class IntentionPreviewUtils { else if (command instanceof ModChooseAction target) { return getChoosePreview(context, target); } - else if (command instanceof ModDisplayError error) { - return new IntentionPreviewInfo.Html(new HtmlBuilder().append( - AnalysisBundle.message("preview.cannot.perform.action")).br().append(error.errorMessage()).toFragment()); + else if (command instanceof ModDisplayMessage message) { + if (message.kind() == ModDisplayMessage.MessageKind.ERROR) { + return new IntentionPreviewInfo.Html(new HtmlBuilder().append( + AnalysisBundle.message("preview.cannot.perform.action")).br().append(message.messageText()).toFragment()); + } } } return customDiffList.isEmpty() ? navigateInfo : diff --git a/platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFixAndIntentionActionOnPsiElement.java b/platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFixAndIntentionActionOnPsiElement.java index 0b09edacf304..08b6cf42116f 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFixAndIntentionActionOnPsiElement.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFixAndIntentionActionOnPsiElement.java @@ -120,7 +120,7 @@ public abstract class LocalQuickFixAndIntentionActionOnPsiElement extends LocalQ @NotNull PsiElement endElement) { ModCommandAction.ActionContext context = ModCommandAction.ActionContext.from(editor, file).withElement(startElement); ModCommand command = action.perform(context); - ModCommandService.getInstance().executeInteractively(context, command); + ModCommandService.getInstance().executeInteractively(context, command, editor); } @Override diff --git a/platform/analysis-api/src/com/intellij/modcommand/ModCommand.java b/platform/analysis-api/src/com/intellij/modcommand/ModCommand.java index 62bd5d1c8b15..f84d27c36487 100644 --- a/platform/analysis-api/src/com/intellij/modcommand/ModCommand.java +++ b/platform/analysis-api/src/com/intellij/modcommand/ModCommand.java @@ -15,7 +15,7 @@ import java.util.Set; * All inheritors are records, so the whole state is declarative and readable. */ public sealed interface ModCommand - permits ModChooseAction, ModCompositeCommand, ModCreateFile, ModDeleteFile, ModDisplayError, ModHighlight, ModNavigate, + permits ModChooseAction, ModCompositeCommand, ModCreateFile, ModDeleteFile, ModDisplayMessage, ModHighlight, ModNavigate, ModNothing, ModRenameSymbol, ModUpdateFileText { /** diff --git a/platform/analysis-api/src/com/intellij/modcommand/ModCommandQuickFix.java b/platform/analysis-api/src/com/intellij/modcommand/ModCommandQuickFix.java index 73a8617d2c53..68fbf7cbd5ba 100644 --- a/platform/analysis-api/src/com/intellij/modcommand/ModCommandQuickFix.java +++ b/platform/analysis-api/src/com/intellij/modcommand/ModCommandQuickFix.java @@ -47,7 +47,7 @@ public abstract class ModCommandQuickFix implements LocalQuickFix { @Override public final void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { ModCommand command = perform(project, descriptor); - ModCommandService.getInstance().executeInteractively(ModCommandAction.ActionContext.from(descriptor), command); + ModCommandService.getInstance().executeInteractively(ModCommandAction.ActionContext.from(descriptor), command, null); } @Override diff --git a/platform/analysis-api/src/com/intellij/modcommand/ModCommandService.java b/platform/analysis-api/src/com/intellij/modcommand/ModCommandService.java index 609f27a1fe2a..c56c2e7dd406 100644 --- a/platform/analysis-api/src/com/intellij/modcommand/ModCommandService.java +++ b/platform/analysis-api/src/com/intellij/modcommand/ModCommandService.java @@ -5,6 +5,7 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.modcommand.ModCommandAction.ActionContext; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; import com.intellij.util.concurrency.annotations.RequiresEdt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,9 +52,10 @@ public interface ModCommandService { * * @param context current context * @param command a command to execute + * @param editor context editor, if known */ @RequiresEdt - void executeInteractively(@NotNull ActionContext context, @NotNull ModCommand command); + void executeInteractively(@NotNull ActionContext context, @NotNull ModCommand command, @Nullable Editor editor); /** * Executes given {@link ModCommand} in batch (applies default options, do not navigate) diff --git a/platform/analysis-api/src/com/intellij/modcommand/ModDisplayError.java b/platform/analysis-api/src/com/intellij/modcommand/ModDisplayError.java deleted file mode 100644 index 138025de8ce6..000000000000 --- a/platform/analysis-api/src/com/intellij/modcommand/ModDisplayError.java +++ /dev/null @@ -1,13 +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 com.intellij.modcommand; - -import com.intellij.openapi.util.NlsContexts; -import org.jetbrains.annotations.NotNull; - -/** - * A command that displays an error message. - * - * @param errorMessage localized error message to display - */ -public record ModDisplayError(@NlsContexts.Tooltip @NotNull String errorMessage) implements ModCommand { -} diff --git a/platform/analysis-api/src/com/intellij/modcommand/ModDisplayMessage.java b/platform/analysis-api/src/com/intellij/modcommand/ModDisplayMessage.java new file mode 100644 index 000000000000..e8c79953b685 --- /dev/null +++ b/platform/analysis-api/src/com/intellij/modcommand/ModDisplayMessage.java @@ -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 com.intellij.modcommand; + +import com.intellij.openapi.util.NlsContexts; +import org.jetbrains.annotations.NotNull; + +/** + * A command that displays an message. + * + * @param messageText localized message to display + * @param kind + */ +public record ModDisplayMessage(@NlsContexts.Tooltip @NotNull String messageText, MessageKind kind) implements ModCommand { + public enum MessageKind { + INFORMATION, ERROR; + } +} diff --git a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PackageSet.java b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PackageSet.java index d8bff0b60472..88482364cc5a 100644 --- a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PackageSet.java +++ b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PackageSet.java @@ -17,6 +17,7 @@ package com.intellij.psi.search.scope.packageSet; import com.intellij.openapi.util.NlsSafe; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileSystemItem; import org.jetbrains.annotations.NotNull; import java.util.function.Function; @@ -24,10 +25,22 @@ import java.util.function.Predicate; public interface PackageSet { boolean contains(@NotNull PsiFile file, NamedScopesHolder holder); + + default boolean contains(@NotNull PsiFileSystemItem file, NamedScopesHolder holder) { + if (file instanceof PsiFile) { + return contains((PsiFile)file, holder); + } + else { + return false; + } + } + @NotNull PackageSet createCopy(); + @NlsSafe @NotNull String getText(); + int getNodePriority(); /** diff --git a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PackageSetBase.java b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PackageSetBase.java index 0221cf593a18..b5284e7eb2c3 100644 --- a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PackageSetBase.java +++ b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PackageSetBase.java @@ -5,6 +5,7 @@ import com.intellij.diagnostic.PluginException; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileSystemItem; import com.intellij.psi.PsiManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,6 +24,11 @@ public abstract class PackageSetBase implements PackageSet { @Override public boolean contains(@NotNull PsiFile file, @Nullable NamedScopesHolder holder) { + return contains((PsiFileSystemItem)file, holder); + } + + @Override + public boolean contains(@NotNull PsiFileSystemItem file, NamedScopesHolder holder) { VirtualFile virtualFile = file.getVirtualFile(); return virtualFile != null && contains(virtualFile, file.getProject(), holder); } diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java index 364866345edd..233a9bf8ec18 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java @@ -195,10 +195,15 @@ public class GlobalInspectionContextBase extends UserDataHolderBase implements G } public boolean isToCheckMember(@NotNull RefElement owner, @NotNull InspectionProfileEntry tool) { - return isToCheckFile(((RefElementImpl)owner).getContainingFile(), tool) && !((RefElementImpl)owner).isSuppressed(tool.getShortName(), tool.getAlternativeID()); + return isToCheckFile(((RefElementImpl)owner).getContainingFile(), tool) && + !((RefElementImpl)owner).isSuppressed(tool.getShortName(), tool.getAlternativeID()); } public boolean isToCheckFile(PsiFile file, @NotNull InspectionProfileEntry tool) { + return isToCheckFile((PsiFileSystemItem)file, tool); + } + + public boolean isToCheckFile(PsiFileSystemItem file, @NotNull InspectionProfileEntry tool) { Tools tools = getTools().get(tool.getShortName()); if (tools != null && file != null) { for (ScopeToolState state : tools.getTools()) { diff --git a/platform/build-scripts/dev-server/src/BuildServer.kt b/platform/build-scripts/dev-server/src/BuildServer.kt index 7a33d34153ab..6781a3242a3a 100644 --- a/platform/build-scripts/dev-server/src/BuildServer.kt +++ b/platform/build-scripts/dev-server/src/BuildServer.kt @@ -25,6 +25,11 @@ internal data class ProductConfiguration(@JvmField val modules: List, @J private const val PRODUCTS_PROPERTIES_PATH = "build/dev-build.json" +/** + * Custom path for product properties + */ +private const val CUSTOM_PRODUCT_PROPERTIES_PATH = "idea.product.properties.path" + @Suppress("SpellCheckingInspection") fun getIdeSystemProperties(runDir: Path): Map { // see BuildContextImpl.getAdditionalJvmArguments - we should somehow deduplicate code @@ -60,15 +65,28 @@ suspend fun buildProductInProcess(request: BuildRequest) { private fun createConfiguration(productionClassOutput: Path, homePath: Path): Configuration { // for compatibility with local runs and runs on CI System.setProperty(BuildOptions.PROJECT_CLASSES_OUTPUT_DIRECTORY_PROPERTY, productionClassOutput.parent.toString()) - var projectPropertiesPath = homePath.resolve(PRODUCTS_PROPERTIES_PATH) + val projectPropertiesPath = getProductPropertiesPath(homePath) + return Json.decodeFromString(Configuration.serializer(), Files.readString(projectPropertiesPath)) +} + +private fun getProductPropertiesPath(homePath: Path): Path { + // Handle custom product properties path + val customPath = System.getProperty(CUSTOM_PRODUCT_PROPERTIES_PATH)?.let { homePath.resolve(it) } + if (customPath != null && customPath.exists()) { + return customPath + } + + val projectPropertiesPath = homePath.resolve(PRODUCTS_PROPERTIES_PATH) + // Handle Rider repository layout if (!projectPropertiesPath.exists() && homePath.parent?.parent?.resolve(".dotnet-products.root.marker")?.exists() == true) { val riderSpecificProjectPropertiesPath = homePath.parent.resolve("ultimate").resolve(PRODUCTS_PROPERTIES_PATH) if (riderSpecificProjectPropertiesPath.exists()) { - projectPropertiesPath = riderSpecificProjectPropertiesPath + return riderSpecificProjectPropertiesPath } } - return Json.decodeFromString(Configuration.serializer(), Files.readString(projectPropertiesPath)) + + return projectPropertiesPath } private fun getProductConfiguration(configuration: Configuration, platformPrefix: String): ProductConfiguration { diff --git a/platform/build-scripts/icons/intellij.platform.images.build.iml b/platform/build-scripts/icons/intellij.platform.images.build.iml index c86a07fc9735..08b1cf2d7abc 100644 --- a/platform/build-scripts/icons/intellij.platform.images.build.iml +++ b/platform/build-scripts/icons/intellij.platform.images.build.iml @@ -32,7 +32,13 @@ - + + + + 79bf02e8f49833dc3433ae1554999dd375075e5ab13447fc1e558857b51baecc + + + diff --git a/platform/build-scripts/intellij.platform.buildScripts.iml b/platform/build-scripts/intellij.platform.buildScripts.iml index 5dd4240a7b3b..303047021513 100644 --- a/platform/build-scripts/intellij.platform.buildScripts.iml +++ b/platform/build-scripts/intellij.platform.buildScripts.iml @@ -86,6 +86,11 @@ + + + c5edac7046453d487daf26bfce1ebb0ccb2d51e07167d01878a13ffdb9b66b8e + + @@ -120,6 +125,29 @@ + + + 25ac259e3506b4d80d038131445643d80bffc097488da73a9cbea05a2f14270b + + + 45b24b098dcaec230fde72b4e0568dab464cf7d8afd8b83fb9ac628778c67df9 + + + ffc62a11ad6a454d150a28c66c98e0300186faa53ec34d1c58c7dc5e2f7a3011 + + + e17a93342d623ecd58449b6142db53c5ec9d1fb7a6a40d6266e56ed796e06fdf + + + 0d127b205a1fce0abc2a3757a041748651bc66c15cf4c059bac5833b27d471a5 + + + 238630e244b369b57238bb35e9a23382be65771b04a0f36d85df07b61b4ae2b9 + + + 25a2353a1789870d960c0a9d8878a62eb1873116a2299d74f278451697676a67 + + @@ -179,6 +207,23 @@ + + + 92bf25de8508be9d8dc84f65fd1b08c348a3f54a726fae389f0a92797e8816ce + + + 80f807bca6b0c01ec2d9c126f65906172698ba67897286574aff17d52cfae792 + + + ac0192fd110a0363732b17ea94fd1ce8cfd85790c8e1551e14f866908b5d80e1 + + + 0b20f45e3a0fd8f0d12cdc5316b06776e902b1365db00118876f9175c60f302c + + + 8d83e6fe0ee319266dde031126da7c67024151b7c6a56410c3abb065fcd1ee7c + + diff --git a/platform/build-scripts/resources/win/launcher/aarch64/WinLauncher.exe b/platform/build-scripts/resources/win/launcher/aarch64/WinLauncher.exe index 8b571bee1955..3cf0fdef0191 100644 Binary files a/platform/build-scripts/resources/win/launcher/aarch64/WinLauncher.exe and b/platform/build-scripts/resources/win/launcher/aarch64/WinLauncher.exe differ diff --git a/platform/build-scripts/resources/win/launcher/amd64/WinLauncher.exe b/platform/build-scripts/resources/win/launcher/amd64/WinLauncher.exe index 16dcabf31809..6a406f967192 100644 Binary files a/platform/build-scripts/resources/win/launcher/amd64/WinLauncher.exe and b/platform/build-scripts/resources/win/launcher/amd64/WinLauncher.exe differ diff --git a/platform/collaboration-tools/src/com/intellij/collaboration/ui/codereview/details/ReviewDetailsUIUtil.kt b/platform/collaboration-tools/src/com/intellij/collaboration/ui/codereview/details/ReviewDetailsUIUtil.kt index 7a05cf81de63..f3d061261fb6 100644 --- a/platform/collaboration-tools/src/com/intellij/collaboration/ui/codereview/details/ReviewDetailsUIUtil.kt +++ b/platform/collaboration-tools/src/com/intellij/collaboration/ui/codereview/details/ReviewDetailsUIUtil.kt @@ -21,7 +21,7 @@ object ReviewDetailsUIUtil { fun getReviewStateIcon(reviewState: ReviewState): Icon = when (reviewState) { ReviewState.ACCEPTED -> AllIcons.RunConfigurations.TestPassed - ReviewState.WAIT_FOR_UPDATES, + ReviewState.WAIT_FOR_UPDATES -> AllIcons.RunConfigurations.TestError ReviewState.NEED_REVIEW -> AllIcons.RunConfigurations.TestFailed } diff --git a/platform/collaboration-tools/src/com/intellij/collaboration/ui/codereview/details/model/CodeReviewFlowViewModel.kt b/platform/collaboration-tools/src/com/intellij/collaboration/ui/codereview/details/model/CodeReviewFlowViewModel.kt index 33c6384ddd81..ab38f3a6dd3c 100644 --- a/platform/collaboration-tools/src/com/intellij/collaboration/ui/codereview/details/model/CodeReviewFlowViewModel.kt +++ b/platform/collaboration-tools/src/com/intellij/collaboration/ui/codereview/details/model/CodeReviewFlowViewModel.kt @@ -4,6 +4,6 @@ package com.intellij.collaboration.ui.codereview.details.model import com.intellij.collaboration.ui.codereview.details.data.ReviewState import kotlinx.coroutines.flow.Flow -interface CodeReviewFlowViewModel { - val reviewerReviews: Flow> +interface CodeReviewFlowViewModel { + val reviewerReviews: Flow> } \ No newline at end of file diff --git a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java index 9dc24fdfe570..f46cf3e1ffce 100644 --- a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java +++ b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java @@ -20,8 +20,6 @@ public abstract class ApplicationInfoEx extends ApplicationInfo { public abstract String getSplashImageUrl(); - public abstract String getAboutImageUrl(); - /** @deprecated please use {@link #getSmallApplicationSvgIconUrl()} instead */ @Deprecated @ApiStatus.ScheduledForRemoval @@ -47,8 +45,6 @@ public abstract class ApplicationInfoEx extends ApplicationInfo { @ApiStatus.ScheduledForRemoval public abstract @Nullable String getWelcomeScreenLogoUrl(); - public abstract boolean showLicenseeInfo(); - public abstract String getCopyrightStart(); public abstract boolean isEAP(); @@ -96,10 +92,6 @@ public abstract class ApplicationInfoEx extends ApplicationInfo { public abstract String getMacKeymapUrl(); - public abstract long getAboutForeground(); - - public abstract long getAboutLinkColor(); - public interface UpdateUrls { String getCheckingUrl(); String getPatchesUrl(); @@ -114,8 +106,6 @@ public abstract class ApplicationInfoEx extends ApplicationInfo { public abstract @Nullable String getWelcomeWizardDialog(); - public abstract int @Nullable [] getAboutLogoRect(); - public abstract String getSubscriptionFormId(); public abstract String getSubscriptionNewsKey(); @@ -135,8 +125,6 @@ public abstract class ApplicationInfoEx extends ApplicationInfo { return "JetBrains".equals(getShortCompanyName()); } - public abstract long getCopyrightForeground(); - public abstract @NotNull BuildNumber getApiVersionAsNumber(); public abstract @NotNull List getEssentialPluginsIds(); diff --git a/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java b/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java index d954c19f3daa..a0b6b18bb306 100644 --- a/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java @@ -54,13 +54,8 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx { private String myCopyrightStart = "2000"; private String myShortCompanyName; private String myCompanyUrl = "https://www.jetbrains.com/"; - private long myCopyrightForeground = -1; - private long myAboutForeground = -1; - private long myAboutLinkColor = -1; - private int[] myAboutLogoRect; // don't use Rectangle to avoid dependency on AWT private String mySplashImageUrl; private String myEapSplashImageUrl; - private String myAboutImageUrl; private String mySmallIconUrl = "/icon_small.png"; private String mySvgIconUrl; private String mySvgEapIconUrl; @@ -71,7 +66,6 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx { private Calendar myBuildDate; private Calendar myMajorReleaseBuildDate; - private boolean myShowLicensee = true; private String myWelcomeScreenDialog; private UpdateUrls myUpdateUrls; private String myDocumentationUrl; @@ -157,37 +151,6 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx { } break; - case "about": { - myAboutImageUrl = child.getAttributeValue("url"); - - String v = child.getAttributeValue("foreground"); - if (v != null) { - myAboutForeground = parseColor(v); - } - v = child.getAttributeValue("copyrightForeground"); - if (v != null) { - myCopyrightForeground = parseColor(v); - } - - String c = child.getAttributeValue("linkColor"); - if (c != null) { - myAboutLinkColor = parseColor(c); - } - - String logoX = child.getAttributeValue("logoX"); - String logoY = child.getAttributeValue("logoY"); - String logoW = child.getAttributeValue("logoW"); - String logoH = child.getAttributeValue("logoH"); - if (logoX != null && logoY != null && logoW != null && logoH != null) { - try { - myAboutLogoRect = new int[]{Integer.parseInt(logoX), Integer.parseInt(logoY), Integer.parseInt(logoW), Integer.parseInt(logoH)}; - } - catch (NumberFormatException ignored) { - } - } - } - break; - case "icon": { mySmallIconUrl = child.getAttributeValue("size16", mySmallIconUrl); String toolWindowIcon = getAttributeValue(child, "size12"); @@ -205,11 +168,6 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx { } break; - case "licensee": { - myShowLicensee = Boolean.parseBoolean(child.getAttributeValue("show")); - } - break; - case "welcome-screen": { myWelcomeScreenLogoUrl = child.getAttributeValue("logo-url"); } @@ -501,16 +459,6 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx { return isEAP() && myEapSplashImageUrl != null ? myEapSplashImageUrl : mySplashImageUrl; } - @Override - public String getAboutImageUrl() { - return myAboutImageUrl; - } - - @Override - public long getCopyrightForeground() { - return myCopyrightForeground; - } - @Override public @NotNull String getSmallIconUrl() { return mySmallIconUrl; @@ -648,26 +596,11 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx { return myMacKeymapUrl; } - @Override - public long getAboutForeground() { - return myAboutForeground; - } - - @Override - public long getAboutLinkColor() { - return myAboutLinkColor; - } - @Override public String getFullApplicationName() { return getVersionName() + " " + getFullVersion(); } - @Override - public boolean showLicenseeInfo() { - return myShowLicensee; - } - @Override public String getCopyrightStart() { return myCopyrightStart; @@ -687,11 +620,6 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx { return myKeyConversionUrl; } - @Override - public int @Nullable [] getAboutLogoRect() { - return myAboutLogoRect; - } - @Override public String getSubscriptionFormId() { return mySubscriptionFormId; @@ -834,10 +762,6 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx { return calendar; } - private static long parseColor(String colorString) { - return Long.parseLong(colorString, 16); - } - @ReviseWhenPortedToJDK("9") private static String requireNonNullElse(String s) { return s != null ? s : "0"; @@ -861,37 +785,25 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx { @Override public @Nullable String getDefaultLightLaf() { String override = System.getProperty(IDEA_APPLICATION_INFO_DEFAULT_LIGHT_LAF); - if (override != null) { - return override; - } - return myDefaultLightLaf; + return override != null ? override : myDefaultLightLaf; } @Override public @Nullable String getDefaultClassicLightLaf() { String override = System.getProperty(IDEA_APPLICATION_INFO_DEFAULT_CLASSIC_LIGHT_LAF); - if (override != null) { - return override; - } - return myDefaultClassicLightLaf; + return override != null ? override : myDefaultClassicLightLaf; } @Override public @Nullable String getDefaultDarkLaf() { String override = System.getProperty(IDEA_APPLICATION_INFO_DEFAULT_DARK_LAF); - if (override != null) { - return override; - } - return myDefaultDarkLaf; + return override != null ? override : myDefaultDarkLaf; } @Override public @Nullable String getDefaultClassicDarkLaf() { String override = System.getProperty(IDEA_APPLICATION_INFO_DEFAULT_CLASSIC_DARK_LAF); - if (override != null) { - return override; - } - return myDefaultClassicDarkLaf; + return override != null ? override : myDefaultClassicDarkLaf; } public @Nullable ZenDeskForm getFeedbackForm() { diff --git a/platform/credential-store/intellij.platform.credentialStore.iml b/platform/credential-store/intellij.platform.credentialStore.iml index 31669b1bc3d0..14c8f41abd8a 100644 --- a/platform/credential-store/intellij.platform.credentialStore.iml +++ b/platform/credential-store/intellij.platform.credentialStore.iml @@ -26,6 +26,14 @@ + + + bb67de9bd08148123b918458efc78055146bd5ae1538487cf4a018dd0f644837 + + + 3a7b9fd543a1be94de99009c36ac1803f08d6d12357706c8f5040855315469d1 + + diff --git a/platform/diagnostic/telemetry-impl/src/com/intellij/platform/diagnostic/telemetry/impl/open-telemetry-metrics-plotter.html b/platform/diagnostic/telemetry-impl/src/com/intellij/platform/diagnostic/telemetry/impl/open-telemetry-metrics-plotter.html index 56576b9935b9..d9dbf995ce15 100644 --- a/platform/diagnostic/telemetry-impl/src/com/intellij/platform/diagnostic/telemetry/impl/open-telemetry-metrics-plotter.html +++ b/platform/diagnostic/telemetry-impl/src/com/intellij/platform/diagnostic/telemetry/impl/open-telemetry-metrics-plotter.html @@ -823,11 +823,31 @@ as an example return } + const writeActionExecutionsCount = extractTimeSeries("WriteAction.executionsCount") + const readActionExecutionsCount = extractTimeSeries("ReadAction.executionsCount") + const finalizedExecutionsCount = extractTimeSeries("NonBlockingReadAction.finalizedExecutionsCount") const failedExecutionsCount = extractTimeSeries("NonBlockingReadAction.failedExecutionsCount") const finalizedExecutionTimeMs = extractTimeSeries("NonBlockingReadAction.finalizedExecutionTimeUs").mulScalar(1e-3) const failedExecutionTimeMs = extractTimeSeries("NonBlockingReadAction.failedExecutionTimeUs").mulScalar(1e-3) + plotTimeSeries( + 'Read and Write Actions count', + 'ReadAndWriteActions_CountChart', + [{ + name: 'Write Actions', + color: 'red', + series: writeActionExecutionsCount + }, { + name: 'Read Actions', + color: 'blue', + series: readActionExecutionsCount + }], + /*yaxis:*/ { + title: 'actions' + } + ) + plotTimeSeries( 'NonBlockingReadActions count: successful/interrupted', 'NonBlockingReads_CountChart', @@ -1280,7 +1300,7 @@ as an example

-
EDT: AWT & Flush Queues:
+
EDT: AWT & Flush Queues
@@ -1292,9 +1312,11 @@ as an example
-
+
-
NonBlockingReadAction:
+
Actions: Write, Read, and Non-Blocking-Read
+ +
diff --git a/platform/elevation/common/intellij.platform.elevation.common.iml b/platform/elevation/common/intellij.platform.elevation.common.iml index 8255872b9784..7d5b50f90a3f 100644 --- a/platform/elevation/common/intellij.platform.elevation.common.iml +++ b/platform/elevation/common/intellij.platform.elevation.common.iml @@ -23,6 +23,17 @@ + + + 424e8f9f9452fa2029ed54f664917b848745e488faaad5eebdb51174683f1db8 + + + fab15bbc792057f3762867574b3bb7c993b1ee4f9e82b1c79471891c9b3a7055 + + + 58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2 + + diff --git a/platform/icons/src/PlatformIconMappings.json b/platform/icons/src/PlatformIconMappings.json index f3f483e5a927..cd8c7dd1e5fc 100644 --- a/platform/icons/src/PlatformIconMappings.json +++ b/platform/icons/src/PlatformIconMappings.json @@ -3,6 +3,7 @@ "actions": { "buildAutoReloadChanges.svg": "actions/buildAutoReloadChanges.svg", "deploy.svg": "nodes/deploy.svg", + "diagramDiff.svg": "actions/diagramDiff.svg", "diffWithClipboard.svg": "actions/diffWithClipboard.svg", "filterdups.svg": "toolbar/filterdups.svg", "generated.svg": "actions/generatedFolder.svg", @@ -13,6 +14,7 @@ "inSelection.svg": "actions/inSelection.svg", "install.svg": "actions/install.svg", "lightning.svg": "actions/lightning.svg", + "minimap.svg": "actions/minimap.svg", "moveToBottomLeft.svg": "actions/moveToBottomLeft.svg", "moveToBottomRight.svg": "actions/moveToBottomRight.svg", "moveToButton.svg": "actions/move-to-button.svg", @@ -28,8 +30,10 @@ "profileCPU.svg": "actions/profileCPU.svg", "projectDirectory.svg": "actions/projectDirectory.svg", "runAll.svg": "actions/runAll.svg", + "reformatCode.svg": "actions/reformatCode.svg", "showReadAccess.svg": "actions/showReadAccess.svg", "showWriteAccess.svg": "actions/showWriteAccess.svg", + "split.svg": "modules/split.svg", "swapPanels.svg": "actions/swapPanels.svg", "synchronizeScrolling.svg": "actions/synchronizeScrolling.svg", "showImportStatements.svg": "actions/showImportStatements.svg", @@ -160,6 +164,8 @@ "nodes/ppJar.svg" ], "aspectJ.svg": "fileTypes/aspectj.svg", + "changedFile.svg": "scope/changedFiles.svg", + "changedFiles.svg": "scope/changedFilesAll.svg", "config.svg": "fileTypes/config.svg", "css.svg": "fileTypes/css.svg", "cucumber.svg": "org/jetbrains/plugins/cucumber/icons/cucumber.svg", @@ -171,7 +177,10 @@ "ideaModule.svg": "nodes/ideaModule.svg", "idl.svg": "fileTypes/idl.svg", "ignored.svg": "vcs/ignore_file.svg", - "java.svg": "fileTypes/java.svg", + "java.svg": [ + "fileTypes/java.svg", + "fileTypes/javaOutsideSource.svg" + ], "javaScript.svg": "fileTypes/javaScript.svg", "jest.svg": "icons/fileTypes/jestSnapshot.svg", "jfr.svg": "fileTypes/jfr.svg", @@ -202,6 +211,7 @@ "fileTypes/custom.svg", "fileTypes/text.svg" ], + "uiForm.svg": "fileTypes/uiForm.svg", "image.svg": "fileTypes/image.svg", "unknown.svg": "fileTypes/unknown.svg", "vueJs.svg": "icons/vue.svg", @@ -397,6 +407,10 @@ "suggestedRefactoringDisabled.svg": "gutter/suggestedRefactoringBulbDisabled.svg", "writeAccess.svg": "gutter/writeAccess.svg" }, + "hierarchy": { + "subtypes.svg": "hierarchy/subtypes.svg", + "supertypes.svg": "hierarchy/supertypes.svg" + }, "ide": { "configFile.svg": "ide/configFile.svg", "externalLink.svg": "ide/external_link_arrow.svg", @@ -508,7 +522,14 @@ "excludeRoot.svg": "modules/excludeRoot.svg", "excludedGenerated.svg": "modules/excludedGeneratedRoot.svg", "field.svg": "nodes/field.svg", - "folder.svg": "nodes/folder.svg", + "folder.svg": [ + "nodes/folder.svg", + "nodes/keymapAnt.svg", + "nodes/keymapEditor.svg", + "nodes/keymapMainMenu.svg", + "nodes/keymapOther.svg", + "nodes/keymapTools.svg" + ], "function.svg": "nodes/function.svg", "generated.svg": "modules/generatedFolder.svg", "generatedSource.svg": "modules/generatedSourceRoot.svg", @@ -658,7 +679,10 @@ "viewBreakpoints.svg": "debugger/viewBreakpoints.svg" }, "runConfigurations": { - "application.svg": "runConfigurations/application.svg", + "application.svg": [ + "runConfigurations/application.svg", + "runConfigurations/applet.svg" + ], "applicationRemote.svg": "runConfigurations/remote.svg", "compound.svg": "runConfigurations/compound.svg", "invalidConfigurationLayer.svg": "runConfigurations/invalidConfigurationLayer.svg", @@ -712,6 +736,7 @@ "settingSync.svg": "toolwindows/settingSync.svg", "structure.svg": "toolwindows/toolWindowStructure.svg", "todo.svg": "toolwindows/toolWindowTodo.svg", + "toolWindowJsonPath.svg": "toolwindows/toolWindowJsonPath.svg", "toolWindowVariableView.svg": "toolwindows/toolWindowVariableView.svg", "vcs.svg": "toolwindows/toolWindowChanges.svg", "web.svg": [ @@ -748,6 +773,9 @@ "update.svg": "actions/checkOut.svg", "vcs.svg": "vcs/branchNode.svg" }, + "webReferences": { + "server.svg": "webreferences/server.svg" + }, "welcome": { "createNewProjectTab.svg": "welcome/createNewProjectTab.svg", "fromVCSTab.svg": "welcome/fromVCSTab.svg", diff --git a/platform/icons/src/actions/reformatCode.svg b/platform/icons/src/actions/reformatCode.svg new file mode 100644 index 000000000000..2a184cb1bbf7 --- /dev/null +++ b/platform/icons/src/actions/reformatCode.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/actions/reformatCode_dark.svg b/platform/icons/src/actions/reformatCode_dark.svg new file mode 100644 index 000000000000..5b649bcb5fbc --- /dev/null +++ b/platform/icons/src/actions/reformatCode_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/actions/diagramDiff.svg b/platform/icons/src/expui/actions/diagramDiff.svg new file mode 100644 index 000000000000..abf0dffa4b0f --- /dev/null +++ b/platform/icons/src/expui/actions/diagramDiff.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/actions/diagramDiff_dark.svg b/platform/icons/src/expui/actions/diagramDiff_dark.svg new file mode 100644 index 000000000000..714838287621 --- /dev/null +++ b/platform/icons/src/expui/actions/diagramDiff_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/actions/minimap.svg b/platform/icons/src/expui/actions/minimap.svg new file mode 100644 index 000000000000..f24d3b7afe4e --- /dev/null +++ b/platform/icons/src/expui/actions/minimap.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/icons/src/expui/actions/minimap_dark.svg b/platform/icons/src/expui/actions/minimap_dark.svg new file mode 100644 index 000000000000..3fc7dc1b710d --- /dev/null +++ b/platform/icons/src/expui/actions/minimap_dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/icons/src/expui/actions/moveToBottomLeft.svg b/platform/icons/src/expui/actions/moveToBottomLeft.svg index 71995c0cd8a1..889d0cea2e55 100644 --- a/platform/icons/src/expui/actions/moveToBottomLeft.svg +++ b/platform/icons/src/expui/actions/moveToBottomLeft.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToBottomLeft_dark.svg b/platform/icons/src/expui/actions/moveToBottomLeft_dark.svg index 55ba3445b977..d59acfa8e345 100644 --- a/platform/icons/src/expui/actions/moveToBottomLeft_dark.svg +++ b/platform/icons/src/expui/actions/moveToBottomLeft_dark.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToBottomRight.svg b/platform/icons/src/expui/actions/moveToBottomRight.svg index b083a5428d1c..6b2124087bb0 100644 --- a/platform/icons/src/expui/actions/moveToBottomRight.svg +++ b/platform/icons/src/expui/actions/moveToBottomRight.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToBottomRight_dark.svg b/platform/icons/src/expui/actions/moveToBottomRight_dark.svg index d3195f19de7e..84a3ad19af0b 100644 --- a/platform/icons/src/expui/actions/moveToBottomRight_dark.svg +++ b/platform/icons/src/expui/actions/moveToBottomRight_dark.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToLeftBottom.svg b/platform/icons/src/expui/actions/moveToLeftBottom.svg index a09ab6037203..f41217d87139 100644 --- a/platform/icons/src/expui/actions/moveToLeftBottom.svg +++ b/platform/icons/src/expui/actions/moveToLeftBottom.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToLeftBottom_dark.svg b/platform/icons/src/expui/actions/moveToLeftBottom_dark.svg index 38a9308a9886..96000e7dd292 100644 --- a/platform/icons/src/expui/actions/moveToLeftBottom_dark.svg +++ b/platform/icons/src/expui/actions/moveToLeftBottom_dark.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToLeftTop.svg b/platform/icons/src/expui/actions/moveToLeftTop.svg index def3718e2c9b..e6ae3bf1ff90 100644 --- a/platform/icons/src/expui/actions/moveToLeftTop.svg +++ b/platform/icons/src/expui/actions/moveToLeftTop.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToLeftTop_dark.svg b/platform/icons/src/expui/actions/moveToLeftTop_dark.svg index eaaf69c566e3..f2ed50f0b55e 100644 --- a/platform/icons/src/expui/actions/moveToLeftTop_dark.svg +++ b/platform/icons/src/expui/actions/moveToLeftTop_dark.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToRightBottom.svg b/platform/icons/src/expui/actions/moveToRightBottom.svg index b011d9e4a6ee..292b4e348219 100644 --- a/platform/icons/src/expui/actions/moveToRightBottom.svg +++ b/platform/icons/src/expui/actions/moveToRightBottom.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToRightBottom_dark.svg b/platform/icons/src/expui/actions/moveToRightBottom_dark.svg index bb2f3bf499c3..4ab6eed6609d 100644 --- a/platform/icons/src/expui/actions/moveToRightBottom_dark.svg +++ b/platform/icons/src/expui/actions/moveToRightBottom_dark.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToRightTop.svg b/platform/icons/src/expui/actions/moveToRightTop.svg index 84fa31fa983d..e775b5e325b8 100644 --- a/platform/icons/src/expui/actions/moveToRightTop.svg +++ b/platform/icons/src/expui/actions/moveToRightTop.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/moveToRightTop_dark.svg b/platform/icons/src/expui/actions/moveToRightTop_dark.svg index 01f8611b0ed8..32541012759e 100644 --- a/platform/icons/src/expui/actions/moveToRightTop_dark.svg +++ b/platform/icons/src/expui/actions/moveToRightTop_dark.svg @@ -1,4 +1,4 @@ - + diff --git a/platform/icons/src/expui/actions/reformatCode.svg b/platform/icons/src/expui/actions/reformatCode.svg new file mode 100644 index 000000000000..ef85a66bdf04 --- /dev/null +++ b/platform/icons/src/expui/actions/reformatCode.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/icons/src/expui/actions/reformatCode_dark.svg b/platform/icons/src/expui/actions/reformatCode_dark.svg new file mode 100644 index 000000000000..20872d3a2cb9 --- /dev/null +++ b/platform/icons/src/expui/actions/reformatCode_dark.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/icons/src/expui/actions/split.svg b/platform/icons/src/expui/actions/split.svg new file mode 100644 index 000000000000..c972abfb842a --- /dev/null +++ b/platform/icons/src/expui/actions/split.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/icons/src/expui/actions/split_dark.svg b/platform/icons/src/expui/actions/split_dark.svg new file mode 100644 index 000000000000..2c9d204f7c53 --- /dev/null +++ b/platform/icons/src/expui/actions/split_dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/icons/src/expui/fileTypes/changedFile.svg b/platform/icons/src/expui/fileTypes/changedFile.svg new file mode 100644 index 000000000000..4578be9c93c1 --- /dev/null +++ b/platform/icons/src/expui/fileTypes/changedFile.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/icons/src/expui/fileTypes/changedFile_dark.svg b/platform/icons/src/expui/fileTypes/changedFile_dark.svg new file mode 100644 index 000000000000..5e8be56c5bed --- /dev/null +++ b/platform/icons/src/expui/fileTypes/changedFile_dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/platform/icons/src/expui/fileTypes/changedFiles.svg b/platform/icons/src/expui/fileTypes/changedFiles.svg new file mode 100644 index 000000000000..976e2120d6b2 --- /dev/null +++ b/platform/icons/src/expui/fileTypes/changedFiles.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/icons/src/expui/fileTypes/changedFiles_dark.svg b/platform/icons/src/expui/fileTypes/changedFiles_dark.svg new file mode 100644 index 000000000000..2325f946fd1e --- /dev/null +++ b/platform/icons/src/expui/fileTypes/changedFiles_dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/platform/icons/src/expui/fileTypes/uiForm.svg b/platform/icons/src/expui/fileTypes/uiForm.svg new file mode 100644 index 000000000000..23a796e89481 --- /dev/null +++ b/platform/icons/src/expui/fileTypes/uiForm.svg @@ -0,0 +1,4 @@ + + + + diff --git a/platform/icons/src/expui/fileTypes/uiForm_dark.svg b/platform/icons/src/expui/fileTypes/uiForm_dark.svg new file mode 100644 index 000000000000..caf70e0861ab --- /dev/null +++ b/platform/icons/src/expui/fileTypes/uiForm_dark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/platform/icons/src/expui/hierarchy/subtypes.svg b/platform/icons/src/expui/hierarchy/subtypes.svg new file mode 100644 index 000000000000..df40830ddabd --- /dev/null +++ b/platform/icons/src/expui/hierarchy/subtypes.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/hierarchy/subtypes_dark.svg b/platform/icons/src/expui/hierarchy/subtypes_dark.svg new file mode 100644 index 000000000000..c416967d15f0 --- /dev/null +++ b/platform/icons/src/expui/hierarchy/subtypes_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/hierarchy/supertypes.svg b/platform/icons/src/expui/hierarchy/supertypes.svg new file mode 100644 index 000000000000..60ceaf9eefb8 --- /dev/null +++ b/platform/icons/src/expui/hierarchy/supertypes.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/hierarchy/supertypes_dark.svg b/platform/icons/src/expui/hierarchy/supertypes_dark.svg new file mode 100644 index 000000000000..31832fe1d6c0 --- /dev/null +++ b/platform/icons/src/expui/hierarchy/supertypes_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/run/attachToProcess.svg b/platform/icons/src/expui/run/attachToProcess.svg index 8ccc5ceaa0c9..a68a716309d4 100644 --- a/platform/icons/src/expui/run/attachToProcess.svg +++ b/platform/icons/src/expui/run/attachToProcess.svg @@ -1,7 +1,7 @@ - - - - + + + + diff --git a/platform/icons/src/expui/run/attachToProcess_dark.svg b/platform/icons/src/expui/run/attachToProcess_dark.svg index a7a6ec938cf5..d498d92f8314 100644 --- a/platform/icons/src/expui/run/attachToProcess_dark.svg +++ b/platform/icons/src/expui/run/attachToProcess_dark.svg @@ -1,7 +1,7 @@ - - - - + + + + diff --git a/platform/icons/src/expui/runConfigurations/applicationRemote.svg b/platform/icons/src/expui/runConfigurations/applicationRemote.svg index 0c48d4be7514..deb5d22422a0 100644 --- a/platform/icons/src/expui/runConfigurations/applicationRemote.svg +++ b/platform/icons/src/expui/runConfigurations/applicationRemote.svg @@ -1,8 +1,8 @@ - - + + - + diff --git a/platform/icons/src/expui/runConfigurations/applicationRemote_dark.svg b/platform/icons/src/expui/runConfigurations/applicationRemote_dark.svg index bcbf16adcb5a..43a5e7e456ad 100644 --- a/platform/icons/src/expui/runConfigurations/applicationRemote_dark.svg +++ b/platform/icons/src/expui/runConfigurations/applicationRemote_dark.svg @@ -1,11 +1,11 @@ - - + + - + diff --git a/platform/icons/src/expui/toolwindow/toolWindowJsonPath.svg b/platform/icons/src/expui/toolwindow/toolWindowJsonPath.svg new file mode 100644 index 000000000000..4a962976b22f --- /dev/null +++ b/platform/icons/src/expui/toolwindow/toolWindowJsonPath.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/toolwindow/toolWindowJsonPath@20x20.svg b/platform/icons/src/expui/toolwindow/toolWindowJsonPath@20x20.svg new file mode 100644 index 000000000000..e93a489a8328 --- /dev/null +++ b/platform/icons/src/expui/toolwindow/toolWindowJsonPath@20x20.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/toolwindow/toolWindowJsonPath@20x20_dark.svg b/platform/icons/src/expui/toolwindow/toolWindowJsonPath@20x20_dark.svg new file mode 100644 index 000000000000..253de11170dc --- /dev/null +++ b/platform/icons/src/expui/toolwindow/toolWindowJsonPath@20x20_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/toolwindow/toolWindowJsonPath_dark.svg b/platform/icons/src/expui/toolwindow/toolWindowJsonPath_dark.svg new file mode 100644 index 000000000000..522bb8a380ba --- /dev/null +++ b/platform/icons/src/expui/toolwindow/toolWindowJsonPath_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/platform/icons/src/expui/webReferences/server.svg b/platform/icons/src/expui/webReferences/server.svg new file mode 100644 index 000000000000..7da67bb33993 --- /dev/null +++ b/platform/icons/src/expui/webReferences/server.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/platform/icons/src/expui/webReferences/server_dark.svg b/platform/icons/src/expui/webReferences/server_dark.svg new file mode 100644 index 000000000000..b07f67d94cdb --- /dev/null +++ b/platform/icons/src/expui/webReferences/server_dark.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/platform/icons/src/welcome/project/remove-hover.svg b/platform/icons/src/welcome/recentProjects/remove-hover.svg similarity index 100% rename from platform/icons/src/welcome/project/remove-hover.svg rename to platform/icons/src/welcome/recentProjects/remove-hover.svg diff --git a/platform/icons/src/welcome/project/remove-hover_dark.svg b/platform/icons/src/welcome/recentProjects/remove-hover_dark.svg similarity index 100% rename from platform/icons/src/welcome/project/remove-hover_dark.svg rename to platform/icons/src/welcome/recentProjects/remove-hover_dark.svg diff --git a/platform/icons/src/welcome/project/remove.svg b/platform/icons/src/welcome/recentProjects/remove.svg similarity index 100% rename from platform/icons/src/welcome/project/remove.svg rename to platform/icons/src/welcome/recentProjects/remove.svg diff --git a/platform/icons/src/welcome/project/removeDisabled-hover.svg b/platform/icons/src/welcome/recentProjects/removeDisabled-hover.svg similarity index 100% rename from platform/icons/src/welcome/project/removeDisabled-hover.svg rename to platform/icons/src/welcome/recentProjects/removeDisabled-hover.svg diff --git a/platform/icons/src/welcome/project/removeDisabled-hover_dark.svg b/platform/icons/src/welcome/recentProjects/removeDisabled-hover_dark.svg similarity index 100% rename from platform/icons/src/welcome/project/removeDisabled-hover_dark.svg rename to platform/icons/src/welcome/recentProjects/removeDisabled-hover_dark.svg diff --git a/platform/icons/src/welcome/project/removeDisabled.svg b/platform/icons/src/welcome/recentProjects/removeDisabled.svg similarity index 100% rename from platform/icons/src/welcome/project/removeDisabled.svg rename to platform/icons/src/welcome/recentProjects/removeDisabled.svg diff --git a/platform/icons/src/welcome/project/removeDisabled_dark.svg b/platform/icons/src/welcome/recentProjects/removeDisabled_dark.svg similarity index 100% rename from platform/icons/src/welcome/project/removeDisabled_dark.svg rename to platform/icons/src/welcome/recentProjects/removeDisabled_dark.svg diff --git a/platform/icons/src/welcome/project/remove_dark.svg b/platform/icons/src/welcome/recentProjects/remove_dark.svg similarity index 100% rename from platform/icons/src/welcome/project/remove_dark.svg rename to platform/icons/src/welcome/recentProjects/remove_dark.svg diff --git a/platform/lang-api/resources/messages/LangBundle.properties b/platform/lang-api/resources/messages/LangBundle.properties index 447c9c5e016e..d3ec4c5f5c60 100644 --- a/platform/lang-api/resources/messages/LangBundle.properties +++ b/platform/lang-api/resources/messages/LangBundle.properties @@ -584,4 +584,5 @@ label.change.shortcut=Change Shortcut action.clear.recent.actions.text=Clear Recent Actions action.clear.recent.actions.description=Clear recent history actions.tab.assign.a.shortcut=Press {0} to assign a shortcut -search.everywhere.advertiser.class.on.in.split=Open In Right Split \ No newline at end of file +search.everywhere.advertiser.class.on.in.split=Open In Right Split +double.shift=Double Shift \ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/codeInspection/ModCommands.java b/platform/lang-api/src/com/intellij/codeInspection/ModCommands.java index fb891bf38859..41175c018d80 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/ModCommands.java +++ b/platform/lang-api/src/com/intellij/codeInspection/ModCommands.java @@ -37,7 +37,15 @@ public final class ModCommands { * @return a command that displays the specified error message in the editor */ public static @NotNull ModCommand error(@NotNull @NlsContexts.Tooltip String message) { - return new ModDisplayError(message); + return new ModDisplayMessage(message, ModDisplayMessage.MessageKind.ERROR); + } + + /** + * @param message informational message to display + * @return a command that displays the specified informational message in the editor + */ + public static @NotNull ModCommand info(@NotNull @NlsContexts.Tooltip String message) { + return new ModDisplayMessage(message, ModDisplayMessage.MessageKind.INFORMATION); } /** @@ -152,6 +160,11 @@ public final class ModCommands { public @NotNull String getFamilyName() { return title; } + + @Override + public String toString() { + return "Step: [" + title + "] " + element.getText(); + } }; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index bd315e1308e5..ab978a314c4a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -14,7 +14,6 @@ import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.SelectionModel; -import com.intellij.openapi.editor.ex.util.EditorScrollingPositionKeeper; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; @@ -28,7 +27,6 @@ import com.intellij.psi.codeStyle.ChangedRangesInfo; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.impl.source.codeStyle.CodeFormatterFacade; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.SlowOperations; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -182,25 +180,23 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { KeptLineFeedsCollector.setup(fileToProcess); } try { - SlowOperations.allowSlowOperations(() -> { - if (document != null) { - // In languages that are supported by a non-commit typing assistant (such as C++ and Kotlin), - // the `document` here can be in an uncommitted state. In the case of an external formatter, - // this may be the cause of formatting artifacts - PsiDocumentManager.getInstance(myProject).commitDocument(document); + if (document != null) { + // In languages that are supported by a non-commit typing assistant (such as C++ and Kotlin), + // the `document` here can be in an uncommitted state. In the case of an external formatter, + // this may be the cause of formatting artifacts + PsiDocumentManager.getInstance(myProject).commitDocument(document); + } + if (processChangedTextOnly) { + ChangedRangesInfo info = VcsFacade.getInstance().getChangedRangesInfo(fileToProcess); + if (info != null) { + assertFileIsValid(fileToProcess); + CodeStyleManager.getInstance(myProject).reformatChanges(fileToProcess, info); } - if (processChangedTextOnly) { - ChangedRangesInfo info = VcsFacade.getInstance().getChangedRangesInfo(fileToProcess); - if (info != null) { - assertFileIsValid(fileToProcess); - CodeStyleManager.getInstance(myProject).reformatChanges(fileToProcess, info); - } - } - else { - Collection ranges = getRangesToFormat(fileToProcess); - CodeStyleManager.getInstance(myProject).reformatText(fileToProcess, ranges); - } - }); + } + else { + Collection ranges = getRangesToFormat(fileToProcess); + CodeStyleManager.getInstance(myProject).reformatText(fileToProcess, ranges); + } } catch (ProcessCanceledException pce) { if (before != null) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java index 12bec8b6a42b..beeb5c45aeff 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.completion.impl; import com.intellij.codeInsight.completion.*; @@ -6,8 +6,6 @@ import com.intellij.codeInsight.lookup.Classifier; import com.intellij.codeInsight.lookup.ClassifierFactory; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeWithMe.ClientId; -import com.intellij.platform.diagnostic.telemetry.IJTracer; -import com.intellij.platform.diagnostic.telemetry.TelemetryManager; import com.intellij.ide.plugins.DynamicPluginListener; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.openapi.Disposable; @@ -22,6 +20,8 @@ import com.intellij.openapi.project.ProjectCloseListener; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.NlsContexts; import com.intellij.patterns.ElementPattern; +import com.intellij.platform.diagnostic.telemetry.IJTracer; +import com.intellij.platform.diagnostic.telemetry.TelemetryManager; import com.intellij.psi.Weigher; import com.intellij.util.Consumer; import com.intellij.util.ExceptionUtil; @@ -31,7 +31,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; -import static com.intellij.codeInsight.util.CodeCompletionKt.*; +import static com.intellij.codeInsight.util.CodeCompletionKt.CodeCompletion; import static com.intellij.platform.diagnostic.telemetry.helpers.TraceKt.runWithSpan; /** @@ -44,18 +44,16 @@ public final class CompletionServiceImpl extends BaseCompletionService { private final IJTracer myCompletionTracer = TelemetryManager.getInstance().getTracer(CodeCompletion); private static class ClientCompletionService implements Disposable { - @Nullable - public static ClientCompletionService tryGetInstance(@Nullable ClientAppSession session) { - if (session == null) + public static @Nullable ClientCompletionService tryGetInstance(@Nullable ClientAppSession session) { + if (session == null) { return null; + } return session.getService(ClientCompletionService.class); } - @NotNull - private final ClientAppSession myAppSession; + private final @NotNull ClientAppSession myAppSession; - @NotNull - private volatile CompletionPhaseHolder myPhaseHolder = DEFAULT_PHASE_HOLDER; + private volatile @NotNull CompletionPhaseHolder myPhaseHolder = DEFAULT_PHASE_HOLDER; ClientCompletionService(@NotNull ClientAppSession appSession) { myAppSession = appSession; @@ -155,7 +153,7 @@ public final class CompletionServiceImpl extends BaseCompletionService { } @Override - public void setAdvertisementText(@NlsContexts.PopupAdvertisement @Nullable final String text) { + public void setAdvertisementText(final @NlsContexts.PopupAdvertisement @Nullable String text) { if (text == null) return; final CompletionProgressIndicator completion = getCurrentCompletionProgressIndicator(); if (completion != null) { @@ -182,8 +180,7 @@ public final class CompletionServiceImpl extends BaseCompletionService { return ClientId.isCurrentlyUnderLocalId() ? myApiCompletionProcess : null; } - @Nullable - public static CompletionProgressIndicator getCurrentCompletionProgressIndicator() { + public static @Nullable CompletionProgressIndicator getCurrentCompletionProgressIndicator() { ClientCompletionService clientCompletionService = ClientCompletionService.tryGetInstance(ClientSessionsManager.getAppSession()); if (clientCompletionService == null) return null; @@ -212,8 +209,7 @@ public final class CompletionServiceImpl extends BaseCompletionService { } @Override - @NotNull - public CompletionResultSet withPrefixMatcher(@NotNull final PrefixMatcher matcher) { + public @NotNull CompletionResultSet withPrefixMatcher(final @NotNull PrefixMatcher matcher) { if (matcher.equals(getPrefixMatcher())) { return this; } @@ -221,9 +217,8 @@ public final class CompletionServiceImpl extends BaseCompletionService { return new CompletionResultSetImpl(getConsumer(), matcher, myContributor, myParameters, mySorter, this); } - @NotNull @Override - public CompletionResultSet withRelevanceSorter(@NotNull CompletionSorter sorter) { + public @NotNull CompletionResultSet withRelevanceSorter(@NotNull CompletionSorter sorter) { return new CompletionResultSetImpl(getConsumer(), getPrefixMatcher(), myContributor, myParameters, sorter, this); } @@ -306,18 +301,16 @@ public final class CompletionServiceImpl extends BaseCompletionService { return clientCompletionService.getCompletionPhase(); } - @NotNull @Override - protected CompletionSorterImpl addWeighersBefore(@NotNull CompletionSorterImpl sorter) { + protected @NotNull CompletionSorterImpl addWeighersBefore(@NotNull CompletionSorterImpl sorter) { CompletionSorterImpl processed = super.addWeighersBefore(sorter); return processed.withClassifier(CompletionSorterImpl.weighingFactory(new LiveTemplateWeigher())); } - @NotNull @Override - protected CompletionSorterImpl processStatsWeigher(@NotNull CompletionSorterImpl sorter, - @NotNull Weigher weigher, - @NotNull CompletionLocation location) { + protected @NotNull CompletionSorterImpl processStatsWeigher(@NotNull CompletionSorterImpl sorter, + @NotNull Weigher weigher, + @NotNull CompletionLocation location) { CompletionSorterImpl processedSorter = super.processStatsWeigher(sorter, weigher, location); return processedSorter.withClassifier(new ClassifierFactory<>("stats") { @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionLookupManagerListener.kt b/platform/lang-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionLookupManagerListener.kt new file mode 100644 index 000000000000..50bdb1d7f267 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionLookupManagerListener.kt @@ -0,0 +1,29 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.codeInsight.inline.completion + +import com.intellij.codeInsight.lookup.Lookup +import com.intellij.codeInsight.lookup.LookupEvent +import com.intellij.codeInsight.lookup.LookupListener +import com.intellij.codeInsight.lookup.LookupManagerListener + +class InlineCompletionLookupManagerListener : LookupManagerListener { + override fun activeLookupChanged(oldLookup: Lookup?, newLookup: Lookup?) { + newLookup?.addLookupListener(object : LookupListener { + override fun currentItemChanged(event: LookupEvent) { + if (!event.lookup.isFocused || event.item == null) { + return + } + val listener = event.lookup.editor.getUserData(InlineCompletionHandler.KEY) ?: return + listener.invoke(event) + } + + override fun lookupCanceled(event: LookupEvent) { + // TODO: Try to continue inline completion + } + + override fun lookupShown(event: LookupEvent) { + // TODO: Strip current inline completion text to one-line + } + }) + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionHintComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionHintComponent.java index 165c17013dc2..644d43da8608 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionHintComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionHintComponent.java @@ -6,6 +6,7 @@ import com.intellij.codeInsight.hint.*; import com.intellij.codeInsight.intention.CustomizableIntentionAction; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.IntentionActionDelegate; +import com.intellij.codeInsight.intention.actions.ShowIntentionActionsAction; import com.intellij.codeInsight.intention.impl.config.IntentionManagerSettings; import com.intellij.codeInsight.intention.impl.preview.IntentionPreviewPopupUpdateProcessor; import com.intellij.codeInsight.unwrap.ScopeHighlighter; @@ -18,6 +19,7 @@ import com.intellij.internal.statistic.IntentionFUSCollector; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.impl.ActionButton; import com.intellij.openapi.actionSystem.impl.SimpleDataContext; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; @@ -43,6 +45,7 @@ import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.refactoring.BaseRefactoringIntentionAction; import com.intellij.ui.*; import com.intellij.ui.awt.RelativePoint; +import com.intellij.ui.codeFloatingToolbar.CodeFloatingToolbar; import com.intellij.ui.icons.RowIcon; import com.intellij.ui.popup.WizardPopup; import com.intellij.ui.popup.list.ListPopupImpl; @@ -221,37 +224,82 @@ public final class IntentionHintComponent implements Disposable, ScrollAwareHint @RequiresEdt private void showPopup(boolean mouseClick) { - RelativePoint positionHint = null; if (mouseClick && myLightBulbPanel.isShowing()) { - RelativePoint swCorner = RelativePoint.getSouthWestOf(myLightBulbPanel); - Point popup = swCorner.getPoint(); - - Point panel = SwingUtilities.convertPoint(myLightBulbPanel, new Point(), myEditor.getContentComponent()); - Point caretLine = myEditor.offsetToXY(myEditor.getCaretModel().getOffset()); - if (panel.y + myLightBulbPanel.getHeight() <= caretLine.y) { - // The light bulb panel is shown above the caret line. - // The caret line should be completely visible, as it contains the interesting code. - // The popup menu is shown below the caret line. - popup.y += 1; // Step outside the light bulb panel. - popup.y += myEditor.getLineHeight(); - } - else { - // Let the top border pixel of the popup menu overlap the bottom border pixel of the light bulb panel. - } - - // XXX: This formula is only guessed. - int adjust = (int)(UISettingsUtils.getInstance().getCurrentIdeScale() - 0.5); - // Align the left border of the popup menu with the light bulb panel. - // XXX: Where does the 1 come from? - popup.x += 1 + adjust; - // Align the top border of the menu bar. - popup.y += adjust; - - positionHint = new RelativePoint(swCorner.getComponent(), popup); + showPopup(findPositionForBulbButton()); + return; } + CodeFloatingToolbar toolbar = CodeFloatingToolbar.getToolbar(myEditor); + if (toolbar != null) { + if (toolbar.isShown()) { + showPopupFromToolbar(toolbar); + } else { + toolbar.show(() -> showPopupFromToolbar(toolbar)); + } + return; + } + showPopup(null); + } + + private void showPopupFromToolbar(CodeFloatingToolbar toolbar) { + RelativePoint position = findPositionForToolbarButton(toolbar); + adjustVerticalOverlapping(position); + showPopup(position); + } + + private void adjustVerticalOverlapping(@Nullable RelativePoint position) { + if (position == null) return; + if (myPopup.myListPopup == null) { + myPopup.myHint = this; + IntentionPopup.recreateMyPopup(myPopup, new IntentionListStep(myPopup, myPopup.myEditor, myPopup.myFile, myPopup.myProject, myPopup.myCachedIntentions)); + } + ActionButton.adjustVerticalOverlapping(myPopup.myListPopup, position.getOriginalComponent()); + } + + private void showPopup(@Nullable RelativePoint positionHint) { myPopup.show(this, positionHint); } + private @NotNull RelativePoint findPositionForBulbButton() { + RelativePoint swCorner = RelativePoint.getSouthWestOf(myLightBulbPanel); + Point popup = swCorner.getPoint(); + + Point panel = SwingUtilities.convertPoint(myLightBulbPanel, new Point(), myEditor.getContentComponent()); + Point caretLine = myEditor.offsetToXY(myEditor.getCaretModel().getOffset()); + if (panel.y + myLightBulbPanel.getHeight() <= caretLine.y) { + // The light bulb panel is shown above the caret line. + // The caret line should be completely visible, as it contains the interesting code. + // The popup menu is shown below the caret line. + popup.y += 1; // Step outside the light bulb panel. + popup.y += myEditor.getLineHeight(); + } + else { + // Let the top border pixel of the popup menu overlap the bottom border pixel of the light bulb panel. + } + + // XXX: This formula is only guessed. + int adjust = (int)(UISettingsUtils.getInstance().getCurrentIdeScale() - 0.5); + // Align the left border of the popup menu with the light bulb panel. + // XXX: Where does the 1 come from? + popup.x += 1 + adjust; + // Align the top border of the menu bar. + popup.y += adjust; + + return new RelativePoint(swCorner.getComponent(), popup); + } + + private static @Nullable RelativePoint findPositionForToolbarButton(@NotNull CodeFloatingToolbar toolbar){ + JComponent component = toolbar.getHintComponent(); + if (component == null) return null; + List buttons = UIUtil.findComponentsOfType(component, ActionButton.class); + ActionButton intentionButton = ContainerUtil.find(buttons, (button) -> button.getAction() instanceof ShowIntentionActionsAction); + if (intentionButton == null) return null; + RelativePoint buttonPoint = RelativePoint.getSouthWestOf(intentionButton); + RelativePoint toolbarPoint = RelativePoint.getSouthWestOf(component); + int horizontalOffset = toolbarPoint.getScreenPoint().x - buttonPoint.getScreenPoint().x; + buttonPoint.getPoint().translate(horizontalOffset, 0); + return buttonPoint; + } + private static final class MyComponentHint extends LightweightHint { private boolean myVisible; private boolean myShouldDelay; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java index 08abdfd9efee..47145205e080 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java @@ -294,7 +294,7 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler { Project project = context.project(); IntentionFUSCollector.record(project, commandAction, context.file().getLanguage()); CommandProcessor.getInstance().executeCommand(project, () -> { - ModCommandService.getInstance().executeInteractively(context, contextAndCommand.command()); + ModCommandService.getInstance().executeInteractively(context, contextAndCommand.command(), hostEditor); }, commandName, null); } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereManagerImpl.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereManagerImpl.java index c014a93948b7..27443cb51b4b 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereManagerImpl.java @@ -6,6 +6,7 @@ import com.intellij.ide.actions.BigPopupUI; import com.intellij.ide.actions.OpenInRightSplitAction; import com.intellij.ide.lightEdit.LightEdit; import com.intellij.ide.lightEdit.LightEditCompatible; +import com.intellij.lang.LangBundle; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.keymap.KeymapUtil; @@ -26,6 +27,7 @@ import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBInsets; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -375,9 +377,9 @@ public final class SearchEverywhereManagerImpl implements SearchEverywhereManage } private static Map createShortcutsMap() { - Map res = new HashMap<>(); + Map res = new HashMap<>(); - res.put(ALL_CONTRIBUTORS_GROUP_ID, "Double Shift"); + res.put(ALL_CONTRIBUTORS_GROUP_ID, LangBundle.message("double.shift")); addShortcut(res, "ClassSearchEverywhereContributor", "GotoClass"); addShortcut(res, "FileSearchEverywhereContributor", "GotoFile"); addShortcut(res, "SymbolSearchEverywhereContributor", "GotoSymbol"); @@ -388,7 +390,7 @@ public final class SearchEverywhereManagerImpl implements SearchEverywhereManage return res; } - private static void addShortcut(Map map, String contributorID, String actionID) { + private static void addShortcut(Map map, String contributorID, String actionID) { KeyboardShortcut shortcut = ActionManager.getInstance().getKeyboardShortcut(actionID); if (shortcut != null) map.put(contributorID, KeymapUtil.getShortcutText(shortcut)); } diff --git a/platform/lang-impl/src/com/intellij/lang/impl/modcommand/ModCommandActionWrapper.java b/platform/lang-impl/src/com/intellij/lang/impl/modcommand/ModCommandActionWrapper.java index 49ca7f093df5..9bc459b1abf2 100644 --- a/platform/lang-impl/src/com/intellij/lang/impl/modcommand/ModCommandActionWrapper.java +++ b/platform/lang-impl/src/com/intellij/lang/impl/modcommand/ModCommandActionWrapper.java @@ -70,7 +70,7 @@ import java.util.Objects; public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { ModCommandAction.ActionContext context = ModCommandAction.ActionContext.from(editor, file); ModCommand command = myAction.perform(context); - ModCommandService.getInstance().executeInteractively(context, command); + ModCommandService.getInstance().executeInteractively(context, command, editor); } @Override diff --git a/platform/lang-impl/src/com/intellij/lang/impl/modcommand/ModCommandServiceImpl.java b/platform/lang-impl/src/com/intellij/lang/impl/modcommand/ModCommandServiceImpl.java index 5e8baa7ae7a6..d0550f45ed6f 100644 --- a/platform/lang-impl/src/com/intellij/lang/impl/modcommand/ModCommandServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/lang/impl/modcommand/ModCommandServiceImpl.java @@ -86,9 +86,9 @@ public class ModCommandServiceImpl implements ModCommandService { @RequiresEdt @Override - public void executeInteractively(@NotNull ActionContext context, @NotNull ModCommand command) { + public void executeInteractively(@NotNull ActionContext context, @NotNull ModCommand command, @Nullable Editor editor) { if (!ensureWritable(context.project(), command)) return; - doExecute(context, command, true); + doExecute(context, command, editor, true); } private static boolean ensureWritable(@NotNull Project project, @NotNull ModCommand command) { @@ -99,16 +99,16 @@ public class ModCommandServiceImpl implements ModCommandService { @Override public void executeInBatch(@NotNull ActionContext context, @NotNull ModCommand command) { if (!ensureWritable(context.project(), command)) return; - doExecute(context, command, false); + doExecute(context, command, null, false); } - private boolean doExecute(@NotNull ActionContext context, @NotNull ModCommand command, boolean onTheFly) { + private boolean doExecute(@NotNull ActionContext context, @NotNull ModCommand command, @Nullable Editor editor, boolean onTheFly) { Project project = context.project(); if (command instanceof ModUpdateFileText upd) { return executeUpdate(project, upd); } if (command instanceof ModCompositeCommand cmp) { - return executeComposite(context, cmp, onTheFly); + return executeComposite(context, cmp, editor, onTheFly); } if (command instanceof ModNavigate nav) { if (!onTheFly) return true; @@ -122,11 +122,11 @@ public class ModCommandServiceImpl implements ModCommandService { return true; } if (command instanceof ModChooseAction chooser) { - return executeChoose(context, chooser, onTheFly); + return executeChoose(context, chooser, onTheFly, editor); } - if (command instanceof ModDisplayError error) { + if (command instanceof ModDisplayMessage message) { if (!onTheFly) return true; // TODO: gather all errors and display them together? - return executeError(project, error); + return executeMessage(project, message); } if (command instanceof ModRenameSymbol rename) { if (!onTheFly) return true; @@ -147,7 +147,7 @@ public class ModCommandServiceImpl implements ModCommandService { return true; } catch (IOException e) { - executeError(project, new ModDisplayError(e.getMessage())); + executeMessage(project, new ModDisplayMessage(e.getMessage(), ModDisplayMessage.MessageKind.ERROR)); return false; } } @@ -167,7 +167,7 @@ public class ModCommandServiceImpl implements ModCommandService { }); } catch (IOException e) { - executeError(project, new ModDisplayError(e.getMessage())); + executeMessage(project, new ModDisplayMessage(e.getMessage(), ModDisplayMessage.MessageKind.ERROR)); return false; } } @@ -256,14 +256,17 @@ public class ModCommandServiceImpl implements ModCommandService { } } - private static boolean executeError(@NotNull Project project, @NotNull ModDisplayError error) { + private static boolean executeMessage(@NotNull Project project, @NotNull ModDisplayMessage message) { Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); if (editor == null) return false; - HintManager.getInstance().showErrorHint(editor, error.errorMessage()); + switch (message.kind()) { + case INFORMATION -> HintManager.getInstance().showInformationHint(editor, message.messageText()); + case ERROR -> HintManager.getInstance().showErrorHint(editor, message.messageText()); + } return true; } - private boolean executeChoose(@NotNull ActionContext context, ModChooseAction chooser, boolean onTheFly) { + private boolean executeChoose(@NotNull ActionContext context, ModChooseAction chooser, boolean onTheFly, @Nullable Editor editor) { record ActionAndPresentation(@NotNull ModCommandAction action, @NotNull ModCommandAction.Presentation presentation) {} List actions = StreamEx.of(chooser.actions()).mapToEntry(action -> action.getPresentation(context)) .nonNullValues().mapKeyValue(ActionAndPresentation::new).toList(); @@ -272,7 +275,7 @@ public class ModCommandServiceImpl implements ModCommandService { String name = CommandProcessor.getInstance().getCurrentCommandName(); if (actions.size() == 1 || !onTheFly) { ModCommandAction action = actions.get(0).action(); - executeNextStep(context, name, onTheFly, () -> { + executeNextStep(context, name, editor, onTheFly, () -> { if (action.getPresentation(context) == null) return null; return action.perform(context); }); @@ -280,14 +283,14 @@ public class ModCommandServiceImpl implements ModCommandService { } VirtualFile file = context.file().getVirtualFile(); if (file == null) return false; - Editor editor = getEditor(context.project(), file); + Editor finalEditor = editor == null ? getEditor(context.project(), file) : editor; if (editor == null) return false; ShowIntentionsPass.IntentionsInfo info = new ShowIntentionsPass.IntentionsInfo(); List descriptors = ContainerUtil.map( actions, (actionAndPresentation) -> { ModCommandAction.Presentation presentation = actionAndPresentation.presentation(); IntentionAction intention = actionAndPresentation.action().asIntention(); - intention.isAvailable(context.project(), editor, context.file()); // cache text + intention.isAvailable(context.project(), finalEditor, context.file()); // cache text return new HighlightInfo.IntentionActionDescriptor(intention, List.of(), presentation.name(), presentation.icon(), null, null, null); }); info.intentionsToShow.addAll(descriptors); @@ -297,15 +300,15 @@ public class ModCommandServiceImpl implements ModCommandService { return true; } - private void executeNextStep(@NotNull ActionContext context, @Nullable @NlsContexts.Command String name, boolean onTheFly, + private void executeNextStep(@NotNull ActionContext context, @Nullable @NlsContexts.Command String name, @Nullable Editor editor, boolean onTheFly, Callable supplier) { ReadAction.nonBlocking(supplier) .finishOnUiThread(ModalityState.defaultModalityState(), next -> { if (next == null) return; if (name != null) { - CommandProcessor.getInstance().executeCommand(context.project(), () -> doExecute(context, next, true), name, onTheFly); + CommandProcessor.getInstance().executeCommand(context.project(), () -> doExecute(context, next, editor, true), name, onTheFly); } else { - doExecute(context, next, onTheFly); + doExecute(context, next, editor, onTheFly); } }) .submit(AppExecutorUtil.getAppExecutorService()); @@ -352,9 +355,9 @@ public class ModCommandServiceImpl implements ModCommandService { return FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, file), true); } - private boolean executeComposite(@NotNull ActionContext context, ModCompositeCommand cmp, boolean onTheFly) { + private boolean executeComposite(@NotNull ActionContext context, ModCompositeCommand cmp, @Nullable Editor editor, boolean onTheFly) { for (ModCommand command : cmp.commands()) { - boolean status = doExecute(context, command, onTheFly); + boolean status = doExecute(context, command, editor, onTheFly); if (!status) { return false; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java index 3022a2edf9a0..a26570aa6eca 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java @@ -2,7 +2,6 @@ package com.intellij.psi.impl.file.impl; import com.intellij.AppTopics; -import com.intellij.ProjectTopics; import com.intellij.application.Topics; import com.intellij.ide.PsiCopyPasteManager; import com.intellij.ide.impl.ProjectUtilCore; @@ -87,7 +86,6 @@ public final class PsiVFSListener implements BulkFileListener { }, project); } - connection.subscribe(ProjectTopics.PROJECT_ROOTS, new MyModuleRootListener(project)); connection.subscribe(AdditionalLibraryRootsListener.TOPIC, new MyAdditionalLibraryRootListener(project)); connection.subscribe(FileTypeManager.TOPIC, new FileTypeListener() { @Override @@ -596,14 +594,12 @@ public final class PsiVFSListener implements BulkFileListener { name, fileTypeByFileName, "", vFile.getModificationStamp(), true, false); } - private static final class MyModuleRootListener implements ModuleRootListener { + public static final class MyModuleRootListener implements ModuleRootListener { private int depthCounter; // accessed from within write action only - private final PsiManagerImpl psiManager; - private final FileManagerImpl fileManager; + private final Project myListenerProject; - private MyModuleRootListener(@NotNull Project project) { - psiManager = (PsiManagerImpl)PsiManager.getInstance(project); - fileManager = (FileManagerImpl)psiManager.getFileManager(); + public MyModuleRootListener(@NotNull Project project) { + myListenerProject = project; } @Override @@ -617,6 +613,7 @@ public final class PsiVFSListener implements BulkFileListener { if (LOG.isTraceEnabled()) LOG.trace("depthCounter increased " + depthCounter); if (depthCounter > 1) return; + PsiManagerImpl psiManager = (PsiManagerImpl)PsiManager.getInstance(myListenerProject); PsiTreeChangeEventImpl treeEvent = new PsiTreeChangeEventImpl(psiManager); treeEvent.setPropertyName(PsiTreeChangeEvent.PROP_ROOTS); psiManager.beforePropertyChange(treeEvent); @@ -627,6 +624,8 @@ public final class PsiVFSListener implements BulkFileListener { @Override public void rootsChanged(@NotNull ModuleRootEvent event) { if (LOG.isTraceEnabled()) LOG.trace("rootsChanged call"); + PsiManagerImpl psiManager = (PsiManagerImpl)PsiManager.getInstance(myListenerProject); + FileManagerImpl fileManager = (FileManagerImpl)psiManager.getFileManager(); fileManager.dispatchPendingEvents(); if (event.isCausedByFileTypesChange()) return; diff --git a/platform/lang-impl/src/com/intellij/task/impl/ProjectTaskManagerImpl.java b/platform/lang-impl/src/com/intellij/task/impl/ProjectTaskManagerImpl.java index a055c48552f6..92fa56fc3b82 100644 --- a/platform/lang-impl/src/com/intellij/task/impl/ProjectTaskManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/task/impl/ProjectTaskManagerImpl.java @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.task.impl; import com.intellij.execution.ExecutionException; @@ -17,6 +17,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.OrderEnumerator; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectModelBuildableElement; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; @@ -55,6 +56,8 @@ import static java.util.stream.Collectors.groupingBy; */ public final class ProjectTaskManagerImpl extends ProjectTaskManager { private static final Logger LOG = Logger.getInstance(ProjectTaskManager.class); + private static final Key BUILD_ORIGINATOR_KEY = Key.create("project task build originator"); + private final ProjectTaskRunner myDummyTaskRunner = new DummyTaskRunner(); private final ProjectTaskListener myEventPublisher; private final List myListeners = new CopyOnWriteArrayList<>(); @@ -183,7 +186,7 @@ public final class ProjectTaskManagerImpl extends ProjectTaskManager { }); - StructuredIdeActivity activity = reportBuildStart(projectTask, toRun); + Pair>> activity = reportBuildStart(projectTask, toRun); myEventPublisher.started(context); Runnable runnable = () -> { @@ -193,14 +196,14 @@ public final class ProjectTaskManagerImpl extends ProjectTaskManager { } catch (ExecutionException e) { sendAbortedEmptyResult(context, new ResultConsumer(promiseResult)); - activity.finished(); + activity.first.finished(() -> activity.second); return; } } if (toRun.isEmpty()) { sendSuccessEmptyResult(context, new ResultConsumer(promiseResult)); - activity.finished(); + activity.first.finished(() -> activity.second); return; } @@ -239,9 +242,8 @@ public final class ProjectTaskManagerImpl extends ProjectTaskManager { return promiseResult; } - @NotNull - private StructuredIdeActivity reportBuildStart(@NotNull ProjectTask projectTask, - List>> toRun) { + private Pair>> reportBuildStart(@NotNull ProjectTask projectTask, + List>> toRun) { Ref incremental = new Ref<>(null); AtomicInteger modules = new AtomicInteger(0); visitTask(projectTask, tasks -> { @@ -271,7 +273,12 @@ public final class ProjectTaskManagerImpl extends ProjectTaskManager { if (modules.get() > 0) { fields.add(MODULES.with(modules.get())); } - return BUILD_ACTIVITY.started(myProject, () -> fields); + String buildOriginator = BUILD_ORIGINATOR_KEY.get(myProject); + if (buildOriginator != null) { + myProject.putUserData(BUILD_ORIGINATOR_KEY, null); + fields.add(BUILD_ORIGINATOR.with(buildOriginator)); + } + return Pair.create(BUILD_ACTIVITY.started(myProject, () -> fields), fields); } private List>> groupByRunner(@NotNull ProjectTask projectTask) { @@ -306,6 +313,12 @@ public final class ProjectTaskManagerImpl extends ProjectTaskManager { visitTasks(projectTask instanceof ProjectTaskList ? (ProjectTaskList)projectTask : Collections.singleton(projectTask), taskClassifier); } + public static void putBuildOriginator(@Nullable Project project, @NotNull Class clazz) { + if (BUILD_ORIGINATOR_KEY.get(project) == null) { + BUILD_ORIGINATOR_KEY.set(project, clazz.getName()); + } + } + @ApiStatus.Experimental public static @Nullable T waitForPromise(@NotNull Promise promise) { while (true) { @@ -428,7 +441,7 @@ public final class ProjectTaskManagerImpl extends ProjectTaskManager { private final ProjectTaskContext myContext; private final ResultConsumer myResultConsumer; private final AtomicInteger myProgressCounter; - private final StructuredIdeActivity myActivity; + private final Pair>> myActivity; private final AtomicBoolean myErrorsFlag; private final AtomicBoolean myAbortedFlag; private final Map myTasksState = new ConcurrentHashMap<>(); @@ -436,7 +449,7 @@ public final class ProjectTaskManagerImpl extends ProjectTaskManager { private ProjectTaskResultsAggregator(@NotNull ProjectTaskContext context, @NotNull ResultConsumer resultConsumer, int expectedResults, - @NotNull StructuredIdeActivity activity) { + Pair>> activity) { myContext = context; myResultConsumer = resultConsumer; myProgressCounter = new AtomicInteger(expectedResults); @@ -473,7 +486,9 @@ public final class ProjectTaskManagerImpl extends ProjectTaskManager { myResultConsumer.accept(new MyResult(myContext, myTasksState, myAbortedFlag.get(), myErrorsFlag.get())); } finally { - myActivity.finished(() -> List.of(HAS_ERRORS.with(myErrorsFlag.get()))); + List> events = new ArrayList<>(myActivity.second); + events.add(HAS_ERRORS.with(myErrorsFlag.get())); + myActivity.first.finished(() -> events); } } } diff --git a/platform/lang-impl/src/com/intellij/task/impl/ProjectTaskManagerStatisticsCollector.kt b/platform/lang-impl/src/com/intellij/task/impl/ProjectTaskManagerStatisticsCollector.kt index b2dd6d3698cf..236696973d44 100644 --- a/platform/lang-impl/src/com/intellij/task/impl/ProjectTaskManagerStatisticsCollector.kt +++ b/platform/lang-impl/src/com/intellij/task/impl/ProjectTaskManagerStatisticsCollector.kt @@ -1,18 +1,15 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.task.impl import com.intellij.internal.statistic.IdeActivityDefinition import com.intellij.internal.statistic.collectors.fus.ClassNameRuleValidator import com.intellij.internal.statistic.eventLog.EventLogGroup -import com.intellij.internal.statistic.eventLog.events.BooleanEventField -import com.intellij.internal.statistic.eventLog.events.EventFields -import com.intellij.internal.statistic.eventLog.events.IntEventField -import com.intellij.internal.statistic.eventLog.events.StringListEventField +import com.intellij.internal.statistic.eventLog.events.* import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector class ProjectTaskManagerStatisticsCollector : CounterUsagesCollector() { companion object { - val GROUP: EventLogGroup = EventLogGroup("build", 6) + val GROUP: EventLogGroup = EventLogGroup("build", 7) @JvmField val TASK_RUNNER: StringListEventField = EventFields.StringListValidatedByCustomRule("task_runner_class", ClassNameRuleValidator::class.java) @@ -23,13 +20,16 @@ class ProjectTaskManagerStatisticsCollector : CounterUsagesCollector() { @JvmField val INCREMENTAL: BooleanEventField = EventFields.Boolean("incremental") + @JvmField + val BUILD_ORIGINATOR: StringEventField = EventFields.StringValidatedByCustomRule("build_originator", ClassNameRuleValidator::class.java) + @JvmField val HAS_ERRORS: BooleanEventField = EventFields.Boolean("has_errors") @JvmField val BUILD_ACTIVITY: IdeActivityDefinition = GROUP.registerIdeActivity(null, - startEventAdditionalFields = arrayOf(TASK_RUNNER, EventFields.PluginInfo, MODULES, INCREMENTAL), - finishEventAdditionalFields = arrayOf(HAS_ERRORS)) + startEventAdditionalFields = arrayOf(TASK_RUNNER, EventFields.PluginInfo, MODULES, INCREMENTAL, BUILD_ORIGINATOR), + finishEventAdditionalFields = arrayOf(TASK_RUNNER, MODULES, INCREMENTAL, BUILD_ORIGINATOR, HAS_ERRORS)) } override fun getGroup(): EventLogGroup { diff --git a/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/CodeFloatingToolbar.kt b/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/CodeFloatingToolbar.kt index b08f50afac04..d2a6b73c9792 100644 --- a/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/CodeFloatingToolbar.kt +++ b/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/CodeFloatingToolbar.kt @@ -7,6 +7,7 @@ import com.intellij.codeInsight.template.impl.TemplateManagerImpl import com.intellij.ide.ui.customization.CustomActionsSchema import com.intellij.openapi.actionSystem.ActionGroup import com.intellij.openapi.actionSystem.DefaultActionGroup +import com.intellij.openapi.actionSystem.Separator import com.intellij.openapi.actionSystem.impl.FloatingToolbar import com.intellij.openapi.actionSystem.impl.MoreActionGroup import com.intellij.openapi.editor.Editor @@ -21,6 +22,7 @@ import com.intellij.psi.PsiElement import com.intellij.ui.LightweightHint import kotlinx.coroutines.CoroutineScope import java.awt.Point +import javax.swing.JComponent /** * Represents floating toolbar which is shown for selected text inside editor. @@ -35,8 +37,8 @@ class CodeFloatingToolbar( private val FLOATING_TOOLBAR = Key("floating.codeToolbar") @JvmStatic - fun getToolbar(editor: Editor): CodeFloatingToolbar? { - return editor.getUserData(FLOATING_TOOLBAR) + fun getToolbar(editor: Editor?): CodeFloatingToolbar? { + return editor?.getUserData(FLOATING_TOOLBAR) } } @@ -55,12 +57,13 @@ class CodeFloatingToolbar( override fun disableForDoubleClickSelection(): Boolean = true - override fun shouldReviveAfterClose(): Boolean = false - override fun shouldSurviveDocumentChange(): Boolean = false override fun hideByOtherHints(): Boolean = false + val hintComponent: JComponent? + get() = hint?.component + override fun getHintPosition(hint: LightweightHint): Point { val selectionEnd = editor.selectionModel.selectionEnd val selectionStart = editor.selectionModel.selectionStart @@ -71,7 +74,7 @@ class CodeFloatingToolbar( val offsetForHint = when { isOneLineSelection -> selectionStart isBelow -> getOffsetForLine(editor, getLineByVisualStart(editor, selectionEnd, true)) - else -> getOffsetForLine(editor, getLineByVisualStart(editor, selectionEnd, false)) + else -> getOffsetForLine(editor, getLineByVisualStart(editor, selectionStart, false)) } val visualPosition = editor.offsetToVisualPosition(offsetForHint) val hintPoint = HintManagerImpl.getHintPosition(hint, editor, visualPosition, HintManager.DEFAULT) @@ -118,8 +121,9 @@ class CodeFloatingToolbar( override fun createActionGroup(): ActionGroup? { val contextAwareActionGroupId = getContextAwareGroupId() val mainActionGroup = CustomActionsSchema.getInstance().getCorrectedAction(contextAwareActionGroupId) as? ActionGroup ?: return super.createActionGroup() + val showIntentionsAction = CustomActionsSchema.getInstance().getCorrectedAction("ShowIntentionActions") ?: error("Can't find ShowIntentionActions action") val configurationGroup = createConfigureGroup(contextAwareActionGroupId) - return DefaultActionGroup(mainActionGroup, configurationGroup) + return DefaultActionGroup(showIntentionsAction, Separator.create(), mainActionGroup, Separator.create(), configurationGroup) } private fun getContextAwareGroupId(): String { diff --git a/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/DisableCodeFloatingToolbarAction.kt b/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/DisableCodeFloatingToolbarAction.kt index 197efb4ac9bd..d7d9b0503ad6 100644 --- a/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/DisableCodeFloatingToolbarAction.kt +++ b/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/DisableCodeFloatingToolbarAction.kt @@ -3,10 +3,13 @@ package com.intellij.ui.codeFloatingToolbar import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.options.advanced.AdvancedSettings class DisableCodeFloatingToolbarAction: AnAction() { override fun actionPerformed(e: AnActionEvent) { AdvancedSettings.setBoolean("floating.codeToolbar.hide", true) + val editor = e.dataContext.getData(CommonDataKeys.EDITOR) + CodeFloatingToolbar.getToolbar(editor)?.scheduleHide() } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/DropdownActionGroup.kt b/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/DropdownActionGroup.kt index 70a3482346c0..d769e476f252 100644 --- a/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/DropdownActionGroup.kt +++ b/platform/lang-impl/src/com/intellij/ui/codeFloatingToolbar/DropdownActionGroup.kt @@ -4,7 +4,6 @@ package com.intellij.ui.codeFloatingToolbar import com.intellij.openapi.actionSystem.* import com.intellij.openapi.actionSystem.ex.CustomComponentAction import com.intellij.openapi.actionSystem.impl.ActionButtonWithText -import com.intellij.ui.popup.PopupFactoryImpl import javax.swing.JComponent class DropdownActionGroup: DefaultActionGroup(), CustomComponentAction { @@ -12,12 +11,7 @@ class DropdownActionGroup: DefaultActionGroup(), CustomComponentAction { override fun createCustomComponent(presentation: Presentation, place: String): JComponent { return object: ActionButtonWithText(this, presentation, place, ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE) { override fun actionPerformed(event: AnActionEvent) { - val group = this@DropdownActionGroup - val popupPlace = ActionPlaces.getPopupPlace(place) - val context = event.dataContext - val popup = PopupFactoryImpl.getInstance().createActionGroupPopup(null, group, context, null, true, popupPlace) - popup.setRequestFocus(false) - popup.showUnderneathOf(this) + showActionGroupPopup(this@DropdownActionGroup, event) } } } diff --git a/platform/platform-api/resources/messages/IdeBundle.properties b/platform/platform-api/resources/messages/IdeBundle.properties index 9f81f5f46d7f..33d01aa249ac 100644 --- a/platform/platform-api/resources/messages/IdeBundle.properties +++ b/platform/platform-api/resources/messages/IdeBundle.properties @@ -2373,6 +2373,7 @@ dialog.message.no.message=No message dialog.text.error.getting.value=Error getting value: {0} recent.project.unavailable=(unavailable) search.everywhere.command.plugins=Plugins: {0} +progress.third.party.software=Loading Third-Party Software Licenses dialog.title.third.party.software=Third-Party Software Used by {0} {1} status.bar.text.script.execution.finished=Script execution finished status.bar.message.at.line=Line {0}: {1} diff --git a/platform/platform-api/src/com/intellij/ui/jcef/JBCefPsiNavigationUtils.kt b/platform/platform-api/src/com/intellij/ui/jcef/JBCefPsiNavigationUtils.kt index 0c819d7dac37..c7e5851cad7a 100644 --- a/platform/platform-api/src/com/intellij/ui/jcef/JBCefPsiNavigationUtils.kt +++ b/platform/platform-api/src/com/intellij/ui/jcef/JBCefPsiNavigationUtils.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.fileEditor.OpenFileDescriptor import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.util.text.LineColumn import com.intellij.openapi.vfs.VirtualFileManager import org.jetbrains.annotations.NonNls import java.nio.file.Paths @@ -19,6 +20,14 @@ object JBCefPsiNavigationUtils { fun navigateTo(requestLink: String): Boolean { val (filePath, offset) = parsePsiElementCoordinates(requestLink) ?: return false + return navigateTo(filePath, offset) + } + + fun navigateTo(filePath: String, lineColumn: LineColumn): Boolean { + return navigateTo(filePath, null, lineColumn) + } + + private fun navigateTo(filePath: String, offset: Int?, lineColumn: LineColumn? = null): Boolean { DataManager.getInstance().dataContextFromFocusAsync.onSuccess { dataContext -> val project = CommonDataKeys.PROJECT.getData(dataContext) ?: return@onSuccess val virtualFile = ProjectRootManager.getInstance(project) @@ -27,9 +36,12 @@ object JBCefPsiNavigationUtils { .mapNotNull(VirtualFileManager.getInstance()::findFileByNioPath) .firstOrNull() ?: return@onSuccess + val descriptor = offset?.let { OpenFileDescriptor(project, virtualFile, offset) } + ?: lineColumn?.let { OpenFileDescriptor(project, virtualFile, lineColumn.line, lineColumn.column) } + ?: return@onSuccess + ApplicationManager.getApplication().invokeLater { - FileEditorManager.getInstance(project) - .openEditor(OpenFileDescriptor(project, virtualFile, offset), true) + FileEditorManager.getInstance(project).openEditor(descriptor, true) } } return true diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java index 0790c4478ad6..d8b9cb86ef4c 100644 --- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java +++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java @@ -80,6 +80,8 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component private final Color disabledForeground = JBColor.namedColor("Table.disabledForeground", JBColor.gray); private boolean myShowLastHorizontalLine; + private ValueScaler myValueScaler; + public JBTable() { this(new DefaultTableModel()); } @@ -184,7 +186,7 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component protected void onTableChanged(@NotNull TableModelEvent e) { if (!myRowHeightIsExplicitlySet) { - myRowHeight = -1; + setRowHeightWithScaler(-1); } if (e.getType() == TableModelEvent.DELETE && isEmpty() || e.getType() == TableModelEvent.INSERT && !isEmpty() || @@ -239,7 +241,7 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component if (myRowHeight < 0) { try { myRowHeightIsComputing = true; - myRowHeight = calculateRowHeight(); + setRowHeightWithScaler(calculateRowHeight()); } finally { myRowHeightIsComputing = false; @@ -293,19 +295,28 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component @Override public void setRowHeight(int rowHeight) { if (!myUiUpdating) { - myRowHeight = rowHeight; + setRowHeightWithScaler(rowHeight); myRowHeightIsExplicitlySet = true; } // call super to clean rowModel super.setRowHeight(rowHeight); } + private void setRowHeightWithScaler(int rowHeight) { + myRowHeight = rowHeight; + if (myRowHeight < 0) myValueScaler = null; + else myValueScaler = new ValueScaler(myRowHeight); + } + @Override public void updateUI() { myUiUpdating = true; try { super.updateUI(); + myMinRowHeight = null; + if (!myRowHeightIsExplicitlySet) setRowHeightWithScaler(-1); + else if (myValueScaler != null) myRowHeight = myValueScaler.get(); } finally { myUiUpdating = false; diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java b/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java index 7796b2cf2544..9b794d74cd92 100644 --- a/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java +++ b/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java @@ -92,8 +92,11 @@ public final class ConfirmingTrustManager extends ClientOnlyTrustManager { Collection additionalTrustedCertificates = OsCertificatesService.getInstance().getCustomOsSpecificTrustedCertificates(); if (additionalTrustedCertificates.isEmpty()) { - LOG.warn( - "Received an empty list of custom trusted root certificates from the system. Check log above for possible errors, enable debug logging in category 'org.jetbrains.nativecerts' for more information"); + // don't nag developers, on jetbrains developer's machine this list is usually empty on MacOs and Windows + if (!ApplicationManager.getApplication().isUnitTestMode()) { + LOG.warn( + "Received an empty list of custom trusted root certificates from the system. Check log above for possible errors, enable debug logging in category 'org.jetbrains.nativecerts' for more information"); + } return null; } diff --git a/platform/platform-impl/intellij.platform.ide.impl.iml b/platform/platform-impl/intellij.platform.ide.impl.iml index 0bf65f1a5e00..4cb547995fa3 100644 --- a/platform/platform-impl/intellij.platform.ide.impl.iml +++ b/platform/platform-impl/intellij.platform.ide.impl.iml @@ -85,7 +85,13 @@ - + + + + 4b23cda64beade8b78ec80fd321e017a0cc2413e4d73f323d8e617222a0e5d2c + + + diff --git a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/Actions.kt b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/Actions.kt index f57b281ab64f..553493374e43 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/Actions.kt +++ b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/Actions.kt @@ -4,50 +4,14 @@ package com.intellij.codeInsight.inline.completion import com.intellij.codeInsight.hint.HintManagerImpl import com.intellij.codeInsight.inline.completion.InlineCompletionContext.Companion.getInlineCompletionContextOrNull import com.intellij.codeInsight.inline.completion.InlineCompletionContext.Companion.resetInlineCompletionContext +import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.editor.Caret import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.actionSystem.EditorAction import com.intellij.openapi.editor.actionSystem.EditorActionHandler import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler -import com.intellij.openapi.editor.event.CaretEvent -import com.intellij.openapi.editor.event.CaretListener -import com.intellij.openapi.editor.ex.FocusChangeListener import org.jetbrains.annotations.ApiStatus -import java.awt.event.KeyAdapter -import java.awt.event.KeyEvent - -@ApiStatus.Experimental -class InlineCompletionCaretListener : CaretListener { - override fun caretPositionChanged(event: CaretEvent) { - event.editor.resetInlineCompletionContext() - } -} - -@ApiStatus.Experimental -class InlineCompletionFocusListener : FocusChangeListener { - override fun focusGained(editor: Editor) {} - override fun focusLost(editor: Editor) { - editor.resetInlineCompletionContext() - } -} - -@ApiStatus.Experimental -class InlineCompletionKeyListener(private val editor: Editor) : KeyAdapter() { - private val usedKeys = listOf( - KeyEvent.VK_ALT, - KeyEvent.VK_OPEN_BRACKET, - KeyEvent.VK_CLOSE_BRACKET, - KeyEvent.VK_TAB, - ) - - override fun keyReleased(event: KeyEvent) { - if (usedKeys.contains(event.keyCode)) { - return - } - editor.resetInlineCompletionContext() - } -} @ApiStatus.Experimental class InsertInlineCompletionAction : EditorAction(InsertInlineCompletionHandler()), HintManagerImpl.ActionToIgnore { @@ -80,3 +44,16 @@ class EscapeInlineCompletionHandler(val originalHandler: EditorActionHandler) : return originalHandler.isEnabled(editor, caret, dataContext) } } + +@ApiStatus.Experimental +class CallInlineCompletionAction : EditorAction(CallInlineCompletionHandler()), HintManagerImpl.ActionToIgnore { + class CallInlineCompletionHandler : EditorWriteActionHandler() { + override fun doExecute(editor: Editor, caret: Caret?, dataContext: DataContext?) { + if (caret == null) return + val listener = editor.getUserData(InlineCompletionHandler.KEY) ?: return + val file = dataContext?.getData(CommonDataKeys.PSI_FILE) ?: return + + listener.invoke(editor, file, caret) + } + } +} diff --git a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/DebouncedInlineCompletionProvider.kt b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/DebouncedInlineCompletionProvider.kt new file mode 100644 index 000000000000..d8b33b3d3307 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/DebouncedInlineCompletionProvider.kt @@ -0,0 +1,51 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.codeInsight.inline.completion + +import com.intellij.openapi.application.ApplicationManager +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.job +import org.jetbrains.annotations.ApiStatus +import kotlin.coroutines.coroutineContext +import kotlin.time.Duration + +@ApiStatus.Experimental +abstract class DebouncedInlineCompletionProvider : InlineCompletionProvider { + private var jobCall: Job? = null + abstract val delay: Duration + + /** + * Returns a Flow of InlineCompletionElement objects with debounced proposals for the given InlineCompletionRequest. + * Override [delay] to control debounce delay + */ + abstract suspend fun getProposalsDebounced(request: InlineCompletionRequest): Flow + + /** + * Forces the inline completion for the given request. + * Might be useful for direct call, since it does not requires any delays + * + * @return `true` if the inline completion need to be forced, `false` otherwise. + */ + abstract fun force(request: InlineCompletionRequest): Boolean + + override suspend fun getProposals(request: InlineCompletionRequest): Flow { + if (ApplicationManager.getApplication().isUnitTestMode) { + return getProposalsDebounced(request) + } + + if (force(request)) { + jobCall?.cancel() + getProposalsDebounced(request) + } + + return debounce(request) + } + + private suspend fun debounce(request: InlineCompletionRequest): Flow { + jobCall?.cancel() + jobCall = coroutineContext.job + delay(delay) + return getProposalsDebounced(request) + } +} diff --git a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionContext.kt b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionContext.kt index 05060d1df4b6..2e6a1fef8c8d 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionContext.kt +++ b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionContext.kt @@ -2,9 +2,9 @@ package com.intellij.codeInsight.inline.completion import com.intellij.codeInsight.inline.completion.InlineState.Companion.resetInlineCompletionState +import com.intellij.codeInsight.inline.completion.listeners.InlineCompletionKeyListener import com.intellij.openapi.Disposable import com.intellij.openapi.editor.Editor -import com.intellij.openapi.editor.ex.EditorEx import com.intellij.openapi.editor.impl.EditorImpl import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Key @@ -20,13 +20,6 @@ class InlineCompletionContext private constructor(val editor: Editor) : Disposab private var completions = emptyList() private var selectedIndex = -1 - init { - editor.caretModel.addCaretListener(InlineCompletionCaretListener()) - if (editor is EditorEx) { - editor.addFocusListener(InlineCompletionFocusListener()) - } - } - val isCurrentlyDisplayingInlays: Boolean get() = !inlay.isEmpty @@ -87,6 +80,7 @@ class InlineCompletionContext private constructor(val editor: Editor) : Disposab putUserData(INLINE_COMPLETION_CONTEXT, it) } } + fun Editor.getInlineCompletionContextOrNull(): InlineCompletionContext? = getUserData(INLINE_COMPLETION_CONTEXT) fun Editor.removeInlineCompletionContext(): Unit = putUserData(INLINE_COMPLETION_CONTEXT, null) fun Editor.resetInlineCompletionContext(): Unit? = getInlineCompletionContextOrNull()?.let { diff --git a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionEditorListener.kt b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionEditorListener.kt deleted file mode 100644 index 57fe38bb69f4..000000000000 --- a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionEditorListener.kt +++ /dev/null @@ -1,117 +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 com.intellij.codeInsight.inline.completion - -import com.intellij.codeInsight.completion.CompletionUtil -import com.intellij.codeInsight.inline.completion.InlineCompletionContext.Companion.getInlineCompletionContextOrNull -import com.intellij.openapi.Disposable -import com.intellij.openapi.actionSystem.IdeActions -import com.intellij.openapi.actionSystem.ex.ActionUtil -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.editor.EditorKind -import com.intellij.openapi.editor.event.DocumentEvent -import com.intellij.openapi.editor.event.DocumentListener -import com.intellij.openapi.editor.event.EditorFactoryEvent -import com.intellij.openapi.editor.event.EditorFactoryListener -import com.intellij.openapi.editor.impl.EditorImpl -import com.intellij.openapi.project.DumbAwareAction -import com.intellij.openapi.util.Disposer -import com.intellij.openapi.util.Key -import com.intellij.openapi.util.registry.Registry -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.debounce -import org.jetbrains.annotations.ApiStatus - -/** - * Inline completion will be shown only if at least one [InlineCompletionProvider] is enabled and returns at least one proposal - */ -@ApiStatus.Experimental -class InlineCompletionEditorListener(private val scope: CoroutineScope) : EditorFactoryListener { - override fun editorCreated(event: EditorFactoryEvent) { - val editor = event.editor - if (editor.project == null || editor !is EditorImpl || editor.editorKind != EditorKind.MAIN_EDITOR) return - - InlineCompletionDocumentListener(editor, scope).listenForChanges() - } -} - -@Suppress("MemberVisibilityCanBePrivate") -@OptIn(FlowPreview::class) -@ApiStatus.Experimental -class InlineCompletionDocumentListener(private val editor: EditorImpl, private val scope: CoroutineScope) : DocumentListener, Disposable { - private val handler = InlineCompletionHandler(scope) - private var flow = MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) - private var jobCall: Job? = null - - fun isEnabled(event: DocumentEvent): Boolean { - return event.newFragment != CompletionUtil.DUMMY_IDENTIFIER && event.newLength >= 1 - } - - private fun documentChangedDebounced(inlineCompletionEvent: InlineCompletionEvent) { - val (event, providers) = inlineCompletionEvent - if (event.document.isInBulkUpdate) return - - // As PoC inline completion does not support multiple providers - // TODO: handle multiple providers - handler.invoke(event, editor, providers.first()) - } - - fun listenForChanges() { - Disposer.register(editor.disposable, this) - editor.document.addDocumentListener(this, this) - editor.putUserData(KEY, this) - - //overrideCaretMove(editor) - - jobCall = scope.launch(CoroutineName("inline.completion.call")) { - flow.debounce(minDelay) - .collect(::documentChangedDebounced) - } - } - - override fun documentChanged(event: DocumentEvent) { - if (InlineCompletionHandler.isMuted.get() || !isEnabled(event)) { - return - } - - val providers = InlineCompletionProvider.extensions().filter { it.isEnabled(event) } - .takeIf { it.isNotEmpty() } ?: return - val inlineCompletionEvent = InlineCompletionEvent(event, providers) - - if (ApplicationManager.getApplication().isUnitTestMode) { - documentChangedDebounced(inlineCompletionEvent) - } - else { - flow.tryEmit(inlineCompletionEvent) - } - } - - private fun overrideCaretMove(editor: EditorImpl) { - //val moveCaretAction = ActionUtil.getAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT) ?: return - // - //DumbAwareAction.create { - // val toAct = if (editor.getInlineCompletionContextOrNull()?.isCurrentlyDisplayingInlays == true) { - // InsertInlineCompletionAction() - // } - // else { - // moveCaretAction - // } - // - // ActionUtil.performActionDumbAwareWithCallbacks(toAct, it) - //}.registerCustomShortcutSet(moveCaretAction.shortcutSet, editor.component) - } - - override fun dispose() { - editor.putUserData(KEY, null) - jobCall?.cancel() - } - - private data class InlineCompletionEvent(val event: DocumentEvent, val providers: List) - - companion object { - private val KEY = Key.create("inline.completion.listener") - - val minDelay: Long = Registry.get("inline.completion.trigger.delay").asInteger().toLong() - } -} diff --git a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionElements.kt b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionElements.kt index 7fdd2d21fa9d..4a891662eb35 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionElements.kt +++ b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionElements.kt @@ -1,33 +1,116 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.inline.completion +import com.intellij.codeInsight.lookup.LookupElement +import com.intellij.codeInsight.lookup.LookupEvent import com.intellij.openapi.application.ReadAction +import com.intellij.openapi.editor.Caret import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.event.DocumentEvent +import com.intellij.openapi.editor.event.EditorMouseEvent import com.intellij.psi.PsiFile import com.intellij.psi.PsiManager import org.jetbrains.annotations.ApiStatus +private typealias EditorCaret = Caret + @ApiStatus.Experimental data class InlineCompletionRequest( + val event: InlineCompletionEvent, + val file: PsiFile, val editor: Editor, val document: Document, val startOffset: Int, val endOffset: Int, -) { + val lookupElement: LookupElement? = null, +) + +@ApiStatus.Experimental +data class InlineCompletionElement(val text: String) { + fun withText(text: String) = InlineCompletionElement(text) +} + +@ApiStatus.Experimental +sealed interface InlineCompletionEvent { + fun toRequest(): InlineCompletionRequest? + + /** + * A class representing a direct call in the code editor by [InsertInlineCompletionAction]. + */ + @ApiStatus.Experimental + class DirectCall(val editor: Editor, val file: PsiFile, val caret: EditorCaret) : InlineCompletionEvent { + override fun toRequest(): InlineCompletionRequest? { + return InlineCompletionRequest(this, file, editor, editor.document, caret.offset, caret.offset, null) + } + } + + /** + * Represents a non-dummy not empty document event call in the editor. + */ + @ApiStatus.Experimental + class Document(val event: DocumentEvent, val editor: Editor) : InlineCompletionEvent { + override fun toRequest(): InlineCompletionRequest? { + val virtualFile = editor.virtualFile ?: return null + val project = editor.project ?: return null + if (editor.caretModel.caretCount != 1) return null + + val file = ReadAction.compute { PsiManager.getInstance(project).findFile(virtualFile) } + + return InlineCompletionRequest(this, file, editor, event.document, event.offset, event.offset + event.newLength, null) + } + } + + + /** + * Represents a caret move event only in selected editor. + * + * Be careful with this one because it might duplicate document events. It worth to add check for "non-simple offset change" + * ``` + * if (event.oldPosition.line == event.newPosition.line && event.oldPosition.column + 1 == event.newPosition.column) { + * return + * } + * ``` + */ + @ApiStatus.Experimental + class Caret(val event: EditorMouseEvent) : InlineCompletionEvent { + override fun toRequest(): InlineCompletionRequest? { + val editor = event.editor + val virtualFile = editor.virtualFile ?: return null + val project = editor.project ?: return null + if (editor.caretModel.caretCount != 1) return null + + val file = ReadAction.compute { PsiManager.getInstance(project).findFile(virtualFile) } + + val offset = ReadAction.compute { editor.caretModel.offset } + + return InlineCompletionRequest(this, file, editor, editor.document, offset, offset, null) + } + } + + /** + * A class representing a lookup event. + * + * This class implements the [InlineCompletionEvent] interface and provides a method to convert the event to a request + * using the [toRequest] method. + * + * @param event The lookup event. + */ + @ApiStatus.Experimental + class Lookup(val event: LookupEvent) : InlineCompletionEvent { + override fun toRequest(): InlineCompletionRequest? { + val item = event.item ?: return null + val editor = event.lookup?.editor ?: return null + if (editor.caretModel.caretCount != 1) return null - companion object { - fun fromDocumentEvent(event: DocumentEvent, editor: Editor): InlineCompletionRequest? { val virtualFile = editor.virtualFile ?: return null val project = editor.project ?: return null val file = ReadAction.compute { PsiManager.getInstance(project).findFile(virtualFile) } - return InlineCompletionRequest(file, editor, event.document, event.offset, event.offset + event.newLength) + val offset = ReadAction.compute { editor.caretModel.offset } + + return InlineCompletionRequest(this, file, editor, editor.document, offset, offset, item) } } } - -@ApiStatus.Experimental -data class InlineCompletionElement(val text: String) diff --git a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionHandler.kt b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionHandler.kt index 312c93af7c05..af46e39af74e 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionHandler.kt +++ b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionHandler.kt @@ -5,46 +5,78 @@ import com.intellij.codeInsight.CodeInsightActionHandler import com.intellij.codeInsight.inline.completion.InlineCompletionContext.Companion.initOrGetInlineCompletionContext import com.intellij.codeInsight.inline.completion.InlineState.Companion.getInlineCompletionState import com.intellij.codeInsight.inline.completion.InlineState.Companion.initOrGetInlineCompletionState +import com.intellij.codeInsight.lookup.LookupEvent +import com.intellij.codeInsight.lookup.LookupManager import com.intellij.openapi.application.EDT +import com.intellij.openapi.editor.Caret import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.event.DocumentEvent +import com.intellij.openapi.editor.event.EditorMouseEvent import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key import com.intellij.psi.PsiFile -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collectIndexed +import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.flow.takeWhile import org.jetbrains.annotations.ApiStatus import java.util.concurrent.atomic.AtomicBoolean @ApiStatus.Experimental class InlineCompletionHandler(private val scope: CoroutineScope) : CodeInsightActionHandler { + private var runningJob: Job? = null + + private fun getProvider(event: InlineCompletionEvent): InlineCompletionProvider? { + return InlineCompletionProvider.extensions().filter { it.isEnabled(event) }.firstOrNull() + } + override fun invoke(project: Project, editor: Editor, file: PsiFile) { val inlineState = editor.getInlineCompletionState() ?: return showInlineSuggestion(editor, inlineState, editor.caretModel.offset) } - fun invoke(event: DocumentEvent, editor: Editor, provider: InlineCompletionProvider) { - val request = InlineCompletionRequest.fromDocumentEvent(event, editor) ?: return - invoke(request, provider) - } + fun invoke(event: DocumentEvent, editor: Editor) = invoke(InlineCompletionEvent.Document(event, editor)) + fun invoke(event: EditorMouseEvent) = invoke(InlineCompletionEvent.Caret(event)) + fun invoke(event: LookupEvent) = invoke(InlineCompletionEvent.Lookup(event)) + fun invoke(editor: Editor, file: PsiFile, caret: Caret) = invoke(InlineCompletionEvent.DirectCall(editor, file, caret)) - fun invoke(request: InlineCompletionRequest, provider: InlineCompletionProvider) { - scope.launch { + private fun invoke(event: InlineCompletionEvent) { + if (isMuted.get()) { + return + } + val request = event.toRequest() ?: return + val provider = getProvider(event) ?: return + + runningJob?.cancel() + runningJob = scope.launch { val modificationStamp = request.document.modificationStamp - val result = provider.getProposals(request) + val resultFlow = provider.getProposals(request) val editor = request.editor val offset = request.endOffset val inlineState = editor.initOrGetInlineCompletionState() - if (modificationStamp == request.document.modificationStamp) { - inlineState.suggestions = result - } withContext(Dispatchers.EDT) { - showInlineSuggestion(editor, inlineState, offset) + resultFlow.let { + // In case lookup is shown - request must be only single line, due to lookup render issues + if (LookupManager.getActiveLookup(request.editor) != null) { + it.takeFirstLine() + } + else { + it + } + }.collectIndexed { index, value -> + if (index == 0 && modificationStamp != request.document.modificationStamp) { + cancel() + return@collectIndexed + } + + inlineState.suggestions = listOf(InlineCompletionElement(value.text)) + showInlineSuggestion(editor, inlineState, offset) + } } } } @@ -70,7 +102,23 @@ class InlineCompletionHandler(private val scope: CoroutineScope) : CodeInsightAc inlineContext.lastModificationStamp = editor.document.modificationStamp } + @OptIn(ExperimentalCoroutinesApi::class) + private fun Flow.takeFirstLine(): Flow { + var found = false + return takeWhile { + val value = it.text + !found.also { + if (value.contains("\n")) found = true + } + }.mapLatest { + it.withText(it.text.takeWhile { c -> c != '\n' }) + } + } + + companion object { + val KEY = Key.create("inline.completion.handler") + val isMuted: AtomicBoolean = AtomicBoolean(false) fun mute(): Unit = isMuted.set(true) fun unmute(): Unit = isMuted.set(false) diff --git a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionProvider.kt b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionProvider.kt index 62b4de3c77f1..ab16e64e73b4 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionProvider.kt +++ b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/InlineCompletionProvider.kt @@ -1,20 +1,36 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.inline.completion -import com.intellij.openapi.editor.event.DocumentEvent import com.intellij.openapi.extensions.ExtensionPointName +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.emptyFlow import org.jetbrains.annotations.ApiStatus /** * Proposals provider for inline completion. - * Implement [getProposals] method to return a list of proposals and [isEnabled] to control if a provider need to be called. - * Inline completion has a user type delay. By default, it's 300ms. You can change it by modifying `inline.completion.listener` registry value (@see [InlineCompletionDocumentListener]) + * + * The [getProposals] method should return a [Flow] of [InlineCompletionElement] objects representing the proposals for completion. + * The [isEnabled] method should be implemented to control whether the provider should be called for a particular [InlineCompletionEvent]. + * + * #### Things to note: + * - Currently delay ([Flow.debounce]) for [InlineCompletionEvent.Document] is disabled and might be implemented later. + * You may implement it on provider side or use [DebouncedInlineCompletionProvider] as a entrypoint, + * otherwise, proposals will be generated/canceled on each typing. + * - Any inline completion request will be cancelled if inline is in rendering mode + * - In case a newer inline completion proposals are generated, previous call will be cancelled and hidden + * + * @see InlineCompletionElement + * @see InlineCompletionRequest + * @see InlineCompletionEvent + * + * @since experimental API */ @ApiStatus.Experimental interface InlineCompletionProvider { - suspend fun getProposals(request: InlineCompletionRequest): List + suspend fun getProposals(request: InlineCompletionRequest): Flow - fun isEnabled(event: DocumentEvent): Boolean + fun isEnabled(event: InlineCompletionEvent): Boolean companion object { private val EP_NAME = ExtensionPointName.create("com.intellij.inline.completion.provider") @@ -22,7 +38,8 @@ interface InlineCompletionProvider { } object DUMMY : InlineCompletionProvider { - override suspend fun getProposals(request: InlineCompletionRequest): List = emptyList() - override fun isEnabled(event: DocumentEvent): Boolean = true + override suspend fun getProposals(request: InlineCompletionRequest): Flow = emptyFlow() + override fun isEnabled(event: InlineCompletionEvent): Boolean = false } } + diff --git a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/listeners/InlineCompletionEditorListener.kt b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/listeners/InlineCompletionEditorListener.kt new file mode 100644 index 000000000000..bf284bfef55e --- /dev/null +++ b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/listeners/InlineCompletionEditorListener.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 com.intellij.codeInsight.inline.completion.listeners + +import com.intellij.codeInsight.inline.completion.InlineCompletionHandler +import com.intellij.codeInsight.inline.completion.InlineCompletionProvider +import com.intellij.openapi.editor.EditorKind +import com.intellij.openapi.editor.event.EditorFactoryEvent +import com.intellij.openapi.editor.event.EditorFactoryListener +import com.intellij.openapi.editor.ex.util.EditorUtil +import com.intellij.openapi.editor.impl.EditorImpl +import com.intellij.openapi.util.Disposer +import kotlinx.coroutines.CoroutineScope +import org.jetbrains.annotations.ApiStatus + +/** + * Inline completion will be shown only if at least one [InlineCompletionProvider] is enabled and returns at least one proposal + */ +@ApiStatus.Experimental +class InlineCompletionEditorListener(scope: CoroutineScope) : EditorFactoryListener { + val caretListener = InlineCompletionCaretListener() + val focusListener = InlineCompletionFocusListener() + + val handler = InlineCompletionHandler(scope) + + override fun editorCreated(event: EditorFactoryEvent) { + val editor = event.editor + if (editor.project == null || editor !is EditorImpl || editor.editorKind != EditorKind.MAIN_EDITOR || editor.project?.isDisposed != false) return + + val disposable = Disposer.newDisposable("inline-completion").also { + EditorUtil.disposeWithEditor(editor, it) + } + + editor.putUserData(InlineCompletionHandler.KEY, handler) + val docListener = InlineCompletionDocumentListener(editor) + + editor.document.addDocumentListener(docListener, disposable) + editor.addEditorMouseListener(caretListener, disposable) + editor.addFocusListener(focusListener, disposable) + } + + override fun editorReleased(event: EditorFactoryEvent) { + event.editor.putUserData(InlineCompletionHandler.KEY, null) + } +} + + diff --git a/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/listeners/InlineCompletionListeners.kt b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/listeners/InlineCompletionListeners.kt new file mode 100644 index 000000000000..ba42783405ad --- /dev/null +++ b/platform/platform-impl/src/com/intellij/codeInsight/inline/completion/listeners/InlineCompletionListeners.kt @@ -0,0 +1,89 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.codeInsight.inline.completion.listeners + +import com.intellij.codeInsight.completion.CompletionUtil +import com.intellij.codeInsight.inline.completion.InlineCompletionContext.Companion.resetInlineCompletionContext +import com.intellij.codeInsight.inline.completion.InlineCompletionHandler +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.editor.event.DocumentEvent +import com.intellij.openapi.editor.event.DocumentListener +import com.intellij.openapi.editor.event.EditorMouseEvent +import com.intellij.openapi.editor.event.EditorMouseListener +import com.intellij.openapi.editor.ex.FocusChangeListener +import com.intellij.openapi.editor.impl.EditorImpl +import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.fileEditor.TextEditor +import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl +import org.jetbrains.annotations.ApiStatus +import java.awt.event.KeyAdapter +import java.awt.event.KeyEvent + +@ApiStatus.Experimental +class InlineCompletionDocumentListener(private val editor: EditorImpl) : DocumentListener { + override fun documentChanged(event: DocumentEvent) { + if (!isEnabled(event) || event.document.isInBulkUpdate) { + return + } + + if (event.document.isInBulkUpdate) return + editor.getUserData(InlineCompletionHandler.KEY)?.invoke(event, editor) + } + + fun isEnabled(event: DocumentEvent): Boolean { + return event.newFragment != CompletionUtil.DUMMY_IDENTIFIER && event.newLength >= 1 + } +} + +@ApiStatus.Experimental +class InlineCompletionCaretListener : EditorMouseListener { + override fun mouseClicked(event: EditorMouseEvent) { + super.mouseClicked(event) + + // Check that edit is selected and opened + if (!event.editor.isSelected()) { + return + } + event.editor.resetInlineCompletionContext() + event.editor.getUserData(InlineCompletionHandler.KEY)?.invoke(event) + } + + private fun Editor.isSelected(): Boolean { + val project = this.project ?: return false + if (project.isDisposed()) { + return false + } + val editorManager = FileEditorManager.getInstance(project) ?: return false + + if (editorManager is FileEditorManagerImpl) { + val current = editorManager.getSelectedTextEditor(true) + return current != null && current == this + } + + val current = editorManager.getSelectedEditor() + return current is TextEditor && this == current.getEditor() + } +} + +@ApiStatus.Experimental +class InlineCompletionKeyListener(private val editor: Editor) : KeyAdapter() { + private val usedKeys = listOf( + KeyEvent.VK_ALT, + KeyEvent.VK_OPEN_BRACKET, + KeyEvent.VK_CLOSE_BRACKET, + KeyEvent.VK_TAB, + ) + + override fun keyReleased(event: KeyEvent) { + if (usedKeys.contains(event.keyCode)) { + return + } + editor.resetInlineCompletionContext() + } +} + +@ApiStatus.Experimental +class InlineCompletionFocusListener : FocusChangeListener { + override fun focusLost(editor: Editor) { + editor.resetInlineCompletionContext() + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/AboutPopupDescriptionProvider.kt b/platform/platform-impl/src/com/intellij/ide/AboutPopupDescriptionProvider.kt index 11b1b411f1ae..cd57568d8293 100644 --- a/platform/platform-impl/src/com/intellij/ide/AboutPopupDescriptionProvider.kt +++ b/platform/platform-impl/src/com/intellij/ide/AboutPopupDescriptionProvider.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide import com.intellij.openapi.util.NlsContexts.DetailedDescription @@ -10,7 +10,7 @@ import com.intellij.openapi.util.NlsContexts.DetailedDescription */ interface AboutPopupDescriptionProvider { /** - * Return additional info which should be shown in About popup. + * Return additional info which should be shown in the "About" dialog. */ fun getDescription(): @DetailedDescription String? -} \ No newline at end of file +} diff --git a/platform/platform-impl/src/com/intellij/ide/ProjectWindowCustomizerService.kt b/platform/platform-impl/src/com/intellij/ide/ProjectWindowCustomizerService.kt index bf4d5675294a..f3234d4d4bfb 100644 --- a/platform/platform-impl/src/com/intellij/ide/ProjectWindowCustomizerService.kt +++ b/platform/platform-impl/src/com/intellij/ide/ProjectWindowCustomizerService.kt @@ -7,6 +7,7 @@ import com.intellij.ide.ui.UISettings import com.intellij.ide.ui.UISettingsListener import com.intellij.ide.util.PropertiesComponent import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.project.Project @@ -21,6 +22,7 @@ import com.intellij.ui.GotItTooltip import com.intellij.ui.JBColor import com.intellij.util.PlatformUtils import com.intellij.util.concurrency.SynchronizedClearableLazy +import com.intellij.util.concurrency.annotations.RequiresBlockingContext import com.intellij.util.ui.ColorPalette import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.job @@ -62,7 +64,7 @@ private class ProjectWindowCustomizerIconCache(private val project: Project) { } } -enum class MainToolbarCustomizationType { +internal enum class MainToolbarCustomizationType { JUST_ICON, LINEAR_GRAD_WITH_ICON, CIRCULAR_GRADIENT_WITH_ICON, @@ -78,15 +80,34 @@ enum class MainToolbarCustomizationType { private const val TOOLBAR_BACKGROUND_KEY = "PROJECT_TOOLBAR_COLOR" +private fun isForceColorfulToolbar() = Registry.`is`("ide.colorful.toolbar.force", true) + +private fun conditionToEnable() = isForceColorfulToolbar() || ProjectManagerEx.getOpenProjects().size > 1 + @Service class ProjectWindowCustomizerService : Disposable { companion object { - fun getInstance(): ProjectWindowCustomizerService = service() + private var instance: ProjectWindowCustomizerService? = null + + init { + ApplicationManager.registerCleaner { instance = null } + } + + @RequiresBlockingContext + fun getInstance(): ProjectWindowCustomizerService { + var result = instance + if (result == null) { + result = service() + instance = result + } + return result + } } - private data class ProjectColors(val gradient: Color, val background: Color) + private data class ProjectColors(@JvmField val gradient: Color, @JvmField val background: Color) + + private var wasGradientPainted = isForceColorfulToolbar() - private var wasGradientPainted = false private var ourSettingsValue = UISettings.getInstance().differentiateProjects private val colorCache = mutableMapOf() private val listeners = mutableListOf<(Boolean) -> Unit>() @@ -139,13 +160,15 @@ class ProjectWindowCustomizerService : Disposable { } } - fun getPaintingType() = when (Registry.get("ide.colorful.toolbar.gradient.type").selectedOption) { + internal fun getPaintingType(): MainToolbarCustomizationType { + return when (Registry.get("ide.colorful.toolbar.gradient.type").selectedOption) { "Just Icon" -> MainToolbarCustomizationType.JUST_ICON "Linear Gradient and Icon" -> MainToolbarCustomizationType.LINEAR_GRAD_WITH_ICON "Circular Gradient and Icon" -> MainToolbarCustomizationType.CIRCULAR_GRADIENT_WITH_ICON "Dropdown Background and Icon" -> MainToolbarCustomizationType.DROPDOWN_WITH_ICON "Just Dropdown" -> MainToolbarCustomizationType.JUST_DROPDOWN else -> MainToolbarCustomizationType.LINEAR_GRAD_WITH_ICON + } } internal fun update(newValue: Boolean) { @@ -176,8 +199,6 @@ class ProjectWindowCustomizerService : Disposable { } } - private fun conditionToEnable() = ProjectManagerEx.getOpenProjects().size > 1 || Registry.`is`("ide.colorful.toolbar.force") - fun addListener(coroutineScope: CoroutineScope, fireFirstTime: Boolean, listener: (Boolean) -> Unit) { if (fireFirstTime) { listener(isActive()) @@ -219,13 +240,13 @@ class ProjectWindowCustomizerService : Disposable { * @return true if method painted something */ fun paint(project: Project, parent: JComponent, g: Graphics2D): Boolean { - g.color = parent.background - g.fillRect(0, 0, parent.width, parent.height) - if (!isActive() || !getPaintingType().isGradient()) { return false } + g.color = parent.background + g.fillRect(0, 0, parent.width, parent.height) + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY) val color = getGradientProjectColor(project) @@ -245,7 +266,9 @@ class ProjectWindowCustomizerService : Disposable { } fun getToolbarBackground(project: Project?):Color? { - if (project == null) return null + if (project == null) { + return null + } return getBackgroundProjectColor(project) } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/AboutAction.java b/platform/platform-impl/src/com/intellij/ide/actions/AboutAction.java index 0bdc00aa3bf2..014c414a9db1 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/AboutAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/AboutAction.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 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. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide.actions; import com.intellij.ide.lightEdit.LightEditCompatible; @@ -7,8 +7,6 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.wm.WindowManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,11 +28,6 @@ public class AboutAction extends AnAction implements DumbAware, LightEditCompati } public static void perform(@Nullable Project project) { - if (Registry.is("ide.new.about.dialog")) { - new AboutDialog(project).show(); - } - else { - AboutPopup.show(WindowManager.getInstance().suggestParentWindow(project), false); - } + new AboutDialog(project).show(); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java b/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java index e7a52b9cffac..be22614f93d2 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java @@ -1,53 +1,76 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide.actions; +import com.intellij.CommonBundle; import com.intellij.ide.AboutPopupDescriptionProvider; import com.intellij.ide.IdeBundle; import com.intellij.ide.nls.NlsMessages; +import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ApplicationNamesInfo; +import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.ex.ApplicationInfoEx; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.ide.CopyPasteManager; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.NlsContexts; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.AppUIUtil; -import com.intellij.ui.HyperlinkAdapter; -import com.intellij.ui.HyperlinkLabel; -import com.intellij.ui.LicensingFacade; +import com.intellij.openapi.util.NlsSafe; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtilRt; +import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.registry.RegistryValue; +import com.intellij.openapi.vfs.DiskQueryRelay; +import com.intellij.ui.*; import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBScrollPane; +import com.intellij.ui.scale.JBUIScale; import com.intellij.ui.scale.ScaleContext; -import com.intellij.util.ObjectUtils; -import com.intellij.util.ui.JBFont; -import com.intellij.util.ui.JBUI; +import com.intellij.util.PlatformUtils; +import com.intellij.util.ui.*; import com.intellij.util.ui.components.BorderLayoutPanel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.HyperlinkEvent; +import javax.swing.text.html.HTMLDocument; import java.awt.*; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; +import java.io.IOException; +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import java.nio.file.Files; +import java.nio.file.Path; import java.text.DateFormat; import java.text.MessageFormat; import java.text.SimpleDateFormat; +import java.time.LocalDate; import java.util.List; import java.util.*; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static java.util.Objects.requireNonNullElse; +import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER; +import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED; -/** - * @author Konstantin Bulenkov - */ public class AboutDialog extends DialogWrapper { + private static final ExtensionPointName EP_NAME = new ExtensionPointName<>("com.intellij.aboutPopupDescriptionProvider"); /** - * Use paragraph to support copy/paste multilines + * See {@link org.jetbrains.intellij.build.impl.DistributionJARsBuilderKt#createBuildThirdPartyLibraryListJob}. */ - private static final String EOL = "

"; + private static final String THIRD_PARTY_LIBRARIES_FILE = "license/third-party-libraries.html"; private final List myInfo = new ArrayList<>(); @@ -64,7 +87,7 @@ public class AboutDialog extends DialogWrapper { protected JComponent createSouthPanel() { JComponent result = super.createSouthPanel(); - // Register copy action on buttons panel only, because it conflicts with copyable labels in center panel + // Registering the copy action only on the buttons panel, because it conflicts with copyable labels in the center panel new DumbAwareAction() { @Override public void actionPerformed(@NotNull AnActionEvent e) { @@ -115,16 +138,12 @@ public class AboutDialog extends DialogWrapper { catch (Exception ignore) { } } - public String getExtendedAboutText() { - return StringUtil.join(myInfo, "\n") + "\n" + AboutPopup.getExtraInfo(); - } - - @SuppressWarnings("DuplicatedCode") private Box getText() { Box box = Box.createVerticalBox(); List lines = new ArrayList<>(); ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx(); - String appName = appInfo.getFullApplicationName(); //NON-NLS + + @NlsSafe String appName = appInfo.getFullApplicationName(); String edition = ApplicationNamesInfo.getInstance().getEditionName(); if (edition != null) appName += " (" + edition + ")"; box.add(label(appName, JBFont.h3().asBold())); @@ -133,17 +152,16 @@ public class AboutDialog extends DialogWrapper { String buildInfo = IdeBundle.message("about.box.build.number", appInfo.getBuild().asString()); String buildInfoNonLocalized = MessageFormat.format("Build #{0}", appInfo.getBuild().asString()); - Date timestamp = appInfo.getBuildDate().getTime(); + Date buildDate = appInfo.getBuildDate().getTime(); + String formattedBuildDate = DateFormat.getDateInstance(DateFormat.LONG, Locale.US).format(buildDate); if (appInfo.getBuild().isSnapshot()) { - String time = new SimpleDateFormat("HH:mm").format(timestamp); - buildInfo += IdeBundle.message("about.box.build.date.time", NlsMessages.formatDateLong(timestamp), time); - buildInfoNonLocalized += MessageFormat.format(", built on {0} at {1}", - DateFormat.getDateInstance(DateFormat.LONG, Locale.US).format(timestamp), time); + String buildTime = new SimpleDateFormat("HH:mm").format(buildDate); + buildInfo += IdeBundle.message("about.box.build.date.time", NlsMessages.formatDateLong(buildDate), buildTime); + buildInfoNonLocalized += MessageFormat.format(", built on {0} at {1}", formattedBuildDate, buildTime); } else { - buildInfo += IdeBundle.message("about.box.build.date", NlsMessages.formatDateLong(timestamp)); - buildInfoNonLocalized += MessageFormat.format(", built on {0}", - DateFormat.getDateInstance(DateFormat.LONG, Locale.US).format(timestamp)); + buildInfo += IdeBundle.message("about.box.build.date", NlsMessages.formatDateLong(buildDate)); + buildInfoNonLocalized += MessageFormat.format(", built on {0}", formattedBuildDate); } lines.add(buildInfo); lines.add(""); @@ -151,7 +169,7 @@ public class AboutDialog extends DialogWrapper { LicensingFacade la = LicensingFacade.getInstance(); if (la != null) { - final String licensedTo = la.getLicensedToMessage(); //NON-NLS + String licensedTo = la.getLicensedToMessage(); if (licensedTo != null) { lines.add(licensedTo); myInfo.add(licensedTo); @@ -179,14 +197,14 @@ public class AboutDialog extends DialogWrapper { //Print extra information from plugins ExtensionPointName ep = new ExtensionPointName<>("com.intellij.aboutPopupDescriptionProvider"); for (AboutPopupDescriptionProvider aboutInfoProvider : ep.getExtensions()) { - String description = aboutInfoProvider.getDescription(); //NON-NLS + String description = aboutInfoProvider.getDescription(); if (description != null) { lines.add(description); lines.add(""); } } - String text = String.join(EOL, lines); //NON-NLS + @NlsSafe String text = String.join("

", lines); // joining with paragraph separators for better-looking copied text box.add(label(text, getDefaultTextFont())); addEmptyLine(box); @@ -197,7 +215,7 @@ public class AboutDialog extends DialogWrapper { openSourceSoftware.addHyperlinkListener(new HyperlinkAdapter() { @Override protected void hyperlinkActivated(@NotNull HyperlinkEvent e) { - AboutPopup.showOpenSoftwareSources(ObjectUtils.notNull(AboutPopup.loadThirdPartyLibraries(), "")); + showOssInfo(box); } }); openSourceSoftware.setFont(getDefaultTextFont()); @@ -207,7 +225,9 @@ public class AboutDialog extends DialogWrapper { box.add(panel); //Copyright - box.add(label(AboutPopup.getCopyrightText(), getDefaultTextFont())); + int year = LocalDate.now().getYear(); + @NlsSafe String copyrightText = String.format(Locale.ROOT, "Copyright © %s–%d %s", appInfo.getCopyrightStart(), year, appInfo.getCompanyName()); + box.add(label(copyrightText, getDefaultTextFont())); addEmptyLine(box); return box; @@ -226,4 +246,127 @@ public class AboutDialog extends DialogWrapper { label.setCopyable(true); return label; } + + public String getExtendedAboutText() { + var text = new StringBuilder(); + + myInfo.forEach(s -> text.append(s).append('\n')); + + text.append(SystemInfo.getOsNameAndVersion()).append('\n'); + + for (var aboutInfoProvider : EP_NAME.getExtensions()) { + var description = aboutInfoProvider.getDescription(); + if (description != null) { + text.append(description).append('\n'); + } + } + + text.append("GC: ") + .append(ManagementFactory.getGarbageCollectorMXBeans().stream().map(GarbageCollectorMXBean::getName).collect(Collectors.joining(", "))) + .append('\n'); + + text.append("Memory: ").append(Runtime.getRuntime().maxMemory() / FileUtilRt.MEGABYTE).append("M\n"); + + text.append("Cores: ").append(Runtime.getRuntime().availableProcessors()).append('\n'); + + if (UIUtil.isMetalRendering()) { + text.append("Metal Rendering is ON\n"); + } + + var changedValues = Registry.getAll().stream().filter(RegistryValue::isChangedFromDefault).toList(); + if (!changedValues.isEmpty()) { + text.append("Registry:\n"); + changedValues.forEach(v -> text.append(" ").append(v.getKey()).append('=').append(v.asString()).append('\n')); + } + + var extraPlugins = PluginManagerCore.getLoadedPlugins().stream().filter(p -> !p.isBundled()).toList(); + if (!extraPlugins.isEmpty()) { + text.append("Non-Bundled Plugins:\n"); + extraPlugins.forEach(p -> text.append(" ").append(p.getPluginId().getIdString()).append(" (").append(p.getVersion()).append(")\n")); + } + + if (PlatformUtils.isIntelliJ()) { + var kotlinPlugin = PluginManagerCore.getPlugin(PluginId.findId("org.jetbrains.kotlin")); + if (kotlinPlugin != null) { + text.append("Kotlin: ").append(kotlinPlugin.getVersion()).append('\n'); + } + } + + if (SystemInfo.isXWindow) { + text.append("Current Desktop: ").append(requireNonNullElse(System.getenv("XDG_CURRENT_DESKTOP"), "Undefined")).append('\n'); + } + + return text.toString(); + } + + private static void showOssInfo(JComponent component) { + @NlsSafe String licenseText; + try { + var title = IdeBundle.message("progress.third.party.software"); + licenseText = ProgressManager.getInstance().run(new Task.WithResult(null, component, title, true) { + @Override + protected String compute(@NotNull ProgressIndicator indicator) throws IOException { + return DiskQueryRelay.compute(() -> { + var content = Files.readString(Path.of(PathManager.getHomePath(), THIRD_PARTY_LIBRARIES_FILE)); + var matcher = Pattern.compile("(\\d+)px").matcher(content); + var sb = new StringBuilder(); + while (matcher.find()) { + matcher.appendReplacement(sb, JBUIScale.scale(Integer.parseInt(matcher.group(1))) + "px"); + } + matcher.appendTail(sb); + content = sb.toString(); + if (StartupUiUtil.isUnderDarcula()) { + content = content.replace("779dbd", "5676a0"); + } + return content; + }); + } + }); + } + catch (IOException e) { + Logger.getInstance(AboutDialog.class).error(e); + return; + } + + var dialog = new DialogWrapper(true) { + { + init(); + setAutoAdjustable(false); + setOKButtonText(CommonBundle.message("close.action.name")); + } + + @Override + protected JComponent createCenterPanel() { + var viewer = SwingHelper.createHtmlViewer(true, null, JBColor.WHITE, JBColor.BLACK); + viewer.setFocusable(true); + viewer.addHyperlinkListener(new BrowserHyperlinkListener()); + viewer.setText(licenseText); + + var styleSheet = ((HTMLDocument)viewer.getDocument()).getStyleSheet(); + styleSheet.addRule("body {font-family: \"Segoe UI\", Tahoma, \"Helvetica Neue\", Helvetica, Arial, sans-serif;}"); + styleSheet.addRule("body {margin-top:0;padding-top:0;}"); + styleSheet.addRule("body {font-size:" + JBUIScale.scaleFontSize((float)14) + "pt;}"); + + viewer.setCaretPosition(0); + viewer.setBorder(JBUI.Borders.empty(0, 5, 5, 5)); + + var scrollPane = new JBScrollPane(viewer, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_NEVER); + + var centerPanel = new JPanel(new BorderLayout(JBUIScale.scale(5), JBUIScale.scale(5))); + centerPanel.add(scrollPane, BorderLayout.CENTER); + return centerPanel; + } + + @Override + protected Action @NotNull [] createActions() { + return new Action[]{getOKAction()}; + } + }; + + dialog.setTitle(IdeBundle.message("dialog.title.third.party.software", + ApplicationNamesInfo.getInstance().getFullProductName(), + ApplicationInfo.getInstance().getFullVersion())); + dialog.setSize(JBUIScale.scale(750), JBUIScale.scale(650)); + dialog.show(); + } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/AboutPopup.java b/platform/platform-impl/src/com/intellij/ide/actions/AboutPopup.java deleted file mode 100644 index a144e8cdd05b..000000000000 --- a/platform/platform-impl/src/com/intellij/ide/actions/AboutPopup.java +++ /dev/null @@ -1,834 +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 com.intellij.ide.actions; - -import com.intellij.CommonBundle; -import com.intellij.icons.AllIcons; -import com.intellij.ide.AboutPopupDescriptionProvider; -import com.intellij.ide.BrowserUtil; -import com.intellij.ide.IdeBundle; -import com.intellij.ide.nls.NlsMessages; -import com.intellij.ide.plugins.IdeaPluginDescriptor; -import com.intellij.ide.plugins.PluginManagerCore; -import com.intellij.ide.ui.UISettings; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.CustomShortcutSet; -import com.intellij.openapi.application.ApplicationInfo; -import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.application.ex.ApplicationInfoEx; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.PluginId; -import com.intellij.openapi.ide.CopyPasteManager; -import com.intellij.openapi.project.DumbAwareAction; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.ui.GraphicsConfig; -import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.IconLoader; -import com.intellij.openapi.util.NlsSafe; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.io.FileUtilRt; -import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.util.registry.RegistryValue; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.BrowserHyperlinkListener; -import com.intellij.ui.JBColor; -import com.intellij.ui.LicensingFacade; -import com.intellij.ui.awt.RelativePoint; -import com.intellij.ui.components.JBScrollPane; -import com.intellij.ui.scale.JBUIScale; -import com.intellij.util.Alarm; -import com.intellij.util.MathUtil; -import com.intellij.util.PlatformUtils; -import com.intellij.util.ui.*; -import com.intellij.util.ui.accessibility.AccessibleContextUtil; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.accessibility.AccessibleAction; -import javax.accessibility.AccessibleContext; -import javax.swing.*; -import javax.swing.text.html.HTMLDocument; -import javax.swing.text.html.StyleSheet; -import java.awt.*; -import java.awt.event.*; -import java.io.File; -import java.io.IOException; -import java.lang.management.GarbageCollectorMXBean; -import java.lang.management.ManagementFactory; -import java.text.DateFormat; -import java.text.MessageFormat; -import java.text.SimpleDateFormat; -import java.util.List; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collector; -import java.util.stream.Collectors; - -import static com.intellij.util.ObjectUtils.notNull; -import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER; -import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED; - -/** - * @author Konstantin Bulenkov - */ -public final class AboutPopup { - private static JBPopup ourPopup; - private static final Logger LOG = Logger.getInstance(AboutPopup.class); - /** - * File with third party libraries HTML content, - * see the same constant at org.jetbrains.intellij.build.impl.DistributionJARsBuilder#THIRD_PARTY_LIBRARIES_FILE_PATH - */ - private static final String THIRD_PARTY_LIBRARIES_FILE_PATH = "license/third-party-libraries.html"; - - public static void show(@Nullable Window window, boolean showDebugInfo) { - ApplicationInfoEx appInfo = (ApplicationInfoEx)ApplicationInfo.getInstance(); - - final PopupPanel panel = new PopupPanel(new BorderLayout()); - Icon image = IconLoader.getIcon(appInfo.getAboutImageUrl(), AboutPopup.class.getClassLoader()); - if (appInfo.showLicenseeInfo()) { - final InfoSurface infoSurface = new InfoSurface(image, showDebugInfo); - infoSurface.setPreferredSize(new Dimension(image.getIconWidth(), image.getIconHeight())); - panel.setInfoSurface(infoSurface); - } - else { - panel.add(new JLabel(image), BorderLayout.NORTH); - } - - RelativePoint location; - if (window != null) { - Rectangle r = window.getBounds(); - location = new RelativePoint(window, new Point((r.width - image.getIconWidth()) / 2, (r.height - image.getIconHeight()) / 2)); - } - else { - Rectangle r = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getBounds(); - location = new RelativePoint(new Point((r.width - image.getIconWidth()) / 2, (r.height - image.getIconHeight()) / 2)); - } - - ourPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, panel) - .setRequestFocus(true) - .setFocusable(true) - .setResizable(false) - .setMovable(false) - .setModalContext(false) - .setShowShadow(true) - .setShowBorder(false) - .setCancelKeyEnabled(true) - .setCancelOnClickOutside(true) - .setCancelOnOtherWindowOpen(true) - .createPopup(); - - Disposer.register(ourPopup, new Disposable() { - @Override - @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod") - public void dispose() { - ourPopup = null; - } - }); - - ourPopup.show(location); - } - - static @Nullable String loadThirdPartyLibraries() { - final File thirdPartyLibrariesFile = new File(PathManager.getHomePath(), THIRD_PARTY_LIBRARIES_FILE_PATH); - if (thirdPartyLibrariesFile.isFile()) { - try { - return FileUtil.loadFile(thirdPartyLibrariesFile); - } - catch (IOException e) { - LOG.warn(e); - } - } - return null; - } - - static @NotNull @Nls String getCopyrightText() { - ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx(); - // Copyright message should not be translated - @NlsSafe - String copyrightText = String.format(Locale.ROOT, - "Copyright © %s–%d %s", appInfo.getCopyrightStart(), Calendar.getInstance(Locale.US).get(Calendar.YEAR), appInfo.getCompanyName()); - return copyrightText; - } - - private static final class InfoSurface extends JPanel { - private static final ExtensionPointName EP_NAME = new ExtensionPointName<>("com.intellij.aboutPopupDescriptionProvider"); - - private final Color myColor; - private final Color myLinkColor; - private final Icon myImage; - private final boolean myShowDebugInfo; - private Font myFont; - private Font myBoldFont; - private final List myLines = new ArrayList<>(); - private final StringBuilder myInfo = new StringBuilder(); - private final List myLinks = new ArrayList<>(); - private Link myActiveLink; - private boolean myShowCopy = false; - private float myShowCopyAlpha; - private final Alarm myAlarm = new Alarm(); - - InfoSurface(Icon image, final boolean showDebugInfo) { - ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx(); - - myImage = image; - //noinspection UseJBColor - myColor = Color.white; - long aboutLinkColor = appInfo.getAboutLinkColor(); - //noinspection UseJBColor - myLinkColor = aboutLinkColor == -1 ? JBUI.CurrentTheme.Link.Foreground.ENABLED : new Color((int)aboutLinkColor, aboutLinkColor > 0xffffff); - myShowDebugInfo = showDebugInfo; - - setOpaque(false); - setBackground(myColor); - setFocusable(true); - - String appName = appInfo.getFullApplicationName(); - String edition = ApplicationNamesInfo.getInstance().getEditionName(); - if (edition != null) appName += " (" + edition + ")"; - myLines.add(new AboutBoxLine(appName, true)); - appendLast(); - - String buildInfo = IdeBundle.message("about.box.build.number", appInfo.getBuild().asString()); - String buildInfoNonLocalized = MessageFormat.format("Build #{0}", appInfo.getBuild().asString()); - Date timestamp = appInfo.getBuildDate().getTime(); - if (appInfo.getBuild().isSnapshot()) { - String time = new SimpleDateFormat("HH:mm").format(timestamp); - buildInfo += IdeBundle.message("about.box.build.date.time", NlsMessages.formatDateLong(timestamp), time); - buildInfoNonLocalized += MessageFormat.format(", built on {0} at {1}", - DateFormat.getDateInstance(DateFormat.LONG, Locale.US).format(timestamp), time); - } - else { - buildInfo += IdeBundle.message("about.box.build.date", NlsMessages.formatDateLong(timestamp)); - buildInfoNonLocalized += MessageFormat.format(", built on {0}", - DateFormat.getDateInstance(DateFormat.LONG, Locale.US).format(timestamp)); - } - myLines.add(new AboutBoxLine(buildInfo)); - myInfo.append(buildInfoNonLocalized).append("\n"); - - myLines.add(new AboutBoxLine("")); - - LicensingFacade la = LicensingFacade.getInstance(); - if (la != null) { - final String licensedTo = la.getLicensedToMessage(); - if (licensedTo != null) { - myLines.add(new AboutBoxLine(licensedTo, true)); - appendLast(); - } - for (String message : la.getLicenseRestrictionsMessages()) { - myLines.add(new AboutBoxLine(message)); - appendLast(); - } - } - - myLines.add(new AboutBoxLine("")); - - Properties properties = System.getProperties(); - String javaVersion = properties.getProperty("java.runtime.version", properties.getProperty("java.version", "unknown")); - String arch = properties.getProperty("os.arch", ""); - myLines.add(new AboutBoxLine(IdeBundle.message("about.box.jre", javaVersion, arch))); - myInfo.append(MessageFormat.format("Runtime version: {0} {1}\n", javaVersion, arch)); - - String vmVersion = properties.getProperty("java.vm.name", "unknown"); - String vmVendor = properties.getProperty("java.vendor", "unknown"); - myLines.add(new AboutBoxLine(IdeBundle.message("about.box.vm", vmVersion, vmVendor))); - myInfo.append(MessageFormat.format("VM: {0} by {1}\n", vmVersion, vmVendor)); - - myLines.add(new AboutBoxLine("")); - myLines.add(new AboutBoxLine("")); - myLines.add(new AboutBoxLine(IdeBundle.message("about.box.powered.by") + " ").keepWithNext()); - - final String thirdPartyLibraries = loadThirdPartyLibraries(); - if (thirdPartyLibraries != null) { - myLines.add(new AboutBoxLine(IdeBundle.message("about.box.open.source.software"), - () -> showOpenSoftwareSources(thirdPartyLibraries))); - } - else { - // When compiled from sources, third-party-libraries.html file isn't generated, so window can't be shown - myLines.add(new AboutBoxLine(IdeBundle.message("about.box.open.source.software"))); - } - - addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent event) { - if (myActiveLink != null) { - event.consume(); - myActiveLink.actionPerformed(new ActionEvent(event.getSource(), event.getID(), event.paramString())); - } - - if (getCopyIconArea().contains(event.getPoint())) { - CopyPasteManager.copyTextToClipboard(getText()); - if (ourPopup != null) { - ourPopup.cancel(); - } - } - } - - static final double maxAlpha = 1.0; - static final double fadeStep = 0.05; - static final int animationDelay = 15; - - @Override - public void mouseEntered(MouseEvent e) { - if (!myShowCopy) { - myShowCopy = true; - myAlarm.cancelAllRequests(); - myAlarm.addRequest(new Runnable() { - @Override - public void run() { - if (myShowCopyAlpha < maxAlpha) { - myShowCopyAlpha = (float)Math.min(myShowCopyAlpha + fadeStep, maxAlpha); - repaint(); - myAlarm.addRequest(this, animationDelay); - } - } - }, animationDelay); - } - } - - @Override - public void mouseExited(MouseEvent e) { - if (myShowCopy) { - myShowCopy = false; - myAlarm.cancelAllRequests(); - myAlarm.addRequest(new Runnable() { - @Override - public void run() { - if (myShowCopyAlpha > 0) { - myShowCopyAlpha -= fadeStep; - repaint(); - myAlarm.addRequest(this, animationDelay); - } - } - }, animationDelay); - } - } - }); - - addMouseMotionListener(new MouseMotionAdapter() { - @Override - public void mouseMoved(MouseEvent event) { - boolean hadLink = (myActiveLink != null) || getCursor() == Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); - myActiveLink = null; - Point point = event.getPoint(); - for (Link link : myLinks) { - if (link.myRectangle.contains(point)) { - myActiveLink = link; - if (!hadLink) { - setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - return; - } - } - - if (getCopyIconArea().contains(point)) { - setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - return; - } - - if (hadLink && myActiveLink == null) { - setCursor(Cursor.getDefaultCursor()); - } - } - }); - } - private static Rectangle getCopyIconArea() { - return new Rectangle(getCopyIconCoord(), JBUI.size(16)); - } - - private void appendLast() { - myInfo.append(myLines.get(myLines.size() - 1).getText()).append("\n"); - } - - @Override - public void paint(Graphics g) { - super.paint(g); - - Graphics2D g2 = (Graphics2D)g; - GraphicsConfig config = new GraphicsConfig(g); - UISettings.setupAntialiasing(g); - - Font labelFont; - if (SystemInfo.isWindows) { - labelFont = JBUI.Fonts.create("Segoe UI", 14); - } else if (SystemInfo.isMac) { - labelFont = JBUI.Fonts.create("Helvetica Neue", 13); - } else { - labelFont = JBUI.Fonts.create("Arial", 14); - } - - int startFontSize = 14; - for (int labelSize = JBUIScale.scale(startFontSize); labelSize != JBUIScale.scale(6); labelSize -= 1) { - myLinks.clear(); - g2.setPaint(myColor); - myImage.paintIcon(this, g2, 0, 0); - - g2.setColor(myColor); - TextRenderer renderer = createTextRenderer(g2); - UIUtil.setupComposite(g2); - myFont = labelFont.deriveFont(Font.PLAIN, labelSize); - myBoldFont = labelFont.deriveFont(Font.BOLD, labelSize + 1); - try { - renderer.render(0, 0, myLines); - break; - } - catch (TextRenderer.OverflowException ignore) { } - } - - ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx(); - int[] aboutLogoRect = appInfo.getAboutLogoRect(); - if (aboutLogoRect != null) { - myLinks.add(new Link(new JBRectangle(aboutLogoRect[0], aboutLogoRect[1], aboutLogoRect[2], aboutLogoRect[3]), appInfo.getCompanyURL())); - } - - long copyrightForeground = appInfo.getCopyrightForeground(); - Color color; - if (copyrightForeground < 0) { - color = JBColor.BLACK; - } - else { - //noinspection UseJBColor - color = new Color((int)copyrightForeground, copyrightForeground > 0xffffff); - } - g2.setColor(color); - if (SystemInfo.isWindows) { - g.setFont(JBUI.Fonts.create("Segoe UI", 10)); - } else if (SystemInfo.isMac) { - g.setFont(JBUI.Fonts.create("Helvetica Neue", 10)); - } else { - g.setFont(JBUI.Fonts.create("Arial", 10)); - } - - JBPoint copyrightCoord = getCopyrightCoord(); - g2.drawString(getCopyrightText(), copyrightCoord.x, copyrightCoord.y); - if (myShowDebugInfo) { - g2.setColor(createColor(appInfo.getAboutForeground())); - for (Link link : myLinks) { - g2.drawRect(link.myRectangle.x, link.myRectangle.y, link.myRectangle.width, link.myRectangle.height); - } - } - - config.restore(); - if (myShowCopy) { - JBPoint coord = getCopyIconCoord(); - float alpha = myShowCopyAlpha; - config = new GraphicsConfig(g).paintWithAlpha(MathUtil.clamp(alpha, 0f, 1f)); - AllIcons.General.CopyHovered.paintIcon(this, g, coord.x, coord.y); - config.restore(); - } - } - - private @NotNull TextRenderer createTextRenderer(Graphics2D g) { - Rectangle r = getTextRendererRect(); - return new TextRenderer(r.x, r.y, r.width, r.height, g); - } - - private static JBRectangle getTextRendererRect() { - return new JBRectangle(49, 169, 500, 220); - } - - private static JBPoint getCopyrightCoord() { - return new JBPoint(49, 365); - } - - private static JBPoint getCopyIconCoord() { - return new JBPoint(15, 155); - } - - public String getText() { - return myInfo + getExtraInfo(); - } - - private class TextRenderer { - private final int xBase; - private final int yBase; - private final int w; - private final int h; - private final Graphics2D g2; - - private int x = 0; - private int y = 0; - private FontMetrics fontmetrics; - private int fontAscent; - private int fontHeight; - private Font font; - - public static class OverflowException extends Exception { } - - TextRenderer(final int xBase, final int yBase, final int w, final int h, final Graphics2D g2) { - this.xBase = xBase; - this.yBase = yBase; - this.w = w; - this.h = h; - this.g2 = g2; - - if (SystemInfo.isWindows) { - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - } - } - - public void render(int indentX, int indentY, List lines) throws OverflowException { - x = indentX; - y = indentY; - ApplicationInfoEx appInfo = (ApplicationInfoEx)ApplicationInfo.getInstance(); - for (AboutBoxLine line : lines) { - final String s = line.getText(); - setFont(line.isBold() ? myBoldFont : myFont); - if (line.isRunnable()) { - g2.setColor(myLinkColor); - FontMetrics metrics = g2.getFontMetrics(font); - final Rectangle myRectangle = new Rectangle(xBase + x, yBase + y - fontAscent, metrics.stringWidth(s + " "), fontHeight); - myLinks.add(new Link(myRectangle, line)); - } - else { - g2.setColor(createColor(appInfo.getAboutForeground())); - } - renderString(s, indentX); - if (!line.isKeepWithNext() && !line.equals(lines.get(lines.size()-1))) { - lineFeed(indentX, s); - } - } - } - - private void renderString(final String s, final int indentX) throws OverflowException { - final List words = StringUtil.split(s, " "); - for (String word : words) { - int wordWidth = fontmetrics.stringWidth(word); - if (x + wordWidth >= w) { - lineFeed(indentX, word); - } - renderWord(word, indentX); - } - } - - private void renderWord(final String s, final int indentX) throws OverflowException { - FontMetrics fm = null; - Font f = null; - try { - for (int j = 0; j != s.length(); ++j) { - final char c = s.charAt(j); - if (!g2.getFont().canDisplay(c)) { - f = g2.getFont(); - fm = fontmetrics; - g2.setFont(new Font("Monospaced", f.getStyle(), f.getSize())); - fontmetrics = g2.getFontMetrics(); - } - final int cW = fontmetrics.charWidth(c); - if (x + cW >= w) { - lineFeed(indentX, s); - } - g2.drawChars(new char[]{c}, 0, 1, xBase + x, yBase + y); - x += cW; - } - x += fontmetrics.charWidth(' '); - } - finally { - if (f != null) { - g2.setFont(f); - fontmetrics = fm; - } - } - } - - private void lineFeed(int indent, final String s) throws OverflowException { - x = indent; - if (s.length() == 0) { - y += fontHeight / 3; - } - else { - y += fontHeight; - } - if (y >= h) { - throw new OverflowException(); - } - } - - private void setFont(Font font) { - this.font = font; - fontmetrics = g2.getFontMetrics(font); - g2.setFont(font); - fontAscent = fontmetrics.getAscent(); - fontHeight = fontmetrics.getHeight(); - } - } - - private static class AboutBoxLine implements ActionListener { - private final String myText; - private final boolean myBold; - private boolean myKeepWithNext; - private final Runnable myRunnable; - - AboutBoxLine(final String text, final boolean bold) { - myText = text; - myBold = bold; - myRunnable = null; - } - - AboutBoxLine(final String text) { - this(text, false); - } - - AboutBoxLine(final String text, @NotNull Runnable runnable) { - myText = text; - myBold = false; - myRunnable = runnable; - } - - public String getText() { - return myText; - } - - public boolean isBold() { - return myBold; - } - - public boolean isRunnable() { - return myRunnable != null; - } - - public boolean isKeepWithNext() { - return myKeepWithNext; - } - - public AboutBoxLine keepWithNext() { - myKeepWithNext = true; - return this; - } - - @Override - public void actionPerformed(ActionEvent e) { - if (myRunnable != null) myRunnable.run(); - } - } - - private static final class Link implements ActionListener { - private final Rectangle myRectangle; - private final ActionListener myAction; - - private Link(Rectangle rectangle, ActionListener action) { - myRectangle = rectangle; - myAction = action; - } - - private Link(Rectangle rectangle, String url) { - myRectangle = rectangle; - myAction = e -> BrowserUtil.browse(url); - } - - @Override - public void actionPerformed(ActionEvent e) { - myAction.actionPerformed(e); - } - } - - @Override - public AccessibleContext getAccessibleContext() { - if (accessibleContext == null) { - accessibleContext = new AccessibleInfoSurface(); - } - return accessibleContext; - } - - protected class AccessibleInfoSurface extends AccessibleJPanel { - @Override - public String getAccessibleName() { - String text = IdeBundle.message("about.popup.system.info", getText(), getCopyrightText()); - @NlsSafe String result = AccessibleContextUtil.replaceLineSeparatorsWithPunctuation(text); - return result; - } - } - } - - @SuppressWarnings("UseJBColor") - private static Color createColor(long rgba) { - return rgba == -1 ? Color.BLACK : new Color((int)rgba, rgba > 0xffffff); - } - - static @NotNull String getExtraInfo() { - String extraInfo = SystemInfo.getOsNameAndVersion() + "\n"; - - for (AboutPopupDescriptionProvider aboutInfoProvider : InfoSurface.EP_NAME.getExtensions()) { - String description = aboutInfoProvider.getDescription(); - if (description != null) { - extraInfo += description + "\n"; - } - } - - extraInfo += "GC: " + ManagementFactory.getGarbageCollectorMXBeans().stream() - .map(GarbageCollectorMXBean::getName).collect(StringUtil.joining()) + "\n"; - - extraInfo += "Memory: " + (Runtime.getRuntime().maxMemory() / FileUtilRt.MEGABYTE) + "M" + "\n"; - - extraInfo += "Cores: " + Runtime.getRuntime().availableProcessors() + "\n"; - - if (UIUtil.isMetalRendering()) { - extraInfo += "Metal Rendering is ON\n"; - } - - Collector joiner = Collectors.joining("\n"); - - String registryKeys = Registry.getAll().stream().filter(RegistryValue::isChangedFromDefault) - .map(v -> " " + v.getKey() + "=" + v.asString()).collect(joiner); - if (!StringUtil.isEmpty(registryKeys)) { - extraInfo += "Registry:\n" + registryKeys + "\n\n"; - } - - String nonBundledPlugins = PluginManagerCore.getLoadedPlugins().stream() - .filter(p -> !p.isBundled()) - .map(p -> " " + p.getPluginId().getIdString() + " (" + p.getVersion() + ")") - .collect(joiner); - if (!StringUtil.isEmpty(nonBundledPlugins)) { - extraInfo += "Non-Bundled Plugins:\n" + nonBundledPlugins + "\n"; - } - - if (PlatformUtils.isIntelliJ()) { - IdeaPluginDescriptor kotlinPlugin = PluginManagerCore.getPlugin(PluginId.findId("org.jetbrains.kotlin")); - if (kotlinPlugin != null) { - extraInfo += "\nKotlin: " + kotlinPlugin.getVersion(); - } - } - - if (SystemInfo.isUnix && !SystemInfo.isMac) { - extraInfo += "\nCurrent Desktop: " + notNull(System.getenv("XDG_CURRENT_DESKTOP"), "Undefined"); - } - return extraInfo; - } - - public static class PopupPanel extends JPanel { - - private InfoSurface myInfoSurface; - - public PopupPanel(LayoutManager layout) { - super(layout); - } - - @Override - public AccessibleContext getAccessibleContext() { - if (accessibleContext == null) { - accessibleContext = new AccessiblePopupPanel(); - } - return accessibleContext; - } - - public void setInfoSurface(InfoSurface infoSurface) { - myInfoSurface = infoSurface; - add(infoSurface, BorderLayout.NORTH); - DumbAwareAction.create(e -> CopyPasteManager.copyTextToClipboard(myInfoSurface.getText())) - .registerCustomShortcutSet(CustomShortcutSet.fromString("meta C", "control C"), this); - } - - protected class AccessiblePopupPanel extends AccessibleJPanel implements AccessibleAction { - @Override - public String getAccessibleName() { - ApplicationInfoEx appInfo = (ApplicationInfoEx)ApplicationInfo.getInstance(); - return IdeBundle.message("about.popup.about.app", appInfo.getFullApplicationName()); - } - - @Override - public String getAccessibleDescription() { - return myInfoSurface != null ? IdeBundle.message("press.copy.key.to.copy.system.information.to.clipboard") : null; - } - - @Override - public AccessibleAction getAccessibleAction() { - return this; - } - - @Override - public int getAccessibleActionCount() { - return myInfoSurface != null ? 1 : 0; - } - - @Override - public String getAccessibleActionDescription(int i) { - return i == 0 && myInfoSurface != null ? IdeBundle.message("copy.system.information.to.clipboard") : null; - } - - @Override - public boolean doAccessibleAction(int i) { - if (i == 0 && myInfoSurface != null) { - CopyPasteManager.copyTextToClipboard(myInfoSurface.getText()); - return true; - } - return false; - } - } - } - - public static void showOpenSoftwareSources(@NotNull String htmlText) { - DialogWrapper dialog = new DialogWrapper(true) { - { - init(); - setAutoAdjustable(false); - setOKButtonText(CommonBundle.message("close.action.name")); - } - - @Override - protected JComponent createCenterPanel() { - JPanel centerPanel = new JPanel(new BorderLayout(JBUIScale.scale(5), JBUIScale.scale(5))); - - JEditorPane viewer = SwingHelper.createHtmlViewer(true, null, JBColor.WHITE, JBColor.BLACK); - viewer.setFocusable(true); - viewer.addHyperlinkListener(new BrowserHyperlinkListener()); - - @NonNls String resultHtmlText = getScaledHtmlText(); - if (StartupUiUtil.isUnderDarcula()) { - resultHtmlText = resultHtmlText.replaceAll("779dbd", "5676a0"); - } - viewer.setText(resultHtmlText); - - StyleSheet styleSheet = ((HTMLDocument)viewer.getDocument()).getStyleSheet(); - styleSheet.addRule("body {font-family: \"Segoe UI\", Tahoma, \"Helvetica Neue\", Helvetica, Arial, sans-serif;}"); - styleSheet.addRule("body {margin-top:0;padding-top:0;}"); - styleSheet.addRule("body {font-size:" + JBUIScale.scaleFontSize((float)14) + "pt;}"); - - viewer.setCaretPosition(0); - viewer.setBorder(JBUI.Borders.empty(0, 5, 5, 5)); - - JBScrollPane scrollPane = new JBScrollPane(viewer, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_NEVER); - - centerPanel.add(scrollPane, BorderLayout.CENTER); - return centerPanel; - } - - @Override - protected Action @NotNull [] createActions() { - return new Action[]{getOKAction()}; - } - - private @NotNull String getScaledHtmlText() { - final Pattern pattern = Pattern.compile("(\\d+)px"); - final Matcher matcher = pattern.matcher(htmlText); - - StringBuilder sb = new StringBuilder(); - while (matcher.find()) { - matcher.appendReplacement(sb, JBUIScale.scale(Integer.parseInt(matcher.group(1))) + "px"); - } - matcher.appendTail(sb); - - return sb.toString(); - } - }; - - if (ourPopup != null) { - ourPopup.cancel(); - } - dialog.setTitle(IdeBundle.message("dialog.title.third.party.software", - ApplicationNamesInfo.getInstance().getFullProductName(), - ApplicationInfo.getInstance().getFullVersion())); - dialog.setSize(JBUIScale.scale(750), JBUIScale.scale(650)); - dialog.show(); - } - - public static @NotNull @NlsSafe String getAboutText() { - ApplicationInfoEx appInfo = (ApplicationInfoEx)ApplicationInfo.getInstance(); - InfoSurface infoSurface = new InfoSurface(IconLoader.getIcon(appInfo.getAboutImageUrl(), AboutPopup.class.getClassLoader()), false); - return infoSurface.getText(); - } -} diff --git a/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java b/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java index db9a356b34c0..57bb730ec308 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java @@ -76,11 +76,6 @@ public class WhatsNewAction extends AnAction implements DumbAware { } } - @ApiStatus.Internal - public static boolean isAvailable() { - return ApplicationInfoEx.getInstanceEx().isShowWhatsNewOnUpdate() && !AppMode.isRemoteDevHost(); - } - @ApiStatus.Internal public static void openWhatsNewPage(@NotNull Project project, @NotNull String url) { if (!JBCefApp.isSupported()) { @@ -148,4 +143,4 @@ public class WhatsNewAction extends AnAction implements DumbAware { var title = IdeBundle.message("update.whats.new", ApplicationNamesInfo.getInstance().getFullProductName()); HTMLEditorProvider.openEditor(project, title, request); } -} +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewUtil.java b/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewUtil.java new file mode 100644 index 000000000000..a45abd541e5b --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewUtil.java @@ -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 com.intellij.ide.actions; + +import com.intellij.idea.AppMode; +import com.intellij.openapi.application.ex.ApplicationInfoEx; +import org.jetbrains.annotations.ApiStatus; + +public final class WhatsNewUtil { + @ApiStatus.Internal + public static boolean isWhatsNewAvailable() { + return ApplicationInfoEx.getInstanceEx().isShowWhatsNewOnUpdate() && !AppMode.isRemoteDevHost(); + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingMenuBarFlavor.kt b/platform/platform-impl/src/com/intellij/ide/menu/FloatingMenuBarFlavor.kt similarity index 98% rename from platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingMenuBarFlavor.kt rename to platform/platform-impl/src/com/intellij/ide/menu/FloatingMenuBarFlavor.kt index 72e4efff6fef..5da18d6f5df1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingMenuBarFlavor.kt +++ b/platform/platform-impl/src/com/intellij/ide/menu/FloatingMenuBarFlavor.kt @@ -1,7 +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 com.intellij.openapi.wm.impl +package com.intellij.ide.menu import com.intellij.ide.IdeEventQueue +import com.intellij.openapi.wm.impl.* +import com.intellij.openapi.wm.impl.IdeMenuBarState import com.intellij.openapi.wm.impl.status.ClockPanel import com.intellij.ui.ColorUtil import com.intellij.util.ui.Animator diff --git a/platform/platform-impl/src/com/intellij/ide/menu/IdeMenuBarHelper.kt b/platform/platform-impl/src/com/intellij/ide/menu/IdeMenuBarHelper.kt new file mode 100644 index 000000000000..a24913e77778 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/menu/IdeMenuBarHelper.kt @@ -0,0 +1,256 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.ide.menu + +import com.intellij.diagnostic.StartUpMeasurer +import com.intellij.diagnostic.rootTask +import com.intellij.diagnostic.subtask +import com.intellij.ide.DataManager +import com.intellij.ide.ui.UISettings +import com.intellij.ide.ui.UISettingsListener +import com.intellij.ide.ui.customization.CustomActionsSchema +import com.intellij.openapi.actionSystem.* +import com.intellij.openapi.actionSystem.ex.ActionManagerEx +import com.intellij.openapi.actionSystem.ex.ActionUtil +import com.intellij.openapi.actionSystem.impl.ActionMenu +import com.intellij.openapi.actionSystem.impl.MenuItemPresentationFactory +import com.intellij.openapi.actionSystem.impl.PresentationFactory +import com.intellij.openapi.actionSystem.impl.Utils +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.EDT +import com.intellij.openapi.application.ModalityState +import com.intellij.openapi.application.asContextElement +import com.intellij.openapi.components.serviceAsync +import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.progress.ProcessCanceledException +import com.intellij.openapi.wm.WindowManager +import com.intellij.openapi.wm.impl.IdeFrameDecorator +import com.intellij.openapi.wm.impl.IdeMenuBarState +import com.intellij.openapi.wm.impl.IdeRootPane +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow +import org.jetbrains.concurrency.await +import java.awt.Component +import java.awt.Dialog +import java.awt.Dimension +import java.awt.KeyboardFocusManager +import java.util.concurrent.atomic.AtomicLong +import javax.swing.JComponent +import javax.swing.JFrame +import kotlin.coroutines.EmptyCoroutineContext +import kotlin.time.Duration.Companion.seconds + +internal interface ActionAwareIdeMenuBar { + fun updateMenuActions(forceRebuild: Boolean = false) +} + +internal interface IdeMenuFlavor { + val state: IdeMenuBarState + get() = IdeMenuBarState.EXPANDED + + fun jMenuSelectionChanged(isIncluded: Boolean) { + } + + fun getPreferredSize(size: Dimension): Dimension = size + + fun updateAppMenu() + + fun layoutClockPanelAndButton() { + } + + fun correctMenuCount(menuCount: Int): Int = menuCount + + fun suspendAnimator() {} +} + +internal sealed class IdeMenuBarHelper(@JvmField val flavor: IdeMenuFlavor, + @JvmField internal val menuBar: MenuBarImpl) : ActionAwareIdeMenuBar { + protected abstract fun isUpdateForbidden(): Boolean + + @JvmField + protected var visibleActions = emptyList() + + @JvmField + protected val presentationFactory: PresentationFactory = MenuItemPresentationFactory() + + private val updateRequests = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) + + interface MenuBarImpl { + val frame: JFrame + + val coroutineScope: CoroutineScope + val isDarkMenu: Boolean + val component: JComponent + + fun updateGlobalMenuRoots() + + suspend fun getMainMenuActionGroup(): ActionGroup? + } + + init { + val app = ApplicationManager.getApplication() + val coroutineScope = menuBar.coroutineScope + @Suppress("IfThenToSafeAccess") + if (app != null) { + app.messageBus.connect(coroutineScope).subscribe(UISettingsListener.TOPIC, UISettingsListener { + check(updateRequests.tryEmit(true)) + }) + } + + coroutineScope.launch(ModalityState.any().asContextElement()) { + withContext(if (StartUpMeasurer.isEnabled()) (rootTask() + CoroutineName("ide menu bar actions init")) else EmptyCoroutineContext) { + val actions = updateMenuActions(mainActionGroup = menuBar.getMainMenuActionGroup(), forceRebuild = false, isFirstUpdate = true) + postInitActions(actions) + } + + val actionManager = serviceAsync() + if (actionManager is ActionManagerEx) { + coroutineScope.launch { + actionManager.timerEvents.collect { + updateOnTimer() + } + } + } + + val lastUpdate = AtomicLong(System.currentTimeMillis()) + updateRequests + .collect { forceRebuild -> + // as ActionManagerImpl TIMER_DELAY + if ((System.currentTimeMillis() - lastUpdate.get()) < 500) { + return@collect + } + + if (!withContext(Dispatchers.EDT) { filterUpdate() }) { + return@collect + } + + presentationFactory.reset() + updateMenuActions(mainActionGroup = menuBar.getMainMenuActionGroup(), forceRebuild = forceRebuild, isFirstUpdate = false) + lastUpdate.set(System.currentTimeMillis()) + } + } + } + + private fun filterUpdate(): Boolean { + if (!menuBar.frame.isShowing || !menuBar.frame.isActive) { + return false + } + + // do not update when a popup menu is shown + // (if a popup menu contains action which is also in the menu bar, it should not be enabled/disabled) + if (isUpdateForbidden()) { + return false + } + + // don't update the toolbar if there is currently active modal dialog + val window = KeyboardFocusManager.getCurrentKeyboardFocusManager().focusedWindow + return window !is Dialog || !window.isModal + } + + private suspend fun updateOnTimer() { + withContext(Dispatchers.EDT) { + // don't update the toolbar if there is currently active modal dialog + val window = KeyboardFocusManager.getCurrentKeyboardFocusManager().focusedWindow + if (window !is Dialog || !window.isModal) { + updateRequests.emit(false) + } + } + } + + final override fun updateMenuActions(forceRebuild: Boolean) { + check(updateRequests.tryEmit(forceRebuild)) + } + + protected open suspend fun postInitActions(actions: List) { + } + + abstract suspend fun updateMenuActions(mainActionGroup: ActionGroup?, forceRebuild: Boolean, isFirstUpdate: Boolean): List + + protected fun createActionMenuList(newVisibleActions: List, consumer: (ActionMenu) -> Unit) { + if (newVisibleActions.isEmpty()) { + return + } + + val enableMnemonics = !UISettings.getInstance().disableMnemonics + val isCustomDecorationActive = IdeFrameDecorator.isCustomDecorationActive() + for (action in newVisibleActions) { + val actionMenu = ActionMenu(null, ActionPlaces.MAIN_MENU, action, presentationFactory, enableMnemonics, menuBar.isDarkMenu, true) + if (isCustomDecorationActive) { + actionMenu.isOpaque = false + actionMenu.isFocusable = false + } + consumer(actionMenu) + } + } +} + +@Suppress("unused") +private val firstUpdateFastTrackUpdateTimeout = 30.seconds.inWholeMilliseconds +private val useAsyncExpand = System.getProperty("idea.app.menu.async.expand", "false").toBoolean() + +internal suspend fun expandMainActionGroup(mainActionGroup: ActionGroup, + menuBar: Component, + frame: JFrame, + presentationFactory: PresentationFactory, + isFirstUpdate: Boolean): List { + if (!useAsyncExpand) { + return syncExpandMainActionGroup(mainActionGroup, serviceAsync(), frame, menuBar, presentationFactory) + } + + try { + return withContext(CoroutineName("expandMainActionGroup") + Dispatchers.EDT) { + val targetComponent = serviceAsync().getFocusedComponent(frame) ?: menuBar + val dataContext = Utils.wrapToAsyncDataContext(DataManager.getInstance().getDataContext(targetComponent)) + val fastTrackTimeout = if (isFirstUpdate) firstUpdateFastTrackUpdateTimeout else Utils.getFastTrackTimeout() + Utils.expandActionGroupAsync(/* group = */ mainActionGroup, + /* presentationFactory = */ presentationFactory, + /* context = */ dataContext, + /* place = */ ActionPlaces.MAIN_MENU, + /* isToolbarAction = */ false, + /* fastTrackTimeout = */ fastTrackTimeout) + }.await().filterIsInstance() + } + catch (e: ProcessCanceledException) { + if (isFirstUpdate) { + logger().warn("Cannot expand action group", e) + } + + // don't repeat - will do on next timer event + return emptyList() + } +} + +private suspend fun syncExpandMainActionGroup(mainActionGroup: ActionGroup, + actionManager: ActionManager, + frame: JFrame, + menuBar: Component, + presentationFactory: PresentationFactory): List { + return subtask("expandMainActionGroup", Dispatchers.EDT) { + val children = mainActionGroup.getChildren(null, actionManager) + if (children.isEmpty()) { + return@subtask emptyList() + } + + val targetComponent = WindowManager.getInstance().getFocusedComponent(frame) ?: menuBar + val dataContext = DataManager.getInstance().getDataContext(targetComponent) + val list = mutableListOf() + for (action in children) { + if (action !is ActionGroup) { + continue + } + + val presentation = presentationFactory.getPresentation(action) + val e = AnActionEvent(null, dataContext, ActionPlaces.MAIN_MENU, presentation, actionManager, 0) + ActionUtil.performDumbAwareUpdate(action, e, false) + if (presentation.isVisible) { + list.add(action) + } + } + list + } +} + +internal suspend fun getMainMenuActionGroup(frame: JFrame): ActionGroup? { + val group = (frame.rootPane as? IdeRootPane)?.mainMenuActionGroup + return group ?: CustomActionsSchema.getInstanceAsync().getCorrectedActionAsync(IdeActions.GROUP_MAIN_MENU) +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/menu/JMenuBasedIdeMenuBarHelper.kt b/platform/platform-impl/src/com/intellij/ide/menu/JMenuBasedIdeMenuBarHelper.kt new file mode 100644 index 000000000000..9483874ef8bc --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/menu/JMenuBasedIdeMenuBarHelper.kt @@ -0,0 +1,66 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.ide.menu + +import com.intellij.ide.ui.UISettings +import com.intellij.openapi.actionSystem.ActionGroup +import com.intellij.openapi.actionSystem.ActionPlaces +import com.intellij.openapi.actionSystem.impl.ActionMenu +import com.intellij.openapi.actionSystem.impl.PopupMenuPreloader +import com.intellij.openapi.application.EDT +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import javax.swing.MenuSelectionManager + +internal open class JMenuBasedIdeMenuBarHelper(flavor: IdeMenuFlavor, menuBar: MenuBarImpl) : IdeMenuBarHelper(flavor, menuBar) { + override fun isUpdateForbidden() = MenuSelectionManager.defaultManager().selectedPath.isNotEmpty() + + override suspend fun postInitActions(actions: List) { + withContext(Dispatchers.EDT) { + for (action in actions) { + PopupMenuPreloader.install(menuBar.component, ActionPlaces.MAIN_MENU, null) { action } + } + } + } + + override suspend fun updateMenuActions(mainActionGroup: ActionGroup?, forceRebuild: Boolean, isFirstUpdate: Boolean): List { + val menuBarComponent = menuBar.component + val newVisibleActions = mainActionGroup?.let { + expandMainActionGroup(mainActionGroup = it, + menuBar = menuBarComponent, + frame = menuBar.frame, + presentationFactory = presentationFactory, + isFirstUpdate = isFirstUpdate) + } ?: emptyList() + + if (!forceRebuild && newVisibleActions == visibleActions && !presentationFactory.isNeedRebuild) { + val enableMnemonics = !UISettings.getInstance().disableMnemonics + withContext(Dispatchers.EDT) { + for (child in menuBarComponent.components) { + if (child is ActionMenu) { + child.updateFromPresentation(enableMnemonics) + } + } + } + return newVisibleActions + } + + // should rebuild UI + val changeBarVisibility = newVisibleActions.isEmpty() || visibleActions.isEmpty() + withContext(Dispatchers.EDT) { + visibleActions = newVisibleActions + menuBarComponent.removeAll() + createActionMenuList(newVisibleActions) { + menuBarComponent.add(it) + } + presentationFactory.resetNeedRebuild() + flavor.updateAppMenu() + menuBar.updateGlobalMenuRoots() + menuBarComponent.validate() + if (changeBarVisibility) { + menuBarComponent.invalidate() + menuBar.frame.validate() + } + } + return newVisibleActions + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/MacMenuBar.kt b/platform/platform-impl/src/com/intellij/ide/menu/MacMenuBar.kt similarity index 54% rename from platform/platform-impl/src/com/intellij/openapi/wm/impl/MacMenuBar.kt rename to platform/platform-impl/src/com/intellij/ide/menu/MacMenuBar.kt index b3b522b95197..904a476a5834 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/MacMenuBar.kt +++ b/platform/platform-impl/src/com/intellij/ide/menu/MacMenuBar.kt @@ -1,14 +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 com.intellij.openapi.wm.impl +package com.intellij.ide.menu import com.intellij.diagnostic.runActivity +import com.intellij.openapi.actionSystem.ActionGroup +import com.intellij.openapi.util.Disposer +import com.intellij.openapi.wm.impl.doUpdateAppMenu import com.intellij.ui.mac.foundation.NSDefaults +import com.intellij.ui.mac.screenmenu.MenuBar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.job import javax.swing.JComponent import javax.swing.JFrame -internal fun createMacMenuBar(coroutineScope: CoroutineScope, component: JComponent, frame: JFrame): ActionAwareIdeMenuBar { +internal fun createMacMenuBar( + coroutineScope: CoroutineScope, + component: JComponent, + frame: JFrame, + mainMenuActionGroupProvider: suspend () -> ActionGroup? = { getMainMenuActionGroup(frame) }, +): ActionAwareIdeMenuBar { val flavor = object : IdeMenuFlavor { override fun updateAppMenu() { doUpdateAppMenu() @@ -28,22 +37,14 @@ internal fun createMacMenuBar(coroutineScope: CoroutineScope, component: JCompon override fun updateGlobalMenuRoots() { } - override suspend fun getMainMenuActionGroup() = getMainMenuActionGroup(frame) + override suspend fun getMainMenuActionGroup() = mainMenuActionGroupProvider() } - val screenMenuPeer = runActivity("ide menu bar init") { createScreeMenuPeer(frame) } - val menuBarHelper = if (screenMenuPeer == null) { - JMenuBasedIdeMenuBarHelper(flavor = flavor, menuBar = facade) - } - else { - PeerBasedIdeMenuBarHelper(screenMenuPeer = screenMenuPeer, flavor = flavor, menuBar = facade) - } + val screenMenuPeer = runActivity("ide menu bar init") { MenuBar("MainMenu", frame) } + val menuBarHelper = PeerBasedIdeMenuBarHelper(screenMenuPeer = screenMenuPeer, flavor = flavor, menuBar = facade) coroutineScope.coroutineContext.job.invokeOnCompletion { - screenMenuPeer?.let { - @Suppress("SSBasedInspection") - it.dispose() - } + Disposer.dispose(screenMenuPeer) } return menuBarHelper } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/menu/PeerBasedIdeMenuBarHelper.kt b/platform/platform-impl/src/com/intellij/ide/menu/PeerBasedIdeMenuBarHelper.kt new file mode 100644 index 000000000000..2382f56a7167 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/menu/PeerBasedIdeMenuBarHelper.kt @@ -0,0 +1,44 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.ide.menu + +import com.intellij.openapi.actionSystem.ActionGroup +import com.intellij.openapi.application.EDT +import com.intellij.ui.mac.screenmenu.MenuBar +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +internal open class PeerBasedIdeMenuBarHelper(private val screenMenuPeer: MenuBar, + flavor: IdeMenuFlavor, + menuBar: MenuBarImpl) : IdeMenuBarHelper(flavor, menuBar) { + override fun isUpdateForbidden() = screenMenuPeer.isAnyChildOpened + + override suspend fun updateMenuActions(mainActionGroup: ActionGroup?, forceRebuild: Boolean, isFirstUpdate: Boolean): List { + val newVisibleActions = mainActionGroup?.let { + expandMainActionGroup(mainActionGroup = it, + menuBar = menuBar.component, + frame = menuBar.frame, + presentationFactory = presentationFactory, + isFirstUpdate = isFirstUpdate) + } ?: emptyList() + + if (!forceRebuild && newVisibleActions == visibleActions && !presentationFactory.isNeedRebuild) { + return newVisibleActions + } + + withContext(Dispatchers.EDT) { + visibleActions = newVisibleActions + screenMenuPeer.beginFill() + try { + createActionMenuList(newVisibleActions) { + screenMenuPeer.add(it.screenMenuPeer) + } + } + finally { + screenMenuPeer.endFill() + presentationFactory.resetNeedRebuild() + } + flavor.updateAppMenu() + } + return newVisibleActions + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/BundledPluginsState.kt b/platform/platform-impl/src/com/intellij/ide/plugins/BundledPluginsState.kt index f24dc73ddac2..a09a23e97a8e 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/BundledPluginsState.kt +++ b/platform/platform-impl/src/com/intellij/ide/plugins/BundledPluginsState.kt @@ -22,6 +22,7 @@ import org.jetbrains.annotations.VisibleForTesting import java.io.IOException import java.nio.file.Files import java.nio.file.Path +import java.util.concurrent.atomic.AtomicReference import kotlin.io.path.exists import kotlin.io.path.readLines @@ -43,10 +44,24 @@ class BundledPluginsState : ApplicationInitializedListener { val loadedPlugins: Set @VisibleForTesting get() = PluginManagerCore.getLoadedPlugins().filterTo(HashSet()) { it.isBundled } + private val stateExistedAtTheStart = AtomicReference(null) + + /** + * should be called before writing to the file + */ + fun checkStateExistedAtTheStart(bundledPluginsFile: Path = PathManager.getConfigDir().resolve(BUNDLED_PLUGINS_FILENAME)): Boolean { + if (stateExistedAtTheStart.get() == null) { + stateExistedAtTheStart.set(bundledPluginsFile.exists()) + } + return stateExistedAtTheStart.get() + } + @VisibleForTesting fun writePluginIdsToFile(pluginIds: Set, configDir: Path = PathManager.getConfigDir()) { + val bundledPluginsFile = configDir.resolve(BUNDLED_PLUGINS_FILENAME) + checkStateExistedAtTheStart(bundledPluginsFile) PluginManagerCore.writePluginIdsToFile( - configDir.resolve(BUNDLED_PLUGINS_FILENAME), + bundledPluginsFile, pluginIds.map { "${it.pluginId.idString}|${it.category}\n" }, ) } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/customization/ChangeMainToolbarColorAction.kt b/platform/platform-impl/src/com/intellij/ide/ui/customization/ChangeMainToolbarColorAction.kt index 5256db033c4b..64a857fa678a 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/customization/ChangeMainToolbarColorAction.kt +++ b/platform/platform-impl/src/com/intellij/ide/ui/customization/ChangeMainToolbarColorAction.kt @@ -14,19 +14,21 @@ import java.awt.Point /** * @author Konstantin Bulenkov */ -class ChangeMainToolbarColorAction : DumbAwareAction() { +private class ChangeMainToolbarColorAction : DumbAwareAction() { override fun actionPerformed(e: AnActionEvent) { val project = e.project!! val ideFrame = IdeFocusManager.getInstance(project).lastFocusedFrame - var relativePoint:RelativePoint? = null + var relativePoint: RelativePoint? = null if (ideFrame != null) { relativePoint = RelativePoint(ideFrame.component, Point(200, 30)) } - ColorChooserService.instance.showPopup(project, - ProjectWindowCustomizerService.getInstance().getToolbarBackground(project), - { color, _ -> ProjectWindowCustomizerService.getInstance().setToolbarColor(color, project) }, - relativePoint) + ColorChooserService.instance.showPopup(project = project, + currentColor = ProjectWindowCustomizerService.getInstance().getToolbarBackground(project), + listener = { color, _ -> + ProjectWindowCustomizerService.getInstance().setToolbarColor(color, project) + }, + location = relativePoint) } override fun getActionUpdateThread(): ActionUpdateThread { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.theme.json b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.theme.json index 44ccc6d3bf20..f46044961e66 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.theme.json +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.theme.json @@ -695,10 +695,6 @@ "Ide.Shadow": { "borderInsets": "6,10,14,10", - "topLeftSize": "18,14", - "topRightSize": "18,14", - "bottomLeftSize": "18,22", - "bottomRightSize": "18,22", "top0Color": "#2C2C2C92", "top1Color": "#24242492", "bottom0Color": "#20202092", @@ -718,10 +714,6 @@ }, "Notification.Shadow": { "borderInsets": "6,10,6,10", - "topLeftSize": "18,14", - "topRightSize": "18,14", - "bottomLeftSize": "18,22", - "bottomRightSize": "18,22", "top0Color": "#2C2C2C32", "top1Color": "#24242432", "bottom0Color": "#20202032", diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.theme.json b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.theme.json index d51b6969c5d0..8f8b32895cbe 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.theme.json +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.theme.json @@ -406,10 +406,6 @@ "Ide.Shadow": { "borderInsets": "6,10,14,10", - "topLeftSize": "18,14", - "topRightSize": "18,14", - "bottomLeftSize": "18,22", - "bottomRightSize": "18,22", "top0Color": "#FCFCFC92", "top1Color": "#F4F4F492", "bottom0Color": "#F0F0F092", @@ -429,10 +425,6 @@ }, "Notification.Shadow": { "borderInsets": "6,10,6,10", - "topLeftSize": "18,14", - "topRightSize": "18,14", - "bottomLeftSize": "18,22", - "bottomRightSize": "18,22", "top0Color": "#FCFCFC32", "top1Color": "#F4F4F432", "bottom0Color": "#F0F0F032", diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.kt b/platform/platform-impl/src/com/intellij/idea/StartupUtil.kt index b48ca34f12b8..d396ca90c46b 100644 --- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.kt +++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.kt @@ -11,6 +11,7 @@ import com.intellij.ide.* import com.intellij.ide.bootstrap.* import com.intellij.ide.gdpr.EndUserAgreement import com.intellij.ide.instrument.WriteIntentLockInstrumenter +import com.intellij.ide.plugins.BundledPluginsState import com.intellij.ide.plugins.PluginManagerCore import com.intellij.ide.ui.laf.IntelliJLaf import com.intellij.idea.DirectoryLock.CannotActivateException @@ -213,12 +214,15 @@ fun CoroutineScope.startApplication(args: List, appStarter = appStarterDeferred.await(), euaDocumentDeferred = euaDocumentDeferred, ) + } - if (ConfigImportHelper.isNewUser() && System.getProperty(NewUiValue.KEY) == null) { - runCatching { - EarlyAccessRegistryManager.setAndFlush(mapOf(NewUiValue.KEY to "true")) - }.getOrLogException(log) - } + if ((ConfigImportHelper.isNewUser() || + // config directory may exist even if user is a new. + !(BundledPluginsState.checkStateExistedAtTheStart() || ApplicationManagerEx.isInIntegrationTest())) + && System.getProperty(NewUiValue.KEY) == null) { + runCatching { + EarlyAccessRegistryManager.setAndFlush(mapOf(NewUiValue.KEY to true.toString())) + }.getOrLogException(logDeferred.await()) } PluginManagerCore.scheduleDescriptorLoading(asyncScope, zipFilePoolDeferred) @@ -335,7 +339,12 @@ fun CoroutineScope.startApplication(args: List, } fun isConfigImportNeeded(configPath: Path): Boolean { - return !Files.exists(configPath) || Files.exists(configPath.resolve(ConfigImportHelper.CUSTOM_MARKER_FILE_NAME)) + // switch off import dialog for UI tests + if (java.lang.Boolean.getBoolean("idea.is.force.import.config.switched.off")) { + return false + } + return !Files.exists(configPath) + || Files.exists(configPath.resolve(ConfigImportHelper.CUSTOM_MARKER_FILE_NAME)) || customTargetDirectoryToImportConfig != null } diff --git a/platform/platform-impl/src/com/intellij/internal/ui/ShowAboutPopupInDebugModeAction.java b/platform/platform-impl/src/com/intellij/internal/ui/ShowAboutPopupInDebugModeAction.java deleted file mode 100644 index 486ac9407fad..000000000000 --- a/platform/platform-impl/src/com/intellij/internal/ui/ShowAboutPopupInDebugModeAction.java +++ /dev/null @@ -1,22 +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 com.intellij.internal.ui; - -import com.intellij.ide.actions.AboutPopup; -import com.intellij.openapi.actionSystem.ActionUpdateThread; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.project.DumbAwareAction; -import com.intellij.openapi.wm.WindowManager; -import org.jetbrains.annotations.NotNull; - -final class ShowAboutPopupInDebugModeAction extends DumbAwareAction { - - @Override - public @NotNull ActionUpdateThread getActionUpdateThread() { - return ActionUpdateThread.BGT; - } - - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - AboutPopup.show(WindowManager.getInstance().suggestParentWindow(getEventProject(e)), true); - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/SplitButtonAction.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/SplitButtonAction.java index 18e06bf1940a..95e55b8caaf3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/SplitButtonAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/SplitButtonAction.java @@ -186,7 +186,7 @@ public class SplitButtonAction extends ActionGroup implements CustomComponentAct } } - x = baseRect.x + (x - actionIcon.getIconWidth()) / 2; + x = baseRect.x + (x - baseRect.x - actionIcon.getIconWidth()) / 2; y = baseRect.y + (baseRect.height - actionIcon.getIconHeight()) / 2; look.paintIcon(g, this, actionIcon, x, y); } diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java index dddd0c7c4e83..82ab81d362ed 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java @@ -11,6 +11,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.keymap.impl.IdeMouseEventDispatcher; import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.JBPopupListener; +import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Key; @@ -20,6 +22,8 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.Strings; import com.intellij.ui.ExperimentalUI; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.ui.popup.AbstractPopup; import com.intellij.ui.popup.PopupFactoryImpl; import com.intellij.ui.popup.PopupState; import com.intellij.ui.popup.WizardPopup; @@ -247,10 +251,39 @@ public class ActionButton extends JComponent implements ActionButtonComponent, A popup.setShowSubmenuOnHover(true); popup.setAlignByParentBounds(false); popup.setActiveRoot(getPopupContainer(this) == null); - popup.showUnderneathOf(event.getInputEvent().getComponent()); + InputEvent inputEvent = event.getInputEvent(); + LOG.assertTrue(inputEvent != null); + Component component = inputEvent.getComponent(); + adjustVerticalOverlapping(popup, component); + popup.showUnderneathOf(component); return popup; } + public static void adjustVerticalOverlapping(JBPopup popup, Component component){ + popup.addListener(new JBPopupListener() { + @Override + public void beforeShown(@NotNull LightweightWindowEvent event) { + Dimension popupSize = getFullPopupSize(popup); + Point currentLocation = popup.getLocationOnScreen(); + Rectangle currentArea = new Rectangle(currentLocation, popupSize); + Point aboveLocation = new RelativePoint(component, new Point(0, 0)).getScreenPoint(); + Rectangle componentArea = new Rectangle(aboveLocation, component.getSize()); + if (currentArea.intersects(componentArea)) { + int y = aboveLocation.y - popupSize.height; + if (y >= 0) { + popup.setLocation(new Point(currentLocation.x, y)); + } + } + } + }); + } + + private static @NotNull Dimension getFullPopupSize(@NotNull JBPopup popup){ + Dimension contentSize = popup.getSize(); + int footerAdvertisementHeight = popup instanceof AbstractPopup abstractPopup ? abstractPopup.getAdComponentHeight() : 0; + return new Dimension(contentSize.width, contentSize.height + footerAdvertisementHeight); + } + @NotNull private MenuItemPresentationFactory createPresentationFactory() { return new MenuItemPresentationFactory() { diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.kt b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.kt index 693dfcea820f..1b48ded4dd49 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.kt @@ -462,10 +462,15 @@ open class ActionManagerImpl protected constructor(private val coroutineScope: C synchronized(lock) { if (element.attributes.get(OVERRIDES_ATTR_NAME).toBoolean()) { - if (getActionOrStub(id) == null) { - LOG.error("$element '$id' doesn't override anything") + val actionOrStub = getActionOrStub(id) + if (actionOrStub == null) { + LOG.error("'$id' action group in '${plugin.name}' does not override anything") return } + if (action is ActionGroup && actionOrStub is ActionGroup && + action.isPopup != actionOrStub.isPopup) { + LOG.info("'$id' action group in '${plugin.name}' sets isPopup=$action.isPopup") + } val prev = replaceAction(actionId = id, newAction = action, pluginId = plugin.pluginId) if (action is DefaultActionGroup && prev is DefaultActionGroup) { @@ -542,6 +547,14 @@ open class ActionManagerImpl protected constructor(private val coroutineScope: C @Suppress("NAME_SHADOWING") val id = id ?: "" + val popup = element.attributes.get("popup") + if (popup != null) { + group.isPopup = popup.toBoolean() + if (group is ActionGroupStub) { + group.popupDefinedInXml = true + } + } + registerOrReplaceActionInner(element = element, id = id, action = group, plugin = module) val presentation = group.templatePresentation @@ -586,14 +599,6 @@ open class ActionManagerImpl protected constructor(private val coroutineScope: C presentation.icon = loadIcon(module = module, iconPath = iconPath, requestor = className) } - // popup - val popup = element.attributes.get("popup") - if (popup != null) { - group.isPopup = popup.toBoolean() - if (group is ActionGroupStub) { - group.popupDefinedInXml = true - } - } val searchable = element.attributes.get("searchable") if (searchable != null) { group.isSearchable = searchable.toBoolean() @@ -1329,7 +1334,7 @@ open class ActionManagerImpl protected constructor(private val coroutineScope: C } } - private val _timerEvents = MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_LATEST) + private val _timerEvents = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_LATEST) @Internal @Experimental diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionMenu.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionMenu.java deleted file mode 100644 index 429ceb88fde9..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionMenu.java +++ /dev/null @@ -1,666 +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 com.intellij.openapi.actionSystem.impl; - -import com.intellij.ide.DataManager; -import com.intellij.ide.IdeEventQueue; -import com.intellij.ide.ui.UISettings; -import com.intellij.internal.inspector.UiInspectorUtil; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.actionSystem.ex.MainMenuPresentationAware; -import com.intellij.openapi.actionSystem.impl.actionholder.ActionRef; -import com.intellij.openapi.actionSystem.impl.actionholder.ActionRefKt; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.ui.JBPopupMenu; -import com.intellij.openapi.util.*; -import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.wm.IdeFocusManager; -import com.intellij.openapi.wm.IdeFrame; -import com.intellij.openapi.wm.StatusBar; -import com.intellij.ui.ColorUtil; -import com.intellij.ui.ComponentUtil; -import com.intellij.ui.ExperimentalUI; -import com.intellij.ui.JBColor; -import com.intellij.ui.awt.RelativePoint; -import com.intellij.ui.components.JBMenu; -import com.intellij.ui.icons.IconUtilKt; -import com.intellij.ui.mac.foundation.NSDefaults; -import com.intellij.ui.mac.screenmenu.Menu; -import com.intellij.ui.plaf.beg.BegMenuItemUI; -import com.intellij.ui.plaf.beg.IdeaMenuUI; -import com.intellij.util.*; -import com.intellij.util.concurrency.EdtScheduledExecutorService; -import com.intellij.util.concurrency.annotations.RequiresEdt; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.MenuEvent; -import javax.swing.event.MenuListener; -import java.awt.*; -import java.awt.event.AWTEventListener; -import java.awt.event.ComponentEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.util.Arrays; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -public final class ActionMenu extends JBMenu { - /** - * By default, a "performable" non-empty popup action group menu item still shows a submenu. - * Use this key to disable the submenu and avoid children expansion on update as follows: - *

- * {@code presentation.putClientProperty(ActionMenu.SUPPRESS_SUBMENU, true)}. - *

- * Both ordinary and template presentations are supported. - * - * @see Presentation#setPerformGroup(boolean) - */ - public static final Key SUPPRESS_SUBMENU = Key.create("SUPPRESS_SUBMENU"); - - private final String myPlace; - private final DataContext myContext; - private final ActionRef myGroup; - private final PresentationFactory myPresentationFactory; - private final Presentation myPresentation; - private boolean myMnemonicEnabled; - private StubItem myStubItem; // A PATCH!!! Do not remove this code, otherwise you will lose all keyboard navigation in JMenuBar. - private final boolean myUseDarkIcons; - private Disposable myDisposable; - private final @Nullable Menu myScreenMenuPeer; - private final @Nullable SubElementSelector mySubElementSelector; - private final boolean myHeaderMenuItem; - - public ActionMenu(@Nullable DataContext context, - @NotNull String place, - @NotNull ActionGroup group, - @NotNull PresentationFactory presentationFactory, - boolean enableMnemonics, - boolean useDarkIcons) { - this(context, place, group, presentationFactory, enableMnemonics, useDarkIcons, false); - } - - public ActionMenu(@Nullable DataContext context, - @NotNull String place, - @NotNull ActionGroup group, - @NotNull PresentationFactory presentationFactory, - boolean enableMnemonics, - boolean useDarkIcons, - boolean headerMenuItem) { - myContext = context; - myPlace = place; - myGroup = ActionRefKt.createActionRef(group); - myPresentationFactory = presentationFactory; - myPresentation = myPresentationFactory.getPresentation(group); - myMnemonicEnabled = enableMnemonics; - myUseDarkIcons = useDarkIcons; - myHeaderMenuItem = headerMenuItem; - mySubElementSelector = SubElementSelector.isForceDisabled ? null : new SubElementSelector(this); - - if (Menu.isJbScreenMenuEnabled() && ActionPlaces.MAIN_MENU.equals(myPlace)) { - myScreenMenuPeer = new Menu(myPresentation.getText(enableMnemonics)); - myScreenMenuPeer.setOnOpen(() -> { - // NOTE: setSelected(true) calls fillMenu internally - setSelected(true); - }, this); - myScreenMenuPeer.setOnClose(() -> setSelected(false), this); - myScreenMenuPeer.listenPresentationChanges(myPresentation); - } - else { - myScreenMenuPeer = null; - updateUI(); - } - - init(); - - if (myScreenMenuPeer == null) { - // also triggering initialization of private field "popupMenu" from JMenu with our own JBPopupMenu - BegMenuItemUI.registerMultiChoiceSupport(getPopupMenu(), popupMenu -> { - Utils.updateMenuItems(popupMenu, getDataContext(), myPlace, myPresentationFactory); - }); - } - } - - public @NotNull AnAction getAnAction() { return myGroup.getAction(); } - - @Override - public void removeNotify() { - super.removeNotify(); - if (myDisposable != null) { - Disposer.dispose(myDisposable); - myDisposable = null; - } - } - - private JPopupMenu mySpecialMenu; - - @Override - public JPopupMenu getPopupMenu() { - if (mySpecialMenu == null) { - mySpecialMenu = new JBPopupMenu(); - mySpecialMenu.setInvoker(this); - popupListener = createWinListener(mySpecialMenu); - ReflectionUtil.setField(JMenu.class, this, JPopupMenu.class, "popupMenu", mySpecialMenu); - UiInspectorUtil.registerProvider(mySpecialMenu, () -> UiInspectorUtil.collectActionGroupInfo("Menu", myGroup.getAction(), myPlace)); - } - return super.getPopupMenu(); - } - - @Override - public void updateUI() { - // null myPlace means that Swing calls updateUI before our constructor - if (myScreenMenuPeer != null || myPlace == null) { - return; - } - - setUI(IdeaMenuUI.createUI(this)); - setFont(FontUtil.getMenuFont()); - - JPopupMenu popupMenu = getPopupMenu(); - if (popupMenu != null) { - popupMenu.updateUI(); - } - } - - public @Nullable Menu getScreenMenuPeer() { - return myScreenMenuPeer; - } - - public boolean isHeaderMenuItem() { - return myHeaderMenuItem; - } - - private void init() { - boolean macSystemMenu = SystemInfo.isMacSystemMenu && isMainMenuPlace(); - - myStubItem = macSystemMenu ? null : new StubItem(); - addStubItem(); - setBorderPainted(false); - - MenuListenerImpl menuListener = new MenuListenerImpl(); - addMenuListener(menuListener); - getModel().addChangeListener(menuListener); - - updateFromPresentation(myMnemonicEnabled); - } - - public boolean isMainMenuPlace() { - return myPlace.equals(ActionPlaces.MAIN_MENU); - } - - public void updateFromPresentation(boolean enableMnemonics) { - myMnemonicEnabled = enableMnemonics; - setVisible(myPresentation.isVisible()); - setEnabled(myPresentation.isEnabled()); - - setText(myPresentation.getText(myMnemonicEnabled)); - setMnemonic(myPresentation.getMnemonic()); - setDisplayedMnemonicIndex(myPresentation.getDisplayedMnemonicIndex()); - updateIcon(); - } - - private void addStubItem() { - if (myStubItem != null) { - add(myStubItem); - } - } - - @Override - public void setDisplayedMnemonicIndex(int index) throws IllegalArgumentException { - super.setDisplayedMnemonicIndex(myMnemonicEnabled ? index : -1); - } - - @Override - public void setMnemonic(int mnemonic) { - super.setMnemonic(myMnemonicEnabled ? mnemonic : 0); - } - - private void updateIcon() { - UISettings settings = UISettings.getInstanceOrNull(); - Icon icon = myPresentation.getIcon(); - if (icon != null && settings != null && settings.getShowIconsInMenus()) { - if (SystemInfo.isMacSystemMenu && ActionPlaces.MAIN_MENU.equals(myPlace)) { - // JDK can't paint correctly our HiDPI icons at the system menu bar - icon = IconUtilKt.getMenuBarIcon(icon, myUseDarkIcons); - } - else if (shouldConvertIconToDarkVariant()) { - icon = IconLoader.getDarkIcon(icon, true); - } - if (isShowNoIcons()) { - setIcon(null); - setDisabledIcon(null); - } - else { - setIcon(icon); - Icon presentationDisabledIcon = myPresentation.getDisabledIcon(); - setDisabledIcon(presentationDisabledIcon == null ? IconLoader.getDisabledIcon(icon) : presentationDisabledIcon); - if (myScreenMenuPeer != null) { - myScreenMenuPeer.setIcon(icon); - } - } - } - } - - static boolean shouldConvertIconToDarkVariant() { - return JBColor.isBright() && ColorUtil.isDark(JBColor.namedColor("MenuItem.background", 0xffffff)); - } - - static boolean isShowNoIcons() { - return SystemInfoRt.isMac && (Registry.get("ide.macos.main.menu.alignment.options").isOptionEnabled("No icons") || ExperimentalUI.isNewUI()); - } - - static boolean isShowNoIcons(AnAction action) { - if (action == null) { - return false; - } - if (action instanceof MainMenuPresentationAware && ((MainMenuPresentationAware)action).alwaysShowIconInMainMenu()) { - return false; - } - return isShowNoIcons(); - } - - static boolean isAligned() { - return SystemInfoRt.isMac && Registry.get("ide.macos.main.menu.alignment.options").isOptionEnabled("Aligned"); - } - - static boolean isAlignedInGroup() { - return SystemInfoRt.isMac && Registry.get("ide.macos.main.menu.alignment.options").isOptionEnabled("Aligned in group"); - } - - @Override - public void menuSelectionChanged(boolean isIncluded) { - super.menuSelectionChanged(isIncluded); - showDescriptionInStatusBar(isIncluded, this, myPresentation.getDescription()); - } - - public static void showDescriptionInStatusBar(boolean isIncluded, Component component, @NlsContexts.StatusBarText String description) { - IdeFrame frame = (IdeFrame)(component instanceof IdeFrame ? component : SwingUtilities.getAncestorOfClass(IdeFrame.class, component)); - StatusBar statusBar; - if (frame != null && (statusBar = frame.getStatusBar()) != null) { - statusBar.setInfo(isIncluded ? description : null); - } - } - - @Override - protected void processMouseEvent(MouseEvent e) { - boolean shouldCancelIgnoringOfNextSelectionRequest = false; - - if (mySubElementSelector != null) { - switch (e.getID()) { - case MouseEvent.MOUSE_PRESSED -> { - mySubElementSelector.ignoreNextSelectionRequest(); - shouldCancelIgnoringOfNextSelectionRequest = true; - } - case MouseEvent.MOUSE_ENTERED -> mySubElementSelector.ignoreNextSelectionRequest(getDelay() * 2); - } - } - - try { - super.processMouseEvent(e); - } - finally { - if (shouldCancelIgnoringOfNextSelectionRequest) { - mySubElementSelector.cancelIgnoringOfNextSelectionRequest(); - } - } - } - - private class MenuListenerImpl implements ChangeListener, MenuListener { - ScheduledFuture myDelayedClear; - boolean isSelected = false; - - @Override - public void stateChanged(ChangeEvent e) { - // Re-implement javax.swing.JMenu.MenuChangeListener to avoid recursive event notifications - // if 'menuSelected' fires unrelated 'stateChanged' event, without changing 'model.isSelected()' value. - ButtonModel model = (ButtonModel)e.getSource(); - boolean modelSelected = model.isSelected(); - - if (modelSelected != isSelected) { - isSelected = modelSelected; - - if (modelSelected) { - menuSelected(); - } - else { - menuDeselected(); - } - } - } - - @Override - public void menuCanceled(MenuEvent e) { - onMenuHidden(); - } - - @Override - public void menuDeselected(MenuEvent e) { - // Use ChangeListener instead to guard against recursive calls - } - - @Override - public void menuSelected(MenuEvent e) { - // Use ChangeListener instead to guard against recursive calls - } - - private void menuDeselected() { - if (myDisposable != null) { - Disposer.dispose(myDisposable); - myDisposable = null; - } - onMenuHidden(); - - if (mySubElementSelector != null) mySubElementSelector.cancelNextSelection(); - } - - private void onMenuHidden() { - Runnable clearSelf = () -> { - clearItems(); - addStubItem(); - }; - - if (SystemInfo.isMacSystemMenu && isMainMenuPlace()) { - // Menu items may contain mnemonic, and they can affect key-event dispatching (when Alt pressed) - // To avoid the influence of mnemonic it's necessary to clear items when a menu was hidden. - // When a user selects item of a system menu (under macOS), AppKit generates such sequence: CloseParentMenu -> PerformItemAction - // So we can destroy menu-item before item's action performed, and because of that action will not be executed. - // Defer clearing to avoid this problem. - myDelayedClear = EdtScheduledExecutorService.getInstance().schedule(clearSelf, 1000, TimeUnit.MILLISECONDS); - } - else { - clearSelf.run(); - } - } - - private void menuSelected() { - UsabilityHelper helper = new UsabilityHelper(ActionMenu.this); - if (myDisposable == null) { - myDisposable = Disposer.newDisposable(); - } - Disposer.register(myDisposable, helper); - if (myDelayedClear != null) { - myDelayedClear.cancel(false); - myDelayedClear = null; - clearItems(); - } - if (SystemInfo.isMacSystemMenu && ActionPlaces.MAIN_MENU.equals(myPlace)) { - fillMenu(); - } - } - } - - @Override - public void setPopupMenuVisible(boolean b) { - if (b && !(SystemInfo.isMacSystemMenu && ActionPlaces.MAIN_MENU.equals(myPlace))) { - fillMenu(); - if (!isSelected()) { - return; - } - } - - super.setPopupMenuVisible(b); - - if (b && (mySubElementSelector != null)) { - mySubElementSelector.selectSubElementIfNecessary(); - } - } - - public void clearItems() { - if (SystemInfo.isMacSystemMenu && isMainMenuPlace()) { - for (Component menuComponent : getMenuComponents()) { - if (menuComponent instanceof ActionMenu) { - ((ActionMenu)menuComponent).clearItems(); - } - else if (menuComponent instanceof ActionMenuItem) { - // Looks like an old-fashioned ugly workaround - // JDK 1.7 on Mac works wrong with such functional keys - if (!SystemInfo.isMac) { - ((ActionMenuItem)menuComponent).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F24, 0)); - } - } - } - } - - removeAll(); - validate(); - } - - private @NotNull DataContext getDataContext() { - DataContext context; - - if (myContext != null) { - context = myContext; - } - else { - DataManager dataManager = DataManager.getInstance(); - @SuppressWarnings("deprecation") DataContext contextFromFocus = dataManager.getDataContext(); - context = contextFromFocus; - if (PlatformCoreDataKeys.CONTEXT_COMPONENT.getData(context) == null) { - IdeFrame frame = ComponentUtil.getParentOfType((Class)IdeFrame.class, (Component)this); - context = dataManager.getDataContext(IdeFocusManager.getGlobalInstance().getLastFocusedFor((Window)frame)); - } - context = Utils.wrapDataContext(context); - } - return context; - } - - public void fillMenu() { - DataContext context = getDataContext(); - boolean isDarkMenu = SystemInfo.isMacSystemMenu && NSDefaults.isDarkMenuBar(); - Utils.fillMenu(myGroup.getAction(), this, myMnemonicEnabled, myPresentationFactory, context, myPlace, true, isDarkMenu, - RelativePoint.getNorthEastOf(this), () -> !isSelected()); - } - - private static final class UsabilityHelper implements IdeEventQueue.EventDispatcher, AWTEventListener, Disposable { - private Component myComponent; - private Point myStartMousePoint; - private Point myUpperTargetPoint; - private Point myLowerTargetPoint; - private SingleAlarm myCallbackAlarm; - private MouseEvent myEventToRedispatch; - - private UsabilityHelper(Component component) { - myCallbackAlarm = new SingleAlarm(() -> { - Disposer.dispose(myCallbackAlarm); - myCallbackAlarm = null; - if (myEventToRedispatch != null) { - IdeEventQueue.getInstance().dispatchEvent(myEventToRedispatch); - } - }, 50, this, Alarm.ThreadToUse.SWING_THREAD, ModalityState.any()); - myComponent = component; - PointerInfo info = MouseInfo.getPointerInfo(); - myStartMousePoint = info != null ? info.getLocation() : null; - if (myStartMousePoint != null) { - Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.COMPONENT_EVENT_MASK); - IdeEventQueue.getInstance().addDispatcher(this, this); - } - } - - @Override - public void eventDispatched(AWTEvent event) { - if (event instanceof ComponentEvent componentEvent) { - Component component = componentEvent.getComponent(); - JPopupMenu popup = ComponentUtil.getParentOfType((Class)JPopupMenu.class, component); - if (popup != null && popup.getInvoker() == myComponent && popup.isShowing()) { - Rectangle bounds = popup.getBounds(); - if (bounds.isEmpty()) return; - bounds.setLocation(popup.getLocationOnScreen()); - if (myStartMousePoint.x < bounds.x) { - myUpperTargetPoint = new Point(bounds.x, bounds.y); - myLowerTargetPoint = new Point(bounds.x, bounds.y + bounds.height); - } - if (myStartMousePoint.x > bounds.x + bounds.width) { - myUpperTargetPoint = new Point(bounds.x + bounds.width, bounds.y); - myLowerTargetPoint = new Point(bounds.x + bounds.width, bounds.y + bounds.height); - } - } - } - } - - @Override - public boolean dispatch(@NotNull AWTEvent e) { - if (e instanceof MouseEvent && myUpperTargetPoint != null && myLowerTargetPoint != null && myCallbackAlarm != null) { - if (e.getID() == MouseEvent.MOUSE_PRESSED || e.getID() == MouseEvent.MOUSE_RELEASED || e.getID() == MouseEvent.MOUSE_CLICKED) { - return false; - } - Point point = ((MouseEvent)e).getLocationOnScreen(); - Rectangle bounds = myComponent.getBounds(); - bounds.setLocation(myComponent.getLocationOnScreen()); - boolean isMouseMovingTowardsSubmenu = bounds.contains(point) || new Polygon( - new int[]{myStartMousePoint.x, myUpperTargetPoint.x, myLowerTargetPoint.x}, - new int[]{myStartMousePoint.y, myUpperTargetPoint.y, myLowerTargetPoint.y}, - 3).contains(point); - - myEventToRedispatch = (MouseEvent)e; - - if (!isMouseMovingTowardsSubmenu) { - myCallbackAlarm.request(); - } - else { - myCallbackAlarm.cancel(); - } - return true; - } - return false; - } - - @Override - public void dispose() { - myComponent = null; - myEventToRedispatch = null; - myStartMousePoint = myUpperTargetPoint = myLowerTargetPoint = null; - Toolkit.getDefaultToolkit().removeAWTEventListener(this); - } - } - - private static final class SubElementSelector { - static final boolean isForceDisabled = - SystemInfo.isMacSystemMenu || - !Registry.is("ide.popup.menu.navigation.keyboard.selectFirstEnabledSubItem", false); - - - SubElementSelector(@NotNull ActionMenu owner) { - if (isForceDisabled) { - throw new IllegalStateException("Attempt to create an instance of ActionMenu.SubElementSelector class when it is force disabled"); - } - - myOwner = owner; - myShouldIgnoreNextSelectionRequest = false; - myShouldIgnoreNextSelectionRequestSinceTimestamp = -1; - myShouldIgnoreNextSelectionRequestTimeoutMs = -1; - myCurrentRequestId = -1; - } - - @RequiresEdt - void ignoreNextSelectionRequest(int timeoutMs) { - myShouldIgnoreNextSelectionRequest = true; - myShouldIgnoreNextSelectionRequestTimeoutMs = timeoutMs; - if (timeoutMs >= 0) { - myShouldIgnoreNextSelectionRequestSinceTimestamp = System.currentTimeMillis(); - } - else { - myShouldIgnoreNextSelectionRequestSinceTimestamp = -1; - } - } - - @RequiresEdt - void ignoreNextSelectionRequest() { - ignoreNextSelectionRequest(-1); - } - - @RequiresEdt - void cancelIgnoringOfNextSelectionRequest() { - myShouldIgnoreNextSelectionRequest = false; - myShouldIgnoreNextSelectionRequestSinceTimestamp = -1; - myShouldIgnoreNextSelectionRequestTimeoutMs = -1; - } - - @RequiresEdt - void selectSubElementIfNecessary() { - final boolean shouldIgnoreThisSelectionRequest; - if (myShouldIgnoreNextSelectionRequest) { - if (myShouldIgnoreNextSelectionRequestTimeoutMs >= 0) { - shouldIgnoreThisSelectionRequest = - ( (System.currentTimeMillis() - myShouldIgnoreNextSelectionRequestSinceTimestamp) <= myShouldIgnoreNextSelectionRequestTimeoutMs ); - } - else { - shouldIgnoreThisSelectionRequest = true; - } - } - else { - shouldIgnoreThisSelectionRequest = false; - } - - cancelIgnoringOfNextSelectionRequest(); - - if (shouldIgnoreThisSelectionRequest) { - return; - } - - final int thisRequestId = ++myCurrentRequestId; - SwingUtilities.invokeLater(() -> selectFirstEnabledElement(thisRequestId)); - } - - @RequiresEdt - void cancelNextSelection() { - ++myCurrentRequestId; - } - - - private final @NotNull ActionMenu myOwner; - private boolean myShouldIgnoreNextSelectionRequest; - private long myShouldIgnoreNextSelectionRequestSinceTimestamp; - private int myShouldIgnoreNextSelectionRequestTimeoutMs; - private int myCurrentRequestId; - - - @RequiresEdt - private void selectFirstEnabledElement(final int requestId) { - if (requestId != myCurrentRequestId) { - // the request was cancelled or a newer request was created - return; - } - - if (!myOwner.isSelected()) { - return; - } - - final var menuSelectionManager = MenuSelectionManager.defaultManager(); - - final var currentSelectedPath = menuSelectionManager.getSelectedPath(); - if (currentSelectedPath.length < 2) { - return; - } - - final var lastElementInCurrentPath = currentSelectedPath[currentSelectedPath.length - 1]; - - final MenuElement[] newSelectionPath; - if (lastElementInCurrentPath == myOwner.myStubItem) { - newSelectionPath = currentSelectedPath.clone(); - } - else if (lastElementInCurrentPath == myOwner.getPopupMenu()) { - newSelectionPath = Arrays.copyOf(currentSelectedPath, currentSelectedPath.length + 1); - } - else if ( (currentSelectedPath[currentSelectedPath.length - 2] == myOwner.getPopupMenu()) && - !ArrayUtil.contains(lastElementInCurrentPath.getComponent(), myOwner.getMenuComponents()) ) { - newSelectionPath = currentSelectedPath.clone(); - } - else { - return; - } - - final var menuComponents = myOwner.getMenuComponents(); - for (final var component : menuComponents) { - if ((component != myOwner.myStubItem) && component.isEnabled() && (component instanceof JMenuItem)) { - newSelectionPath[newSelectionPath.length - 1] = (MenuElement)component; - menuSelectionManager.setSelectedPath(newSelectionPath); - - return; - } - } - } - } -} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionMenu.kt b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionMenu.kt new file mode 100644 index 000000000000..d4543c0caa14 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionMenu.kt @@ -0,0 +1,604 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.openapi.actionSystem.impl + +import com.intellij.ide.DataManager +import com.intellij.ide.IdeEventQueue +import com.intellij.ide.IdeEventQueue.Companion.getInstance +import com.intellij.ide.ui.UISettings +import com.intellij.internal.inspector.UiInspectorContextProvider +import com.intellij.internal.inspector.UiInspectorUtil +import com.intellij.openapi.Disposable +import com.intellij.openapi.actionSystem.* +import com.intellij.openapi.actionSystem.ex.MainMenuPresentationAware +import com.intellij.openapi.actionSystem.impl.actionholder.createActionRef +import com.intellij.openapi.application.ModalityState +import com.intellij.openapi.ui.JBPopupMenu +import com.intellij.openapi.util.* +import com.intellij.openapi.util.IconLoader.getDarkIcon +import com.intellij.openapi.util.IconLoader.getDisabledIcon +import com.intellij.openapi.util.registry.Registry +import com.intellij.openapi.wm.IdeFocusManager +import com.intellij.openapi.wm.IdeFrame +import com.intellij.ui.ColorUtil +import com.intellij.ui.ComponentUtil +import com.intellij.ui.ExperimentalUI +import com.intellij.ui.JBColor +import com.intellij.ui.awt.RelativePoint +import com.intellij.ui.components.JBMenu +import com.intellij.ui.icons.getMenuBarIcon +import com.intellij.ui.mac.foundation.NSDefaults +import com.intellij.ui.mac.screenmenu.Menu +import com.intellij.ui.plaf.beg.BegMenuItemUI +import com.intellij.ui.plaf.beg.IdeaMenuUI +import com.intellij.util.Alarm +import com.intellij.util.FontUtil +import com.intellij.util.ReflectionUtil +import com.intellij.util.SingleAlarm +import com.intellij.util.concurrency.EdtScheduledExecutorService +import com.intellij.util.concurrency.annotations.RequiresEdt +import java.awt.* +import java.awt.event.AWTEventListener +import java.awt.event.ComponentEvent +import java.awt.event.KeyEvent +import java.awt.event.MouseEvent +import java.util.concurrent.ScheduledFuture +import java.util.concurrent.TimeUnit +import javax.swing.* +import javax.swing.event.ChangeEvent +import javax.swing.event.ChangeListener +import javax.swing.event.MenuEvent +import javax.swing.event.MenuListener + +class ActionMenu @JvmOverloads constructor(private val context: DataContext?, + private val place: String, + group: ActionGroup, + private val presentationFactory: PresentationFactory, + private var isMnemonicEnabled: Boolean, + private val useDarkIcons: Boolean, + val isHeaderMenuItem: Boolean = false) : JBMenu() { + private val group = createActionRef(group) + private val presentation = presentationFactory.getPresentation(group) + // A PATCH!!! Do not remove this code, otherwise you will lose all keyboard navigation in JMenuBar. + private var stubItem: StubItem? = null + private var disposable: Disposable? = null + var screenMenuPeer: Menu? = null + private val subElementSelector = if (SubElementSelector.isForceDisabled) null else SubElementSelector(this) + val anAction: AnAction + get() = group.getAction() + + private var specialMenu: JPopupMenu? = null + + override fun removeNotify() { + super.removeNotify() + if (disposable != null) { + Disposer.dispose(disposable!!) + disposable = null + } + } + + init { + if (Menu.isJbScreenMenuEnabled() && ActionPlaces.MAIN_MENU == place) { + val screenMenuPeer = Menu(presentation.getText(isMnemonicEnabled)) + this.screenMenuPeer = screenMenuPeer + screenMenuPeer.setOnOpen(Runnable { + // NOTE: setSelected(true) calls fillMenu internally + setSelected(true) + }, this) + screenMenuPeer.setOnClose(Runnable { setSelected(false) }, this) + screenMenuPeer.listenPresentationChanges(presentation) + } + else { + screenMenuPeer = null + updateUI() + } + + init() + + if (screenMenuPeer == null) { + // also triggering initialization of private field "popupMenu" from JMenu with our own JBPopupMenu + BegMenuItemUI.registerMultiChoiceSupport(getPopupMenu()) { popupMenu -> + Utils.updateMenuItems(popupMenu, getDataContext(), this.place, this.presentationFactory) + } + } + } + + companion object { + /** + * By default, a "performable" non-empty popup action group menu item still shows a submenu. + * Use this key to disable the submenu and avoid children expansion on update as follows: + * + * `presentation.putClientProperty(ActionMenu.SUPPRESS_SUBMENU, true)`. + * + * Both ordinary and template presentations are supported. + * @see Presentation.setPerformGroup + */ + @JvmField + val SUPPRESS_SUBMENU: Key = Key.create("SUPPRESS_SUBMENU") + + @JvmStatic + fun shouldConvertIconToDarkVariant(): Boolean { + return JBColor.isBright() && ColorUtil.isDark(JBColor.namedColor("MenuItem.background", 0xffffff)) + } + + @JvmStatic + val isShowNoIcons: Boolean + get() { + return SystemInfoRt.isMac && (ExperimentalUI.isNewUI() || + Registry.get("ide.macos.main.menu.alignment.options").isOptionEnabled("No icons")) + } + + @JvmStatic + fun isShowNoIcons(action: AnAction?): Boolean { + return when { + action == null -> false + action is MainMenuPresentationAware && (action as MainMenuPresentationAware).alwaysShowIconInMainMenu() -> false + else -> isShowNoIcons + } + } + + @JvmStatic + val isAligned: Boolean + get() = SystemInfoRt.isMac && Registry.get("ide.macos.main.menu.alignment.options").isOptionEnabled("Aligned") + @JvmStatic + val isAlignedInGroup: Boolean + get() = SystemInfoRt.isMac && Registry.get("ide.macos.main.menu.alignment.options").isOptionEnabled("Aligned in group") + + @JvmStatic + fun showDescriptionInStatusBar(isIncluded: Boolean, component: Component?, description: @NlsContexts.StatusBarText String?) { + val frame = (if (component is IdeFrame) component else SwingUtilities.getAncestorOfClass(IdeFrame::class.java, component)) as? IdeFrame + frame?.getStatusBar()?.setInfo(if (isIncluded) description else null) + } + } + + override fun getPopupMenu(): JPopupMenu { + var specialMenu = specialMenu + if (specialMenu == null) { + specialMenu = JBPopupMenu() + this.specialMenu = specialMenu + specialMenu.setInvoker(this) + popupListener = createWinListener(specialMenu) + ReflectionUtil.setField(JMenu::class.java, this, JPopupMenu::class.java, "popupMenu", specialMenu) + UiInspectorUtil.registerProvider(specialMenu, UiInspectorContextProvider { + UiInspectorUtil.collectActionGroupInfo("Menu", group.getAction(), place) + }) + } + return super.getPopupMenu() + } + + override fun updateUI() { + // null myPlace means that Swing calls updateUI before our constructor + @Suppress("SENSELESS_COMPARISON") + if (screenMenuPeer != null || place == null) { + return + } + + setUI(IdeaMenuUI.createUI(this)) + setFont(FontUtil.getMenuFont()) + getPopupMenu().updateUI() + } + + private fun init() { + stubItem = if (SystemInfo.isMacSystemMenu && isMainMenuPlace) null else StubItem() + addStubItem() + setBorderPainted(false) + val menuListener = MenuListenerImpl() + addMenuListener(menuListener) + getModel().addChangeListener(menuListener) + updateFromPresentation(isMnemonicEnabled) + } + + val isMainMenuPlace: Boolean + get() = place == ActionPlaces.MAIN_MENU + + fun updateFromPresentation(enableMnemonics: Boolean) { + isMnemonicEnabled = enableMnemonics + isVisible = presentation.isVisible + setEnabled(presentation.isEnabled) + setText(presentation.getText(isMnemonicEnabled)) + mnemonic = presentation.getMnemonic() + displayedMnemonicIndex = presentation.getDisplayedMnemonicIndex() + updateIcon() + } + + private fun addStubItem() { + stubItem?.let { + add(it) + } + } + + override fun setDisplayedMnemonicIndex(index: Int) { + super.setDisplayedMnemonicIndex(if (isMnemonicEnabled) index else -1) + } + + override fun setMnemonic(mnemonic: Int) { + super.setMnemonic(if (isMnemonicEnabled) mnemonic else 0) + } + + private fun updateIcon() { + var icon = presentation.icon ?: return + if (!UISettings.getInstance().showIconsInMenus) { + return + } + + if (SystemInfo.isMacSystemMenu && ActionPlaces.MAIN_MENU == place) { + // JDK can't paint correctly our HiDPI icons at the system menu bar + icon = getMenuBarIcon(icon, useDarkIcons) + } + else if (shouldConvertIconToDarkVariant()) { + icon = getDarkIcon(icon, true) + } + + if (isShowNoIcons) { + setIcon(null) + setDisabledIcon(null) + } + else { + setIcon(icon) + val presentationDisabledIcon = presentation.disabledIcon + setDisabledIcon(presentationDisabledIcon ?: getDisabledIcon(icon)) + screenMenuPeer?.setIcon(icon) + } + } + + override fun menuSelectionChanged(isIncluded: Boolean) { + super.menuSelectionChanged(isIncluded) + showDescriptionInStatusBar(isIncluded = isIncluded, component = this, description = presentation.description) + } + + override fun processMouseEvent(e: MouseEvent) { + var shouldCancelIgnoringOfNextSelectionRequest = false + val subElementSelector = subElementSelector + if (subElementSelector != null) { + when (e.id) { + MouseEvent.MOUSE_PRESSED -> { + subElementSelector.ignoreNextSelectionRequest() + shouldCancelIgnoringOfNextSelectionRequest = true + } + MouseEvent.MOUSE_ENTERED -> subElementSelector.ignoreNextSelectionRequest(delay * 2) + } + } + + try { + super.processMouseEvent(e) + } + finally { + if (shouldCancelIgnoringOfNextSelectionRequest) { + subElementSelector?.cancelIgnoringOfNextSelectionRequest() + } + } + } + + private inner class MenuListenerImpl : ChangeListener, MenuListener { + var delayedClear: ScheduledFuture<*>? = null + var isSelected: Boolean = false + + override fun stateChanged(e: ChangeEvent) { + // Re-implement javax.swing.JMenu.MenuChangeListener to avoid recursive event notifications + // if 'menuSelected' fires unrelated 'stateChanged' event, without changing 'model.isSelected()' value. + val model = e.source as ButtonModel + val modelSelected = model.isSelected + if (modelSelected != isSelected) { + isSelected = modelSelected + if (modelSelected) { + menuSelected() + } + else { + menuDeselected() + } + } + } + + override fun menuCanceled(e: MenuEvent) { + onMenuHidden() + } + + override fun menuDeselected(e: MenuEvent) { + // Use ChangeListener instead to guard against recursive calls + } + + override fun menuSelected(e: MenuEvent) { + // Use ChangeListener instead to guard against recursive calls + } + + private fun menuDeselected() { + if (disposable != null) { + Disposer.dispose(disposable!!) + disposable = null + } + onMenuHidden() + subElementSelector?.cancelNextSelection() + } + + private fun onMenuHidden() { + val clearSelf = Runnable { + clearItems() + addStubItem() + } + + if (SystemInfo.isMacSystemMenu && isMainMenuPlace) { + // Menu items may contain mnemonic, and they can affect key-event dispatching (when Alt pressed) + // To avoid the influence of mnemonic it's necessary to clear items when a menu was hidden. + // When a user selects item of a system menu (under macOS), AppKit generates such sequence: CloseParentMenu -> PerformItemAction + // So we can destroy menu-item before item's action performed, and because of that action will not be executed. + // Defer clearing to avoid this problem. + delayedClear = EdtScheduledExecutorService.getInstance().schedule(clearSelf, 1000, TimeUnit.MILLISECONDS) + } + else { + clearSelf.run() + } + } + + private fun menuSelected() { + val helper = UsabilityHelper(this@ActionMenu) + if (disposable == null) { + disposable = Disposer.newDisposable() + } + Disposer.register(disposable!!, helper) + if (delayedClear != null) { + delayedClear!!.cancel(false) + delayedClear = null + clearItems() + } + if (SystemInfo.isMacSystemMenu && ActionPlaces.MAIN_MENU == place) { + fillMenu() + } + } + } + + override fun setPopupMenuVisible(value: Boolean) { + if (value && !(SystemInfo.isMacSystemMenu && ActionPlaces.MAIN_MENU == place)) { + fillMenu() + if (!isSelected) { + return + } + } + + super.setPopupMenuVisible(value) + + if (value) { + subElementSelector?.selectSubElementIfNecessary() + } + } + + fun clearItems() { + if (SystemInfo.isMacSystemMenu && isMainMenuPlace) { + for (menuComponent in getMenuComponents()) { + if (menuComponent is ActionMenu) { + menuComponent.clearItems() + } + else if (menuComponent is ActionMenuItem) { + // Looks like an old-fashioned ugly workaround + // JDK 1.7 on Mac works wrong with such functional keys + if (!SystemInfoRt.isMac) { + menuComponent.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F24, 0)) + } + } + } + } + removeAll() + validate() + } + + private fun getDataContext(): DataContext { + var context = context + if (context != null) { + return context + } + + val dataManager = DataManager.getInstance() + @Suppress("DEPRECATION") + context = dataManager.getDataContext() + if (PlatformCoreDataKeys.CONTEXT_COMPONENT.getData(context) == null) { + val frame = ComponentUtil.getParentOfType(IdeFrame::class.java, this) + context = dataManager.getDataContext(IdeFocusManager.getGlobalInstance().getLastFocusedFor(frame as Window?)) + } + return Utils.wrapDataContext(context) + } + + fun fillMenu() { + val context = getDataContext() + val isDarkMenu = SystemInfo.isMacSystemMenu && NSDefaults.isDarkMenuBar() + Utils.fillMenu(/* group = */ group.getAction(), + /* component = */ this, + /* enableMnemonics = */ isMnemonicEnabled, + /* presentationFactory = */ presentationFactory, + /* context = */ context, + /* place = */ place, + /* isWindowMenu = */ true, + /* useDarkIcons = */ isDarkMenu, + /* progressPoint = */ RelativePoint.getNorthEastOf(this)) { !isSelected } + } + + private class UsabilityHelper(component: Component) : IdeEventQueue.EventDispatcher, AWTEventListener, Disposable { + private var component: Component? + private var startMousePoint: Point? + private var upperTargetPoint: Point? = null + private var lowerTargetPoint: Point? = null + private var callbackAlarm: SingleAlarm? = null + private var eventToRedispatch: MouseEvent? = null + + init { + callbackAlarm = SingleAlarm({ + Disposer.dispose(callbackAlarm!!) + callbackAlarm = null + if (eventToRedispatch != null) { + getInstance().dispatchEvent(eventToRedispatch!!) + } + }, 50, this, Alarm.ThreadToUse.SWING_THREAD, ModalityState.any()) + this.component = component + val info = MouseInfo.getPointerInfo() + startMousePoint = info?.location + if (startMousePoint != null) { + Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.COMPONENT_EVENT_MASK) + getInstance().addDispatcher(this, this) + } + } + + override fun eventDispatched(event: AWTEvent) { + if (event !is ComponentEvent) { + return + } + + val component = event.component + val popup = ComponentUtil.getParentOfType(JPopupMenu::class.java, component) + if (popup != null && popup.invoker === this.component && popup.isShowing()) { + val bounds = popup.bounds + if (bounds.isEmpty) { + return + } + + bounds.location = popup.locationOnScreen + if (startMousePoint!!.x < bounds.x) { + upperTargetPoint = Point(bounds.x, bounds.y) + lowerTargetPoint = Point(bounds.x, bounds.y + bounds.height) + } + if (startMousePoint!!.x > bounds.x + bounds.width) { + upperTargetPoint = Point(bounds.x + bounds.width, bounds.y) + lowerTargetPoint = Point(bounds.x + bounds.width, bounds.y + bounds.height) + } + } + } + + override fun dispatch(e: AWTEvent): Boolean { + val callbackAlarm = callbackAlarm + if (e !is MouseEvent || upperTargetPoint == null || lowerTargetPoint == null || callbackAlarm == null) { + return false + } + + if (e.getID() == MouseEvent.MOUSE_PRESSED || e.getID() == MouseEvent.MOUSE_RELEASED || e.getID() == MouseEvent.MOUSE_CLICKED) { + return false + } + + val point = e.locationOnScreen + val bounds = component!!.bounds + bounds.location = component!!.locationOnScreen + val isMouseMovingTowardsSubmenu = bounds.contains(point) || + Polygon(intArrayOf(startMousePoint!!.x, upperTargetPoint!!.x, lowerTargetPoint!!.x), + intArrayOf(startMousePoint!!.y, upperTargetPoint!!.y, lowerTargetPoint!!.y), 3) + .contains(point) + eventToRedispatch = e + if (!isMouseMovingTowardsSubmenu) { + callbackAlarm.request() + } + else { + callbackAlarm.cancel() + } + return true + } + + override fun dispose() { + component = null + eventToRedispatch = null + lowerTargetPoint = null + upperTargetPoint = null + startMousePoint = null + Toolkit.getDefaultToolkit().removeAWTEventListener(this) + } + } + + private class SubElementSelector(private val owner: ActionMenu) { + companion object { + val isForceDisabled: Boolean = SystemInfo.isMacSystemMenu || + !Registry.`is`("ide.popup.menu.navigation.keyboard.selectFirstEnabledSubItem", false) + } + + @RequiresEdt + fun ignoreNextSelectionRequest(timeoutMs: Int) { + shouldIgnoreNextSelectionRequest = true + shouldIgnoreNextSelectionRequestTimeoutMs = timeoutMs + shouldIgnoreNextSelectionRequestSinceTimestamp = if (timeoutMs >= 0) { + System.currentTimeMillis() + } + else { + -1 + } + } + + @RequiresEdt + fun ignoreNextSelectionRequest() { + ignoreNextSelectionRequest(-1) + } + + @RequiresEdt + fun cancelIgnoringOfNextSelectionRequest() { + shouldIgnoreNextSelectionRequest = false + shouldIgnoreNextSelectionRequestSinceTimestamp = -1 + shouldIgnoreNextSelectionRequestTimeoutMs = -1 + } + + @RequiresEdt + fun selectSubElementIfNecessary() { + val shouldIgnoreThisSelectionRequest = if (shouldIgnoreNextSelectionRequest) { + if (shouldIgnoreNextSelectionRequestTimeoutMs >= 0) { + System.currentTimeMillis() - shouldIgnoreNextSelectionRequestSinceTimestamp <= shouldIgnoreNextSelectionRequestTimeoutMs + } + else { + true + } + } + else { + false + } + + cancelIgnoringOfNextSelectionRequest() + if (shouldIgnoreThisSelectionRequest) { + return + } + + val thisRequestId = ++currentRequestId + SwingUtilities.invokeLater { selectFirstEnabledElement(thisRequestId) } + } + + @RequiresEdt + fun cancelNextSelection() { + ++currentRequestId + } + + private var shouldIgnoreNextSelectionRequest = false + private var shouldIgnoreNextSelectionRequestSinceTimestamp = -1L + private var shouldIgnoreNextSelectionRequestTimeoutMs = -1 + private var currentRequestId = -1 + + init { + if (isForceDisabled) { + throw IllegalStateException("Attempt to create an instance of ActionMenu.SubElementSelector class when it is force disabled") + } + } + + @RequiresEdt + private fun selectFirstEnabledElement(requestId: Int) { + if (requestId != currentRequestId) { + // the request was canceled or a newer request was created + return + } + + if (!owner.isSelected) { + return + } + + val menuSelectionManager = MenuSelectionManager.defaultManager() + val currentSelectedPath = menuSelectionManager.getSelectedPath() + if (currentSelectedPath.size < 2) { + return + } + + val lastElementInCurrentPath = currentSelectedPath[currentSelectedPath.size - 1] + val newSelectionPath = when { + lastElementInCurrentPath === owner.stubItem -> currentSelectedPath.clone() + lastElementInCurrentPath === owner.getPopupMenu() -> currentSelectedPath.copyOf(currentSelectedPath.size + 1) + currentSelectedPath[currentSelectedPath.size - 2] === owner.getPopupMenu() && + !owner.getMenuComponents().contains(lastElementInCurrentPath!!.component) -> currentSelectedPath.clone() + else -> return + } + + val menuComponents = owner.getMenuComponents() + for (component in menuComponents) { + if (component != owner.stubItem && component.isEnabled && component is JMenuItem) { + newSelectionPath[newSelectionPath.size - 1] = component + menuSelectionManager.setSelectedPath(newSelectionPath) + return + } + } + } + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/FloatingToolbar.kt b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/FloatingToolbar.kt index 1b0a70b12212..e3232aa19ded 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/FloatingToolbar.kt +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/FloatingToolbar.kt @@ -16,7 +16,6 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.VisualPosition import com.intellij.openapi.editor.event.* import com.intellij.openapi.util.Disposer -import com.intellij.openapi.util.registry.Registry import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement import com.intellij.psi.util.PsiEditorUtil @@ -31,6 +30,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.debounce import org.jetbrains.annotations.ApiStatus +import java.awt.AWTEvent import java.awt.Point import java.awt.event.KeyAdapter import java.awt.event.KeyEvent @@ -50,10 +50,9 @@ open class FloatingToolbar( private val coroutineScope: CoroutineScope, protected val defaultActionGroupId: String ): Disposable { - private var hint: LightweightHint? = null + protected var hint: LightweightHint? = null private var buttonSize: Int by Delegates.notNull() private var lastSelection: String? = null - private var showToolbar = true private var hintWasShownForSelection = false private enum class HintRequest { @@ -88,17 +87,19 @@ open class FloatingToolbar( @RequiresEdt fun isShown(): Boolean { - return hint != null + return hint?.isVisible == true } @RequiresEdt private fun hide() { hint?.hide() + hint = null } @RequiresEdt private suspend fun showIfHidden() { - if (hint != null || !shouldReviveAfterClose() && !showToolbar) { + hintWasShownForSelection = true + if (isShown() || !isEnabled()) { return } val canBeShownAtCurrentSelection = readAction { canBeShownAtCurrentSelection() } @@ -106,12 +107,20 @@ open class FloatingToolbar( return } val hint = createHint() + showHint(hint) hint.addHintListener { this.hint = null - showToolbar = false } this.hint = hint - showHint(hint) + } + + fun show(callback: Runnable){ + coroutineScope.launch { + withContext(Dispatchers.EDT) { + showIfHidden() + callback.run() + } + } } private suspend fun createHint(): LightweightHint { @@ -126,7 +135,7 @@ open class FloatingToolbar( } fun scheduleShow() { - if (isEnabled()) { + if (isEnabled() && !hintWasShownForSelection) { check(hintRequests.tryEmit(HintRequest.Show)) } } @@ -143,7 +152,6 @@ open class FloatingToolbar( override fun dispose() { coroutineScope.cancel() hide() - hint = null } protected open fun createActionGroup(): ActionGroup? { @@ -210,9 +218,6 @@ open class FloatingToolbar( return false } - - protected open fun shouldReviveAfterClose(): Boolean = true - protected open fun shouldSurviveDocumentChange(): Boolean = true protected open fun isEnabled(): Boolean { @@ -242,7 +247,6 @@ open class FloatingToolbar( private inner class MouseListener : EditorMouseListener { override fun mouseReleased(event: EditorMouseEvent) { - hintWasShownForSelection = false updateOnProbablyChangedSelection { if (isShown()) { updateLocationIfShown() @@ -259,7 +263,6 @@ open class FloatingToolbar( if (event.source != editor.contentComponent) { return } - hintWasShownForSelection = false updateOnProbablyChangedSelection { scheduleHide() } @@ -270,13 +273,10 @@ open class FloatingToolbar( override fun mouseMoved(event: EditorMouseEvent) { val visualPosition = event.visualPosition val hoverSelected = editor.caretModel.allCarets.any { visualPosition.isInsideSelection(it) } - if (hoverSelected && (hintWasShownForSelection || hint?.isVisible == true)) { - hintWasShownForSelection = true + if (hoverSelected) { scheduleShow() - } else { - if (!Registry.get("floating.codeToolbar.revive.selectionChangeOnly").asBoolean()) { - showToolbar = true - } + } else if (!isShown()){ + hintWasShownForSelection = false } } @@ -289,10 +289,14 @@ open class FloatingToolbar( private inner class EditorSelectionListener : SelectionListener { override fun selectionChanged(event: SelectionEvent) { - val event = IdeEventQueue.getInstance().trueCurrentEvent - val isDoubleClick = (event as? MouseEvent)?.clickCount == 2 - showToolbar = !(disableForDoubleClickSelection() && isDoubleClick) hintWasShownForSelection = false + if (isIgnoredEvent(IdeEventQueue.getInstance().trueCurrentEvent)) { + hintWasShownForSelection = true + } + } + + private fun isIgnoredEvent(event: AWTEvent): Boolean { + return disableForDoubleClickSelection() && (event as? MouseEvent)?.clickCount == 2 } } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index 89fa483ca70a..e757c81a0702 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -35,6 +35,7 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.platform.diagnostic.telemetry.IJTracer; +import com.intellij.platform.diagnostic.telemetry.PlatformScopesKt; import com.intellij.platform.diagnostic.telemetry.TelemetryManager; import com.intellij.platform.diagnostic.telemetry.helpers.TraceUtil; import com.intellij.psi.util.ReadActionCache; @@ -47,6 +48,8 @@ import com.intellij.util.concurrency.Propagation; import com.intellij.util.containers.Stack; import com.intellij.util.messages.Topic; import com.intellij.util.ui.EDT; +import io.opentelemetry.api.metrics.BatchCallback; +import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Scope; import kotlin.coroutines.EmptyCoroutineContext; @@ -62,6 +65,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import static com.intellij.ide.ShutdownKt.cancelAndJoinBlocking; @@ -118,6 +122,8 @@ public class ApplicationImpl extends ClientAwareComponentManager implements Appl private static final String WAS_EVER_SHOWN = "was.ever.shown"; + private final OTelReadWriteActionsMonitor otelMonitor = new OTelReadWriteActionsMonitor(TelemetryManager.getMeter(PlatformScopesKt.EDT)); + @TestOnly public ApplicationImpl(boolean isHeadless, @NotNull RwLockHolder lockHolder) { super(null, @@ -385,6 +391,8 @@ public class ApplicationImpl extends ClientAwareComponentManager implements Appl else { Disposer.dispose(myLastDisposable); } + + otelMonitor.close(); } @Override @@ -899,6 +907,7 @@ public class ApplicationImpl extends ClientAwareComponentManager implements Appl if (status != null) { myLock.endRead(status); } + otelMonitor.readActionExecuted(); } } @@ -913,6 +922,7 @@ public class ApplicationImpl extends ClientAwareComponentManager implements Appl if (status != null) { myLock.endRead(status); } + otelMonitor.readActionExecuted(); } } @@ -927,6 +937,7 @@ public class ApplicationImpl extends ClientAwareComponentManager implements Appl if (status != null) { myLock.endRead(status); } + otelMonitor.readActionExecuted(); } } @@ -1137,6 +1148,7 @@ public class ApplicationImpl extends ClientAwareComponentManager implements Appl if (status != null) { myLock.endRead(status); } + otelMonitor.readActionExecuted(); } return true; } @@ -1233,6 +1245,7 @@ public class ApplicationImpl extends ClientAwareComponentManager implements Appl if (myWriteActionsStack.isEmpty()) { fireAfterWriteActionFinished(clazz); } + otelMonitor.writeActionExecuted(); } } @@ -1309,6 +1322,7 @@ public class ApplicationImpl extends ClientAwareComponentManager implements Appl public void finish() { myReadActionCacheImpl.clear(); myLock.endRead(myReader); + otelMonitor.readActionExecuted(); } } @@ -1499,4 +1513,44 @@ public class ApplicationImpl extends ClientAwareComponentManager implements Appl myLock.setAllowImplicitRead(oldVal); } } + + /** Count read & write actions executed, and report to OpenTelemetry Metrics */ + private static class OTelReadWriteActionsMonitor implements AutoCloseable{ + private final @NotNull BatchCallback batchCallback; + + private final AtomicInteger readActionsExecuted = new AtomicInteger(); + + private final AtomicInteger writeActionsExecuted = new AtomicInteger(); + + private OTelReadWriteActionsMonitor(@NotNull Meter meter) { + var raExecutionsCounter = meter.counterBuilder("ReadAction.executionsCount") + .setDescription("Total read actions executed") + .buildObserver(); + var waExecutionsCounter = meter.counterBuilder("WriteAction.executionsCount") + .setDescription("Total write actions executed") + .buildObserver(); + + this.batchCallback = meter.batchCallback( + () -> { + raExecutionsCounter.record(readActionsExecuted.get()); + waExecutionsCounter.record(writeActionsExecuted.get()); + }, + raExecutionsCounter, + waExecutionsCounter + ); + } + + public void readActionExecuted(){ + readActionsExecuted.incrementAndGet(); + } + + public void writeActionExecuted(){ + writeActionsExecuted.incrementAndGet(); + } + + @Override + public void close() { + batchCallback.close(); + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeDetectionService.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeDetectionService.java index 94c57cb2721f..1cd7488a4662 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeDetectionService.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeDetectionService.java @@ -367,11 +367,16 @@ final class FileTypeDetectionService implements Disposable { int flags = BitUtil.set(0, AUTO_DETECTED_AS_TEXT_MASK, wasAutodetectedAsText); flags = BitUtil.set(flags, AUTO_DETECTED_AS_BINARY_MASK, wasAutodetectedAsBinary); if (file instanceof VirtualFileWithId) { - writeFlagsToCache(file, flags); int id = ((VirtualFileWithId)file).getId(); - flags = BitUtil.set(flags, AUTO_DETECT_WAS_RUN_MASK, true); - flags = BitUtil.set(flags, ATTRIBUTES_WERE_LOADED_MASK, true); - packedFlags.set(id, flags); + long oldFlags = packedFlags.set(id, flags); + boolean isSavedStateUpToDate = BitUtil.isSet(oldFlags, AUTO_DETECTED_AS_TEXT_MASK) == wasAutodetectedAsText && + BitUtil.isSet(oldFlags, AUTO_DETECTED_AS_BINARY_MASK) == wasAutodetectedAsBinary && + BitUtil.isSet(oldFlags, AUTO_DETECT_WAS_RUN_MASK); + if (!isSavedStateUpToDate) { + flags = BitUtil.set(flags, AUTO_DETECT_WAS_RUN_MASK, true); + flags = BitUtil.set(flags, ATTRIBUTES_WERE_LOADED_MASK, true); + writeFlagsToCache(file, flags); + } if (wasAutodetectedAsText || wasAutodetectedAsBinary) { file.putUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY, null); diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.kt b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.kt index 41194a15dbe8..b962c5aebcba 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.kt +++ b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.kt @@ -27,6 +27,7 @@ import com.intellij.openapi.wm.impl.LinuxIdeMenuBar.Companion.doBindAppMenuOfPar import com.intellij.openapi.wm.impl.customFrameDecorations.header.CustomFrameDialogContent import com.intellij.openapi.wm.impl.customFrameDecorations.header.CustomHeader import com.intellij.ui.* +import com.intellij.ui.mac.screenmenu.Menu import com.intellij.ui.mac.touchbar.TouchbarSupport import com.intellij.util.childScope import com.intellij.util.ui.ImageUtil @@ -299,10 +300,9 @@ open class FrameWrapper @JvmOverloads constructor(private var project: Project?, init { FrameState.setFrameStateListener(this) glassPane = IdeGlassPaneImpl(rootPane = getRootPane(), installPainters = true) - if (SystemInfoRt.isMac && !(SystemInfo.isMacSystemMenu && java.lang.Boolean.getBoolean("mac.system.menu.singleton"))) { + if (SystemInfoRt.isMac && !Menu.isJbScreenMenuEnabled()) { @Suppress("DEPRECATION") jMenuBar = createMenuBar(coroutineScope = ApplicationManager.getApplication().coroutineScope.childScope(), this) - } MouseGestureManager.getInstance().add(this) focusTraversalPolicy = IdeFocusTraversalPolicy() diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index d6e015ab5c14..d1e031b84d08 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -392,7 +392,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { AnCancelAction anCancelAction = new AnCancelAction(); JRootPane rootPane = getRootPane(); - UIUtil.decorateWindowHeader(rootPane); + ComponentUtil.decorateWindowHeader(rootPane); Window window = getWindow(); if (window instanceof JDialog && !((JDialog)window).isUndecorated() && rootPane != null && LoadingState.COMPONENTS_LOADED.isOccurred()) { @@ -663,7 +663,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer { @Override public void addNotify() { if (IdeFrameDecorator.isCustomDecorationActive()) { - CustomHeader.enableCustomHeader(this); + CustomHeader.Companion.enableCustomHeader(this); } super.addNotify(); if (SystemInfo.isMacOSVentura && Registry.is("ide.mac.stage.manager.support", false)) { diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java index 7868019834e0..d01be72ab531 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java @@ -24,6 +24,7 @@ import com.intellij.openapi.wm.impl.IdeFrameImpl; import com.intellij.openapi.wm.impl.IdeGlassPaneEx; import com.intellij.ui.ComponentUtil; import com.intellij.ui.ScreenUtil; +import com.intellij.ui.ShadowJava2DPainter; import com.intellij.ui.components.JBLayeredPane; import com.intellij.ui.jcef.HwFacadeJPanel; import com.intellij.util.MathUtil; @@ -348,8 +349,15 @@ public final class GlassPaneDialogWrapperPeer extends DialogWrapperPeer { private MyDialog(IdeGlassPaneEx pane, DialogWrapper wrapper) { setLayout(new BorderLayout()); setOpaque(false); - setBorder(BorderFactory.createEmptyBorder(AllIcons.Ide.Shadow.Top.getIconHeight(), AllIcons.Ide.Shadow.Left.getIconWidth(), - AllIcons.Ide.Shadow.Bottom.getIconHeight(), AllIcons.Ide.Shadow.Right.getIconWidth())); + + if (ShadowJava2DPainter.Companion.enabled()) { + Insets insets = ShadowJava2DPainter.Companion.getInsets("Ide"); + setBorder(BorderFactory.createEmptyBorder(insets.top, insets.left, insets.bottom, insets.right)); + } + else { + setBorder(BorderFactory.createEmptyBorder(AllIcons.Ide.Shadow.Top.getIconHeight(), AllIcons.Ide.Shadow.Left.getIconWidth(), + AllIcons.Ide.Shadow.Bottom.getIconHeight(), AllIcons.Ide.Shadow.Right.getIconWidth())); + } myPane = pane; myDialogWrapper = new WeakReference<>(wrapper); diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerService.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerService.java index 11491384dfe3..60376fe9c791 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerService.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerService.java @@ -6,6 +6,7 @@ import com.intellij.ide.AppLifecycleListener; import com.intellij.ide.BrowserUtil; import com.intellij.ide.IdeBundle; import com.intellij.ide.actions.WhatsNewAction; +import com.intellij.ide.actions.WhatsNewUtil; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.InstalledPluginsState; import com.intellij.ide.plugins.PluginManagerConfigurable; @@ -187,7 +188,7 @@ final class UpdateCheckerService { private static void showWhatsNew(Project project, BuildNumber current) { String url = ApplicationInfoEx.getInstanceEx().getWhatsNewUrl(); - if (url != null && WhatsNewAction.isAvailable() && shouldShowWhatsNew(current, ApplicationInfoEx.getInstanceEx().isMajorEAP())) { + if (url != null && WhatsNewUtil.isWhatsNewAvailable() && shouldShowWhatsNew(current, ApplicationInfoEx.getInstanceEx().isMajorEAP())) { if (UpdateSettings.getInstance().isShowWhatsNewEditor()) { ApplicationManager.getApplication().invokeLater(() -> WhatsNewAction.openWhatsNewPage(project, url)); IdeUpdateUsageTriggerCollector.majorUpdateHappened(true); diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.kt b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.kt index 7689ea42b5b2..abdec8ec88c0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.kt +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.kt @@ -4,7 +4,7 @@ package com.intellij.openapi.updateSettings.impl import com.intellij.icons.AllIcons import com.intellij.ide.DataManager import com.intellij.ide.IdeBundle -import com.intellij.ide.actions.WhatsNewAction +import com.intellij.ide.actions.WhatsNewUtil import com.intellij.ide.nls.NlsMessages import com.intellij.ide.plugins.newui.reloadPluginIcon import com.intellij.openapi.actionSystem.CommonDataKeys @@ -92,7 +92,7 @@ class UpdateSettingsConfigurable @JvmOverloads constructor (private val checkNow }.topGap(TopGap.SMALL) .bottomGap(BottomGap.SMALL) - if (WhatsNewAction.isAvailable()) { + if (WhatsNewUtil.isWhatsNewAvailable()) { row { checkBox(IdeBundle.message("updates.settings.show.editor")) .bindSelected(settings.state::isShowWhatsNewEditor) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/CheckVFSHealthAction.kt b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/CheckVFSHealthAction.kt index 8abb998237f6..8bc20bfe85c6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/CheckVFSHealthAction.kt +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/CheckVFSHealthAction.kt @@ -22,7 +22,7 @@ import org.jetbrains.annotations.ApiStatus class CheckVFSHealthService(val coroutineScope: CoroutineScope) -internal class CheckVFSHealthAction : AnAction() { +internal class CheckVFSHealthAction : AnAction(ActionsBundle.message("action.CheckVfsSanity.text")) { override fun actionPerformed(e: AnActionEvent) { service().coroutineScope.launch(Dispatchers.IO) { @@ -31,7 +31,7 @@ internal class CheckVFSHealthAction : AnAction() { ActionsBundle.message("action.CheckVfsSanity.progress"), TaskCancellation.nonCancellable()) { val checker = VFSHealthChecker(FSRecords.implOrFail(), FSRecords.LOG) - checker.checkHealth() + checker.checkHealth(checkForOrphanRecords = true) } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java index 903bc6921f5a..121a9946a406 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java @@ -395,6 +395,7 @@ public final class FSRecords { return implOrFail().readAttributeRawWithLock(fileId, attribute, reader); } + @ApiStatus.Internal public static void writeAttributeRaw(int fileId, FileAttribute attribute, ByteBufferWriter writer) { @@ -445,7 +446,7 @@ public final class FSRecords { //========== aux: ======================================================== - /** With method create 'VFS corruption marker', which forces VFS to rebuild on the next startup */ + /** Method creates 'VFS corruption marker', which forces VFS to rebuild on the next startup */ public static void invalidateCaches(@NotNull String diagnosticMessage, @NotNull Throwable errorCause) { implOrFail().invalidateCaches(diagnosticMessage, errorCause); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecordsImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecordsImpl.java index 862e63e68318..c4a0fef43611 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecordsImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecordsImpl.java @@ -93,6 +93,9 @@ public final class FSRecordsImpl { */ public static final ErrorHandler ON_ERROR_MARK_CORRUPTED_AND_SCHEDULE_REBUILD = (records, error) -> { records.connection.markAsCorruptedAndScheduleRebuild(error); + if (error instanceof IOException) { + throw new UncheckedIOException((IOException)error); + } ExceptionUtil.rethrow(error); }; diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSConnection.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSConnection.java index 2a6d87327a7f..c1c56f4405f8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSConnection.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSConnection.java @@ -4,7 +4,6 @@ package com.intellij.openapi.vfs.newvfs.persistent; import com.intellij.core.CoreBundle; import com.intellij.notification.NotificationGroup; import com.intellij.notification.NotificationGroupManager; -import com.intellij.notification.NotificationType; import com.intellij.openapi.Forceable; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; @@ -97,7 +96,7 @@ public final class PersistentFSConnection { private volatile boolean myDirty; - private final Closeable flushingTask; + private final @Nullable Closeable flushingTask; /** accessed under {@link #r}/{@link #w} */ private final AtomicInteger corruptionsDetected = new AtomicInteger(); @@ -230,19 +229,16 @@ public final class PersistentFSConnection { } void doForce() throws IOException { - // avoid NPE when close has already taken place - if (myNames != null && flushingTask != null) { - if (myNames instanceof Forceable) { - ((Forceable)myNames).force(); - } - myAttributesStorage.force(); - myContents.force(); - if (myContentHashesEnumerator != null) { - myContentHashesEnumerator.force(); - } - writeConnectionState(); - myRecords.force(); + if (myNames instanceof Forceable) { + ((Forceable)myNames).force(); } + myAttributesStorage.force(); + myContents.force(); + if (myContentHashesEnumerator != null) { + myContentHashesEnumerator.force(); + } + writeConnectionState(); + myRecords.force(); } public boolean isDirty() { @@ -260,6 +256,7 @@ public final class PersistentFSConnection { } writeConnectionState(); + myRecords.force(); closeStorages(myRecords, myNames, myAttributesStorage, @@ -272,8 +269,11 @@ public final class PersistentFSConnection { return myPersistentFSPaths; } - //TODO RC: we use it to mark file record modified there something derived is modified -- i.e. children attribute - // or content. This looks suspicious to me: why we need to update _file_ record version in those cases? + /** + * Method used to mark file record modified if something _derived_ is modified -- i.e. children attribute + * or content. If file record _fields_ are mutated directly -- record marked as modified automatically, no + * need to call this method. + */ public void markRecordAsModified(int fileId) throws IOException { getRecords().markRecordAsModified(fileId); markDirty(); @@ -358,10 +358,10 @@ public final class PersistentFSConnection { if (errorCause == null) { //Without 'errorCause' it is not an error, but, likely, an explicit 'invalidateCache' call: // no need to print stacktrace then, also no need for a WARN - LOG.info("VFS is corrupted; Creating VFS corruption marker: " + message); + LOG.info("VFS rebuild is requested: creating VFS rebuild marker. Message: " + message); } else { - LOG.warn("VFS is corrupted; Creating VFS corruption marker", corruptedException); + LOG.warn("VFS is corrupted: creating VFS rebuild marker.", corruptedException); } try { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java index 89320c265730..2204c0eafab8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java @@ -28,7 +28,6 @@ import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl; import com.intellij.openapi.vfs.newvfs.*; import com.intellij.openapi.vfs.newvfs.events.*; import com.intellij.openapi.vfs.newvfs.impl.*; -import com.intellij.openapi.vfs.newvfs.monitoring.VfsUsageCollector; import com.intellij.openapi.vfs.newvfs.persistent.log.VfsLog; import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; import com.intellij.util.*; @@ -246,16 +245,20 @@ public final class PersistentFSImpl extends PersistentFS implements Disposable { } // return actual children - private static @NotNull List persistAllChildren(VirtualFile dir, int id) { + private static @NotNull List persistAllChildren(VirtualFile dir, int dirId) { NewVirtualFileSystem fs = getFileSystem(dir); + //FIXME RC: this method is not thread-safe: it creates new file records from children names outside + // of lock, hence it is possible >1 child to be created for the same name, and only + // last children list remains written, while children created during invocations that + // lost the race are remains orphan try { String[] fsNames = VfsUtil.filterNames( fs instanceof LocalFileSystemImpl ? ((LocalFileSystemImpl)fs).listWithCaching(dir) : fs.list(dir) ); Map justCreated = new HashMap<>(); - ListResult saved = FSRecords.update(dir, id, current -> { + ListResult saved = FSRecords.update(dir, dirId, current -> { List currentChildren = current.children; if (fsNames.length == 0 && !currentChildren.isEmpty()) { return current; @@ -277,7 +280,7 @@ public final class PersistentFSImpl extends PersistentFS implements Disposable { FileAttributes attrs = entry.getValue(); String target = attrs.isSymLink() ? fs.resolveSymLink(new FakeVirtualFile(dir, newName)) : null; Pair<@NotNull FileAttributes, String> childData = getChildData(fs, dir, newName, attrs, target); - ChildInfo newChild = justCreated.computeIfAbsent(newName, name -> makeChildRecord(dir, id, name, childData, fs, null)); + ChildInfo newChild = justCreated.computeIfAbsent(newName, name -> makeChildRecord(dir, dirId, name, childData, fs, null)); toAddChildren.add(newChild); } } @@ -285,7 +288,7 @@ public final class PersistentFSImpl extends PersistentFS implements Disposable { for (String newName : toAddNames) { Pair<@NotNull FileAttributes, String> childData = getChildData(fs, dir, newName, null, null); if (childData != null) { - ChildInfo newChild = justCreated.computeIfAbsent(newName, name -> makeChildRecord(dir, id, name, childData, fs, null)); + ChildInfo newChild = justCreated.computeIfAbsent(newName, name -> makeChildRecord(dir, dirId, name, childData, fs, null)); toAddChildren.add(newChild); } } @@ -296,7 +299,7 @@ public final class PersistentFSImpl extends PersistentFS implements Disposable { return current.merge(toAddChildren, caseSensitive); }); - setChildrenCached(id); + setChildrenCached(dirId); return saved.children; } @@ -391,6 +394,8 @@ public final class PersistentFSImpl extends PersistentFS implements Disposable { boolean overwriteMissed) { assert id > 0 : id; assert parentId >= 0 : parentId; // 0 means there's no parent + //RC: why we reject the changes in those 2 cases -- what is special with loaded children or + // same-name? if (!name.isEmpty()) { if (Comparing.equal(name, FSRecords.getNameSequence(id), cs)) return -1; // TODO: Handle root attributes change. } @@ -1967,8 +1972,10 @@ public final class PersistentFSImpl extends PersistentFS implements Disposable { int childId = FSRecords.createRecord(); int nameId = writeAttributesToRecord(childId, parentId, name, parentFile.isCaseSensitive(), attributes, true); + if(nameId < 0){ + throw new AssertionError("writeAttributesToRecord(" + childId + ", " + parentId + ", '" + name + "',...) returns -1"); + } - assert childId > 0 : childId; if (attributes.isDirectory()) { FSRecords.loadDirectoryData(childId, parentFile, name, fs); } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsLockFreeOverMMappedFile.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsLockFreeOverMMappedFile.java index 7a92b962cb2a..077c9d7153ee 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsLockFreeOverMMappedFile.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSRecordsLockFreeOverMMappedFile.java @@ -164,6 +164,7 @@ public class PersistentFSRecordsLockFreeOverMMappedFile implements PersistentFSR try (final Page page = storage.pageByOffset(0)) { if (updater.updateHeader(headerAccessor)) { globalModCount.incrementAndGet(); + dirty.compareAndSet(true, false); } } } @@ -195,7 +196,6 @@ public class PersistentFSRecordsLockFreeOverMMappedFile implements PersistentFSR return getIntField(ATTR_REF_OFFSET); } - @Override public int getParent() { return getIntField(PARENT_REF_OFFSET); @@ -619,7 +619,8 @@ public class PersistentFSRecordsLockFreeOverMMappedFile implements PersistentFSR if (dirty.compareAndSet(true, false)) { setIntHeaderField(HEADER_RECORDS_ALLOCATED, allocatedRecordsCount.get()); setIntHeaderField(HEADER_GLOBAL_MOD_COUNT_OFFSET, globalModCount.get()); - //TODO RC: should we do fsync() here, or we could trust OS will flush mmapped pages to disk? + //MAYBE RC: should we do fsync() here, or we could trust OS will flush mmapped pages to disk? + storage.fsync(); } } @@ -940,6 +941,12 @@ public class PersistentFSRecordsLockFreeOverMMappedFile implements PersistentFSR } } + public void fsync() throws IOException { + if (channel.isOpen()) { + channel.force(true); + } + } + public static class Page implements AutoCloseable { private final int pageIndex; private final long offsetInFile; @@ -977,6 +984,7 @@ public class PersistentFSRecordsLockFreeOverMMappedFile implements PersistentFSR } /** Opens records.dat file given as args[0], prints header fields, and first records (up to 1024) */ + @SuppressWarnings("UseOfSystemOutOrSystemErr") public static void main(String[] args) throws IOException { if (args.length < 1) { System.err.println("Args: "); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/VFSHealthChecker.kt b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/VFSHealthChecker.kt index 72bcb2e68aa4..a573fa94225d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/VFSHealthChecker.kt +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/VFSHealthChecker.kt @@ -39,7 +39,7 @@ import kotlin.time.toDuration object VFSHealthCheckerConstants { @JvmStatic val HEALTH_CHECKING_ENABLED = getBooleanProperty("vfs.health-check.enabled", - ApplicationManager.getApplication().isEAP) + ApplicationManager.getApplication().isEAP && !ApplicationManager.getApplication().isUnitTestMode) @JvmStatic val HEALTH_CHECKING_PERIOD_MS = getIntProperty("vfs.health-check.checking-period-ms", @@ -53,7 +53,10 @@ object VFSHealthCheckerConstants { 10.minutes.inWholeMilliseconds.toInt()) - /** May take quite a time, hence disabled by default */ + /** + * May slow down scanning significantly, hence dedicated property to control. + * Default: false, since orphan records appear to be quite common so far. + */ @JvmStatic val CHECK_ORPHAN_RECORDS = getBooleanProperty("vfs.health-check.check-orphan-records", false) @@ -112,7 +115,7 @@ class VFSHealthCheckServiceStarter : ApplicationInitializedListener { } val checker = VFSHealthChecker(fsRecordsImpl, LOG) val checkHealthReport = try { - checker.checkHealth() + checker.checkHealth(CHECK_ORPHAN_RECORDS) } catch (e: AlreadyDisposedException) { return @@ -159,10 +162,12 @@ class VFSHealthCheckServiceStarter : ApplicationInitializedListener { class VFSHealthChecker(private val impl: FSRecordsImpl, private val log: Logger = LOG) { - fun checkHealth(): VFSHealthCheckReport { + constructor() : this(FSRecords.implOrFail(), FSRecords.LOG) + + fun checkHealth(checkForOrphanRecords: Boolean = CHECK_ORPHAN_RECORDS): VFSHealthCheckReport { log.info("Checking VFS started") val startedAtNs = System.nanoTime() - val fileRecordsReport = verifyFileRecords() + val fileRecordsReport = verifyFileRecords(checkForOrphanRecords) val rootsReport = verifyRoots() val namesEnumeratorReport = verifyNamesEnumerator() val contentEnumeratorReport = verifyContentEnumerator() @@ -178,7 +183,7 @@ class VFSHealthChecker(private val impl: FSRecordsImpl, return vfsHealthCheckReport } - private fun verifyFileRecords(): VFSHealthCheckReport.FileRecordsReport { + private fun verifyFileRecords(checkForOrphanRecords: Boolean): VFSHealthCheckReport.FileRecordsReport { val connection = impl.connection() val fileRecords = connection.records val namesEnumerator = connection.names @@ -246,21 +251,39 @@ class VFSHealthChecker(private val impl: FSRecordsImpl, } } //else: it is ok, contentId _could_ be NULL_ID - if (parentId == DataEnumeratorEx.NULL_ID) { + if (parentId == FSRecords.NULL_FILE_ID) { if (!allRoots.contains(fileId)) { nullParents++ log.info("file[#$fileId]{$fileName}: not in ROOTS, but parentId is not set (NULL_ID) -> non-ROOTS must have parents") } } else { - if (CHECK_ORPHAN_RECORDS) { - if (BitUtil.isSet(flags, CHILDREN_CACHED)) { - val childrenOfParent = impl.listIds(parentId) - if (childrenOfParent.indexOf(fileId) < 0) { - inconsistentParentChildRelationships++ //MAYBE RC: dedicated counter? - log.info("file[#$fileId]{$fileName}: record is orphan, .parent.children(first 64: ${ - childrenOfParent.take(64) - }...) doesn't contain it!") + val parentFlags = fileRecords.getFlags(parentId) + val parentIsDirectory = BitUtil.isSet(parentFlags, IS_DIRECTORY) + if (!parentIsDirectory) { + inconsistentParentChildRelationships++ + log.info("file[#$fileId]{$fileName}: parent[#$parentId] is !directory (flags: ${Integer.toBinaryString(parentFlags)}") + } + + if (checkForOrphanRecords) { + if (BitUtil.isSet(parentFlags, CHILDREN_CACHED)) { + try { + //MAYBE RC: use .listIdsUnchecked() method -- to not trigger VFS rebuild? + val childrenOfParent = impl.listIds(parentId) + if (childrenOfParent.indexOf(fileId) < 0) { + inconsistentParentChildRelationships++ //MAYBE RC: dedicated counter? + val maxChildrenToLog = 32 + val childrenPrefix = if (childrenOfParent.size > maxChildrenToLog) + "first $maxChildrenToLog of ${childrenOfParent.size}: " + else + "" + log.info("file[#$fileId]{$fileName}: record is orphan, " + + ".parent[#$parentId].children($childrenPrefix${childrenOfParent.joinToString(limit = maxChildrenToLog)}) doesn't contain it!") + } + } + catch (e: Throwable) { + generalErrors++ + log.info("file[#$fileId]{$fileName}.parent[#$parentId]: error accessing children", e) } } } @@ -268,7 +291,14 @@ class VFSHealthChecker(private val impl: FSRecordsImpl, val isDirectory = BitUtil.isSet(flags, IS_DIRECTORY) - val children = impl.listIds(fileId) + val children = try { + impl.listIds(fileId) + } + catch (e: Throwable) { + generalErrors++ + log.info("file[#$fileId]{$fileName}: error accessing children", e) + IntArray(0) + } if (isDirectory) { for (i in children.indices) { childrenChecked++ @@ -276,6 +306,8 @@ class VFSHealthChecker(private val impl: FSRecordsImpl, //re-request maxAllocatedID before loop so racing changes will be accounted for: val maxAllocatedID = fileRecords.maxAllocatedID() if (childId < FSRecords.MIN_REGULAR_FILE_ID || childId > maxAllocatedID) { + //RC: actually this branch is now unreachable -- childId is checked inside .listIds(), and + // CorruptionException is thrown if childId is outside the range. generalErrors++ //MAYBE RC: dedicated counter? log.info("file[#$fileId]{$fileName}: children[$i][#$childId] " + "is outside of allocated IDs range [${FSRecords.MIN_REGULAR_FILE_ID}..$maxAllocatedID]") @@ -298,14 +330,14 @@ class VFSHealthChecker(private val impl: FSRecordsImpl, //TODO RC: try read _all_ attributes, check all them are readable //TODO RC: check attribute storage _has_ such a record (not deleted) //if(attributeRecordId!=AbstractAttributesStorage.NON_EXISTENT_ATTR_RECORD_ID) { - //connection.attributes.forEachAttribute(connection, fileId){ - //} + // connection.attributes.forEachAttribute(connection, fileId){ + // } //} } catch (t: Throwable) { generalErrors++ - log.info("file[#$fileId]: exception while checking", t) + log.info("file[#$fileId]: unhandled exception while checking", t) } } log.info("${fileRecords.recordsCount()} file records checked: ${childrenChecked} children, ${notNullContentIds} contents") @@ -420,6 +452,9 @@ class VFSHealthChecker(private val impl: FSRecordsImpl, val contentEnumeratorReport: ContentEnumeratorReport, val timeTaken: Duration) { + val healthy: Boolean + get() = recordsReport.healthy && rootsReport.healthy && namesEnumeratorReport.healthy && contentEnumeratorReport.healthy + data class FileRecordsReport(var fileRecordsChecked: Int = 0, var fileRecordsDeleted: Int = 0, /* record.nameId = NULL_ID */ @@ -436,7 +471,15 @@ class VFSHealthChecker(private val impl: FSRecordsImpl, /* record.children[].parent != record */ var inconsistentParentChildRelationships: Int = 0, /* exceptions */ - var generalErrors: Int = 0) + var generalErrors: Int = 0) { + val healthy: Boolean + get() = nullNameIds == 0 + && unresolvableNameIds == 0 + && unresolvableContentIds == 0 + && nullParents == 0 + && inconsistentParentChildRelationships == 0 + && generalErrors == 0 + } data class NamesEnumeratorReport(var namesChecked: Int = 0, /* .tryEnumerate(existentNameId) = NULL_ID */ @@ -446,7 +489,13 @@ class VFSHealthChecker(private val impl: FSRecordsImpl, /* existent name -> tryEnumerate() -> .valueOf() -> different name */ var inconsistentNames: Int = 0, /* tryEnumerate/valueOf/etc exceptions */ - var generalErrors: Int = 0) + var generalErrors: Int = 0) { + val healthy: Boolean + get() = namesResolvedToNull == 0 + && idsResolvedToNull == 0 + && inconsistentNames == 0 + && generalErrors == 0 + } data class RootsReport(var rootsCount: Int = 0, /* root.parentId != NULL_ID */ @@ -454,13 +503,21 @@ class VFSHealthChecker(private val impl: FSRecordsImpl, /* root.isDeleted but still present in roots catalog*/ var rootsDeletedButNotRemoved: Int = 0, /* exceptions */ - var generalErrors: Int = 0) + var generalErrors: Int = 0) { + val healthy: Boolean + get() = rootsWithParents == 0 + && rootsDeletedButNotRemoved == 0 + && generalErrors == 0 + } data class ContentEnumeratorReport( var contentRecordsChecked: Int = 0, /* tryEnumerate/valueOf/etc exceptions */ var generalErrors: Int = 0 - ) + ) { + val healthy: Boolean + get() = (generalErrors == 0) + } } } @@ -484,7 +541,7 @@ fun main(args: Array) { } val log = configureLogger() - val checkupReport = VFSHealthChecker(records, log).checkHealth() + val checkupReport = VFSHealthChecker(records, log).checkHealth(checkForOrphanRecords = true) println(checkupReport) exitProcess(0) //too many non-daemon threads diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java index 22bca3b81a09..b56f5b9744f8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java @@ -18,7 +18,6 @@ import com.intellij.ui.*; import com.intellij.ui.paint.LinePainter2D; import com.intellij.util.Alarm; import com.intellij.util.MathUtil; -import com.intellij.util.ui.UIUtil; import kotlin.Unit; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -116,7 +115,7 @@ public final class FloatingDecorator extends JDialog implements FloatingDecorato @Override public void show(){ - UIUtil.decorateWindowHeader(rootPane); + ComponentUtil.decorateWindowHeader(rootPane); ToolbarService.Companion.getInstance().setTransparentTitleBar(this, rootPane, runnable -> { Disposer.register(myDisposable, () -> runnable.run()); return Unit.INSTANCE; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java index a5981dc725d0..2c5b0c47ad4c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java @@ -29,7 +29,7 @@ import static com.intellij.openapi.ui.impl.DialogWrapperPeerImpl.isDisableAutoRe import static com.intellij.openapi.wm.impl.WindowManagerImplKt.IDE_FRAME_EVENT_LOG; public abstract class IdeFrameDecorator { - static final String FULL_SCREEN = "ide.frame.full.screen"; + public static final String FULL_SCREEN = "ide.frame.full.screen"; protected final IdeFrameImpl frame; @@ -152,8 +152,9 @@ public abstract class IdeFrameDecorator { if (toFocus != null && !(toFocus instanceof JRootPane)) { // Window 'forgets' last focused component on disposal, so we need to restore it explicitly. - // Special case is toggling fullscreen mode from menu. In this case menu UI moves focus to the root pane before performing - // the action. We shouldn't explicitly request focus in this case - menu UI will restore the focus without our help. + // Special case is toggling fullscreen mode from a menu. + // In this case menu UI moves focus to the root pane before performing the action. + // We shouldn't explicitly request focus in this case - menu UI will restore the focus without our help. toFocus.requestFocusInWindow(); } } @@ -234,7 +235,7 @@ public abstract class IdeFrameDecorator { public static boolean isCustomDecorationActive() { UISettings settings = UISettings.getInstanceOrNull(); if (settings == null) { - // true by default if no settings is available (e.g. during the initial IDE setup wizard) and not overridden (only for Windows) + // true by default if no settings are available (e.g., during the initial IDE setup wizard) and not overridden (only for Windows) return isCustomDecorationAvailable() && getDefaultCustomDecorationState(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.kt index ab646ba9b696..4d37b6df91c5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.kt @@ -2,7 +2,7 @@ package com.intellij.openapi.wm.impl import com.intellij.DynamicBundle -import com.intellij.diagnostic.runActivity +import com.intellij.ide.menu.* import com.intellij.ide.ui.UISettings import com.intellij.openapi.actionSystem.ActionGroup import com.intellij.openapi.diagnostic.Logger @@ -14,7 +14,6 @@ import com.intellij.ui.Gray import com.intellij.ui.ScreenUtil import com.intellij.ui.mac.foundation.NSDefaults import com.intellij.ui.mac.screenmenu.Menu -import com.intellij.ui.mac.screenmenu.MenuBar import com.intellij.ui.plaf.beg.IdeaMenuUI import com.intellij.util.ui.JBUI import com.intellij.util.ui.StartupUiUtil @@ -42,8 +41,6 @@ open class IdeMenuBar internal constructor(@JvmField internal val coroutineScope @JvmField internal val frame: JFrame) : JMenuBar(), ActionAwareIdeMenuBar { private val menuBarHelper: IdeMenuBarHelper - private val screenMenuPeer: MenuBar? - init { val flavor = if (isFloatingMenuBarSupported) { FloatingMenuBarFlavor(this) @@ -73,14 +70,7 @@ open class IdeMenuBar internal constructor(@JvmField internal val coroutineScope override suspend fun getMainMenuActionGroup(): ActionGroup? = this@IdeMenuBar.getMainMenuActionGroup() } - screenMenuPeer = runActivity("ide menu bar init") { createScreeMenuPeer(frame) } - if (screenMenuPeer == null) { - menuBarHelper = JMenuBasedIdeMenuBarHelper(flavor = flavor, menuBar = facade) - } - else { - menuBarHelper = PeerBasedIdeMenuBarHelper(screenMenuPeer = screenMenuPeer, flavor = flavor, menuBar = facade) - } - + menuBarHelper = JMenuBasedIdeMenuBarHelper(flavor = flavor, menuBar = facade) if (IdeFrameDecorator.isCustomDecorationActive()) { isOpaque = false } @@ -147,11 +137,6 @@ open class IdeMenuBar internal constructor(@JvmField internal val coroutineScope override fun removeNotify() { if (ScreenUtil.isStandardAddRemoveNotify(this)) { - screenMenuPeer?.let { - @Suppress("SSBasedInspection") - it.dispose() - } - menuBarHelper.flavor.suspendAnimator() } super.removeNotify() @@ -240,14 +225,6 @@ internal fun doUpdateAppMenu() { //} } -internal fun createScreeMenuPeer(frame: JFrame): MenuBar? { - return if (Menu.isJbScreenMenuEnabled()) MenuBar("MainMenu", frame) else null -} - -internal fun createMenuBar(coroutineScope: CoroutineScope, frame: JFrame): IdeMenuBar { - return if (SystemInfoRt.isLinux) LinuxIdeMenuBar(coroutineScope, frame) else IdeMenuBar(coroutineScope, frame) -} - internal fun installAppMenuIfNeeded(frame: JFrame) { if (!SystemInfoRt.isLinux) { return diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBarHelper.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBarHelper.kt deleted file mode 100644 index 02cb229e840c..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBarHelper.kt +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -@file:OptIn(FlowPreview::class) - -package com.intellij.openapi.wm.impl - -import com.intellij.diagnostic.StartUpMeasurer -import com.intellij.diagnostic.rootTask -import com.intellij.diagnostic.subtask -import com.intellij.ide.DataManager -import com.intellij.ide.ui.UISettings -import com.intellij.ide.ui.UISettingsListener -import com.intellij.ide.ui.customization.CustomActionsSchema -import com.intellij.openapi.actionSystem.* -import com.intellij.openapi.actionSystem.ex.ActionManagerEx -import com.intellij.openapi.actionSystem.ex.ActionUtil -import com.intellij.openapi.actionSystem.impl.* -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.application.EDT -import com.intellij.openapi.application.ModalityState -import com.intellij.openapi.application.asContextElement -import com.intellij.openapi.components.serviceAsync -import com.intellij.openapi.wm.WindowManager -import com.intellij.ui.mac.screenmenu.MenuBar -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.debounce -import java.awt.Component -import java.awt.Dialog -import java.awt.Dimension -import java.awt.KeyboardFocusManager -import javax.swing.JComponent -import javax.swing.JFrame -import javax.swing.MenuSelectionManager -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.seconds - -internal interface ActionAwareIdeMenuBar { - fun updateMenuActions(forceRebuild: Boolean = false) -} - -internal interface IdeMenuFlavor { - val state: IdeMenuBarState - get() = IdeMenuBarState.EXPANDED - - fun jMenuSelectionChanged(isIncluded: Boolean) { - } - - fun getPreferredSize(size: Dimension): Dimension = size - - fun updateAppMenu() - - fun layoutClockPanelAndButton() { - } - - fun correctMenuCount(menuCount: Int): Int = menuCount - - fun suspendAnimator() {} -} - -internal sealed class IdeMenuBarHelper(@JvmField val flavor: IdeMenuFlavor, - @JvmField internal val menuBar: MenuBarImpl) : ActionAwareIdeMenuBar { - protected abstract fun isUpdateForbidden(): Boolean - - @JvmField - protected var visibleActions = emptyList() - - @JvmField - protected val presentationFactory: PresentationFactory = MenuItemPresentationFactory() - - private val updateRequests = MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) - - interface MenuBarImpl { - val frame: JFrame - - val coroutineScope: CoroutineScope - val isDarkMenu: Boolean - val component: JComponent - - fun updateGlobalMenuRoots() - - suspend fun getMainMenuActionGroup(): ActionGroup? - } - - init { - val app = ApplicationManager.getApplication() - val coroutineScope = menuBar.coroutineScope - @Suppress("IfThenToSafeAccess") - if (app != null) { - app.messageBus.connect(coroutineScope).subscribe(UISettingsListener.TOPIC, UISettingsListener { - check(updateRequests.tryEmit(true)) - }) - } - - coroutineScope.launch(ModalityState.any().asContextElement()) { - withContext(if (StartUpMeasurer.isEnabled()) (rootTask() + CoroutineName("ide menu bar actions init")) else EmptyCoroutineContext) { - val mainActionGroup = menuBar.getMainMenuActionGroup() - val actions = updateMenuActions(mainActionGroup = mainActionGroup, forceRebuild = false, isFirstUpdate = true) - postInitActions(actions) - } - - val actionManager = serviceAsync() - if (actionManager is ActionManagerEx) { - coroutineScope.launch { - actionManager.timerEvents.collect { - updateOnTimer() - } - } - } - - updateRequests - .debounce(50.milliseconds) - .collect { forceRebuild -> - presentationFactory.reset() - updateMenuActions(mainActionGroup = menuBar.getMainMenuActionGroup(), forceRebuild = forceRebuild, isFirstUpdate = false) - } - } - } - - private suspend fun updateOnTimer() { - withContext(Dispatchers.EDT) { - if (!menuBar.frame.isShowing || !menuBar.frame.isActive) { - return@withContext - } - - // do not update when a popup menu is shown - // (if a popup menu contains action which is also in the menu bar, it should not be enabled/disabled) - if (isUpdateForbidden()) { - return@withContext - } - - // don't update the toolbar if there is currently active modal dialog - val window = KeyboardFocusManager.getCurrentKeyboardFocusManager().focusedWindow - if (window !is Dialog || !window.isModal) { - updateRequests.emit(false) - } - } - } - - final override fun updateMenuActions(forceRebuild: Boolean) { - check(updateRequests.tryEmit(forceRebuild)) - } - - protected open suspend fun postInitActions(actions: List) { - } - - abstract suspend fun updateMenuActions(mainActionGroup: ActionGroup?, forceRebuild: Boolean, isFirstUpdate: Boolean): List - - protected fun createActionMenuList(newVisibleActions: List, consumer: (ActionMenu) -> Unit) { - if (newVisibleActions.isEmpty()) { - return - } - - val enableMnemonics = !UISettings.getInstance().disableMnemonics - val isCustomDecorationActive = IdeFrameDecorator.isCustomDecorationActive() - for (action in newVisibleActions) { - val actionMenu = ActionMenu(null, ActionPlaces.MAIN_MENU, action, presentationFactory, enableMnemonics, menuBar.isDarkMenu, true) - if (isCustomDecorationActive) { - actionMenu.isOpaque = false - actionMenu.isFocusable = false - } - consumer(actionMenu) - } - } -} - -internal open class JMenuBasedIdeMenuBarHelper(flavor: IdeMenuFlavor, menuBar: MenuBarImpl) : IdeMenuBarHelper(flavor, menuBar) { - override fun isUpdateForbidden() = MenuSelectionManager.defaultManager().selectedPath.isNotEmpty() - - override suspend fun postInitActions(actions: List) { - withContext(Dispatchers.EDT) { - for (action in actions) { - PopupMenuPreloader.install(menuBar.component, ActionPlaces.MAIN_MENU, null) { action } - } - } - } - - override suspend fun updateMenuActions(mainActionGroup: ActionGroup?, forceRebuild: Boolean, isFirstUpdate: Boolean): List { - val menuBarComponent = menuBar.component - val newVisibleActions = mainActionGroup?.let { - expandMainActionGroup(mainActionGroup = it, - menuBar = menuBarComponent, - frame = menuBar.frame, - presentationFactory = presentationFactory, - isFirstUpdate = isFirstUpdate) - } ?: emptyList() - - if (!forceRebuild && newVisibleActions == visibleActions && !presentationFactory.isNeedRebuild) { - val enableMnemonics = !UISettings.getInstance().disableMnemonics - withContext(Dispatchers.EDT) { - for (child in menuBarComponent.components) { - if (child is ActionMenu) { - child.updateFromPresentation(enableMnemonics) - } - } - } - return newVisibleActions - } - - // should rebuild UI - val changeBarVisibility = newVisibleActions.isEmpty() || visibleActions.isEmpty() - withContext(Dispatchers.EDT) { - visibleActions = newVisibleActions - menuBarComponent.removeAll() - createActionMenuList(newVisibleActions) { - menuBarComponent.add(it) - } - presentationFactory.resetNeedRebuild() - flavor.updateAppMenu() - menuBar.updateGlobalMenuRoots() - menuBarComponent.validate() - if (changeBarVisibility) { - menuBarComponent.invalidate() - menuBar.frame.validate() - } - } - return newVisibleActions - } -} - -internal open class PeerBasedIdeMenuBarHelper(private val screenMenuPeer: MenuBar, - flavor: IdeMenuFlavor, - menuBar: MenuBarImpl) : IdeMenuBarHelper(flavor, menuBar) { - override fun isUpdateForbidden() = screenMenuPeer.isAnyChildOpened - - override suspend fun updateMenuActions(mainActionGroup: ActionGroup?, forceRebuild: Boolean, isFirstUpdate: Boolean): List { - val newVisibleActions = mainActionGroup?.let { - expandMainActionGroup(mainActionGroup = it, - menuBar = menuBar.component, - frame = menuBar.frame, - presentationFactory = presentationFactory, - isFirstUpdate = isFirstUpdate) - } ?: emptyList() - - if (!forceRebuild && newVisibleActions == visibleActions && !presentationFactory.isNeedRebuild) { - return newVisibleActions - } - - withContext(Dispatchers.EDT) { - visibleActions = newVisibleActions - screenMenuPeer.beginFill() - try { - createActionMenuList(newVisibleActions) { - screenMenuPeer.add(it.screenMenuPeer) - } - } - finally { - screenMenuPeer.endFill() - presentationFactory.resetNeedRebuild() - } - flavor.updateAppMenu() - } - return newVisibleActions - } -} - -@Suppress("unused") -private val firstUpdateFastTrackUpdateTimeout = 30.seconds.inWholeMilliseconds - -private suspend fun expandMainActionGroup(mainActionGroup: ActionGroup, - menuBar: Component, - frame: JFrame, - presentationFactory: PresentationFactory, - @Suppress("UNUSED_PARAMETER") isFirstUpdate: Boolean): List { - val actionManager = serviceAsync() - return subtask("expandMainActionGroup", Dispatchers.EDT) { - val children = mainActionGroup.getChildren(null, actionManager) - if (children.isEmpty()) { - return@subtask emptyList() - } - - val targetComponent = WindowManager.getInstance().getFocusedComponent(frame) ?: menuBar - val dataContext = Utils.wrapToAsyncDataContext(DataManager.getInstance().getDataContext(targetComponent)) - val list = mutableListOf() - for (action in children) { - if (action !is ActionGroup) { - continue - } - - val presentation = presentationFactory.getPresentation(action) - val e = AnActionEvent(null, dataContext, ActionPlaces.MAIN_MENU, presentation, actionManager, 0) - ActionUtil.performDumbAwareUpdate(action, e, false) - if (presentation.isVisible) { - list.add(action) - } - } - list - } - - // don't repeat for JetBrains Client - deadlock possible - //repeat(if (PlatformUtils.isJetBrainsClient()) 1 else 3) { - // presentationFactory.resetNeedRebuild() - // try { - // return withContext(CoroutineName("expandMainActionGroup") + Dispatchers.EDT) { - // val targetComponent = WindowManager.getInstance().getFocusedComponent(frame) ?: menuBar - // val dataContext = Utils.wrapToAsyncDataContext(DataManager.getInstance().getDataContext(targetComponent)) - // // disable fast track for JetBrains Client - deadlock otherwise - // val fastTrackTimeout = when { - // // disable fast track for JetBrains Client - deadlock otherwise - // PlatformUtils.isJetBrainsClient() -> -1 - // isFirstUpdate -> firstUpdateFastTrackUpdateTimeout - // else -> Utils.getFastTrackTimeout() - // } - // Utils.expandActionGroupAsync(/* group = */ mainActionGroup, - // /* presentationFactory = */ presentationFactory, - // /* context = */ dataContext, - // /* place = */ ActionPlaces.MAIN_MENU, - // /* isToolbarAction = */ false, - // /* fastTrackTimeout = */ fastTrackTimeout) - // }.await().filterIsInstance() - // } - // catch (e: ProcessCanceledException) { - // if (isFirstUpdate) { - // logger().warn("Cannot expand action group", e) - // return emptyList() - // } - // } - //} - //return emptyList() -} - -internal suspend fun getMainMenuActionGroup(frame: JFrame): ActionGroup? { - val group = (frame.rootPane as? IdeRootPane)?.mainMenuActionGroup - return group ?: CustomActionsSchema.getInstanceAsync().getCorrectedActionAsync(IdeActions.GROUP_MAIN_MENU) -} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.kt index 4e7b29004f55..5e0ae3872da8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.kt @@ -8,6 +8,8 @@ import com.intellij.diagnostic.rootTask import com.intellij.diagnostic.subtask import com.intellij.ide.GeneralSettings import com.intellij.ide.actions.ToggleDistractionFreeModeAction +import com.intellij.ide.menu.ActionAwareIdeMenuBar +import com.intellij.ide.menu.createMacMenuBar import com.intellij.ide.ui.UISettings import com.intellij.ide.ui.UISettingsListener import com.intellij.ide.ui.customization.CustomActionsSchema @@ -164,7 +166,7 @@ open class IdeRootPane internal constructor(private val frame: IdeFrameImpl, val isDecoratedMenu = isDecoratedMenu val isFloatingMenuBarSupported = isFloatingMenuBarSupported if (!isDecoratedMenu && !isFloatingMenuBarSupported) { - jMenuBar = createMenuBar(coroutineScope.childScope(), frame) + createMacAwareMenuBar(frame = frame, component = this, coroutineScope.childScope()) helper = UndecoratedHelper(isFloatingMenuBarSupported = false) } else { @@ -175,22 +177,12 @@ open class IdeRootPane internal constructor(private val frame: IdeFrameImpl, val ideMenu: ActionAwareIdeMenuBar val customFrameTitlePane = if (ExperimentalUI.isNewUI()) { selectedEditorFilePath = null + ideMenu = createMacAwareMenuBar(frame = frame, component = this, coroutineScope.childScope()) if (SystemInfoRt.isMac) { - ideMenu = if (isFloatingMenuBarSupported || !Menu.isJbScreenMenuEnabled()) { - val menuBar = IdeMenuBar(coroutineScope.childScope(), frame) - // if -DjbScreenMenuBar.enabled=false - frame.jMenuBar = menuBar - menuBar - } - else { - createMacMenuBar(coroutineScope = coroutineScope.childScope(), component = this, frame = frame) - } - MacToolbarFrameHeader(coroutineScope = coroutineScope.childScope(), frame = frame, root = this) } else { - ideMenu = createMenuBar(coroutineScope.childScope(), frame) - ToolbarFrameHeader(coroutineScope = coroutineScope.childScope(), frame = frame, root = this, ideMenuBar = ideMenu) + ToolbarFrameHeader(coroutineScope = coroutineScope.childScope(), frame = frame, root = this, ideMenuBar = ideMenu as IdeMenuBar) } } else { @@ -735,12 +727,11 @@ private val isDecoratedMenu: Boolean private suspend fun createToolbar(coroutineScope: CoroutineScope, frame: JFrame): JComponent { if (ExperimentalUI.isNewUI()) { val toolbar = withContext(Dispatchers.EDT) { - MainToolbar(coroutineScope, frame) + val toolbar = MainToolbar(coroutineScope = coroutineScope, frame = frame, isOpaque = true) + toolbar.border = JBUI.Borders.emptyLeft(5) + toolbar } toolbar.init(computeMainActionGroups()) - withContext(Dispatchers.EDT) { - toolbar.border = JBUI.Borders.empty(0, 5) - } return toolbar } else { @@ -760,4 +751,26 @@ private fun disposeIfNeeded(component: JComponent) { if (component is Disposable && !Disposer.isDisposed(component)) { Disposer.dispose(component) } +} + +private fun createMacAwareMenuBar(frame: JFrame, component: JComponent, coroutineScope: CoroutineScope): ActionAwareIdeMenuBar { + if (SystemInfoRt.isMac) { + val ideMenu = if (Menu.isJbScreenMenuEnabled()) { + createMacMenuBar(coroutineScope = coroutineScope, component = component, frame = frame) + } + else { + val menuBar = IdeMenuBar(coroutineScope = coroutineScope, frame = frame) + // if -DjbScreenMenuBar.enabled=false + frame.jMenuBar = menuBar + menuBar + } + return ideMenu + } + else { + return createMenuBar(coroutineScope = coroutineScope, frame = frame) + } +} + +internal fun createMenuBar(coroutineScope: CoroutineScope, frame: JFrame): IdeMenuBar { + return if (SystemInfoRt.isLinux) LinuxIdeMenuBar(coroutineScope, frame) else IdeMenuBar(coroutineScope, frame) } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerState.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerState.kt index 19636e998c54..a03bcc6dc35e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerState.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerState.kt @@ -82,7 +82,7 @@ class ToolWindowManagerStateImpl : ToolWindowManagerState { } element.addContent(recentState) } - if (moreButton !== ToolWindowAnchor.LEFT) { + if (moreButton != ToolWindowAnchor.LEFT) { element.addContent(Element(MORE_BUTTON_TAG).setAttribute("side", moreButton.toString())) } return element diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/CustomFrameTitleButtons.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/CustomFrameTitleButtons.kt index 59f5262e0498..d92b7285e4f0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/CustomFrameTitleButtons.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/CustomFrameTitleButtons.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.wm.impl.customFrameDecorations import com.intellij.icons.AllIcons @@ -6,10 +6,7 @@ import com.intellij.ide.ui.UISettings import com.intellij.openapi.wm.impl.customFrameDecorations.style.ComponentStyle import com.intellij.openapi.wm.impl.customFrameDecorations.style.ComponentStyleState import com.intellij.openapi.wm.impl.customFrameDecorations.style.StyleManager -import com.intellij.ui.icons.overrideIconScale import com.intellij.ui.scale.JBUIScale -import com.intellij.ui.scale.ScaleType -import com.intellij.util.IconUtil import com.intellij.util.ui.JBInsets import com.intellij.util.ui.JBUI.Borders import com.intellij.util.ui.JBUI.CurrentTheme @@ -22,12 +19,8 @@ import javax.swing.plaf.basic.BasicButtonUI internal open class CustomFrameTitleButtons(myCloseAction: Action) { companion object { - private val closeIcon = AllIcons.Windows.CloseActive - private val closeHoverIcon = AllIcons.Windows.CloseHover - private val closeInactive = AllIcons.Windows.CloseInactive - - fun create(myCloseAction: Action): CustomFrameTitleButtons { - val darculaTitleButtons = CustomFrameTitleButtons(myCloseAction) + fun create(closeAction: Action): CustomFrameTitleButtons { + val darculaTitleButtons = CustomFrameTitleButtons(closeAction) darculaTitleButtons.createChildren() return darculaTitleButtons } @@ -67,24 +60,24 @@ internal open class CustomFrameTitleButtons(myCloseAction: Action) { val closeStyleBuilder: ComponentStyle.ComponentStyleBuilder = ComponentStyle.ComponentStyleBuilder { isOpaque = false border = Borders.empty() - icon = closeIcon + icon = AllIcons.Windows.CloseActive }.apply { style(ComponentStyleState.HOVERED) { isOpaque = true background = Color(0xe81123) - icon = closeHoverIcon + icon = AllIcons.Windows.CloseHover } style(ComponentStyleState.PRESSED) { isOpaque = true background = Color(0xf1707a) - icon = closeHoverIcon + icon = AllIcons.Windows.CloseHover } } private val activeCloseStyle = closeStyleBuilder.build() private val inactiveCloseStyle = closeStyleBuilder .updateDefault { - icon = closeInactive + icon = AllIcons.Windows.CloseInactive }.build() private val panel = TitleButtonsPanel() @@ -165,41 +158,42 @@ internal open class CustomFrameTitleButtons(myCloseAction: Action) { button.text = null return button } +} - private class TitleButtonsPanel : JPanel(FlowLayout(FlowLayout.LEADING, 0, 0)) { - var isCompactMode = false - set(value) { - field = value - updateScaledPreferredSize() - } - - init { - isOpaque = false +private class TitleButtonsPanel : JPanel(FlowLayout(FlowLayout.LEADING, 0, 0)) { + var isCompactMode = false + set(value) { + field = value + updateScaledPreferredSize() } - fun addComponent(component: JComponent) { - component.setScaledPreferredSize() - add(component, "top") - } + init { + isOpaque = false + } - private fun updateScaledPreferredSize() { - components.forEach { (it as? JComponent)?.setScaledPreferredSize() } - } + fun addComponent(component: JComponent) { + component.setScaledPreferredSize() + add(component, "top") + } - private fun JComponent.setScaledPreferredSize() { - val size = CurrentTheme.TitlePane.buttonPreferredSize().clone() as Dimension - if (isCompactMode) size.height = JBUIScale.scale(30) - preferredSize = Dimension((size.width * UISettings.defFontScale).toInt(), (size.height * UISettings.defFontScale).toInt()) - } + private fun updateScaledPreferredSize() { + components.forEach { (it as? JComponent)?.setScaledPreferredSize() } + } - override fun updateUI() { - super.updateUI() - components?.forEach { component -> - if (component is JComponent) { - component.setScaledPreferredSize() - } + private fun JComponent.setScaledPreferredSize() { + val size = CurrentTheme.TitlePane.buttonPreferredSize().clone() as Dimension + if (isCompactMode) { + size.height = JBUIScale.scale(30) + } + preferredSize = Dimension((size.width * UISettings.defFontScale).toInt(), (size.height * UISettings.defFontScale).toInt()) + } + + override fun updateUI() { + super.updateUI() + components?.forEach { component -> + if (component is JComponent) { + component.setScaledPreferredSize() } } } - } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/ResizableCustomFrameTitleButtons.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/ResizableCustomFrameTitleButtons.kt index 2b5aee6c50fd..5dd3606a582e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/ResizableCustomFrameTitleButtons.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/ResizableCustomFrameTitleButtons.kt @@ -1,17 +1,16 @@ -// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.wm.impl.customFrameDecorations import com.intellij.icons.AllIcons import com.intellij.openapi.wm.impl.customFrameDecorations.style.StyleManager import javax.swing.Action -import javax.swing.JButton internal class ResizableCustomFrameTitleButtons(closeAction: Action, private val myRestoreAction: Action, private val myIconifyAction: Action, private val myMaximizeAction: Action ) : CustomFrameTitleButtons(closeAction) { - companion object{ + companion object { private val restoreIcon = AllIcons.Windows.Restore private val restoreInactiveIcon = AllIcons.Windows.RestoreInactive @@ -21,16 +20,19 @@ internal class ResizableCustomFrameTitleButtons(closeAction: Action, private val minimizeIcon = AllIcons.Windows.Minimize private val minimizeInactiveIcon = AllIcons.Windows.MinimizeInactive - fun create(myCloseAction: Action, myRestoreAction: Action, myIconifyAction: Action, myMaximizeAction: Action) : ResizableCustomFrameTitleButtons { + fun create(myCloseAction: Action, + myRestoreAction: Action, + myIconifyAction: Action, + myMaximizeAction: Action): ResizableCustomFrameTitleButtons { val darculaTitleButtons = ResizableCustomFrameTitleButtons(myCloseAction, myRestoreAction, myIconifyAction, myMaximizeAction) darculaTitleButtons.createChildren() return darculaTitleButtons } } - val restoreButton: JButton = createButton("Restore", myRestoreAction) - val maximizeButton: JButton = createButton("Maximize", myMaximizeAction) - val minimizeButton: JButton = createButton("Iconify", myIconifyAction) + private val restoreButton = createButton("Restore", myRestoreAction) + private val maximizeButton = createButton("Maximize", myMaximizeAction) + private val minimizeButton = createButton("Iconify", myIconifyAction) override fun fillButtonPane() { super.fillButtonPane() @@ -48,10 +50,8 @@ internal class ResizableCustomFrameTitleButtons(closeAction: Action, override fun updateStyles() { super.updateStyles() - StyleManager.applyStyle(restoreButton, getStyle(if(isSelected) restoreIcon else restoreInactiveIcon, restoreIcon)) - StyleManager.applyStyle(maximizeButton, getStyle(if(isSelected) maximizeIcon else maximizeInactiveIcon, maximizeIcon)) - StyleManager.applyStyle(minimizeButton, getStyle(if(isSelected) minimizeIcon else minimizeInactiveIcon, minimizeIcon)) + StyleManager.applyStyle(restoreButton, getStyle(if (isSelected) restoreIcon else restoreInactiveIcon, restoreIcon)) + StyleManager.applyStyle(maximizeButton, getStyle(if (isSelected) maximizeIcon else maximizeInactiveIcon, maximizeIcon)) + StyleManager.applyStyle(minimizeButton, getStyle(if (isSelected) minimizeIcon else minimizeInactiveIcon, minimizeIcon)) } - - } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt index f04372a858a4..dd3370ea20cd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt @@ -6,14 +6,16 @@ import com.intellij.accessibility.AccessibilityUtils import com.intellij.icons.AllIcons import com.intellij.ide.ui.UISettings import com.intellij.ide.ui.customization.CustomActionsSchema +import com.intellij.internal.inspector.ConfigureCustomSizeAction.CustomSizeModel.height +import com.intellij.internal.inspector.ConfigureCustomSizeAction.CustomSizeModel.width import com.intellij.openapi.MnemonicHelper import com.intellij.openapi.actionSystem.ActionGroup import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.ui.JBPopupMenu import com.intellij.openapi.util.NlsActions import com.intellij.openapi.util.SystemInfo +import com.intellij.openapi.util.SystemInfoRt import com.intellij.openapi.wm.impl.IdeRootPane -import com.intellij.openapi.wm.impl.customFrameDecorations.CustomFrameTitleButtons import com.intellij.openapi.wm.impl.headertoolbar.computeMainActionGroups import com.intellij.ui.* import com.intellij.ui.paint.LinePainter2D @@ -22,24 +24,36 @@ import com.intellij.ui.scale.ScaleContext import com.intellij.ui.scale.ScaleContextCache import com.intellij.util.ui.* import com.jetbrains.JBR -import com.jetbrains.WindowDecorations +import com.jetbrains.WindowDecorations.CustomTitleBar import org.jetbrains.annotations.ApiStatus import java.awt.* import java.awt.event.* import java.beans.PropertyChangeListener import javax.accessibility.AccessibleContext -import javax.accessibility.AccessibleRole import javax.swing.* import javax.swing.border.Border import kotlin.math.ceil import kotlin.math.floor import kotlin.math.roundToInt -private const val HEADER_HEIGHT_DFM = 30 -private const val HEADER_HEIGHT_COMPACT = 34 -private const val HEADER_HEIGHT_NORMAL = 40 +internal const val HEADER_HEIGHT_DFM = 30 +internal const val HEADER_HEIGHT_COMPACT = 34 +internal const val HEADER_HEIGHT_NORMAL = 40 -internal abstract class CustomHeader(private val window: Window) : JPanel() { +private val windowBorderThicknessInPhysicalPx: Int = run { + // Windows 10 (tested on 1809) determines the window border size by the main display scaling, rounded down. This value is + // calculated once on desktop session start, so it should be okay to store once per IDE session. + val scale = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration.defaultTransform.scaleY + floor(scale).toInt() +} + +internal fun updateWinControlsTheme(panel: JPanel, customTitleBar: CustomTitleBar) { + customTitleBar.putProperty("controls.dark", ColorUtil.isDark(panel.background)) + customTitleBar.putProperty("controls.foreground.normal", UIManager.getColor("WindowControls.foreground")) + customTitleBar.putProperty("controls.foreground.inactive", UIManager.getColor("WindowControls.inactiveForeground")) +} + +internal sealed class CustomHeader(@JvmField internal val window: Window) : JPanel() { companion object { val H: Int get() = 12 @@ -49,70 +63,64 @@ internal abstract class CustomHeader(private val window: Window) : JPanel() { val LABEL_BORDER: JBEmptyBorder get() = JBUI.Borders.empty(V, 0) - private val windowBorderThicknessInPhysicalPx: Int = run { - // Windows 10 (tested on 1809) determines the window border size by the main display scaling, rounded down. This value is - // calculated once on desktop session start, so it should be okay to store once per IDE session. - val scale = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration.defaultTransform.scaleY - floor(scale).toInt() + internal fun createCloseAction(header: CustomHeader): Action { + return CustomFrameAction(name = CommonBundle.getCloseButtonText(), icon = AllIcons.Windows.CloseSmall, action = header::close) } - @JvmStatic fun enableCustomHeader(w: Window) { JBR.getWindowDecorations()?.let { val bar = it.createCustomTitleBar() bar.height = 1f - if (w is Dialog) it.setCustomTitleBar(w, bar) - else if (w is Frame) it.setCustomTitleBar(w, bar) + if (w is Dialog) { + it.setCustomTitleBar(w, bar) + } + else if (w is Frame) { + it.setCustomTitleBar(w, bar) + } } } } - private var windowListener: WindowAdapter - private val componentListener: ComponentListener + private val windowListener = object : WindowAdapter() { + override fun windowActivated(ev: WindowEvent?) { + setActive(true) + } + + override fun windowDeactivated(ev: WindowEvent?) { + setActive(false) + } + + override fun windowStateChanged(e: WindowEvent?) { + windowStateChanged() + } + } + + private val componentListener = object : ComponentAdapter() { + override fun componentResized(e: ComponentEvent?) { + SwingUtilities.invokeLater { updateCustomTitleBar() } + } + } private val iconProvider = ScaleContextCache { AppUIUtil.loadSmallApplicationIcon(it) } - protected var myActive = false + @JvmField + internal var isActive = false private var customFrameTopBorder: CustomFrameTopBorder? = null @ApiStatus.Internal - val customTitleBar: WindowDecorations.CustomTitleBar? + val customTitleBar: CustomTitleBar? protected val productIcon: JComponent by lazy { createProductIcon() } - protected val buttonPanes: CustomFrameTitleButtons? by lazy { - createButtonsPane() - } - init { isOpaque = true background = getHeaderBackground() - myActive = window.isActive - - windowListener = object : WindowAdapter() { - override fun windowActivated(ev: WindowEvent?) { - setActive(true) - } - - override fun windowDeactivated(ev: WindowEvent?) { - setActive(false) - } - - override fun windowStateChanged(e: WindowEvent?) { - windowStateChanged() - } - } - - componentListener = object : ComponentAdapter() { - override fun componentResized(e: ComponentEvent?) { - SwingUtilities.invokeLater { updateCustomTitleBar() } - } - } + isActive = window.isActive setCustomFrameTopBorder() @@ -121,8 +129,10 @@ internal abstract class CustomHeader(private val window: Window) : JPanel() { override fun updateUI() { super.updateUI() - updateWinControlsTheme() - updateSize { computeMainActionGroups(CustomActionsSchema.getInstance()) } + customTitleBar?.let { + updateWinControlsTheme(panel = this, customTitleBar = it) + } + updateSize(mainToolbarActionSupplier = { computeMainActionGroups(CustomActionsSchema.getInstance()) }) } protected fun updateSize(mainToolbarActionSupplier: () -> List>) { @@ -130,32 +140,29 @@ internal abstract class CustomHeader(private val window: Window) : JPanel() { return } - preferredSize = preferredSize.apply { - height = JBUI.scale( - when { - (rootPane as? IdeRootPane)?.isCompactHeader(mainToolbarActionSupplier) == true -> HEADER_HEIGHT_DFM - UISettings.getInstance().compactMode -> HEADER_HEIGHT_COMPACT - else -> HEADER_HEIGHT_NORMAL - } - ) - } + updatePreferredSize(isCompactHeader = { (rootPane as? IdeRootPane)?.isCompactHeader(mainToolbarActionSupplier) == true }) } - private fun updateWinControlsTheme() { - customTitleBar?.putProperty("controls.dark", ColorUtil.isDark(background)) - customTitleBar?.putProperty("controls.foreground.normal", UIManager.getColor("WindowControls.foreground")) - customTitleBar?.putProperty("controls.foreground.inactive", UIManager.getColor("WindowControls.inactiveForeground")) + protected fun updatePreferredSize(isCompactHeader: () -> Boolean): Dimension { + val size = preferredSize + size.height = JBUI.scale( + when { + isCompactHeader() -> HEADER_HEIGHT_DFM + UISettings.getInstance().compactMode -> HEADER_HEIGHT_COMPACT + else -> HEADER_HEIGHT_NORMAL + } + ) + preferredSize = size + return size } protected open fun getHeaderBackground(active: Boolean = true) = JBUI.CurrentTheme.CustomFrameDecorations.titlePaneBackground(active) protected fun setCustomFrameTopBorder(isTopNeeded: () -> Boolean = { true }, isBottomNeeded: () -> Boolean = { false }) { - customFrameTopBorder = CustomFrameTopBorder(isTopNeeded = isTopNeeded, isBottomNeeded = isBottomNeeded) + customFrameTopBorder = CustomFrameTopBorder(isTopNeeded = isTopNeeded, isBottomNeeded = isBottomNeeded, header = this) border = customFrameTopBorder } - open fun createButtonsPane(): CustomFrameTitleButtons? = null - open fun windowStateChanged() { updateCustomTitleBar() } @@ -207,11 +214,9 @@ internal abstract class CustomHeader(private val window: Window) : JPanel() { customTitleBar.height = (height - insets.bottom).toFloat() setCustomTitleBar(customTitleBar) } - - //border = JBUI.Borders.empty(0, customTitleBar.leftInset.toInt(), 0, customTitleBar.rightInset.toInt()) } - private fun setCustomTitleBar(titleBar: WindowDecorations.CustomTitleBar?) { + private fun setCustomTitleBar(titleBar: CustomTitleBar?) { JBR.getWindowDecorations()?.let { if (window is Dialog) { it.setCustomTitleBar(window, titleBar) @@ -223,7 +228,7 @@ internal abstract class CustomHeader(private val window: Window) : JPanel() { } private fun setActive(value: Boolean) { - myActive = value + isActive = value updateActive() updateCustomTitleBar() } @@ -231,12 +236,12 @@ internal abstract class CustomHeader(private val window: Window) : JPanel() { protected open fun updateActive() { customFrameTopBorder?.repaintBorder() - background = getHeaderBackground(myActive) - updateWinControlsTheme() + background = getHeaderBackground(isActive) + customTitleBar?.let { + updateWinControlsTheme(panel = this, customTitleBar = it) + } } - protected val myCloseAction: Action = CustomFrameAction(CommonBundle.getCloseButtonText(), AllIcons.Windows.CloseSmall) { close() } - protected fun close() { window.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING)) } @@ -268,7 +273,7 @@ internal abstract class CustomHeader(private val window: Window) : JPanel() { } open fun addMenuItems(menu: JPopupMenu) { - val closeMenuItem = menu.add(myCloseAction) + val closeMenuItem = menu.add(createCloseAction(this)) closeMenuItem.font = JBFont.label().deriveFont(Font.BOLD) } @@ -281,156 +286,163 @@ internal abstract class CustomHeader(private val window: Window) : JPanel() { } private inner class AccessibleCustomHeader: AccessibleJPanel() { - override fun getAccessibleRole(): AccessibleRole { - return AccessibilityUtils.GROUPED_ELEMENTS - } - } - - inner class CustomFrameTopBorder(val isTopNeeded: () -> Boolean = { true }, val isBottomNeeded: () -> Boolean = { false }) : Border { - // Bottom border is a line between a window title/main menu area and the frame content. - private val bottomBorderWidthLogicalPx = JBUI.scale(1) - - // In reality, Windows uses #262626 with alpha-blending with alpha=0.34, but we have no (easy) way of doing the same, so let's just - // use the value on white background (since it is most noticeable on white). - // - // Unfortunately, DWM doesn't offer an API to determine this value, so it has to be hardcoded here. - private val defaultActiveBorder = Color(0x707070) - private val inactiveColor = Color(0xaaaaaa) - - private val menuBarBorderColor: Color = JBColor.namedColor("MenuBar.borderColor", JBColor(Gray.xCD, Gray.x51)) - private var colorizationAffectsBorders: Boolean = false - private var activeColor: Color = defaultActiveBorder - - private fun calculateAffectsBorders(): Boolean { - val windowsBuild = SystemInfo.getWinBuildNumber() ?: 0 - if (windowsBuild < 17763) return true // should always be active on older versions on Windows - return Toolkit.getDefaultToolkit().getDesktopProperty("win.dwm.colorizationColor.affects.borders") as Boolean? ?: true - } - - private fun calculateActiveBorderColor(): Color { - if (!colorizationAffectsBorders) - return defaultActiveBorder - - try { - val toolkit = Toolkit.getDefaultToolkit() - val colorizationColor = toolkit.getDesktopProperty("win.dwm.colorizationColor") as Color? - if (colorizationColor != null) { - // The border color is a result of an alpha blend of colorization color and #D9D9D9 with the alpha value set by the - // colorization color balance. - var colorizationColorBalance = toolkit.getDesktopProperty("win.dwm.colorizationColorBalance") as Int? - if (colorizationColorBalance != null) { - if (colorizationColorBalance > 100) { - // May be caused by custom Windows themes installed. - colorizationColorBalance = 100 - } - - // If the desktop setting "Automatically pick an accent color from my background" is active, then the border - // color should be the same as the colorization color read from the registry. To detect that setting, we use the - // fact that colorization color balance is set to 0xfffffff3 when the setting is active. - if (colorizationColorBalance < 0) - colorizationColorBalance = 100 - - return when (colorizationColorBalance) { - 0 -> Color(0xD9D9D9) - 100 -> colorizationColor - else -> { - val alpha = colorizationColorBalance / 100.0f - val remainder = 1 - alpha - val r = (colorizationColor.red * alpha + 0xD9 * remainder).roundToInt() - val g = (colorizationColor.green * alpha + 0xD9 * remainder).roundToInt() - val b = (colorizationColor.blue * alpha + 0xD9 * remainder).roundToInt() - Color(r, g, b) - } - } - } - } - - return colorizationColor - ?: toolkit.getDesktopProperty("win.frame.activeBorderColor") as Color? - ?: menuBarBorderColor - } - catch (t: Throwable) { - // Should be as fail-safe as possible, since any errors during border coloring could lead to an IDE being broken. - logger().error(t) - return defaultActiveBorder - } - } - - private fun calculateWindowBorderThicknessInLogicalPx(): Double { - return windowBorderThicknessInPhysicalPx.toDouble() / JBUIScale.sysScale(window) - } - - private val listeners = mutableListOf>() - private inline fun listenForPropertyChanges(vararg propertyNames: String, crossinline action: () -> Unit) { - val toolkit = Toolkit.getDefaultToolkit() - val listener = PropertyChangeListener { action() } - for (property in propertyNames) { - toolkit.addPropertyChangeListener(property, listener) - listeners.add(property to listener) - } - } - - fun addNotify() { - colorizationAffectsBorders = calculateAffectsBorders() - listenForPropertyChanges("win.dwm.colorizationColor.affects.borders") { - colorizationAffectsBorders = calculateAffectsBorders() - activeColor = calculateActiveBorderColor() // active border color is dependent on whether colorization affects borders or not - } - - activeColor = calculateActiveBorderColor() - listenForPropertyChanges("win.dwm.colorizationColor", "win.dwm.colorizationColorBalance", "win.frame.activeBorderColor") { - activeColor = calculateActiveBorderColor() - } - } - - fun removeNotify() { - val toolkit = Toolkit.getDefaultToolkit() - for ((propertyName, listener) in listeners) - toolkit.removePropertyChangeListener(propertyName, listener) - listeners.clear() - } - - fun repaintBorder() { - val borderInsets = getBorderInsets(this@CustomHeader) - - val thickness = calculateWindowBorderThicknessInLogicalPx() - repaint(0, 0, width, ceil(thickness).toInt()) - repaint(0, height - borderInsets.bottom, width, borderInsets.bottom) - } - - private val shouldDrawTopBorder: Boolean - get() { - val drawTopBorderActive = myActive && (colorizationAffectsBorders || UIUtil.isUnderIntelliJLaF()) // omit in Darcula with colorization disabled - val drawTopBorderInactive = !myActive && UIUtil.isUnderIntelliJLaF() - return drawTopBorderActive || drawTopBorderInactive - } - - override fun paintBorder(c: Component, g: Graphics, x: Int, y: Int, width: Int, height: Int) { - val thickness = calculateWindowBorderThicknessInLogicalPx() - if (isTopNeeded() && shouldDrawTopBorder) { - g.color = if (myActive) activeColor else inactiveColor - LinePainter2D.paint(g as Graphics2D, x.toDouble(), y.toDouble(), width.toDouble(), y.toDouble(), LinePainter2D.StrokeType.INSIDE, - thickness) - } - - if (isBottomNeeded()) { - g.color = menuBarBorderColor - val y1 = y + height - bottomBorderWidthLogicalPx - LinePainter2D.paint(g as Graphics2D, x.toDouble(), y1.toDouble(), width.toDouble(), y1.toDouble()) - } - } - - override fun getBorderInsets(c: Component): Insets { - val thickness = calculateWindowBorderThicknessInLogicalPx() - val top = if (isTopNeeded() && (colorizationAffectsBorders || StartupUiUtil.isUnderIntelliJLaF())) ceil(thickness).toInt() else 0 - val bottom = if (isBottomNeeded()) bottomBorderWidthLogicalPx else 0 - val left = customTitleBar?.leftInset?.toInt() ?: 0 - val right = customTitleBar?.rightInset?.toInt() ?: 0 - return Insets(top, left, bottom, right) - } - - override fun isBorderOpaque(): Boolean = true + override fun getAccessibleRole() = AccessibilityUtils.GROUPED_ELEMENTS } } +internal class CustomFrameTopBorder(@JvmField val isTopNeeded: () -> Boolean = { true }, + @JvmField val isBottomNeeded: () -> Boolean = { false }, + @JvmField val header: CustomHeader) : Border { + // The bottom border is a line between a window title/main menu area and the frame content. + private val bottomBorderWidthLogicalPx = JBUI.scale(1) + + // In reality, Windows uses #262626 with alpha-blending with alpha=0.34, but we have no (easy) way of doing the same, so let's just + // use the value on a white background (since it is most noticeable on white). + // + // Unfortunately, DWM doesn't offer an API to determine this value, so it has to be hardcoded here. + private val defaultActiveBorder = Color(0x707070) + private val inactiveColor = Color(0xaaaaaa) + + private val menuBarBorderColor = JBColor.namedColor("MenuBar.borderColor", JBColor(Gray.xCD, Gray.x51)) + private var colorizationAffectsBorders: Boolean = false + private var activeColor = defaultActiveBorder + + private fun calculateAffectsBorders(): Boolean { + if (SystemInfoRt.isWindows) { + val windowsBuild = SystemInfo.getWinBuildNumber() ?: 0 + if (windowsBuild < 17763) { + // should always be active on older versions on Windows + return true + } + } + return Toolkit.getDefaultToolkit().getDesktopProperty("win.dwm.colorizationColor.affects.borders") as Boolean? ?: true + } + + private fun calculateActiveBorderColor(): Color { + if (!colorizationAffectsBorders) { + return defaultActiveBorder + } + + try { + val toolkit = Toolkit.getDefaultToolkit() + val colorizationColor = toolkit.getDesktopProperty("win.dwm.colorizationColor") as Color? + if (colorizationColor != null) { + // The border color is a result of an alpha blend of colorization color and #D9D9D9 with the alpha value set by the + // colorization color balance. + var colorizationColorBalance = toolkit.getDesktopProperty("win.dwm.colorizationColorBalance") as Int? + if (colorizationColorBalance != null) { + if (colorizationColorBalance > 100) { + // May be caused by custom Windows themes installed. + colorizationColorBalance = 100 + } + + // If the desktop setting "Automatically pick an accent color from my background" is active, then the border + // color should be the same as the colorization color read from the registry. To detect that setting, we use the + // fact that colorization color balance is set to 0xfffffff3 when the setting is active. + if (colorizationColorBalance < 0) + colorizationColorBalance = 100 + + return when (colorizationColorBalance) { + 0 -> Color(0xD9D9D9) + 100 -> colorizationColor + else -> { + val alpha = colorizationColorBalance / 100.0f + val remainder = 1 - alpha + val r = (colorizationColor.red * alpha + 0xD9 * remainder).roundToInt() + val g = (colorizationColor.green * alpha + 0xD9 * remainder).roundToInt() + val b = (colorizationColor.blue * alpha + 0xD9 * remainder).roundToInt() + Color(r, g, b) + } + } + } + } + + return colorizationColor + ?: toolkit.getDesktopProperty("win.frame.activeBorderColor") as Color? + ?: menuBarBorderColor + } + catch (t: Throwable) { + // Should be as fail-safe as possible, since any errors during border coloring could lead to an IDE being broken. + logger().error(t) + return defaultActiveBorder + } + } + + private fun calculateWindowBorderThicknessInLogicalPx(): Double { + return windowBorderThicknessInPhysicalPx.toDouble() / JBUIScale.sysScale(header.window) + } + + private val listeners = mutableListOf>() + private inline fun listenForPropertyChanges(vararg propertyNames: String, crossinline action: () -> Unit) { + val toolkit = Toolkit.getDefaultToolkit() + val listener = PropertyChangeListener { action() } + for (property in propertyNames) { + toolkit.addPropertyChangeListener(property, listener) + listeners.add(property to listener) + } + } + + fun addNotify() { + colorizationAffectsBorders = calculateAffectsBorders() + listenForPropertyChanges("win.dwm.colorizationColor.affects.borders") { + colorizationAffectsBorders = calculateAffectsBorders() + activeColor = calculateActiveBorderColor() // active border color is dependent on whether colorization affects borders or not + } + + activeColor = calculateActiveBorderColor() + listenForPropertyChanges("win.dwm.colorizationColor", "win.dwm.colorizationColorBalance", "win.frame.activeBorderColor") { + activeColor = calculateActiveBorderColor() + } + } + + fun removeNotify() { + val toolkit = Toolkit.getDefaultToolkit() + for ((propertyName, listener) in listeners) { + toolkit.removePropertyChangeListener(propertyName, listener) + } + listeners.clear() + } + + fun repaintBorder() { + val borderInsets = getBorderInsets(header) + + val thickness = calculateWindowBorderThicknessInLogicalPx() + header.repaint(0, 0, width, ceil(thickness).toInt()) + header.repaint(0, height - borderInsets.bottom, width, borderInsets.bottom) + } + + private val shouldDrawTopBorder: Boolean + get() { + val drawTopBorderActive = header.isActive && (colorizationAffectsBorders || UIUtil.isUnderIntelliJLaF()) // omit in Darcula with colorization disabled + val drawTopBorderInactive = !header.isActive && UIUtil.isUnderIntelliJLaF() + return drawTopBorderActive || drawTopBorderInactive + } + + override fun paintBorder(c: Component, g: Graphics, x: Int, y: Int, width: Int, height: Int) { + val thickness = calculateWindowBorderThicknessInLogicalPx() + if (isTopNeeded() && shouldDrawTopBorder) { + g.color = if (header.isActive) activeColor else inactiveColor + LinePainter2D.paint(g as Graphics2D, x.toDouble(), y.toDouble(), width.toDouble(), y.toDouble(), LinePainter2D.StrokeType.INSIDE, + thickness) + } + + if (isBottomNeeded()) { + g.color = menuBarBorderColor + val y1 = y + height - bottomBorderWidthLogicalPx + LinePainter2D.paint(g as Graphics2D, x.toDouble(), y1.toDouble(), width.toDouble(), y1.toDouble()) + } + } + + override fun getBorderInsets(c: Component): Insets { + val thickness = calculateWindowBorderThicknessInLogicalPx() + val top = if (isTopNeeded() && (colorizationAffectsBorders || StartupUiUtil.isUnderIntelliJLaF())) ceil(thickness).toInt() else 0 + val bottom = if (isBottomNeeded()) bottomBorderWidthLogicalPx else 0 + val left = header.customTitleBar?.leftInset?.toInt() ?: 0 + val right = header.customTitleBar?.rightInset?.toInt() ?: 0 + return Insets(top, left, bottom, right) + } + + override fun isBorderOpaque(): Boolean = true +} + diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/DefaultFrameHeader.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/DefaultFrameHeader.kt index 2bbfb4267de0..65195029336a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/DefaultFrameHeader.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/DefaultFrameHeader.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.wm.impl.customFrameDecorations.header import com.intellij.openapi.wm.impl.customFrameDecorations.header.titleLabel.CustomDecorationTitle @@ -25,11 +25,11 @@ internal class DefaultFrameHeader(frame: JFrame, isForDockContainerProvider: Boo add(customDecorationTitle.view, gb.next().fillCell().weightx(1.0)) buttonPanes?.let { add(it.getView(), gb.next().anchor(GridBagConstraints.EAST)) } - setCustomFrameTopBorder(isTopNeeded = { myState != Frame.MAXIMIZED_VERT && myState != Frame.MAXIMIZED_BOTH }) + setCustomFrameTopBorder(isTopNeeded = { state != Frame.MAXIMIZED_VERT && state != Frame.MAXIMIZED_BOTH }) } override fun updateActive() { - customDecorationTitle.setActive(myActive) + customDecorationTitle.setActive(isActive) super.updateActive() } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/DialogHeader.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/DialogHeader.kt index fb9ca3a2d8a8..1e34b8659250 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/DialogHeader.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/DialogHeader.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.wm.impl.customFrameDecorations.header import com.intellij.openapi.util.NlsContexts @@ -16,71 +16,78 @@ import java.beans.PropertyChangeListener import javax.swing.JLabel import javax.swing.UIManager -internal class DialogHeader(val window: Window) : CustomHeader(window) { - private val titleLabel = JLabel().apply { - border = LABEL_BORDER - } - private val titleChangeListener = PropertyChangeListener{ - titleLabel.text = getTitle() +internal class DialogHeader(window: Window) : CustomHeader(window) { + private val titleLabel = JLabel().apply { + border = LABEL_BORDER + } + private val titleChangeListener = PropertyChangeListener { + titleLabel.text = getTitle() + } + + init { + layout = GridBagLayout() + titleLabel.text = getTitle() + + productIcon.border = JBUI.Borders.empty(0, H, 0, H) + + val gb = GridBag().setDefaultFill(GridBagConstraints.VERTICAL).setDefaultAnchor(GridBagConstraints.WEST) + add(productIcon, gb.next()) + add(titleLabel, gb.next().fillCell().weightx(1.0)) + createButtonsPane()?.let { add(it.getView(), gb.next().anchor(GridBagConstraints.EAST)) } + } + + private val dragListener = object : MouseAdapter() { //passing events to OS handler to make it draggable + override fun mouseDragged(e: MouseEvent?) { + customTitleBar?.forceHitTest(false) } - init { - layout = GridBagLayout() - titleLabel.text = getTitle() - - productIcon.border = JBUI.Borders.empty(0, H, 0, H) - - val gb = GridBag().setDefaultFill(GridBagConstraints.VERTICAL).setDefaultAnchor(GridBagConstraints.WEST) - add(productIcon, gb.next()) - add(titleLabel, gb.next().fillCell().weightx(1.0)) - buttonPanes?.let { add(it.getView(), gb.next().anchor(GridBagConstraints.EAST)) } + override fun mouseClicked(e: MouseEvent?) { + customTitleBar?.forceHitTest(false) } - private val dragListener = object : MouseAdapter() { //passing events to OS handler to make it draggable - override fun mouseDragged(e: MouseEvent?) { customTitleBar?.forceHitTest(false) } - override fun mouseClicked(e: MouseEvent?) { customTitleBar?.forceHitTest(false) } - override fun mouseMoved(e: MouseEvent?) { customTitleBar?.forceHitTest(false) } + override fun mouseMoved(e: MouseEvent?) { + customTitleBar?.forceHitTest(false) } + } - override fun installListeners() { - super.installListeners() - window.addPropertyChangeListener("title", titleChangeListener) - addMouseListener(dragListener) - addMouseMotionListener(dragListener) + override fun installListeners() { + super.installListeners() + window.addPropertyChangeListener("title", titleChangeListener) + addMouseListener(dragListener) + addMouseMotionListener(dragListener) + } + + override fun uninstallListeners() { + super.uninstallListeners() + window.removePropertyChangeListener(titleChangeListener) + removeMouseListener(dragListener) + removeMouseMotionListener(dragListener) + } + + override fun updateActive() { + titleLabel.foreground = if (isActive) UIManager.getColor("Panel.foreground") else UIManager.getColor("Label.disabledForeground") + super.updateActive() + } + + override fun windowStateChanged() { + super.windowStateChanged() + titleLabel.text = getTitle() + } + + override fun addNotify() { + super.addNotify() + titleLabel.text = getTitle() + } + + @NlsContexts.DialogTitle + private fun getTitle(): String? { + when (window) { + is Dialog -> return window.title + else -> return "" } + } - override fun uninstallListeners() { - super.uninstallListeners() - window.removePropertyChangeListener(titleChangeListener) - removeMouseListener(dragListener) - removeMouseMotionListener(dragListener) - } - - override fun updateActive() { - titleLabel.foreground = if (myActive) UIManager.getColor("Panel.foreground") else UIManager.getColor("Label.disabledForeground") - super.updateActive() - } - - override fun windowStateChanged() { - super.windowStateChanged() - titleLabel.text = getTitle() - } - - override fun addNotify() { - super.addNotify() - titleLabel.text = getTitle() - } - - @NlsContexts.DialogTitle - private fun getTitle(): String? { - when (window) { - is Dialog -> return window.title - else -> return "" - } - } - - override fun createButtonsPane(): CustomFrameTitleButtons? { - if (IdeRootPane.hideNativeLinuxTitle) CustomFrameTitleButtons.create(myCloseAction) - return null + private fun createButtonsPane(): CustomFrameTitleButtons? { + return if (IdeRootPane.hideNativeLinuxTitle) CustomFrameTitleButtons.create(createCloseAction(this)) else null } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/FrameHeader.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/FrameHeader.kt index 58612eaf27d4..aebe15920cd7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/FrameHeader.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/FrameHeader.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.wm.impl.customFrameDecorations.header import com.intellij.CommonBundle @@ -12,30 +12,25 @@ import com.intellij.util.ui.JBFont import java.awt.Font import java.awt.Frame import java.awt.Toolkit -import java.awt.event.WindowAdapter -import java.awt.event.WindowStateListener -import javax.swing.Action import javax.swing.JFrame import javax.swing.JPopupMenu import javax.swing.JSeparator internal open class FrameHeader(protected val frame: JFrame) : CustomHeader(frame) { - private val iconifyAction: Action = CustomFrameAction(ActionsBundle.message("action.MinimizeCurrentWindow.text"), + private val iconifyAction = CustomFrameAction(ActionsBundle.message("action.MinimizeCurrentWindow.text"), AllIcons.Windows.MinimizeSmall) { iconify() } - private val restoreAction: Action = CustomFrameAction(CommonBundle.message("button.without.mnemonic.restore"), + private val restoreAction = CustomFrameAction(CommonBundle.message("button.without.mnemonic.restore"), AllIcons.Windows.RestoreSmall) { restore() } - private val maximizeAction: Action = CustomFrameAction(IdeBundle.message("action.maximize.text"), + private val maximizeAction = CustomFrameAction(IdeBundle.message("action.maximize.text"), AllIcons.Windows.MaximizeSmall) { maximize() } - private var windowStateListener: WindowStateListener - protected var myState = 0 + protected var state = 0 - init { - windowStateListener = object : WindowAdapter() { - override fun windowStateChanged(e: java.awt.event.WindowEvent?) { - updateActions() - } - } + @Suppress("LeakingThis") + private val closeAction = createCloseAction(this) + + protected val buttonPanes: CustomFrameTitleButtons? by lazy { + createButtonsPane() } override fun windowStateChanged() { @@ -44,19 +39,19 @@ internal open class FrameHeader(protected val frame: JFrame) : CustomHeader(fram } private fun iconify() { - frame.extendedState = myState or Frame.ICONIFIED + frame.extendedState = state or Frame.ICONIFIED } private fun maximize() { - frame.extendedState = myState or Frame.MAXIMIZED_BOTH + frame.extendedState = state or Frame.MAXIMIZED_BOTH } private fun restore() { - if (myState and Frame.ICONIFIED != 0) { - frame.extendedState = myState and Frame.ICONIFIED.inv() + if (state and Frame.ICONIFIED != 0) { + frame.extendedState = state and Frame.ICONIFIED.inv() } else { - frame.extendedState = myState and Frame.MAXIMIZED_BOTH.inv() + frame.extendedState = state and Frame.MAXIMIZED_BOTH.inv() } } @@ -66,9 +61,9 @@ internal open class FrameHeader(protected val frame: JFrame) : CustomHeader(fram } private fun updateActions() { - myState = frame.extendedState + state = frame.extendedState if (frame.isResizable) { - if (myState and Frame.MAXIMIZED_BOTH != 0) { + if (state and Frame.MAXIMIZED_BOTH != 0) { maximizeAction.isEnabled = false restoreAction.isEnabled = true } @@ -82,7 +77,7 @@ internal open class FrameHeader(protected val frame: JFrame) : CustomHeader(fram restoreAction.isEnabled = false } iconifyAction.isEnabled = true - myCloseAction.isEnabled = true + closeAction.isEnabled = true buttonPanes?.updateVisibility() updateCustomTitleBar() @@ -97,14 +92,14 @@ internal open class FrameHeader(protected val frame: JFrame) : CustomHeader(fram menu.add(JSeparator()) - val closeMenuItem = menu.add(myCloseAction) + val closeMenuItem = menu.add(closeAction) closeMenuItem.font = JBFont.label().deriveFont(Font.BOLD) } - override fun createButtonsPane(): CustomFrameTitleButtons? { - if (IdeRootPane.hideNativeLinuxTitle) - return ResizableCustomFrameTitleButtons.create(myCloseAction, restoreAction, iconifyAction, maximizeAction) - + private fun createButtonsPane(): CustomFrameTitleButtons? { + if (IdeRootPane.hideNativeLinuxTitle) { + return ResizableCustomFrameTitleButtons.create(closeAction, restoreAction, iconifyAction, maximizeAction) + } return null } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/MacToolbarFrameHeader.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/MacToolbarFrameHeader.kt index f66f46aab018..daa651201c4b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/MacToolbarFrameHeader.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/MacToolbarFrameHeader.kt @@ -1,6 +1,7 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.wm.impl.customFrameDecorations.header +import com.intellij.accessibility.AccessibilityUtils import com.intellij.ide.ProjectWindowCustomizerService import com.intellij.ide.ui.LafManagerListener import com.intellij.ide.ui.UISettings @@ -14,11 +15,13 @@ import com.intellij.openapi.wm.impl.ToolbarHolder import com.intellij.openapi.wm.impl.customFrameDecorations.header.titleLabel.SimpleCustomDecorationPath import com.intellij.openapi.wm.impl.headertoolbar.MainToolbar import com.intellij.openapi.wm.impl.headertoolbar.computeMainActionGroups +import com.intellij.ui.UIBundle import com.intellij.ui.mac.MacFullScreenControlsManager import com.intellij.ui.mac.MacMainFrameDecorator import com.intellij.util.childScope import com.intellij.util.ui.JBUI import com.jetbrains.JBR +import com.jetbrains.WindowDecorations import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.BufferOverflow @@ -26,32 +29,53 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.awt.BorderLayout -import java.awt.Color +import java.awt.Dimension import java.awt.Graphics -import java.awt.event.ComponentAdapter -import java.awt.event.ComponentEvent +import java.awt.event.WindowAdapter +import java.awt.event.WindowEvent import java.beans.PropertyChangeListener +import javax.accessibility.AccessibleContext import javax.swing.JComponent import javax.swing.JFrame +import javax.swing.JPanel private const val GAP_FOR_BUTTONS = 80 -private const val DEFAULT_HEADER_HEIGHT = 40 internal class MacToolbarFrameHeader(private val coroutineScope: CoroutineScope, private val frame: JFrame, private val root: IdeRootPane) - : CustomHeader(frame), MainFrameCustomHeader, ToolbarHolder, UISettingsListener { - private var toolbar: MainToolbar + : JPanel(AdjustableSizeCardLayout()), MainFrameCustomHeader, ToolbarHolder, UISettingsListener { + private var toolbar: MainToolbar? private var currentComponent: JComponent - private val updateRequests = MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) + private val updateRequests = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) - private var lastHeight = DEFAULT_HEADER_HEIGHT + private val windowListener = object : WindowAdapter() { + override fun windowActivated(ev: WindowEvent) { + updateActive() + } + + override fun windowDeactivated(ev: WindowEvent) { + updateActive() + } + + override fun windowStateChanged(e: WindowEvent) { + updateBorders() + } + } + + private val customTitleBar: WindowDecorations.CustomTitleBar? init { - layout = AdjustableSizeCardLayout() + isOpaque = true + background = JBUI.CurrentTheme.CustomFrameDecorations.mainToolbarBackground(true) + + val windowDecorations = JBR.getWindowDecorations() + customTitleBar = windowDecorations?.createCustomTitleBar() + root.addPropertyChangeListener(MacMainFrameDecorator.FULL_SCREEN, PropertyChangeListener { updateBorders() }) - toolbar = createToolBar(coroutineScope.childScope()) + val toolbar = createToolBar(coroutineScope.childScope()) + this.toolbar = toolbar add(toolbar, BorderLayout.CENTER) currentComponent = toolbar @@ -71,37 +95,42 @@ internal class MacToolbarFrameHeader(private val coroutineScope: CoroutineScope, } if (customTitleBar != null) { - customTitleBar.height = DEFAULT_HEADER_HEIGHT.toFloat() - JBR.getWindowDecorations()!!.setCustomTitleBar(frame, customTitleBar) + customTitleBar.height = HEADER_HEIGHT_NORMAL.toFloat() + windowDecorations.setCustomTitleBar(frame, customTitleBar) } coroutineScope.launch(ModalityState.any().asContextElement()) { - initToolbar() + val toolbarActionGroups = computeMainActionGroups() + val isCompactHeader = root.isCompactHeader(mainToolbarActionSupplier = { toolbarActionGroups }) + if (isCompactHeader) { + withContext(Dispatchers.EDT) { + updateVisibleComponent(isCompactHeader = true) + } + } + else { + toolbar.init(toolbarActionGroups, customTitleBar) + } updateRequests.collect { - initToolbar() - withContext(Dispatchers.EDT) { - toolbar.updateBackground() - updateCustomTitleBar() - revalidate() - } + updateState() } } } - private fun createToolBar(coroutineScope: CoroutineScope): MainToolbar { - val toolbar = MainToolbar(coroutineScope, frame) - toolbar.layoutCallBack = { updateCustomTitleBar() } - toolbar.isOpaque = false - toolbar.addComponentListener(object: ComponentAdapter() { - override fun componentResized(e: ComponentEvent?) { - updateCustomTitleBar() - super.componentResized(e) - } - }) - return toolbar + private suspend fun updateState() { + val toolbarActionGroups = computeMainActionGroups() + val mainToolbarActionSupplier = { toolbarActionGroups } + val isCompactHeader = root.isCompactHeader(mainToolbarActionSupplier) + + withContext(Dispatchers.EDT) { + updateVisibleComponent(isCompactHeader) + } + + toolbar?.init(toolbarActionGroups, customTitleBar) } + private fun createToolBar(coroutineScope: CoroutineScope) = MainToolbar(coroutineScope = coroutineScope, frame = frame) + override fun paint(g: Graphics) { ProjectWindowCustomizerService.getInstance().paint(window = frame, parent = this, g = g) super.paint(g) @@ -110,100 +139,124 @@ internal class MacToolbarFrameHeader(private val coroutineScope: CoroutineScope, override fun updateUI() { super.updateUI() + customTitleBar?.let { + updateWinControlsTheme(panel = this, customTitleBar = it) + } + if (parent != null) { scheduleUpdateToolbar() updateBorders() } } - private suspend fun initToolbar() { - val toolbarActionGroups = computeMainActionGroups() - val mainToolbarActionSupplier = { toolbarActionGroups } - val isCompactHeader = root.isCompactHeader(mainToolbarActionSupplier) - if (!isCompactHeader) { - toolbar.init(toolbarActionGroups, customTitleBar) - } - - withContext(Dispatchers.EDT) { - updateVisibleCard(isCompactHeader) - updateSize(mainToolbarActionSupplier) - } - } - override fun scheduleUpdateToolbar() { updateRequests.tryEmit(Unit) } - private fun updateVisibleCard(isCompactHeader: Boolean) { + private fun updateVisibleComponent(isCompactHeader: Boolean) { if (isCompactHeader) { + if (toolbar == null) { + return + } + remove(currentComponent) + toolbar = null val headerTitle = SimpleCustomDecorationPath(frame) headerTitle.isOpaque = false add(headerTitle, BorderLayout.CENTER) currentComponent = headerTitle updateBorders() - revalidate() - repaint() } else if (componentCount != 0 && currentComponent != toolbar) { remove(currentComponent) val coroutineScope = coroutineScope.childScope() - toolbar = createToolBar(coroutineScope) + val toolbar = createToolBar(coroutineScope) + this.toolbar = toolbar add(toolbar) currentComponent = toolbar - - updateRequests.tryEmit(Unit) - revalidate() - repaint() } - } + else { + return + } - override fun windowStateChanged() { - super.windowStateChanged() - updateBorders() + val h = updatePreferredSize(isCompactHeader = { isCompactHeader }).height + customTitleBar?.height = h.toFloat() + + revalidate() + repaint() } override fun addNotify() { super.addNotify() + updateActive() + frame.addWindowListener(windowListener) + frame.addWindowStateListener(windowListener) updateBorders() } override fun getComponent(): JComponent = this - override fun getHeaderBackground(active: Boolean): Color { - return JBUI.CurrentTheme.CustomFrameDecorations.mainToolbarBackground(active) - } - - override fun updateCustomTitleBar() { - val height = height - if (height != 0 && lastHeight != height) { - customTitleBar?.let { - it.height = height.toFloat() - } - } - updateBorders() - } - private fun updateBorders() { val isFullscreen = root.getClientProperty(MacMainFrameDecorator.FULL_SCREEN) != null + val rightGap: Int if (isFullscreen && !MacFullScreenControlsManager.enabled()) { border = JBUI.Borders.empty() - ((if (componentCount == 0) null else getComponent(0)) as? SimpleCustomDecorationPath)?.updateBorders(0) + rightGap = 0 } else { border = JBUI.Borders.emptyLeft(GAP_FOR_BUTTONS) - ((if (componentCount == 0) null else getComponent(0)) as? SimpleCustomDecorationPath)?.updateBorders(GAP_FOR_BUTTONS) + rightGap = GAP_FOR_BUTTONS } - toolbar.border = JBUI.Borders.empty() - } - override fun updateActive() { - super.updateActive() - toolbar.background = getHeaderBackground(myActive) + val toolbar = toolbar + if (toolbar == null) { + (currentComponent as? SimpleCustomDecorationPath)?.updateBorders(rightGap) + } + else { + toolbar.border = JBUI.Borders.empty() + } } override fun uiSettingsChanged(uiSettings: UISettings) { updateRequests.tryEmit(Unit) } + + private fun updatePreferredSize(isCompactHeader: () -> Boolean): Dimension { + val size = preferredSize + size.height = JBUI.scale( + when { + isCompactHeader() -> HEADER_HEIGHT_DFM + UISettings.getInstance().compactMode -> HEADER_HEIGHT_COMPACT + else -> HEADER_HEIGHT_NORMAL + } + ) + preferredSize = size + return size + } + + override fun removeNotify() { + super.removeNotify() + frame.removeWindowListener(windowListener) + frame.removeWindowStateListener(windowListener) + } + + private fun updateActive() { + background = JBUI.CurrentTheme.CustomFrameDecorations.mainToolbarBackground(frame.isActive) + customTitleBar?.let { + updateWinControlsTheme(panel = this, customTitleBar = it) + } + } + + override fun getAccessibleContext(): AccessibleContext { + if (accessibleContext == null) { + accessibleContext = AccessibleCustomHeader() + accessibleContext.accessibleName = UIBundle.message("frame.header.accessible.group.name") + } + return accessibleContext + } + + private inner class AccessibleCustomHeader : AccessibleJPanel() { + override fun getAccessibleRole() = AccessibilityUtils.GROUPED_ELEMENTS + } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/MenuFrameHeader.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/MenuFrameHeader.kt index 7573b72aa5b8..88f846678f93 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/MenuFrameHeader.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/MenuFrameHeader.kt @@ -52,7 +52,7 @@ internal class MenuFrameHeader(frame: JFrame, add(view, "left, growx, gapbottom 1") buttonPanes?.let { add(it.getView(), "right, gapbottom 1") } - setCustomFrameTopBorder({ myState != Frame.MAXIMIZED_VERT && myState != Frame.MAXIMIZED_BOTH }, {true}) + setCustomFrameTopBorder({ state != Frame.MAXIMIZED_VERT && state != Frame.MAXIMIZED_BOTH }, {true}) mainMenuUpdater = UISettingsListener { menuHolder.isVisible = UISettings.getInstance().showMainMenu @@ -66,7 +66,7 @@ internal class MenuFrameHeader(frame: JFrame, override fun updateActive() { super.updateActive() - headerTitle.setActive(myActive) + headerTitle.setActive(isActive) } override fun installListeners() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/toolbar/HeaderToolbarButtonLook.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/toolbar/HeaderToolbarButtonLook.kt index 14e3b8aa678d..7a4b7755b12b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/toolbar/HeaderToolbarButtonLook.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/toolbar/HeaderToolbarButtonLook.kt @@ -15,6 +15,7 @@ import com.intellij.util.ui.JBValue import com.intellij.util.ui.UIUtil import org.jetbrains.annotations.ApiStatus import java.awt.Color +import java.awt.Dimension import java.awt.Graphics import java.awt.Rectangle import java.awt.image.RGBImageFilter @@ -63,7 +64,12 @@ internal class HeaderToolbarButtonLook( override fun paintIcon(g: Graphics?, actionButton: ActionButtonComponent?, icon: Icon, x: Int, y: Int) { val scaledIcon = scaleIcon(adjustIconForHeader(icon)) - paintIconImpl(g, actionButton, scaledIcon, x, y) + val originalSize = Dimension(icon.iconWidth, icon.iconHeight) + val scaledSize = Dimension(scaledIcon.iconWidth, scaledIcon.iconHeight) + val scaledX = x - (scaledSize.width - originalSize.width) / 2 + val scaledY = y - (scaledSize.height - originalSize.height) / 2 + + paintIconImpl(g, actionButton, scaledIcon, scaledX, scaledY) } override fun paintDownArrow(g: Graphics?, actionButton: ActionButtonComponent?, originalIcon: Icon, arrowIcon: Icon) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/toolbar/ToolbarFrameHeader.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/toolbar/ToolbarFrameHeader.kt index b0d05bfca677..a9a1610816e6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/toolbar/ToolbarFrameHeader.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/toolbar/ToolbarFrameHeader.kt @@ -2,6 +2,7 @@ package com.intellij.openapi.wm.impl.customFrameDecorations.header.toolbar import com.intellij.ide.ProjectWindowCustomizerService +import com.intellij.ide.menu.ActionAwareIdeMenuBar import com.intellij.ide.ui.UISettings import com.intellij.ide.ui.UISettingsListener import com.intellij.ide.ui.customization.CustomActionsSchema @@ -187,14 +188,10 @@ internal class ToolbarFrameHeader(private val coroutineScope: CoroutineScope, val toolbar = withContext(Dispatchers.EDT) { toolbar?.removeComponentListener(contentResizeListener) toolbarPlaceholder.removeAll() - - val toolbar = MainToolbar(coroutineScope.childScope(), frame) - toolbar.layoutCallBack = { updateCustomTitleBar() } - toolbar + MainToolbar(coroutineScope = coroutineScope.childScope(), frame = frame, layoutCallBack = { updateCustomTitleBar() }) } toolbar.init(toolbarActionGroups, customTitleBar) withContext(Dispatchers.EDT) { - toolbar.isOpaque = false toolbar.addComponentListener(contentResizeListener) this@ToolbarFrameHeader.toolbar = toolbar toolbarHeaderTitle.updateBorders(0) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/headertoolbar/MainToolbar.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/headertoolbar/MainToolbar.kt index 59ffedd65c7f..7b6873daba61 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/headertoolbar/MainToolbar.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/headertoolbar/MainToolbar.kt @@ -14,6 +14,7 @@ import com.intellij.openapi.actionSystem.* import com.intellij.openapi.actionSystem.ex.ComboBoxAction import com.intellij.openapi.actionSystem.ex.ComboBoxAction.ComboBoxButton import com.intellij.openapi.actionSystem.ex.CustomComponentAction +import com.intellij.openapi.actionSystem.impl.ActionButton import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl import com.intellij.openapi.application.EDT import com.intellij.openapi.components.serviceAsync @@ -76,13 +77,20 @@ private class MenuButtonInToolbarMainToolbarFlavor(coroutineScope: CoroutineScop private object DefaultMainToolbarFlavor : MainToolbarFlavor -internal class MainToolbar(private val coroutineScope: CoroutineScope, frame: JFrame) : JPanel(HorizontalLayout(10)) { - var layoutCallBack: LayoutCallBack? = null +internal class MainToolbar constructor( + private val coroutineScope: CoroutineScope, + frame: JFrame, + isOpaque: Boolean = false, + background: Color? = JBUI.CurrentTheme.CustomFrameDecorations.mainToolbarBackground(true), + val layoutCallBack: LayoutCallBack? = null, +) : JPanel(HorizontalLayout(10)) { private val flavor: MainToolbarFlavor init { - updateBackground() - isOpaque = true + background?.let { + this.background = it + } + this.isOpaque = isOpaque flavor = if (IdeRootPane.isMenuButtonInToolbar) { MenuButtonInToolbarMainToolbarFlavor(headerContent = this, coroutineScope = coroutineScope, frame = frame) } @@ -92,10 +100,6 @@ internal class MainToolbar(private val coroutineScope: CoroutineScope, frame: JF ClientProperty.put(this, IdeBackgroundUtil.NO_BACKGROUND, true) } - fun updateBackground() { - background = JBUI.CurrentTheme.CustomFrameDecorations.mainToolbarBackground(true) - } - override fun getComponentGraphics(g: Graphics): Graphics = super.getComponentGraphics(IdeBackgroundUtil.getOriginalGraphics(g)) suspend fun init(actionGroups: List>, customTitleBar: WindowDecorations.CustomTitleBar? = null) { @@ -244,7 +248,7 @@ internal class MainToolbar(private val coroutineScope: CoroutineScope, frame: JF private fun createActionBar(group: ActionGroup, customizationGroup: ActionGroup?): MyActionToolbarImpl { val toolbar = MyActionToolbarImpl(group, layoutCallBack, customizationGroup) toolbar.setActionButtonBorder(JBUI.Borders.empty(mainToolbarButtonInsets())) - toolbar.setActionButtonBorder(2, 5) + toolbar.setActionButtonBorder(5, 5) toolbar.setCustomButtonLook(HeaderToolbarButtonLook()) toolbar.setMinimumButtonSize { ActionToolbar.experimentalToolbarMinimumButtonSize() } @@ -363,6 +367,8 @@ private class MyActionToolbarImpl(group: ActionGroup, adjustIcons(presentation) + (component as? ActionButton)?.let { button -> button.setMinimumButtonSize(ActionToolbar.experimentalToolbarMinimumButtonSize()) } + if (action is ComboBoxAction) { findComboButton(component)?.apply { margin = JBInsets.emptyInsets() diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.kt index 8d3bc911c512..27533a987a28 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.kt @@ -9,10 +9,10 @@ import com.intellij.ide.RecentProjectListActionProvider import com.intellij.ide.dnd.FileCopyPasteUtil import com.intellij.ide.impl.ProjectUtil import com.intellij.ide.lightEdit.LightEditServiceListener +import com.intellij.ide.menu.createMacMenuBar import com.intellij.ide.ui.LafManagerListener import com.intellij.notification.NotificationsManager import com.intellij.notification.impl.NotificationsManagerImpl -import com.intellij.openapi.Disposable import com.intellij.openapi.MnemonicHelper import com.intellij.openapi.actionSystem.* import com.intellij.openapi.application.ApplicationManager @@ -41,6 +41,7 @@ import com.intellij.ui.components.labels.ActionLink import com.intellij.ui.components.panels.NonOpaquePanel import com.intellij.ui.components.panels.VerticalLayout import com.intellij.ui.components.panels.Wrapper +import com.intellij.ui.mac.screenmenu.Menu import com.intellij.ui.mac.touchbar.Touchbar import com.intellij.ui.mac.touchbar.TouchbarActionCustomizations import com.intellij.ui.scale.JBUIScale @@ -52,7 +53,7 @@ import com.intellij.util.ui.StartupUiUtil import com.intellij.util.ui.UIUtil import com.intellij.util.ui.accessibility.AccessibleContextAccessor import com.intellij.util.ui.update.UiNotifyConnector -import kotlinx.coroutines.launch +import kotlinx.coroutines.* import net.miginfocom.swing.MigLayout import java.awt.* import java.awt.dnd.* @@ -68,17 +69,20 @@ import javax.swing.event.ListDataListener @Suppress("LeakingThis") open class FlatWelcomeFrame @JvmOverloads constructor( suggestedScreen: AbstractWelcomeScreen? = if (USE_TABBED_WELCOME_SCREEN) TabbedWelcomeScreen() else null -) : JFrame(), IdeFrame, Disposable, AccessibleContextAccessor { +) : JFrame(), IdeFrame, AccessibleContextAccessor { val screen: AbstractWelcomeScreen private val content: Wrapper private var balloonLayout: WelcomeBalloonLayoutImpl? private var isDisposed = false private var header: DefaultFrameHeader? = null + private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + companion object { @JvmField var USE_TABBED_WELCOME_SCREEN: Boolean = java.lang.Boolean.parseBoolean(System.getProperty("use.tabbed.welcome.screen", "true")) const val BOTTOM_PANEL: String = "BOTTOM_PANEL" + @JvmField val DEFAULT_HEIGHT: Int = if (USE_TABBED_WELCOME_SCREEN) 650 else 460 const val MAX_DEFAULT_WIDTH: Int = 800 @@ -113,9 +117,7 @@ open class FlatWelcomeFrame @JvmOverloads constructor( content.setContent(getCustomContentHolder(this, screen.welcomePanel, header!!)) } else { - if (USE_TABBED_WELCOME_SCREEN && SystemInfoRt.isMac) { - rootPane.jMenuBar = WelcomeFrameMenuBar(this) - } + createWelcomeMenuBar(this, coroutineScope) content.setContent(screen.welcomePanel) } val glassPane = IdeGlassPaneImpl(rootPane) @@ -126,16 +128,16 @@ open class FlatWelcomeFrame @JvmOverloads constructor( // at this point, window insets may be unavailable, so we need to resize the window when it is shown UiNotifyConnector.doWhenFirstShown(this, ::pack) val app = ApplicationManager.getApplication() - val connection = app.messageBus.connect(this) + val connection = app.messageBus.connect(coroutineScope) connection.subscribe(ProjectManager.TOPIC, object : ProjectManagerListener { @Suppress("OVERRIDE_DEPRECATION") override fun projectOpened(project: Project) { - Disposer.dispose(this@FlatWelcomeFrame) + dispose() } }) connection.subscribe(LightEditServiceListener.TOPIC, object : LightEditServiceListener { override fun lightEditWindowOpened(project: Project) { - Disposer.dispose(this@FlatWelcomeFrame) + dispose() } }) connection.subscribe(AppLifecycleListener.TOPIC, object : AppLifecycleListener { @@ -159,17 +161,26 @@ open class FlatWelcomeFrame @JvmOverloads constructor( setupCloseAction() MnemonicHelper.init(this) - Disposer.register(app, this) - UIUtil.decorateWindowHeader(getRootPane()) + ComponentUtil.decorateWindowHeader(getRootPane()) ToolbarService.getInstance().setTransparentTitleBar( window = this, rootPane = getRootPane(), - onDispose = { runnable -> Disposer.register(this) { runnable.run() } }, + onDispose = { runnable -> + coroutineScope.coroutineContext.job.invokeOnCompletion { + runnable.run() + } + }, ) app.invokeLater({ (NotificationsManager.getNotificationsManager() as NotificationsManagerImpl).dispatchEarlyNotifications() }, ModalityState.nonModal()) } + override fun removeNotify() { + super.removeNotify() + + coroutineScope.cancel() + } + protected open fun setupCloseAction() { WelcomeFrame.setupCloseAction(this) } @@ -183,9 +194,7 @@ open class FlatWelcomeFrame @JvmOverloads constructor( } } else { - if (USE_TABBED_WELCOME_SCREEN && SystemInfoRt.isMac) { - rootPane.jMenuBar = WelcomeFrameMenuBar(this) - } + createWelcomeMenuBar(this, coroutineScope) content.setContent(screen.welcomePanel) } if (USE_TABBED_WELCOME_SCREEN) { @@ -212,7 +221,7 @@ open class FlatWelcomeFrame @JvmOverloads constructor( size.width, size.height ) - UIUtil.decorateWindowHeader(getRootPane()) + ComponentUtil.decorateWindowHeader(getRootPane()) title = "" title = welcomeFrameTitle updateAppWindowIcon(this) @@ -226,6 +235,7 @@ open class FlatWelcomeFrame @JvmOverloads constructor( } override fun dispose() { + coroutineScope.cancel() if (isDisposed) { return } @@ -380,12 +390,13 @@ open class FlatWelcomeFrame @JvmOverloads constructor( return panel } - private fun createSettingsAndDocsPanel(frame: JFrame): JComponent { + private fun createSettingsAndDocsPanel(frame: FlatWelcomeFrame): JComponent { val panel: JPanel = NonOpaquePanel(BorderLayout()) val toolbar = NonOpaquePanel() toolbar.layout = BoxLayout(toolbar, BoxLayout.X_AXIS) toolbar.add(WelcomeScreenComponentFactory.createErrorsLink(this)) - toolbar.add(createEventsLink()) + toolbar.add(WelcomeScreenComponentFactory.createEventLink(IdeBundle.message("action.Events"), + ApplicationManager.getApplication().messageBus.connect(frame.coroutineScope))) toolbar.add(WelcomeScreenComponentFactory.createActionLink( frame, IdeBundle.message("action.Anonymous.text.configure"), @@ -393,16 +404,14 @@ open class FlatWelcomeFrame @JvmOverloads constructor( AllIcons.General.GearPlain, UIUtil.findComponentOfType(frame.rootPane, JList::class.java)) ) - toolbar.add(WelcomeScreenComponentFactory.createActionLink(frame, IdeBundle.message("action.GetHelp"), IdeActions.GROUP_WELCOME_SCREEN_DOC, null, null)) + toolbar.add( + WelcomeScreenComponentFactory.createActionLink(frame, IdeBundle.message("action.GetHelp"), IdeActions.GROUP_WELCOME_SCREEN_DOC, + null, null)) panel.add(toolbar, BorderLayout.EAST) panel.border = JBUI.Borders.empty(0, 0, 8, 11) return panel } - private fun createEventsLink(): Component { - return WelcomeScreenComponentFactory.createEventLink(IdeBundle.message("action.Events"), frame) - } - private fun createQuickStartActionPanel(): ActionPanel { val group = DefaultActionGroup() val quickStart = ActionManager.getInstance().getAction(IdeActions.GROUP_WELCOME_SCREEN_QUICKSTART) as ActionGroup @@ -474,10 +483,25 @@ open class FlatWelcomeFrame @JvmOverloads constructor( } } -@Suppress("DEPRECATION") -private class WelcomeFrameMenuBar(frame: JFrame) : IdeMenuBar(ApplicationManager.getApplication().coroutineScope.childScope(), frame) { - override suspend fun getMainMenuActionGroup(): ActionGroup { +private fun createWelcomeMenuBar(frame: JFrame, parentCoroutineScope: CoroutineScope) { + if (!FlatWelcomeFrame.USE_TABBED_WELCOME_SCREEN || !SystemInfoRt.isMac) { + return + } + + val mainMenuActionGroupProvider: suspend () -> ActionGroup = { val manager = serviceAsync() - return DefaultActionGroup(manager.getAction(IdeActions.GROUP_FILE), manager.getAction(IdeActions.GROUP_HELP_MENU)) + DefaultActionGroup(manager.getAction(IdeActions.GROUP_FILE), manager.getAction(IdeActions.GROUP_HELP_MENU)) + } + + if (Menu.isJbScreenMenuEnabled()) { + createMacMenuBar(coroutineScope = parentCoroutineScope.childScope(), + component = frame.rootPane, + frame = frame, + mainMenuActionGroupProvider = mainMenuActionGroupProvider) + } + else { + frame.rootPane.jMenuBar = object : IdeMenuBar(parentCoroutineScope.childScope(), frame) { + override suspend fun getMainMenuActionGroup(): ActionGroup = mainMenuActionGroupProvider() + } } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java index cbb4b39b6559..502b338d9b8c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java @@ -359,7 +359,7 @@ public class RecentProjectPanel extends JPanel { private Icon detectActionIcon(int rowIndex, boolean hovered) { if (isProjectInvalid(rowIndex)) { - return hovered ? AllIcons.Welcome.Project.RemoveHover : AllIcons.Welcome.Project.Remove; + return hovered ? AllIcons.Welcome.RecentProjects.RemoveHover : AllIcons.Welcome.RecentProjects.Remove; } return hovered ? AllIcons.Ide.Notification.GearHover : AllIcons.Ide.Notification.Gear; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/TreeWelcomeScreenLeftPanel.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/TreeWelcomeScreenLeftPanel.kt index 6effb9cd2edc..a1df6aea185f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/TreeWelcomeScreenLeftPanel.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/TreeWelcomeScreenLeftPanel.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.wm.impl.welcomeScreen import com.intellij.openapi.Disposable @@ -31,7 +31,7 @@ import javax.swing.event.TreeSelectionListener import javax.swing.tree.* import kotlin.collections.ArrayDeque -class TreeWelcomeScreenLeftPanel : WelcomeScreenLeftPanel { +internal class TreeWelcomeScreenLeftPanel : WelcomeScreenLeftPanel { private val root = DefaultMutableTreeNode() private val treeModel = DefaultTreeModel(root) private val tree: JTree = Tree(treeModel) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeScreenComponentFactory.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeScreenComponentFactory.java index f142868812b9..7cfa2cf4675f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeScreenComponentFactory.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeScreenComponentFactory.java @@ -1,12 +1,11 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.wm.impl.welcomeScreen; -import com.intellij.application.Topics; import com.intellij.diagnostic.IdeMessagePanel; import com.intellij.diagnostic.MessagePool; import com.intellij.icons.AllIcons; import com.intellij.ide.IdeBundle; -import com.intellij.ide.actions.AboutPopup; +import com.intellij.ide.actions.AboutDialog; import com.intellij.notification.NotificationType; import com.intellij.notification.impl.widget.IdeNotificationArea; import com.intellij.openapi.Disposable; @@ -14,6 +13,7 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl; import com.intellij.openapi.actionSystem.impl.MenuItemPresentationFactory; import com.intellij.openapi.application.ApplicationInfo; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.ide.CopyPasteManager; @@ -33,6 +33,7 @@ import com.intellij.ui.popup.PopupFactoryImpl; import com.intellij.ui.popup.list.SelectablePanel; import com.intellij.ui.scale.JBUIScale; import com.intellij.util.IconUtil; +import com.intellij.util.messages.SimpleMessageBusConnection; import com.intellij.util.ui.*; import com.intellij.util.ui.accessibility.AccessibleContextDelegate; import org.jetbrains.annotations.Nls; @@ -147,7 +148,7 @@ public final class WelcomeScreenComponentFactory { private static AnAction createCopyAboutAction() { return DumbAwareAction.create(e -> { - CopyPasteManager.getInstance().setContents(new StringSelection(AboutPopup.getAboutText())); + CopyPasteManager.getInstance().setContents(new StringSelection(new AboutDialog(null).getExtendedAboutText())); }); } @@ -280,7 +281,7 @@ public final class WelcomeScreenComponentFactory { * @deprecated use {@link NotificationEventAction} instead */ @Deprecated - public static @NotNull JComponent createEventLink(@NotNull @Nls String linkText, @NotNull Disposable parentDisposable) { + public static @NotNull JComponent createEventLink(@NotNull @Nls String linkText, @NotNull SimpleMessageBusConnection busConnection) { SelectablePanel selectablePanel = new SelectablePanel(); ActionLink actionLink = new ActionLink(linkText, getNotificationIcon(Collections.emptyList(), null), new DumbAwareAction() { private boolean hideListenerInstalled = false; @@ -299,7 +300,6 @@ public final class WelcomeScreenComponentFactory { } }); - JComponent panel = wrapActionLink(actionLink); selectablePanel.setLayout(new BorderLayout()); selectablePanel.add(panel); @@ -309,7 +309,7 @@ public final class WelcomeScreenComponentFactory { panel.setBorder(null); selectablePanel.setVisible(false); - Topics.subscribe(WelcomeBalloonLayoutImpl.BALLOON_NOTIFICATION_TOPIC, parentDisposable, types -> { + busConnection.subscribe(WelcomeBalloonLayoutImpl.BALLOON_NOTIFICATION_TOPIC, types -> { BalloonLayout balloonLayout = WelcomeFrame.getInstance().getBalloonLayout(); if (balloonLayout instanceof WelcomeBalloonLayoutImpl welcomeBalloonLayout) { if (welcomeBalloonLayout.getLocationComponent() == null) { @@ -385,7 +385,7 @@ public final class WelcomeScreenComponentFactory { @Deprecated public static @NotNull JPanel createNotificationPanel(@NotNull Disposable parentDisposable) { JComponent errorsLink = createErrorsLink(parentDisposable); - JComponent eventLink = createEventLink("", parentDisposable); + JComponent eventLink = createEventLink("", ApplicationManager.getApplication().getMessageBus().connect(parentDisposable)); JPanel panel = new NonOpaquePanel(); if (ExperimentalUI.isNewUI()) { panel.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0)); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/recentProjects/RecentProjectFilteringTree.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/recentProjects/RecentProjectFilteringTree.kt index 17587a9e7daa..73c844652daf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/recentProjects/RecentProjectFilteringTree.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/recentProjects/RecentProjectFilteringTree.kt @@ -415,8 +415,8 @@ internal class RecentProjectFilteringTree( AllIcons.Ide.Notification.GearHover) } else { - buttonViewModel.prepareActionsButton(projectActions, rowHovered, AllIcons.Welcome.Project.Remove, - AllIcons.Welcome.Project.RemoveHover) + buttonViewModel.prepareActionsButton(projectActions, rowHovered, AllIcons.Welcome.RecentProjects.Remove, + AllIcons.Welcome.RecentProjects.RemoveHover) } val toolTipPath = PathUtil.toSystemDependentName(item.projectPath) @@ -537,8 +537,8 @@ internal class RecentProjectFilteringTree( projectActionButton.isVisible = true // always visible } false -> { - buttonViewModel.prepareActionsButton(projectActionButton, rowHovered, AllIcons.Welcome.Project.Remove, - AllIcons.Welcome.Project.RemoveHover) + buttonViewModel.prepareActionsButton(projectActionButton, rowHovered, AllIcons.Welcome.RecentProjects.Remove, + AllIcons.Welcome.RecentProjects.RemoveHover) } else -> {} } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/recentProjects/RecentProjectTreeItem.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/recentProjects/RecentProjectTreeItem.kt index e8dfdd8337c7..e537f99cca40 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/recentProjects/RecentProjectTreeItem.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/recentProjects/RecentProjectTreeItem.kt @@ -11,7 +11,6 @@ import com.intellij.openapi.actionSystem.PlatformCoreDataKeys import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project import com.intellij.openapi.ui.Messages -import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.NlsSafe import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.wm.impl.welcomeScreen.FlatWelcomeFrame @@ -91,11 +90,8 @@ internal data class RecentProjectItem( } if (event.place == ActionPlaces.WELCOME_SCREEN) { - val welcomeFrame = SwingUtilities.getAncestorOfClass(FlatWelcomeFrame::class.java, - event.getData(PlatformCoreDataKeys.CONTEXT_COMPONENT)) as FlatWelcomeFrame? - if (welcomeFrame != null) { - Disposer.dispose(welcomeFrame) - } + (SwingUtilities.getAncestorOfClass(FlatWelcomeFrame::class.java, + event.getData(PlatformCoreDataKeys.CONTEXT_COMPONENT)) as FlatWelcomeFrame?)?.dispose() } val forceOpenInNewFrame = BitUtil.isSet(event.modifiers, ActionEvent.CTRL_MASK) || diff --git a/platform/platform-impl/src/com/intellij/toolWindow/MoreSquareStripeButton.kt b/platform/platform-impl/src/com/intellij/toolWindow/MoreSquareStripeButton.kt index eb188c0139f6..dd5136fdcbe1 100644 --- a/platform/platform-impl/src/com/intellij/toolWindow/MoreSquareStripeButton.kt +++ b/platform/platform-impl/src/com/intellij/toolWindow/MoreSquareStripeButton.kt @@ -63,8 +63,7 @@ internal class MoreSquareStripeButton(toolWindowToolbar: ToolWindowToolbar, } override fun isAvailable(project: Project): Boolean { - return super.isAvailable(project) && ToolWindowManagerEx.getInstanceEx( - project).getMoreButtonSide() == side + return super.isAvailable(project) && ToolWindowManagerEx.getInstanceEx(project).getMoreButtonSide() == side } override fun checkSkipPressForEvent(e: MouseEvent) = e.button != MouseEvent.BUTTON1 @@ -89,11 +88,16 @@ private fun createAction(toolWindowToolbar: ToolWindowToolbar): DumbAwareAction override fun actionPerformed(e: AnActionEvent) { val actions = ToolWindowsGroup.getToolWindowActions(e.project ?: return, true) val popup = JBPopupFactory.getInstance().createActionGroupPopup(null, DefaultActionGroup(actions), e.dataContext, null, true) - popup.setMinimumSize(Dimension(300, -1)) - - + val minimumPopupWidth = JBUI.scale(300) + popup.setMinimumSize(Dimension(minimumPopupWidth, -1)) val moreSquareStripeButton = toolWindowToolbar.moreButton - popup.show(RelativePoint(toolWindowToolbar, Point(toolWindowToolbar.width, moreSquareStripeButton.y))) + val x = if (toolWindowToolbar is ToolWindowLeftToolbar) { + toolWindowToolbar.width + } + else { + -minimumPopupWidth + } + popup.show(RelativePoint(toolWindowToolbar, Point(x, moreSquareStripeButton.y))) } override fun getActionUpdateThread() = ActionUpdateThread.EDT @@ -104,11 +108,7 @@ internal abstract class AbstractMoreSquareStripeButton(action: AnAction) : Abstr override fun update() { super.update() val project = dataContext.getData(CommonDataKeys.PROJECT) - if (project == null) { - return - } - - val available = isAvailable(project) + val available = project != null && isAvailable(project) myPresentation.isEnabledAndVisible = available isEnabled = available diff --git a/platform/platform-impl/src/com/intellij/ui/ShadowJava2DPainter.kt b/platform/platform-impl/src/com/intellij/ui/ShadowJava2DPainter.kt index c69aa9096323..96e91a5082dc 100644 --- a/platform/platform-impl/src/com/intellij/ui/ShadowJava2DPainter.kt +++ b/platform/platform-impl/src/com/intellij/ui/ShadowJava2DPainter.kt @@ -2,13 +2,15 @@ package com.intellij.ui import com.intellij.openapi.util.registry.Registry -import com.intellij.util.ui.JBDimension import com.intellij.util.ui.JBInsets import com.intellij.util.ui.JBUI -import java.awt.* +import java.awt.Color +import java.awt.GradientPaint +import java.awt.Graphics2D +import java.awt.Insets + private val DEF_INSETS = JBInsets(5) -private val DEF_SIZE = JBDimension(5, 5) private val DEF_COLOR = Gray._200.withAlpha(50) /** @@ -19,136 +21,84 @@ class ShadowJava2DPainter(private val uiKeyGroup: String, private val roundedCor companion object { fun enabled(): Boolean = Registry.`is`("ide.java2d.shadowEnabled", false) + + fun getInsets(uiKeyGroup: String): Insets = JBUI.insets("${uiKeyGroup}.Shadow.borderInsets", DEF_INSETS) } fun hideBottomSide() { hideBottomSide = true } - fun getInsets(): Insets = JBUI.insets("${uiKeyGroup}.Shadow.borderInsets", DEF_INSETS) + fun getInsets() = Companion.getInsets(uiKeyGroup) fun paintShadow(g: Graphics2D, x: Int, y: Int, width: Int, height: Int) { val insets = getInsets() - val topLeftSize = JBUI.size("${uiKeyGroup}.Shadow.topLeftSize", DEF_SIZE) - val topRightSize = JBUI.size("${uiKeyGroup}.Shadow.topRightSize", DEF_SIZE) - val bottomLeftSize = JBUI.size("${uiKeyGroup}.Shadow.bottomLeftSize", DEF_SIZE) - val bottomRightSize = JBUI.size("${uiKeyGroup}.Shadow.bottomRightSize", DEF_SIZE) - - setGradient(g, "top", 0, insets.top) - g.fillRect(x + topLeftSize.width, y, width - topLeftSize.width - topRightSize.width, insets.top) - - if (!hideBottomSide) { - setGradient(g, "bottom", 0, insets.bottom) - g.fillRect(x + bottomLeftSize.width, y + height - insets.bottom, width - bottomLeftSize.width - bottomRightSize.width, insets.bottom) - } - - setGradient(g, "left", insets.left, 0) - g.fillRect(x, y + topLeftSize.height, insets.left, height - topLeftSize.height - bottomLeftSize.height) - - setGradient(g, "right", insets.right, 0) - g.fillRect(x + width - insets.right, y + topRightSize.height, insets.right, height - topRightSize.height - bottomRightSize.height) + val xxLeft = x + insets.left + val yyTop = y + insets.top + val xxRight = x + width - insets.right + val yyBottom = y + height - insets.bottom + val widthLR = width - insets.left - insets.right + val heightTB = height - insets.top - insets.bottom if (roundedCorners) { - paintArcCorner(g, x, y, topLeftSize, true, true, "topLeft") - paintArcCorner(g, x + width - topRightSize.width, y, topRightSize, true, false, "topRight") + val size = JBUI.scale(6) + + g.color = getColor("topLeft", "1") + g.fillRect(x + insets.left, y + insets.top, size, size) + + g.color = getColor("topRight", "1") + g.fillRect(xxRight - size, y + insets.top, size, size) + if (!hideBottomSide) { - paintArcCorner(g, x + width - bottomRightSize.width, y + height - bottomRightSize.height, bottomRightSize, false, false, - "bottomRight") - paintArcCorner(g, x, y + height - bottomLeftSize.height, bottomLeftSize, false, true, "bottomLeft") + g.color = getColor("bottomRight", "1") + g.fillRect(xxRight - size, yyBottom - size, size, size) + + g.color = getColor("bottomLeft", "1") + g.fillRect(x + insets.left, yyBottom - size, size, size) } } - else { - paintPolygonCorner(g, x, y, width, height, insets, topLeftSize, true, true, "topLeft") - paintPolygonCorner(g, x, y, width, height, insets, topRightSize, true, false, "topRight") - if (!hideBottomSide) { - paintPolygonCorner(g, x, y, width, height, insets, bottomRightSize, false, false, "bottomRight") - paintPolygonCorner(g, x, y, width, height, insets, bottomLeftSize, false, true, "bottomLeft") - } + + setGradient(g, "top", "0", "1", xxLeft, y, xxLeft, yyTop) + g.fillRect(xxLeft, y, widthLR, insets.top) + + if (!hideBottomSide) { + setGradient(g, "bottom", "1", "0", xxLeft, yyBottom, xxLeft, y + height) + g.fillRect(xxLeft, yyBottom, widthLR, insets.bottom) + } + + setGradient(g, "left", "0", "1", x, yyTop, xxLeft, yyTop) + g.fillRect(x, yyTop, insets.left, heightTB) + + setGradient(g, "right", "1", "0", xxRight, yyTop, x + width, yyTop) + g.fillRect(xxRight, yyTop, insets.right, heightTB) + + drawCorner(g, "topLeft", x, y, insets.left, insets.top) + drawCorner(g, "topRight", xxRight, y, insets.right, insets.top) + + if (!hideBottomSide) { + drawCorner(g, "bottomRight", xxRight, yyBottom, insets.right, insets.bottom) + drawCorner(g, "bottomLeft", x, yyBottom, insets.left, insets.bottom) } if (borderColor != null) { + val one = JBUI.scale(1) g.color = borderColor - g.drawRect(x + insets.left - 1, y + insets.top - 1, x + width - insets.left - insets.right + 1, - y + height - insets.top - insets.bottom + 1) + g.drawRect(xxLeft - one, yyTop - one, widthLR + one, heightTB + one) } } - private fun paintArcCorner(g: Graphics2D, x: Int, y: Int, size: Dimension, top: Boolean, left: Boolean, side: String) { - val w2 = size.width * 2 - val h2 = size.height * 2 - - setGradient(g, side, size.width, size.height) - - if (top && left) { - g.fillArc(x, y, w2, h2, 90, 90) - } - else if (top/* && !left*/) { - g.fillArc(x - size.width, y, w2, h2, 0, 90) - } - else if (/*!top && */!left) { - g.fillArc(x - size.width, y - size.height, w2, h2, 0, -90) - } - else /*if (!top && left)*/ { - g.fillArc(x, y - size.height, w2, h2, -90, -90) + private fun drawCorner(g: Graphics2D, side: String, x: Int, y: Int, width: Int, height: Int) { + when (side) { + "topLeft" -> setGradient(g, side, "0", "1", x, y, x + width / 2, y + height / 2) + "topRight" -> setGradient(g, side, "0", "1", x + width, y, x + width / 2, y + height / 2) + "bottomRight" -> setGradient(g, side, "0", "1", x + width, y + height, x + width / 2, y + height / 2) + "bottomLeft" -> setGradient(g, side, "0", "1", x, y + height, x + width / 2, y + height / 2) } + g.fillRect(x, y, width, height) } - private fun paintPolygonCorner(g: Graphics2D, - x: Int, - y: Int, - width: Int, - height: Int, - insets: Insets, - sideSize: Dimension, - top: Boolean, - left: Boolean, - side: String) { - setGradient(g, side, sideSize.width, sideSize.height) - - val polygon = Polygon() - - if (top && left) { - polygon.addPoint(x, y + sideSize.height) - polygon.addPoint(x, y) - polygon.addPoint(x + sideSize.width, y) - polygon.addPoint(x + sideSize.width, y + insets.top) - polygon.addPoint(x + insets.left, y + insets.top) - polygon.addPoint(x + insets.left, y + sideSize.height) - polygon.addPoint(x, y + sideSize.height) - } - else if (top/* && !left*/) { - polygon.addPoint(x + width - sideSize.width, y) - polygon.addPoint(x + width, y) - polygon.addPoint(x + width, y + sideSize.height) - polygon.addPoint(x + width - insets.right, y + sideSize.height) - polygon.addPoint(x + width - insets.right, y + insets.top) - polygon.addPoint(x + width - sideSize.width, y + insets.top) - polygon.addPoint(x + width - sideSize.width, y) - } - else if (/*!top && */!left) { - polygon.addPoint(x + width - sideSize.width, y + height - insets.bottom) - polygon.addPoint(x + width - insets.right, y + height - insets.bottom) - polygon.addPoint(x + width - insets.right, y + height - sideSize.height) - polygon.addPoint(x + width, y + height - sideSize.height) - polygon.addPoint(x + width, y + height) - polygon.addPoint(x + width - sideSize.width, y + height) - polygon.addPoint(x + width - sideSize.width, y + height - insets.bottom) - } - else /*if (!top && left)*/ { - polygon.addPoint(x, y + height) - polygon.addPoint(x, y + height - sideSize.height) - polygon.addPoint(x + insets.left, y + height - sideSize.height) - polygon.addPoint(x + insets.left, y + height - insets.bottom) - polygon.addPoint(x + sideSize.width, y + height - insets.bottom) - polygon.addPoint(x + sideSize.width, y + height) - polygon.addPoint(x, y + height) - } - - g.fillPolygon(polygon) - } - - private fun setGradient(g: Graphics2D, sideKey: String, lengthX: Int, lengthY: Int) { - g.paint = GradientPaint(0f, 0f, getColor(sideKey, "0"), lengthX.toFloat(), lengthY.toFloat(), getColor(sideKey, "1"), true) + private fun setGradient(g: Graphics2D, sideKey: String, gKey0: String, gKey1: String, x0: Int, y0: Int, x1: Int, y1: Int) { + g.paint = GradientPaint(x0.toFloat(), y0.toFloat(), getColor(sideKey, gKey0), x1.toFloat(), y1.toFloat(), getColor(sideKey, gKey1)) } private fun getColor(sideKey: String, gradientKey: String): Color { diff --git a/platform/platform-impl/src/com/intellij/ui/ToolbarServiceImpl.java b/platform/platform-impl/src/com/intellij/ui/ToolbarServiceImpl.java deleted file mode 100644 index 7596d3def95f..000000000000 --- a/platform/platform-impl/src/com/intellij/ui/ToolbarServiceImpl.java +++ /dev/null @@ -1,159 +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 com.intellij.ui; - -import com.intellij.openapi.util.SystemInfoRt; -import com.intellij.ui.paint.LinePainter2D; -import com.intellij.util.ui.JBInsets; -import com.intellij.util.ui.JBUI; -import com.intellij.util.ui.UIUtil; -import kotlin.Unit; -import kotlin.jvm.functions.Function0; -import kotlin.jvm.functions.Function1; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import javax.swing.border.AbstractBorder; -import javax.swing.border.Border; -import java.awt.*; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.beans.PropertyChangeListener; - -public class ToolbarServiceImpl implements ToolbarService { - @Override - public void setCustomTitleBar(@NotNull Window window, @NotNull JRootPane rootPane, @NotNull Function1 onDispose) { - if (SystemInfoRt.isMac) { - if (ExperimentalUI.isNewUI()) { - setCustomTitleForToolbar(window, rootPane, onDispose); - } - else { - setTransparentTitleBar(window, rootPane, onDispose); - } - } - } - - @Override - public void setTransparentTitleBar(@NotNull Window window, - @NotNull JRootPane rootPane, - @Nullable Function0 handlerProvider, - @NotNull Function1 onDispose) { - if (!SystemInfoRt.isMac) { - return; - } - - FullScreenSupport handler = handlerProvider == null ? null : handlerProvider.invoke(); - if (handler != null) { - handler.addListener(window); - } - JBInsets topWindowInset = JBUI.insetsTop(UIUtil.getTransparentTitleBarHeight(rootPane)); - AbstractBorder customBorder = new AbstractBorder() { - @Override - public Insets getBorderInsets(Component c) { - if (handler != null && handler.isFullScreen()) { - return JBInsets.emptyInsets(); - } - return topWindowInset; - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - if (handler != null && handler.isFullScreen()) { - return; - } - Graphics2D graphics = (Graphics2D)g.create(); - try { - Rectangle headerRectangle = new Rectangle(0, 0, c.getWidth(), topWindowInset.top); - graphics.setColor(UIUtil.getPanelBackground()); - graphics.fill(headerRectangle); - if (window instanceof RootPaneContainer) { - JRootPane pane = ((RootPaneContainer)window).getRootPane(); - if (pane == null || pane.getClientProperty(UIUtil.NO_BORDER_UNDER_WINDOW_TITLE_KEY) == Boolean.FALSE) { - graphics.setColor(JBUI.CurrentTheme.CustomFrameDecorations.separatorForeground()); - LinePainter2D.paint(graphics, 0, topWindowInset.top - 1, c.getWidth(), topWindowInset.top - 1, - LinePainter2D.StrokeType.INSIDE, 1); - } - } - Color color = window.isActive() ? JBColor.black : JBColor.gray; - graphics.setColor(color); - } - finally { - graphics.dispose(); - } - } - }; - if (handler != null) { - Function1 onDisposeOld = onDispose; - onDispose = runnable -> { - onDisposeOld.invoke((Runnable)() -> { - runnable.run(); - handler.removeListener(window); - }); - return Unit.INSTANCE; - }; - } - doSetCustomTitleBar(window, rootPane, onDispose, customBorder); - } - - private static void setCustomTitleForToolbar(@NotNull Window window, - @NotNull JRootPane rootPane, - Function1 onDispose) { - JBInsets topWindowInset = JBUI.insetsTop(UIUtil.getTransparentTitleBarHeight(rootPane)); - AbstractBorder customBorder = new AbstractBorder() { - @Override - public Insets getBorderInsets(Component c) { - return topWindowInset; - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Graphics2D graphics = (Graphics2D)g.create(); - try { - Rectangle headerRectangle = new Rectangle(0, 0, c.getWidth(), topWindowInset.top); - Color color = UIManager.getColor("MainToolbar.background"); - graphics.setColor(color != null ? color : UIUtil.getPanelBackground()); - graphics.fill(headerRectangle); - } - finally { - graphics.dispose(); - } - } - }; - rootPane.putClientProperty("apple.awt.windowTitleVisible", false); - doSetCustomTitleBar(window, rootPane, onDispose, customBorder); - } - - private static void doSetCustomTitleBar(@NotNull Window window, - @NotNull JRootPane rootPane, - Function1 onDispose, - @NotNull Border customBorder) { - - rootPane.putClientProperty("apple.awt.fullWindowContent", true); - rootPane.putClientProperty("apple.awt.transparentTitleBar", true); - - // Use standard properties starting jdk 17 - //if (Runtime.version().feature() >= 17) { - //rootPane.putClientProperty("apple.awt.windowTitleVisible", false); - //} - - rootPane.setBorder(customBorder); - - WindowAdapter windowAdapter = new WindowAdapter() { - @Override - public void windowActivated(WindowEvent e) { - rootPane.repaint(); - } - - @Override - public void windowDeactivated(WindowEvent e) { - rootPane.repaint(); - } - }; - PropertyChangeListener propertyChangeListener = e -> rootPane.repaint(); - window.addPropertyChangeListener("title", propertyChangeListener); - onDispose.invoke((Runnable)() -> { - window.removeWindowListener(windowAdapter); - window.removePropertyChangeListener("title", propertyChangeListener); - }); - } -} diff --git a/platform/platform-impl/src/com/intellij/ui/ToolbarServiceImpl.kt b/platform/platform-impl/src/com/intellij/ui/ToolbarServiceImpl.kt new file mode 100644 index 000000000000..30977a8378d7 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ui/ToolbarServiceImpl.kt @@ -0,0 +1,119 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.ui + +import com.intellij.openapi.util.SystemInfoRt +import com.intellij.ui.paint.LinePainter2D +import com.intellij.util.ui.JBInsets +import com.intellij.util.ui.JBUI +import com.intellij.util.ui.UIUtil +import java.awt.* +import java.beans.PropertyChangeListener +import javax.swing.JRootPane +import javax.swing.RootPaneContainer +import javax.swing.UIManager +import javax.swing.border.AbstractBorder +import javax.swing.border.Border + +open class ToolbarServiceImpl : ToolbarService { + override fun setCustomTitleBar(window: Window, rootPane: JRootPane, onDispose: (Runnable) -> Unit) { + if (!SystemInfoRt.isMac) { + return + } + else if (ExperimentalUI.isNewUI()) { + setCustomTitleForToolbar(window = window, rootPane = rootPane, onDispose = onDispose) + } + else { + setTransparentTitleBar(window = window, rootPane = rootPane, onDispose = onDispose) + } + } + + override fun setTransparentTitleBar(window: Window, + rootPane: JRootPane, + handlerProvider: (() -> FullScreenSupport)?, + onDispose: (Runnable) -> Unit) { + @Suppress("NAME_SHADOWING") + var onDispose = onDispose + if (!SystemInfoRt.isMac) { + return + } + + val handler = handlerProvider?.invoke() + handler?.addListener(window) + + val topWindowInset = JBUI.insetsTop(UIUtil.getTransparentTitleBarHeight(rootPane)) + val customBorder = object : AbstractBorder() { + override fun getBorderInsets(c: Component): Insets { + return if (handler != null && handler.isFullScreen()) JBInsets.emptyInsets() else topWindowInset + } + + override fun paintBorder(c: Component, g: Graphics, x: Int, y: Int, width: Int, height: Int) { + if (handler != null && handler.isFullScreen()) { + return + } + + val graphics = g.create() as Graphics2D + try { + val headerRectangle = Rectangle(0, 0, c.width, topWindowInset.top) + graphics.color = JBColor.PanelBackground + graphics.fill(headerRectangle) + if (window is RootPaneContainer) { + val pane = (window as RootPaneContainer).rootPane + if (pane == null || pane.getClientProperty(UIUtil.NO_BORDER_UNDER_WINDOW_TITLE_KEY) == false) { + graphics.color = JBUI.CurrentTheme.CustomFrameDecorations.separatorForeground() + LinePainter2D.paint(graphics, 0.0, (topWindowInset.top - 1).toDouble(), c.width.toDouble(), + (topWindowInset.top - 1).toDouble(), + LinePainter2D.StrokeType.INSIDE, 1.0) + } + } + val color = if (window.isActive) JBColor.black else JBColor.gray + graphics.color = color + } + finally { + graphics.dispose() + } + } + } + if (handler != null) { + val onDisposeOld = onDispose + onDispose = { runnable -> + onDisposeOld { + runnable.run() + handler.removeListener(window) + } + } + } + doSetCustomTitleBar(window = window, rootPane = rootPane, onDispose = onDispose, customBorder = customBorder) + } +} + +private fun setCustomTitleForToolbar(window: Window, rootPane: JRootPane, onDispose: (Runnable) -> Unit) { + val topWindowInset = JBUI.insetsTop(UIUtil.getTransparentTitleBarHeight(rootPane)) + val customBorder = object : AbstractBorder() { + override fun getBorderInsets(c: Component): Insets = topWindowInset + + override fun paintBorder(c: Component, g: Graphics, x: Int, y: Int, width: Int, height: Int) { + val graphics = g.create() as Graphics2D + try { + val headerRectangle = Rectangle(0, 0, c.width, topWindowInset.top) + val color = UIManager.getColor("MainToolbar.background") + graphics.color = color ?: UIUtil.getPanelBackground() + graphics.fill(headerRectangle) + } + finally { + graphics.dispose() + } + } + } + rootPane.putClientProperty("apple.awt.windowTitleVisible", false) + doSetCustomTitleBar(window = window, rootPane = rootPane, onDispose = onDispose, customBorder = customBorder) +} + +private fun doSetCustomTitleBar(window: Window, rootPane: JRootPane, onDispose: (Runnable) -> Unit, customBorder: Border) { + rootPane.putClientProperty("apple.awt.fullWindowContent", true) + rootPane.putClientProperty("apple.awt.transparentTitleBar", true) + + rootPane.setBorder(customBorder) + val propertyChangeListener = PropertyChangeListener { rootPane.repaint() } + window.addPropertyChangeListener("title", propertyChangeListener) + onDispose { window.removePropertyChangeListener("title", propertyChangeListener) } +} diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacGestureSupportForMouseShortcutPanel.java b/platform/platform-impl/src/com/intellij/ui/mac/MacGestureSupportForMouseShortcutPanel.java index 089aae4006ef..39cf55549556 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacGestureSupportForMouseShortcutPanel.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacGestureSupportForMouseShortcutPanel.java @@ -10,25 +10,24 @@ import com.apple.eawt.event.GestureUtilities; import com.apple.eawt.event.PressureEvent; import com.apple.eawt.event.PressureListener; import com.intellij.openapi.actionSystem.PressureShortcut; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.keymap.impl.ui.MouseShortcutPanel; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.util.lang.JavaVersion; public final class MacGestureSupportForMouseShortcutPanel { public MacGestureSupportForMouseShortcutPanel(MouseShortcutPanel panel, Runnable runnable) { - //todo[kb]: return pressure listener to jbr17 - if (SystemInfo.isJetBrainsJvm && JavaVersion.current().isAtLeast(17)) { - return; - } - GestureListener pressureListener = new PressureListener() { - @Override - public void pressure(PressureEvent e) { - if (e.getStage() == 2) { - panel.setShortcut(new PressureShortcut(e.getStage())); - runnable.run(); + try { + GestureListener pressureListener = new PressureListener() { + @Override + public void pressure(PressureEvent e) { + if (e.getStage() == 2) { + panel.setShortcut(new PressureShortcut(e.getStage())); + runnable.run(); + } } - } - }; - GestureUtilities.addGestureListenerTo(panel, pressureListener); + }; + GestureUtilities.addGestureListenerTo(panel, pressureListener); + } catch (Throwable t) { + Logger.getInstance(MacGestureSupportForMouseShortcutPanel.class).warn("macOS gesture support failed", t); + } } } diff --git a/platform/platform-impl/src/com/intellij/ui/mac/WindowTabsComponent.java b/platform/platform-impl/src/com/intellij/ui/mac/WindowTabsComponent.java index 74540ce85607..f161ff19901c 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/WindowTabsComponent.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/WindowTabsComponent.java @@ -14,6 +14,7 @@ import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.wm.IdeGlassPaneUtil; import com.intellij.openapi.wm.impl.IdeFrameImpl; import com.intellij.ui.*; @@ -188,14 +189,14 @@ public final class WindowTabsComponent extends JBTabsImpl { }, BorderLayout.WEST); myActionPanel.setBorder(JBUI.Borders.emptyLeft(6)); - myActionPanel.setVisible(false); + myActionPanel.setVisible(!showCloseActionOnHover()); } } @Override protected void setHovered(boolean value) { super.setHovered(value); - myActionPanel.setVisible(value || getInfo() == myTabs.getPopupInfo()); + myActionPanel.setVisible(!showCloseActionOnHover() || value || getInfo() == myTabs.getPopupInfo()); } @Override @@ -216,7 +217,7 @@ public final class WindowTabsComponent extends JBTabsImpl { private void handle() { popup.removePopupMenuListener(this); - myActionPanel.setVisible(isHovered()); + myActionPanel.setVisible(!showCloseActionOnHover() || isHovered()); } }); } @@ -234,6 +235,10 @@ public final class WindowTabsComponent extends JBTabsImpl { }; } + private static boolean showCloseActionOnHover() { + return Registry.is("ide.mac.os.wintabs.show.closeaction.on.hover", true); + } + @Override protected @NotNull TabPainterAdapter createTabPainterAdapter() { return new TabPainterAdapter() { diff --git a/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java b/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java index adebb7090f13..2025dc02c97c 100644 --- a/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java +++ b/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.util; import com.intellij.openapi.options.advanced.AdvancedSettings; @@ -87,7 +87,7 @@ public final class IJSwingUtilities { if (c instanceof RootPaneContainer) { JRootPane rootPane = ((RootPaneContainer)c).getRootPane(); if (rootPane != null) { - UIUtil.decorateWindowHeader(rootPane); + ComponentUtil.decorateWindowHeader(rootPane); } } diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 97de8802c987..ac4a43765275 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -856,6 +856,8 @@ action.Inline.text=I_nline... action.Inline.description=Inline the selected method or variable action.InsertInlineCompletionAction.text=Insert inline proposal action.InsertInlineCompletionAction.description=Insert current inline completion proposal +action.CallInlineCompletionAction.text=Call inline completion +action.CallInlineCompletionAction.description=Generate suggestion for current cursor position and show as inline action.AnonymousToInner.text=Convert Anon_ymous to Inner... action.AnonymousToInner.description=Convert anonymous class into an inner class action.EncapsulateFields.text=_Encapsulate Fields... @@ -1400,8 +1402,11 @@ action.MethodHierarchy.OverrideMethodAction.text=Override Method action.MethodHierarchy.OverrideMethodAction.description=Override Method (from Method Hierarchy) action.Vcs.MoveChangedLinesToChangelist.text=Move Lines to Another Changelist... action.Vcs.MoveChangedLinesToChangelist.description=Move changes in selected lines to another changelist -action.Vcs.Diff.IncludeChangedLinesIntoCommit.text=Include Selected Lines into Commit -action.Vcs.Diff.ExcludeChangedLinesFromCommit.text=Exclude Selected Lines from Commit +action.Vcs.Diff.IncludeChangedLinesIntoCommit.text=Spit Chunks and Include Selected Lines into Commit +action.Vcs.Diff.ExcludeChangedLinesFromCommit.text=Spit Chunks and Exclude Selected Lines from Commit +# '{0} == 0' is used when the chunks are already split +action.Vcs.Diff.IncludeChangedLinesIntoCommit.template.text={0,choice,0#|1#Spit Chunk and |2#Spit Chunks and }Include {1,choice,0#Current Line|2#Selected Lines} into Commit +action.Vcs.Diff.ExcludeChangedLinesFromCommit.template.text={0,choice,0#|1#Spit Chunk and |2#Spit Chunks and }Exclude {1,choice,0#Current Line|2#Selected Lines} from Commit action.Vcs.Diff.ShowDiffInEditorTab.text=Show Diff in Editor Tab action.Vcs.Diff.ShowDiffInNewWindow.text=Show Diff in Separate Window action.Vcs.Diff.ShowCombinedDiff.text=Show Combined Diff @@ -2185,7 +2190,6 @@ action.ToggleUiInspectorHierarchyTrace.text.disable=Disable UI Inspector Hierarc action.GrayFilterConfig.text=&GrayFilter action.TextGrayFilterConfig.text=&TextGrayFilter action.ShowSplash.text=Show Splash -action.ShowAboutPopupInDebugModeAction.text=Show About Popup in Debug Mode action.ValidationTest.text=Validation Dialog Test action.MacMessagesTest.text=Test Mac Messages action.ColorBlindnessTest.text=Test ColorBlindness @@ -2789,4 +2793,6 @@ action.addQuickAction.BackForward.text=Back / Forward action.addQuickAction.UndoRedo.text=Undo / Redo action.ColoredHeaderAction.text=Use Project Colors in Toolbar -action.ChangeMainToolbarColor.text=Change Toolbar Color... \ No newline at end of file +action.ChangeMainToolbarColor.text=Change Toolbar Color... + +group.Internal.WorkspaceModel.text=Workspace Model diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index d32cfda1fb3c..1032fe0370bf 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -1556,7 +1556,7 @@ id="inline.completion.escape" action="EditorEscape" implementationClass="com.intellij.codeInsight.inline.completion.EscapeInlineCompletionHandler" order="before hide-hints"/> - + @@ -1702,7 +1702,7 @@ - + + + diff --git a/platform/platform-resources/src/idea/ApplicationInfo.xsd b/platform/platform-resources/src/idea/ApplicationInfo.xsd index 2a353c0f4e05..3150ad544f4c 100644 --- a/platform/platform-resources/src/idea/ApplicationInfo.xsd +++ b/platform/platform-resources/src/idea/ApplicationInfo.xsd @@ -316,8 +316,9 @@ - If 'true' information about licensee will be shown on the splash screen. + Deprecated: information about licensee is never shown on the splash screen (for faster loading) + deprecated diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 8cb620243823..ef650b4fe379 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -484,7 +484,7 @@ - + - + @@ -1730,7 +1730,7 @@ - + @@ -1748,5 +1748,9 @@ + + + + diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index acb9fcfcec84..a8eacc70b20b 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -1209,7 +1209,7 @@ - + @@ -1277,7 +1277,6 @@ - diff --git a/platform/platform-resources/src/themes/expUI/expUI_dark.theme.json b/platform/platform-resources/src/themes/expUI/expUI_dark.theme.json index 53808fa5d472..4b1dcc8ba74f 100644 --- a/platform/platform-resources/src/themes/expUI/expUI_dark.theme.json +++ b/platform/platform-resources/src/themes/expUI/expUI_dark.theme.json @@ -319,10 +319,6 @@ "Ide.Shadow": { "borderInsets": "6,10,14,10", - "topLeftSize": "18,14", - "topRightSize": "18,14", - "bottomLeftSize": "18,22", - "bottomRightSize": "18,22", "top0Color": "#1C1C1C92", "top1Color": "#14141492", "bottom0Color": "#10101092", @@ -342,10 +338,6 @@ }, "Notification.Shadow": { "borderInsets": "6,10,6,10", - "topLeftSize": "18,14", - "topRightSize": "18,14", - "bottomLeftSize": "18,22", - "bottomRightSize": "18,22", "top0Color": "#1C1C1C32", "top1Color": "#14141432", "bottom0Color": "#10101032", diff --git a/platform/platform-resources/src/themes/expUI/expUI_light.theme.json b/platform/platform-resources/src/themes/expUI/expUI_light.theme.json index ecc78c7f1703..21803b4b8949 100644 --- a/platform/platform-resources/src/themes/expUI/expUI_light.theme.json +++ b/platform/platform-resources/src/themes/expUI/expUI_light.theme.json @@ -343,50 +343,42 @@ }, "Ide.Shadow": { - "borderInsets": "6,10,14,10", - "topLeftSize": "18,14", - "topRightSize": "18,14", - "bottomLeftSize": "18,22", - "bottomRightSize": "18,22", - "top0Color": "#FCFCFC92", - "top1Color": "#F4F4F492", - "bottom0Color": "#F0F0F092", - "bottom1Color": "#FDFDFD92", - "left0Color": "#FDFDFD92", - "left1Color": "#F0F0F092", - "right0Color": "#F0F0F092", - "right1Color": "#FDFDFD92", - "topLeft0Color": "#FDFDFD92", - "topLeft1Color": "#F0F0F092", - "topRight0Color": "#F4F4F492", - "topRight1Color": "#FDFDFD92", - "bottomLeft0Color": "#F3F3F392", - "bottomLeft1Color": "#FCFCFC92", - "bottomRight0Color": "#F0F0F092", - "bottomRight1Color": "#FCFCFC92" + "borderInsets": "10,10,10,10", + "top0Color": "#FF0000", + "top1Color": "#00FF00", + "bottom0Color": "#FF0000", + "bottom1Color": "#00FF00", + "left0Color": "#FF0000", + "left1Color": "#00FF00", + "right0Color": "#FF0000", + "right1Color": "#00FF00", + "topLeft0Color": "#FF0000", + "topLeft1Color": "#00FF00", + "topRight0Color": "#FF0000", + "topRight1Color": "#00FF00", + "bottomLeft0Color": "#FF0000", + "bottomLeft1Color": "#00FF00", + "bottomRight0Color": "#FF0000", + "bottomRight1Color": "#00FF00" }, "Notification.Shadow": { - "borderInsets": "6,10,6,10", - "topLeftSize": "18,14", - "topRightSize": "18,14", - "bottomLeftSize": "18,22", - "bottomRightSize": "18,22", - "top0Color": "#FCFCFC32", - "top1Color": "#F4F4F432", - "bottom0Color": "#F0F0F032", - "bottom1Color": "#FDFDFD32", - "left0Color": "#FDFDFD32", - "left1Color": "#F0F0F032", - "right0Color": "#F0F0F032", - "right1Color": "#FDFDFD32", - "topLeft0Color": "#FDFDFD32", - "topLeft1Color": "#F0F0F032", - "topRight0Color": "#F4F4F432", - "topRight1Color": "#FDFDFD32", - "bottomLeft0Color": "#F3F3F332", - "bottomLeft1Color": "#FCFCFC32", - "bottomRight0Color": "#F0F0F032", - "bottomRight1Color": "#FCFCFC32" + "borderInsets": "10,10,10,10", + "top0Color": "#FF0000", + "top1Color": "#00FF00", + "bottom0Color": "#FF0000", + "bottom1Color": "#00FF00", + "left0Color": "#FF0000", + "left1Color": "#00FF00", + "right0Color": "#FF0000", + "right1Color": "#00FF00", + "topLeft0Color": "#FF0000", + "topLeft1Color": "#00FF00", + "topRight0Color": "#FF0000", + "topRight1Color": "#00FF00", + "bottomLeft0Color": "#FF0000", + "bottomLeft1Color": "#00FF00", + "bottomRight0Color": "#FF0000", + "bottomRight1Color": "#00FF00" }, "Notification": { diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/impl/FileTypesTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/impl/FileTypesTest.java index cc041f84231e..5cbe8c7cf4b0 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/impl/FileTypesTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/impl/FileTypesTest.java @@ -39,6 +39,7 @@ import com.intellij.openapi.vfs.PersistentFSConstants; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.encoding.EncodingProjectManager; import com.intellij.openapi.vfs.encoding.EncodingProjectManagerImpl; +import com.intellij.openapi.vfs.newvfs.ManagingFS; import com.intellij.openapi.vfs.newvfs.impl.CachedFileType; import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile; import com.intellij.psi.PsiBinaryFile; @@ -53,6 +54,7 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.PatternUtil; import com.intellij.util.ThrowableRunnable; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.keyFMap.KeyFMap; import com.intellij.util.ui.UIUtil; import org.intellij.lang.annotations.Language; import org.jdom.Element; @@ -206,6 +208,22 @@ public class FileTypesTest extends HeavyPlatformTestCase { assertTrue(myFileTypeManager.isFileIgnored(fileName)); } + public void testRedetectionDoesntRewriteAttributes() throws IOException { + File dir = createTempDirectory(); + File file = FileUtil.createTempFile(dir, "x", "xxx_xx_xx", true); + VirtualFile virtualFile = getVirtualFile(file); + assertNotNull(virtualFile); + assertEquals(DetectedByContentFileType.INSTANCE, getFileType(virtualFile)); + int modificationCount = ManagingFS.getInstance().getModificationCount(); + virtualFile.set(KeyFMap.EMPTY_MAP); + WriteAction.run(() -> { + CachedFileType.clearCache(); + }); + assertEquals(DetectedByContentFileType.INSTANCE, getFileType(virtualFile)); + int modificationCountAfterRedetection = ManagingFS.getInstance().getModificationCount(); + assertEquals(modificationCount, modificationCountAfterRedetection); + } + public void testAutoDetected() throws IOException { File dir = createTempDirectory(); File file = FileUtil.createTempFile(dir, "x", "xxx_xx_xx", true); diff --git a/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleDependencyIndexImpl.kt b/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleDependencyIndexImpl.kt index 621b55f35377..8e0cf20607f7 100644 --- a/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleDependencyIndexImpl.kt +++ b/platform/projectModel-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleDependencyIndexImpl.kt @@ -14,17 +14,18 @@ import com.intellij.openapi.roots.ex.ProjectRootManagerEx import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.roots.libraries.LibraryTable import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar +import com.intellij.platform.backend.workspace.WorkspaceModel import com.intellij.platform.workspace.jps.entities.* +import com.intellij.platform.workspace.jps.serialization.impl.LibraryNameGenerator +import com.intellij.platform.workspace.storage.EntityChange +import com.intellij.platform.workspace.storage.VersionedStorageChange +import com.intellij.platform.workspace.storage.orderToRemoveReplaceAdd import com.intellij.util.EventDispatcher import com.intellij.util.containers.BidirectionalMultiMap import com.intellij.util.containers.MultiMap -import com.intellij.platform.backend.workspace.WorkspaceModel -import com.intellij.platform.workspace.jps.serialization.impl.LibraryNameGenerator import com.intellij.workspaceModel.ide.legacyBridge.ModifiableRootModelBridge import com.intellij.workspaceModel.ide.legacyBridge.ModuleDependencyIndex import com.intellij.workspaceModel.ide.legacyBridge.ModuleDependencyListener -import com.intellij.platform.workspace.storage.VersionedStorageChange -import com.intellij.platform.workspace.storage.orderToRemoveReplaceAdd import java.util.function.Supplier class ModuleDependencyIndexImpl(private val project: Project): ModuleDependencyIndex, Disposable { @@ -52,9 +53,11 @@ class ModuleDependencyIndexImpl(private val project: Project): ModuleDependencyI } override fun setupTrackedLibrariesAndJdks() { + ApplicationManager.getApplication().assertWriteAccessAllowed() + LOG.debug { "Add tracked global libraries and SDK for all modules" } val currentStorage = WorkspaceModel.getInstance(project).currentSnapshot for (moduleEntity in currentStorage.entities(ModuleEntity::class.java)) { - addTrackedLibraryAndJdkFromEntity(moduleEntity) + addTrackedLibrariesAndSdks(moduleEntity.dependencies, moduleEntity) } } @@ -80,16 +83,29 @@ class ModuleDependencyIndexImpl(private val project: Project): ModuleDependencyI // Roots changed event should be fired for the global libraries linked with module val moduleChanges = event.getChanges(ModuleEntity::class.java).orderToRemoveReplaceAdd() for (change in moduleChanges) { - change.oldEntity?.let { removeTrackedLibrariesAndJdkFromEntity(it) } - change.newEntity?.let { addTrackedLibraryAndJdkFromEntity(it) } + when (change) { + is EntityChange.Added -> { + LOG.debug { "Add tracked global libraries and SDK from ${change.entity.name}" } + addTrackedLibrariesAndSdks(change.entity.dependencies, change.entity) + } + is EntityChange.Removed -> { + LOG.debug { "Removed tracked global libraries and SDK from ${change.entity.name}" } + removeTrackedLibrariesAndSdks(change.entity.dependencies, change.entity) + } + is EntityChange.Replaced -> { + val removedDependencies = change.oldEntity.dependencies - change.newEntity.dependencies.toSet() + val addedDependencies = change.newEntity.dependencies - change.oldEntity.dependencies.toSet() + LOG.debug { "Update tracked global libraries and SDK for ${change.newEntity.name}: ${removedDependencies.size} removed, ${addedDependencies.size} added" } + removeTrackedLibrariesAndSdks(removedDependencies, change.oldEntity) + addTrackedLibrariesAndSdks(addedDependencies, change.newEntity) + } + } } } - private fun addTrackedLibraryAndJdkFromEntity(moduleEntity: ModuleEntity) { - ApplicationManager.getApplication().assertWriteAccessAllowed() - LOG.debug { "Add tracked global libraries and JDK from ${moduleEntity.name}" } + private fun addTrackedLibrariesAndSdks(dependencies: List, moduleEntity: ModuleEntity) { val libraryTablesRegistrar = LibraryTablesRegistrar.getInstance() - moduleEntity.dependencies.forEach { + dependencies.forEach { when { it is ModuleDependencyItem.Exportable.LibraryDependency && it.library.tableId !is LibraryTableId.ModuleLibraryTableId -> { val libraryName = it.library.name @@ -105,10 +121,9 @@ class ModuleDependencyIndexImpl(private val project: Project): ModuleDependencyI } } - private fun removeTrackedLibrariesAndJdkFromEntity(moduleEntity: ModuleEntity) { - LOG.debug { "Removed tracked global libraries and JDK from ${moduleEntity.name}" } + private fun removeTrackedLibrariesAndSdks(dependencies: List, moduleEntity: ModuleEntity) { val libraryTablesRegistrar = LibraryTablesRegistrar.getInstance() - moduleEntity.dependencies.forEach { + dependencies.forEach { when { it is ModuleDependencyItem.Exportable.LibraryDependency && it.library.tableId !is LibraryTableId.ModuleLibraryTableId -> { val libraryName = it.library.name diff --git a/platform/refactoring/src/com/intellij/ide/actions/FqnUtil.java b/platform/refactoring/src/com/intellij/ide/actions/FqnUtil.java index a5fa25b10546..a39a0506a04c 100644 --- a/platform/refactoring/src/com/intellij/ide/actions/FqnUtil.java +++ b/platform/refactoring/src/com/intellij/ide/actions/FqnUtil.java @@ -10,7 +10,6 @@ import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NlsSafe; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.Strings; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; @@ -18,7 +17,6 @@ import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; -import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileIndex; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -70,14 +68,6 @@ public class FqnUtil { } } - VirtualFile root = WorkspaceFileIndex.getInstance(project).getContentFileSetRoot(virtualFile, false); - if (root != null) { - String relativePath = VfsUtilCore.getRelativePath(virtualFile, root); - if (Strings.isNotEmpty(relativePath)) { - return relativePath; - } - } - VirtualFile baseDirectory = BaseProjectDirectories.getInstance(project).getBaseDirectoryFor(virtualFile); if (baseDirectory != null) { String relativePath = VfsUtilCore.getRelativePath(virtualFile, baseDirectory); diff --git a/platform/remote-driver/client/src/com/intellij/driver/client/Driver.kt b/platform/remote-driver/client/src/com/intellij/driver/client/Driver.kt index 6ac48db5f077..2a3aa8378220 100644 --- a/platform/remote-driver/client/src/com/intellij/driver/client/Driver.kt +++ b/platform/remote-driver/client/src/com/intellij/driver/client/Driver.kt @@ -15,6 +15,11 @@ interface Driver : AutoCloseable { fun getProductVersion(): ProductVersion + /** + * Forcefully exits the application + */ + fun exitApplication() + @Contract(pure = true) fun service(clazz: KClass): T diff --git a/platform/remote-driver/client/src/com/intellij/driver/client/impl/DriverImpl.kt b/platform/remote-driver/client/src/com/intellij/driver/client/impl/DriverImpl.kt index a142ddd60f87..754ada31a9ed 100644 --- a/platform/remote-driver/client/src/com/intellij/driver/client/impl/DriverImpl.kt +++ b/platform/remote-driver/client/src/com/intellij/driver/client/impl/DriverImpl.kt @@ -39,6 +39,10 @@ internal class DriverImpl(host: JmxHost?) : Driver { return invoker.getProductVersion() } + override fun exitApplication() { + invoker.exit() + } + @Suppress("UNCHECKED_CAST") override fun service(clazz: KClass): T { return appServices.computeIfAbsent(clazz.java, ::serviceBridge) as T @@ -321,6 +325,8 @@ private val NO_SESSION: Session = Session(0, OnDispatcher.DEFAULT, LockSemantics internal interface Invoker : AutoCloseable { fun getProductVersion(): ProductVersion + fun exit() + fun invoke(call: RemoteCall): RemoteCallResult fun newSession(): Int diff --git a/platform/remote-driver/core/src/com/intellij/driver/impl/Invoker.java b/platform/remote-driver/core/src/com/intellij/driver/impl/Invoker.java index cf1dfe4031e7..ba461af686b3 100644 --- a/platform/remote-driver/core/src/com/intellij/driver/impl/Invoker.java +++ b/platform/remote-driver/core/src/com/intellij/driver/impl/Invoker.java @@ -67,6 +67,11 @@ public class Invoker implements InvokerMBean { ); } + @Override + public void exit() { + ApplicationManager.getApplication().exit(true, true, false); + } + @Override public @NotNull RemoteCallResult invoke(@NotNull RemoteCall call) { Object[] transformedArgs = transformArgs(call); @@ -75,11 +80,11 @@ public class Invoker implements InvokerMBean { if (call instanceof NewInstanceCall) { Class targetClass = getTargetClass(call); - Constructor constructor = getConstructor(call, targetClass); + Constructor constructor = getConstructor(call, targetClass, transformedArgs); LOG.debug("Creating instance of " + targetClass); - result = withSemantics(call, () -> constructor.newInstance(transformedArgs)); + result = withSemantics(call, () -> invokeConstructor(constructor, transformedArgs)); } else { CallTarget callTarget = getCallTarget(call, transformedArgs); @@ -165,19 +170,40 @@ public class Invoker implements InvokerMBean { } } + private static @NotNull Object invokeConstructor(Constructor constructor, Object[] transformedArgs) throws Exception { + try { + return constructor.newInstance(transformedArgs); + } + catch (IllegalArgumentException ie) { + String message = "Argument type mismatch for constructor " + constructor + " , actual types are [" + + getExpectedTypesMessage(transformedArgs) + "]"; + LOG.warn(message, ie); + + throw new IllegalArgumentException(message, ie); + } + catch (Throwable e) { + LOG.warn("Error during remote driver call " + constructor, e); + + throw e; + } + } + + private static @NotNull String getExpectedTypesMessage(Object[] transformedArgs) { + return Arrays.stream(transformedArgs) + .map(a -> { + if (a == null) return "null"; + return a.getClass().getSimpleName(); + }) + .collect(Collectors.joining(", ")); + } + private static Object invokeMethod(CallTarget callTarget, Object instance, Object[] args) throws Exception { try { return callTarget.targetMethod().invoke(instance, args); } catch (IllegalArgumentException ie) { - String types = Arrays.stream(args) - .map(a -> { - if (a == null) return "null"; - return a.getClass().getSimpleName(); - }) - .collect(Collectors.joining(", ")); - - String message = "Argument type mismatch for call " + callTarget.targetMethod() + ", actual types are [" + types + "]"; + String message = "Argument type mismatch for call " + callTarget.targetMethod() + ", actual types are [" + + getExpectedTypesMessage(args) + "]"; LOG.warn(message, ie); throw new IllegalArgumentException(message, ie); @@ -238,12 +264,29 @@ public class Invoker implements InvokerMBean { return RefProducer.makeRef(itemId, item); } - private static Constructor getConstructor(@NotNull RemoteCall call, @NotNull Class targetClass) { + private static Constructor getConstructor(@NotNull RemoteCall call, @NotNull Class targetClass, Object[] transformedArgs) { int argCount = call.getArgs().length; - return Arrays.stream(targetClass.getConstructors()) + List> constructors = Arrays.stream(targetClass.getConstructors()) .filter(x -> x.getParameterCount() == argCount) - .findFirst() - .orElseThrow(() -> new IllegalStateException("No such constructor found in " + targetClass)); + .toList(); + + if (constructors.isEmpty()) { + throw new IllegalStateException( + "No constructor with parameter count " + argCount + + " in class " + call.getClassName()); + } + + if (constructors.size() > 1) { + List<@Nullable Class> argumentTypes = getArgumentTypes(transformedArgs); + // take into account argument types + for (Constructor constructor : constructors) { + if (areTypesCompatible(constructor.getParameterTypes(), argumentTypes)) { + return constructor; + } + } + } + + return constructors.get(0); } private @NotNull CallTarget getCallTarget(@NotNull RemoteCall call, Object[] transformedArgs) { @@ -262,16 +305,10 @@ public class Invoker implements InvokerMBean { } if (targetMethods.size() > 1) { - List<@Nullable Class> argumentTypes = Arrays.stream(transformedArgs) - .map(a -> { - if (a == null) return (Class)null; - return a.getClass(); - }) - .toList(); - + List<@Nullable Class> argumentTypes = getArgumentTypes(transformedArgs); // take into account argument types for (Method method : targetMethods) { - if (areTypesCompatible(method, argumentTypes)) { + if (areTypesCompatible(method.getParameterTypes(), argumentTypes)) { return new CallTarget(clazz, method); } } @@ -280,20 +317,27 @@ public class Invoker implements InvokerMBean { return new CallTarget(clazz, targetMethods.get(0)); } - private static boolean areTypesCompatible(@NotNull Method method, @NotNull List<@Nullable Class> argumentTypes) { - Class[] types = method.getParameterTypes(); + private static @NotNull List<@Nullable Class> getArgumentTypes(Object[] transformedArgs) { + return Arrays.stream(transformedArgs) + .map(a -> { + if (a == null) return (Class)null; + return a.getClass(); + }) + .toList(); + } + private static boolean areTypesCompatible(Class @NotNull [] parameterTypes, @NotNull List<@Nullable Class> argumentTypes) { for (int i = 0; i < argumentTypes.size(); i++) { Class argType = argumentTypes.get(i); if (argType == null) continue; - Class parameterType = types[i]; + Class parameterType = parameterTypes[i]; if (!parameterType.isAssignableFrom(argType)) return false; } return true; } - private Class getTargetClass(RemoteCall call) { + private @NotNull Class getTargetClass(RemoteCall call) { Class clazz; try { clazz = getClassLoader(call).loadClass(call.getClassName()); @@ -304,7 +348,7 @@ public class Invoker implements InvokerMBean { return clazz; } - private ClassLoader getClassLoader(RemoteCall call) { + private @NotNull ClassLoader getClassLoader(RemoteCall call) { String pluginId = call.getPluginId(); if (pluginId == null || pluginId.isEmpty()) return getClass().getClassLoader(); @@ -331,7 +375,7 @@ public class Invoker implements InvokerMBean { return plugin.getClassLoader(); } - private Object findInstance(RemoteCall call, Class clazz) { + private @Nullable Object findInstance(RemoteCall call, Class clazz) { if (call instanceof ServiceCall) { Object projectInstance = null; Ref projectRef = ((ServiceCall)call).getProjectRef(); diff --git a/platform/remote-driver/core/src/com/intellij/driver/impl/InvokerMBean.java b/platform/remote-driver/core/src/com/intellij/driver/impl/InvokerMBean.java index f20fde1c79fe..4c95b73f7320 100644 --- a/platform/remote-driver/core/src/com/intellij/driver/impl/InvokerMBean.java +++ b/platform/remote-driver/core/src/com/intellij/driver/impl/InvokerMBean.java @@ -14,6 +14,8 @@ import java.util.function.Supplier; public interface InvokerMBean { ProductVersion getProductVersion(); + void exit(); + RemoteCallResult invoke(RemoteCall call); int newSession(); diff --git a/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt b/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt index 2c2943222172..61b9ad5794b6 100644 --- a/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt +++ b/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt @@ -634,7 +634,11 @@ abstract class ComponentManagerImpl( } final override suspend fun getServiceAsync(keyClass: Class): T { - return getServiceAsyncIfDefined(keyClass) ?: throw RuntimeException("service is not defined for $keyClass") + val result = getServiceAsyncIfDefined(keyClass) + if (result == null && isLightServiceSupported && isLightService(keyClass)) { + return getOrCreateLightServiceAdapater(keyClass).getInstanceAsync(componentManager = this, keyClass = keyClass) + } + return result ?: throw RuntimeException("service is not defined for $keyClass") } suspend fun getServiceAsyncIfDefined(keyClass: Class): T? { @@ -677,7 +681,13 @@ abstract class ComponentManagerImpl( } if (isLightServiceSupported && isLightService(serviceClass)) { - return if (createIfNeeded) getOrCreateLightService(serviceClass) else null + if (createIfNeeded) { + return getOrCreateLightServiceAdapater(serviceClass) + .getInstance(componentManager = this, keyClass = serviceClass, createIfNeeded = true)!! + } + else { + return null + } } checkCanceledIfNotInClassInit() @@ -712,7 +722,7 @@ abstract class ComponentManagerImpl( return result } - private fun getOrCreateLightService(serviceClass: Class): T { + private fun getOrCreateLightServiceAdapater(serviceClass: Class): BaseComponentAdapter { val adapter = componentKeyToAdapter.computeIfAbsent(serviceClass.name) { val classLoader = serviceClass.classLoader LightServiceComponentAdapter( @@ -721,7 +731,7 @@ abstract class ComponentManagerImpl( componentManager = this, ) } as BaseComponentAdapter - return adapter.getInstance(componentManager = this, keyClass = serviceClass, createIfNeeded = true)!! + return adapter } @Synchronized diff --git a/platform/smart-update/intellij.smart.update.iml b/platform/smart-update/intellij.smart.update.iml index e4d06c974403..8a2a53783c5e 100644 --- a/platform/smart-update/intellij.smart.update.iml +++ b/platform/smart-update/intellij.smart.update.iml @@ -11,7 +11,7 @@ - + diff --git a/platform/smart-update/src/com/intellij/smartUpdate/BuildProjectStep.kt b/platform/smart-update/src/com/intellij/smartUpdate/BuildProjectStep.kt index c240ab807b5b..1271270eaba5 100644 --- a/platform/smart-update/src/com/intellij/smartUpdate/BuildProjectStep.kt +++ b/platform/smart-update/src/com/intellij/smartUpdate/BuildProjectStep.kt @@ -3,6 +3,7 @@ package com.intellij.smartUpdate import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project import com.intellij.task.ProjectTaskManager +import com.intellij.task.impl.ProjectTaskManagerImpl const val BUILD_PROJECT = "build.project" @@ -12,6 +13,7 @@ class BuildProjectStep: SmartUpdateStep { override fun performUpdateStep(project: Project, e: AnActionEvent?, onSuccess: () -> Unit) { val start = System.currentTimeMillis() + ProjectTaskManagerImpl.putBuildOriginator(project, this.javaClass) ProjectTaskManager.getInstance(project).buildAllModules().onSuccess { SmartUpdateUsagesCollector.logBuild(System.currentTimeMillis() - start, true) onSuccess.invoke() diff --git a/platform/statistics/uploader/src/com/intellij/internal/statistic/eventLog/LogEventSerializer.kt b/platform/statistics/uploader/src/com/intellij/internal/statistic/eventLog/LogEventSerializer.kt index 8985ba69f564..250666b2350b 100644 --- a/platform/statistics/uploader/src/com/intellij/internal/statistic/eventLog/LogEventSerializer.kt +++ b/platform/statistics/uploader/src/com/intellij/internal/statistic/eventLog/LogEventSerializer.kt @@ -7,8 +7,8 @@ import com.fasterxml.jackson.core.exc.StreamReadException import com.fasterxml.jackson.databind.* import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.databind.module.SimpleModule -import com.fasterxml.jackson.module.kotlin.kotlinModule import com.fasterxml.jackson.databind.node.* +import com.fasterxml.jackson.module.kotlin.kotlinModule import com.jetbrains.fus.reporting.model.lion3.LogEvent import com.jetbrains.fus.reporting.model.lion3.LogEventAction import com.jetbrains.fus.reporting.model.lion3.LogEventGroup @@ -52,7 +52,7 @@ object LogEventSerializer { /** * Serialize events manually, so it won't be changed by scrambling */ - fun toJson(event: LogEvent): ObjectNode { + private fun toJson(event: LogEvent): ObjectNode { val mapper = ObjectMapper() val obj = mapper.createObjectNode() @@ -119,62 +119,61 @@ class LogEventRecordRequestJsonDeserializer : JsonDeserializer + + + 4a30234a911a73ae71f5aec5f98bee243c172665e841f8d532ef77e0b5e81010 + + + 9c9e3ef454b514d4a1342faf99c7d4cb41eaae4cb7aefcc93cb7b202bdf4fdfd + + diff --git a/platform/testFramework/junit5/src/impl/CheckVFSHealthExtension.kt b/platform/testFramework/junit5/src/impl/CheckVFSHealthExtension.kt new file mode 100644 index 000000000000..01994e90668a --- /dev/null +++ b/platform/testFramework/junit5/src/impl/CheckVFSHealthExtension.kt @@ -0,0 +1,69 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.testFramework.junit5.impl + +import com.intellij.openapi.vfs.newvfs.persistent.VFSHealthChecker +import org.jetbrains.annotations.TestOnly +import org.junit.jupiter.api.extension.AfterAllCallback +import org.junit.jupiter.api.extension.AfterEachCallback +import org.junit.jupiter.api.extension.BeforeAllCallback +import org.junit.jupiter.api.extension.BeforeEachCallback +import org.junit.jupiter.api.extension.ExtensionContext + +/** + * Checks VFS to be consistent before/after all/each tests have passed. + */ +@TestOnly +class CheckVFSHealthExtension +private constructor(private val checkBeforeEach: Boolean = false, + private val checkAfterEach: Boolean = false, + private val checkBeforeAll: Boolean = false, + private val checkAfterAll: Boolean = false) : BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback { + + init { + if (!checkBeforeAll && !checkBeforeEach && !checkAfterAll && !checkAfterEach) { + throw IllegalArgumentException( + "All check[Before|After][All|Each] flags are false -- nothing to do. At least one of flags must be true") + } + } + + override fun beforeAll(context: ExtensionContext?) = if (checkBeforeAll) checkVFS(context!!) else Unit + + override fun afterAll(context: ExtensionContext?) = if (checkAfterAll) checkVFS(context!!) else Unit + + override fun beforeEach(context: ExtensionContext?) = if (checkBeforeEach) checkVFS(context!!) else Unit + + override fun afterEach(context: ExtensionContext?) = if (checkAfterEach) checkVFS(context!!) else Unit + + @Suppress("TestOnlyProblems") + companion object { + @JvmStatic + fun beforeAll() = CheckVFSHealthExtension(checkBeforeAll = true) + + @JvmStatic + fun afterAll() = CheckVFSHealthExtension(checkAfterAll = true) + + @JvmStatic + fun beforeAndAfterAll() = CheckVFSHealthExtension(checkBeforeAll = true, checkAfterAll = true) + + + @JvmStatic + fun beforeEach() = CheckVFSHealthExtension(checkBeforeEach = true) + + @JvmStatic + fun afterEach() = CheckVFSHealthExtension(checkAfterEach = true) + + @JvmStatic + fun beforeAndAfterEach() = CheckVFSHealthExtension(checkBeforeEach = true, checkAfterEach = true) + } + + + @Throws(Exception::class) + private fun checkVFS(context: ExtensionContext) { + val checker = VFSHealthChecker() + val report = checker.checkHealth(checkForOrphanRecords = true) + context.publishReportEntry("vfs-report", report.toString()) + if (!report.healthy) { + throw AssertionError("VFS is corrupted: $report") + } + } +} diff --git a/platform/testFramework/junit5/src/impl/CleanVFSExtension.kt b/platform/testFramework/junit5/src/impl/CleanVFSExtension.kt new file mode 100644 index 000000000000..a573e575327f --- /dev/null +++ b/platform/testFramework/junit5/src/impl/CleanVFSExtension.kt @@ -0,0 +1,62 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.testFramework.junit5.impl + +import com.intellij.openapi.vfs.newvfs.persistent.FSRecords +import org.jetbrains.annotations.TestOnly +import org.junit.jupiter.api.extension.* + +/** + * Cleans VFS before/after all/each tests have passed. + */ +@TestOnly +class CleanVFSExtension +private constructor(private val cleanBeforeEach: Boolean = false, + private val cleanAfterEach: Boolean = false, + private val cleanBeforeAll: Boolean = false, + private val cleanAfterAll: Boolean = false) : BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback { + + init { + if (!cleanBeforeAll && !cleanBeforeEach && !cleanAfterAll && !cleanAfterEach) { + throw IllegalArgumentException( + "All clean[Before|After][All|Each] flags are false -- nothing to do. At least one of flags must be true") + } + } + + override fun beforeAll(context: ExtensionContext?) = if (cleanBeforeAll) cleanVFS(context!!) else Unit + + override fun afterAll(context: ExtensionContext?) = if (cleanAfterAll) cleanVFS(context!!) else Unit + + override fun beforeEach(context: ExtensionContext?) = if (cleanBeforeEach) cleanVFS(context!!) else Unit + + override fun afterEach(context: ExtensionContext?) = if (cleanAfterEach) cleanVFS(context!!) else Unit + + @Suppress("TestOnlyProblems") + companion object { + @JvmStatic + fun beforeAll() = CleanVFSExtension(cleanBeforeAll = true) + + @JvmStatic + fun afterAll() = CleanVFSExtension(cleanAfterAll = true) + + @JvmStatic + fun beforeAndAfterAll() = CleanVFSExtension(cleanBeforeAll = true, cleanAfterAll = true) + + + @JvmStatic + fun beforeEach() = CleanVFSExtension(cleanBeforeEach = true) + + @JvmStatic + fun afterEach() = CleanVFSExtension(cleanAfterEach = true) + + @JvmStatic + fun beforeAndAfterEach() = CleanVFSExtension(cleanBeforeEach = true, cleanAfterEach = true) + } + + + @Throws(Exception::class) + private fun cleanVFS(context: ExtensionContext) { + context.publishReportEntry("Request VFS rebuild (for better tests isolation)") + + FSRecords.invalidateCaches("Rebuild VFS (for better tests isolation)") + } +} diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index 3dc1a8bf1689..fda87dd821bf 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -1845,7 +1845,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig throw new FileComparisonFailure(expectedFile, expectedText, actualText, loader.filePath); } - EditorTestUtil.verifyCaretAndSelectionState(editor, loader.caretState, expectedFile); + EditorTestUtil.verifyCaretAndSelectionState(editor, loader.caretState, expectedFile, loader.filePath); } @NotNull diff --git a/platform/testFramework/ui/intellij.platform.testFramework.ui.iml b/platform/testFramework/ui/intellij.platform.testFramework.ui.iml index c464a174b96a..c8f3abbe9764 100644 --- a/platform/testFramework/ui/intellij.platform.testFramework.ui.iml +++ b/platform/testFramework/ui/intellij.platform.testFramework.ui.iml @@ -13,7 +13,13 @@ - + + + + f7d51a8bda35e72bb4ef01301916b96a793c9f8ddd26474da54c38fa9e8ec2cc + + + @@ -32,6 +38,56 @@ + + + 7a7b77c25d28059eecc73075198eab5d06b23774ab6e0aab10b1fc9e82f0abbd + + + f20be85d7ec4ad921b9d14f116b8661ab9e6a1a1df20bf2101c9c532bdd0a513 + + + a223e6df91b84f19d49c5ebc5f5f97c7f4438419f84a52fa05e1cfc6eed38aa9 + + + 187c5e5a588a6ed18c3a41b54df138a5944121bdb396be1c3fa4abee67397955 + + + e6ea1929c46852f5bec66ab3357da383476cef4e8d1deefdbf195b79cc4d6581 + + + 2570fab55515cbf881d7a4ceef49fc515490bc027057e666776a2832465aeca0 + + + f80ce42d2ffac47ad4c47e1d6f980d604d247ceb1a886705cf4581ab0c9fe2b8 + + + 32aa206b9a29c9df5eda93a092cfb3b0b9133e232c062baa882f0319f0e79f0e + + + c9290b0d801bf0dbbbc44338e0f769b7650a0c5d04e6bb1aeb85775c0211b003 + + + e56fea51b7969240460d027a17f1c704b43e4eeca49a8c57206d573da3e30871 + + + 59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a + + + 66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9 + + + e36445438d72d83cc48015dcb3f14d9a97eaa42c4663a9826db2bb50e4c7713b + + + d9a978d559d0b52a87f419b3d8f5bb137b97c661f7be2134e0498b454e4b980e + + + 7b52f4d3ad41b7ed71f5b6b11833113b7e08326c8ef70d2dedf0b430c7ba5341 + + + c1ca19fcf0cd3555baf7c2af147c04ad22b4393ab75e5db0284e5170fb554c16 + + diff --git a/platform/util-ex/src/com/intellij/util/lazy.kt b/platform/util-ex/src/com/intellij/util/lazy.kt index a4c63046cf97..8c686a8482f1 100644 --- a/platform/util-ex/src/com/intellij/util/lazy.kt +++ b/platform/util-ex/src/com/intellij/util/lazy.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.util import kotlinx.coroutines.CoroutineScope @@ -22,8 +22,16 @@ fun recursionSafeLazy(recursionKey: Any? = null, initializer: () -> T): Lazy return RecursionPreventingSafePublicationLazy(recursionKey, initializer) } +/** + * Creates a lazy property that is thread-safe on publication. + */ fun lazyPub(initializer: () -> T): Lazy = lazy(LazyThreadSafetyMode.PUBLICATION, initializer) +/** + * Creates a lazy property that is thread-unsafe. Do not use it in multithreading environment + */ +fun lazyUnsafe(initializer: () -> T): Lazy = lazy(LazyThreadSafetyMode.NONE, initializer) + /** * Creates a new instance of [SuspendingLazy] that uses the specified initialization function [initializer]. * diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index f77a856dce2d..8295859ddc1a 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -1040,8 +1040,6 @@ floating.codeToolbar.verticalOffset=2 floating.codeToolbar.verticalOffset.description=Vertical offset between line and floating toolbar for code floating.codeToolbar.showBelow=true floating.codeToolbar.showBelow.description=Always show floating code toolbar below the selection when possible. -floating.codeToolbar.revive.selectionChangeOnly=true -floating.codeToolbar.revive.selectionChangeOnly.description=Show closed toolbar again only if editor selection was changed run.refactorings.under.progress=true run.refactorings.under.progress.description=Run refactorings write action under progress, not to freeze the UI during long operations @@ -1059,9 +1057,6 @@ completion.show.intention.icon=true always.show.intention.above.current.line=false always.show.intention.above.current.line.description=Avoid showing intention popup on line where caret stays (e.g. show it above current line) -inline.completion.trigger.delay=300 -inline.completion.trigger.delay.description==Delay in milliseconds before triggering gray text pipeline - python.django.timeout=30 python.django.timeout.description=Number of seconds to wait for manage.py list commands introduce.variable.prefer.statements=false @@ -2189,6 +2184,9 @@ ide.mac.os.wintabs.version2=true ide.mac.os.wintabs.version2.description=Enable Mac OS project tabs for New UI ide.mac.os.wintabs.version2.restartRequired=true +ide.mac.os.wintabs.show.closeaction.on.hover=true +ide.mac.os.wintabs.show.closeaction.on.hover.description=Show close tab action only on tab hover + apple.awt.newFullScreeControls=true ea.enable.developers.list=true @@ -2254,9 +2252,6 @@ eclipse.scan.home.directory.description=Scan home directory for existing Eclipse ide.diagnostics.show.context.menu.invocation.time=false ide.diagnostics.show.context.menu.invocation.time.description=Show time in ms between mouse event and context menu appearance on screen -ide.new.about.dialog=true -ide.new.about.dialog.description=Enable dialog based About popup - run.index.rescanning.on.plugin.load.unload=true run.index.rescanning.on.plugin.load.unload.description=Run force index rescanning on plugin load/unload diff --git a/platform/util/src/com/intellij/openapi/util/SystemInfo.java b/platform/util/src/com/intellij/openapi/util/SystemInfo.java index fd3ac82d639f..c5743e466191 100644 --- a/platform/util/src/com/intellij/openapi/util/SystemInfo.java +++ b/platform/util/src/com/intellij/openapi/util/SystemInfo.java @@ -75,10 +75,9 @@ public final class SystemInfo { } } - public static final boolean isAppleSystemMenu = isMac && Boolean.getBoolean("apple.laf.useScreenMenuBar"); public static final boolean isJBSystemMenu = isMac && Boolean.getBoolean("jbScreenMenuBar.enabled"); - public static final boolean isMacSystemMenu = isAppleSystemMenu || isJBSystemMenu; + public static final boolean isMacSystemMenu = isJBSystemMenu || Boolean.getBoolean("apple.laf.useScreenMenuBar"); public static final boolean isFileSystemCaseSensitive = SystemInfoRt.isFileSystemCaseSensitive; diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 38bf0603beb5..7077ed379591 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -3056,8 +3056,9 @@ public class StringUtil extends StringUtilRt { /** * Finds the next position in the supplied CharSequence which is neither a space nor a tab. + * * @param text text - * @param pos starting position + * @param pos starting position * @return position of the first non-whitespace character after or equal to pos; or the length of the CharSequence * if no non-whitespace character found */ @@ -3070,9 +3071,26 @@ public class StringUtil extends StringUtilRt { } /** - * Finds the previous position in the supplied CharSequence which is neither a space nor a tab. + * Finds the next position in the supplied CharSequence which is neither a space, a new line nor a tab. + * * @param text text - * @param pos starting position + * @param pos starting position + * @return position of the first non-whitespace character after or equal to pos; or the length of the CharSequence + * if no non-whitespace character found + */ + public static int skipWhitespaceOrNewLineForward(@NotNull CharSequence text, int pos) { + int length = text.length(); + while (pos < length && isWhitespaceTabOrNewLine(text.charAt(pos))) { + pos++; + } + return pos; + } + + /** + * Finds the previous position in the supplied CharSequence which is neither a space nor a tab. + * + * @param text text + * @param pos starting position * @return position of the character before or equal to pos which has no space or tab before; * or zero if no non-whitespace character found */ @@ -3083,10 +3101,29 @@ public class StringUtil extends StringUtilRt { return pos; } + /** + * Finds the previous position in the supplied CharSequence which is neither a space, a new line nor a tab. + * + * @param text text + * @param pos starting position + * @return position of the character before or equal to pos which has no space or tab before; + * or zero if no non-whitespace character found + */ + public static int skipWhitespaceOrNewLineBackward(@NotNull CharSequence text, int pos) { + while (pos > 0 && isWhitespaceTabOrNewLine(text.charAt(pos - 1))) { + pos--; + } + return pos; + } + private static boolean isWhitespaceOrTab(char c) { return c == ' ' || c == '\t'; } + private static boolean isWhitespaceTabOrNewLine(char c) { + return c == ' ' || c == '\t' || c == '\n'; + } + /** * @deprecated use {@link com.intellij.ide.nls.NlsMessages#formatAndList(java.util.Collection)} instead to get properly localized concatenation */ diff --git a/platform/util/src/com/intellij/util/KtUtils.kt b/platform/util/src/com/intellij/util/KtUtils.kt index 7d4b9c88283d..bde869863618 100644 --- a/platform/util/src/com/intellij/util/KtUtils.kt +++ b/platform/util/src/com/intellij/util/KtUtils.kt @@ -27,4 +27,3 @@ operator fun AtomicReference.getValue(thisRef: Any?, property: KProperty< operator fun AtomicReference.setValue(thisRef: Any?, property: KProperty<*>, value: V): Unit = set(value) -fun simpleLazy(initializer: () -> T): Lazy = lazy(LazyThreadSafetyMode.NONE, initializer) \ No newline at end of file diff --git a/platform/util/trove/intellij.platform.util.trove.iml b/platform/util/trove/intellij.platform.util.trove.iml index 4fd1884a5bc7..e5028e7f4343 100644 --- a/platform/util/trove/intellij.platform.util.trove.iml +++ b/platform/util/trove/intellij.platform.util.trove.iml @@ -9,7 +9,13 @@ - + + + + 3d1ce86790d123de204215c4b2b8896afaed63abfdece24393e2183df5394c32 + + + diff --git a/platform/util/ui/src/com/intellij/icons/AllIcons.java b/platform/util/ui/src/com/intellij/icons/AllIcons.java index a0eeda689a30..4711b9b2d0d1 100644 --- a/platform/util/ui/src/com/intellij/icons/AllIcons.java +++ b/platform/util/ui/src/com/intellij/icons/AllIcons.java @@ -162,6 +162,7 @@ public class AllIcons { /** 16x16 */ public static final @NotNull Icon RealIntentionBulb = load("actions/realIntentionBulb.svg", 516517225, 2); /** 16x16 */ public static final @NotNull Icon Redo = load("actions/redo.svg", 1384796752, 2); /** 16x16 */ public static final @NotNull Icon RefactoringBulb = load("actions/refactoringBulb.svg", -1341396806, 2); + /** 16x16 */ public static final @NotNull Icon ReformatCode = load("actions/reformatCode.svg", 1503774223, 2); /** 16x16 */ public static final @NotNull Icon Refresh = load("actions/refresh.svg", 954789704, 2); /** 16x16 */ public static final @NotNull Icon Regex = load("actions/regex.svg", -669040651, 0); /** 16x16 */ public static final @NotNull Icon RegexHovered = load("actions/regexHovered.svg", -17694115, 0); @@ -1248,11 +1249,11 @@ public class AllIcons { /** 24x24 */ public static final @NotNull Icon Open = load("welcome/open.svg", -1167853047, 2); /** 24x24 */ public static final @NotNull Icon OpenSelected = load("welcome/openSelected.svg", 297876432, 0); - public static final class Project { - /** 10x10 */ public static final @NotNull Icon RemoveHover = load("welcome/project/remove-hover.svg", -1138969467, 2); - /** 10x10 */ public static final @NotNull Icon Remove = load("welcome/project/remove.svg", -1344345313, 2); - /** 10x10 */ public static final @NotNull Icon RemoveDisabledHover = load("welcome/project/removeDisabled-hover.svg", 225648199, 2); - /** 10x10 */ public static final @NotNull Icon RemoveDisabled = load("welcome/project/removeDisabled.svg", 693821036, 2); + public static final class RecentProjects { + /** 10x10 */ public static final @NotNull Icon RemoveHover = load("welcome/recentProjects/remove-hover.svg", -1138969467, 2); + /** 10x10 */ public static final @NotNull Icon Remove = load("welcome/recentProjects/remove.svg", -1344345313, 2); + /** 10x10 */ public static final @NotNull Icon RemoveDisabledHover = load("welcome/recentProjects/removeDisabled-hover.svg", 225648199, 2); + /** 10x10 */ public static final @NotNull Icon RemoveDisabled = load("welcome/recentProjects/removeDisabled.svg", 693821036, 2); } /** @deprecated to be removed */ diff --git a/platform/util/ui/src/com/intellij/icons/ExpUiIcons.java b/platform/util/ui/src/com/intellij/icons/ExpUiIcons.java index 9c4a21d0345f..e216f2842071 100644 --- a/platform/util/ui/src/com/intellij/icons/ExpUiIcons.java +++ b/platform/util/ui/src/com/intellij/icons/ExpUiIcons.java @@ -19,6 +19,7 @@ public final class ExpUiIcons { /** 16x16 */ public static final @NotNull Icon BuildAutoReloadChanges = load("expui/actions/buildAutoReloadChanges.svg", -769137589, 2); /** 16x16 */ public static final @NotNull Icon ClearCash = load("expui/actions/clearCash.svg", -651670985, 2); /** 16x16 */ public static final @NotNull Icon Deploy = load("expui/actions/deploy.svg", -42046735, 2); + /** 16x16 */ public static final @NotNull Icon DiagramDiff = load("expui/actions/diagramDiff.svg", 2129574955, 2); /** 16x16 */ public static final @NotNull Icon DiffWithClipboard = load("expui/actions/diffWithClipboard.svg", -1141011475, 2); /** 16x16 */ public static final @NotNull Icon Filterdups = load("expui/actions/filterdups.svg", -1675572656, 2); /** 16x16 */ public static final @NotNull Icon Generated = load("expui/actions/generated.svg", -1905788368, 2); @@ -29,13 +30,14 @@ public final class ExpUiIcons { /** 16x16 */ public static final @NotNull Icon InSelection = load("expui/actions/inSelection.svg", -672670687, 2); /** 16x16 */ public static final @NotNull Icon Install = load("expui/actions/install.svg", 1754913287, 2); /** 16x16 */ public static final @NotNull Icon Lightning = load("expui/actions/lightning.svg", -270648659, 2); - /** 16x16 */ public static final @NotNull Icon MoveToBottomLeft = load("expui/actions/moveToBottomLeft.svg", -1880102300, 2); - /** 16x16 */ public static final @NotNull Icon MoveToBottomRight = load("expui/actions/moveToBottomRight.svg", 742208591, 2); + /** 16x16 */ public static final @NotNull Icon Minimap = load("expui/actions/minimap.svg", -1838091231, 2); + /** 16x16 */ public static final @NotNull Icon MoveToBottomLeft = load("expui/actions/moveToBottomLeft.svg", -1473386956, 2); + /** 16x16 */ public static final @NotNull Icon MoveToBottomRight = load("expui/actions/moveToBottomRight.svg", 1803793130, 2); /** 16x16 */ public static final @NotNull Icon MoveToButton = load("expui/actions/moveToButton.svg", -483907299, 2); - /** 16x16 */ public static final @NotNull Icon MoveToLeftBottom = load("expui/actions/moveToLeftBottom.svg", -1805039462, 2); - /** 16x16 */ public static final @NotNull Icon MoveToLeftTop = load("expui/actions/moveToLeftTop.svg", 1510043922, 2); - /** 16x16 */ public static final @NotNull Icon MoveToRightBottom = load("expui/actions/moveToRightBottom.svg", -622483511, 2); - /** 16x16 */ public static final @NotNull Icon MoveToRightTop = load("expui/actions/moveToRightTop.svg", 532814306, 2); + /** 16x16 */ public static final @NotNull Icon MoveToLeftBottom = load("expui/actions/moveToLeftBottom.svg", -1236920830, 2); + /** 16x16 */ public static final @NotNull Icon MoveToLeftTop = load("expui/actions/moveToLeftTop.svg", 881154656, 2); + /** 16x16 */ public static final @NotNull Icon MoveToRightBottom = load("expui/actions/moveToRightBottom.svg", 1351639515, 2); + /** 16x16 */ public static final @NotNull Icon MoveToRightTop = load("expui/actions/moveToRightTop.svg", -67380800, 2); /** 16x16 */ public static final @NotNull Icon NewFolder = load("expui/actions/newFolder.svg", 1487335447, 2); /** 16x16 */ public static final @NotNull Icon PlayBack = load("expui/actions/playBack.svg", 1165836244, 2); /** 16x16 */ public static final @NotNull Icon PlayFirst = load("expui/actions/playFirst.svg", -1838173000, 2); @@ -43,10 +45,12 @@ public final class ExpUiIcons { /** 16x16 */ public static final @NotNull Icon PlayLast = load("expui/actions/playLast.svg", -236076917, 2); /** 16x16 */ public static final @NotNull Icon ProfileCPU = load("expui/actions/profileCPU.svg", -143458575, 2); /** 16x16 */ public static final @NotNull Icon ProjectDirectory = load("expui/actions/projectDirectory.svg", 1333538549, 2); + /** 16x16 */ public static final @NotNull Icon ReformatCode = load("expui/actions/reformatCode.svg", 1018232520, 2); /** 16x16 */ public static final @NotNull Icon RunAll = load("expui/actions/runAll.svg", 892135407, 2); /** 16x16 */ public static final @NotNull Icon ShowImportStatements = load("expui/actions/showImportStatements.svg", 935761482, 2); /** 16x16 */ public static final @NotNull Icon ShowReadAccess = load("expui/actions/showReadAccess.svg", 432207500, 2); /** 16x16 */ public static final @NotNull Icon ShowWriteAccess = load("expui/actions/showWriteAccess.svg", 799113071, 2); + /** 16x16 */ public static final @NotNull Icon Split = load("expui/actions/split.svg", 1102270400, 2); /** 16x16 */ public static final @NotNull Icon SwapPanels = load("expui/actions/swapPanels.svg", 2147313806, 2); /** 16x16 */ public static final @NotNull Icon SynchronizeScrolling = load("expui/actions/synchronizeScrolling.svg", -731160875, 2); /** 16x16 */ public static final @NotNull Icon ToggleVisibility = load("expui/actions/toggleVisibility.svg", 2137980334, 2); @@ -181,6 +185,8 @@ public final class ExpUiIcons { /** 16x16 */ public static final @NotNull Icon AnyType = load("expui/fileTypes/anyType.svg", 1371529814, 2); /** 16x16 */ public static final @NotNull Icon Archive = load("expui/fileTypes/archive.svg", -782079458, 2); /** 16x16 */ public static final @NotNull Icon AspectJ = load("expui/fileTypes/aspectJ.svg", 2084203057, 2); + /** 16x16 */ public static final @NotNull Icon ChangedFile = load("expui/fileTypes/changedFile.svg", -1545199036, 2); + /** 16x16 */ public static final @NotNull Icon ChangedFiles = load("expui/fileTypes/changedFiles.svg", -1547714866, 2); /** 16x16 */ public static final @NotNull Icon Config = load("expui/fileTypes/config.svg", 1239979240, 2); /** 16x16 */ public static final @NotNull Icon Css = load("expui/fileTypes/css.svg", 1158571392, 0); /** 16x16 */ public static final @NotNull Icon Csv = load("expui/fileTypes/csv.svg", -2009889099, 2); @@ -224,6 +230,7 @@ public final class ExpUiIcons { /** 16x16 */ public static final @NotNull Icon SourceMap = load("expui/fileTypes/sourceMap.svg", -798309148, 2); /** 16x16 */ public static final @NotNull Icon Sql = load("expui/fileTypes/sql.svg", -1496861857, 2); /** 16x16 */ public static final @NotNull Icon Text = load("expui/fileTypes/text.svg", 1946633559, 2); + /** 16x16 */ public static final @NotNull Icon UiForm = load("expui/fileTypes/uiForm.svg", -397412144, 2); /** 16x16 */ public static final @NotNull Icon Unknown = load("expui/fileTypes/unknown.svg", -2043297803, 2); /** 16x16 */ public static final @NotNull Icon VueJs = load("expui/fileTypes/vueJs.svg", -1118824585, 0); /** 16x16 */ public static final @NotNull Icon Wsdl = load("expui/fileTypes/wsdl.svg", 53700367, 2); @@ -376,6 +383,11 @@ public final class ExpUiIcons { /** 14x14 */ public static final @NotNull Icon WriteAccess = load("expui/gutter/writeAccess.svg", -998663344, 2); } + public static final class Hierarchy { + /** 16x16 */ public static final @NotNull Icon Subtypes = load("expui/hierarchy/subtypes.svg", -570232233, 2); + /** 16x16 */ public static final @NotNull Icon Supertypes = load("expui/hierarchy/supertypes.svg", 1662070576, 2); + } + public static final class Ide { /** 16x16 */ public static final @NotNull Icon ConfigFile = load("expui/ide/configFile.svg", 1264425469, 2); /** 16x16 */ public static final @NotNull Icon ExternalLink = load("expui/ide/externalLink.svg", -932621117, 2); @@ -531,7 +543,7 @@ public final class ExpUiIcons { } public static final class Run { - /** 16x16 */ public static final @NotNull Icon AttachToProcess = load("expui/run/attachToProcess.svg", -1557990976, 2); + /** 16x16 */ public static final @NotNull Icon AttachToProcess = load("expui/run/attachToProcess.svg", 1612859511, 2); /** 16x16 */ public static final @NotNull Icon Debug = load("expui/run/debug.svg", 1409937178, 10); /** 16x16 */ public static final @NotNull Icon DumpThreads = load("expui/run/dumpThreads.svg", -887924950, 2); /** 16x16 */ public static final @NotNull Icon EvaluateExpression = load("expui/run/evaluateExpression.svg", -1931888328, 2); @@ -581,7 +593,7 @@ public final class ExpUiIcons { public static final class RunConfigurations { /** 16x16 */ public static final @NotNull Icon Application = load("expui/runConfigurations/application.svg", 326858300, 2); - /** 16x16 */ public static final @NotNull Icon ApplicationRemote = load("expui/runConfigurations/applicationRemote.svg", 1461896360, 2); + /** 16x16 */ public static final @NotNull Icon ApplicationRemote = load("expui/runConfigurations/applicationRemote.svg", -111652439, 2); /** 16x16 */ public static final @NotNull Icon Compound = load("expui/runConfigurations/compound.svg", 1035092097, 2); /** 16x16 */ public static final @NotNull Icon InvalidConfigurationLayer = load("expui/runConfigurations/invalidConfigurationLayer.svg", 3963890, 2); /** 16x16 */ public static final @NotNull Icon Junit = load("expui/runConfigurations/junit.svg", 884878395, 2); @@ -664,6 +676,8 @@ public final class ExpUiIcons { /** 20x20 */ public static final @NotNull Icon Todo_20x20 = load("expui/toolwindow/todo@20x20.svg", -811890978, 2); /** 16x16 */ public static final @NotNull Icon ToolWindowInternal = load("expui/toolwindow/toolWindowInternal.svg", -1900747368, 2); /** 20x20 */ public static final @NotNull Icon ToolWindowInternal_20x20 = load("expui/toolwindow/toolWindowInternal@20x20.svg", -434982620, 2); + /** 16x16 */ public static final @NotNull Icon ToolWindowJsonPath = load("expui/toolwindow/toolWindowJsonPath.svg", 1764965987, 2); + /** 20x20 */ public static final @NotNull Icon ToolWindowJsonPath_20x20 = load("expui/toolwindow/toolWindowJsonPath@20x20.svg", -308711555, 2); /** 16x16 */ public static final @NotNull Icon ToolWindowVariableView = load("expui/toolwindow/toolWindowVariableView.svg", -944459308, 2); /** 20x20 */ public static final @NotNull Icon ToolWindowVariableView_20x20 = load("expui/toolwindow/toolWindowVariableView@20x20.svg", 1193386499, 2); /** 16x16 */ public static final @NotNull Icon Vcs = load("expui/toolwindow/vcs.svg", 468795750, 2); @@ -700,6 +714,10 @@ public final class ExpUiIcons { /** 16x16 */ public static final @NotNull Icon Vcs = load("expui/vcs/vcs.svg", 468795750, 2); } + public static final class WebReferences { + /** 16x16 */ public static final @NotNull Icon Server = load("expui/webReferences/server.svg", 1021314784, 2); + } + public static final class Welcome { /** 20x20 */ public static final @NotNull Icon CreateNewProjectTab = load("expui/welcome/createNewProjectTab.svg", 78176762, 2); /** 20x20 */ public static final @NotNull Icon FromVCSTab = load("expui/welcome/fromVCSTab.svg", 587255847, 2); diff --git a/platform/util/ui/src/com/intellij/util/ui/JBInsets.java b/platform/util/ui/src/com/intellij/util/ui/JBInsets.java index 8e3182b79982..73dad6f29c3e 100644 --- a/platform/util/ui/src/com/intellij/util/ui/JBInsets.java +++ b/platform/util/ui/src/com/intellij/util/ui/JBInsets.java @@ -158,6 +158,7 @@ public class JBInsets extends Insets { @ApiStatus.Internal public static Insets unwrap(@NotNull Insets insets) { if (insets instanceof JBInsets jbInsets) { + // Check that scaled values consistent with unscaled ones JBInsets cleanInsets = create(jbInsets.getUnscaled()); if (insets.equals(cleanInsets)) return jbInsets.getUnscaled(); diff --git a/platform/util/ui/src/com/intellij/util/ui/JBUI.java b/platform/util/ui/src/com/intellij/util/ui/JBUI.java index f2aa5e3f2c17..2359b21b699f 100644 --- a/platform/util/ui/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/ui/src/com/intellij/util/ui/JBUI.java @@ -506,8 +506,12 @@ public final class JBUI { public static @NotNull Color mainToolbarBackground(boolean active) { JBColor activeBG = JBColor.namedColor("MainToolbar.background", titlePaneBackground()); - JBColor inactiveBG = JBColor.namedColor("MainToolbar.inactiveBackground", activeBG); - return active ? activeBG : inactiveBG; + if (active) { + return activeBG; + } + else { + return JBColor.namedColor("MainToolbar.inactiveBackground", activeBG); + } } public static @NotNull Color titlePaneInfoForeground() { @@ -1170,7 +1174,7 @@ public final class JBUI { public static final class Dropdown { @NotNull public static Insets borderInsets() { - return insets("MainToolbar.Dropdown.borderInsets", isNewUI() ? insets(5, 12, 5, 6) : insets(3, 5)); + return insets("MainToolbar.Dropdown.borderInsets", isNewUI() ? insets(5, 10, 5, 6) : insets(3, 5)); } } diff --git a/platform/util/ui/src/com/intellij/util/ui/UIUtil.java b/platform/util/ui/src/com/intellij/util/ui/UIUtil.java index 6c4894dda122..e604d472d328 100644 --- a/platform/util/ui/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/ui/src/com/intellij/util/ui/UIUtil.java @@ -97,10 +97,6 @@ public final class UIUtil { return Logger.getInstance(UIUtil.class); } - public static void decorateWindowHeader(JRootPane pane) { - ComponentUtil.decorateWindowHeader(pane); - } - public static int getTransparentTitleBarHeight(JRootPane rootPane) { Object property = rootPane.getClientProperty("Window.transparentTitleBarHeight"); if (property instanceof Integer) { diff --git a/platform/util/ui/src/com/intellij/util/ui/ValueScaler.kt b/platform/util/ui/src/com/intellij/util/ui/ValueScaler.kt new file mode 100644 index 000000000000..84cbfa06cd9b --- /dev/null +++ b/platform/util/ui/src/com/intellij/util/ui/ValueScaler.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 com.intellij.util.ui + +import com.intellij.ui.scale.JBUIScale +import org.jetbrains.annotations.ApiStatus.Internal +import kotlin.math.roundToInt + + +/** + * Internal class used for scaling integer values based on the current scale factor. + * + * Example: + * // userScale == 1.0 + * val scaler = ValueScaler(2) + * ... + * // userScale == 1.5 + * val value = scaler.get() // value == 3 + * + * @property origValue The original value scaled with the userScale at the moment of ValueScaler initialization + */ +@Internal +class ValueScaler(private val origValue: Int) { + private val origScale = JBUIScale.scale(1f) + + fun get(): Int { + val currentScale = JBUIScale.scale(1f) + return if (origScale == currentScale) origValue + else (origValue.toFloat() * currentScale / origScale).roundToInt() + } +} \ No newline at end of file diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/LocalTrackerDiffUtil.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/LocalTrackerDiffUtil.kt index fa1360025991..62df076c6b3f 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/LocalTrackerDiffUtil.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/LocalTrackerDiffUtil.kt @@ -24,9 +24,13 @@ import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.colors.EditorColors import com.intellij.openapi.editor.ex.EditorEx +import com.intellij.openapi.editor.ex.MarkupModelEx +import com.intellij.openapi.editor.impl.DocumentMarkupModel import com.intellij.openapi.editor.markup.* import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.project.DumbAwareAction +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.NlsContexts import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vcs.VcsBundle import com.intellij.openapi.vcs.changes.ChangeListManager @@ -35,6 +39,7 @@ import com.intellij.openapi.vcs.impl.LineStatusTrackerManager import com.intellij.ui.DirtyUI import com.intellij.ui.InplaceButton import com.intellij.ui.scale.JBUIScale +import com.intellij.util.CommonProcessors.FindProcessor import com.intellij.util.concurrency.annotations.RequiresWriteLock import com.intellij.util.ui.JBUI import org.jetbrains.annotations.Nls @@ -226,14 +231,20 @@ object LocalTrackerDiffUtil { HighlighterLayer.ADDITIONAL_SYNTAX, HighlighterTargetArea.LINES_IN_RANGE) val message = DiffBundle.message("action.presentation.diff.include.into.commit.text") - checkboxHighlighter.gutterIconRenderer = object : DiffGutterRenderer(icon, message) { - override fun handleMouseClick() { - onClick.run() - } - } + checkboxHighlighter.gutterIconRenderer = CheckboxDiffGutterRenderer(icon, message, onClick) return checkboxHighlighter } + private class CheckboxDiffGutterRenderer( + icon: Icon, + tooltip: @NlsContexts.Tooltip String?, + val onClick: Runnable + ) : DiffGutterRenderer(icon, tooltip) { + override fun handleMouseClick() { + onClick.run() + } + } + @JvmStatic fun toggleBlockExclusion(provider: LocalTrackerActionProvider, line: Int, wasExcludedFromCommit: Boolean) { val tracker = provider.localRequest.partialTracker ?: return @@ -291,6 +302,29 @@ object LocalTrackerDiffUtil { return checkboxHighlighter } + @JvmStatic + fun hasIconHighlighters(project: Project?, editor: EditorEx, line: Int): Boolean { + if (hasIconHighlighters(editor, line, editor.markupModel)) return true + + val documentModel = DocumentMarkupModel.forDocument(editor.document, project, false) as MarkupModelEx + return hasIconHighlighters(editor, line, documentModel) + } + + private fun hasIconHighlighters(editor: EditorEx, line: Int, markupModelEx: MarkupModelEx): Boolean { + val processor = object : FindProcessor() { + override fun accept(it: RangeHighlighter): Boolean { + return it.getGutterIconRenderer() != null && + it.editorFilter.avaliableIn(editor) + } + } + + val document = editor.getDocument() + val start = document.getLineStartOffset(line) + val end = document.getLineEndOffset(line) + markupModelEx.processRangeHighlightersOverlappingWith(start, end, processor) + return processor.isFound + } + private class ToggleAreaThumbRenderer(val onClick: Runnable) : LineMarkerRenderer, ActiveGutterRenderer { private fun getDrawArea(editor: Editor): Pair { val gutter = (editor as EditorEx).gutterComponentEx @@ -452,13 +486,23 @@ object LocalTrackerDiffUtil { } val affectedRanges = getAffectedRanges(selectedLines) - val isPartialBlockSelection = affectedRanges.isEmpty() || affectedRanges.any { isPartiallySelected(it, selectedLines) } + val isPartialBlockSelection = affectedRanges.any { isPartiallySelected(it, selectedLines) } - if (isPartialBlockSelection) { + if (affectedRanges.isEmpty()) { e.presentation.text = when { isExclude -> ActionsBundle.message("action.Vcs.Diff.ExcludeChangedLinesFromCommit.text") else -> ActionsBundle.message("action.Vcs.Diff.IncludeChangedLinesIntoCommit.text") } + e.presentation.isEnabled = false + } + else if (isPartialBlockSelection) { + val willSplit = affectedRanges.any { it.exclusionState !is RangeExclusionState.Partial } + val rangesCount = if (willSplit) affectedRanges.size else 0 + val selectionSize = (selectedLines.localLines?.cardinality() ?: 0) + (selectedLines.vcsLines?.cardinality() ?: 0) + e.presentation.text = when { + isExclude -> ActionsBundle.message("action.Vcs.Diff.ExcludeChangedLinesFromCommit.template.text", rangesCount, selectionSize) + else -> ActionsBundle.message("action.Vcs.Diff.IncludeChangedLinesIntoCommit.template.text", rangesCount, selectionSize) + } e.presentation.isEnabled = affectedRanges.any { val selectionState = checkPartialSelectionState(it, selectedLines) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/SimpleLocalChangeListDiffViewer.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/SimpleLocalChangeListDiffViewer.java index 8c5b64ac6b21..7cc8929770dd 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/SimpleLocalChangeListDiffViewer.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/SimpleLocalChangeListDiffViewer.java @@ -13,7 +13,9 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.ex.EditorGutterComponentEx; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; @@ -23,6 +25,8 @@ import com.intellij.openapi.vcs.changes.actions.diff.lst.LocalTrackerDiffUtil.Lo import com.intellij.openapi.vcs.changes.actions.diff.lst.LocalTrackerDiffUtil.SelectedTrackerLine; import com.intellij.openapi.vcs.changes.actions.diff.lst.LocalTrackerDiffUtil.ToggleableLineRange; import com.intellij.openapi.vcs.ex.RangeExclusionState; +import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.components.BorderLayoutPanel; import one.util.streamex.StreamEx; @@ -31,6 +35,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.*; public class SimpleLocalChangeListDiffViewer extends SimpleDiffViewer { @@ -40,6 +46,7 @@ public class SimpleLocalChangeListDiffViewer extends SimpleDiffViewer { private final LocalTrackerDiffUtil.LocalTrackerActionProvider myTrackerActionProvider; private final LocalTrackerDiffUtil.ExcludeAllCheckboxPanel myExcludeAllCheckboxPanel; + private final GutterCheckboxMouseMotionListener myGutterCheckboxMouseMotionListener; private final @NotNull List myToggleExclusionsHighlighters = new ArrayList<>(); @@ -54,6 +61,9 @@ public class SimpleLocalChangeListDiffViewer extends SimpleDiffViewer { myExcludeAllCheckboxPanel.init(myLocalRequest, myAllowExcludeChangesFromCommit); LocalTrackerDiffUtil.installTrackerListener(this, myLocalRequest); + + myGutterCheckboxMouseMotionListener = new GutterCheckboxMouseMotionListener(); + myGutterCheckboxMouseMotionListener.install(); } @NotNull @@ -181,6 +191,8 @@ public class SimpleLocalChangeListDiffViewer extends SimpleDiffViewer { operation.dispose(); } myToggleExclusionsHighlighters.clear(); + + myGutterCheckboxMouseMotionListener.destroyHoverHighlighter(); } private @NotNull Runnable applyGutterOperations(@NotNull List toggleableLineRanges) { @@ -455,4 +467,78 @@ public class SimpleLocalChangeListDiffViewer extends SimpleDiffViewer { } } } + + private class GutterCheckboxMouseMotionListener { + private @Nullable RangeHighlighter myHighlighter; + + public void install() { + for (Side side : Side.values()) { + MyGutterMouseListener listener = new MyGutterMouseListener(side); + getEditor(side).getGutterComponentEx().addMouseListener(listener); + getEditor(side).getGutterComponentEx().addMouseMotionListener(listener); + } + } + + public void destroyHoverHighlighter() { + if (myHighlighter != null) { + myHighlighter.dispose(); + myHighlighter = null; + } + } + + private void updateHoverHighlighter(@NotNull Side side, int line) { + MySimpleDiffChange change = ObjectUtils.tryCast(ContainerUtil.find(getDiffChanges(), it -> it.getStartLine(side) <= line && + it.getEndLine(side) > line), + MySimpleDiffChange.class); + if (change == null || + change.isPartiallyExcluded() || + !myLocalRequest.getChangelistId().equals(change.getChangelistId())) { + destroyHoverHighlighter(); + return; + } + + EditorEx editor = getEditor(side); + if (LocalTrackerDiffUtil.hasIconHighlighters(myProject, editor, line)) { + if (myHighlighter != null && editor.getDocument().getLineNumber(myHighlighter.getStartOffset()) != line) { + destroyHoverHighlighter(); + } + return; + } + + destroyHoverHighlighter(); + + boolean isExcludedFromCommit = change.getExclusionState() instanceof RangeExclusionState.Excluded; + myHighlighter = LocalTrackerDiffUtil.createCheckboxToggle(editor, line, isExcludedFromCommit, () -> { + LocalTrackerDiffUtil.toggleLinePartialExclusion(myTrackerActionProvider, line, side, isExcludedFromCommit); + destroyHoverHighlighter(); + }); + } + + private class MyGutterMouseListener extends MouseAdapter { + private final Side mySide; + + MyGutterMouseListener(@NotNull Side side) { + mySide = side; + } + + @Override + public void mouseMoved(MouseEvent e) { + EditorEx editor = getEditor(mySide); + EditorGutterComponentEx gutter = editor.getGutterComponentEx(); + int xOffset = DiffUtil.isMirrored(editor) ? gutter.getWidth() - e.getX() : e.getX(); + if (xOffset < gutter.getIconAreaOffset() || xOffset > gutter.getIconAreaOffset() + gutter.getIconsAreaWidth()) { + destroyHoverHighlighter(); + return; + } + + LogicalPosition position = editor.xyToLogicalPosition(e.getPoint()); + updateHoverHighlighter(mySide, position.line); + } + + @Override + public void mouseExited(MouseEvent e) { + destroyHoverHighlighter(); + } + } + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/UnifiedLocalChangeListDiffViewer.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/UnifiedLocalChangeListDiffViewer.java index 9da31066d1b3..153f92d91165 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/UnifiedLocalChangeListDiffViewer.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/lst/UnifiedLocalChangeListDiffViewer.java @@ -10,6 +10,8 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.editor.ex.EditorGutterComponentEx; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; @@ -18,6 +20,8 @@ import com.intellij.openapi.vcs.changes.actions.diff.lst.LocalTrackerDiffUtil.Li import com.intellij.openapi.vcs.changes.actions.diff.lst.LocalTrackerDiffUtil.SelectedTrackerLine; import com.intellij.openapi.vcs.changes.actions.diff.lst.LocalTrackerDiffUtil.ToggleableLineRange; import com.intellij.openapi.vcs.ex.RangeExclusionState; +import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.components.BorderLayoutPanel; import one.util.streamex.StreamEx; @@ -26,6 +30,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.BitSet; import java.util.Collections; @@ -38,6 +44,7 @@ public class UnifiedLocalChangeListDiffViewer extends UnifiedDiffViewer { private final LocalTrackerDiffUtil.LocalTrackerActionProvider myTrackerActionProvider; private final LocalTrackerDiffUtil.ExcludeAllCheckboxPanel myExcludeAllCheckboxPanel; + private final GutterCheckboxMouseMotionListener myGutterCheckboxMouseMotionListener; private final @NotNull List myToggleExclusionsHighlighters = new ArrayList<>(); @@ -52,6 +59,9 @@ public class UnifiedLocalChangeListDiffViewer extends UnifiedDiffViewer { myExcludeAllCheckboxPanel.init(myLocalRequest, myAllowExcludeChangesFromCommit); LocalTrackerDiffUtil.installTrackerListener(this, myLocalRequest); + + myGutterCheckboxMouseMotionListener = new GutterCheckboxMouseMotionListener(); + myGutterCheckboxMouseMotionListener.install(); } @Nullable @@ -212,6 +222,8 @@ public class UnifiedLocalChangeListDiffViewer extends UnifiedDiffViewer { operation.dispose(); } myToggleExclusionsHighlighters.clear(); + + myGutterCheckboxMouseMotionListener.destroyHoverHighlighter(); } private @NotNull Runnable applyGutterOperations(@NotNull UnifiedFragmentBuilder builder, @@ -427,4 +439,92 @@ public class UnifiedLocalChangeListDiffViewer extends UnifiedDiffViewer { return new SelectedTrackerLine(deletions, additions); } } + + private class GutterCheckboxMouseMotionListener { + private @Nullable RangeHighlighter myHighlighter; + + public void install() { + MyGutterMouseListener listener = new MyGutterMouseListener(); + myEditor.getGutterComponentEx().addMouseListener(listener); + myEditor.getGutterComponentEx().addMouseMotionListener(listener); + } + + public void destroyHoverHighlighter() { + if (myHighlighter != null) { + myHighlighter.dispose(); + myHighlighter = null; + } + } + + private void updateHoverHighlighter(int editorLine) { + List changes = getDiffChanges(); + if (changes == null) { + destroyHoverHighlighter(); + return; + } + + MyUnifiedDiffChange change = ObjectUtils.tryCast(ContainerUtil.find(changes, it -> it.getLine1() <= editorLine && + it.getLine2() > editorLine), + MyUnifiedDiffChange.class); + if (change == null || + change.isPartiallyExcluded() || + !myLocalRequest.getChangelistId().equals(change.getChangelistId())) { + destroyHoverHighlighter(); + return; + } + + int rightLine = transferLineFromOnesideStrict(Side.RIGHT, editorLine); + int leftLine = transferLineFromOnesideStrict(Side.LEFT, editorLine); + + int line; + Side side; + if (rightLine != -1) { + line = rightLine; + side = Side.RIGHT; + } + else if (leftLine != -1) { + line = leftLine; + side = Side.LEFT; + } + else { + destroyHoverHighlighter(); + return; + } + + if (LocalTrackerDiffUtil.hasIconHighlighters(myProject, myEditor, editorLine)) { + if (myHighlighter != null && myEditor.getDocument().getLineNumber(myHighlighter.getStartOffset()) != editorLine) { + destroyHoverHighlighter(); + } + return; + } + + destroyHoverHighlighter(); + + boolean isExcludedFromCommit = change.getExclusionState() instanceof RangeExclusionState.Excluded; + myHighlighter = LocalTrackerDiffUtil.createCheckboxToggle(myEditor, editorLine, isExcludedFromCommit, () -> { + LocalTrackerDiffUtil.toggleLinePartialExclusion(myTrackerActionProvider, line, side, isExcludedFromCommit); + destroyHoverHighlighter(); + }); + } + + private class MyGutterMouseListener extends MouseAdapter { + @Override + public void mouseMoved(MouseEvent e) { + EditorGutterComponentEx gutter = myEditor.getGutterComponentEx(); + int xOffset = DiffUtil.isMirrored(myEditor) ? gutter.getWidth() - e.getX() : e.getX(); + if (xOffset < gutter.getIconAreaOffset() || xOffset > gutter.getIconAreaOffset() + gutter.getIconsAreaWidth()) { + destroyHoverHighlighter(); + return; + } + + LogicalPosition position = myEditor.xyToLogicalPosition(e.getPoint()); + updateHoverHighlighter(position.line); + } + + @Override + public void mouseExited(MouseEvent e) { + destroyHoverHighlighter(); + } + } + } } diff --git a/platform/warmup/src/com/intellij/warmup/PlatformBuildWarmupSupport.kt b/platform/warmup/src/com/intellij/warmup/PlatformBuildWarmupSupport.kt index 4f9059c84b20..4beedc390ae7 100644 --- a/platform/warmup/src/com/intellij/warmup/PlatformBuildWarmupSupport.kt +++ b/platform/warmup/src/com/intellij/warmup/PlatformBuildWarmupSupport.kt @@ -3,6 +3,7 @@ package com.intellij.warmup import com.intellij.openapi.project.Project import com.intellij.task.ProjectTaskManager +import com.intellij.task.impl.ProjectTaskManagerImpl import org.jetbrains.concurrency.asDeferred internal class PlatformBuildWarmupSupport(val project: Project) : ProjectBuildWarmupSupport { @@ -13,6 +14,7 @@ internal class PlatformBuildWarmupSupport(val project: Project) : ProjectBuildWa } override suspend fun buildProjectWithStatus(rebuild: Boolean): WarmupBuildStatus.InvocationStatus { + ProjectTaskManagerImpl.putBuildOriginator(project, this.javaClass) val projectTaskManager = ProjectTaskManager.getInstance(project) val result = (if (rebuild) projectTaskManager.rebuildAllModules() else projectTaskManager.buildAllModules()).asDeferred().await() diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java index 1d54380f35a3..ed8e8a51de96 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java @@ -59,6 +59,7 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu super(tree, parent, true, value); myName = name; + // todo: should be rewritten, this code passes partially initialized 'this' into a call value.computePresentation(this, XValuePlace.TREE); // add "Collecting" message only if computation is not yet done diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UnsupportedChronoFieldUnitCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UnsupportedChronoFieldUnitCallInspection.java index 670d6af7f0e8..3c54dd26c350 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UnsupportedChronoFieldUnitCallInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UnsupportedChronoFieldUnitCallInspection.java @@ -29,16 +29,19 @@ public class UnsupportedChronoFieldUnitCallInspection extends AbstractBaseJavaLo return new JavaElementVisitor() { @Override public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) { - PsiMethod method = call.resolveMethod(); - if (method == null) return; - String methodName = method.getName(); + String methodName = call.getMethodExpression().getReferenceName(); if (!"get".equals(methodName) && !"getLong".equals(methodName) && !"with".equals(methodName) && !"plus".equals(methodName) && !"minus".equals(methodName)) { return; } + if (!myMatcher.test(call)) { return; } + + PsiMethod method = call.resolveMethod(); + if (method == null) return; + int fieldArgumentIndex = 1; if ("get".equals(methodName) || "getLong".equals(methodName) || "with".equals(methodName)) { fieldArgumentIndex = 0; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/StaticInheritanceFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/StaticInheritanceFix.java index af7b789f81ca..acd6199eebfc 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/StaticInheritanceFix.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/StaticInheritanceFix.java @@ -1,45 +1,31 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ig.inheritance; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.QuickFixFactory; -import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo; +import com.intellij.codeInspection.ModCommands; import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.java.analysis.JavaAnalysisBundle; -import com.intellij.openapi.application.ReadAction; -import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.Task; +import com.intellij.modcommand.ModCommand; +import com.intellij.modcommand.ModCommandAction; +import com.intellij.modcommand.ModCommandQuickFix; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.impl.DebugUtil; -import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Query; import com.siyeh.InspectionGadgetsBundle; -import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.psiutils.ClassUtils; import org.jetbrains.annotations.NotNull; -class StaticInheritanceFix extends InspectionGadgetsFix { +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +class StaticInheritanceFix extends ModCommandQuickFix { private final boolean myReplaceInWholeProject; StaticInheritanceFix(boolean replaceInWholeProject) { @@ -61,17 +47,8 @@ class StaticInheritanceFix extends InspectionGadgetsFix { } @Override - public boolean startInWriteAction() { - return false; - } - - @Override - public void doFix(final @NotNull Project project, @NotNull ProblemDescriptor descriptor) { - doFix(project, descriptor, false); - } - - private void doFix(final Project project, ProblemDescriptor descriptor, boolean inPreview) { - final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement)descriptor.getPsiElement(); + public @NotNull ModCommand perform(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement)descriptor.getStartElement(); final PsiClass iface = (PsiClass)referenceElement.resolve(); assert iface != null; final PsiField[] allFields = iface.getAllFields(); @@ -80,83 +57,58 @@ class StaticInheritanceFix extends InspectionGadgetsFix { assert implementingClass != null; final PsiFile file = implementingClass.getContainingFile(); - if (inPreview) { - processUsages(allFields, implementingClass, project, true, iface, file); - } else { - ProgressManager.getInstance().run(new Task.Modal(project, - JavaAnalysisBundle.message("static.inheritrance.fix.replace.progress", iface.getName()), false) { - - @Override - public void run(@NotNull ProgressIndicator indicator) { - processUsages(allFields, implementingClass, project, false, iface, file); - } - }); - } + return ModCommands.psiUpdate(ModCommandAction.ActionContext.from(descriptor), updater -> + processUsages(allFields, implementingClass, project, iface, file, updater)); } - private void processUsages(PsiField[] allFields, - PsiClass implementingClass, - Project project, - boolean inPreview, - PsiClass iface, - PsiFile file) { + private void processUsages(@NotNull PsiField @NotNull [] allFields, + PsiClass implementingClass, + Project project, + PsiClass iface, + PsiFile file, + @NotNull ModPsiUpdater updater) { + Map replacements = findReplacements(allFields, implementingClass, updater); + PsiClassType classType = JavaPsiFacade.getInstance(project).getElementFactory().createType(iface); + IntentionAction fix = QuickFixFactory.getInstance().createExtendsListFix(updater.getWritable(implementingClass), classType, false); + fix.invoke(project, null, file); + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); + replacements.forEach((referenceExpression, containingClass) -> { + final PsiReferenceExpression qualified = (PsiReferenceExpression) + elementFactory.createExpressionFromText("xxx." + referenceExpression.getText(), referenceExpression); + final PsiReferenceExpression newReference = (PsiReferenceExpression)referenceExpression.replace(qualified); + final PsiReferenceExpression qualifier = (PsiReferenceExpression)newReference.getQualifierExpression(); + assert qualifier != null : DebugUtil.psiToString(newReference, true); + qualifier.bindToElement(containingClass); + }); + } + + @NotNull + private Map findReplacements(@NotNull PsiField @NotNull [] allFields, + @NotNull PsiClass implementingClass, + @NotNull ModPsiUpdater updater) { + Map replacements = new LinkedHashMap<>(); for (final PsiField field : allFields) { - SearchScope scope = ReadAction.compute(() -> implementingClass.getUseScope()); - if (inPreview) { - scope = scope.intersectWith(new LocalSearchScope(file)); - } + SearchScope scope = implementingClass.getUseScope(); final Query search = ReferencesSearch.search(field, scope, false); for (PsiReference reference : search) { if (!(reference instanceof PsiReferenceExpression referenceExpression)) { continue; } if (!myReplaceInWholeProject) { - boolean isInheritor = - ReadAction.compute(() -> { - boolean isInheritor1 = false; - PsiClass aClass = PsiTreeUtil.getParentOfType(referenceExpression, PsiClass.class); - while (aClass != null) { - isInheritor1 = InheritanceUtil.isInheritorOrSelf(aClass, implementingClass, true); - if (isInheritor1) break; - aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class); - } - return isInheritor1; - }); + boolean isInheritor = false; + PsiClass aClass = PsiTreeUtil.getParentOfType(referenceExpression, PsiClass.class); + while (aClass != null) { + isInheritor = InheritanceUtil.isInheritorOrSelf(aClass, implementingClass, true); + if (isInheritor) break; + aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class); + } if (!isInheritor) continue; } - final Runnable runnable = () -> { - final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); - final PsiReferenceExpression qualified = (PsiReferenceExpression) - elementFactory.createExpressionFromText("xxx." + referenceExpression.getText(), referenceExpression); - final PsiReferenceExpression newReference = (PsiReferenceExpression)referenceExpression.replace(qualified); - final PsiReferenceExpression qualifier = (PsiReferenceExpression)newReference.getQualifierExpression(); - assert qualifier != null : DebugUtil.psiToString(newReference, true); - final PsiClass containingClass = field.getContainingClass(); - qualifier.bindToElement(containingClass); - }; - if (inPreview) { - runnable.run(); - } else { - WriteCommandAction.runWriteCommandAction(project, null, null, runnable, - ReadAction.compute(() -> referenceExpression.getContainingFile())); - } + + final PsiClass containingClass = Objects.requireNonNull(field.getContainingClass()); + replacements.put(updater.getWritable(referenceExpression), containingClass); } } - final Runnable runnable = () -> { - PsiClassType classType = JavaPsiFacade.getInstance(project).getElementFactory().createType(iface); - IntentionAction fix = QuickFixFactory.getInstance().createExtendsListFix(implementingClass, classType, false); - fix.invoke(project, null, file); - }; - if (inPreview) { - runnable.run(); - } else { - WriteCommandAction.runWriteCommandAction(project, null, null, runnable, file); - } - } - - @Override - public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull ProblemDescriptor previewDescriptor) { - doFix(project, previewDescriptor, true); - return IntentionPreviewInfo.DIFF; + return replacements; } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/StaticInheritanceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/StaticInheritanceInspection.java index 7636504368c3..a4efa40f8775 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/StaticInheritanceInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/StaticInheritanceInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.inheritance; +import com.intellij.codeInspection.LocalQuickFix; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiJavaCodeReferenceElement; @@ -22,7 +23,6 @@ import com.intellij.psi.PsiReferenceList; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; -import com.siyeh.ig.InspectionGadgetsFix; import org.jetbrains.annotations.NotNull; import java.util.HashSet; @@ -38,8 +38,8 @@ public class StaticInheritanceInspection extends BaseInspection { } @Override - protected InspectionGadgetsFix @NotNull [] buildFixes(Object... infos) { - return new InspectionGadgetsFix[]{new StaticInheritanceFix(false), new StaticInheritanceFix(true)}; + protected LocalQuickFix @NotNull [] buildFixes(Object... infos) { + return new LocalQuickFix[]{new StaticInheritanceFix(false), new StaticInheritanceFix(true)}; } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/DynamicRegexReplaceableByCompiledPatternInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/DynamicRegexReplaceableByCompiledPatternInspection.java index fc4a141a637b..48f02a59c9ba 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/DynamicRegexReplaceableByCompiledPatternInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/DynamicRegexReplaceableByCompiledPatternInspection.java @@ -1,24 +1,24 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ig.performance; -import com.intellij.codeInsight.CodeInsightUtilCore; -import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.PsiUpdateModCommandQuickFix; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.impl.AllowedApiFilterExtension; import com.intellij.psi.util.PsiUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; -import com.siyeh.ig.InspectionGadgetsFix; -import com.siyeh.ig.psiutils.ClassUtils; -import com.siyeh.ig.psiutils.CommentTracker; -import com.siyeh.ig.psiutils.ExpressionUtils; -import com.siyeh.ig.psiutils.HighlightUtils; +import com.siyeh.ig.psiutils.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.List; import java.util.Set; import java.util.regex.Matcher; @@ -29,7 +29,7 @@ public class DynamicRegexReplaceableByCompiledPatternInspection extends BaseInsp ); @Override - protected InspectionGadgetsFix buildFix(Object... infos) { + protected LocalQuickFix buildFix(Object... infos) { return new DynamicRegexReplaceableByCompiledPatternFix(); } @@ -40,17 +40,12 @@ public class DynamicRegexReplaceableByCompiledPatternInspection extends BaseInsp "dynamic.regex.replaceable.by.compiled.pattern.problem.descriptor"); } - @Override - protected boolean buildQuickFixesOnlyForOnTheFlyErrors() { - return true; - } - @Override public BaseInspectionVisitor buildVisitor() { return new DynamicRegexReplaceableByCompiledPatternVisitor(); } - private static class DynamicRegexReplaceableByCompiledPatternFix extends InspectionGadgetsFix { + private static class DynamicRegexReplaceableByCompiledPatternFix extends PsiUpdateModCommandQuickFix { @Override @NotNull @@ -60,8 +55,7 @@ public class DynamicRegexReplaceableByCompiledPatternInspection extends BaseInsp } @Override - protected void doFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - final PsiElement element = descriptor.getPsiElement(); + protected void applyFix(@NotNull Project project, @NotNull PsiElement element, @NotNull ModPsiUpdater updater) { final PsiClass aClass = ClassUtils.getContainingStaticClass(element); if (aClass == null) { return; @@ -76,21 +70,33 @@ public class DynamicRegexReplaceableByCompiledPatternInspection extends BaseInsp } final PsiExpressionList list = methodCallExpression.getArgumentList(); final PsiExpression[] expressions = list.getExpressions(); + if (expressions.length == 0) return; CommentTracker commentTracker = new CommentTracker(); - @NonNls final StringBuilder fieldText = - new StringBuilder("private static final java.util.regex.Pattern PATTERN = java.util.regex.Pattern.compile("); - final int expressionsLength = expressions.length; - if (expressionsLength > 0) { - fieldText.append(commentTracker.text(expressions[0])); - } - @NonNls final String methodName = methodExpression.getReferenceName(); + final String methodName = methodExpression.getReferenceName(); final boolean literalReplacement = "replace".equals(methodName); - if (literalReplacement) { - fieldText.append(", java.util.regex.Pattern.LITERAL"); + String regexpText = commentTracker.text(expressions[0]); + String initializer = "java.util.regex.Pattern.compile(" + regexpText + + (literalReplacement ? ", java.util.regex.Pattern.LITERAL" : "") + ")"; + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + List names = new VariableNameGenerator(aClass, VariableKind.STATIC_FINAL_FIELD) + .byExpression(factory.createExpressionFromText("__(" + regexpText + ")", null)) + .byName("PATTERN", "REGEX", "REGEXP").generateAll(true); + String name = names.get(0); + String fieldText = "private static final java.util.regex.Pattern " + name + " = "+ initializer + ";"; + final int expressionsLength = expressions.length; + PsiField fieldTemplate = factory.createFieldFromText(fieldText, element); + for (PsiField classField : aClass.getFields()) { + if (classField.hasModifierProperty(PsiModifier.STATIC) && classField.hasModifierProperty(PsiModifier.FINAL) && + fieldTemplate.getType().equals(classField.getType()) && + EquivalenceChecker.getCanonicalPsiEquivalence() + .expressionsAreEquivalent(fieldTemplate.getInitializer(), classField.getInitializer())) { + name = classField.getName(); + fieldTemplate = null; + break; + } } - fieldText.append(");"); - @NonNls final StringBuilder expressionText = new StringBuilder("PATTERN."); + @NonNls final StringBuilder expressionText = new StringBuilder(name + "."); final PsiExpression qualifier = methodExpression.getQualifierExpression(); @NonNls final String qualifierText = (qualifier == null) ? "this" : commentTracker.text(qualifier); if ("split".equals(methodName)) { @@ -130,32 +136,20 @@ public class DynamicRegexReplaceableByCompiledPatternInspection extends BaseInsp expressionText.append(')'); } - final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); - final PsiElement field = aClass.add(factory.createFieldFromText(fieldText.toString(), element)); - PsiMethodCallExpression newMethodCallExpression = - (PsiMethodCallExpression)commentTracker.replaceAndRestoreComments(methodCallExpression, expressionText.toString()); - newMethodCallExpression = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(newMethodCallExpression); - if (newMethodCallExpression == null) return; - final PsiReferenceExpression reference = getReference(newMethodCallExpression); - HighlightUtils.showRenameTemplate(aClass, (PsiNameIdentifierOwner)field, reference); + JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project); + if (fieldTemplate != null) { + PsiField field = (PsiField)aClass.add(fieldTemplate); + field = (PsiField)javaCodeStyleManager.shortenClassReferences(field); + updater.rename(field, names); + } + javaCodeStyleManager.shortenClassReferences( + commentTracker.replaceAndRestoreComments(methodCallExpression, expressionText.toString())); } private static boolean needsQuote(PsiExpression expr) { Object constExprValue = ExpressionUtils.computeConstantExpression(expr); - return !(constExprValue instanceof String) || - Matcher.quoteReplacement((String) constExprValue) != constExprValue; - } - - private static PsiReferenceExpression getReference(PsiMethodCallExpression newMethodCallExpression) { - final PsiReferenceExpression methodExpression = newMethodCallExpression.getMethodExpression(); - final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); - if (qualifierExpression instanceof PsiMethodCallExpression methodCallExpression) { - return getReference(methodCallExpression); - } - if (!(qualifierExpression instanceof PsiReferenceExpression)) { - return null; - } - return (PsiReferenceExpression)qualifierExpression; + return !(constExprValue instanceof String value) || + Matcher.quoteReplacement(value) != constExprValue; } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantExplicitChronoFieldInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantExplicitChronoFieldInspection.java index bb37d8e535fb..d4c6db2c7945 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantExplicitChronoFieldInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantExplicitChronoFieldInspection.java @@ -32,16 +32,13 @@ public class RedundantExplicitChronoFieldInspection extends AbstractBaseJavaLoca return new JavaElementVisitor() { @Override public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) { - PsiMethod method = call.resolveMethod(); - if (method == null) { - return; - } - String methodName = method.getName(); + String methodName = call.getMethodExpression().getReferenceName(); if (!"get".equals(methodName) && !"with".equals(methodName) && !"plus".equals(methodName) && !"minus".equals(methodName)) { return; } - if (!CAN_BE_SIMPLIFIED_MATCHERS.methodMatches(method)) return; + + if (!CAN_BE_SIMPLIFIED_MATCHERS.matches(call)) return; int fieldArgumentIndex = 1; if ("get".equals(methodName) || "with".equals(methodName)) { fieldArgumentIndex = 0; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_compiled_pattern/ReplaceAll.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_compiled_pattern/ReplaceAll.after.java new file mode 100644 index 000000000000..0f2b21af298e --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_compiled_pattern/ReplaceAll.after.java @@ -0,0 +1,14 @@ +import java.util.regex.Pattern; + +class Literal { + + private static final Pattern PATTERN = Pattern.compile("https://.+"); + private static final Pattern REGEX = Pattern.compile("http://.+"); + + void f(String text, String replacement) { + REGEX.matcher(text).replaceAll(replacement); + REGEX.matcher(text).replaceAll(replacement); + PATTERN.matcher(text).replaceAll(replacement); + PATTERN.matcher(text).replaceAll(replacement); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_compiled_pattern/ReplaceAll.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_compiled_pattern/ReplaceAll.java new file mode 100644 index 000000000000..a801233301d0 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_compiled_pattern/ReplaceAll.java @@ -0,0 +1,9 @@ +class Literal { + + void f(String text, String replacement) { + text.replaceAll("http://.+", replacement); + text.replaceAll("http://.+", replacement); + text.replaceAll("https://.+", replacement); + text.replaceAll("https://.+", replacement); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/DynamicRegexReplaceableByCompiledPatternFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/DynamicRegexReplaceableByCompiledPatternFixTest.java index 2303adc0d5f3..497b943b26a3 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/DynamicRegexReplaceableByCompiledPatternFixTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/DynamicRegexReplaceableByCompiledPatternFixTest.java @@ -1,6 +1,8 @@ -// Copyright 2000-2021 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. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ig.fixes.performance; +import com.intellij.testFramework.IdeaTestUtil; +import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.IGQuickFixesTestCase; import com.siyeh.ig.performance.DynamicRegexReplaceableByCompiledPatternInspection; @@ -13,21 +15,15 @@ public class DynamicRegexReplaceableByCompiledPatternFixTest extends IGQuickFixe myFixture.enableInspections(new DynamicRegexReplaceableByCompiledPatternInspection()); myRelativePath = "performance/replace_with_compiled_pattern"; myDefaultHint = InspectionGadgetsBundle.message("dynamic.regex.replaceable.by.compiled.pattern.quickfix"); - myFixture.addClass(""" - package java.util.regex;public class Pattern { public static Pattern compile(String regex, int flags) { - return null; - } public Matcher matcher(CharSequence input) { return null; }}"""); - myFixture.addClass("package java.util.regex;" + - "public class Matcher {" + - " public String replaceAll(String replacement) {" + - " return \"\";" + - " }" + - " public static String quoteReplacement(String s) {" + - " return s;" + - " }" + - "}"); } public void testLiteral() { doTest(); } public void testLiteralLiteral() { doTest(); } + public void testReplaceAll() { doTest("Fix all 'Dynamic regular expression could be replaced by compiled 'Pattern'' problems in file"); } + + @Override + protected void tuneFixture(JavaModuleFixtureBuilder builder) throws Exception { + super.tuneFixture(builder); + builder.addJdk(IdeaTestUtil.getMockJdk18Path().getPath()); + } } diff --git a/plugins/IntentionPowerPak/resources/messages/IntentionPowerPackBundle.properties b/plugins/IntentionPowerPak/resources/messages/IntentionPowerPackBundle.properties index aa8674997956..2b185d2b8fd4 100644 --- a/plugins/IntentionPowerPak/resources/messages/IntentionPowerPackBundle.properties +++ b/plugins/IntentionPowerPak/resources/messages/IntentionPowerPackBundle.properties @@ -86,6 +86,7 @@ copy.concatenated.string.to.clipboard.intention.family.name=Copy string concaten flip.expression.intention.family.name=Flip binary expression flip.setter.call.intention.family.name=Flip setter call eliminate.parentheses.intention.name=Eliminate parentheses +eliminate.parentheses.intention.title=Eliminate Parentheses reverse.for.loop.direction.intention.family.name=Reverse direction of for loop reverse.for.loop.direction.intention.name=Reverse direction of for loop replace.operator.assignment.with.postfix.expression.intention.family.name=Replace operator assignment with postfix expression @@ -133,7 +134,6 @@ inline.increment.intention.name=Inline ''{0}'' replace.assert.literal.with.assert.equals.intention.name=Replace ''{0}()'' with ''assertEquals({1}, ...)'' replace.assert.literal.with.assert.equals.intention.name2=Replace ''{0}()'' with ''assertEquals()'' replace.assert.literal.with.assert.equals.intention.name1=Replace ''{0}()'' with ''assertEquals(..., {1}, ...)'' -flip.setter.call.intention.name=Flip Setter Call adapter.to.listener.intention.name=Replace extension of ''{0}'' with ''Listener'' implementation adapter.to.listener.intention.family.name=Replace adapter extension with listener implementation change.variable.type.to.rhs.type.intention.name=Declare ''{0}'' with type ''{1}'' diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java index 745212417b9a..561bf261777b 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java @@ -33,38 +33,32 @@ public abstract class Intention extends BaseElementAtCaretIntentionAction { @Override public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element){ - final PsiElement matchingElement = findMatchingElement(element, editor); + final PsiElement matchingElement = findMatchingElement(element); if (matchingElement == null) { return; } - processIntention(editor, matchingElement); + processIntention(matchingElement); } protected abstract void processIntention(@NotNull PsiElement element); - protected void processIntention(Editor editor, @NotNull PsiElement element) { - processIntention(element); - } - @NotNull protected abstract PsiElementPredicate getElementPredicate(); @Nullable - PsiElement findMatchingElement(@Nullable PsiElement element, Editor editor) { + PsiElement findMatchingElement(@Nullable PsiElement element) { if (element == null || !JavaLanguage.INSTANCE.equals(element.getLanguage())) return null; PsiElementPredicate predicate = myPredicate.get(); + if (predicate instanceof PsiElementContextPredicate) { + throw new UnsupportedOperationException("Context predicate must be used with MCIntention"); + } while (element != null) { if (!JavaLanguage.INSTANCE.equals(element.getLanguage())) { break; } - if (predicate instanceof PsiElementEditorPredicate) { - if (((PsiElementEditorPredicate)predicate).satisfiedBy(element, editor)) { - return element; - } - } else if (predicate.satisfiedBy(element)) { return element; } @@ -78,6 +72,6 @@ public abstract class Intention extends BaseElementAtCaretIntentionAction { @Override public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - return findMatchingElement(element, editor) != null; + return findMatchingElement(element) != null; } } \ No newline at end of file diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/MCIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/MCIntention.java index b4bf172b96e9..322b4302ddfb 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/MCIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/MCIntention.java @@ -15,12 +15,12 @@ */ package com.siyeh.ipp.base; -import com.intellij.modcommand.ModPsiUpdater; import com.intellij.codeInspection.ModCommands; import com.intellij.codeInspection.util.IntentionName; import com.intellij.lang.java.JavaLanguage; import com.intellij.modcommand.ModCommand; import com.intellij.modcommand.ModCommandAction; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.concurrency.SynchronizedClearableLazy; @@ -57,19 +57,19 @@ public abstract class MCIntention implements ModCommandAction { @Nullable - PsiElement findMatchingElement(@Nullable PsiElement element) { + PsiElement findMatchingElement(@Nullable PsiElement element, ActionContext context) { if (element == null || !JavaLanguage.INSTANCE.equals(element.getLanguage())) return null; PsiElementPredicate predicate = myPredicate.get(); - if (predicate instanceof PsiElementEditorPredicate) { - throw new UnsupportedOperationException("Editor predicate is not supported"); - } while (element != null) { if (!JavaLanguage.INSTANCE.equals(element.getLanguage())) { break; } - if (predicate.satisfiedBy(element)) { + boolean satisfied = predicate instanceof PsiElementContextPredicate contextPredicate ? + contextPredicate.satisfiedBy(element, context) : + predicate.satisfiedBy(element); + if (satisfied) { return element; } element = element.getParent(); @@ -91,10 +91,10 @@ public abstract class MCIntention implements ModCommandAction { @Nullable protected PsiElement findMatchingElement(@NotNull ActionContext context) { PsiElement leaf = context.findLeaf(); - PsiElement element = findMatchingElement(leaf); + PsiElement element = findMatchingElement(leaf, context); if (element != null) return element; PsiElement leftLeaf = context.findLeafOnTheLeft(); - if (leftLeaf != leaf) return findMatchingElement(leftLeaf); + if (leftLeaf != leaf) return findMatchingElement(leftLeaf, context); return null; } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/MutablyNamedIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/MutablyNamedIntention.java index 86ff2d3d394f..87a1a4b63b10 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/MutablyNamedIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/MutablyNamedIntention.java @@ -36,7 +36,7 @@ public abstract class MutablyNamedIntention extends Intention { @Override public final boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement node) { - final PsiElement element = findMatchingElement(node, editor); + final PsiElement element = findMatchingElement(node); if (element == null) { return false; } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/PsiElementEditorPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/PsiElementContextPredicate.java similarity index 67% rename from plugins/IntentionPowerPak/src/com/siyeh/ipp/base/PsiElementEditorPredicate.java rename to plugins/IntentionPowerPak/src/com/siyeh/ipp/base/PsiElementContextPredicate.java index 639a4aaa9254..b38193b66e1a 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/PsiElementEditorPredicate.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/PsiElementContextPredicate.java @@ -15,15 +15,15 @@ */ package com.siyeh.ipp.base; -import com.intellij.openapi.editor.Editor; +import com.intellij.modcommand.ModCommandAction; import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; -public abstract class PsiElementEditorPredicate implements PsiElementPredicate { - public abstract boolean satisfiedBy(PsiElement element, @Nullable Editor editor); +public abstract class PsiElementContextPredicate implements PsiElementPredicate { + public abstract boolean satisfiedBy(PsiElement element, @NotNull ModCommandAction.ActionContext context); @Override public boolean satisfiedBy(PsiElement element) { - return satisfiedBy(element, null); + throw new UnsupportedOperationException("Context must be provided"); } } \ No newline at end of file diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/PsiElementPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/PsiElementPredicate.java index 5c016f7fa343..616a4095945d 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/PsiElementPredicate.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/PsiElementPredicate.java @@ -19,7 +19,8 @@ import com.intellij.psi.PsiElement; public interface PsiElementPredicate { /** - * Use {@link PsiElementEditorPredicate} when editor selection should be checked + * Check if element satisfies the predicate. All parent elements are supplied here until the satisfying element is found. + * Use {@link PsiElementContextPredicate} if you need caret position and/or selection. */ boolean satisfiedBy(PsiElement element); } \ No newline at end of file diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/datetime/ShowDateTimeExampleOutputIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/datetime/ShowDateTimeExampleOutputIntention.java index a77c6021e435..9f1680f18b01 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/datetime/ShowDateTimeExampleOutputIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/datetime/ShowDateTimeExampleOutputIntention.java @@ -1,19 +1,18 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ipp.datetime; -import com.intellij.codeInsight.hint.HintManager; -import com.intellij.codeInsight.intention.HighPriorityAction; -import com.intellij.openapi.editor.Editor; +import com.intellij.codeInsight.intention.PriorityAction; +import com.intellij.codeInspection.ModCommands; +import com.intellij.modcommand.ModCommand; +import com.intellij.modcommand.PsiBasedModCommandAction; import com.intellij.psi.*; import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiUtil; import com.siyeh.IntentionPowerPackBundle; import com.siyeh.ig.callMatcher.CallMatcher; import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.TypeUtils; -import com.siyeh.ipp.base.Intention; -import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.text.SimpleDateFormat; import java.time.LocalDateTime; @@ -25,7 +24,11 @@ import static com.siyeh.ig.callMatcher.CallMatcher.*; /** * @author Bas Leijdekkers */ -public class ShowDateTimeExampleOutputIntention extends Intention implements HighPriorityAction { +public class ShowDateTimeExampleOutputIntention extends PsiBasedModCommandAction { + + public ShowDateTimeExampleOutputIntention() { + super(PsiExpression.class); + } private static final CallMatcher DATE_TIME_FORMATTER_METHODS = anyOf( staticCall("java.time.format.DateTimeFormatter", "ofPattern"), @@ -33,107 +36,87 @@ public class ShowDateTimeExampleOutputIntention extends Intention implements Hig ); private static final CallMatcher SIMPLE_DATE_FORMAT_METHODS = instanceCall("java.text.SimpleDateFormat", "applyPattern", "applyLocalizedPattern").parameterTypes(CommonClassNames.JAVA_LANG_STRING); - Boolean dateTimeFormatter = null; @Override public @NotNull String getFamilyName() { return IntentionPowerPackBundle.message("show.example.date.time.output.intention.family.name"); } + enum Formatter { + NONE, DATE_TIME_FORMATTER, SIMPLE_DATE_FORMAT + } + + private static @NotNull Formatter getFormatter(@NotNull PsiExpression expression) { + if (!(expression.getParent() instanceof PsiExpressionList parent)) return Formatter.NONE; + final PsiType type = expression.getType(); + if (!TypeUtils.isJavaLangString(type)) return Formatter.NONE; + final PsiElement grandParent = parent.getParent(); + if (grandParent instanceof PsiMethodCallExpression call) { + if (SIMPLE_DATE_FORMAT_METHODS.test(call)) { + return Formatter.SIMPLE_DATE_FORMAT; + } + if (DATE_TIME_FORMATTER_METHODS.test(call)) { + return Formatter.DATE_TIME_FORMATTER; + } + return Formatter.NONE; + } + if (grandParent instanceof PsiNewExpression newExpression) { + final PsiJavaCodeReferenceElement classReference = newExpression.getClassReference(); + if (classReference == null || !"SimpleDateFormat".equals(classReference.getReferenceName())) { + return Formatter.NONE; + } + final PsiElement target = classReference.resolve(); + if (!(target instanceof PsiClass aClass)) { + return Formatter.NONE; + } + if (!InheritanceUtil.isInheritor(aClass, "java.text.SimpleDateFormat")) { + return Formatter.NONE; + } + return Formatter.SIMPLE_DATE_FORMAT; + } + return Formatter.NONE; + } + @Override - public @NotNull String getText() { - return getFamilyName(); + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiExpression expression) { + while (expression.getParent() instanceof PsiExpression parent) { + expression = parent; + } + Formatter formatter = getFormatter(expression); + if (formatter == Formatter.NONE) return null; + final Object value = ExpressionUtils.computeConstantExpression(expression); + return value instanceof String ? Presentation.of(getFamilyName()).withPriority(PriorityAction.Priority.HIGH) : null; } @Override - public boolean startInWriteAction() { - return false; - } - - @Override - protected @NotNull PsiElementPredicate getElementPredicate() { - return new PsiElementPredicate() { - @Override - public boolean satisfiedBy(PsiElement element) { - if (!(element instanceof PsiExpression expression)) { - return false; + protected @NotNull ModCommand perform(@NotNull ActionContext context, @NotNull PsiExpression expression) { + while (expression.getParent() instanceof PsiExpression parent) { + expression = parent; + } + Formatter formatter = getFormatter(expression); + final Object value = ExpressionUtils.computeConstantExpression(expression); + if (!(value instanceof String)) return ModCommands.nop(); + return switch (formatter) { + case NONE -> ModCommands.nop(); + case DATE_TIME_FORMATTER -> { + try { + final DateTimeFormatter fmt = DateTimeFormatter.ofPattern((String)value); + //noinspection HardCodedStringLiteral + yield ModCommands.info(LocalDateTime.now().format(fmt)); } - final PsiType type = expression.getType(); - if (!TypeUtils.isJavaLangString(type)) { - return false; + catch (IllegalArgumentException e) { + yield ModCommands.error(IntentionPowerPackBundle.message("invalid.pattern.hint.text")); } - PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression).getParent(); - if (parent == null) return false; - final PsiElement grandParent = parent.getParent(); - if (grandParent instanceof PsiMethodCallExpression) { - if (SIMPLE_DATE_FORMAT_METHODS.test((PsiMethodCallExpression)grandParent)) { - dateTimeFormatter = false; - } - else if (DATE_TIME_FORMATTER_METHODS.test((PsiMethodCallExpression)grandParent)) { - dateTimeFormatter = true; - } - else { - return false; - } + } + case SIMPLE_DATE_FORMAT -> { + try { + final SimpleDateFormat format = new SimpleDateFormat((String)value); + yield ModCommands.info(format.format(new Date())); } - else if (grandParent instanceof PsiNewExpression newExpression) { - final PsiJavaCodeReferenceElement classReference = newExpression.getClassReference(); - if (classReference == null || !"SimpleDateFormat".equals(classReference.getReferenceName())) { - return false; - } - final PsiElement target = classReference.resolve(); - if (!(target instanceof PsiClass aClass)) { - return false; - } - if (!InheritanceUtil.isInheritor(aClass, "java.text.SimpleDateFormat")) { - return false; - } - dateTimeFormatter = false; - return true; + catch (IllegalArgumentException e) { + yield ModCommands.error(IntentionPowerPackBundle.message("invalid.pattern.hint.text")); } - else { - return false; - } - final Object value = ExpressionUtils.computeConstantExpression(expression); - return value instanceof String; } }; } - - @Override - protected void processIntention(Editor editor, @NotNull PsiElement element) { - if (!(element instanceof PsiExpression expression) || dateTimeFormatter == null) { - return; - } - final Object value = ExpressionUtils.computeConstantExpression(expression); - if (!(value instanceof String)) { - return; - } - String example; - if (dateTimeFormatter) { - try { - final DateTimeFormatter formatter = DateTimeFormatter.ofPattern((String)value); - //noinspection HardCodedStringLiteral - example = LocalDateTime.now().format(formatter); - } - catch (IllegalArgumentException e) { - example = IntentionPowerPackBundle.message("invalid.pattern.hint.text"); - } - } - else { - try { - final SimpleDateFormat format = new SimpleDateFormat((String)value); - example = format.format(new Date()); - } - catch (IllegalArgumentException e) { - example = IntentionPowerPackBundle.message("invalid.pattern.hint.text"); - } - } - HintManager.getInstance().showInformationHint(editor, example); - } - - @Override - protected void processIntention(@NotNull PsiElement element) { - assert false; - } } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipSetterCallIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipSetterCallIntention.java index ebcc7bb31d00..6078a3070735 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipSetterCallIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipSetterCallIntention.java @@ -1,17 +1,15 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ipp.expression; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.project.Project; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.psi.*; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiUtil; import com.siyeh.IntentionPowerPackBundle; import com.siyeh.ig.psiutils.CommentTracker; import com.siyeh.ig.psiutils.ExpressionUtils; -import com.siyeh.ipp.base.Intention; -import com.siyeh.ipp.base.PsiElementEditorPredicate; +import com.siyeh.ipp.base.MCIntention; +import com.siyeh.ipp.base.PsiElementContextPredicate; import com.siyeh.ipp.base.PsiElementPredicate; import com.siyeh.ipp.psiutils.PsiSelectionSearcher; import org.jetbrains.annotations.NotNull; @@ -22,7 +20,11 @@ import java.util.List; /** * @author Konstantin Bulenkov */ -public class FlipSetterCallIntention extends Intention { +public class FlipSetterCallIntention extends MCIntention { + @Override + protected @Nullable String getTextForElement(@NotNull PsiElement element) { + return getFamilyName(); + } @Override public @NotNull String getFamilyName() { @@ -30,27 +32,23 @@ public class FlipSetterCallIntention extends Intention { } @Override - public @NotNull String getText() { - return IntentionPowerPackBundle.message("flip.setter.call.intention.name"); - } - - @Override - protected void processIntention(@NotNull PsiElement element) { - final Project project = element.getProject(); - final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - if (editor != null) { + protected void processIntention(@NotNull ActionContext context, @NotNull ModPsiUpdater updater, @NotNull PsiElement element) { + if (!context.selection().isEmpty()) { final List methodCalls = - PsiSelectionSearcher.searchElementsInSelection(editor, project, PsiMethodCallExpression.class, false); + PsiSelectionSearcher.searchElementsInSelection(element.getContainingFile(), context.selection(), PsiMethodCallExpression.class, false); if (!methodCalls.isEmpty()) { for (PsiMethodCallExpression call : methodCalls) { - flipCall(call); + PsiMethodCallExpression flipped = flipCall(call); + if (flipped != null) { + updater.highlight(flipped); + updater.moveTo(flipped); + } } - editor.getSelectionModel().removeSelection(); return; } } - if (element instanceof PsiMethodCallExpression) { - flipCall((PsiMethodCallExpression)element); + if (element instanceof PsiMethodCallExpression call) { + flipCall(call); } } @@ -60,24 +58,24 @@ public class FlipSetterCallIntention extends Intention { return new SetterCallPredicate(); } - private static void flipCall(PsiMethodCallExpression call) { + private static PsiMethodCallExpression flipCall(PsiMethodCallExpression call) { final PsiExpression[] arguments = call.getArgumentList().getExpressions(); - if (arguments.length != 1) return; + if (arguments.length != 1) return null; final PsiExpression argument = PsiUtil.skipParenthesizedExprDown(arguments[0]); - if (!(argument instanceof PsiMethodCallExpression call2)) return; + if (!(argument instanceof PsiMethodCallExpression call2)) return null; final PsiExpression qualifierExpression1 = ExpressionUtils.getEffectiveQualifier(call.getMethodExpression()); final PsiExpression qualifierExpression2 = ExpressionUtils.getEffectiveQualifier(call2.getMethodExpression()); - if (qualifierExpression1 == null || qualifierExpression2 == null) return; + if (qualifierExpression1 == null || qualifierExpression2 == null) return null; final PsiMethod setter = call.resolveMethod(); final PsiMethod getter = call2.resolveMethod(); final PsiMethod get = PropertyUtil.getReversePropertyMethod(setter); final PsiMethod set = PropertyUtil.getReversePropertyMethod(getter); - if (get == null || set == null) return; + if (get == null || set == null) return null; CommentTracker ct = new CommentTracker(); final String text = ct.text(qualifierExpression2) + "." + set.getName() + "(" + ct.text(qualifierExpression1) + "." + get.getName() + "())"; - ct.replaceAndRestoreComments(call, text); + return (PsiMethodCallExpression)ct.replaceAndRestoreComments(call, text); } private static boolean isSetGetMethodCall(PsiElement element) { @@ -109,12 +107,12 @@ public class FlipSetterCallIntention extends Intention { return parameter.getType().equals(getter.getReturnType()); } - private static class SetterCallPredicate extends PsiElementEditorPredicate { + private static class SetterCallPredicate extends PsiElementContextPredicate { @Override - public boolean satisfiedBy(PsiElement element, @Nullable Editor editor) { - if (editor != null && editor.getSelectionModel().hasSelection()) { + public boolean satisfiedBy(PsiElement element, @NotNull ActionContext context) { + if (!context.selection().isEmpty()) { final List list = - PsiSelectionSearcher.searchElementsInSelection(editor, element.getProject(), PsiMethodCallExpression.class, false); + PsiSelectionSearcher.searchElementsInSelection(context.file(), context.selection(), PsiMethodCallExpression.class, false); for (PsiMethodCallExpression methodCallExpression : list) { if (isSetGetMethodCall(methodCallExpression)) { return true; diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/eliminate/EliminateParenthesesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/eliminate/EliminateParenthesesIntention.java index be7d59a7f4bb..2811885c7ca6 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/eliminate/EliminateParenthesesIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/eliminate/EliminateParenthesesIntention.java @@ -1,17 +1,14 @@ -// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ipp.expression.eliminate; -import com.intellij.codeInsight.intention.BaseElementAtCaretIntentionAction; -import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.NlsContexts; -import com.intellij.openapi.util.Pass; +import com.intellij.codeInspection.ModCommands; +import com.intellij.modcommand.ModChooseAction; +import com.intellij.modcommand.ModCommand; +import com.intellij.modcommand.ModCommandAction; +import com.intellij.modcommand.PsiBasedModCommandAction; import com.intellij.psi.*; import com.intellij.psi.util.PsiExpressionTrimRenderer; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.refactoring.IntroduceTargetChooser; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.siyeh.IntentionPowerPackBundle; @@ -24,54 +21,33 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; -public final class EliminateParenthesesIntention extends BaseElementAtCaretIntentionAction { - private static final Pass ELIMINATE_CALLBACK = new Pass<>() { - @Override - public void pass(@NotNull PsiParenthesizedExpression expression) { - WriteCommandAction.writeCommandAction(expression.getProject(), expression.getContainingFile()) - .withName(getName()) - .run(() -> replaceExpression(expression)); - } - }; +public final class EliminateParenthesesIntention extends PsiBasedModCommandAction { + public EliminateParenthesesIntention() { + super(PsiJavaToken.class); + } @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull @Override public String getFamilyName() { - return getName(); - } - - @NotNull - @Override - public String getText() { - return getName(); - } - - private static @NlsContexts.Command String getName() { return IntentionPowerPackBundle.message("eliminate.parentheses.intention.name"); } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - List possibleInnerExpressions = getPossibleInnerExpressions(element); - return possibleInnerExpressions != null && !possibleInnerExpressions.isEmpty(); + protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiJavaToken leaf) { + List possibleInnerExpressions = getPossibleInnerExpressions(leaf); + return possibleInnerExpressions != null && !possibleInnerExpressions.isEmpty() ? Presentation.of( + IntentionPowerPackBundle.message("eliminate.parentheses.intention.name")) : null; } @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { - List possibleInnerExpressions = getPossibleInnerExpressions(element); - if (possibleInnerExpressions == null) return; - processInnerExpression(editor, possibleInnerExpressions); - } - - private static void processInnerExpression(@Nullable Editor editor, @NotNull List expressions) { - PsiParenthesizedExpression firstItem = ContainerUtil.getFirstItem(expressions); - if (expressions.size() == 1 || firstItem != null && !firstItem.isPhysical()) { - replaceExpression(expressions.get(0)); - return; - } - if (expressions.isEmpty() || editor == null) return; - IntroduceTargetChooser.showChooser(editor, expressions, ELIMINATE_CALLBACK, new PsiExpressionTrimRenderer.RenderFunction()); + protected @NotNull ModCommand perform(@NotNull ActionContext context, @NotNull PsiJavaToken leaf) { + List possibleInnerExpressions = getPossibleInnerExpressions(leaf); + if (possibleInnerExpressions == null) return ModCommands.nop(); + List actions = ContainerUtil.map( + possibleInnerExpressions, + expr -> ModCommands.psiUpdateStep(expr, PsiExpressionTrimRenderer.render(expr), (e, u) -> replaceExpression(e))); + return new ModChooseAction(IntentionPowerPackBundle.message("eliminate.parentheses.intention.title"), actions); } private static void replaceExpression(@NotNull PsiParenthesizedExpression parenthesized) { diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/PsiSelectionSearcher.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/PsiSelectionSearcher.java index 26d9bbafce6c..f283011ef063 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/PsiSelectionSearcher.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/PsiSelectionSearcher.java @@ -1,14 +1,11 @@ -// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ipp.psiutils; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.SelectionModel; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.UnfairTextRange; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; @@ -24,24 +21,17 @@ public final class PsiSelectionSearcher { /** * Searches elements in selection * - * @param editor editor to get text selection - * @param project Project - * @param filter PsiElement filter, e.g. PsiMethodCallExpression.class + * @param file file to search in + * @param selection selected range + * @param filter PsiElement filter, e.g. PsiMethodCallExpression.class * @param searchChildrenOfFound if true, visitor will look for matching elements in the children of a found element, otherwise will not look inside found element. - * @param type based on PsiElement type + * @param type based on PsiElement type * @return elements in selection */ @NotNull - public static List searchElementsInSelection(Editor editor, - Project project, - final Class filter, - final boolean searchChildrenOfFound) { - final SelectionModel selectionModel = editor.getSelectionModel(); - if (!selectionModel.hasSelection()) { - return Collections.emptyList(); - } - final TextRange selection = new UnfairTextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); - final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + public static List searchElementsInSelection(@Nullable PsiFile file, + @NotNull TextRange selection, + @NotNull Class filter, boolean searchChildrenOfFound) { if (file == null || file instanceof PsiCompiledElement) { return Collections.emptyList(); } @@ -53,8 +43,8 @@ public final class PsiSelectionSearcher { if (!selection.intersects(element.getTextRange())) { return; } - if (filter.isAssignableFrom(element.getClass())) { - results.add((T)element); + if (filter.isInstance(element)) { + results.add(filter.cast(element)); if (!searchChildrenOfFound) { return; } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/ReplaceOctalEscapeWithUnicodeEscapeIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/ReplaceOctalEscapeWithUnicodeEscapeIntention.java index 35a1fdf7c002..a09d5c496137 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/ReplaceOctalEscapeWithUnicodeEscapeIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/ReplaceOctalEscapeWithUnicodeEscapeIntention.java @@ -1,17 +1,15 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ipp.unicode; -import com.intellij.openapi.editor.CaretModel; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLiteralExpression; import com.siyeh.IntentionPowerPackBundle; import com.siyeh.ig.PsiReplacementUtil; -import com.siyeh.ipp.base.Intention; -import com.siyeh.ipp.base.PsiElementEditorPredicate; +import com.siyeh.ipp.base.MCIntention; +import com.siyeh.ipp.base.PsiElementContextPredicate; import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -20,7 +18,7 @@ import org.jetbrains.annotations.Nullable; /** * @author Bas Leijdekkers */ -public class ReplaceOctalEscapeWithUnicodeEscapeIntention extends Intention { +public class ReplaceOctalEscapeWithUnicodeEscapeIntention extends MCIntention { @Override public @NotNull String getFamilyName() { @@ -28,23 +26,18 @@ public class ReplaceOctalEscapeWithUnicodeEscapeIntention extends Intention { } @Override - public @NotNull String getText() { + protected @Nullable String getTextForElement(@NotNull PsiElement element) { return IntentionPowerPackBundle.message("replace.octal.escape.with.unicode.escape.intention.name"); } @Override - protected void processIntention(@NotNull PsiElement element) {} - - @Override - protected void processIntention(Editor editor, @NotNull PsiElement element) { - final SelectionModel selectionModel = editor.getSelectionModel(); - if (selectionModel.hasSelection()) { + protected void processIntention(@NotNull ActionContext context, @NotNull ModPsiUpdater updater, @NotNull PsiElement element) { + TextRange selection = context.selection(); + if (!selection.isEmpty()) { // does not check if octal escape is inside char or string literal (garbage in, garbage out) - final Document document = editor.getDocument(); - final int start = selectionModel.getSelectionStart(); - final int end = selectionModel.getSelectionEnd(); - final String text = document.getText(new TextRange(start, end)); - final int textLength = end - start; + final Document document = element.getContainingFile().getViewProvider().getDocument(); + final String text = document.getText(selection); + final int textLength = selection.getLength(); final StringBuilder replacement = new StringBuilder(textLength); int anchor = 0; while (true) { @@ -56,12 +49,13 @@ public class ReplaceOctalEscapeWithUnicodeEscapeIntention extends Intention { anchor = appendUnicodeEscape(text, index, replacement); } replacement.append(text, anchor, textLength); + final int start = selection.getStartOffset(); + final int end = selection.getEndOffset(); document.replaceString(start, end, replacement); } else if (element instanceof PsiLiteralExpression literalExpression) { final String text = literalExpression.getText(); - final CaretModel model = editor.getCaretModel(); - final int offset = model.getOffset() - literalExpression.getTextOffset(); + final int offset = context.offset() - literalExpression.getTextOffset(); final StringBuilder newLiteralText = new StringBuilder(); final int index1 = indexOfOctalEscape(text, offset); final int index2 = indexOfOctalEscape(text, offset + 1); @@ -139,27 +133,20 @@ public class ReplaceOctalEscapeWithUnicodeEscapeIntention extends Intention { return new OctalEscapePredicate(); } - private static class OctalEscapePredicate extends PsiElementEditorPredicate { + private static class OctalEscapePredicate extends PsiElementContextPredicate { @Override - public boolean satisfiedBy(PsiElement element, @Nullable Editor editor) { - if (editor == null) { - return false; - } - final SelectionModel selectionModel = editor.getSelectionModel(); - if (selectionModel.hasSelection()) { - final int start = selectionModel.getSelectionStart(); - final int end = selectionModel.getSelectionEnd(); - if (start < 0 || end < 0 || start > end) { - // shouldn't happen but http://ea.jetbrains.com/browser/ea_problems/51155 - return false; - } - final String text = editor.getDocument().getCharsSequence().subSequence(start, end).toString(); + public boolean satisfiedBy(PsiElement element, @NotNull ActionContext context) { + TextRange selection = context.selection(); + if (!selection.isEmpty()) { + final int start = selection.getStartOffset(); + final int end = selection.getEndOffset(); + final String text = element.getContainingFile().getViewProvider().getDocument() + .getCharsSequence().subSequence(start, end).toString(); return indexOfOctalEscape(text, 1) >= 0; } else if (element instanceof PsiLiteralExpression literalExpression) { final String text = literalExpression.getText(); - final CaretModel model = editor.getCaretModel(); - final int offset = model.getOffset() - literalExpression.getTextOffset(); + final int offset = context.offset() - literalExpression.getTextOffset(); final int index = indexOfOctalEscape(text, offset); return index >= 0 && offset >= index; } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/UnicodeUnescapeIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/UnicodeUnescapeIntention.java index 5eef781a254e..9151f21954f8 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/UnicodeUnescapeIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/UnicodeUnescapeIntention.java @@ -1,16 +1,15 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ipp.unicode; -import com.intellij.openapi.editor.CaretModel; +import com.intellij.modcommand.ModCommandAction; +import com.intellij.modcommand.ModPsiUpdater; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.siyeh.IntentionPowerPackBundle; -import com.siyeh.ipp.base.Intention; -import com.siyeh.ipp.base.PsiElementEditorPredicate; +import com.siyeh.ipp.base.MCIntention; +import com.siyeh.ipp.base.PsiElementContextPredicate; import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,7 +17,7 @@ import org.jetbrains.annotations.Nullable; /** * @author Bas Leijdekkers */ -public class UnicodeUnescapeIntention extends Intention { +public class UnicodeUnescapeIntention extends MCIntention { @Override public @NotNull String getFamilyName() { @@ -26,23 +25,18 @@ public class UnicodeUnescapeIntention extends Intention { } @Override - public @NotNull String getText() { + protected @Nullable String getTextForElement(@NotNull PsiElement element) { return IntentionPowerPackBundle.message("unicode.unescape.intention.name"); } @Override - protected void processIntention(@NotNull PsiElement element) {} - - @Override - protected void processIntention(Editor editor, @NotNull PsiElement element) { - final SelectionModel selectionModel = editor.getSelectionModel(); - if (selectionModel.hasSelection()) { + protected void processIntention(@NotNull ActionContext context, @NotNull ModPsiUpdater updater, @NotNull PsiElement element) { + TextRange selection = context.selection(); + final Document document = element.getContainingFile().getViewProvider().getDocument(); + if (!selection.isEmpty()) { // does not check if Unicode escape is inside char or string literal (garbage in, garbage out) - final Document document = editor.getDocument(); - final int start = selectionModel.getSelectionStart(); - final int end = selectionModel.getSelectionEnd(); - final String text = document.getText(new TextRange(start, end)); - final int textLength = end - start; + final String text = document.getText(selection); + final int textLength = selection.getLength(); final StringBuilder replacement = new StringBuilder(textLength); int anchor = 0; while (true) { @@ -60,15 +54,15 @@ public class UnicodeUnescapeIntention extends Intention { replacement.appendCodePoint(c); } replacement.append(text, anchor, textLength); + final int start = selection.getStartOffset(); + final int end = selection.getEndOffset(); document.replaceString(start, end, replacement); } else { - final CaretModel caretModel = editor.getCaretModel(); - final Document document = editor.getDocument(); - final int lineNumber = document.getLineNumber(caretModel.getOffset()); + final int lineNumber = document.getLineNumber(context.offset()); final int lineStartOffset = document.getLineStartOffset(lineNumber); final String line = document.getText(new TextRange(lineStartOffset, document.getLineEndOffset(lineNumber))); - final int column = caretModel.getLogicalPosition().column; + final int column = context.offset() - lineStartOffset; final int index1 = indexOfUnicodeEscape(line, column); final int index2 = indexOfUnicodeEscape(line, column + 1); // if the caret is between two unicode escapes, replace the one to the right @@ -155,17 +149,14 @@ public class UnicodeUnescapeIntention extends Intention { return new UnicodeEscapePredicate(); } - private static class UnicodeEscapePredicate extends PsiElementEditorPredicate { + private static class UnicodeEscapePredicate extends PsiElementContextPredicate { @Override - public boolean satisfiedBy(PsiElement element, @Nullable Editor editor) { - if (editor == null) { - return false; - } - final SelectionModel selectionModel = editor.getSelectionModel(); - final Document document = editor.getDocument(); - if (selectionModel.hasSelection()) { - final int start = selectionModel.getSelectionStart(); - final int end = selectionModel.getSelectionEnd(); + public boolean satisfiedBy(PsiElement element, @NotNull ModCommandAction.ActionContext context) { + TextRange selection = context.selection(); + Document document = element.getContainingFile().getViewProvider().getDocument(); + if (!selection.isEmpty()) { + final int start = selection.getStartOffset(); + final int end = selection.getEndOffset(); if (start < 0 || end < 0 || start > end) { // shouldn't happen but http://ea.jetbrains.com/browser/ea_problems/50192 return false; @@ -174,10 +165,10 @@ public class UnicodeUnescapeIntention extends Intention { return indexOfUnicodeEscape(text, 1) >= 0; } else { - final CaretModel caretModel = editor.getCaretModel(); - final int lineNumber = document.getLineNumber(caretModel.getOffset()); - final String line = document.getText(new TextRange(document.getLineStartOffset(lineNumber), document.getLineEndOffset(lineNumber))); - final int column = caretModel.getLogicalPosition().column; + final int lineNumber = document.getLineNumber(context.offset()); + int lineStart = document.getLineStartOffset(lineNumber); + final String line = document.getText(new TextRange(lineStart, document.getLineEndOffset(lineNumber))); + final int column = context.offset() - lineStart; final int index = indexOfUnicodeEscape(line, column); return index >= 0 && column >= index; } diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_setter_call/Parentheses_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_setter_call/Parentheses_after.java index be17232a18f8..84e4fe8c2d5f 100644 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_setter_call/Parentheses_after.java +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_setter_call/Parentheses_after.java @@ -11,6 +11,6 @@ class X { void test(X a, X b) { /*comment*/ - b.setName(a.getName()); + b.setName(a.getName()); } } \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_setter_call/Selection.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_setter_call/Selection.java new file mode 100644 index 000000000000..e1c21fa0853d --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_setter_call/Selection.java @@ -0,0 +1,35 @@ +public class MyClass { + String firstName; + String lastName; + int age; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + void copy(MyClass c) { + setFirstName(c.getFirstName()); + setLastName(c.getLastName()); + setAge(c.getAge()); + } +} diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_setter_call/Selection_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_setter_call/Selection_after.java new file mode 100644 index 000000000000..c56e486ee6f1 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_setter_call/Selection_after.java @@ -0,0 +1,35 @@ +public class MyClass { + String firstName; + String lastName; + int age; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + void copy(MyClass c) { + c.setFirstName(this.getFirstName()); + c.setLastName(this.getLastName()); + c.setAge(this.getAge()); + } +} diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/EliminateParenthesesIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/EliminateParenthesesIntentionTest.java index 7ede7d974022..d542681b7875 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/EliminateParenthesesIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/EliminateParenthesesIntentionTest.java @@ -1,9 +1,15 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ipp.expression; +import com.intellij.modcommand.ModCommand; +import com.intellij.modcommand.ModCommandAction; +import com.intellij.modcommand.ModCommandService; +import com.intellij.openapi.application.impl.NonBlockingReadActionImpl; +import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.CaretModel; import com.siyeh.IntentionPowerPackBundle; import com.siyeh.ipp.IPPTestCase; +import com.siyeh.ipp.expression.eliminate.EliminateParenthesesIntention; import org.jetbrains.annotations.NotNull; public class EliminateParenthesesIntentionTest extends IPPTestCase { @@ -25,9 +31,16 @@ public class EliminateParenthesesIntentionTest extends IPPTestCase { String testName = getTestName(false); myFixture.configureByFile(testName + ".java"); CaretModel model = myFixture.getEditor().getCaretModel(); + EliminateParenthesesIntention intention = new EliminateParenthesesIntention(); model.runForEachCaret(caret -> { - model.moveToOffset(caret.getOffset()); - myFixture.launchAction(myFixture.findSingleIntention(intentionName)); + ModCommandAction.ActionContext context = ModCommandAction.ActionContext.from(getEditor(), getFile()); + assertNotNull(intention.getPresentation(context)); + ModCommand command = intention.perform(context); + CommandProcessor.getInstance().executeCommand( + getProject(), + () -> ModCommandService.getInstance().executeInBatch(context, command), + "", null); + NonBlockingReadActionImpl.waitForAsyncTaskCompletion(); }); myFixture.checkResultByFile(testName + "_after.java", false); } diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/FlipSetterCallIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/FlipSetterCallIntentionTest.java index 76265ad1a2e7..a6636554e36e 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/FlipSetterCallIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/FlipSetterCallIntentionTest.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ipp.expression; import com.siyeh.IntentionPowerPackBundle; @@ -11,10 +11,11 @@ public class FlipSetterCallIntentionTest extends IPPTestCase { public void testSimple() { doTest(); } public void testUnqualified() { doTest(); } public void testParentheses() { doTest(); } + public void testSelection() { doTest(); } @Override protected String getIntentionName() { - return IntentionPowerPackBundle.message("flip.setter.call.intention.name"); + return IntentionPowerPackBundle.message("flip.setter.call.intention.family.name"); } @Override diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntShortcutStartupActivity.kt b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntShortcutStartupActivity.kt index 22fe00933b24..c49caa3e3ed4 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntShortcutStartupActivity.kt +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntShortcutStartupActivity.kt @@ -10,6 +10,8 @@ import com.intellij.openapi.actionSystem.ex.ActionManagerEx import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.serviceAsync import com.intellij.openapi.extensions.ExtensionNotApplicableException +import com.intellij.openapi.keymap.Keymap +import com.intellij.openapi.keymap.KeymapManagerListener import com.intellij.openapi.keymap.ex.KeymapManagerEx import com.intellij.openapi.project.Project import com.intellij.openapi.startup.ProjectActivity @@ -23,15 +25,19 @@ private class AntShortcutStartupActivity : ProjectActivity { } override suspend fun execute(project: Project) { - val prefix = AntConfiguration.getActionIdPrefix(project) - val actionManager = ApplicationManager.getApplication().serviceAsync() - for (keymap in KeymapManagerEx.getInstanceEx().allKeymaps) { - for (id in keymap.actionIdList) { - if (id.startsWith(prefix) && actionManager.getAction(id) == null) { - actionManager.registerAction(id, TargetActionStub(id, project)) - } - } - } + val listenerDisposable = Disposer.newDisposable() + Disposer.register(AntDisposable.getInstance(project), listenerDisposable) + val actionManager: ActionManager = ApplicationManager.getApplication().serviceAsync() + registerActionForKeymap(project, actionManager, KeymapManagerEx.getInstanceEx().activeKeymap) + ApplicationManager.getApplication().getMessageBus().connect(listenerDisposable) + .subscribe(KeymapManagerListener.TOPIC, + object : KeymapManagerListener { + override fun activeKeymapChanged(keymap: Keymap?) { + if (keymap == null) + return + registerActionForKeymap(project, actionManager, keymap) + } + }) Disposer.register(AntDisposable.getInstance(project), Disposable { unregisterAction(project) @@ -39,6 +45,15 @@ private class AntShortcutStartupActivity : ProjectActivity { } } +private fun registerActionForKeymap(project: Project, actionManager: ActionManager, keymap: Keymap) { + val prefix: String = AntConfiguration.getActionIdPrefix(project) + for (id in keymap.actionIdList) { + if (id.startsWith(prefix) && actionManager.getAction(id) == null) { + actionManager.registerAction(id, TargetActionStub(id, project)) + } + } +} + private fun unregisterAction(project: Project) { val actionManager = ActionManagerEx.getInstanceEx() for (oldId in actionManager.getActionIdList(AntConfiguration.getActionIdPrefix(project))) { diff --git a/plugins/changeReminder/intellij.vcs.changeReminder.iml b/plugins/changeReminder/intellij.vcs.changeReminder.iml index 445eb09209ea..a6fda7c59e04 100644 --- a/plugins/changeReminder/intellij.vcs.changeReminder.iml +++ b/plugins/changeReminder/intellij.vcs.changeReminder.iml @@ -17,7 +17,13 @@ - + + + + a6908f14a17757a20a0d629c5d2f0986826021c679bfb224963ef6a06097aa21 + + + diff --git a/plugins/completion-ml-ranking-models/intellij.completionMlRankingModels.iml b/plugins/completion-ml-ranking-models/intellij.completionMlRankingModels.iml index bfec9e3bf43d..387cd8776255 100644 --- a/plugins/completion-ml-ranking-models/intellij.completionMlRankingModels.iml +++ b/plugins/completion-ml-ranking-models/intellij.completionMlRankingModels.iml @@ -12,7 +12,13 @@ - + + + + c1686a3bfa4f29059b39ec51c6d6774fe11933d11aebd95bdb0d94e3ad9d3905 + + + @@ -24,7 +30,13 @@ - + + + + 2492dead3c2800e114634681b25b6e718df17005107ed4f1d30403e3aedffeb9 + + + @@ -36,7 +48,13 @@ - + + + + c4aed95367eeff94afb97ccf969bc65adee1292e24b61170838cfd0b732384c9 + + + @@ -48,7 +66,13 @@ - + + + + 2bbdd2aeaa31dc35180490ba20ee3096097e8ca4bcecdd1b80a1c162487d3c15 + + + @@ -60,7 +84,13 @@ - + + + + 1a220f42926fc3ac2bfce50c521aced95821ef8e8e7478a00e884acbbdc98248 + + + @@ -73,7 +103,13 @@ - + + + + f8f253b40454960df2f9b744b98ba5a08b490db4227fb2e97cfa1d18d103321a + + + @@ -85,7 +121,13 @@ - + + + + b73ea2290e95b8f8350a3bcf1c1ab260aed8a249049501f4b175c8dda0f04a78 + + + @@ -97,7 +139,13 @@ - + + + + 10392061789cf7c0101931dbfe851355b3fd33c9249947586d855a9180c439a7 + + + @@ -109,7 +157,13 @@ - + + + + a5b09d91c7633fa4dede7c640f189dce258c69aa65874f4eaca0a799a5fc35f9 + + + @@ -121,7 +175,13 @@ - + + + + e73816d0b63fa701e916b89f44559f6b8f104501f8b4f2feb300ac513e7a3850 + + + @@ -133,7 +193,13 @@ - + + + + 1ad40bce28263d3e4ff3e140949211d8812b05a6a0f121e92cb23980832838fc + + + @@ -145,7 +211,13 @@ - + + + + 024322c6d09f72f9bddeb94d52e803d235a9afc284bc3efe7dfbc9de58d4fa6f + + + @@ -157,7 +229,13 @@ - + + + + c1d511070b2900ced87e03443091640ff7758f5064ff14d3503d6c8f50d28c1b + + + @@ -169,7 +247,13 @@ - + + + + 2c09237e1e0e76d571b77c4f43371d8cd828903ffa442f0e3593894bce3021c3 + + + diff --git a/plugins/coverage/intellij.java.coverage.iml b/plugins/coverage/intellij.java.coverage.iml index f165dbc26121..d7e3e632069b 100644 --- a/plugins/coverage/intellij.java.coverage.iml +++ b/plugins/coverage/intellij.java.coverage.iml @@ -11,7 +11,34 @@ - + + + + 02e33bd2c48dc0be67c2fea84d43beececfd400da6797c58153253d4c30aca15 + + + 474c782f809d88924713dfdbf0acb79d330f904be576484803463d0465611643 + + + b9d4fe4d71938df38839f0eca42aaaa64cf8b313d678da036f0cb3ca199b47f5 + + + be4ce53138a238bb522cd781cf91f3ba5ce2f6ca93ec62d46a162a127225e0a6 + + + 878fbe521731c072d14d2d65b983b1beae6ad06fda0007b6a8bae81f73f433c4 + + + aabf9bd23091a4ebfc109c1f3ee7cf3e4b89f6ba2d3f51c5243f16b3cffae011 + + + 2c129110f3e3fcaa1f8179578ea3894586199cb0826be5c7790278084c9622a9 + + + 072ecbd496896623899a696fff12c01c1615f737616d2792e6d0e10cdf8a610d + + + @@ -57,6 +84,14 @@ + + + 5959f0aa7f33c74c8cde6babb2d9b92638f0e143461d2c37f6859f731c275c59 + + + 04d65ec1bde6cea20e3495d5e78ef96ab774d9936434861d3254bd88e7e94f92 + + diff --git a/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java b/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java index 19463b46ed47..2db04ade1582 100644 --- a/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java +++ b/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.coverage; import com.intellij.CommonBundle; @@ -58,6 +58,7 @@ import com.intellij.rt.coverage.data.JumpData; import com.intellij.rt.coverage.data.LineData; import com.intellij.rt.coverage.data.SwitchData; import com.intellij.task.ProjectTaskManager; +import com.intellij.task.impl.ProjectTaskManagerImpl; import com.intellij.testIntegration.TestFramework; import com.intellij.util.containers.ContainerUtil; import jetbrains.coverage.report.ReportGenerationFailedException; @@ -359,6 +360,7 @@ public class JavaCoverageEngine extends CoverageEngine { JavaCoverageBundle.message("project.class.files.are.out.of.date"), NotificationType.INFORMATION); notification.addAction(NotificationAction.createSimpleExpiring(JavaCoverageBundle.message("coverage.recompile"), () -> { + ProjectTaskManagerImpl.putBuildOriginator(project, this.getClass()); ProjectTaskManager taskManager = ProjectTaskManager.getInstance(project); Promise promise = taskManager.buildAllModules(); promise.onSuccess(result -> ApplicationManager.getApplication().invokeLater(() -> { diff --git a/plugins/cucumber-jvm-formatter3/intellij.cucumber.jvmFormatter3.iml b/plugins/cucumber-jvm-formatter3/intellij.cucumber.jvmFormatter3.iml index ebdcea7a60df..53d4900d5eaf 100644 --- a/plugins/cucumber-jvm-formatter3/intellij.cucumber.jvmFormatter3.iml +++ b/plugins/cucumber-jvm-formatter3/intellij.cucumber.jvmFormatter3.iml @@ -9,7 +9,31 @@ - + + + + d3fc5dce5cd26a8a71a94b932395b9588c1c6abbd40c49c2281da74e5e48f6a4 + + + c2413a16c107a137f7a9d73f24af17211ef9580eef5fc2fab589610166781099 + + + e35cfa4a16204bf59fa167bb6d45be0717d6b7cfba1c30f156d8f21cde2f4065 + + + e5a0a71fb846752900c0e5a99aa13e5a1bbc3ec97e7faf26803648fa45215584 + + + e7e296e57f911d4f3827df55753611446c427fc46f41ecb94d5e9f9dacda872a + + + 0d7fa64225d159ee9d29554ea6fa2bd0891319e5c06a3b0b58db2decf72fd6f2 + + + ec82d25da10509aab64430406fbcdc9a376f1c55a0081cf1326429ff691fc99d + + + diff --git a/plugins/cucumber-jvm-formatter4/intellij.cucumber.jvmFormatter4.iml b/plugins/cucumber-jvm-formatter4/intellij.cucumber.jvmFormatter4.iml index 30c8cb375428..fede64b31186 100644 --- a/plugins/cucumber-jvm-formatter4/intellij.cucumber.jvmFormatter4.iml +++ b/plugins/cucumber-jvm-formatter4/intellij.cucumber.jvmFormatter4.iml @@ -9,7 +9,31 @@ - + + + + 25c52c0401f0786f66be90e384e765dbe0358b73fddd8874f7029da5f1b3c259 + + + c2413a16c107a137f7a9d73f24af17211ef9580eef5fc2fab589610166781099 + + + 67f1cedeb8e85e6af84f89a8fe70bafaf6216dfad7a46b76fe10c5ee814e51e3 + + + e5a0a71fb846752900c0e5a99aa13e5a1bbc3ec97e7faf26803648fa45215584 + + + 660ba952417b95cfb22dda2e8be6fba46f521188e4f8a47ae9614f675bdb9bb8 + + + 487db14bc5471639a5b05e66f3b5f60ca3f73f9d984088ba88c64078709f38aa + + + 33b9c48799b681328ec865756a0eb9c8ade946052ef1409a4d882e438956692c + + + diff --git a/plugins/cucumber-jvm-formatter5/intellij.cucumber.jvmFormatter5.iml b/plugins/cucumber-jvm-formatter5/intellij.cucumber.jvmFormatter5.iml index 6c19302c25b4..fd80ec426156 100644 --- a/plugins/cucumber-jvm-formatter5/intellij.cucumber.jvmFormatter5.iml +++ b/plugins/cucumber-jvm-formatter5/intellij.cucumber.jvmFormatter5.iml @@ -10,7 +10,52 @@ - + + + + 789e598804155bcca83a01071382af90d0e9e1f6c686c881800b07fc0c1ea3c4 + + + ada4315573c505d9dbb03cb0624f4a4e9fe9af92f4d278c4d7eb0422cdf299ff + + + ab8af6e8e1f5bea8cf04aeb6e87a96121d554132615c35d1d0d0bb8aac6ebe05 + + + 6ac4b12c6b694ac9ee4eecc8949cf7976d1bd892871cf816298de404bde44bb2 + + + 2c0fd9f293b2ca0ce22531b8769dc2aef37eb704f1212030513a90f6eb975476 + + + 81ad14ebf1a885ab4a201f0e48695eb60d8c55265c8323d49b98a0e34093e30b + + + e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9 + + + ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050 + + + b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21 + + + c021f59d4d914edc42cb4c40dc440dca05f36902e0eb36c0307ed2d192ae0860 + + + 0348ab1b354dbaa327ee3bead884cf6d7b4cb23c086d803012dbb7cc319277b0 + + + 4d4cc28f9c73f5137db7b0ecd371d33696f5eac18db6c1ef65b65dd16275b3f3 + + + 90049802a975fde907069eea511687871b53824027ba54d2b7d7f447502e5d59 + + + a9aae9ff8ae3e17a2a18f79175e82b16267c246fbbd3ca9dfbbb290b08dcfdd4 + + + diff --git a/plugins/devkit/devkit-core/src/run/PluginRunConfiguration.java b/plugins/devkit/devkit-core/src/run/PluginRunConfiguration.java index a26e024135aa..7bae670b784c 100644 --- a/plugins/devkit/devkit-core/src/run/PluginRunConfiguration.java +++ b/plugins/devkit/devkit-core/src/run/PluginRunConfiguration.java @@ -223,7 +223,6 @@ public class PluginRunConfiguration extends RunConfigurationBase implem } if (SystemInfo.isMac) { - vm.defineProperty("apple.laf.useScreenMenuBar", "true"); vm.defineProperty("apple.awt.fileDialogForDirectories", "true"); } diff --git a/plugins/evaluation-plugin/intellij.evaluationPlugin.iml b/plugins/evaluation-plugin/intellij.evaluationPlugin.iml index 2abd92ea8e5a..8bab12d9409e 100644 --- a/plugins/evaluation-plugin/intellij.evaluationPlugin.iml +++ b/plugins/evaluation-plugin/intellij.evaluationPlugin.iml @@ -11,7 +11,13 @@ - + + + + beb3136d06764ec8ce0810a8fd6c8b7b49d04287d1deef3a07c016e43a458d33 + + + diff --git a/plugins/filePrediction/intellij.filePrediction.iml b/plugins/filePrediction/intellij.filePrediction.iml index 6ed32934f820..51675bd5adc7 100644 --- a/plugins/filePrediction/intellij.filePrediction.iml +++ b/plugins/filePrediction/intellij.filePrediction.iml @@ -24,7 +24,13 @@ - + + + + e506fd77462afcdb16f0ccfe7c96c1549443580a3be240c5dcff1ae2bfac0555 + + + diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRStatisticsCollector.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRStatisticsCollector.kt index 2510f45f8394..68ea0ec41707 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRStatisticsCollector.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRStatisticsCollector.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.plugins.github.pullrequest -import com.intellij.collaboration.async.disposingScope import com.intellij.internal.statistic.eventLog.EventLogGroup import com.intellij.internal.statistic.eventLog.FeatureUsageData import com.intellij.internal.statistic.eventLog.events.EventFields import com.intellij.internal.statistic.eventLog.events.EventPair import com.intellij.internal.statistic.eventLog.events.PrimitiveEventField import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector -import com.intellij.openapi.Disposable import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.project.Project import com.intellij.openapi.startup.ProjectActivity +import com.intellij.util.childScope +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.future.await import kotlinx.coroutines.launch import org.jetbrains.plugins.github.api.GithubServerPath @@ -25,7 +25,7 @@ import org.jetbrains.plugins.github.util.GHEnterpriseServerMetadataLoader import java.util.* internal object GHPRStatisticsCollector { - private val COUNTERS_GROUP = EventLogGroup("vcs.github.pullrequest.counters", 4) + private val COUNTERS_GROUP = EventLogGroup("vcs.github.pullrequest.counters", 5) class Counters : CounterUsagesCollector() { override fun getGroup() = COUNTERS_GROUP @@ -34,12 +34,12 @@ internal object GHPRStatisticsCollector { private val SELECTORS_OPENED_EVENT = COUNTERS_GROUP.registerEvent("selectors.opened") private val LIST_OPENED_EVENT = COUNTERS_GROUP.registerEvent("list.opened") - private val FILTER_SEARCH_PRESENT = EventFields.Boolean("hasSearch") - private val FILTER_STATE_PRESENT = EventFields.Boolean("hasState") - private val FILTER_AUTHOR_PRESENT = EventFields.Boolean("hasAuthor") - private val FILTER_ASSIGNEE_PRESENT = EventFields.Boolean("hasAssignee") - private val FILTER_REVIEW_PRESENT = EventFields.Boolean("hasReviewState") - private val FILTER_LABEL_PRESENT = EventFields.Boolean("hasLabel") + private val FILTER_SEARCH_PRESENT = EventFields.Boolean("has_search") + private val FILTER_STATE_PRESENT = EventFields.Boolean("has_state") + private val FILTER_AUTHOR_PRESENT = EventFields.Boolean("has_author") + private val FILTER_ASSIGNEE_PRESENT = EventFields.Boolean("has_assignee") + private val FILTER_REVIEW_PRESENT = EventFields.Boolean("has_review_state") + private val FILTER_LABEL_PRESENT = EventFields.Boolean("has_label") private val FILTERS_APPLIED_EVENT = COUNTERS_GROUP.registerVarargEvent("list.filters.applied", FILTER_SEARCH_PRESENT, @@ -80,19 +80,20 @@ internal object GHPRStatisticsCollector { private val DETAILS_ACTION_EVENT = COUNTERS_GROUP.registerEvent("details.additional.actions.invoked", - EventFields.Enum("action", GHPRAction::class.java), - EventFields.Boolean("isDefault")) + EventFields.Enum("action"), + EventFields.Boolean("is_default")) - fun logSelectorsOpened() { - SELECTORS_OPENED_EVENT.log() + fun logSelectorsOpened(project: Project) { + SELECTORS_OPENED_EVENT.log(project) } - fun logListOpened() { - LIST_OPENED_EVENT.log() + fun logListOpened(project: Project) { + LIST_OPENED_EVENT.log(project) } - fun logListFiltersApplied(filters: GHPRListSearchValue): Unit = + fun logListFiltersApplied(project: Project, filters: GHPRListSearchValue): Unit = FILTERS_APPLIED_EVENT.log( + project, EventPair(FILTER_SEARCH_PRESENT, filters.searchQuery != null), EventPair(FILTER_STATE_PRESENT, filters.state != null), EventPair(FILTER_AUTHOR_PRESENT, filters.author != null), @@ -101,12 +102,12 @@ internal object GHPRStatisticsCollector { EventPair(FILTER_LABEL_PRESENT, filters.label != null) ) - fun logDetailsOpened() { - DETAILS_OPENED_EVENT.log() + fun logDetailsOpened(project: Project) { + DETAILS_OPENED_EVENT.log(project) } - fun logNewPRViewOpened() { - NEW_OPENED_EVENT.log() + fun logNewPRViewOpened(project: Project) { + NEW_OPENED_EVENT.log(project) } fun logTimelineOpened(project: Project) { @@ -122,40 +123,40 @@ internal object GHPRStatisticsCollector { DIFF_OPENED_EVENT.log(project, count) } - fun logDetailsBranchesOpened() { - DETAILS_BRANCHES_EVENT.log() + fun logDetailsBranchesOpened(project: Project) { + DETAILS_BRANCHES_EVENT.log(project) } - fun logDetailsBranchCheckedOut() { - DETAILS_BRANCH_CHECKED_OUT_EVENT.log() + fun logDetailsBranchCheckedOut(project: Project) { + DETAILS_BRANCH_CHECKED_OUT_EVENT.log(project) } - fun logDetailsCommitChosen() { - DETAILS_COMMIT_CHOSEN_EVENT.log() + fun logDetailsCommitChosen(project: Project) { + DETAILS_COMMIT_CHOSEN_EVENT.log(project) } - fun logDetailsNextCommitChosen() { - DETAILS_NEXT_COMMIT_EVENT.log() + fun logDetailsNextCommitChosen(project: Project) { + DETAILS_NEXT_COMMIT_EVENT.log(project) } - fun logDetailsPrevCommitChosen() { - DETAILS_PREV_COMMIT_EVENT.log() + fun logDetailsPrevCommitChosen(project: Project) { + DETAILS_PREV_COMMIT_EVENT.log(project) } - fun logDetailsChecksOpened() { - DETAILS_CHECKS_EVENT.log() + fun logDetailsChecksOpened(project: Project) { + DETAILS_CHECKS_EVENT.log(project) } - fun logDetailsActionInvoked(action: GHPRAction, isDefault: Boolean) { - DETAILS_ACTION_EVENT.log(action, isDefault) + fun logDetailsActionInvoked(project: Project, action: GHPRAction, isDefault: Boolean) { + DETAILS_ACTION_EVENT.log(project, action, isDefault) } - fun logChangeSelected() { - DETAILS_CHANGE_EVENT.log() + fun logChangeSelected(project: Project) { + DETAILS_CHANGE_EVENT.log(project) } - fun logMergedEvent(method: GithubPullRequestMergeMethod) { - MERGED_EVENT.log(method) + fun logMergedEvent(project: Project, method: GithubPullRequestMergeMethod) { + MERGED_EVENT.log(project, method) } fun logEnterpriseServerMeta(project: Project, server: GithubServerPath, meta: GHEnterpriseServerMeta) { @@ -175,10 +176,13 @@ enum class GHPRAction { REBASE_MERGE } -@Service -private class GHServerVersionsCollector(private val project: Project) : Disposable { +@Service(Service.Level.PROJECT) +private class GHServerVersionsCollector( + private val project: Project, + parentCs: CoroutineScope +) { - private val scope = disposingScope() + private val scope = parentCs.childScope() init { val accountsFlow = project.service().accountsState @@ -206,6 +210,4 @@ private class GHServerVersionsCollector(private val project: Project) : Disposab project.service() } } - - override fun dispose() = Unit } diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/data/GHPRDataContextRepository.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/data/GHPRDataContextRepository.kt index 54fe3e7cc746..5c77def0a52e 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/data/GHPRDataContextRepository.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/data/GHPRDataContextRepository.kt @@ -126,7 +126,7 @@ internal class GHPRDataContextRepository(private val project: Project) : Disposa account, currentUser, currentUserTeams, repositoryInfo) val detailsService = GHPRDetailsServiceImpl(ProgressManager.getInstance(), requestExecutor, apiRepositoryCoordinates) - val stateService = GHPRStateServiceImpl(ProgressManager.getInstance(), securityService, + val stateService = GHPRStateServiceImpl(ProgressManager.getInstance(), project, securityService, requestExecutor, account.server, apiRepositoryPath) val commentService = GHPRCommentServiceImpl(ProgressManager.getInstance(), requestExecutor, apiRepositoryCoordinates) val changesService = GHPRChangesServiceImpl(ProgressManager.getInstance(), project, requestExecutor, diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/data/service/GHPRStateServiceImpl.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/data/service/GHPRStateServiceImpl.kt index 27586940e825..e7d2a0627880 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/data/service/GHPRStateServiceImpl.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/data/service/GHPRStateServiceImpl.kt @@ -6,6 +6,7 @@ import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.project.Project import org.jetbrains.plugins.github.api.* import org.jetbrains.plugins.github.api.data.GHBranchProtectionRules import org.jetbrains.plugins.github.api.data.GHRepositoryPermissionLevel @@ -18,6 +19,7 @@ import org.jetbrains.plugins.github.pullrequest.data.service.GHServiceUtil.logEr import java.util.concurrent.CompletableFuture class GHPRStateServiceImpl internal constructor(private val progressManager: ProgressManager, + private val project: Project, private val securityService: GHPRSecurityService, private val requestExecutor: GithubApiRequestExecutor, private val serverPath: GithubServerPath, @@ -91,7 +93,7 @@ class GHPRStateServiceImpl internal constructor(private val progressManager: Pro requestExecutor.execute(it, GithubApiRequests.Repos.PullRequests.merge(serverPath, repoPath, pullRequestId.number, commitMessage.first, commitMessage.second, currentHeadRef)) - GHPRStatisticsCollector.logMergedEvent(GithubPullRequestMergeMethod.merge) + GHPRStatisticsCollector.logMergedEvent(project, GithubPullRequestMergeMethod.merge) return@submitIOTask }.logError(LOG, "Error occurred while merging PR ${pullRequestId.number}") @@ -102,7 +104,7 @@ class GHPRStateServiceImpl internal constructor(private val progressManager: Pro requestExecutor.execute(it, GithubApiRequests.Repos.PullRequests.rebaseMerge(serverPath, repoPath, pullRequestId.number, currentHeadRef)) - GHPRStatisticsCollector.logMergedEvent(GithubPullRequestMergeMethod.rebase) + GHPRStatisticsCollector.logMergedEvent(project, GithubPullRequestMergeMethod.rebase) return@submitIOTask }.logError(LOG, "Error occurred while rebasing PR ${pullRequestId.number}") @@ -113,7 +115,7 @@ class GHPRStateServiceImpl internal constructor(private val progressManager: Pro GithubApiRequests.Repos.PullRequests.squashMerge(serverPath, repoPath, pullRequestId.number, commitMessage.first, commitMessage.second, currentHeadRef)) - GHPRStatisticsCollector.logMergedEvent(GithubPullRequestMergeMethod.squash) + GHPRStatisticsCollector.logMergedEvent(project, GithubPullRequestMergeMethod.squash) return@submitIOTask }.logError(LOG, "Error occurred while squash-merging PR ${pullRequestId.number}") diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRDetailsActionsComponentFactory.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRDetailsActionsComponentFactory.kt index de98193cd6bc..bbec0f05caac 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRDetailsActionsComponentFactory.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRDetailsActionsComponentFactory.kt @@ -18,6 +18,7 @@ import com.intellij.openapi.actionSystem.DefaultActionGroup import com.intellij.openapi.actionSystem.Presentation import com.intellij.openapi.actionSystem.ex.CustomComponentAction import com.intellij.openapi.actionSystem.impl.SimpleDataContext +import com.intellij.openapi.project.Project import com.intellij.ui.components.JBOptionButton import com.intellij.ui.components.panels.Wrapper import kotlinx.coroutines.CoroutineScope @@ -39,20 +40,21 @@ internal object GHPRDetailsActionsComponentFactory { fun create( scope: CoroutineScope, + project: Project, reviewRequestState: Flow, reviewFlowVm: GHPRReviewFlowViewModel, dataProvider: GHPRDataProvider ): JComponent { val reviewActions = CodeReviewActions( - requestReviewAction = GHPRRequestReviewAction(scope, reviewFlowVm), - reRequestReviewAction = GHPRReRequestReviewAction(scope, reviewFlowVm), - closeReviewAction = GHPRCloseAction(scope, reviewFlowVm), - reopenReviewAction = GHPRReopenAction(scope, reviewFlowVm), - setMyselfAsReviewerAction = GHPRSetMyselfAsReviewerAction(scope, reviewFlowVm), - postReviewAction = GHPRPostReviewAction(scope, reviewFlowVm), - mergeReviewAction = GHPRCommitMergeAction(scope, reviewFlowVm), - mergeSquashReviewAction = GHPRSquashMergeAction(scope, reviewFlowVm), - rebaseReviewAction = GHPRRebaseMergeAction(scope, reviewFlowVm) + requestReviewAction = GHPRRequestReviewAction(scope, project, reviewFlowVm), + reRequestReviewAction = GHPRReRequestReviewAction(scope, project, reviewFlowVm), + closeReviewAction = GHPRCloseAction(scope, project, reviewFlowVm), + reopenReviewAction = GHPRReopenAction(scope, project, reviewFlowVm), + setMyselfAsReviewerAction = GHPRSetMyselfAsReviewerAction(scope, project, reviewFlowVm), + postReviewAction = GHPRPostReviewAction(scope, project, reviewFlowVm), + mergeReviewAction = GHPRCommitMergeAction(scope, project, reviewFlowVm), + mergeSquashReviewAction = GHPRSquashMergeAction(scope, project, reviewFlowVm), + rebaseReviewAction = GHPRRebaseMergeAction(scope, project, reviewFlowVm) ) val moreActionsGroup = DefaultActionGroup(GithubBundle.message("pull.request.merge.commit.action"), true) diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRDetailsComponentFactory.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRDetailsComponentFactory.kt index c3afd38239e3..1224c30c0098 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRDetailsComponentFactory.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRDetailsComponentFactory.kt @@ -12,6 +12,7 @@ import com.intellij.openapi.actionSystem.ActionManager import com.intellij.openapi.actionSystem.ActionPlaces import com.intellij.openapi.actionSystem.ex.ActionUtil import com.intellij.openapi.actionSystem.impl.SimpleDataContext +import com.intellij.openapi.project.Project import com.intellij.ui.PopupHandler import kotlinx.coroutines.CoroutineScope import net.miginfocom.layout.AC @@ -35,6 +36,7 @@ internal object GHPRDetailsComponentFactory { fun create( scope: CoroutineScope, + project: Project, reviewDetailsVm: CodeReviewDetailsViewModel, branchesVm: CodeReviewBranchesViewModel, reviewStatusVm: GHPRStatusViewModel, @@ -57,8 +59,10 @@ internal object GHPRDetailsComponentFactory { .add(GHPRActionKeys.REVIEW_BRANCH_VM, branchesVm) .build())) } - val statusChecks = GHPRStatusChecksComponentFactory.create(scope, reviewStatusVm, reviewFlowVm, securityService, avatarIconsProvider) - val actionsComponent = GHPRDetailsActionsComponentFactory.create(scope, reviewDetailsVm.reviewRequestState, reviewFlowVm, dataProvider) + val statusChecks = GHPRStatusChecksComponentFactory.create(scope, project, reviewStatusVm, reviewFlowVm, securityService, + avatarIconsProvider) + val actionsComponent = GHPRDetailsActionsComponentFactory.create(scope, project, reviewDetailsVm.reviewRequestState, reviewFlowVm, + dataProvider) val actionGroup = ActionManager.getInstance().getAction("Github.PullRequest.Details.Popup") as ActionGroup return JPanel(MigLayout( diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRStatusChecksComponentFactory.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRStatusChecksComponentFactory.kt index 19739e20f8d3..134fd8bf87ad 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRStatusChecksComponentFactory.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/GHPRStatusChecksComponentFactory.kt @@ -8,6 +8,7 @@ import com.intellij.collaboration.ui.util.bindTextIn import com.intellij.collaboration.ui.util.toAnAction import com.intellij.icons.AllIcons import com.intellij.openapi.actionSystem.DefaultActionGroup +import com.intellij.openapi.project.Project import com.intellij.ui.ScrollPaneFactory import com.intellij.ui.components.panels.Wrapper import com.intellij.util.childScope @@ -28,6 +29,7 @@ import javax.swing.JScrollPane internal object GHPRStatusChecksComponentFactory { fun create( parentScope: CoroutineScope, + project: Project, reviewStatusVm: GHPRStatusViewModel, reviewFlowVm: GHPRReviewFlowViewModel, securityService: GHPRSecurityService, @@ -48,7 +50,9 @@ internal object GHPRStatusChecksComponentFactory { add(CodeReviewDetailsStatusComponentFactory.createNeedReviewerComponent(scope, reviewFlowVm.reviewerReviews)) add(CodeReviewDetailsStatusComponentFactory.createReviewersReviewStateComponent( scope, reviewFlowVm.reviewerReviews, - reviewerActionProvider = { reviewer -> DefaultActionGroup(GHPRRemoveReviewerAction(scope, reviewFlowVm, reviewer).toAnAction()) }, + reviewerActionProvider = { reviewer -> + DefaultActionGroup(GHPRRemoveReviewerAction(scope, project, reviewFlowVm, reviewer).toAnAction()) + }, reviewerNameProvider = { reviewer -> reviewer.getPresentableName() }, avatarKeyProvider = { reviewer -> reviewer.avatarUrl }, iconProvider = { iconKey, iconSize -> avatarIconsProvider.getIcon(iconKey, iconSize) } diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRCloseAction.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRCloseAction.kt index 57641b20dea2..d496d0edc601 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRCloseAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRCloseAction.kt @@ -1,6 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.github.pullrequest.ui.details.action +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.plugins.github.i18n.GithubBundle @@ -11,7 +12,7 @@ import java.awt.event.ActionEvent import javax.swing.AbstractAction import javax.swing.JButton -internal class GHPRCloseAction(scope: CoroutineScope, private val reviewFlowVm: GHPRReviewFlowViewModel) +internal class GHPRCloseAction(scope: CoroutineScope, private val project: Project, private val reviewFlowVm: GHPRReviewFlowViewModel) : AbstractAction(GithubBundle.message("pull.request.close.action")) { init { @@ -23,7 +24,7 @@ internal class GHPRCloseAction(scope: CoroutineScope, private val reviewFlowVm: } override fun actionPerformed(e: ActionEvent?) { - GHPRStatisticsCollector.logDetailsActionInvoked(GHPRAction.CLOSE, e?.source is JButton) + GHPRStatisticsCollector.logDetailsActionInvoked(project, GHPRAction.CLOSE, e?.source is JButton) reviewFlowVm.closeReview() } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRCommitMergeAction.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRCommitMergeAction.kt index 6b3cb7ffb672..c19ede7b9fc1 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRCommitMergeAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRCommitMergeAction.kt @@ -3,6 +3,7 @@ package org.jetbrains.plugins.github.pullrequest.ui.details.action import com.intellij.collaboration.async.combineAndCollect import com.intellij.collaboration.messages.CollaborationToolsBundle +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.plugins.github.pullrequest.GHPRAction @@ -12,7 +13,7 @@ import java.awt.event.ActionEvent import javax.swing.AbstractAction import javax.swing.JButton -internal class GHPRCommitMergeAction(scope: CoroutineScope, private val reviewFlowVm: GHPRReviewFlowViewModel) +internal class GHPRCommitMergeAction(scope: CoroutineScope, private val project: Project, private val reviewFlowVm: GHPRReviewFlowViewModel) : AbstractAction(CollaborationToolsBundle.message("review.details.action.merge")) { init { @@ -24,7 +25,7 @@ internal class GHPRCommitMergeAction(scope: CoroutineScope, private val reviewFl } override fun actionPerformed(e: ActionEvent?) { - GHPRStatisticsCollector.logDetailsActionInvoked(GHPRAction.MERGE, e?.source is JButton) + GHPRStatisticsCollector.logDetailsActionInvoked(project, GHPRAction.MERGE, e?.source is JButton) reviewFlowVm.mergeReview() } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRPostReviewAction.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRPostReviewAction.kt index 2d2a350dade1..8c0c578cf535 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRPostReviewAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRPostReviewAction.kt @@ -1,6 +1,7 @@ // 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.plugins.github.pullrequest.ui.details.action +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.plugins.github.i18n.GithubBundle @@ -11,7 +12,7 @@ import java.awt.event.ActionEvent import javax.swing.AbstractAction import javax.swing.JButton -internal class GHPRPostReviewAction(scope: CoroutineScope, private val reviewFlowVm: GHPRReviewFlowViewModel) +internal class GHPRPostReviewAction(scope: CoroutineScope, private val project: Project, private val reviewFlowVm: GHPRReviewFlowViewModel) : AbstractAction(GithubBundle.message("pull.request.post.action")) { init { @@ -23,7 +24,7 @@ internal class GHPRPostReviewAction(scope: CoroutineScope, private val reviewFlo } override fun actionPerformed(e: ActionEvent?) { - GHPRStatisticsCollector.logDetailsActionInvoked(GHPRAction.POST_REVIEW, e?.source is JButton) + GHPRStatisticsCollector.logDetailsActionInvoked(project, GHPRAction.POST_REVIEW, e?.source is JButton) reviewFlowVm.postDraftedReview() } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRReRequestReviewAction.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRReRequestReviewAction.kt index 5831bf9a2cfc..58963e6f922d 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRReRequestReviewAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRReRequestReviewAction.kt @@ -2,6 +2,7 @@ package org.jetbrains.plugins.github.pullrequest.ui.details.action import com.intellij.collaboration.messages.CollaborationToolsBundle +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.plugins.github.pullrequest.GHPRAction @@ -11,7 +12,9 @@ import java.awt.event.ActionEvent import javax.swing.AbstractAction import javax.swing.JButton -internal class GHPRReRequestReviewAction(scope: CoroutineScope, private val reviewFlowVm: GHPRReviewFlowViewModel) +internal class GHPRReRequestReviewAction(scope: CoroutineScope, + private val project: Project, + private val reviewFlowVm: GHPRReviewFlowViewModel) : AbstractAction(CollaborationToolsBundle.message("review.details.action.rerequest")) { init { @@ -23,7 +26,7 @@ internal class GHPRReRequestReviewAction(scope: CoroutineScope, private val revi } override fun actionPerformed(event: ActionEvent) { - GHPRStatisticsCollector.logDetailsActionInvoked(GHPRAction.RE_REQUEST_REVIEW, event.source is JButton) + GHPRStatisticsCollector.logDetailsActionInvoked(project, GHPRAction.RE_REQUEST_REVIEW, event.source is JButton) reviewFlowVm.reRequestReview() } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRebaseMergeAction.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRebaseMergeAction.kt index 9b208a9497b5..ad7474a3dd66 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRebaseMergeAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRebaseMergeAction.kt @@ -3,6 +3,7 @@ package org.jetbrains.plugins.github.pullrequest.ui.details.action import com.intellij.collaboration.async.combineAndCollect import com.intellij.collaboration.messages.CollaborationToolsBundle +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.plugins.github.pullrequest.GHPRAction @@ -12,7 +13,7 @@ import java.awt.event.ActionEvent import javax.swing.AbstractAction import javax.swing.JButton -internal class GHPRRebaseMergeAction(scope: CoroutineScope, private val reviewFlowVm: GHPRReviewFlowViewModel) +internal class GHPRRebaseMergeAction(scope: CoroutineScope, private val project: Project, private val reviewFlowVm: GHPRReviewFlowViewModel) : AbstractAction(CollaborationToolsBundle.message("review.details.action.rebase")) { init { @@ -24,7 +25,7 @@ internal class GHPRRebaseMergeAction(scope: CoroutineScope, private val reviewFl } override fun actionPerformed(e: ActionEvent?) { - GHPRStatisticsCollector.logDetailsActionInvoked(GHPRAction.REBASE_MERGE, e?.source is JButton) + GHPRStatisticsCollector.logDetailsActionInvoked(project, GHPRAction.REBASE_MERGE, e?.source is JButton) reviewFlowVm.rebaseReview() } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRemoveReviewerAction.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRemoveReviewerAction.kt index 9b546e891722..7ab34de6ceb1 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRemoveReviewerAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRemoveReviewerAction.kt @@ -2,6 +2,7 @@ package org.jetbrains.plugins.github.pullrequest.ui.details.action import com.intellij.collaboration.messages.CollaborationToolsBundle +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.plugins.github.api.data.pullrequest.GHPullRequestRequestedReviewer @@ -11,6 +12,7 @@ import javax.swing.AbstractAction internal class GHPRRemoveReviewerAction( scope: CoroutineScope, + private val project: Project, private val reviewFlowVm: GHPRReviewFlowViewModel, private val reviewer: GHPullRequestRequestedReviewer ) : AbstractAction(CollaborationToolsBundle.message("review.details.action.remove.reviewer", reviewer.name ?: reviewer.shortName)) { diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRReopenAction.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRReopenAction.kt index ad28482bc15b..ca54c4cb5745 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRReopenAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRReopenAction.kt @@ -1,6 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.github.pullrequest.ui.details.action +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.plugins.github.i18n.GithubBundle @@ -11,7 +12,7 @@ import java.awt.event.ActionEvent import javax.swing.AbstractAction import javax.swing.JButton -internal class GHPRReopenAction(scope: CoroutineScope, private val reviewFlowVm: GHPRReviewFlowViewModel) +internal class GHPRReopenAction(scope: CoroutineScope, private val project: Project, private val reviewFlowVm: GHPRReviewFlowViewModel) : AbstractAction(GithubBundle.message("pull.request.reopen.action")) { init { @@ -23,7 +24,7 @@ internal class GHPRReopenAction(scope: CoroutineScope, private val reviewFlowVm: } override fun actionPerformed(e: ActionEvent?) { - GHPRStatisticsCollector.logDetailsActionInvoked(GHPRAction.REOPEN, e?.source is JButton) + GHPRStatisticsCollector.logDetailsActionInvoked(project, GHPRAction.REOPEN, e?.source is JButton) reviewFlowVm.reopenReview() } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRequestReviewAction.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRequestReviewAction.kt index 080269242be2..67e7b4698272 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRequestReviewAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRRequestReviewAction.kt @@ -2,6 +2,7 @@ package org.jetbrains.plugins.github.pullrequest.ui.details.action import com.intellij.collaboration.messages.CollaborationToolsBundle +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.plugins.github.pullrequest.GHPRAction @@ -12,7 +13,7 @@ import javax.swing.AbstractAction import javax.swing.JButton import javax.swing.JComponent -internal class GHPRRequestReviewAction(scope: CoroutineScope, private val reviewFlowVm: GHPRReviewFlowViewModel) +internal class GHPRRequestReviewAction(scope: CoroutineScope, private val project: Project, private val reviewFlowVm: GHPRReviewFlowViewModel) : AbstractAction(CollaborationToolsBundle.message("review.details.action.request")) { init { @@ -25,7 +26,7 @@ internal class GHPRRequestReviewAction(scope: CoroutineScope, private val review override fun actionPerformed(event: ActionEvent) { val parentComponent = event.source as JComponent - GHPRStatisticsCollector.logDetailsActionInvoked(GHPRAction.REQUEST_REVIEW, parentComponent is JButton) + GHPRStatisticsCollector.logDetailsActionInvoked(project, GHPRAction.REQUEST_REVIEW, parentComponent is JButton) return reviewFlowVm.requestReview(parentComponent) } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRSetMyselfAsReviewerAction.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRSetMyselfAsReviewerAction.kt index 262d5f4ebe01..97528cc7e2af 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRSetMyselfAsReviewerAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRSetMyselfAsReviewerAction.kt @@ -2,6 +2,7 @@ package org.jetbrains.plugins.github.pullrequest.ui.details.action import com.intellij.collaboration.messages.CollaborationToolsBundle +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.plugins.github.pullrequest.GHPRAction @@ -11,7 +12,7 @@ import java.awt.event.ActionEvent import javax.swing.AbstractAction import javax.swing.JButton -internal class GHPRSetMyselfAsReviewerAction(scope: CoroutineScope, private val reviewFlowVm: GHPRReviewFlowViewModel) +internal class GHPRSetMyselfAsReviewerAction(scope: CoroutineScope, private val project: Project, private val reviewFlowVm: GHPRReviewFlowViewModel) : AbstractAction(CollaborationToolsBundle.message("review.details.action.set.myself.as.reviewer")) { init { @@ -23,7 +24,7 @@ internal class GHPRSetMyselfAsReviewerAction(scope: CoroutineScope, private val } override fun actionPerformed(event: ActionEvent) { - GHPRStatisticsCollector.logDetailsActionInvoked(GHPRAction.REQUEST_REVIEW_MYSELF, event.source is JButton) + GHPRStatisticsCollector.logDetailsActionInvoked(project, GHPRAction.REQUEST_REVIEW_MYSELF, event.source is JButton) reviewFlowVm.setMyselfAsReviewer() } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRSquashMergeAction.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRSquashMergeAction.kt index 209eb0fd5843..aa3aa95cd85e 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRSquashMergeAction.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/action/GHPRSquashMergeAction.kt @@ -3,6 +3,7 @@ package org.jetbrains.plugins.github.pullrequest.ui.details.action import com.intellij.collaboration.async.combineAndCollect import com.intellij.collaboration.messages.CollaborationToolsBundle +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.plugins.github.pullrequest.GHPRAction @@ -12,7 +13,7 @@ import java.awt.event.ActionEvent import javax.swing.AbstractAction import javax.swing.JButton -internal class GHPRSquashMergeAction(scope: CoroutineScope, private val reviewFlowVm: GHPRReviewFlowViewModel) +internal class GHPRSquashMergeAction(scope: CoroutineScope, private val project: Project, private val reviewFlowVm: GHPRReviewFlowViewModel) : AbstractAction(CollaborationToolsBundle.message("review.details.action.squash.and.merge")) { init { @@ -24,7 +25,7 @@ internal class GHPRSquashMergeAction(scope: CoroutineScope, private val reviewFl } override fun actionPerformed(e: ActionEvent?) { - GHPRStatisticsCollector.logDetailsActionInvoked(GHPRAction.SQUASH_MERGE, e?.source is JButton) + GHPRStatisticsCollector.logDetailsActionInvoked(project, GHPRAction.SQUASH_MERGE, e?.source is JButton) reviewFlowVm.squashAndMergeReview() } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/GHPRBranchesViewModel.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/GHPRBranchesViewModel.kt index 7bdb5a05e109..9b658428a28b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/GHPRBranchesViewModel.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/GHPRBranchesViewModel.kt @@ -103,7 +103,7 @@ internal class GHPRBranchesViewModel( val branch = "${headRemote.name}/${headBranch}" invokeLater { GitBranchPopupActions.RemoteBranchActions.CheckoutRemoteBranchAction.checkoutRemoteBranch(project, listOf(repository), branch) - GHPRStatisticsCollector.logDetailsBranchCheckedOut() + GHPRStatisticsCollector.logDetailsBranchCheckedOut(project) } } } @@ -162,7 +162,7 @@ internal class GHPRBranchesViewModel( val source = _sourceBranch.value val target = _targetBranch.value _showBranchesRequests.emit(CodeReviewBranches(source, target)) - GHPRStatisticsCollector.logDetailsBranchesOpened() + GHPRStatisticsCollector.logDetailsBranchesOpened(project) } } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/GHPRStatusViewModel.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/GHPRStatusViewModel.kt index 243c5d541e1a..6b6d2a524712 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/GHPRStatusViewModel.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/GHPRStatusViewModel.kt @@ -6,6 +6,7 @@ import com.intellij.collaboration.async.modelFlow import com.intellij.collaboration.ui.codereview.details.data.CodeReviewCIJob import com.intellij.collaboration.ui.codereview.details.model.CodeReviewStatusViewModel import com.intellij.openapi.diagnostic.thisLogger +import com.intellij.openapi.project.Project import com.intellij.util.childScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* @@ -21,7 +22,11 @@ interface GHPRStatusViewModel : CodeReviewStatusViewModel { val requiredApprovingReviewsCount: Flow } -class GHPRStatusViewModelImpl(parentCs: CoroutineScope, stateModel: GHPRStateModel) : GHPRStatusViewModel { +class GHPRStatusViewModelImpl( + parentCs: CoroutineScope, + private val project: Project, + stateModel: GHPRStateModel +) : GHPRStatusViewModel { private val cs = parentCs.childScope() override val viewerDidAuthor: Boolean = stateModel.viewerDidAuthor @@ -59,7 +64,7 @@ class GHPRStatusViewModelImpl(parentCs: CoroutineScope, stateModel: GHPRStateMod cs.launchNow { val jobs = ciJobs.first() _showJobsDetailsRequests.emit(jobs) - GHPRStatisticsCollector.logDetailsChecksOpened() + GHPRStatisticsCollector.logDetailsChecksOpened(project) } } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/impl/GHPRCommitsViewModel.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/impl/GHPRCommitsViewModel.kt index 1dafedad486f..8f4402562ac4 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/impl/GHPRCommitsViewModel.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/details/model/impl/GHPRCommitsViewModel.kt @@ -2,6 +2,7 @@ package org.jetbrains.plugins.github.pullrequest.ui.details.model.impl import com.intellij.collaboration.ui.codereview.details.model.CodeReviewChangesViewModelBase +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -17,6 +18,7 @@ import org.jetbrains.plugins.github.pullrequest.ui.toolwindow.GHPRDiffController internal class GHPRCommitsViewModel( scope: CoroutineScope, + private val project: Project, commitsLoadingModel: GHSimpleLoadingModel>, securityService: GHPRSecurityService, private val diffBridge: GHPRDiffController @@ -39,16 +41,16 @@ internal class GHPRCommitsViewModel( diffBridge.activeTree = GHPRDiffController.ActiveTree.FILES } super.selectCommit(index) - GHPRStatisticsCollector.logDetailsCommitChosen() + GHPRStatisticsCollector.logDetailsCommitChosen(project) } override fun selectNextCommit() { super.selectNextCommit() - GHPRStatisticsCollector.logDetailsNextCommitChosen() + GHPRStatisticsCollector.logDetailsNextCommitChosen(project) } override fun selectPreviousCommit() { super.selectPreviousCommit() - GHPRStatisticsCollector.logDetailsPrevCommitChosen() + GHPRStatisticsCollector.logDetailsPrevCommitChosen(project) } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/filters/GHPRSearchPanelViewModel.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/filters/GHPRSearchPanelViewModel.kt index 313a8a33798b..9a3b3917939c 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/filters/GHPRSearchPanelViewModel.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/filters/GHPRSearchPanelViewModel.kt @@ -4,6 +4,7 @@ package org.jetbrains.plugins.github.pullrequest.ui.filters import com.intellij.collaboration.async.launchNow import com.intellij.collaboration.ui.codereview.list.search.ReviewListQuickFilter import com.intellij.collaboration.ui.codereview.list.search.ReviewListSearchPanelViewModelBase +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.debounce @@ -18,6 +19,7 @@ import org.jetbrains.plugins.github.pullrequest.ui.filters.GHPRListQuickFilter.* @OptIn(FlowPreview::class) internal class GHPRSearchPanelViewModel( scope: CoroutineScope, + private val project: Project, private val repositoryDataService: GHPRRepositoryDataService, historyViewModel: GHPRSearchHistoryModel, currentUser: GHUser @@ -62,7 +64,7 @@ internal class GHPRSearchPanelViewModel( scope.launchNow { // with debounce to avoid collecting intermediate state searchState.drop(1).debounce(5000).collect { - GHPRStatisticsCollector.logListFiltersApplied(it) + GHPRStatisticsCollector.logListFiltersApplied(project, it) } } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/list/GHPRListPanelFactory.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/list/GHPRListPanelFactory.kt index 5c81be284a89..2064e7da3c33 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/list/GHPRListPanelFactory.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/list/GHPRListPanelFactory.kt @@ -57,7 +57,7 @@ internal class GHPRListPanelFactory(private val project: Project, val actionManager = ActionManager.getInstance() val historyModel = GHPRSearchHistoryModel(project.service()) - val searchVm = GHPRSearchPanelViewModel(scope, repositoryDataService, historyModel, securityService.currentUser) + val searchVm = GHPRSearchPanelViewModel(scope, project, repositoryDataService, historyModel, securityService.currentUser) scope.launch { searchVm.searchState.collectLatest { listLoader.searchQuery = it.toQuery() diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/GHPRViewComponentFactory.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/GHPRViewComponentFactory.kt index bb8f17bf1204..db71fe9782b7 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/GHPRViewComponentFactory.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/GHPRViewComponentFactory.kt @@ -182,7 +182,7 @@ internal class GHPRViewComponentFactory(private val actionManager: ActionManager val scope = DisposingScope(disposable, SupervisorJob() + Dispatchers.Main.immediate) val reviewDetailsVm = GHPRDetailsViewModelImpl(detailsModel, stateModel) val reviewBranchesVm = GHPRBranchesViewModel(scope, project, branchesModel, dataProvider.detailsData) - val reviewStatusVm = GHPRStatusViewModelImpl(scope, stateModel) + val reviewStatusVm = GHPRStatusViewModelImpl(scope, project, stateModel) val reviewFlowVm = GHPRReviewFlowViewModelImpl(scope, metadataModel, stateModel, @@ -191,9 +191,10 @@ internal class GHPRViewComponentFactory(private val actionManager: ActionManager dataProvider.detailsData, dataProvider.reviewData, disposable) - val commitsVm = GHPRCommitsViewModel(scope, commitsLoadingModel, dataContext.securityService, diffBridge) + val commitsVm = GHPRCommitsViewModel(scope, project, commitsLoadingModel, dataContext.securityService, diffBridge) GHPRDetailsComponentFactory.create(scope, + project, reviewDetailsVm, reviewBranchesVm, reviewStatusVm, reviewFlowVm, commitsVm, dataProvider, dataContext.securityService, dataContext.avatarIconsProvider, @@ -275,7 +276,7 @@ internal class GHPRViewComponentFactory(private val actionManager: ActionManager tree.addSelectionListener { if (tree.isFocusOwner) { - GHPRStatisticsCollector.logChangeSelected() + GHPRStatisticsCollector.logChangeSelected(project) } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/MultiTabGHPRToolWindowContentController.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/MultiTabGHPRToolWindowContentController.kt index fbdfa60b258a..c56ee3ec73a2 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/MultiTabGHPRToolWindowContentController.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/MultiTabGHPRToolWindowContentController.kt @@ -69,7 +69,7 @@ internal class MultiTabGHPRToolWindowContentController(parentDisposable: Disposa _contentController = CompletableFuture() } showSelectorsTab(requestFocus) - GHPRStatisticsCollector.logSelectorsOpened() + GHPRStatisticsCollector.logSelectorsOpened(project) } else { val controller = showRepositoryContent(conn, requestFocus) diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/MultiTabGHPRToolWindowRepositoryContentController.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/MultiTabGHPRToolWindowRepositoryContentController.kt index 6e325fcf2503..9befeccac331 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/MultiTabGHPRToolWindowRepositoryContentController.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/ui/toolwindow/MultiTabGHPRToolWindowRepositoryContentController.kt @@ -56,7 +56,7 @@ internal class MultiTabGHPRToolWindowRepositoryContentController( it.type == TabType.New } ?: createAndAddNewPRContent() contentManager.setSelectedContent(content, requestFocus) - GHPRStatisticsCollector.logNewPRViewOpened() + GHPRStatisticsCollector.logNewPRViewOpened(project) } private fun createAndAddNewPRContent(): Content { @@ -90,7 +90,7 @@ internal class MultiTabGHPRToolWindowRepositoryContentController( it.type == TabType.List } ?: createAndAddListContent() contentManager.setSelectedContent(content, requestFocus) - GHPRStatisticsCollector.logListOpened() + GHPRStatisticsCollector.logListOpened(project) } private fun createAndAddListContent(): Content { @@ -143,7 +143,7 @@ internal class MultiTabGHPRToolWindowRepositoryContentController( (it.type as? TabType.PR)?.id == id } ?: createAndAddPRContent(id) contentManager.setSelectedContent(content, requestFocus) - GHPRStatisticsCollector.logDetailsOpened() + GHPRStatisticsCollector.logDetailsOpened(project) return UIUtil.findComponentOfType(content.component, ChangesTree::class.java)?.let { ClientProperty.get(it, GHPRCommitBrowserComponentController.KEY) diff --git a/plugins/gitlab/resources/graphql/fragment/mergeRequest.graphql b/plugins/gitlab/resources/graphql/fragment/mergeRequest.graphql index d12dd21b3f2f..8ca8d5e5317f 100644 --- a/plugins/gitlab/resources/graphql/fragment/mergeRequest.graphql +++ b/plugins/gitlab/resources/graphql/fragment/mergeRequest.graphql @@ -25,6 +25,7 @@ fragment mergeRequest on MergeRequest { headSha } + approved conflicts headPipeline { ...pipeline @@ -73,7 +74,7 @@ fragment mergeRequest on MergeRequest { } nodes { - ...user + ...userReviewer } } diff --git a/plugins/gitlab/resources/graphql/fragment/project.graphql b/plugins/gitlab/resources/graphql/fragment/project.graphql index 0dc8c57ef576..96925553a820 100644 --- a/plugins/gitlab/resources/graphql/fragment/project.graphql +++ b/plugins/gitlab/resources/graphql/fragment/project.graphql @@ -1,5 +1,8 @@ fragment project on Project { name + nameWithNamespace + path + fullPath httpUrlToRepo - webUrl + sshUrlToRepo } \ No newline at end of file diff --git a/plugins/gitlab/resources/graphql/fragment/userReviewer.graphql b/plugins/gitlab/resources/graphql/fragment/userReviewer.graphql new file mode 100644 index 000000000000..a536b6f75674 --- /dev/null +++ b/plugins/gitlab/resources/graphql/fragment/userReviewer.graphql @@ -0,0 +1,7 @@ +fragment userReviewer on MergeRequestReviewer { + ...user + mergeRequestInteraction { + approved + reviewed + } +} \ No newline at end of file diff --git a/plugins/gitlab/resources/graphql/query/mergeRequestReviewerRereview.graphql b/plugins/gitlab/resources/graphql/query/mergeRequestReviewerRereview.graphql new file mode 100644 index 000000000000..0e4cbfb516a6 --- /dev/null +++ b/plugins/gitlab/resources/graphql/query/mergeRequestReviewerRereview.graphql @@ -0,0 +1,12 @@ +mutation ($projectId: ID!, $mergeRequestId: String!, $userId: UserID!) { + mergeRequestReviewerRereview(input: { + projectPath: $projectId, + iid: $mergeRequestId, + userId: $userId + }) { + mergeRequest { + ...mergeRequest + } + errors + } +} \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/GitLabGQLQuery.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/GitLabGQLQuery.kt index 672764c80a9b..ff8a588f313d 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/GitLabGQLQuery.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/GitLabGQLQuery.kt @@ -18,5 +18,6 @@ enum class GitLabGQLQuery(val filePath: String) { MERGE_REQUEST_ACCEPT("graphql/query/mergeRequestAccept.graphql"), MERGE_REQUEST_SET_DRAFT("graphql/query/mergeRequestSetDraft.graphql"), MERGE_REQUEST_SET_REVIEWERS("graphql/query/mergeRequestSetReviewers.graphql"), - MERGE_REQUEST_UPDATE("graphql/query/mergeRequestUpdate.graphql") + MERGE_REQUEST_UPDATE("graphql/query/mergeRequestUpdate.graphql"), + MERGE_REQUEST_REVIEWER_REREVIEW("graphql/query/mergeRequestReviewerRereview.graphql") } diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabProjectDTO.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabProjectDTO.kt index a94352e627ed..ce0b4646294b 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabProjectDTO.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabProjectDTO.kt @@ -2,11 +2,18 @@ package org.jetbrains.plugins.gitlab.api.dto import com.intellij.collaboration.api.dto.GraphQLFragment +import com.intellij.openapi.util.NlsSafe import org.jetbrains.annotations.Nls +// namespace can be null for some reason, so we need to parse paths manually @GraphQLFragment("/graphql/fragment/project.graphql") data class GitLabProjectDTO( val name: @Nls String, - val httpUrlToRepo: String, - val webUrl: String -) \ No newline at end of file + val nameWithNamespace: @Nls String, + val path: @NlsSafe String, + val fullPath: @NlsSafe String, + val httpUrlToRepo: @NlsSafe String?, + val sshUrlToRepo: @NlsSafe String? +) { + val ownerPath: @NlsSafe String = fullPath.split("/").dropLast(1).joinToString("/") +} \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabReviewerDTO.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabReviewerDTO.kt new file mode 100644 index 000000000000..80522aa0be61 --- /dev/null +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabReviewerDTO.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.plugins.gitlab.api.dto + +import com.intellij.collaboration.api.dto.GraphQLFragment +import com.intellij.openapi.util.NlsSafe + +@GraphQLFragment("graphql/fragment/userReviewer.graphql") +class GitLabReviewerDTO( + id: String, + username: @NlsSafe String, + name: @NlsSafe String, + avatarUrl: String?, + webUrl: String, + val mergeRequestInteraction: MergeRequestInteraction? +) : GitLabUserDTO(id, username, name, avatarUrl, webUrl) { + + data class MergeRequestInteraction( + val approved: Boolean, + val reviewed: Boolean + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + if (!super.equals(other)) return false + + other as GitLabReviewerDTO + + return mergeRequestInteraction == other.mergeRequestInteraction + } + + override fun hashCode(): Int { + var result = super.hashCode() + result = 31 * result + (mergeRequestInteraction?.hashCode() ?: 0) + return result + } +} \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabUserDTO.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabUserDTO.kt index 4e6b74509ecf..6230e008cc10 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabUserDTO.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/api/dto/GitLabUserDTO.kt @@ -4,6 +4,7 @@ package org.jetbrains.plugins.gitlab.api.dto import com.intellij.collaboration.api.dto.GraphQLFragment import com.intellij.collaboration.auth.AccountDetails import com.intellij.openapi.util.NlsSafe +import java.net.URL @GraphQLFragment("graphql/fragment/user.graphql") open class GitLabUserDTO( @@ -14,13 +15,46 @@ open class GitLabUserDTO( val webUrl: String ) : AccountDetails { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as GitLabUserDTO + + if (id != other.id) return false + if (username != other.username) return false + if (name != other.name) return false + if (avatarUrl != other.avatarUrl) return false + if (webUrl != other.webUrl) return false + + return true + } + + override fun hashCode(): Int { + var result = id.hashCode() + result = 31 * result + username.hashCode() + result = 31 * result + name.hashCode() + result = 31 * result + (avatarUrl?.hashCode() ?: 0) + result = 31 * result + webUrl.hashCode() + return result + } + companion object { - fun fromRestDTO(dto: GitLabUserRestDTO): GitLabUserDTO = GitLabUserDTO( - id = "gid://gitlab/User/${dto.id}", - username = dto.username, - name = dto.name, - avatarUrl = dto.avatarUrl?.removePrefix("https://gitlab.com"), - webUrl = dto.webUrl - ) + fun fromRestDTO(dto: GitLabUserRestDTO): GitLabUserDTO { + val url = URL(dto.webUrl) + val serverId = url.host.split(".").dropLast(1).joinToString(".") + + val server = dto.avatarUrl?.let { + URL(it) + } + + return GitLabUserDTO( + id = "gid://$serverId/User/${dto.id}", + username = dto.username, + name = dto.name, + avatarUrl = server?.path, + webUrl = dto.webUrl + ) + } } } \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/action/GitLabMergeRequestReRequestReviewAction.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/action/GitLabMergeRequestReRequestReviewAction.kt index bb4051c06483..09b48c81ce41 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/action/GitLabMergeRequestReRequestReviewAction.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/action/GitLabMergeRequestReRequestReviewAction.kt @@ -1,11 +1,25 @@ // 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.plugins.gitlab.mergerequest.action +import com.intellij.collaboration.async.combineAndCollect import com.intellij.collaboration.messages.CollaborationToolsBundle +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import org.jetbrains.plugins.gitlab.mergerequest.ui.details.model.GitLabMergeRequestReviewFlowViewModel import java.awt.event.ActionEvent import javax.swing.AbstractAction -// TODO: implement -class GitLabMergeRequestReRequestReviewAction : AbstractAction(CollaborationToolsBundle.message("review.details.action.rerequest")) { - override fun actionPerformed(e: ActionEvent?) {} +internal class GitLabMergeRequestReRequestReviewAction( + scope: CoroutineScope, + private val reviewFlowVm: GitLabMergeRequestReviewFlowViewModel +) : AbstractAction(CollaborationToolsBundle.message("review.details.action.rerequest")) { + init { + scope.launch { + combineAndCollect(reviewFlowVm.isBusy, reviewFlowVm.userCanManage) { isBusy, userCanManageReview -> + isEnabled = !isBusy && userCanManageReview + } + } + } + + override fun actionPerformed(e: ActionEvent?) = reviewFlowVm.reviewerRereview() } \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/dto/GitLabMergeRequestDTO.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/dto/GitLabMergeRequestDTO.kt index 0aac4aebbe4a..b43243e6e826 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/dto/GitLabMergeRequestDTO.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/dto/GitLabMergeRequestDTO.kt @@ -21,6 +21,7 @@ class GitLabMergeRequestDTO( val targetBranch: String, val sourceBranch: String, val diffRefs: GitLabDiffRefs, + val approved: Boolean, val conflicts: Boolean, val headPipeline: GitLabPipelineDTO?, val mergeStatusEnum: GitLabMergeStatus, @@ -43,7 +44,7 @@ class GitLabMergeRequestDTO( val assignees: List = assignees.nodes - val reviewers: List = reviewers.nodes + val reviewers: List = reviewers.nodes val commits: List = commits.nodes @@ -55,8 +56,8 @@ class GitLabMergeRequestDTO( class AssigneeConnection(pageInfo: GraphQLCursorPageInfoDTO, nodes: List) : GraphQLConnectionDTO(pageInfo, nodes) - class ReviewerConnection(pageInfo: GraphQLCursorPageInfoDTO, nodes: List) - : GraphQLConnectionDTO(pageInfo, nodes) + class ReviewerConnection(pageInfo: GraphQLCursorPageInfoDTO, nodes: List) + : GraphQLConnectionDTO(pageInfo, nodes) class CommitConnection(pageInfo: GraphQLCursorPageInfoDTO, nodes: List) : GraphQLConnectionDTO(pageInfo, nodes) diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/dto/GitLabMergeRequestShortRestDTO.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/dto/GitLabMergeRequestShortRestDTO.kt index 6dc77753e07a..31686837c412 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/dto/GitLabMergeRequestShortRestDTO.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/dto/GitLabMergeRequestShortRestDTO.kt @@ -3,7 +3,7 @@ package org.jetbrains.plugins.gitlab.mergerequest.api.dto import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.logger -import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO +import org.jetbrains.plugins.gitlab.api.dto.GitLabUserRestDTO import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequestId import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequestState import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeStatus @@ -18,9 +18,9 @@ data class GitLabMergeRequestShortRestDTO( val state: String, val mergeStatus: String, val mergeable: Boolean, - val author: GitLabUserDTO, - val assignees: List, - val reviewers: List, + val author: GitLabUserRestDTO, + val assignees: List, + val reviewers: List, val labels: List, val createdAt: Date, val draft: Boolean, diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/request/GitLabMergeRequestsApi.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/request/GitLabMergeRequestsApi.kt index 6b2555a1abc7..59af72155c92 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/request/GitLabMergeRequestsApi.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/api/request/GitLabMergeRequestsApi.kt @@ -8,6 +8,7 @@ import com.intellij.collaboration.util.resolveRelative import com.intellij.collaboration.util.withQuery import org.jetbrains.plugins.gitlab.api.* import org.jetbrains.plugins.gitlab.api.dto.GitLabGraphQLMutationResultDTO +import org.jetbrains.plugins.gitlab.api.dto.GitLabReviewerDTO import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.mergerequest.api.dto.GitLabMergeRequestApprovalRestDTO import org.jetbrains.plugins.gitlab.mergerequest.api.dto.GitLabMergeRequestDTO @@ -161,6 +162,22 @@ suspend fun GitLabApi.GraphQL.mergeRequestSetDraft( } } +suspend fun GitLabApi.GraphQL.mergeRequestReviewerRereview( + project: GitLabProjectCoordinates, + mergeRequestId: GitLabMergeRequestId, + reviewer: GitLabReviewerDTO +): HttpResponse?> { + val parameters = mapOf( + "projectId" to project.projectPath.fullPath(), + "mergeRequestId" to mergeRequestId.iid, + "userId" to reviewer.id + ) + val request = gitLabQuery(project.serverPath, GitLabGQLQuery.MERGE_REQUEST_REVIEWER_REREVIEW, parameters) + return withErrorStats(project.serverPath, GitLabGQLQuery.MERGE_REQUEST_REVIEWER_REREVIEW) { + loadResponse(request, "mergeRequestReviewerRereview") + } +} + private class GitLabMergeRequestResult(mergeRequest: GitLabMergeRequestDTO, errors: List?) : GitLabGraphQLMutationResultDTO(errors) { override val value = mergeRequest diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabDiscussion.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabDiscussion.kt index b4107379db88..8ff40c103869 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabDiscussion.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabDiscussion.kt @@ -4,6 +4,7 @@ package org.jetbrains.plugins.gitlab.mergerequest.data import com.intellij.collaboration.async.mapCaching import com.intellij.collaboration.async.modelFlow import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.project.Project import com.intellij.util.childScope import kotlinx.coroutines.* import kotlinx.coroutines.flow.* @@ -47,8 +48,9 @@ private val LOG = logger() @OptIn(ExperimentalCoroutinesApi::class) class LoadedGitLabDiscussion( parentCs: CoroutineScope, + private val project: Project, private val api: GitLabApi, - private val project: GitLabProjectCoordinates, + private val glProject: GitLabProjectCoordinates, private val eventSink: suspend (GitLabDiscussionEvent) -> Unit, private val mr: GitLabMergeRequest, discussionData: GitLabDiscussionDTO, @@ -101,7 +103,7 @@ class LoadedGitLabDiscussion( loadedNotes .mapCaching( GitLabNoteDTO::id, - { note -> MutableGitLabMergeRequestNote(this, api, project, mr, noteEvents::emit, note) }, + { note -> MutableGitLabMergeRequestNote(this, project, api, glProject, mr, noteEvents::emit, note) }, MutableGitLabMergeRequestNote::destroy, MutableGitLabMergeRequestNote::update ).combine(draftNotes) { notes, draftNotes -> @@ -123,25 +125,25 @@ class LoadedGitLabDiscussion( operationsGuard.withLock { val resolved = resolved.first() val result = withContext(Dispatchers.IO) { - api.graphQL.changeMergeRequestDiscussionResolve(project, apiId, !resolved).getResultOrThrow() + api.graphQL.changeMergeRequestDiscussionResolve(glProject, apiId, !resolved).getResultOrThrow() } noteEvents.emit(GitLabNoteEvent.Changed(result.notes)) } } - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.CHANGE_DISCUSSION_RESOLVE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.CHANGE_DISCUSSION_RESOLVE) } override suspend fun addNote(body: String) { withContext(cs.coroutineContext) { withContext(Dispatchers.IO) { - api.graphQL.createReplyNote(project, mr.gid, id, body).getResultOrThrow() + api.graphQL.createReplyNote(glProject, mr.gid, id, body).getResultOrThrow() }.also { withContext(NonCancellable) { noteEvents.emit(GitLabNoteEvent.Added(it)) } } } - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.ADD_DISCUSSION_NOTE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.ADD_DISCUSSION_NOTE) } fun update(data: GitLabDiscussionDTO) { diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequest.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequest.kt index db85d14ac04b..eab81206e0ea 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequest.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequest.kt @@ -42,13 +42,14 @@ interface GitLabMergeRequest : GitLabMergeRequestDiscussionsContainer { val descriptionHtml: Flow val targetBranch: StateFlow val sourceBranch: StateFlow + val isApproved: Flow val hasConflicts: Flow val isDraft: Flow val reviewRequestState: Flow val isMergeable: Flow val shouldBeRebased: Flow val approvedBy: Flow> - val reviewers: Flow> + val reviewers: Flow> val pipeline: Flow val changes: Flow @@ -83,6 +84,8 @@ interface GitLabMergeRequest : GitLabMergeRequestDiscussionsContainer { suspend fun setReviewers(reviewers: List) + suspend fun reviewerRereview(reviewers: Collection) + data class CurrentUserPermissions( val canApprove: Boolean, val canMerge: Boolean, @@ -122,6 +125,7 @@ internal class LoadedGitLabMergeRequest( override val descriptionHtml: Flow = description.map { if (it.isNotBlank()) GitLabUIUtil.convertToHtml(it) else it } override val targetBranch: StateFlow = mergeRequestDetailsState.mapState(cs) { it.targetBranch } override val sourceBranch: StateFlow = mergeRequestDetailsState.mapState(cs) { it.sourceBranch } + override val isApproved: Flow = mergeRequestDetailsState.map { it.isApproved } override val hasConflicts: Flow = mergeRequestDetailsState.map { it.conflicts } override val isDraft: Flow = mergeRequestDetailsState.map { it.draft } override val reviewRequestState: Flow = @@ -137,7 +141,7 @@ internal class LoadedGitLabMergeRequest( override val isMergeable: Flow = mergeRequestDetailsState.map { it.isMergeable } override val shouldBeRebased: Flow = mergeRequestDetailsState.map { it.shouldBeRebased } override val approvedBy: Flow> = mergeRequestDetailsState.map { it.approvedBy } - override val reviewers: Flow> = mergeRequestDetailsState.map { it.reviewers } + override val reviewers: Flow> = mergeRequestDetailsState.map { it.reviewers } override val pipeline: Flow = mergeRequestDetailsState.map { it.headPipeline } override val changes: Flow = mergeRequestDetailsState .distinctUntilChangedBy(GitLabMergeRequestFullDetails::diffRefs).map { @@ -218,7 +222,7 @@ internal class LoadedGitLabMergeRequest( mergeRequestDetailsState.value = GitLabMergeRequestFullDetails.fromGraphQL(updatedMergeRequest) } discussionsContainer.checkUpdates() - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.MERGE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.MERGE) } override suspend fun squashAndMerge(commitMessage: String) { @@ -232,7 +236,7 @@ internal class LoadedGitLabMergeRequest( mergeRequestDetailsState.value = GitLabMergeRequestFullDetails.fromGraphQL(updatedMergeRequest) } discussionsContainer.checkUpdates() - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.SQUASH_MERGE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.SQUASH_MERGE) } override suspend fun rebase() { @@ -246,7 +250,7 @@ internal class LoadedGitLabMergeRequest( while (updatedMergeRequest.rebaseInProgress) } discussionsContainer.checkUpdates() - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.REBASE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.REBASE) } override suspend fun approve() { @@ -264,7 +268,7 @@ internal class LoadedGitLabMergeRequest( } } discussionsContainer.checkUpdates() - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.APPROVE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.APPROVE) } override suspend fun unApprove() { @@ -282,7 +286,7 @@ internal class LoadedGitLabMergeRequest( } } discussionsContainer.checkUpdates() - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.UNAPPROVE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.UNAPPROVE) } override suspend fun close() { @@ -292,7 +296,7 @@ internal class LoadedGitLabMergeRequest( mergeRequestDetailsState.value = GitLabMergeRequestFullDetails.fromGraphQL(updatedMergeRequest) stateEventsLoader.checkForUpdates() } - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.CLOSE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.CLOSE) } override suspend fun reopen() { @@ -302,7 +306,7 @@ internal class LoadedGitLabMergeRequest( mergeRequestDetailsState.value = GitLabMergeRequestFullDetails.fromGraphQL(updatedMergeRequest) stateEventsLoader.checkForUpdates() } - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.REOPEN) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.REOPEN) } override suspend fun postReview() { @@ -312,7 +316,7 @@ internal class LoadedGitLabMergeRequest( mergeRequestDetailsState.value = GitLabMergeRequestFullDetails.fromGraphQL(updatedMergeRequest) } discussionsContainer.checkUpdates() - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.POST_REVIEW) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.POST_REVIEW) } override suspend fun setReviewers(reviewers: List) { @@ -322,10 +326,23 @@ internal class LoadedGitLabMergeRequest( mergeRequestDetailsState.value = GitLabMergeRequestFullDetails.fromGraphQL(updatedMergeRequest) } discussionsContainer.checkUpdates() - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.SET_REVIEWERS) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.SET_REVIEWERS) } - private val discussionsContainer = GitLabMergeRequestDiscussionsContainerImpl(parentCs, api, projectMapping.repository, this) + override suspend fun reviewerRereview(reviewers: Collection) { + withContext(cs.coroutineContext + Dispatchers.IO) { + reviewers.forEach { reviewer -> + val updatedMergeRequest = api.graphQL.mergeRequestReviewerRereview(glProject, mergeRequestDetailsState.value, reviewer) + .getResultOrThrow() + mergeRequestDetailsState.value = GitLabMergeRequestFullDetails.fromGraphQL(updatedMergeRequest) + } + } + discussionsContainer.checkUpdates() + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.REVIEWER_REREVIEW) + } + + private val discussionsContainer = + GitLabMergeRequestDiscussionsContainerImpl(parentCs, project, api, projectMapping.repository, this) override val discussions: Flow> = discussionsContainer.discussions override val systemNotes: Flow> = discussionsContainer.systemNotes diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestDetails.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestDetails.kt index d67dd33b43ba..cc3691c47b17 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestDetails.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestDetails.kt @@ -6,18 +6,18 @@ import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.mergerequest.api.dto.GitLabMergeRequestShortRestDTO import java.util.* -open class GitLabMergeRequestDetails( +data class GitLabMergeRequestDetails( override val iid: String, - open val title: @NlsSafe String, - open val createdAt: Date, - open val author: GitLabUserDTO, - open val mergeStatus: GitLabMergeStatus, - open val isMergeable: Boolean, - open val state: GitLabMergeRequestState, - open val draft: Boolean, - open val assignees: List, - open val reviewers: List, - open val webUrl: @NlsSafe String, + val title: @NlsSafe String, + val createdAt: Date, + val author: GitLabUserDTO, + val mergeStatus: GitLabMergeStatus, + val isMergeable: Boolean, + val state: GitLabMergeRequestState, + val draft: Boolean, + val assignees: List, + val reviewers: List, + val webUrl: @NlsSafe String, val labels: List ) : GitLabMergeRequestId { @@ -27,13 +27,13 @@ open class GitLabMergeRequestDetails( dto.iid, dto.title, dto.createdAt, - dto.author, + GitLabUserDTO.fromRestDTO(dto.author), dto.mergeStatusEnum, dto.mergeable, dto.stateEnum, dto.draft, - dto.assignees, - dto.reviewers, + dto.assignees.map(GitLabUserDTO::fromRestDTO), + dto.reviewers.map(GitLabUserDTO::fromRestDTO), dto.webUrl, dto.labels ) diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestDiscussionsContainer.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestDiscussionsContainer.kt index 73bb552209d8..551e38db869f 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestDiscussionsContainer.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestDiscussionsContainer.kt @@ -8,6 +8,7 @@ import com.intellij.collaboration.async.mapCaching import com.intellij.collaboration.async.mapFiltered import com.intellij.collaboration.async.modelFlow import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.project.Project import com.intellij.util.childScope import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow @@ -48,8 +49,9 @@ private val LOG = logger() @OptIn(ExperimentalCoroutinesApi::class) class GitLabMergeRequestDiscussionsContainerImpl( parentCs: CoroutineScope, + private val project: Project, private val api: GitLabApi, - private val project: GitLabProjectCoordinates, + private val glProject: GitLabProjectCoordinates, private val mr: GitLabMergeRequest ) : GitLabMergeRequestDiscussionsContainer { @@ -72,7 +74,7 @@ class GitLabMergeRequestDiscussionsContainerImpl( val discussionsGuard = Mutex() var lastCursor: String? = null ApiPageUtil.createGQLPagesFlow { - api.graphQL.loadMergeRequestDiscussions(project, mr.id, it) + api.graphQL.loadMergeRequestDiscussions(glProject, mr.id, it) }.collect { page -> discussionsGuard.withLock { for (dto in page.nodes.filter { it.notes.isNotEmpty() }) { @@ -84,7 +86,7 @@ class GitLabMergeRequestDiscussionsContainerImpl( if (lastCursor != null) { launchNow { updateRequests.collect { - val page = api.graphQL.loadMergeRequestDiscussions(project, mr.id, GraphQLRequestPagination(lastCursor!!)) + val page = api.graphQL.loadMergeRequestDiscussions(glProject, mr.id, GraphQLRequestPagination(lastCursor!!)) val newDiscussions = page?.nodes if (newDiscussions != null) { discussionsGuard.withLock { @@ -129,7 +131,9 @@ class GitLabMergeRequestDiscussionsContainerImpl( .mapFiltered { !it.notes.first().system } .mapCaching( GitLabDiscussionDTO::id, - { disc -> LoadedGitLabDiscussion(this, api, project, { discussionEvents.emit(it) }, mr, disc, getDiscussionDraftNotes(disc.id)) }, + { disc -> + LoadedGitLabDiscussion(this, project, api, glProject, { discussionEvents.emit(it) }, mr, disc, getDiscussionDraftNotes(disc.id)) + }, LoadedGitLabDiscussion::destroy, LoadedGitLabDiscussion::update ) @@ -153,16 +157,16 @@ class GitLabMergeRequestDiscussionsContainerImpl( private suspend fun FlowCollector>.collectDraftNotes() { supervisorScope { // we shouldn't get another user's draft notes - val currentUser = api.graphQL.getCurrentUser(project.serverPath) ?: error("Unable to load current user") + val currentUser = api.graphQL.getCurrentUser(glProject.serverPath) ?: error("Unable to load current user") val notesGuard = Mutex() val draftNotes = LinkedHashMap() var lastETag: String? = null - val uri = getMergeRequestDraftNotesUri(project, mr.id) + val uri = getMergeRequestDraftNotesUri(glProject, mr.id) ApiPageUtil.createPagesFlowByLinkHeader(uri) { api.rest.loadUpdatableJsonList( - project.serverPath, GitLabApiRequestName.REST_GET_DRAFT_NOTES, it + glProject.serverPath, GitLabApiRequestName.REST_GET_DRAFT_NOTES, it ) }.collect { val newNotes = it.body() ?: error("Empty response") @@ -178,7 +182,7 @@ class GitLabMergeRequestDiscussionsContainerImpl( launchNow { updateRequests.collect { val response = api.rest.loadUpdatableJsonList( - project.serverPath, GitLabApiRequestName.REST_GET_DRAFT_NOTES, uri, lastETag + glProject.serverPath, GitLabApiRequestName.REST_GET_DRAFT_NOTES, uri, lastETag ) val newNotes = response.body() if (newNotes != null) { @@ -218,7 +222,7 @@ class GitLabMergeRequestDiscussionsContainerImpl( override val draftNotes: Flow> = draftNotesData.mapCaching( { it.note.id }, - { (note, author) -> GitLabMergeRequestDraftNoteImpl(this, api, project, mr, draftNotesEvents::emit, note, author) }, + { (note, author) -> GitLabMergeRequestDraftNoteImpl(this, api, glProject, mr, draftNotesEvents::emit, note, author) }, GitLabMergeRequestDraftNoteImpl::destroy, { update(it.note) } ).modelFlow(cs, LOG) @@ -234,40 +238,40 @@ class GitLabMergeRequestDiscussionsContainerImpl( override suspend fun addNote(body: String) { withContext(cs.coroutineContext) { withContext(Dispatchers.IO) { - api.graphQL.addNote(project, mr.gid, body).getResultOrThrow() + api.graphQL.addNote(glProject, mr.gid, body).getResultOrThrow() }.also { withContext(NonCancellable) { discussionEvents.emit(GitLabDiscussionEvent.Added(it)) } } } - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.ADD_NOTE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.ADD_NOTE) } override suspend fun addNote(position: GitLabDiffPositionInput, body: String) { withContext(cs.coroutineContext) { withContext(Dispatchers.IO) { - api.graphQL.addDiffNote(project, mr.gid, position, body).getResultOrThrow() + api.graphQL.addDiffNote(glProject, mr.gid, position, body).getResultOrThrow() }.also { withContext(NonCancellable) { discussionEvents.emit(GitLabDiscussionEvent.Added(it)) } } } - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.ADD_DIFF_NOTE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.ADD_DIFF_NOTE) } override suspend fun submitDraftNotes() { withContext(cs.coroutineContext) { withContext(Dispatchers.IO) { - api.rest.submitDraftNotes(project, mr.id) + api.rest.submitDraftNotes(glProject, mr.id) } withContext(NonCancellable) { draftNotesEvents.emit(GitLabNoteEvent.AllDeleted()) reloadRequests.emit(Unit) } } - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.SUBMIT_DRAFT_NOTES) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.SUBMIT_DRAFT_NOTES) } fun requestReload() { diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestFullDetails.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestFullDetails.kt index e3d3c9870e7e..1a704ee1e222 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestFullDetails.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabMergeRequestFullDetails.kt @@ -8,16 +8,16 @@ import java.util.* data class GitLabMergeRequestFullDetails( override val iid: String, - override val title: @NlsSafe String, - override val createdAt: Date, - override val author: GitLabUserDTO, - override val mergeStatus: GitLabMergeStatus, - override val isMergeable: Boolean, - override val state: GitLabMergeRequestState, - override val draft: Boolean, - override val assignees: List, - override val reviewers: List, - override val webUrl: @NlsSafe String, + val title: @NlsSafe String, + val createdAt: Date, + val author: GitLabUserDTO, + val mergeStatus: GitLabMergeStatus, + val isMergeable: Boolean, + val state: GitLabMergeRequestState, + val draft: Boolean, + val assignees: List, + val reviewers: List, + val webUrl: @NlsSafe String, val detailedLabels: List, val targetProject: GitLabProjectDTO, val sourceProject: GitLabProjectDTO?, @@ -25,6 +25,7 @@ data class GitLabMergeRequestFullDetails( val approvedBy: List, val targetBranch: String, val sourceBranch: String, + val isApproved: Boolean, val conflicts: Boolean, val commits: List, val diffRefs: GitLabDiffRefs, @@ -32,8 +33,7 @@ data class GitLabMergeRequestFullDetails( val userPermissions: GitLabMergeRequestPermissionsDTO, val shouldBeRebased: Boolean, val rebaseInProgress: Boolean -) : GitLabMergeRequestDetails(iid, title, createdAt, author, mergeStatus, isMergeable, state, draft, assignees, reviewers, webUrl, - detailedLabels.map { it.title }) { +) : GitLabMergeRequestId { companion object { fun fromGraphQL(dto: GitLabMergeRequestDTO) = GitLabMergeRequestFullDetails( @@ -54,6 +54,7 @@ data class GitLabMergeRequestFullDetails( approvedBy = dto.approvedBy, targetBranch = dto.targetBranch, sourceBranch = dto.sourceBranch, + isApproved = dto.approved, conflicts = dto.conflicts, commits = dto.commits, diffRefs = dto.diffRefs, diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabNote.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabNote.kt index 344c97924287..5a5d00e02fb8 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabNote.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabNote.kt @@ -4,6 +4,7 @@ package org.jetbrains.plugins.gitlab.mergerequest.data import com.intellij.collaboration.async.mapState import com.intellij.collaboration.async.modelFlow import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.project.Project import com.intellij.util.childScope import kotlinx.coroutines.* import kotlinx.coroutines.flow.* @@ -54,8 +55,9 @@ private val LOG = logger() class MutableGitLabMergeRequestNote( parentCs: CoroutineScope, + private val project: Project, private val api: GitLabApi, - private val project: GitLabProjectCoordinates, + private val glProject: GitLabProjectCoordinates, mr: GitLabMergeRequest, private val eventSink: suspend (GitLabNoteEvent) -> Unit, private val noteData: GitLabNoteDTO @@ -82,24 +84,24 @@ class MutableGitLabMergeRequestNote( withContext(cs.coroutineContext) { operationsGuard.withLock { withContext(Dispatchers.IO) { - api.graphQL.updateNote(project, noteData.id, newText).getResultOrThrow() + api.graphQL.updateNote(glProject, noteData.id, newText).getResultOrThrow() } } data.update { it.copy(body = newText) } } - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.UPDATE_NOTE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.UPDATE_NOTE) } override suspend fun delete() { withContext(cs.coroutineContext) { operationsGuard.withLock { withContext(Dispatchers.IO) { - api.graphQL.deleteNote(project, noteData.id).getResultOrThrow() + api.graphQL.deleteNote(glProject, noteData.id).getResultOrThrow() } } eventSink(GitLabNoteEvent.Deleted(noteData.id)) } - GitLabStatistics.logMrActionExecuted(GitLabStatistics.MergeRequestAction.DELETE_NOTE) + GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.DELETE_NOTE) } fun update(item: GitLabNoteDTO) { diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffExtension.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffExtension.kt index 514f363667eb..46ef60b781c0 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffExtension.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffExtension.kt @@ -61,7 +61,7 @@ class GitLabMergeRequestDiffExtension : DiffExtension() { cs.launch { val isCumulative = changeVmFlow.first().isCumulativeChange - GitLabStatistics.logMrDiffOpened(isCumulative) + GitLabStatistics.logMrDiffOpened(project, isCumulative) } val discussions = changeVmFlow.flatMapLatest { it.discussions } diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/GitLabMergeRequestDetailsActionsComponentFactory.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/GitLabMergeRequestDetailsActionsComponentFactory.kt index f190b3c629a6..7607149bf199 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/GitLabMergeRequestDetailsActionsComponentFactory.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/GitLabMergeRequestDetailsActionsComponentFactory.kt @@ -25,6 +25,7 @@ import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.mergerequest.action.* import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabMergeRequestSubmitReviewPopup import org.jetbrains.plugins.gitlab.mergerequest.ui.details.model.GitLabMergeRequestReviewFlowViewModel +import org.jetbrains.plugins.gitlab.mergerequest.ui.details.model.GitLabMergeRequestReviewFlowViewModelImpl.Companion.toReviewState import org.jetbrains.plugins.gitlab.util.GitLabBundle import javax.swing.JButton import javax.swing.JComponent @@ -39,7 +40,7 @@ internal object GitLabMergeRequestDetailsActionsComponentFactory { ): JComponent { val reviewActions = CodeReviewActions( requestReviewAction = GitLabMergeRequestRequestReviewAction(scope, reviewFlowVm, avatarIconsProvider), - reRequestReviewAction = GitLabMergeRequestReRequestReviewAction(), + reRequestReviewAction = GitLabMergeRequestReRequestReviewAction(scope, reviewFlowVm), closeReviewAction = GitLabMergeRequestCloseAction(scope, reviewFlowVm), reopenReviewAction = GitLabMergeRequestReopenAction(scope, reviewFlowVm), setMyselfAsReviewerAction = GitLabMergeRequestSetMyselfAsReviewerAction(scope, reviewFlowVm), @@ -53,7 +54,12 @@ internal object GitLabMergeRequestDetailsActionsComponentFactory { return Wrapper().apply { bindContentIn(scope, reviewFlowVm.role) { role -> val mainPanel = when (role) { - ReviewRole.AUTHOR -> createActionsForAuthor(reviewFlowVm.reviewState, reviewFlowVm.reviewers, reviewActions, moreActionsGroup) + ReviewRole.AUTHOR -> { + val requestedReviewers = reviewFlowVm.reviewers.map { reviewers -> + reviewers.filter { it.mergeRequestInteraction.toReviewState() == ReviewState.NEED_REVIEW } + } + createActionsForAuthor(reviewFlowVm.reviewState, requestedReviewers, reviewActions, moreActionsGroup) + } ReviewRole.REVIEWER -> createActionsForReviewer(reviewFlowVm, reviewActions, moreActionsGroup) ReviewRole.GUEST -> CodeReviewDetailsActionsComponentFactory.createActionsForGuest(reviewActions, moreActionsGroup, ::createMergeActionGroup) diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/model/GitLabMergeRequestBranchesViewModel.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/model/GitLabMergeRequestBranchesViewModel.kt index 7de9a5fbaf73..acdb10c2c87f 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/model/GitLabMergeRequestBranchesViewModel.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/model/GitLabMergeRequestBranchesViewModel.kt @@ -1,6 +1,7 @@ // 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.plugins.gitlab.mergerequest.ui.details.model +import com.intellij.collaboration.async.combineState import com.intellij.collaboration.async.launchNow import com.intellij.collaboration.async.modelFlow import com.intellij.collaboration.messages.CollaborationToolsBundle @@ -12,7 +13,6 @@ import com.intellij.openapi.diagnostic.thisLogger import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.Task import com.intellij.openapi.project.Project -import com.intellij.openapi.util.NlsSafe import com.intellij.openapi.vcs.VcsNotifier import com.intellij.util.childScope import git4idea.GitUtil @@ -24,7 +24,10 @@ import git4idea.repo.GitRepository import git4idea.repo.GitRepositoryChangeListener import git4idea.ui.branch.GitBranchPopupActions import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.callbackFlow import org.jetbrains.plugins.gitlab.api.dto.GitLabProjectDTO import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequest import org.jetbrains.plugins.gitlab.util.GitLabBundle @@ -40,17 +43,14 @@ internal class GitLabMergeRequestBranchesViewModel( private val cs: CoroutineScope = parentCs.childScope() - private val targetProject: StateFlow = mergeRequest.targetProject - private val sourceProject: StateFlow = mergeRequest.sourceProject - - override val sourceBranch: StateFlow = - combine(targetProject, sourceProject, mergeRequest.sourceBranch) { targetProject, sourceProject, sourceBranch -> - if (sourceProject == null) return@combine "" - if (targetProject == sourceProject) return@combine sourceBranch - val sourceUrl = sourceProject.webUrl - val sourceProjectOwner = sourceUrl.split("/").dropLast(1).last() - return@combine "$sourceProjectOwner:$sourceBranch" - }.stateIn(cs, SharingStarted.Lazily, mergeRequest.sourceBranch.value) + override val sourceBranch: StateFlow = with(mergeRequest) { + combineState(cs, targetProject, sourceProject, sourceBranch) { targetProject, sourceProject, sourceBranch -> + if (sourceProject == null) return@combineState "" + if (targetProject == sourceProject) return@combineState sourceBranch + val sourceProjectOwner = sourceProject.ownerPath + return@combineState "$sourceProjectOwner:$sourceBranch" + } + } override val isCheckedOut: SharedFlow = callbackFlow { val cs = this @@ -77,13 +77,12 @@ internal class GitLabMergeRequestBranchesViewModel( true ) { override fun run(indicator: ProgressIndicator) { - val sourceBranch = sourceBranch.value - val httpForkUrl = sourceProject.value?.httpUrlToRepo ?: return - val pullRequestAuthor = mergeRequest.author + val sourceProject = mergeRequest.sourceProject.value ?: return + val sourceBranch = mergeRequest.sourceBranch.value - val headRemote = git.findOrCreateRemote(repository, pullRequestAuthor.username, httpForkUrl) + val headRemote = git.findOrCreateRemote(repository, sourceProject) if (headRemote == null) { - notifyRemoteError(vcsNotifier, httpForkUrl) + notifyRemoteError(vcsNotifier, sourceProject) return } @@ -98,10 +97,15 @@ internal class GitLabMergeRequestBranchesViewModel( }.queue() } - private fun notifyRemoteError(vcsNotifier: VcsNotifier, httpForkUrl: @NlsSafe String?) { + private fun notifyRemoteError(vcsNotifier: VcsNotifier, project: GitLabProjectDTO) { var failedMessage = GitLabBundle.message("merge.request.branch.checkout.resolve.remote.failed") - if (httpForkUrl != null) { - failedMessage += "\n$httpForkUrl" + val httpUrl = project.httpUrlToRepo + val sshUrl = project.sshUrlToRepo + if (httpUrl != null) { + failedMessage += "\n$httpUrl" + } + if (sshUrl != null) { + failedMessage += "\n$sshUrl" } vcsNotifier.notifyError( MERGE_REQUEST_CANNOT_SET_TRACKING_BRANCH, @@ -110,39 +114,6 @@ internal class GitLabMergeRequestBranchesViewModel( ) } - private fun isBranchCheckedOut(repository: GitRepository, sourceBranch: String): Boolean { - val currentBranchName = repository.currentBranchName - return currentBranchName == sourceBranch - } - - private fun findRemote(repository: GitRepository, httpUrl: String?): GitRemote? = - repository.remotes.find { - it.firstUrl != null && (it.firstUrl == httpUrl || - it.firstUrl == httpUrl + GitUtil.DOT_GIT) - } - - // TODO: implement logic use sshUrlToRepo - private fun Git.findOrCreateRemote(repository: GitRepository, remoteName: String, httpUrl: String?): GitRemote? { - val existingRemote = findRemote(repository, httpUrl) - if (existingRemote != null) return existingRemote - - if (httpUrl != null && repository.remotes.any { it.name == remoteName }) { - return createRemote(repository, "pull_$remoteName", httpUrl) - } - - return when { - httpUrl != null -> createRemote(repository, remoteName, httpUrl) - else -> null - } - } - - private fun Git.createRemote(repository: GitRepository, remoteName: String, url: String): GitRemote? = - with(repository) { - addRemote(this, remoteName, url) - update() - remotes.find { it.name == remoteName } - } - override fun showBranches() { cs.launchNow { val source = sourceBranch.value @@ -154,4 +125,68 @@ internal class GitLabMergeRequestBranchesViewModel( companion object { private const val MERGE_REQUEST_CANNOT_SET_TRACKING_BRANCH = "gitlab.merge.request.cannot.set.tracking.branch" } +} + +private fun isBranchCheckedOut(repository: GitRepository, sourceBranch: String): Boolean { + val currentBranchName = repository.currentBranchName + return currentBranchName == sourceBranch +} + +private fun Git.findOrCreateRemote(repository: GitRepository, project: GitLabProjectDTO): GitRemote? { + val existingRemote = findRemote(repository, project) + if (existingRemote != null) return existingRemote + + val httpUrl = project.httpUrlToRepo + val sshUrl = project.sshUrlToRepo + val preferHttp = shouldAddHttpRemote(repository) + return if (preferHttp && httpUrl != null) { + createRemote(repository, project.ownerPath, httpUrl) + } + else if (sshUrl != null) { + createRemote(repository, project.ownerPath, sshUrl) + } + else { + null + } +} + +private fun findRemote(repository: GitRepository, project: GitLabProjectDTO): GitRemote? = + repository.remotes.find { + val url = it.firstUrl + url != null && (url.removeSuffix("/").removeSuffix(GitUtil.DOT_GIT).endsWith(project.fullPath)) + } + +private fun shouldAddHttpRemote(repository: GitRepository): Boolean { + val preferredRemoteUrl = repository.remotes.find { it.name == "origin" }?.firstUrl + ?: repository.remotes.firstNotNullOfOrNull { it.firstUrl } + if (preferredRemoteUrl != null) { + return preferredRemoteUrl.startsWith("http") + } + return true +} + +private fun Git.createRemote(repository: GitRepository, remoteName: String, url: String): GitRemote? { + val actualName = findNameForRemote(repository, remoteName) ?: return null + return with(repository) { + addRemote(this, actualName, url) + update() + remotes.find { it.name == actualName } + } +} + +/** + * Returns the [preferredName] if it is not taken or adds a numerical index to it + */ +private fun findNameForRemote(repository: GitRepository, preferredName: String): String? { + val exitingNames = repository.remotes.mapTo(mutableSetOf(), GitRemote::getName) + if (!exitingNames.contains(preferredName)) { + return preferredName + } + else { + return sequenceOf(1..Int.MAX_VALUE).map { + "${preferredName}_$it" + }.find { + exitingNames.contains(it) + } + } } \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/model/GitLabMergeRequestReviewFlowViewModel.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/model/GitLabMergeRequestReviewFlowViewModel.kt index bf9edadf5076..0aa59e12ffc6 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/model/GitLabMergeRequestReviewFlowViewModel.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/details/model/GitLabMergeRequestReviewFlowViewModel.kt @@ -16,7 +16,7 @@ import com.intellij.openapi.util.text.StringUtil import com.intellij.util.childScope import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import org.jetbrains.plugins.gitlab.api.data.GitLabAccessLevel +import org.jetbrains.plugins.gitlab.api.dto.GitLabReviewerDTO import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequest import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabProject @@ -27,21 +27,21 @@ import org.jetbrains.plugins.gitlab.mergerequest.ui.getSubmittableReview import org.jetbrains.plugins.gitlab.util.GitLabBundle import org.jetbrains.plugins.gitlab.util.SingleCoroutineLauncher -internal interface GitLabMergeRequestReviewFlowViewModel : CodeReviewFlowViewModel { - val isBusy: StateFlow +internal interface GitLabMergeRequestReviewFlowViewModel : CodeReviewFlowViewModel { + val isBusy: Flow val currentUser: GitLabUserDTO val author: GitLabUserDTO - val approvedBy: Flow> - val reviewers: StateFlow> - val role: Flow val reviewRequestState: Flow + val reviewers: StateFlow> + val reviewState: Flow + val role: Flow + val isMergeable: Flow val isApproved: StateFlow - val shouldBeRebased: Flow - val reviewState: Flow + val shouldBeRebased: Flow val userCanApprove: Flow val userCanManage: Flow @@ -77,6 +77,8 @@ internal interface GitLabMergeRequestReviewFlowViewModel : CodeReviewFlowViewMod fun removeReviewer(reviewer: GitLabUserDTO) + fun reviewerRereview() + //TODO: extract reviewers update VM suspend fun getPotentialReviewers(): List } @@ -93,39 +95,36 @@ internal class GitLabMergeRequestReviewFlowViewModelImpl( private val scope = parentScope.childScope() private val taskLauncher = SingleCoroutineLauncher(scope) - override val isBusy: StateFlow = taskLauncher.busy.stateIn(scope, SharingStarted.Lazily, false) + override val isBusy: Flow = taskLauncher.busy override val author: GitLabUserDTO = mergeRequest.author - override val approvedBy: Flow> = mergeRequest.approvedBy - override val reviewers: StateFlow> = mergeRequest.reviewers.stateIn(scope, SharingStarted.Lazily, emptyList()) + + override val isApproved: StateFlow = mergeRequest.isApproved.stateIn(scope, SharingStarted.Lazily, false) + + override val reviewRequestState: Flow = mergeRequest.reviewRequestState + override val reviewers: StateFlow> = mergeRequest.reviewers.stateIn(scope, SharingStarted.Lazily, emptyList()) + override val reviewerReviews: Flow> = reviewers.map { reviewers -> + reviewers.associateWith { it.mergeRequestInteraction.toReviewState() } + } + override val reviewState: Flow = combine(reviewerReviews, isApproved) { reviewerReviews, isApproved -> + val reviewStates = reviewerReviews.values + when { + isApproved -> ReviewState.ACCEPTED + reviewStates.any { it == ReviewState.WAIT_FOR_UPDATES } -> ReviewState.WAIT_FOR_UPDATES + else -> ReviewState.NEED_REVIEW + } + } override val role: Flow = reviewers.map { reviewers -> when { - author == currentUser -> ReviewRole.AUTHOR - currentUser in reviewers -> ReviewRole.REVIEWER + author.username == currentUser.username -> ReviewRole.AUTHOR + reviewers.any { it.username == currentUser.username } -> ReviewRole.REVIEWER else -> ReviewRole.GUEST } } - override val reviewRequestState: Flow = mergeRequest.reviewRequestState override val isMergeable: Flow = mergeRequest.isMergeable - override val isApproved: StateFlow = approvedBy - .map { it.isNotEmpty() } - .stateIn(scope, SharingStarted.Lazily, false) override val shouldBeRebased: Flow = mergeRequest.shouldBeRebased - override val reviewState: Flow = isApproved.map { isApproved -> - // TODO: add ReviewState.WAIT_FOR_UPDATES state - if (isApproved) ReviewState.ACCEPTED else ReviewState.NEED_REVIEW - } - - override val reviewerReviews: Flow> = combine(reviewers, approvedBy) { reviewers, approvedBy -> - mutableMapOf().apply { - reviewers.forEach { reviewer -> put(reviewer, ReviewState.NEED_REVIEW) } - approvedBy.forEach { reviewer -> put(reviewer, ReviewState.ACCEPTED) } - // TODO: implement ReviewState.WAIT_FOR_UPDATES - } - } - override val userCanApprove: Flow = mergeRequest.userPermissions.map { it.canApprove } override val userCanManage: Flow = mergeRequest.userPermissions.map { it.canMerge } override val userCanMerge: Flow = mergeRequest.userPermissions.map { it.canMerge } @@ -232,6 +231,11 @@ internal class GitLabMergeRequestReviewFlowViewModelImpl( mergeRequest.setReviewers(newReviewers) // TODO: implement via CollectionDelta } + override fun reviewerRereview() = runAction { + val requestedReviewers = reviewerReviews.first().filterValues { it == ReviewState.WAIT_FOR_UPDATES }.keys + mergeRequest.reviewerRereview(requestedReviewers) + } + private fun runAction(action: suspend () -> Unit) { taskLauncher.launch { try { @@ -245,4 +249,15 @@ internal class GitLabMergeRequestReviewFlowViewModelImpl( } override suspend fun getPotentialReviewers(): List = projectData.getMembers() + + companion object { + fun GitLabReviewerDTO.MergeRequestInteraction?.toReviewState(): ReviewState { + if (this == null) return ReviewState.NEED_REVIEW + return when { + approved -> ReviewState.ACCEPTED + reviewed -> ReviewState.WAIT_FOR_UPDATES + else -> ReviewState.NEED_REVIEW + } + } + } } \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/filters/GitLabMergeRequestsFiltersViewModel.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/filters/GitLabMergeRequestsFiltersViewModel.kt index bb3ecf850292..f90613f9f682 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/filters/GitLabMergeRequestsFiltersViewModel.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/filters/GitLabMergeRequestsFiltersViewModel.kt @@ -5,6 +5,7 @@ import com.intellij.collaboration.async.launchNow import com.intellij.collaboration.ui.codereview.list.search.ReviewListSearchPanelViewModel import com.intellij.collaboration.ui.codereview.list.search.ReviewListSearchPanelViewModelBase import com.intellij.collaboration.ui.icon.IconsProvider +import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.MutableStateFlow @@ -37,6 +38,7 @@ internal interface GitLabMergeRequestsFiltersViewModel : ReviewListSearchPanelVi @OptIn(FlowPreview::class) internal class GitLabMergeRequestsFiltersViewModelImpl( scope: CoroutineScope, + private val project: Project?, // only for statistics historyModel: GitLabMergeRequestsFiltersHistoryModel, override val currentUser: GitLabUserDTO, override val avatarIconsProvider: IconsProvider, @@ -85,7 +87,7 @@ internal class GitLabMergeRequestsFiltersViewModelImpl( // with debounce to avoid collecting intermediate state searchState.drop(1).debounce(5000).collect { if (it.filterCount > 0) { - GitLabStatistics.logMrFiltersApplied(it) + GitLabStatistics.logMrFiltersApplied(project, it) } } } diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/toolwindow/GitLabReviewListTabComponentDescriptor.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/toolwindow/GitLabReviewListTabComponentDescriptor.kt index 613a65d58239..3f1d98e230ef 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/toolwindow/GitLabReviewListTabComponentDescriptor.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/toolwindow/GitLabReviewListTabComponentDescriptor.kt @@ -38,6 +38,7 @@ internal class GitLabReviewListTabComponentDescriptor( private val accountVm = GitLabAccountViewModelImpl(project, cs, ctx.account, accountManager) private val filterVm: GitLabMergeRequestsFiltersViewModel = GitLabMergeRequestsFiltersViewModelImpl( cs, + project, currentUser = ctx.currentUser, historyModel = GitLabMergeRequestsFiltersHistoryModel(project.service()), avatarIconsProvider = avatarIconsProvider, diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/toolwindow/GitLabReviewTabComponentFactory.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/toolwindow/GitLabReviewTabComponentFactory.kt index 50dd2b9323ed..0b271bd17b19 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/toolwindow/GitLabReviewTabComponentFactory.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/toolwindow/GitLabReviewTabComponentFactory.kt @@ -49,7 +49,7 @@ internal class GitLabReviewTabComponentFactory( cs: CoroutineScope, projectContext: GitLabProjectUIContext ): ReviewListTabComponentDescriptor { - GitLabStatistics.logMrListOpened() + GitLabStatistics.logMrListOpened(project) return GitLabReviewListTabComponentDescriptor(project, cs, toolwindowViewModel.accountManager, projectContext) } @@ -58,14 +58,14 @@ internal class GitLabReviewTabComponentFactory( reviewTabType: GitLabReviewTab): JComponent { return when (reviewTabType) { is GitLabReviewTab.ReviewSelected -> { - GitLabStatistics.logMrDetailsOpened() + GitLabStatistics.logMrDetailsOpened(project) createReviewDetailsComponent(cs, projectContext, reviewTabType.reviewId) } } } override fun createEmptyTabContent(cs: CoroutineScope): JComponent { - GitLabStatistics.logMrTwLoginOpened() + GitLabStatistics.logMrTwLoginOpened(project) return createSelectorsComponent(cs) } diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/clone/GitLabCloneComponent.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/clone/GitLabCloneComponent.kt index 2d3e2c805a21..9d1a6cdcc156 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/clone/GitLabCloneComponent.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/clone/GitLabCloneComponent.kt @@ -56,14 +56,12 @@ internal class GitLabCloneComponent( init { cs.launch(start = CoroutineStart.UNDISPATCHED) { cloneVm.selectedItem.collect { selectedItem -> - val isRepositorySelected = selectedItem != null && selectedItem is GitLabCloneListItem.Repository - dialogStateListener.onOkActionEnabled(isRepositorySelected) - if (isRepositorySelected) { - val repository = selectedItem as GitLabCloneListItem.Repository - val selectedUrl = repository.projectMember.project.httpUrlToRepo - val path = ClonePathProvider.relativeDirectoryPathForVcsUrl(project, selectedUrl).removeSuffix(GitUtil.DOT_GIT) + val cloneUrl = (selectedItem as? GitLabCloneListItem.Repository)?.projectMember?.project?.httpUrlToRepo + if (cloneUrl != null) { + val path = ClonePathProvider.relativeDirectoryPathForVcsUrl(project, cloneUrl).removeSuffix(GitUtil.DOT_GIT) cloneDirectoryChildHandle.trySetChildPath(path) } + dialogStateListener.onOkActionEnabled(cloneUrl != null) } } diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/clone/GitLabCloneListItem.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/clone/GitLabCloneListItem.kt index f3f045af83b9..e8611e96152f 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/clone/GitLabCloneListItem.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/clone/GitLabCloneListItem.kt @@ -20,6 +20,4 @@ internal sealed interface GitLabCloneListItem { ) : GitLabCloneListItem } -internal fun GitLabCloneListItem.Repository.presentation(): @NlsSafe String { - return "${projectMember.createdBy.username}/${projectMember.project.name}" -} \ No newline at end of file +internal fun GitLabCloneListItem.Repository.presentation(): @NlsSafe String = projectMember.project.nameWithNamespace \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/util/gitLabStatistics.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/util/gitLabStatistics.kt index 001078e5e8a9..7350cfdfd155 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/util/gitLabStatistics.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/util/gitLabStatistics.kt @@ -9,6 +9,7 @@ import com.intellij.internal.statistic.eventLog.events.EventPair import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsagesCollector import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector import com.intellij.openapi.components.service +import com.intellij.openapi.project.Project import org.jetbrains.plugins.gitlab.api.GitLabGQLQuery import org.jetbrains.plugins.gitlab.authentication.accounts.GitLabAccountManager import org.jetbrains.plugins.gitlab.mergerequest.ui.filters.GitLabMergeRequestsFiltersValue @@ -34,14 +35,14 @@ internal object GitLabStatistics { //endregion //region Counters - private val COUNTERS_GROUP = EventLogGroup("vcs.gitlab.counters", version = 4) + private val COUNTERS_GROUP = EventLogGroup("vcs.gitlab.counters", version = 6) /** * Server returned 5** error */ private val SERVER_ERROR_EVENT = COUNTERS_GROUP.registerEvent("api.server.error.occurred", - EventFields.Enum("requestName", GitLabApiRequestName::class.java), - EventFields.Boolean("isDefaultServer"), + EventFields.Enum("request_name", GitLabApiRequestName::class.java), + EventFields.Boolean("is_default_server"), EventFields.Version) fun logServerError(request: GitLabApiRequestName, isDefaultServer: Boolean, serverVersion: String?): Unit = @@ -73,12 +74,12 @@ internal object GitLabStatistics { override fun getGroup(): EventLogGroup = COUNTERS_GROUP } - private val FILTER_SEARCH_PRESENT = EventFields.Boolean("hasSearch") - private val FILTER_STATE_PRESENT = EventFields.Boolean("hasState") - private val FILTER_AUTHOR_PRESENT = EventFields.Boolean("hasAuthor") - private val FILTER_ASSIGNEE_PRESENT = EventFields.Boolean("hasAssignee") - private val FILTER_REVIEWER_PRESENT = EventFields.Boolean("hasReviewer") - private val FILTER_LABEL_PRESENT = EventFields.Boolean("hasLabel") + private val FILTER_SEARCH_PRESENT = EventFields.Boolean("has_search") + private val FILTER_STATE_PRESENT = EventFields.Boolean("has_state") + private val FILTER_AUTHOR_PRESENT = EventFields.Boolean("has_author") + private val FILTER_ASSIGNEE_PRESENT = EventFields.Boolean("has_assignee") + private val FILTER_REVIEWER_PRESENT = EventFields.Boolean("has_reviewer") + private val FILTER_LABEL_PRESENT = EventFields.Boolean("has_label") /** * Merge requests list filters applied @@ -91,8 +92,9 @@ internal object GitLabStatistics { FILTER_REVIEWER_PRESENT, FILTER_LABEL_PRESENT) - fun logMrFiltersApplied(filters: GitLabMergeRequestsFiltersValue): Unit = + fun logMrFiltersApplied(project: Project?, filters: GitLabMergeRequestsFiltersValue): Unit = FILTERS_APPLIED_EVENT.log( + project, EventPair(FILTER_SEARCH_PRESENT, filters.searchQuery != null), EventPair(FILTER_STATE_PRESENT, filters.state != null), EventPair(FILTER_AUTHOR_PRESENT, filters.author != null), @@ -107,33 +109,33 @@ internal object GitLabStatistics { */ private val MR_TW_LOGIN_OPENED_EVENT = COUNTERS_GROUP.registerEvent("mergerequests.toolwindow.login.opened") - fun logMrTwLoginOpened(): Unit = MR_TW_LOGIN_OPENED_EVENT.log() + fun logMrTwLoginOpened(project: Project): Unit = MR_TW_LOGIN_OPENED_EVENT.log(project) /** * Merge requests toolwindow was opened */ private val MR_LIST_OPENED_EVENT = COUNTERS_GROUP.registerEvent("mergerequests.list.opened") - fun logMrListOpened(): Unit = MR_LIST_OPENED_EVENT.log() + fun logMrListOpened(project: Project): Unit = MR_LIST_OPENED_EVENT.log(project) /** * Merge request details were opened */ private val MR_DETAILS_OPENED_EVENT = COUNTERS_GROUP.registerEvent("mergerequests.details.opened") - fun logMrDetailsOpened(): Unit = MR_DETAILS_OPENED_EVENT.log() + fun logMrDetailsOpened(project: Project): Unit = MR_DETAILS_OPENED_EVENT.log(project) /** * Merge request diff was opened */ - private val MR_DIFF_OPENED_EVENT = COUNTERS_GROUP.registerEvent("mergerequests.diff.opened", EventFields.Boolean("isCumulative")) + private val MR_DIFF_OPENED_EVENT = COUNTERS_GROUP.registerEvent("mergerequests.diff.opened", EventFields.Boolean("is_cumulative")) - fun logMrDiffOpened(isCumulative: Boolean): Unit = MR_DIFF_OPENED_EVENT.log(isCumulative) + fun logMrDiffOpened(project: Project, isCumulative: Boolean): Unit = MR_DIFF_OPENED_EVENT.log(project, isCumulative) /** * Merge request action was executed */ - private val MR_ACTION_FIELD = EventFields.Enum("action", MergeRequestAction::class.java) + private val MR_ACTION_FIELD = EventFields.Enum("action") enum class MergeRequestAction { MERGE, @@ -144,6 +146,7 @@ internal object GitLabStatistics { CLOSE, REOPEN, SET_REVIEWERS, + REVIEWER_REREVIEW, ADD_NOTE, ADD_DIFF_NOTE, ADD_DISCUSSION_NOTE, @@ -159,7 +162,7 @@ internal object GitLabStatistics { */ private val MR_ACTION_EVENT = COUNTERS_GROUP.registerEvent("mergerequests.action.performed", MR_ACTION_FIELD) - fun logMrActionExecuted(action: MergeRequestAction): Unit = MR_ACTION_EVENT.log(action) + fun logMrActionExecuted(project: Project, action: MergeRequestAction): Unit = MR_ACTION_EVENT.log(project, action) //endregion } @@ -194,7 +197,8 @@ enum class GitLabApiRequestName { GQL_MERGE_REQUEST_ACCEPT, GQL_MERGE_REQUEST_SET_DRAFT, GQL_MERGE_REQUEST_SET_REVIEWERS, - GQL_MERGE_REQUEST_UPDATE; + GQL_MERGE_REQUEST_UPDATE, + GQL_MERGE_REQUEST_REVIEWER_REREVIEW; companion object { fun of(gqlQuery: GitLabGQLQuery): GitLabApiRequestName = when (gqlQuery) { @@ -212,6 +216,7 @@ enum class GitLabApiRequestName { GitLabGQLQuery.MERGE_REQUEST_SET_DRAFT -> GQL_MERGE_REQUEST_SET_DRAFT GitLabGQLQuery.MERGE_REQUEST_SET_REVIEWERS -> GQL_MERGE_REQUEST_SET_REVIEWERS GitLabGQLQuery.MERGE_REQUEST_UPDATE -> GQL_MERGE_REQUEST_UPDATE + GitLabGQLQuery.MERGE_REQUEST_REVIEWER_REREVIEW -> GQL_MERGE_REQUEST_REVIEWER_REREVIEW } } } diff --git a/plugins/gitlab/test/org/jetbrains/plugins/gitlab/mergerequest/ui/filters/GitLabMergeRequestsFiltersViewModelImplTest.kt b/plugins/gitlab/test/org/jetbrains/plugins/gitlab/mergerequest/ui/filters/GitLabMergeRequestsFiltersViewModelImplTest.kt index ba21d7cda45a..b53885ee4c83 100644 --- a/plugins/gitlab/test/org/jetbrains/plugins/gitlab/mergerequest/ui/filters/GitLabMergeRequestsFiltersViewModelImplTest.kt +++ b/plugins/gitlab/test/org/jetbrains/plugins/gitlab/mergerequest/ui/filters/GitLabMergeRequestsFiltersViewModelImplTest.kt @@ -35,7 +35,8 @@ internal class GitLabMergeRequestsFiltersViewModelImplTest { @Test fun `check initial default filter search state`() = runTest(UnconfinedTestDispatcher()) { val cs = childScope() - val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, historyModel = emptyHistoryModel, currentUser = mockedUser, + val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, project = null, + historyModel = emptyHistoryModel, currentUser = mockedUser, avatarIconsProvider = mock(), projectData = mock()) val loaderSupplierMock = mockLoaderSupplier() @@ -79,7 +80,8 @@ internal class GitLabMergeRequestsFiltersViewModelImplTest { @Test fun `check changed filter search state`() = runTest(UnconfinedTestDispatcher()) { val cs = childScope() - val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, historyModel = emptyHistoryModel, currentUser = mockedUser, + val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, project = null, + historyModel = emptyHistoryModel, currentUser = mockedUser, avatarIconsProvider = mock(), projectData = mock()) val loaderSupplierMock = mockLoaderSupplier() @@ -109,7 +111,8 @@ internal class GitLabMergeRequestsFiltersViewModelImplTest { @Test fun `check participant filters`() = runTest(UnconfinedTestDispatcher()) { val cs = childScope() - val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, historyModel = emptyHistoryModel, currentUser = mockedUser, + val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, project = null, + historyModel = emptyHistoryModel, currentUser = mockedUser, avatarIconsProvider = mock(), projectData = mock()) val loaderSupplierMock = mockLoaderSupplier() @@ -145,7 +148,8 @@ internal class GitLabMergeRequestsFiltersViewModelImplTest { @Test fun `check default filter`() = runTest(UnconfinedTestDispatcher()) { val cs = childScope() - val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, historyModel = emptyHistoryModel, currentUser = mockedUser, + val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, project = null, + historyModel = emptyHistoryModel, currentUser = mockedUser, avatarIconsProvider = mock(), projectData = mock()) assertEquals(filterVm.searchState.value, defaultFilter) @@ -155,7 +159,8 @@ internal class GitLabMergeRequestsFiltersViewModelImplTest { @Test fun `select empty state filter`() = runTest(UnconfinedTestDispatcher()) { val cs = childScope() - val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, historyModel = emptyHistoryModel, currentUser = mockedUser, + val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, project = null, + historyModel = emptyHistoryModel, currentUser = mockedUser, avatarIconsProvider = mock(), projectData = mock()) assertEquals(filterVm.searchState.value, defaultFilter) @@ -186,7 +191,8 @@ internal class GitLabMergeRequestsFiltersViewModelImplTest { private fun checkSelectedFilter(selectedFilter: GitLabMergeRequestsFiltersValue) = runTest(UnconfinedTestDispatcher()) { val cs = childScope() - val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, historyModel = emptyHistoryModel, currentUser = mockedUser, + val filterVm = GitLabMergeRequestsFiltersViewModelImpl(scope = cs, project = null, + historyModel = emptyHistoryModel, currentUser = mockedUser, avatarIconsProvider = mock(), projectData = mock()) assertEquals(filterVm.searchState.value, defaultFilter) diff --git a/plugins/gradle/java/src/execution/test/runner/events/GradleTestEventConverter.kt b/plugins/gradle/java/src/execution/test/runner/events/GradleTestEventConverter.kt index 8a8f0a92fba5..62bcf82f3647 100644 --- a/plugins/gradle/java/src/execution/test/runner/events/GradleTestEventConverter.kt +++ b/plugins/gradle/java/src/execution/test/runner/events/GradleTestEventConverter.kt @@ -2,7 +2,9 @@ package org.jetbrains.plugins.gradle.execution.test.runner.events import com.intellij.execution.testframework.sm.runner.SMTestProxy +import com.intellij.ide.plugins.PluginManagerCore import com.intellij.openapi.application.runReadAction +import com.intellij.openapi.extensions.PluginId import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project import com.intellij.openapi.util.text.StringUtil @@ -59,13 +61,9 @@ internal class GradleTestEventConverter( } private val isEnabledGroovyPlugin: Boolean by lazy { - try { - Class.forName("org.jetbrains.plugins.groovy.ext.spock.SpecificationKt") - true - } - catch (ex: Throwable) { - false - } + val groovyPluginId = PluginId.findId("org.intellij.groovy") + val groovyPlugin = PluginManagerCore.getPluginSet() + groovyPluginId != null && groovyPlugin.isPluginEnabled(groovyPluginId) } private val isSpockTestMethod: Boolean by lazy { diff --git a/plugins/gradle/java/src/service/project/wizard/GradleNewProjectWizardStep.kt b/plugins/gradle/java/src/service/project/wizard/GradleNewProjectWizardStep.kt index 11e2f0440357..21eb20bd01ba 100644 --- a/plugins/gradle/java/src/service/project/wizard/GradleNewProjectWizardStep.kt +++ b/plugins/gradle/java/src/service/project/wizard/GradleNewProjectWizardStep.kt @@ -250,7 +250,7 @@ abstract class GradleNewProjectWizardStep(parent: ParentStep) : withDialog = withDialog, message = GradleBundle.message( "gradle.settings.wizard.java.unsupported.message", - ApplicationNamesInfo.getInstance().productName, + ApplicationNamesInfo.getInstance().fullProductName, oldestSupportedJavaVersion.toFeatureString() ), dialogTitle = GradleBundle.message( @@ -258,7 +258,7 @@ abstract class GradleNewProjectWizardStep(parent: ParentStep) : ), dialogMessage = GradleBundle.message( "gradle.settings.wizard.java.unsupported.message", - ApplicationNamesInfo.getInstance().productName, + ApplicationNamesInfo.getInstance().fullProductName, oldestSupportedJavaVersion.toFeatureString(), ) ) @@ -273,7 +273,7 @@ abstract class GradleNewProjectWizardStep(parent: ParentStep) : withDialog = withDialog, message = GradleBundle.message( "gradle.settings.wizard.gradle.unsupported.message", - ApplicationNamesInfo.getInstance().productName, + ApplicationNamesInfo.getInstance().fullProductName, oldestSupportedGradleVersion.version ), dialogTitle = GradleBundle.message( @@ -281,7 +281,7 @@ abstract class GradleNewProjectWizardStep(parent: ParentStep) : ), dialogMessage = GradleBundle.message( "gradle.settings.wizard.gradle.unsupported.message", - ApplicationNamesInfo.getInstance().productName, + ApplicationNamesInfo.getInstance().fullProductName, oldestSupportedGradleVersion.version, ) ) diff --git a/plugins/gradle/resources/icons/expui/gradleNavigate.svg b/plugins/gradle/resources/icons/expui/gradleNavigate.svg index dc01ce6d5b83..16687cc32a58 100644 --- a/plugins/gradle/resources/icons/expui/gradleNavigate.svg +++ b/plugins/gradle/resources/icons/expui/gradleNavigate.svg @@ -1,6 +1,6 @@ - - - + + + diff --git a/plugins/gradle/resources/icons/expui/gradleNavigate_dark.svg b/plugins/gradle/resources/icons/expui/gradleNavigate_dark.svg index 300e42e1444f..2f9b28aea6d3 100644 --- a/plugins/gradle/resources/icons/expui/gradleNavigate_dark.svg +++ b/plugins/gradle/resources/icons/expui/gradleNavigate_dark.svg @@ -1,6 +1,6 @@ - - - + + + diff --git a/plugins/gradle/resources/messages/GradleBundle.properties b/plugins/gradle/resources/messages/GradleBundle.properties index aad7bf657e7c..28ee88481404 100644 --- a/plugins/gradle/resources/messages/GradleBundle.properties +++ b/plugins/gradle/resources/messages/GradleBundle.properties @@ -239,17 +239,16 @@ gradle.project.settings.kotlin.dsl.unsupported.message=\ Do you want to proceed with Kotlin DSL and Gradle {1}? gradle.settings.wizard.gradle.unsupported.title=Unsupported Gradle Version gradle.settings.wizard.gradle.unsupported.message=\ - {0} stopped supporting Gradle versions older than {1}. -gradle.settings.wizard.java.undefined=Undefined Java version + {0} doesn''t support Gradle versions older than {1}. gradle.settings.wizard.java.unsupported.title=Unsupported Java Version gradle.settings.wizard.java.unsupported.message=\ - {0} stopped supporting Java versions older than {1} for Gradle projects. + {0} doesn''t support Java versions older than {1} in Gradle projects. +gradle.build.issue.gradle.jvm.unsupported.title=Unsupported Gradle JVM +gradle.build.issue.gradle.jvm.unsupported.description=\ + {0} doesn''t support Gradle execution on Gradle JVM versions older than {1} gradle.dependency.analyzer.loading=Load Gradle Dependencies notification.group.gradle=Gradle -gradle.build.issue.gradle.jvm.unsupported.title=Unsupported Gradle JVM -gradle.build.issue.gradle.jvm.unsupported.description=Idea doesn''t support Gradle execution on JDK older than Java {0} - gradle.build.quick.fix.title=Possible solution: gradle.build.quick.fix.gradle.jvm=Use Java {0} as Gradle JVM: Open Gradle settings \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/issue/UnsupportedGradleJvmIssueChecker.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/issue/UnsupportedGradleJvmIssueChecker.kt index cd5eaa0a70c5..52b82190a896 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/issue/UnsupportedGradleJvmIssueChecker.kt +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/issue/UnsupportedGradleJvmIssueChecker.kt @@ -2,6 +2,7 @@ package org.jetbrains.plugins.gradle.issue import com.intellij.build.issue.BuildIssue +import com.intellij.openapi.application.ApplicationNamesInfo import com.intellij.openapi.project.Project import com.intellij.openapi.util.NlsContexts import com.intellij.pom.Navigatable @@ -22,7 +23,11 @@ class UnsupportedGradleJvmIssueChecker : GradleIssueChecker { val description = DescriptionBuilder() val oldestSupportedJavaVersion = GradleJvmSupportMatrix.getOldestSupportedJavaVersionByIdea() description.addDescription( - GradleBundle.message("gradle.build.issue.gradle.jvm.unsupported.description", oldestSupportedJavaVersion.feature) + GradleBundle.message( + "gradle.build.issue.gradle.jvm.unsupported.description", + ApplicationNamesInfo.getInstance().fullProductName, + oldestSupportedJavaVersion.feature + ) ) val gradleSettingsFix = GradleSettingsQuickFix( issueData.projectPath, true, diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/execution/GradleInitScriptUtil.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/execution/GradleInitScriptUtil.kt index 678f2e87b035..f5030220d55c 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/execution/GradleInitScriptUtil.kt +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/execution/GradleInitScriptUtil.kt @@ -9,6 +9,7 @@ import org.jetbrains.plugins.gradle.tooling.internal.init.Init import org.jetbrains.plugins.gradle.util.GradleConstants import java.io.File import java.io.IOException +import java.nio.file.FileAlreadyExistsException import java.nio.file.Path import java.util.regex.Matcher import kotlin.io.path.* @@ -166,12 +167,15 @@ fun createInitScript(prefix: String, content: String): Path { suffix++ val candidateName = prefix + suffix + "." + GradleConstants.EXTENSION val candidate = tempDirectory.resolve(candidateName) - if (!candidate.exists()) { + try { candidate.createFile() candidate.writeBytes(contentBytes) + @Suppress("SSBasedInspection") candidate.toFile().deleteOnExit() return candidate } + catch (_: FileAlreadyExistsException) { + } if (isContentEquals(candidate, contentBytes)) { return candidate } diff --git a/plugins/gradle/tooling-extension-impl/intellij.gradle.toolingExtension.tests.iml b/plugins/gradle/tooling-extension-impl/intellij.gradle.toolingExtension.tests.iml index a8f7b68307ae..dbd537e1d3db 100644 --- a/plugins/gradle/tooling-extension-impl/intellij.gradle.toolingExtension.tests.iml +++ b/plugins/gradle/tooling-extension-impl/intellij.gradle.toolingExtension.tests.iml @@ -32,7 +32,13 @@ - + + + + 91d2a2b6048c5cfe19f3982ee84eb5c19cab1d741a45ae1b4360c068331f89e6 + + + @@ -45,6 +51,14 @@ + + + e37f9fd2680da69e6e4e0fef6472b53240a935a18804e957ef60ef20f36281de + + + cdb3d038c188de6f46ffd5cd930be2d5e5dba59c53b26437995d534e3db2fb80 + + diff --git a/plugins/grazie/src/intellij.grazie.core.iml b/plugins/grazie/src/intellij.grazie.core.iml index 233fc3a3a5d9..8999ce829a28 100644 --- a/plugins/grazie/src/intellij.grazie.core.iml +++ b/plugins/grazie/src/intellij.grazie.core.iml @@ -18,7 +18,13 @@ - + + + + 770cd903fa7b604d1f7ef7ba17f84108667294b2b478be8ed1af3bffb4ae0018 + + + @@ -41,7 +47,13 @@ - + + + + 0214cac9c32594e6754023069dbc9715ef1cf1662e0142cada300d1e8ff3eded + + + @@ -55,7 +67,13 @@ - + + + + 59a7c525cd3c4227c1e61bcf15912c792835c1616ff26c7aa7f583c47cbdd95e + + + @@ -69,7 +87,13 @@ - + + + + 00ffa85bb3aaf252ecfab4f97f8b49a8894aced02229529ff5c2a7ad31f94070 + + + @@ -81,7 +105,13 @@ - + + + + 6170895b2315b697f4da5630caf57c6c441f1cb419d89d1cb5326b0673293e8a + + + @@ -93,7 +123,13 @@ - + + + + 8d2566a216f401380878f25196f84bd351b807b11f18bc71acd1417e04a1ec29 + + + @@ -105,7 +141,13 @@ - + + + + d58706a2be60c972452550cdba79870bf481447c50eb718308e33a6ba45c65ec + + + @@ -117,7 +159,13 @@ - + + + + f418c519b49470c2ec7024086bf210ba370ff158732368005d3b8cef964d3fff + + + @@ -129,7 +177,13 @@ - + + + + 1bfefce937df14cc94d32a98ce59c33f4d5b6c0eddbb436b6bfe27ff2120a23d + + + @@ -145,7 +199,13 @@ - + + + + 4add5fbcb7f548b79230ed7e01cb9fd4f9e2524bd1598dbcbfd8150563fe27f7 + + + @@ -157,7 +217,13 @@ - + + + + 7cbaa6f42e2c8412ef13cd0fb7f81936d64a1c3ea7c4f69cf75bb4e9410cb76b + + + @@ -169,7 +235,13 @@ - + + + + 35da65fdbd3f9c1fe79cfc8399db975fd97660d8a219febfda9fd1a5fc058f10 + + + @@ -185,7 +257,13 @@ - + + + + 564f0fc690d50702a313510b9a72e9505ace6e81108e84f65de4feb0da244eb8 + + + @@ -197,7 +275,13 @@ - + + + + 537fae02b7b09de5e47de8f21df20c81af3cd373f369f61e20e00d54827539fb + + + @@ -209,7 +293,13 @@ - + + + + 813f37e4820f1854e8a4eb4f80df94bf1b1f2ec6c3b72692f23ab9a556256af6 + + + @@ -229,7 +319,13 @@ - + + + + cbc2a1339391d3ea1e059b192e7424dfff8593bcc5a1b674359714a817f4b705 + + + @@ -241,7 +337,13 @@ - + + + + 311f4f1dc664878ce175cd85dee3165c87058c0dbff5a2c8dbb7de19e161b328 + + + @@ -253,7 +355,13 @@ - + + + + eb8884328f5968fda666efe49ba691bb8bf8903b5b14fcdc9cf97bc4f50569a4 + + + @@ -265,7 +373,13 @@ - + + + + 7ebff7d4811afc02afef17078cf02d3a64c54366b6b5240f25677517ebe04b66 + + + @@ -277,7 +391,13 @@ - + + + + a3165827008fb198af477ece61f1961c2be0a3a14290637cb783e832006e00db + + + @@ -289,7 +409,13 @@ - + + + + 66b9ca18e5b2b583905acee46eb1730af2ff58cfcfa5162a9d67348308c31806 + + + @@ -301,7 +427,13 @@ - + + + + 2cd794e233b637498bf453ded2763a95a5b38e881009e621340c529c8eebd76c + + + @@ -313,7 +445,13 @@ - + + + + 90b65e69c4a1f7375bd32a3a2a7598c142436aef45e97add1b7e86cc5eafba80 + + + @@ -325,7 +463,13 @@ - + + + + a14eb5ef82a23d6c7146a9e63bf503092bfe8e01ba6fa90ba4081a05a69565dc + + + @@ -337,7 +481,13 @@ - + + + + 069b982734bfe22e81d6f833415db3b6a2f3ef83efa080f0409a058052a2f532 + + + @@ -349,7 +499,13 @@ - + + + + 4aff241f00efbe7c17960a3a3efb1ba046586a562b53a25a68d2964fafff48d7 + + + diff --git a/plugins/grazie/src/test/intellij.grazie.tests.iml b/plugins/grazie/src/test/intellij.grazie.tests.iml index 86aa1622c369..7cdf869f3fbf 100644 --- a/plugins/grazie/src/test/intellij.grazie.tests.iml +++ b/plugins/grazie/src/test/intellij.grazie.tests.iml @@ -13,7 +13,13 @@ - + + + + 0214cac9c32594e6754023069dbc9715ef1cf1662e0142cada300d1e8ff3eded + + + @@ -25,7 +31,13 @@ - + + + + 79070a899b8d63acfde91f1f4f0772cc4f20a4c3f3d6d3dd5067821cb9215e70 + + + @@ -38,6 +50,20 @@ + + + 6ab71360ab27c94a0098cdd746e00a81605883c30c0d651b10fc17fe513f7215 + + + 56f0b00adb704cbc1e86776b45f6890efe90685ab370a34b5b299593cdcaae22 + + + 5904e500073c3ed1dadcf56c9bf2712f7b222762d3072421b1c2d83e04795f43 + + + 33021c9cca70c6292d53ff7dac5d1832d422e986aba52ec998532a5f47f921f8 + + @@ -59,7 +85,13 @@ - + + + + f2489582ada5e325870aa0904a8ba53701854b05e85d9896d7ae3d09d00a5a2b + + + diff --git a/plugins/groovy/spock-rt/intellij.groovy.spock.rt.iml b/plugins/groovy/spock-rt/intellij.groovy.spock.rt.iml index 813467754c3b..7821722e3f9b 100644 --- a/plugins/groovy/spock-rt/intellij.groovy.spock.rt.iml +++ b/plugins/groovy/spock-rt/intellij.groovy.spock.rt.iml @@ -12,6 +12,17 @@ + + + fa8ff7446df04c51b3ccbc2a1bbc71f9c280878afe2d53be44d59d00b1b9828c + + + 702868ed7e86b9b4672ede0f1e185e905baca9afab57746a7c650be3c7bca047 + + + 58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2 + + diff --git a/plugins/javaFX/sceneBuilder/intellij.javaFX.sceneBuilder.iml b/plugins/javaFX/sceneBuilder/intellij.javaFX.sceneBuilder.iml index 8fa2a304bcfa..0e6cd6cfb22c 100644 --- a/plugins/javaFX/sceneBuilder/intellij.javaFX.sceneBuilder.iml +++ b/plugins/javaFX/sceneBuilder/intellij.javaFX.sceneBuilder.iml @@ -14,7 +14,13 @@ - + + + + 36cd8f5bc933bcf726fadfc5276f0efcc7873d3a532e4e164674d2e8919f4781 + + + 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/KotlinModuleStateTrackerProvider.kt index 91a79248c877..61f5b83d818f 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/KotlinModuleStateTrackerProvider.kt @@ -3,7 +3,6 @@ package org.jetbrains.kotlin.idea.base.analysisApiProviders import com.intellij.java.workspace.entities.JavaSourceRootPropertiesEntity 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.projectRoots.ProjectJdkTable @@ -44,9 +43,8 @@ import org.jetbrains.kotlin.parsing.KotlinParserDefinition import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.atomic.AtomicLong -@Service(Service.Level.PROJECT) @OptIn(Frontend10ApiUsage::class) -class KotlinModuleStateTrackerProvider(val project: Project) : Disposable { +open class KotlinModuleStateTrackerProvider(val project: Project) : Disposable { init { val busConnection = project.messageBus.connect(this) busConnection.subscribe(WorkspaceModelTopics.CHANGED, ModelChangeListener()) @@ -55,11 +53,14 @@ class KotlinModuleStateTrackerProvider(val project: Project) : Disposable { 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 shouldInvalidateBuiltinSession(events: List): Boolean { return false } + fun getModuleStateTrackerFor(module: KtModule): KtModuleStateTracker { return when (module) { is KtScriptDependencyModule -> ModuleStateTrackerImpl() @@ -85,7 +86,7 @@ class KotlinModuleStateTrackerProvider(val project: Project) : Disposable { is KtLibrarySourceModule -> getModuleStateTrackerFor(module.binaryLibrary) - is KtBuiltinsModule -> ModuleStateTrackerImpl() + is KtBuiltinsModule -> builtinTracker is KtScriptModule -> { val virtualFile = module.file.virtualFile ?: error("Script ${module.file} does not have a backing 'VirtualFile'") @@ -115,6 +116,14 @@ class KotlinModuleStateTrackerProvider(val project: Project) : Disposable { 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() } + return + } events.mapNotNull { event -> val file = when (event) { //for all other events workspace model should do the job @@ -246,7 +255,7 @@ class KotlinModuleStateTrackerProvider(val project: Project) : Disposable { } -private class ModuleStateTrackerImpl : KtModuleStateTracker { +class ModuleStateTrackerImpl : KtModuleStateTracker { private val modificationCount = AtomicLong() @Volatile diff --git a/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/typeUtils.kt b/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/typeUtils.kt new file mode 100644 index 000000000000..c94123686f0b --- /dev/null +++ b/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/typeUtils.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.analysis.api.utils + +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.KtStarTypeProjection +import org.jetbrains.kotlin.analysis.api.components.buildClassType +import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability +import org.jetbrains.kotlin.analysis.api.types.KtTypeParameterType + +/** + * Checks whether [this] is possibly a subtype of [superType] by replacing all type arguments in [superType] with star projections and + * checking subtyping relation between [this] and obtained type. For example, `MutableList>` is possibly a subtype of + * `List>`, because MutableList>` is a subtype of `List<*>`. + * + * This check only approximates the possibility of the subtyping relation. + * An accurate estimation requires the use of the constraint system, which can lead to a loss in performance. + */ +context(KtAnalysisSession) +infix fun KtType.isPossiblySubTypeOf(superType: KtType): Boolean { + if (this is KtTypeParameterType) return this.hasCommonSubTypeWith(superType) + + if (superType is KtTypeParameterType) return superType.symbol.upperBounds.all { this isPossiblySubTypeOf it } + + val superTypeWithReplacedTypeArguments = superType.expandedClassSymbol?.let { symbol -> + buildClassTypeWithStarProjections(symbol, superType.nullability) + } + return superTypeWithReplacedTypeArguments != null && this isSubTypeOf superTypeWithReplacedTypeArguments +} + +private fun KtAnalysisSession.buildClassTypeWithStarProjections(symbol: KtClassOrObjectSymbol, nullability: KtTypeNullability): KtType = + buildClassType(symbol) { + repeat(symbol.typeParameters.size) { + argument(KtStarTypeProjection(token)) + } + }.withNullability(nullability) \ No newline at end of file diff --git a/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/base/codeInsight/KotlinPsiElementMemberChooserObject.kt b/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/base/codeInsight/KotlinPsiElementMemberChooserObject.kt index 1cca948ce965..6eb253ffa507 100644 --- a/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/base/codeInsight/KotlinPsiElementMemberChooserObject.kt +++ b/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/base/codeInsight/KotlinPsiElementMemberChooserObject.kt @@ -13,7 +13,7 @@ import com.intellij.util.concurrency.AppExecutorUtil import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KtDeclarationRendererForSource -import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererModifierFilter +import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererKeywordFilter import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol @@ -42,7 +42,7 @@ class KotlinPsiElementMemberChooserObject( companion object { private val renderer = KtDeclarationRendererForSource.WITH_SHORT_NAMES.with { modifiersRenderer = modifiersRenderer.with { - modifierFilter = KtRendererModifierFilter.NONE + keywordsRenderer = keywordsRenderer.with { keywordFilter = KtRendererKeywordFilter.NONE } } } 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 acdbc7be190a..8e5d7f8e1137 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 @@ -4,6 +4,8 @@ + 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 a57ef258ad02..f9c2b4012ee2 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 @@ -5,6 +5,9 @@ serviceInterface="org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory" serviceImplementation="org.jetbrains.kotlin.idea.base.fir.analysisApiProviders.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/FirIdeKotlinModuleStateTrackerProvider.kt new file mode 100644 index 000000000000..c8269ee0f08a --- /dev/null +++ b/plugins/kotlin/base/fir/analysis-api-providers/src/org/jetbrains/kotlin/idea/base/fir/analysisApiProviders/FirIdeKotlinModuleStateTrackerProvider.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.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 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 { + 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/resources/resources-en/messages/KotlinBundle.properties b/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties index b7c52a194ac4..6dc2b8af7e9f 100644 --- a/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties +++ b/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties @@ -951,6 +951,7 @@ text.remove=remove text.rename.as.part.of.phrase=rename text.rename.is.not.applicable.to.secondary.constructors=Rename is not applicable to secondary constructors text.rename.is.not.applicable.to.synthetic.declarations=Rename is not applicable to synthetic declaration +text.rename.is.not.applicable.to.compiler.plugin.generated.declarations=Rename is not applicable to compiler plugin-generated declaration text.rename.not.applicable.to.backing.field.reference=Rename is not applicable to backing field reference text.rename.not.applicable.to.dynamically.invoked.methods=Rename is not applicable to dynamically invoked members text.rename.overloads.title=Rename Overloads @@ -2176,6 +2177,7 @@ inspection.constant.condition.if.display.name=Condition of 'if' expression is co inspection.null.checks.to.safe.call.display.name=Null-checks can be replaced with safe-calls inspection.cascade.if.display.name=Cascade if can be replaced with when inspection.lift.return.or.assignment.display.name=Return or assignment can be lifted out +inspection.lift.return.or.assignment.option.only.single.statement=Report only if each branch is a single statement inspection.use.expression.body.display.name=Expression body syntax is preferable here inspection.simplifiable.call.chain.display.name=Call chain on collection type can be simplified inspection.useless.call.on.collection.display.name=Useless call on collection type diff --git a/plugins/kotlin/base/resources/src/org/jetbrains/kotlin/idea/KotlinIconProvider.kt b/plugins/kotlin/base/resources/src/org/jetbrains/kotlin/idea/KotlinIconProvider.kt index b0dbd091d136..1f9026f3c207 100644 --- a/plugins/kotlin/base/resources/src/org/jetbrains/kotlin/idea/KotlinIconProvider.kt +++ b/plugins/kotlin/base/resources/src/org/jetbrains/kotlin/idea/KotlinIconProvider.kt @@ -11,7 +11,6 @@ import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile -import com.intellij.psi.util.parentOfType import com.intellij.ui.IconManager import com.intellij.ui.RowIcon import com.intellij.util.PlatformIcons @@ -174,7 +173,7 @@ abstract class KotlinIconProvider : IconProvider(), DumbAware { (shortName?.asString() == JvmFileClassUtil.JVM_NAME_SHORT).ifTrue { val grandParent = parent.parent if (grandParent is KtPropertyAccessor) { - grandParent.parentOfType()?.getBaseIcon() + grandParent.property.getBaseIcon() } else { grandParent.getBaseIcon() } @@ -184,8 +183,10 @@ abstract class KotlinIconProvider : IconProvider(), DumbAware { val origin = (this as? KtLightClass)?.kotlinOrigin //TODO (light classes for decompiled files): correct presentation if (origin != null) origin.getBaseIcon() else CLASS - } - else -> unwrapped?.takeIf { it != this }?.getBaseIcon() + } ?: getBaseIconUnwrapped() + else -> getBaseIconUnwrapped() } + + private fun PsiElement.getBaseIconUnwrapped(): Icon? = unwrapped?.takeIf { it != this }?.getBaseIcon() } } diff --git a/plugins/kotlin/base/scripting/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsUpdater.kt b/plugins/kotlin/base/scripting/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsUpdater.kt index 3ca094e09de8..15952e52afea 100644 --- a/plugins/kotlin/base/scripting/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsUpdater.kt +++ b/plugins/kotlin/base/scripting/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsUpdater.kt @@ -43,6 +43,7 @@ import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicReference +import kotlin.system.measureTimeMillis /** * Holder for [ScriptClassRootsCache]. @@ -58,7 +59,7 @@ import java.util.concurrent.atomic.AtomicReference * Also analysis cache will be cleared and changed opened script files will be reanalyzed. */ -private const val INIT_TIMEOUT_REGISTRY_KEY = "kotlin.scripting.wait-init.timeout.sec" +private const val INIT_WAIT_ATTEMPTS_REGISTRY_KEY = "kotlin.scripting.wait-init.attempts.num" abstract class ScriptClassRootsUpdater( val project: Project, @@ -103,11 +104,21 @@ abstract class ScriptClassRootsUpdater( val classpathRoots: ScriptClassRootsCache get() { - val timeoutSec = Registry.intValue(INIT_TIMEOUT_REGISTRY_KEY, 5).toLong() - if (!cacheNotEmptyLatch.await(timeoutSec, TimeUnit.SECONDS)) { - scriptingWarnLog("Script configurations init timeout elapsed. " + - "Try increasing the value of registry key '${INIT_TIMEOUT_REGISTRY_KEY}'") + val timeoutMs = 500L + var attemptsLeft = Registry.intValue(INIT_WAIT_ATTEMPTS_REGISTRY_KEY, 10) + + val ms = measureTimeMillis { + while (!cacheNotEmptyLatch.await(timeoutMs, TimeUnit.MILLISECONDS) && attemptsLeft > 0) { + attemptsLeft-- + ProgressManager.checkCanceled() + } } + + if (attemptsLeft == 0) { + scriptingWarnLog("Couldn't load initial script cache state after $ms ms. In most cases we can cope with it. " + + "For others see registry key kotlin.scripting.wait-init.attempts.num.") + } + return cache.get() } diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/inspectionDescriptions/LiftReturnOrAssignment.html b/plugins/kotlin/code-insight/descriptions/resources-en/inspectionDescriptions/LiftReturnOrAssignment.html index af2529dbea6f..c08999360a6d 100644 --- a/plugins/kotlin/code-insight/descriptions/resources-en/inspectionDescriptions/LiftReturnOrAssignment.html +++ b/plugins/kotlin/code-insight/descriptions/resources-en/inspectionDescriptions/LiftReturnOrAssignment.html @@ -22,5 +22,6 @@ After the quick-fix is applied: } } +

If you would like this inspection to highlight more complex code with multi-statement branches, uncheck the option "Report only if each branch is a single statement".

\ No newline at end of file diff --git a/plugins/kotlin/code-insight/impl-base/src/org/jetbrains/kotlin/idea/codeinsights/impl/base/RedundantIfInspectionBase.kt b/plugins/kotlin/code-insight/impl-base/src/org/jetbrains/kotlin/idea/codeinsights/impl/base/RedundantIfInspectionBase.kt index 5a1933fa6a2c..ea053d802581 100644 --- a/plugins/kotlin/code-insight/impl-base/src/org/jetbrains/kotlin/idea/codeinsights/impl/base/RedundantIfInspectionBase.kt +++ b/plugins/kotlin/code-insight/impl-base/src/org/jetbrains/kotlin/idea/codeinsights/impl/base/RedundantIfInspectionBase.kt @@ -14,6 +14,7 @@ import com.intellij.psi.* import org.jetbrains.kotlin.idea.base.psi.getLineNumber import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractKotlinInspection +import org.jetbrains.kotlin.idea.codeinsight.utils.getBooleanTestOption import org.jetbrains.kotlin.idea.codeinsight.utils.negate import org.jetbrains.kotlin.idea.util.CommentSaver import org.jetbrains.kotlin.idea.util.application.isUnitTestMode @@ -53,12 +54,7 @@ abstract class RedundantIfInspectionBase : AbstractKotlinInspection(), CleanupLo val (redundancyType, branchType, returnAfterIf) = RedundancyType.of(expression) if (redundancyType == RedundancyType.NONE) return@ifExpressionVisitor - if (isUnitTestMode()) { - ignoreChainedIf = expression.containingKtFile - .findDescendantOfType { it.text.startsWith("// IGNORE_CHAINED_IF:") } - ?.let { it.text.removePrefix("// IGNORE_CHAINED_IF:").trim().toBoolean() } - ?: false - } + initOptionsInUnitTestMode(expression.containingKtFile) val isChainedIf = expression.getPrevSiblingIgnoringWhitespaceAndComments() is KtIfExpression || expression.parent.let { it is KtContainerNodeForControlStructureBody && it.expression == expression } @@ -80,6 +76,14 @@ abstract class RedundantIfInspectionBase : AbstractKotlinInspection(), CleanupLo } } + private fun initOptionsInUnitTestMode(testDataFile: KtFile) { + if (isUnitTestMode()) { + testDataFile.getBooleanTestOption("IGNORE_CHAINED_IF")?.let { + ignoreChainedIf = it + } + } + } + /** * Tells whether the given [expression] is of the boolean type. * diff --git a/plugins/kotlin/code-insight/inspections-k2/resources/kotlin.code-insight.inspections-k2.xml b/plugins/kotlin/code-insight/inspections-k2/resources/kotlin.code-insight.inspections-k2.xml index 5ff8b79d915f..814540a64e41 100644 --- a/plugins/kotlin/code-insight/inspections-k2/resources/kotlin.code-insight.inspections-k2.xml +++ b/plugins/kotlin/code-insight/inspections-k2/resources/kotlin.code-insight.inspections-k2.xml @@ -184,7 +184,7 @@ groupPath="Kotlin" groupBundle="messages.KotlinBundle" groupKey="group.names.style.issues" enabledByDefault="true" - level="WARNING" + level="WEAK WARNING" language="kotlin" key="inspection.lift.return.or.assignment.display.name" bundle="messages.KotlinBundle"/> diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/EqualsOrHashCodeInspection.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/EqualsOrHashCodeInspection.kt index 635121274035..375726ef96af 100644 --- a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/EqualsOrHashCodeInspection.kt +++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/EqualsOrHashCodeInspection.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.Modality @@ -286,7 +287,7 @@ class EqualsOrHashCodeInspection : AbstractKotlinInspection() { type.isArrayOrPrimitiveArray() -> { val canUseArrayContentFunctions = targetClass.canUseArrayContentFunctions() val shouldWrapInLet = isNullable && !canUseArrayContentFunctions - val hashCodeArg = if (shouldWrapInLet) "it" else ref + val hashCodeArg = if (shouldWrapInLet) StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier else ref val hashCodeCall = generateArrayHashCodeCall(type, canUseArrayContentFunctions, hashCodeArg) if (shouldWrapInLet) "$ref?.let { $hashCodeCall }" else hashCodeCall } diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/LiftReturnOrAssignmentInspection.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/LiftReturnOrAssignmentInspection.kt index 840793e76181..f807536d02b4 100644 --- a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/LiftReturnOrAssignmentInspection.kt +++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/LiftReturnOrAssignmentInspection.kt @@ -4,8 +4,10 @@ package org.jetbrains.kotlin.idea.k2.codeinsight.inspections import com.intellij.codeInspection.* import com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING import com.intellij.codeInspection.ProblemHighlightType.INFORMATION +import com.intellij.codeInspection.options.OptPane import com.intellij.codeInspection.util.InspectionMessage import com.intellij.openapi.project.Project +import com.intellij.psi.PsiComment import com.intellij.psi.PsiElement import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.analysis.api.KtAnalysisSession @@ -14,11 +16,14 @@ import org.jetbrains.kotlin.idea.base.psi.getLineCount import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractKotlinInspection import org.jetbrains.kotlin.idea.codeinsight.utils.findExistingEditor +import org.jetbrains.kotlin.idea.codeinsight.utils.getBooleanTestOption import org.jetbrains.kotlin.idea.k2.codeinsight.inspections.branchedTransformations.BranchedFoldingUtils +import org.jetbrains.kotlin.idea.k2.codeinsight.inspections.branchedTransformations.BranchedFoldingUtils.getFoldableAssignmentsFromBranches import org.jetbrains.kotlin.idea.k2.codeinsight.inspections.branchedTransformations.BranchedFoldingUtils.getFoldableReturnsFromBranches -import org.jetbrains.kotlin.idea.k2.codeinsight.inspections.branchedTransformations.BranchedFoldingUtils.getNumberOfFoldableAssignmentsOrNull +import org.jetbrains.kotlin.idea.util.application.isUnitTestMode import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType +import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.startOffset /** @@ -62,9 +67,23 @@ private const val LINES_LIMIT = 15 class LiftReturnOrAssignmentInspection @JvmOverloads constructor(private val skipLongExpressions: Boolean = true) : AbstractKotlinInspection() { + @JvmField + var reportOnlyIfSingleStatement = true + + override fun getOptionsPane(): OptPane { + return OptPane.pane( + OptPane.checkbox( + "reportOnlyIfSingleStatement", + KotlinBundle.message("inspection.lift.return.or.assignment.option.only.single.statement") + ) + ) + } + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = object : KtVisitorVoid() { override fun visitExpression(expression: KtExpression) { + initOptionsInUnitTestMode(expression.containingKtFile) + // Note that we'd better run the following line first instead of running // `if (analyze(expression) { expression.isUsedAsExpression() }) return` // because `getState(expression)` will filter many expressions after checking only PSI. @@ -115,6 +134,14 @@ class LiftReturnOrAssignmentInspection @JvmOverloads constructor(private val ski } + private fun initOptionsInUnitTestMode(testDataFile: KtFile) { + if (isUnitTestMode()) { + testDataFile.getBooleanTestOption("ONLY_SINGLE_STATEMENT")?.let { + reportOnlyIfSingleStatement = it + } + } + } + private class LiftReturnOutFix(private val keyword: String) : LocalQuickFix { override fun getName() = KotlinBundle.message("lift.return.out.fix.text.0", keyword) @@ -146,20 +173,24 @@ class LiftReturnOrAssignmentInspection @JvmOverloads constructor(private val ski if (foldableReturns.isNotEmpty()) { val returns = foldableReturns.returnExpressions val hasOtherReturns = expression.anyDescendantOfType { it !in returns } - val isSerious = !hasOtherReturns && returns.size > 1 - return returns.map { - LiftState(keyword, isSerious, LiftType.LIFT_RETURN_OUT, it, INFORMATION) - } + LiftState(keyword, isSerious, LiftType.LIFT_RETURN_OUT) + val allBranchesAreSingleStatement = returns.none { it.hasSiblings() } + val isSerious = !hasOtherReturns && returns.size > 1 && (allBranchesAreSingleStatement || !reportOnlyIfSingleStatement) + return returns.map { LiftState(keyword, isSerious, LiftType.LIFT_RETURN_OUT, it, INFORMATION) } + + LiftState(keyword, isSerious, LiftType.LIFT_RETURN_OUT) } - val assignmentNumber = getNumberOfFoldableAssignmentsOrNull(expression) ?: return null - if (assignmentNumber > 0) { - val isSerious = assignmentNumber > 1 + val assignments = getFoldableAssignmentsFromBranches(expression) + if (assignments.isNotEmpty()) { + val allBranchesAreSingleStatement = assignments.none { it.hasSiblings() } + val isSerious = assignments.size > 1 && (allBranchesAreSingleStatement || !reportOnlyIfSingleStatement) return listOf(LiftState(keyword, isSerious, LiftType.LIFT_ASSIGNMENT_OUT)) } return null } + private fun KtExpression.hasSiblings(): Boolean = + (parent as? KtBlockExpression)?.statements.orEmpty().size > 1 + private fun getState(expression: KtExpression) = analyze(expression) { when (expression) { is KtWhenExpression -> getStateForWhenOrTry(expression, expression.whenKeyword) diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/branchedTransformations/BranchedFoldingUtils.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/branchedTransformations/BranchedFoldingUtils.kt index 1753ab619251..3a1d66727b8b 100644 --- a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/branchedTransformations/BranchedFoldingUtils.kt +++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/branchedTransformations/BranchedFoldingUtils.kt @@ -96,18 +96,18 @@ object BranchedFoldingUtils { } /** - * Returns the number of assignments in recursive branches of if, when, or try expression (it checks nested branches as well). + * Returns a set of assignments in recursive branches of if, when, or try expression (it checks nested branches as well). * - * @param expression if, when, or try expression to analyze branches for the number of assignments. - * @return null if + * @param expression if, when, or try expression to analyze branches for assignments. + * @return empty set if * - [expression] is null, * - [expression] has some missing cases (cases that no branches handle), or * - The right expressions of assignments do not match each other * (for the concept of "match", see [collectAssignmentsAndCheck] function below). * Otherwise, the number of all assignments. */ - fun KtAnalysisSession.getNumberOfFoldableAssignmentsOrNull(expression: KtExpression?): Int? { - if (expression == null) return null + fun KtAnalysisSession.getFoldableAssignmentsFromBranches(expression: KtExpression?): Set { + if (expression == null) return emptySet() val assignments = mutableSetOf() /** @@ -156,13 +156,13 @@ object BranchedFoldingUtils { } // Check if all assignment have right expressions that match each other. - if (!collectAssignmentsAndCheck(expression)) return null - val firstAssignment = assignments.firstOrNull { it.right?.isNull() != true } ?: assignments.firstOrNull() ?: return 0 - val leftType = firstAssignment.left?.getKtType() ?: return 0 - val rightType = firstAssignment.right?.getKtType() ?: return 0 + if (!collectAssignmentsAndCheck(expression)) return emptySet() + val firstAssignment = assignments.firstOrNull { it.right?.isNull() != true } ?: assignments.firstOrNull() ?: return emptySet() + val leftType = firstAssignment.left?.getKtType() ?: return emptySet() + val rightType = firstAssignment.right?.getKtType() ?: return emptySet() val firstOperation = firstAssignment.operationReference.mainReference.resolve() if (assignments.any { assignment -> !checkAssignmentsMatch(firstAssignment, assignment, firstOperation, leftType, rightType) }) { - return null + return emptySet() } // If there is any child element of expression whose type is KtBinaryExpression for an assignment that does not have the right @@ -176,9 +176,9 @@ object BranchedFoldingUtils { binaryExpression !in assignments } })) { - return null + return emptySet() } - return assignments.size + return assignments } /** diff --git a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java index 92717e66df36..337f3a21a360 100644 --- a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java +++ b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java @@ -925,6 +925,21 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp runTest("../../../idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/lambda2.kt"); } + @TestMetadata("multiStatement.kt") + public void testMultiStatement() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement.kt"); + } + + @TestMetadata("multiStatement2.kt") + public void testMultiStatement2() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement2.kt"); + } + + @TestMetadata("multiStatement3.kt") + public void testMultiStatement3() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement3.kt"); + } + @TestMetadata("multipleAssignments.kt") public void testMultipleAssignments() throws Exception { runTest("../../../idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multipleAssignments.kt"); @@ -1214,6 +1229,21 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp runTest("../../../idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/innerIfTransformed.kt"); } + @TestMetadata("multiStatement.kt") + public void testMultiStatement() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement.kt"); + } + + @TestMetadata("multiStatement2.kt") + public void testMultiStatement2() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement2.kt"); + } + + @TestMetadata("multiStatement3.kt") + public void testMultiStatement3() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement3.kt"); + } + @TestMetadata("onReturn.kt") public void testOnReturn() throws Exception { runTest("../../../idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/onReturn.kt"); diff --git a/plugins/kotlin/code-insight/intentions-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/intentions/ConvertForEachToForLoopIntention.kt b/plugins/kotlin/code-insight/intentions-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/intentions/ConvertForEachToForLoopIntention.kt index e1a85887f908..62d25cf65236 100644 --- a/plugins/kotlin/code-insight/intentions-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/intentions/ConvertForEachToForLoopIntention.kt +++ b/plugins/kotlin/code-insight/intentions-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/intentions/ConvertForEachToForLoopIntention.kt @@ -7,6 +7,7 @@ import com.intellij.psi.PsiDocumentManager import com.intellij.psi.SmartPsiElementPointer import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.codeinsight.api.applicable.intentions.AbstractKotlinApplicableIntentionWithContext import org.jetbrains.kotlin.idea.codeinsight.api.applicators.KotlinApplicabilityRange @@ -212,7 +213,7 @@ internal class ConvertForEachToForLoopIntention } else { factory.createExpressionByPattern( "${loopLabel}for($0 in $1){ $2 }", - parameters.singleOrNull() ?: "it", + parameters.singleOrNull() ?: StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier, loopRange, body.allChildren ) diff --git a/plugins/kotlin/code-insight/intentions-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/intentions/SpecifyTypeExplicitlyIntention.kt b/plugins/kotlin/code-insight/intentions-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/intentions/SpecifyTypeExplicitlyIntention.kt index f064ae643a7f..93233cbdf80a 100644 --- a/plugins/kotlin/code-insight/intentions-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/intentions/SpecifyTypeExplicitlyIntention.kt +++ b/plugins/kotlin/code-insight/intentions-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/intentions/SpecifyTypeExplicitlyIntention.kt @@ -28,6 +28,7 @@ internal class SpecifyTypeExplicitlyIntention : override fun isApplicableByPsi(element: KtCallableDeclaration): Boolean { if (element is KtConstructor<*> || element is KtFunctionLiteral) return false + if (element is KtParameter && element.isLoopParameter && element.destructuringDeclaration != null) return false return element.typeReference == null && (element as? KtNamedFunction)?.hasBlockBody() != true } 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 db48fefdc7e2..60279ccde550 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 @@ -783,6 +783,11 @@ public abstract class K2IntentionTestGenerated extends AbstractK2IntentionTest { runTest("../../../idea/tests/testData/intentions/specifyTypeExplicitly/destructuringInLambda.kt"); } + @TestMetadata("destructuringInLoopParameter.kt") + public void testDestructuringInLoopParameter() throws Exception { + runTest("../../../idea/tests/testData/intentions/specifyTypeExplicitly/destructuringInLoopParameter.kt"); + } + @TestMetadata("enumType.kt") public void testEnumType() throws Exception { runTest("../../../idea/tests/testData/intentions/specifyTypeExplicitly/enumType.kt"); diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/structureView/KotlinFirStructureElementPresentation.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/structureView/KotlinFirStructureElementPresentation.kt index 644d23a17a33..3f99dbb9eca4 100644 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/structureView/KotlinFirStructureElementPresentation.kt +++ b/plugins/kotlin/code-insight/kotlin.code-insight.k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/structureView/KotlinFirStructureElementPresentation.kt @@ -12,11 +12,16 @@ import com.intellij.psi.PsiNamedElement import com.intellij.util.PsiIconUtil import com.intellij.util.ui.StartupUiUtil import org.jetbrains.kotlin.analysis.api.analyze +import org.jetbrains.kotlin.analysis.api.renderer.base.KtKeywordsRenderer import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KtRendererAnnotationsFilter +import org.jetbrains.kotlin.analysis.api.renderer.declarations.KtCallableReturnTypeFilter import org.jetbrains.kotlin.analysis.api.renderer.declarations.bodies.KtParameterDefaultValueRenderer import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KtDeclarationRendererForSource -import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererModifierFilter +import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererKeywordFilter import org.jetbrains.kotlin.analysis.api.renderer.declarations.renderers.KtTypeParametersRenderer +import org.jetbrains.kotlin.analysis.api.renderer.declarations.renderers.callables.KtConstructorSymbolRenderer +import org.jetbrains.kotlin.analysis.api.renderer.declarations.renderers.callables.KtFunctionSymbolRenderer +import org.jetbrains.kotlin.analysis.api.renderer.declarations.renderers.classifiers.KtNamedClassOrObjectSymbolRenderer import org.jetbrains.kotlin.analysis.api.renderer.declarations.superTypes.KtSuperTypesFilter import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol @@ -25,6 +30,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.idea.base.codeInsight.KotlinIconProvider.getIconFor import org.jetbrains.kotlin.idea.codeInsight.KotlinCodeInsightBundle +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import javax.swing.Icon @@ -43,12 +49,24 @@ internal class KotlinFirStructureElementPresentation( } modifiersRenderer = modifiersRenderer.with { - modifierFilter = KtRendererModifierFilter.NONE + keywordsRenderer = keywordsRenderer.with { keywordFilter = KtRendererKeywordFilter.NONE } } superTypesFilter = KtSuperTypesFilter.NONE parameterDefaultValueRenderer = KtParameterDefaultValueRenderer.THREE_DOTS typeParametersRenderer = KtTypeParametersRenderer.NO_TYPE_PARAMETERS + keywordsRenderer = KtKeywordsRenderer.AS_WORD.with { + keywordFilter = KtRendererKeywordFilter.onlyWith( + KtTokens.CONSTRUCTOR_KEYWORD, + KtTokens.OBJECT_KEYWORD, + KtTokens.COMPANION_KEYWORD + ) + } + returnTypeFilter = KtCallableReturnTypeFilter.ALWAYS + classOrObjectRenderer = KtNamedClassOrObjectSymbolRenderer.AS_SOURCE_WITHOUT_PRIMARY_CONSTRUCTOR + parameterDefaultValueRenderer = KtParameterDefaultValueRenderer.NO_DEFAULT_VALUE + constructorRenderer = KtConstructorSymbolRenderer.AS_RAW_SIGNATURE + functionSymbolRenderer = KtFunctionSymbolRenderer.AS_RAW_SIGNATURE } } diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/test/org/jetbrains/kotlin/idea/k2/structureView/AbstractKotlinFirFileStructureTest.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/test/org/jetbrains/kotlin/idea/k2/structureView/AbstractKotlinFirFileStructureTest.kt index be4bfc4cc063..0fbc40b89f32 100644 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/test/org/jetbrains/kotlin/idea/k2/structureView/AbstractKotlinFirFileStructureTest.kt +++ b/plugins/kotlin/code-insight/kotlin.code-insight.k2/test/org/jetbrains/kotlin/idea/k2/structureView/AbstractKotlinFirFileStructureTest.kt @@ -7,6 +7,7 @@ import org.jetbrains.kotlin.idea.fir.invalidateCaches import org.jetbrains.kotlin.idea.k2.codeinsight.structureView.KotlinFirInheritedMembersNodeProvider import org.jetbrains.kotlin.idea.structureView.AbstractKotlinFileStructureTest import org.jetbrains.kotlin.idea.test.runAll +import java.io.File abstract class AbstractKotlinFirFileStructureTest : AbstractKotlinFileStructureTest() { override fun isFirPlugin(): Boolean { @@ -23,4 +24,12 @@ abstract class AbstractKotlinFirFileStructureTest : AbstractKotlinFileStructureT ThrowableRunnable { super.tearDown() } ) } + + override fun getFileName(ext: String): String { + val firSpecificName = getTestName(false) + ".fir" + ( if (ext.isEmpty()) "" else ".$ext") + if (File(testDataDirectory, firSpecificName).exists()) { + return firSpecificName + } + return super.getFileName(ext) + } } \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/test/org/jetbrains/kotlin/idea/k2/structureView/KotlinFirFileStructureTestGenerated.java b/plugins/kotlin/code-insight/kotlin.code-insight.k2/test/org/jetbrains/kotlin/idea/k2/structureView/KotlinFirFileStructureTestGenerated.java index abd0c4936c72..58a953b08b89 100644 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/test/org/jetbrains/kotlin/idea/k2/structureView/KotlinFirFileStructureTestGenerated.java +++ b/plugins/kotlin/code-insight/kotlin.code-insight.k2/test/org/jetbrains/kotlin/idea/k2/structureView/KotlinFirFileStructureTestGenerated.java @@ -17,7 +17,7 @@ import org.junit.runner.RunWith; @TestRoot("code-insight/kotlin.code-insight.k2") @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -@TestMetadata("testData/structureView/fileStructure") +@TestMetadata("../../idea/tests/testData/structureView/fileStructure") public class KotlinFirFileStructureTestGenerated extends AbstractKotlinFirFileStructureTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); @@ -25,91 +25,96 @@ public class KotlinFirFileStructureTestGenerated extends AbstractKotlinFirFileSt @TestMetadata("AnonymousObjectMembers.kt") public void testAnonymousObjectMembers() throws Exception { - runTest("testData/structureView/fileStructure/AnonymousObjectMembers.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/AnonymousObjectMembers.kt"); } @TestMetadata("CheckLocationForKotlin.kt") public void testCheckLocationForKotlin() throws Exception { - runTest("testData/structureView/fileStructure/CheckLocationForKotlin.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/CheckLocationForKotlin.kt"); } @TestMetadata("CheckMemberLocationForJava.kt") public void testCheckMemberLocationForJava() throws Exception { - runTest("testData/structureView/fileStructure/CheckMemberLocationForJava.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/CheckMemberLocationForJava.kt"); } @TestMetadata("DoNotShowParentsInLocationJava.kt") public void testDoNotShowParentsInLocationJava() throws Exception { - runTest("testData/structureView/fileStructure/DoNotShowParentsInLocationJava.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/DoNotShowParentsInLocationJava.kt"); } @TestMetadata("EmptyFile.kt") public void testEmptyFile() throws Exception { - runTest("testData/structureView/fileStructure/EmptyFile.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/EmptyFile.kt"); } @TestMetadata("InheritedDelegationMethods.kt") public void testInheritedDelegationMethods() throws Exception { - runTest("testData/structureView/fileStructure/InheritedDelegationMethods.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/InheritedDelegationMethods.kt"); } @TestMetadata("InheritedInnerClasses.kt") public void testInheritedInnerClasses() throws Exception { - runTest("testData/structureView/fileStructure/InheritedInnerClasses.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/InheritedInnerClasses.kt"); } @TestMetadata("InheritedJavaMembers.kt") public void testInheritedJavaMembers() throws Exception { - runTest("testData/structureView/fileStructure/InheritedJavaMembers.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/InheritedJavaMembers.kt"); } @TestMetadata("InheritedLocalKotlin.kt") public void testInheritedLocalKotlin() throws Exception { - runTest("testData/structureView/fileStructure/InheritedLocalKotlin.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/InheritedLocalKotlin.kt"); } @TestMetadata("InheritedMembers.kt") public void testInheritedMembers() throws Exception { - runTest("testData/structureView/fileStructure/InheritedMembers.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/InheritedMembers.kt"); } @TestMetadata("InheritedMembersOfEnum.kt") public void testInheritedMembersOfEnum() throws Exception { - runTest("testData/structureView/fileStructure/InheritedMembersOfEnum.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/InheritedMembersOfEnum.kt"); } @TestMetadata("InheritedMembersWithSubstitutedTypes.kt") public void testInheritedMembersWithSubstitutedTypes() throws Exception { - runTest("testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.kt"); } @TestMetadata("InheritedSAMConversion.kt") public void testInheritedSAMConversion() throws Exception { - runTest("testData/structureView/fileStructure/InheritedSAMConversion.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/InheritedSAMConversion.kt"); } @TestMetadata("InheritedSynthesizedFromDataClass.kt") public void testInheritedSynthesizedFromDataClass() throws Exception { - runTest("testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.kt"); } @TestMetadata("LocalElements.kt") public void testLocalElements() throws Exception { - runTest("testData/structureView/fileStructure/LocalElements.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/LocalElements.kt"); } @TestMetadata("Render.kt") public void testRender() throws Exception { - runTest("testData/structureView/fileStructure/Render.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/Render.kt"); + } + + @TestMetadata("Script.kts") + public void testScript() throws Exception { + runTest("../../idea/tests/testData/structureView/fileStructure/Script.kts"); } @TestMetadata("SeveralClasses.kt") public void testSeveralClasses() throws Exception { - runTest("testData/structureView/fileStructure/SeveralClasses.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/SeveralClasses.kt"); } @TestMetadata("Simple.kt") public void testSimple() throws Exception { - runTest("testData/structureView/fileStructure/Simple.kt"); + runTest("../../idea/tests/testData/structureView/fileStructure/Simple.kt"); } } diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/AnonymousObjectMembers.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/AnonymousObjectMembers.after deleted file mode 100644 index 9a213410a292..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/AnonymousObjectMembers.after +++ /dev/null @@ -1,10 +0,0 @@ --AnonymousObjectMembers.kt - -class C - -fun bar() - -object : Runnable - fun run() - fun xyzzy() - -val f: Runnable - -object : Runnable - fun run() - fun xyzzy() \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/AnonymousObjectMembers.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/AnonymousObjectMembers.kt deleted file mode 100644 index bf7ac65a8761..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/AnonymousObjectMembers.kt +++ /dev/null @@ -1,15 +0,0 @@ -class C { - val f = object : Runnable { - fun run() { } - - fun xyzzy() { } - } - - fun bar() { - val g = object : Runnable { - fun run() { } - - fun xyzzy() { } - } - } -} \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckLocationForKotlin.Data.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckLocationForKotlin.Data.kt deleted file mode 100644 index 5863771b3a69..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckLocationForKotlin.Data.kt +++ /dev/null @@ -1,62 +0,0 @@ -interface First { - fun foo123() - fun foo12_() - fun foo1_3() - fun foo_23() - - val bar123: String - val bar12_: String - val bar1_3: String - val bar_23: String - - fun foo1__() - fun foo_2_() - fun foo__3() - - val bar1__: String - val bar_2_: String - val bar__3: String - - fun foo___() - val bar___: String -} - -abstract class A1 : First { - override fun foo123() {} - override fun foo12_() {} - override fun foo1_3() {} - - override val bar123 = "test" - override val bar12_ = "test" - override val bar1_3 = "test" - - override fun foo1__() {} - override val bar1__ = "test" -} - -abstract class A2 : A1() { - override fun foo123() {} - override fun foo12_() {} - override fun foo_23() {} - - override val bar123 = "test" - override val bar12_ = "test" - override val bar_23 = "test" - - override fun foo_2_() {} - override val bar_2_ = "test" -} - -open class A3 : A2() { - override fun foo123() {} - override fun foo1_3() {} - override fun foo_23() {} - - override val bar123 = "test" - override val bar1_3 = "test" - override val bar_23 = "test" - - override fun foo__3() {} - override val bar__3 = "test" -} - diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckLocationForKotlin.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckLocationForKotlin.after deleted file mode 100644 index de88c8bbba76..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckLocationForKotlin.after +++ /dev/null @@ -1,21 +0,0 @@ --CheckLocationForKotlin.kt - -class Third - fun equals(other: Any?): Boolean location=→Any - fun foo123() location=→A3 - fun foo12_() location=→A2 - fun foo1_3() location=→A3 - fun foo1__() location=→A1 - fun foo_23() location=→A3 - fun foo_2_() location=→A2 - fun foo__3() location=→A3 - fun foo___() location=→First - fun hashCode(): Int location=→Any - fun toString(): String location=→Any - val bar123: String location=→A3 - val bar12_: String location=→A2 - val bar1_3: String location=→A3 - val bar1__: String location=→A1 - val bar_23: String location=→A3 - val bar_2_: String location=→A2 - val bar__3: String location=→A3 - val bar___: String location=→First \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckLocationForKotlin.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckLocationForKotlin.kt deleted file mode 100644 index 6b01557d9457..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckLocationForKotlin.kt +++ /dev/null @@ -1,5 +0,0 @@ -class Third : A3() { - -} - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckMemberLocationForJava.Data.java b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckMemberLocationForJava.Data.java deleted file mode 100644 index 01324c5c0842..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckMemberLocationForJava.Data.java +++ /dev/null @@ -1,40 +0,0 @@ -public class JavaClass { - public interface First { - void foo123(); - void foo12_(); - void foo1_3(); - void foo_23(); - - void foo1__(); - void foo_2_(); - void foo__3(); - - void foo___(); - } - - public static abstract class A1 implements First { - @Override public void foo123() {} - @Override public void foo12_() {} - @Override public void foo1_3() {} - - @Override public void foo1__() {} - } - - public static abstract class A2 extends A1 { - @Override public void foo123() {} - @Override public void foo12_() {} - @Override public void foo_23() {} - - @Override public void foo_2_() {} - } - - public static class A3 extends A2 { - @Override public void foo123() {} - @Override public void foo1_3() {} - @Override public void foo_23() {} - - @Override public void foo__3() {} - - // @Override public void foo___() {} // Removed intentionally - } -} diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckMemberLocationForJava.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckMemberLocationForJava.after deleted file mode 100644 index e4835ccfe906..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckMemberLocationForJava.after +++ /dev/null @@ -1,13 +0,0 @@ --CheckMemberLocationForJava.kt - -class Some - fun equals(other: Any?): Boolean location=→Any - fun foo123() location=→A3 - fun foo12_() location=→A2 - fun foo1_3() location=→A3 - fun foo1__() location=→A1 - fun foo_23() location=→A3 - fun foo_2_() location=→A2 - fun foo__3() location=→A3 - fun foo___() location=→First - fun hashCode(): Int location=→Any - fun toString(): String location=→Any \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckMemberLocationForJava.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckMemberLocationForJava.kt deleted file mode 100644 index 6130e8fc25ac..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/CheckMemberLocationForJava.kt +++ /dev/null @@ -1,3 +0,0 @@ -class Some: JavaClass.A3() - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/DoNotShowParentsInLocationJava.Data.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/DoNotShowParentsInLocationJava.Data.kt deleted file mode 100644 index 48de19719efc..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/DoNotShowParentsInLocationJava.Data.kt +++ /dev/null @@ -1,5 +0,0 @@ -interface First - -interface Second : First { - fun foo() -} \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/DoNotShowParentsInLocationJava.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/DoNotShowParentsInLocationJava.after deleted file mode 100644 index 13323459860a..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/DoNotShowParentsInLocationJava.after +++ /dev/null @@ -1,6 +0,0 @@ --DoNotShowParentsInLocationJava.kt - -interface Third - fun equals(other: Any?): Boolean location=→Any - fun foo() location=→Second - fun hashCode(): Int location=→Any - fun toString(): String location=→Any \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/DoNotShowParentsInLocationJava.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/DoNotShowParentsInLocationJava.kt deleted file mode 100644 index 8ad176bf8ea3..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/DoNotShowParentsInLocationJava.kt +++ /dev/null @@ -1,3 +0,0 @@ -interface Third: Second - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/EmptyFile.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/EmptyFile.after deleted file mode 100644 index 370952a863e5..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/EmptyFile.after +++ /dev/null @@ -1 +0,0 @@ -EmptyFile.kt \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/EmptyFile.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/EmptyFile.kt deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedDelegationMethods.Data.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedDelegationMethods.Data.kt deleted file mode 100644 index e4726da3caee..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedDelegationMethods.Data.kt +++ /dev/null @@ -1,9 +0,0 @@ -interface Some { - fun first() - fun second() -} - -class ClassSome: Some { - override fun first() {} - override fun second() {} -} \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedDelegationMethods.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedDelegationMethods.after deleted file mode 100644 index 46de6e82572e..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedDelegationMethods.after +++ /dev/null @@ -1,7 +0,0 @@ --InheritedDelegationMethods.kt - -class Test - fun equals(other: Any?): Boolean location=→Any - fun first() location=→Some - fun hashCode(): Int location=→Any - fun second() location=→Some - fun toString(): String location=→Any \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedDelegationMethods.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedDelegationMethods.kt deleted file mode 100644 index a48ef3f43f97..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedDelegationMethods.kt +++ /dev/null @@ -1,3 +0,0 @@ -class Test: Some by ClassSome() - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedInnerClasses.Data.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedInnerClasses.Data.kt deleted file mode 100644 index 86c17c7db65a..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedInnerClasses.Data.kt +++ /dev/null @@ -1,6 +0,0 @@ -open class A { - class I1 - inner class I2 - - fun foo() {} -} \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedInnerClasses.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedInnerClasses.after deleted file mode 100644 index 5b411cec4d5a..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedInnerClasses.after +++ /dev/null @@ -1,6 +0,0 @@ --InheritedInnerClasses.kt - -class B - fun equals(other: Any?): Boolean location=→Any - fun foo() location=→A - fun hashCode(): Int location=→Any - fun toString(): String location=→Any \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedInnerClasses.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedInnerClasses.kt deleted file mode 100644 index 45a3b2d02d20..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedInnerClasses.kt +++ /dev/null @@ -1,5 +0,0 @@ -class B: A() - -// Inner classes are not shown, same to Java - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedJavaMembers.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedJavaMembers.after deleted file mode 100644 index 37115c31f57e..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedJavaMembers.after +++ /dev/null @@ -1,8 +0,0 @@ --InheritedJavaMembers.kt - -class InheritedJavaMembers - constructor() - fun call(): String? location=→Callable - fun equals(other: Any?): Boolean location=→Any - fun hashCode(): Int location=→Any - fun test() - fun toString(): String location=→Any \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedJavaMembers.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedJavaMembers.kt deleted file mode 100644 index e36c9969a437..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedJavaMembers.kt +++ /dev/null @@ -1,8 +0,0 @@ -import java.util.concurrent.Callable - -public abstract class InheritedJavaMembers() : Callable { - fun test() { - } -} - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedLocalKotlin.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedLocalKotlin.after deleted file mode 100644 index 32742480e3f0..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedLocalKotlin.after +++ /dev/null @@ -1,11 +0,0 @@ --InheritedLocalKotlin.kt - -class A - fun equals(other: Any?): Boolean location=→Any - fun hashCode(): Int location=→Any - fun some() - fun toString(): String location=→Any - val a: Int - -class B - fun some() location=→TA - val a: Int location=→TA - interface TA \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedLocalKotlin.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedLocalKotlin.kt deleted file mode 100644 index 401529a3a7e3..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedLocalKotlin.kt +++ /dev/null @@ -1,15 +0,0 @@ -interface TA { - fun some() - val a: Int -} - -class A : TA { - override fun some() { - } - - override val a: Int = 0 -} - -abstract class B : TA - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembers.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembers.after deleted file mode 100644 index aa55072ab2bc..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembers.after +++ /dev/null @@ -1,7 +0,0 @@ --InheritedMembers.kt - -class Test - fun equals(other: Any?): Boolean location=→Any - fun hashCode(): Int location=→Any - fun run() location=→Runnable - fun test() - fun toString(): String location=→Any \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembers.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembers.kt deleted file mode 100644 index ca41c13b56a3..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembers.kt +++ /dev/null @@ -1,7 +0,0 @@ -class Test: Runnable { - fun test() { - - } -} - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersOfEnum.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersOfEnum.after deleted file mode 100644 index 181edb4e398c..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersOfEnum.after +++ /dev/null @@ -1,13 +0,0 @@ --InheritedMembersOfEnum.kt - -enum class Test - FIRST - fun clone(): Any location=→Enum - fun compareTo(other: E): Int location=→Enum - fun equals(other: Any?): Boolean location=→Enum - fun finalize() location=→Enum - fun getDeclaringClass(): Class location=→Enum - fun hashCode(): Int location=→Enum - fun toString(): String location=→Enum - SECOND - val name: String location=→Enum - val ordinal: Int location=→Enum \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersOfEnum.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersOfEnum.kt deleted file mode 100644 index 2666c7f25716..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersOfEnum.kt +++ /dev/null @@ -1,6 +0,0 @@ -enum class Test { - FIRST, - SECOND -} - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.Data.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.Data.kt deleted file mode 100644 index 53e4e92b97f3..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.Data.kt +++ /dev/null @@ -1,7 +0,0 @@ -interface First { - fun foo(a: T) -} - -interface Second : First { - val a: U -} \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.after deleted file mode 100644 index 6de1524e7bd5..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.after +++ /dev/null @@ -1,7 +0,0 @@ --InheritedMembersWithSubstitutedTypes.kt - -interface Third - fun equals(other: Any?): Boolean location=→Any - fun foo(a: T) location=→First - fun hashCode(): Int location=→Any - fun toString(): String location=→Any - val a: U location=→Second \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.kt deleted file mode 100644 index 4f56362050ce..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.kt +++ /dev/null @@ -1,5 +0,0 @@ -interface Third: Second - -// Original type names are shown in members, behaviour is same to Java. - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSAMConversion.Data.java b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSAMConversion.Data.java deleted file mode 100644 index 7c44096e4a9a..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSAMConversion.Data.java +++ /dev/null @@ -1,9 +0,0 @@ -public class TestSAM { - public interface SamClass { - void foo(); - } - - void foo(SamClass samClass) { - - } -} diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSAMConversion.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSAMConversion.after deleted file mode 100644 index 96448f6c64cf..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSAMConversion.after +++ /dev/null @@ -1,6 +0,0 @@ --InheritedSAMConversion.kt - -class KotlinTest - fun equals(other: Any?): Boolean location=→Any - fun foo(samClass: TestSAM.SamClass?) location=→TestSAM - fun hashCode(): Int location=→Any - fun toString(): String location=→Any \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSAMConversion.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSAMConversion.kt deleted file mode 100644 index 8921da07298f..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSAMConversion.kt +++ /dev/null @@ -1,6 +0,0 @@ -class KotlinTest : TestSAM - -// TODO: Show both methods - synthetic and original (base mehtod without Kotlin signature) -// TODO: Show location for synthetic method - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.after deleted file mode 100644 index b131dea14486..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.after +++ /dev/null @@ -1,5 +0,0 @@ --InheritedSynthesizedFromDataClass.kt - -class TestData(a: Int) - a: Int - constructor(a: Int) - fun some() \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.kt deleted file mode 100644 index cc624f804acd..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.kt +++ /dev/null @@ -1,5 +0,0 @@ -data class TestData(val a: Int) { - fun some() {} -} - -// WITH_INHERITED \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/LocalElements.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/LocalElements.after deleted file mode 100644 index 20375f521993..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/LocalElements.after +++ /dev/null @@ -1,7 +0,0 @@ --LocalElements.kt - -fun foo() - -class X - - - fun quux() - fun xyzzy() - fun bar() \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/LocalElements.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/LocalElements.kt deleted file mode 100644 index 88cdac5467cb..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/LocalElements.kt +++ /dev/null @@ -1,13 +0,0 @@ -fun foo() { - fun bar() { } - - class X { - init { - fun quux() { - } - } - - fun xyzzy() { - } - } -} diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Render.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Render.after deleted file mode 100644 index 301b3e209871..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Render.after +++ /dev/null @@ -1,45 +0,0 @@ --Render.kt - class A1 - -class A2(a: Int, b: String = ...) - a: Int - b: String = ... - constructor(a: Int, b: String = ...) - -class A3(a: Int) - a: Int - constructor(a: Int) - var b: String - -class A4(t: T?) - constructor(t: T?) - t: T? - -class A5 - class Inner1 - class Inner2 - -class A6 - -companion object - fun test() - -class A7 - - val a: Int - class TestWithWhere - -class WithDefaultArgs(a: Int = ..., b: String = ...) - a: Int = ... - constructor(a: Int = ..., b: String = ...) - -enum class Enum1 - FIRST - SECOND - fun Comparable.extension2() - fun String.extension1() - fun test1() - fun test2(a: String?) - fun test3(t: T, u: U) - fun test4(t: T) - fun test5(): String - fun test6(): Comparable - fun testWithWhere() - fun withDefaulArgs(a: Int = ..., b: String = ...) - interface Trait - interface Trait1 - val a: Int - -val b: Any - object - val Comparable.a: String \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Render.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Render.kt deleted file mode 100644 index 26586d075fcb..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Render.kt +++ /dev/null @@ -1,54 +0,0 @@ -//package test.render - -fun test1() {} -fun test2(a: String?) {} -fun test3(t: T, u: U) {} -fun test4(t: T) {} -fun test5(): String = "some" -fun test6(): Comparable = "some" - -fun String.extension1() {} -fun Comparable.extension2() {} - -val a: Int = 1 -val Comparable.a = "String" -internal val b = object {} - -class A1 -class A2(val a: Int, var b: String = "some") -class A3(val a: Int) { - var b = "some" -} -class A4(val t: T?) -class A5 { - class Inner1 - inner class Inner2 -} -class A6 { - companion object { - fun test() {} - } -} -class A7 { - val a: Int - - init { - a = 1 - } -} - -enum class Enum1 { - FIRST, - SECOND -} - -interface Trait -interface Trait1: Trait - -class TestWithWhere where T: Any? -fun testWithWhere() where T: String {} - -class WithDefaultArgs(val a: Int = 1, b: String = "str") -fun withDefaulArgs(a: Int = 1, b: String = "str") {} - - diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/SeveralClasses.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/SeveralClasses.after deleted file mode 100644 index ab742c21552d..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/SeveralClasses.after +++ /dev/null @@ -1,5 +0,0 @@ --SeveralClasses.kt - class B - class Other - class Some - interface A \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/SeveralClasses.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/SeveralClasses.kt deleted file mode 100644 index 97e4808d2850..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/SeveralClasses.kt +++ /dev/null @@ -1,4 +0,0 @@ -interface A -open class B -class Some: B(), A -class Other: A \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Simple.after b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Simple.after deleted file mode 100644 index 794fc5583500..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Simple.after +++ /dev/null @@ -1,7 +0,0 @@ --Simple.kt - -class Test(str: String) - constructor(str: String) - fun foo(): Int - fun other() - str: String - val some: Int \ No newline at end of file diff --git a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Simple.kt b/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Simple.kt deleted file mode 100644 index 024b9c3d0d86..000000000000 --- a/plugins/kotlin/code-insight/kotlin.code-insight.k2/testData/structureView/fileStructure/Simple.kt +++ /dev/null @@ -1,5 +0,0 @@ -class Test(val str: String) { - private val some = 1 - protected fun foo() = some - public fun other() {} -} \ No newline at end of file diff --git a/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtClassMember.kt b/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtClassMember.kt index 4d697e9fe8e2..bfd1637207d2 100644 --- a/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtClassMember.kt +++ b/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtClassMember.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.analysis.api.annotations.annotations import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KtRendererAnnotationsFilter import org.jetbrains.kotlin.analysis.api.renderer.declarations.KtDeclarationRenderer import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KtDeclarationRendererForSource -import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererModifierFilter +import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererKeywordFilter import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererOtherModifiersProvider import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol @@ -119,7 +119,7 @@ fun KtAnalysisSession.generateMember( } modifiersRenderer = modifiersRenderer.with { - modifierFilter = KtRendererModifierFilter.without(KtTokens.OPERATOR_KEYWORD) + keywordsRenderer = keywordsRenderer.with { keywordFilter = KtRendererKeywordFilter.without(KtTokens.OPERATOR_KEYWORD) } modalityProvider = modalityProvider.onlyIf { s -> s != symbol } @@ -298,21 +298,22 @@ private object RenderOptions { annotationFilter = KtRendererAnnotationsFilter.NONE } modifiersRenderer = modifiersRenderer.with { - modifierFilter = KtRendererModifierFilter.onlyWith(KtTokens.OVERRIDE_KEYWORD) + keywordsRenderer = keywordsRenderer.with { keywordFilter = KtRendererKeywordFilter.onlyWith(KtTokens.OVERRIDE_KEYWORD) } } } val actualRenderOptions = overrideRenderOptions.with { modifiersRenderer = modifiersRenderer.with { - modifierFilter = modifierFilter or - KtRendererModifierFilter.onlyWith(KtTokens.INNER_KEYWORD) or - KtRendererModifierFilter.onlyWith(KtTokens.VISIBILITY_MODIFIERS) - KtRendererModifierFilter.onlyWith(KtTokens.MODALITY_MODIFIERS) + keywordsRenderer = keywordsRenderer.with { + keywordFilter = + keywordFilter or KtRendererKeywordFilter.onlyWith(KtTokens.INNER_KEYWORD) or KtRendererKeywordFilter.onlyWith(KtTokens.VISIBILITY_MODIFIERS) + KtRendererKeywordFilter.onlyWith(KtTokens.MODALITY_MODIFIERS) + } } } val expectRenderOptions = actualRenderOptions.with { modifiersRenderer = modifiersRenderer.with { - modifierFilter = modifierFilter or KtRendererModifierFilter.onlyWith(KtTokens.ACTUAL_KEYWORD) + keywordsRenderer = keywordsRenderer.with { keywordFilter = keywordFilter or KtRendererKeywordFilter.onlyWith(KtTokens.ACTUAL_KEYWORD) } } } } diff --git a/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtGenerateMembersHandler.kt b/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtGenerateMembersHandler.kt index d297db10b582..bdbe89571c82 100644 --- a/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtGenerateMembersHandler.kt +++ b/plugins/kotlin/code-insight/override-implement-k2/src/org/jetbrains/kotlin/idea/core/overrideImplement/KtGenerateMembersHandler.kt @@ -9,7 +9,6 @@ import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import com.intellij.psi.SmartPsiElementPointer import com.intellij.psi.codeStyle.CodeStyleManager -import com.intellij.psi.stubs.StubElement import org.jetbrains.annotations.ApiStatus import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt import org.jetbrains.kotlin.idea.core.insertMembersAfter @@ -19,7 +18,7 @@ import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KtRendererAnnotationsFilter import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KtDeclarationRendererForSource -import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererModifierFilter +import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererKeywordFilter import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.idea.base.analysis.api.utils.invokeShortening import org.jetbrains.kotlin.lexer.KtTokens @@ -342,7 +341,7 @@ abstract class KtGenerateMembersHandler( annotationFilter = KtRendererAnnotationsFilter.NONE } modifiersRenderer = modifiersRenderer.with { - modifierFilter = KtRendererModifierFilter.onlyWith(KtTokens.OVERRIDE_KEYWORD) + keywordsRenderer = keywordsRenderer.with { keywordFilter = KtRendererKeywordFilter.onlyWith(KtTokens.OVERRIDE_KEYWORD) } } } } diff --git a/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/AnalysisUtils.kt b/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/AnalysisUtils.kt index 319658c227ed..fd2208162cc3 100644 --- a/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/AnalysisUtils.kt +++ b/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/AnalysisUtils.kt @@ -5,8 +5,9 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.calls.singleFunctionCallOrNull import org.jetbrains.kotlin.analysis.api.calls.symbol -import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClass @@ -47,4 +48,11 @@ fun KtValueArgument.getValueArgumentName(): Name? { getArgumentNameIfCanBeUsedForCalls(this@getValueArgumentName, resolvedCall) } } +} +context(KtAnalysisSession) +fun KtSymbol.getFqNameIfPackageOrNonLocal(): FqName? = when (this) { + is KtPackageSymbol -> fqName + is KtCallableSymbol -> callableIdIfNonLocal?.asSingleFqName() + is KtClassLikeSymbol -> classIdIfNonLocal?.asSingleFqName() + else -> null } \ No newline at end of file diff --git a/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/TestUtils.kt b/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/TestUtils.kt new file mode 100644 index 000000000000..d4d7950d76a3 --- /dev/null +++ b/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/TestUtils.kt @@ -0,0 +1,10 @@ +// 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.utils + +import com.intellij.psi.PsiComment +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType + +fun KtFile.getBooleanTestOption(option: String): Boolean? = + findDescendantOfType { it.text.startsWith("// $option:") } + ?.let { it.text.removePrefix("// $option:").trim().toBoolean() } \ No newline at end of file diff --git a/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/implicitLambdaParameterUtils.kt b/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/implicitLambdaParameterUtils.kt new file mode 100644 index 000000000000..b5c4e3bde9d6 --- /dev/null +++ b/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/implicitLambdaParameterUtils.kt @@ -0,0 +1,43 @@ +// 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.utils + +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.lifetime.allowAnalysisOnEdt +import org.jetbrains.kotlin.analysis.api.symbols.KtAnonymousFunctionSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.psi.KtFunctionLiteral +import org.jetbrains.kotlin.psi.KtNameReferenceExpression + +fun KtNameReferenceExpression.isReferenceToImplicitLambdaParameter(): Boolean { + if (getReferencedNameAsName() != StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME) return false + @OptIn(KtAllowAnalysisOnEdt::class) + allowAnalysisOnEdt { + analyze(this) { + return getImplicitLambdaParameterSymbol() != null + } + } +} + +fun KtNameReferenceExpression.getFunctionLiteralByImplicitLambdaParameter(): KtFunctionLiteral? { + if (getReferencedNameAsName() != StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME) return null + @OptIn(KtAllowAnalysisOnEdt::class) + allowAnalysisOnEdt { + analyze(this) { + val implicitParameterSymbol = getImplicitLambdaParameterSymbol() ?: return null + val lambda = implicitParameterSymbol.getContainingSymbol() as? KtAnonymousFunctionSymbol ?: return null + return lambda.psi as? KtFunctionLiteral + } + } +} + + +context(KtAnalysisSession) +fun KtNameReferenceExpression.getImplicitLambdaParameterSymbol(): KtValueParameterSymbol? { + val parameterSymbol = mainReference.resolveToSymbol() as? KtValueParameterSymbol ?: return null + if (!parameterSymbol.isImplicitLambdaParameter) return null + return parameterSymbol +} diff --git a/plugins/kotlin/compiler-reference-index/tests.k2/test/org/jetbrains/kotlin/idea/fir/search/refIndex/FindUsagesWithCompilerReferenceIndexFirTestGenerated.java b/plugins/kotlin/compiler-reference-index/tests.k2/test/org/jetbrains/kotlin/idea/fir/search/refIndex/FindUsagesWithCompilerReferenceIndexFirTestGenerated.java index dfa474fba181..e95e14a0e4ca 100644 --- a/plugins/kotlin/compiler-reference-index/tests.k2/test/org/jetbrains/kotlin/idea/fir/search/refIndex/FindUsagesWithCompilerReferenceIndexFirTestGenerated.java +++ b/plugins/kotlin/compiler-reference-index/tests.k2/test/org/jetbrains/kotlin/idea/fir/search/refIndex/FindUsagesWithCompilerReferenceIndexFirTestGenerated.java @@ -3014,6 +3014,19 @@ public abstract class FindUsagesWithCompilerReferenceIndexFirTestGenerated exten @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/findUsages/kotlin/findTypeAliasUsages") public abstract static class FindTypeAliasUsages extends AbstractFindUsagesWithCompilerReferenceIndexFirTest { + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/findUsages/kotlin/findTypeAliasUsages") + public static class TestClassAlias extends AbstractFindUsagesWithCompilerReferenceIndexFirTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("classAlias.0.kt") + public void testClassAlias() throws Exception { + runTest("../../idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.0.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/findUsages/kotlin/findTypeAliasUsages") public static class TestObjectAlias extends AbstractFindUsagesWithCompilerReferenceIndexFirTest { @@ -3057,6 +3070,19 @@ public abstract class FindUsagesWithCompilerReferenceIndexFirTestGenerated exten } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/findUsages/kotlin/findTypeParameterUsages") + public static class TestKotlinReifiedTypeParameterUsages extends AbstractFindUsagesWithCompilerReferenceIndexFirTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("kotlinReifiedTypeParameterUsages.0.kt") + public void testKotlinReifiedTypeParameterUsages() throws Exception { + runTest("../../idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.0.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/findUsages/kotlin/findTypeParameterUsages") public static class TestPropertyWithTypeParameter extends AbstractFindUsagesWithCompilerReferenceIndexFirTest { diff --git a/plugins/kotlin/compiler-reference-index/tests/test/org/jetbrains/kotlin/idea/search/refIndex/FindUsagesWithCompilerReferenceIndexTestGenerated.java b/plugins/kotlin/compiler-reference-index/tests/test/org/jetbrains/kotlin/idea/search/refIndex/FindUsagesWithCompilerReferenceIndexTestGenerated.java index f971ccf23571..562bfbda1211 100644 --- a/plugins/kotlin/compiler-reference-index/tests/test/org/jetbrains/kotlin/idea/search/refIndex/FindUsagesWithCompilerReferenceIndexTestGenerated.java +++ b/plugins/kotlin/compiler-reference-index/tests/test/org/jetbrains/kotlin/idea/search/refIndex/FindUsagesWithCompilerReferenceIndexTestGenerated.java @@ -3014,6 +3014,19 @@ public abstract class FindUsagesWithCompilerReferenceIndexTestGenerated extends @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/findUsages/kotlin/findTypeAliasUsages") public abstract static class FindTypeAliasUsages extends AbstractFindUsagesWithCompilerReferenceIndexTest { + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/findUsages/kotlin/findTypeAliasUsages") + public static class TestClassAlias extends AbstractFindUsagesWithCompilerReferenceIndexTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("classAlias.0.kt") + public void testClassAlias() throws Exception { + runTest("../../idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.0.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/findUsages/kotlin/findTypeAliasUsages") public static class TestObjectAlias extends AbstractFindUsagesWithCompilerReferenceIndexTest { @@ -3057,6 +3070,19 @@ public abstract class FindUsagesWithCompilerReferenceIndexTestGenerated extends } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/findUsages/kotlin/findTypeParameterUsages") + public static class TestKotlinReifiedTypeParameterUsages extends AbstractFindUsagesWithCompilerReferenceIndexTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("kotlinReifiedTypeParameterUsages.0.kt") + public void testKotlinReifiedTypeParameterUsages() throws Exception { + runTest("../../idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.0.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../../idea/tests/testData/findUsages/kotlin/findTypeParameterUsages") public static class TestPropertyWithTypeParameter extends AbstractFindUsagesWithCompilerReferenceIndexTest { diff --git a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt index 6156ef220738..0284ee2e83f7 100644 --- a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt +++ b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.idea.base.facet.platform.platform import org.jetbrains.kotlin.idea.base.psi.kotlinFqName +import org.jetbrains.kotlin.idea.base.utils.fqname.isJavaClassNotToBeUsedInKotlin import org.jetbrains.kotlin.idea.caches.KotlinShortNamesCache import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper import org.jetbrains.kotlin.idea.resolve.ResolutionFacade diff --git a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt index fab6445efb12..d0ac989487f8 100644 --- a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt +++ b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt @@ -22,6 +22,8 @@ import org.jetbrains.kotlin.idea.base.projectStructure.languageVersionSettings import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.ModuleOrigin import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.OriginCapability import org.jetbrains.kotlin.idea.base.psi.isInsideAnnotationEntryArgumentList +import org.jetbrains.kotlin.idea.base.utils.fqname.ImportableFqNameClassifier +import org.jetbrains.kotlin.idea.base.utils.fqname.isJavaClassNotToBeUsedInKotlin import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.util.getResolveScope import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper diff --git a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt index 855f5f4f9990..3df91b7d7c15 100644 --- a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt +++ b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.KotlinIcons +import org.jetbrains.kotlin.idea.base.utils.fqname.ImportableFqNameClassifier import org.jetbrains.kotlin.idea.completion.handlers.CastReceiverInsertHandler import org.jetbrains.kotlin.idea.completion.smart.KeywordProbability import org.jetbrains.kotlin.idea.completion.smart.keywordProbability diff --git a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/ReferenceVariantsCollector.kt b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/ReferenceVariantsCollector.kt index 3a7cdb08feb3..2c986abb4555 100644 --- a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/ReferenceVariantsCollector.kt +++ b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/ReferenceVariantsCollector.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.idea.completion import com.intellij.codeInsight.completion.PrefixMatcher import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.idea.base.utils.fqname.ImportableFqNameClassifier import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper import org.jetbrains.kotlin.idea.core.util.externalDescriptors diff --git a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt index 511d319ab07d..e226c814e4f6 100644 --- a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt +++ b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt @@ -43,6 +43,9 @@ class KotlinProximityStatistician : ProximityStatistician() { } } +/** + * Implementation in K2: [org.jetbrains.kotlin.idea.codeInsight.K2StatisticsInfoProvider] + */ object KotlinStatisticsInfo { private val SIGNATURE_RENDERER = DescriptorRenderer.withOptions { withDefinedIn = false diff --git a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/Weighers.kt b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/Weighers.kt index b95469ea89f6..f51c0cfb28a7 100644 --- a/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/Weighers.kt +++ b/plugins/kotlin/completion/impl-k1/src/org/jetbrains/kotlin/idea/completion/Weighers.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.base.codeInsight.isEnumValuesSoftDeprecateEnabled import org.jetbrains.kotlin.idea.base.projectStructure.languageVersionSettings +import org.jetbrains.kotlin.idea.base.utils.fqname.ImportableFqNameClassifier import org.jetbrains.kotlin.idea.completion.implCommon.weighers.SoftDeprecationWeigher import org.jetbrains.kotlin.idea.completion.smart.* import org.jetbrains.kotlin.idea.core.ExpectedInfo 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 63515c9e24fb..afb82f1afde8 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 @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.analysis.api.types.KtFunctionalType import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.idea.base.analysis.api.utils.isPossiblySubTypeOf import org.jetbrains.kotlin.idea.base.fir.codeInsight.HLIndexHelper import org.jetbrains.kotlin.idea.base.projectStructure.languageVersionSettings import org.jetbrains.kotlin.idea.base.psi.isInsideAnnotationEntryArgumentList @@ -32,11 +33,9 @@ import org.jetbrains.kotlin.idea.completion.checkers.ExtensionApplicabilityCheck import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext import org.jetbrains.kotlin.idea.completion.context.FirNameReferencePositionContext import org.jetbrains.kotlin.idea.completion.contributors.helpers.* -import org.jetbrains.kotlin.idea.completion.contributors.helpers.ShadowedCallablesFilter import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionOptions import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy -import org.jetbrains.kotlin.idea.completion.lookups.isPossiblySubTypeOf import org.jetbrains.kotlin.idea.completion.weighers.WeighingContext import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.psi.* diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/keywords/OverrideKeywordHandler.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/keywords/OverrideKeywordHandler.kt index 0eaeefdedb72..a70b0cb0a2f4 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/keywords/OverrideKeywordHandler.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/keywords/OverrideKeywordHandler.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.idea.completion.contributors.keywords import com.intellij.codeInsight.completion.CompletionParameters import com.intellij.codeInsight.lookup.LookupElement import com.intellij.icons.AllIcons -import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.project.Project import com.intellij.ui.RowIcon import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt @@ -14,19 +13,22 @@ import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KtRendererAnnotationsFilter import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KtDeclarationRendererForSource -import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererModifierFilter -import org.jetbrains.kotlin.analysis.api.symbols.* +import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtVariableSymbol +import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererKeywordFilter import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithModality import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.idea.KtIconProvider.getBaseIcon -import org.jetbrains.kotlin.idea.base.analysis.api.utils.invokeShortening -import org.jetbrains.kotlin.idea.base.analysis.api.utils.shortenReferences import org.jetbrains.kotlin.idea.base.analysis.api.utils.shortenReferencesInRange -import org.jetbrains.kotlin.idea.completion.* +import org.jetbrains.kotlin.idea.completion.OverridesCompletionLookupElementDecorator import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext import org.jetbrains.kotlin.idea.completion.keywords.CompletionKeywordHandler -import org.jetbrains.kotlin.idea.core.overrideImplement.* +import org.jetbrains.kotlin.idea.core.overrideImplement.BodyType +import org.jetbrains.kotlin.idea.core.overrideImplement.KtClassMember +import org.jetbrains.kotlin.idea.core.overrideImplement.KtOverrideMembersHandler +import org.jetbrains.kotlin.idea.core.overrideImplement.MemberGenerateMode import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* @@ -52,7 +54,8 @@ internal class OverrideKeywordHandler( val result = mutableListOf() val position = parameters.position val isConstructorParameter = position.getNonStrictParentOfType() != null - val classOrObject = position.getNonStrictParentOfType() ?: return result + val parent = position.getNonStrictParentOfType() ?: return result + val classOrObject = parent.getOriginalDeclaration() as? KtClassOrObject ?: parent val members = collectMembers(classOrObject, isConstructorParameter) for (member in members) { @@ -180,7 +183,7 @@ internal class OverrideKeywordHandler( annotationFilter = KtRendererAnnotationsFilter.NONE } modifiersRenderer = modifiersRenderer.with { - modifierFilter = KtRendererModifierFilter.onlyWith(KtTokens.TYPE_MODIFIER_KEYWORDS) + keywordsRenderer = keywordsRenderer.with { keywordFilter = KtRendererKeywordFilter.onlyWith(KtTokens.TYPE_MODIFIER_KEYWORDS) } } } } diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/CompletionShortNamesRenderer.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/CompletionShortNamesRenderer.kt index fe1b7d771fc3..f130e775e116 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/CompletionShortNamesRenderer.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/CompletionShortNamesRenderer.kt @@ -30,7 +30,7 @@ internal object CompletionShortNamesRenderer { private fun KtAnalysisSession.renderFunctionParameter(parameter: KtVariableLikeSignature): String = "${if (parameter.symbol.isVararg) "vararg " else ""}${parameter.name.asString()}: ${ parameter.returnType.renderNonErrorOrUnsubstituted(parameter.symbol.returnType) - }" + }${if (parameter.symbol.hasDefaultValue) " = ..." else ""}" val renderer = KtTypeRendererForSource.WITH_SHORT_NAMES val rendererVerbose = renderer.with { diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/factories/FunctionLookupElementFactory.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/factories/FunctionLookupElementFactory.kt index 71ae7a5bb7bd..7d0158f25b18 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/factories/FunctionLookupElementFactory.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/factories/FunctionLookupElementFactory.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol import org.jetbrains.kotlin.analysis.api.types.* +import org.jetbrains.kotlin.idea.base.analysis.api.utils.isPossiblySubTypeOf import org.jetbrains.kotlin.idea.base.analysis.api.utils.shortenReferencesInRange import org.jetbrains.kotlin.idea.base.analysis.withRootPrefixIfNeeded import org.jetbrains.kotlin.idea.completion.KotlinCompletionCharFilter diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/utils.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/utils.kt index 864ca60f136f..2c173c104635 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/utils.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/lookups/utils.kt @@ -12,15 +12,9 @@ import com.intellij.refactoring.suggested.endOffset import com.intellij.refactoring.suggested.startOffset import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.KtAnalysisSession -import org.jetbrains.kotlin.analysis.api.KtStarTypeProjection -import org.jetbrains.kotlin.analysis.api.components.buildClassType import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.signatures.KtCallableSignature -import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtClassifierSymbol -import org.jetbrains.kotlin.analysis.api.types.KtType -import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability -import org.jetbrains.kotlin.analysis.api.types.KtTypeParameterType import org.jetbrains.kotlin.idea.base.analysis.api.utils.shortenReferencesInRange import org.jetbrains.kotlin.idea.base.codeInsight.KotlinIconProvider.getIconFor import org.jetbrains.kotlin.idea.completion.contributors.helpers.insertString @@ -97,31 +91,4 @@ private fun KtSuperExpression.setSuperTypeQualifier( private fun getSuperTypeQualifierRange(typeReference: KtTypeReference): TextRange = TextRange( (typeReference.prevLeaf { it.elementType == KtTokens.LT } ?: typeReference).startOffset, (typeReference.nextLeaf { it.elementType == KtTokens.GT } ?: typeReference).endOffset -) - -/** - * Checks whether [this] is possibly a subtype of [superType] by replacing all type arguments in [superType] with star projections and - * checking subtyping relation between [this] and obtained type. For example, `MutableList>` is possibly a subtype of - * `List>`, because MutableList>` is a subtype of `List<*>`. - * - * This check only approximates the possibility of the subtyping relation. - * An accurate estimation requires the use of the constraint system, which can lead to a loss in performance. - */ -context(KtAnalysisSession) -internal infix fun KtType.isPossiblySubTypeOf(superType: KtType): Boolean { - if (this is KtTypeParameterType) return this.hasCommonSubTypeWith(superType) - - if (superType is KtTypeParameterType) return superType.symbol.upperBounds.all { this isPossiblySubTypeOf it } - - val superTypeWithReplacedTypeArguments = superType.expandedClassSymbol?.let { symbol -> - buildClassTypeWithStarProjections(symbol, superType.nullability) - } - return superTypeWithReplacedTypeArguments != null && this isSubTypeOf superTypeWithReplacedTypeArguments -} - -private fun KtAnalysisSession.buildClassTypeWithStarProjections(symbol: KtClassOrObjectSymbol, nullability: KtTypeNullability): KtType = - buildClassType(symbol) { - repeat(symbol.typeParameters.size) { - argument(KtStarTypeProjection(token)) - } - }.withNullability(nullability) \ No newline at end of file +) \ No newline at end of file diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/ExpectedTypeWeigher.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/ExpectedTypeWeigher.kt index e837a3da97db..4875e1c47eda 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/ExpectedTypeWeigher.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/ExpectedTypeWeigher.kt @@ -12,9 +12,9 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability +import org.jetbrains.kotlin.idea.base.analysis.api.utils.isPossiblySubTypeOf import org.jetbrains.kotlin.idea.completion.KeywordLookupObject import org.jetbrains.kotlin.idea.completion.impl.k2.lookups.factories.NamedArgumentLookupObject -import org.jetbrains.kotlin.idea.completion.lookups.isPossiblySubTypeOf import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.UserDataProperty diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/NotImportedWeigher.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/NotImportedWeigher.kt index dd6b8f783454..a4692a734a2a 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/NotImportedWeigher.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/NotImportedWeigher.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPackageSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol -import org.jetbrains.kotlin.idea.completion.ImportableFqNameClassifier +import org.jetbrains.kotlin.idea.base.utils.fqname.ImportableFqNameClassifier import org.jetbrains.kotlin.psi.UserDataProperty internal object NotImportedWeigher { diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/Weighers.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/Weighers.kt index 42bcc9b36713..9b82a6f878ee 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/Weighers.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/weighers/Weighers.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.idea.base.facet.platform.platform import org.jetbrains.kotlin.idea.base.projectStructure.compositeAnalysis.findAnalyzerServices import org.jetbrains.kotlin.idea.base.projectStructure.languageVersionSettings -import org.jetbrains.kotlin.idea.completion.ImportableFqNameClassifier +import org.jetbrains.kotlin.idea.base.utils.fqname.ImportableFqNameClassifier import org.jetbrains.kotlin.idea.completion.contributors.helpers.CompletionSymbolOrigin import org.jetbrains.kotlin.idea.completion.contributors.helpers.KtSymbolWithOrigin import org.jetbrains.kotlin.idea.completion.impl.k2.weighers.K2SoftDeprecationWeigher diff --git a/plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/completionUtilsNoResolve.kt b/plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/completionUtilsNoResolve.kt index 5a4ca431937b..651bb6c93c06 100644 --- a/plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/completionUtilsNoResolve.kt +++ b/plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/completionUtilsNoResolve.kt @@ -10,11 +10,8 @@ import com.intellij.patterns.StandardPatterns import com.intellij.psi.PsiElement import com.intellij.ui.JBColor import org.jetbrains.annotations.ApiStatus -import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.load.java.javaToKotlinNameMap -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject @@ -170,9 +167,6 @@ fun referenceScope(declaration: KtNamedDeclaration): KtElement? = when (val pare else -> null } -fun FqName.isJavaClassNotToBeUsedInKotlin(): Boolean = - JavaToKotlinClassMap.isJavaPlatformClass(this) || javaToKotlinNameMap[this] != null - fun findValueArgument(expression: KtExpression): KtValueArgument? { // Search for value argument among parent and grandparent to avoid parsing errors like KTIJ-18231 return expression.parent as? KtValueArgument diff --git a/plugins/kotlin/completion/testData/basic/common/parameterNameAndType/FunctionCall.kt b/plugins/kotlin/completion/testData/basic/common/parameterNameAndType/FunctionCall.kt new file mode 100644 index 000000000000..c2df0b875cb6 --- /dev/null +++ b/plugins/kotlin/completion/testData/basic/common/parameterNameAndType/FunctionCall.kt @@ -0,0 +1,17 @@ +// FIR_COMPARISON +// FIR_IDENTICAL +package pack + +fun foobarOne(required: Int): Int = required + +fun foobarTwo(required: Int, optional: Int = 3): Int = required + optional + +fun test(foobarArg: Int) {} + +fun runTest() { + test(foobar) +} + +// EXIST: { lookupString: "foobarOne", itemText: "foobarOne", tailText:"(required: Int) (pack)", icon: "Function"} +// EXIST: { lookupString: "foobarTwo", itemText: "foobarTwo", tailText: "(required: Int, optional: Int = ...) (pack)", icon:"Function"} +// EXIST: { lookupString: "foobarArg =", itemText: "foobarArg =", tailText: " Int", icon: "Parameter"} \ 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 7c97c24e7ca7..3649e3ef390a 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 @@ -1623,6 +1623,11 @@ public abstract class JSBasicCompletionTestGenerated extends AbstractJSBasicComp runTest("../testData/basic/common/parameterNameAndType/ByAbbreviation.kt"); } + @TestMetadata("FunctionCall.kt") + public void testFunctionCall() throws Exception { + runTest("../testData/basic/common/parameterNameAndType/FunctionCall.kt"); + } + @TestMetadata("InSecondaryConstructor.kt") public void testInSecondaryConstructor() throws Exception { runTest("../testData/basic/common/parameterNameAndType/InSecondaryConstructor.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 c5cca6532862..43828278323c 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 @@ -1623,6 +1623,11 @@ public abstract class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCo runTest("../testData/basic/common/parameterNameAndType/ByAbbreviation.kt"); } + @TestMetadata("FunctionCall.kt") + public void testFunctionCall() throws Exception { + runTest("../testData/basic/common/parameterNameAndType/FunctionCall.kt"); + } + @TestMetadata("InSecondaryConstructor.kt") public void testInSecondaryConstructor() throws Exception { runTest("../testData/basic/common/parameterNameAndType/InSecondaryConstructor.kt"); diff --git a/plugins/kotlin/fir-low-level-api-ide-impl/kotlin.fir.fir-low-level-api-ide-impl.iml b/plugins/kotlin/fir-low-level-api-ide-impl/kotlin.fir.fir-low-level-api-ide-impl.iml index c6acf5c707a6..61f6336c2e9a 100644 --- a/plugins/kotlin/fir-low-level-api-ide-impl/kotlin.fir.fir-low-level-api-ide-impl.iml +++ b/plugins/kotlin/fir-low-level-api-ide-impl/kotlin.fir.fir-low-level-api-ide-impl.iml @@ -20,7 +20,13 @@ - + + + + 58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2 + + + diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/codeInsight/K2StatisticsInfoProvider.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/codeInsight/K2StatisticsInfoProvider.kt new file mode 100644 index 000000000000..ac843934e871 --- /dev/null +++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/codeInsight/K2StatisticsInfoProvider.kt @@ -0,0 +1,54 @@ +// 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 + +import com.intellij.psi.statistics.StatisticsInfo +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.renderer.base.KtKeywordsRenderer +import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KtRendererAnnotationsFilter +import org.jetbrains.kotlin.analysis.api.renderer.declarations.KtCallableReturnTypeFilter +import org.jetbrains.kotlin.analysis.api.renderer.declarations.KtDeclarationRenderer +import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KtDeclarationRendererForSource +import org.jetbrains.kotlin.analysis.api.renderer.declarations.renderers.callables.KtCallableSignatureRenderer +import org.jetbrains.kotlin.analysis.api.symbols.* +import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter +import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint +import org.jetbrains.kotlin.lexer.KtKeywordToken + +/** + * Implementation in K1: [org.jetbrains.kotlin.idea.completion.KotlinStatisticsInfo] + */ +object K2StatisticsInfoProvider { + /** + * The renderer skips some features of a declaration to provide concise (but still unambiguous) description of the declaration. + */ + private val renderer = KtDeclarationRendererForSource.WITH_QUALIFIED_NAMES.with { + annotationRenderer = annotationRenderer.with { annotationFilter = KtRendererAnnotationsFilter.NONE } + modifiersRenderer = modifiersRenderer.with { keywordsRenderer = KtKeywordsRenderer.NONE } + + returnTypeFilter = object : KtCallableReturnTypeFilter { + context(KtAnalysisSession) + override fun shouldRenderReturnType(type: KtType, symbol: KtCallableSymbol): Boolean = symbol !is KtFunctionLikeSymbol + } + + callableSignatureRenderer = object : KtCallableSignatureRenderer { + context(KtAnalysisSession, KtDeclarationRenderer) + override fun renderCallableSignature(symbol: KtCallableSymbol, keyword: KtKeywordToken?, printer: PrettyPrinter) = + when (symbol) { + is KtValueParameterSymbol -> returnTypeRenderer.renderReturnType(symbol, printer) + else -> KtCallableSignatureRenderer.FOR_SOURCE.renderCallableSignature(symbol, keyword = null, printer) + } + } + } + + context(KtAnalysisSession) + fun forDeclarationSymbol(symbol: KtDeclarationSymbol, context: String = ""): StatisticsInfo = when (symbol) { + is KtClassLikeSymbol -> symbol.classIdIfNonLocal?.asFqNameString()?.let { StatisticsInfo(context, it) } + is KtCallableSymbol -> symbol.callableIdIfNonLocal?.let { callableId -> + val containerFqName = callableId.classId?.asFqNameString() ?: callableId.packageName + StatisticsInfo(context, "$containerFqName###${prettyPrint { renderer.renderDeclaration(symbol, this) }}") + } + + else -> null + } ?: StatisticsInfo.EMPTY +} diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickDoc/KotlinDocumentationTarget.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickDoc/KotlinDocumentationTarget.kt index e1234b62a816..6b5e4130f1c0 100644 --- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickDoc/KotlinDocumentationTarget.kt +++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickDoc/KotlinDocumentationTarget.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.idea.KotlinIcons import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.kdoc.* @@ -83,7 +84,7 @@ internal class KotlinDocumentationTarget(val element: PsiElement, private val or private fun computeLocalDocumentation(element: PsiElement, originalElement: PsiElement?, quickNavigation: Boolean): String? { when { element is KtFunctionLiteral -> { - val itElement = findElementWithText(originalElement, "it") + val itElement = findElementWithText(originalElement, StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier) val itReference = itElement?.getParentOfType(false) if (itReference != null) { return buildString { @@ -215,8 +216,13 @@ private fun @receiver:Nls StringBuilder.renderEnumSpecialFunction( val containingClass = symbol.getContainingSymbol() as? KtClassOrObjectSymbol val superClasses = containingClass?.superTypes?.mapNotNull { t -> t.expandedClassSymbol } val kdoc = superClasses?.firstNotNullOfOrNull { superClass -> - superClass.psi?.navigationElement?.findDescendantOfType { doc -> - doc.getChildrenOfType().any { it.findTagByName(name) != null } + val navigationElement = superClass.psi?.navigationElement + if (navigationElement is KtElement && navigationElement.containingKtFile.isCompiled) { + null //no need to search documentation in decompiled code + } else { + navigationElement?.findDescendantOfType { doc -> + doc.getChildrenOfType().any { it.findTagByName(name) != null } + } } } diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ExpressionImportWeigher.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ExpressionImportWeigher.kt new file mode 100644 index 000000000000..270b51ca5009 --- /dev/null +++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ExpressionImportWeigher.kt @@ -0,0 +1,233 @@ +// 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.quickfix.fixes + +import com.intellij.psi.PsiElement +import com.intellij.util.applyIf +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +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.symbols.* +import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability +import org.jetbrains.kotlin.idea.base.analysis.api.utils.isPossiblySubTypeOf +import org.jetbrains.kotlin.idea.codeinsight.utils.getFqNameIfPackageOrNonLocal +import org.jetbrains.kotlin.idea.quickfix.ImportFixHelper +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.types.expressions.OperatorConventions + +/** + * Implementation in K1: [org.jetbrains.kotlin.idea.actions.ExpressionWeigher] + */ +interface ExpressionImportWeigher { + context(KtAnalysisSession) + fun weigh(symbol: KtDeclarationSymbol): Int + + companion object { + context(KtAnalysisSession) + fun createWeigher(element: PsiElement?): ExpressionImportWeigher = + when (element) { + is KtNameReferenceExpression -> CallExpressionImportWeigher( + token, + calculateReceiverTypes(element), + calculateValueArgumentTypes(element), + ) + + is KtOperationReferenceExpression -> { + val operatorName = element.operationSignTokenType?.let { operationSignTokenType -> + OperatorConventions.getNameForOperationSymbol(operationSignTokenType, false, true) + } + + val parent = element.parent + if (parent is KtBinaryExpression) { + OperatorExpressionImportWeigher( + token, + operatorName, + parent.left?.getKtType(), + parent.right?.getKtType(), + ) + } else OperatorExpressionImportWeigher(token, operatorName) + } + + else -> Empty + } + + context(KtAnalysisSession) + private fun calculateReceiverTypes(element: KtNameReferenceExpression): List { + val receiverExpression = element.getParentOfType(false)?.receiverExpression + + return if (receiverExpression != null) { + val explicitType = receiverExpression.getKtType() + // use non-nullable type if safe call is used i.e `val value: T? = ...; value?.smth() + val correctedExplicitType = explicitType?.applyIf(receiverExpression.parent is KtSafeQualifiedExpression) { + withNullability(KtTypeNullability.NON_NULLABLE) + } + listOfNotNull(correctedExplicitType) + } else { + element.containingKtFile.getScopeContextForPosition(element).implicitReceivers.map { it.type } + } + } + + context(KtAnalysisSession) + private fun calculateValueArgumentTypes(element: KtNameReferenceExpression): List { + val callExpression = element.getParentOfType(strict = false) + val valueArgumentList = callExpression?.valueArgumentList ?: return emptyList() + + val valueArguments = valueArgumentList.arguments + return valueArguments.map { it.getArgumentExpression()?.getKtType() } + } + + object Empty : ExpressionImportWeigher { + context(KtAnalysisSession) + override fun weigh(symbol: KtDeclarationSymbol): Int = 0 + } + } +} + +internal abstract class AbstractExpressionImportWeigher : ExpressionImportWeigher { + context(KtAnalysisSession) + override fun weigh(symbol: KtDeclarationSymbol): Int { + val fqName = symbol.getFqNameIfPackageOrNonLocal() + val baseWeight = fqName?.let { ImportFixHelper.calculateWeightBasedOnFqName(it, symbol.sourcePsi()) } ?: 0 + + return baseWeight + ownWeigh(symbol) + } + + context(KtAnalysisSession) + protected abstract fun ownWeigh(symbol: KtDeclarationSymbol): Int + + context(KtAnalysisSession) + protected fun weighType(presentType: KtType, typeFromImport: KtType, baseWeight: Int): Int? { + val adjustedType: KtType + val nullablesWeight = if (presentType.nullability.isNullable == typeFromImport.nullability.isNullable) { + adjustedType = presentType + 2 + } else { + adjustedType = presentType.applyIf(presentType.nullability.isNullable) { withNullability(KtTypeNullability.NON_NULLABLE) } + // no reason to make `typeFromImport` not nullable as `T` is a subtype of `T?` + 0 + } + + return if (adjustedType.isPossiblySubTypeOf(typeFromImport)) { + 100 * baseWeight + 10 + nullablesWeight + } else { + null + } + } +} + +internal class CallExpressionImportWeigher( + override val token: KtLifetimeToken, + private val presentReceiverTypes: List, + private val valueArgumentTypes: List, +) : AbstractExpressionImportWeigher(), KtLifetimeOwner { + + context(KtAnalysisSession) + override fun ownWeigh(symbol: KtDeclarationSymbol): Int = withValidityAssertion { + when { + symbol is KtCallableSymbol -> calculateWeight(symbol, presentReceiverTypes, valueArgumentTypes) + // TODO: some constructors could be not visible + symbol is KtClassOrObjectSymbol && presentReceiverTypes.isEmpty() -> { + val constructors = symbol.getDeclaredMemberScope().getConstructors() + constructors.maxOfOrNull { calculateWeight(it, presentReceiverTypes = emptyList(), valueArgumentTypes) } ?: 0 + } + + else -> 0 + } + } + + context(KtAnalysisSession) + private fun calculateWeight( + symbolToBeImported: KtCallableSymbol, + presentReceiverTypes: List, + presentValueArgumentTypes: List, + ): Int { + var weight = 0 + + val receiverTypeFromImport = symbolToBeImported.receiverType + if (receiverTypeFromImport != null) { + weight = presentReceiverTypes.mapNotNull { weighType(it, receiverTypeFromImport, weight) }.maxOrNull() ?: weight + } + + if (symbolToBeImported is KtFunctionLikeSymbol) { + val symbolValueParameters = symbolToBeImported.valueParameters + val symbolHasVarargParameter = symbolValueParameters.any { it.isVararg } + weight += if (symbolValueParameters.size >= presentValueArgumentTypes.size || symbolHasVarargParameter) { + // same number of arguments is better than bigger number + if (symbolValueParameters.size == presentValueArgumentTypes.size || symbolHasVarargParameter) 1 else 0 + } else { + // apply only base weight if target has fewer parameters than expected + return weight + } + + // TODO: it does not cover the following cases: + // - named parameters + // - default value, e.g. `param: Int = ""` + // - functional types, e.g. `Int.() -> Unit` + // - functional references, e.g. `::foo` + + val valueParametersFromImportIterator = symbolValueParameters.iterator() + var valueParameterFromImport: KtValueParameterSymbol? = null + + // update weight each time argument type matches the type of parameter from import; break once a mismatch appears + for (valueArgumentType in presentValueArgumentTypes) { + if (!valueParametersFromImportIterator.hasNext() || valueArgumentType == null) { + break + } + // don't update current parameter from import if it's vararg + // TODO: cover the case with vararg argument followed by named arguments + if (valueParameterFromImport == null || !valueParameterFromImport.isVararg) { + valueParameterFromImport = valueParametersFromImportIterator.next() + } + val valueParameterType = valueParameterFromImport.returnType + + var updatedWeight = weighType(valueArgumentType, valueParameterType, weight) + + if (updatedWeight == null && valueParameterFromImport.isVararg && valueArgumentType.isArrayOrPrimitiveArray()) { + val arrayElementType = valueArgumentType.getArrayElementType() ?: break + updatedWeight = weighType(arrayElementType, valueParameterType, weight) + } + + weight = updatedWeight ?: break + } + } + return weight + } +} + +internal class OperatorExpressionImportWeigher( + override val token: KtLifetimeToken, + private val operatorName: Name?, + private val leftOperandType: KtType? = null, + private val rightOperandType: KtType? = null, +) : AbstractExpressionImportWeigher(), KtLifetimeOwner { + + context(KtAnalysisSession) + override fun weigh(symbol: KtDeclarationSymbol): Int { + val functionSymbol = (symbol as? KtFunctionSymbol)?.takeIf { it.isOperator } ?: return 0 + + return super.weigh(functionSymbol) + } + + context(KtAnalysisSession) + override fun ownWeigh(symbol: KtDeclarationSymbol): Int = withValidityAssertion { + symbol as KtFunctionSymbol + + val name = symbol.name + + var weight = 0 + if (name == operatorName) { + weight += 8 + } + if (leftOperandType != null) { + weight = symbol.receiverType?.let { weighType(leftOperandType, it, weight) } ?: weight + } + if (rightOperandType != null) { + weight = symbol.valueParameters.firstOrNull()?.returnType?.let { weighType(rightOperandType, it, weight) } ?: weight + } + + return weight + } +} \ 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 03113a48047e..77bbdd765353 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 @@ -8,26 +8,43 @@ import com.intellij.codeInsight.daemon.impl.ShowAutoImportPass import com.intellij.codeInsight.hint.HintManager import com.intellij.codeInsight.hint.QuestionAction import com.intellij.codeInspection.HintAction +import com.intellij.codeInspection.util.IntentionName import com.intellij.lang.jvm.JvmModifier import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.popup.JBPopup -import com.intellij.openapi.ui.popup.JBPopupFactory import com.intellij.psi.* +import com.intellij.psi.statistics.StatisticsInfo +import com.intellij.psi.statistics.StatisticsManager import com.intellij.psi.util.PsiModificationTracker import com.intellij.psi.util.parentsOfType import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KtFirDiagnostic -import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol +import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KtRendererAnnotationsFilter +import org.jetbrains.kotlin.analysis.api.renderer.declarations.KtCallableReturnTypeFilter +import org.jetbrains.kotlin.analysis.api.renderer.declarations.KtDeclarationRenderer +import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KtDeclarationRendererForSource +import org.jetbrains.kotlin.analysis.api.renderer.declarations.modifiers.renderers.KtRendererVisibilityModifierProvider +import org.jetbrains.kotlin.analysis.api.symbols.* +import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithVisibility +import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint +import org.jetbrains.kotlin.idea.actions.KotlinAddImportActionInfo import org.jetbrains.kotlin.idea.base.analysis.api.utils.KtSymbolFromIndexProvider +import org.jetbrains.kotlin.idea.base.codeInsight.KotlinIconProvider.getIconFor +import org.jetbrains.kotlin.idea.base.facet.platform.platform +import org.jetbrains.kotlin.idea.base.projectStructure.compositeAnalysis.findAnalyzerServices +import org.jetbrains.kotlin.idea.base.projectStructure.languageVersionSettings import org.jetbrains.kotlin.idea.base.psi.imports.addImport import org.jetbrains.kotlin.idea.base.resources.KotlinBundle +import org.jetbrains.kotlin.idea.base.utils.fqname.isImported +import org.jetbrains.kotlin.idea.codeInsight.K2StatisticsInfoProvider import org.jetbrains.kotlin.idea.codeinsight.api.applicators.fixes.diagnosticFixFactory import org.jetbrains.kotlin.idea.codeinsight.api.classic.quickfixes.QuickFixActionBase +import org.jetbrains.kotlin.idea.codeinsight.utils.getFqNameIfPackageOrNonLocal +import org.jetbrains.kotlin.idea.quickfix.AutoImportVariant +import org.jetbrains.kotlin.idea.quickfix.ImportFixHelper +import org.jetbrains.kotlin.idea.quickfix.ImportPrioritizer import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.FqName @@ -36,17 +53,29 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.KtPsiUtil.isSelectorInQualified import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.unwrapNullability +import org.jetbrains.kotlin.resolve.ImportPath +import javax.swing.Icon class ImportQuickFix( element: KtElement, - private val importCandidates: List + @IntentionName private val text: String, + private val importVariants: List ) : QuickFixActionBase(element), HintAction { - - init { - require(importCandidates.isNotEmpty()) + private data class SymbolBasedAutoImportVariant( + override val fqName: FqName, + override val declarationToImport: PsiElement?, + override val icon: Icon?, + override val debugRepresentation: String, + val statisticsInfo: StatisticsInfo + ) : AutoImportVariant { + override val hint: String = fqName.asString() } - override fun getText(): String = KotlinBundle.message("fix.import") + init { + require(importVariants.isNotEmpty()) + } + + override fun getText(): String = text override fun getFamilyName(): String = KotlinBundle.message("fix.import") @@ -57,7 +86,7 @@ class ImportQuickFix( } private fun createAddImportAction(project: Project, editor: Editor, file: KtFile): QuestionAction { - return ImportQuestionAction(project, editor, file, importCandidates) + return ImportQuestionAction(project, editor, file, importVariants) } override fun showHint(editor: Editor): Boolean { @@ -73,7 +102,7 @@ class ImportQuickFix( val project = file.project val elementRange = element.textRange - val autoImportHintText = KotlinBundle.message("fix.import.question", importCandidates.first().asString()) + val autoImportHintText = KotlinBundle.message("fix.import.question", importVariants.first().fqName.asString()) HintManager.getInstance().showQuestionHint( editor, @@ -93,7 +122,7 @@ class ImportQuickFix( if (!ShowAutoImportPass.isAddUnambiguousImportsOnTheFlyEnabled(file)) return false val project = file.project val addImportAction = createAddImportAction(project, editor, file) - if (importCandidates.size == 1) { + if (importVariants.size == 1) { addImportAction.execute() return true } else { @@ -120,17 +149,18 @@ class ImportQuickFix( private val project: Project, private val editor: Editor, private val file: KtFile, - private val importCandidates: List + private val importVariants: List ) : QuestionAction { init { - require(importCandidates.isNotEmpty()) + require(importVariants.isNotEmpty()) } override fun execute(): Boolean { - when (importCandidates.size) { + KotlinAddImportActionInfo.executeListener?.onExecute(importVariants) + when (importVariants.size) { 1 -> { - addImport(importCandidates.single()) + addImport(importVariants.single()) return true } @@ -139,25 +169,24 @@ class ImportQuickFix( } else -> { - if (ApplicationManager.getApplication().isUnitTestMode) return false - createImportSelectorPopup().showInBestPositionFor(editor) + if (ApplicationManager.getApplication().isUnitTestMode) { + addImport(importVariants.first()) + return true + } + ImportFixHelper.createListPopupWithImportVariants(project, importVariants, ::addImport).showInBestPositionFor(editor) return true } } } - private fun createImportSelectorPopup(): JBPopup { - return JBPopupFactory.getInstance() - .createPopupChooserBuilder(importCandidates) - .setTitle(KotlinBundle.message("action.add.import.chooser.title")) - .setItemChosenCallback { selectedValue: FqName -> addImport(selectedValue) } - .createPopup() - } + private fun addImport(importVariant: AutoImportVariant) { + require(importVariant is SymbolBasedAutoImportVariant) + + StatisticsManager.getInstance().incUseCount(importVariant.statisticsInfo) - private fun addImport(nameToImport: FqName) { project.executeWriteCommand(QuickFixBundle.message("add.import")) { - file.addImport(nameToImport) + file.addImport(importVariant.fqName) } } } @@ -175,12 +204,133 @@ class ImportQuickFix( if (isSelectorInQualified(element)) null else createImportNameFix(indexProvider, element, element.getReferencedNameAsName()) } + else -> null } listOfNotNull(quickFix) } + private val renderer: KtDeclarationRenderer = KtDeclarationRendererForSource.WITH_QUALIFIED_NAMES.with { + modifiersRenderer = modifiersRenderer.with { + visibilityProvider = KtRendererVisibilityModifierProvider.WITH_IMPLICIT_VISIBILITY + } + annotationRenderer = annotationRenderer.with { + annotationFilter = KtRendererAnnotationsFilter.NONE + } + returnTypeFilter = KtCallableReturnTypeFilter.ALWAYS + } + + + context(KtAnalysisSession) + private fun renderSymbol(symbol: KtDeclarationSymbol): String = prettyPrint { + val fqName = symbol.getFqName() + if (symbol is KtNamedClassOrObjectSymbol) { + append("class $fqName") + } else { + renderer.renderDeclaration(symbol, printer = this) + } + + when (symbol) { + is KtCallableSymbol -> symbol.callableIdIfNonLocal?.packageName + is KtClassLikeSymbol -> symbol.classIdIfNonLocal?.packageFqName + else -> null + }?.let { packageName -> + append(" defined in ${packageName.asString()}") + symbol.psi?.containingFile?.let { append(" in file ${it.name}") } + } + } + + context(KtAnalysisSession) + private fun createImportFix( + element: KtElement, + importCandidateSymbols: List, + ): ImportQuickFix? { + if (importCandidateSymbols.isEmpty()) return null + + val analyzerServices = element.containingKtFile.platform.findAnalyzerServices(element.project) + val defaultImports = analyzerServices.getDefaultImports(element.languageVersionSettings, includeLowPriorityImports = true) + val excludedImports = analyzerServices.excludedImports + + val isImported = { fqName: FqName -> ImportPath(fqName, isAllUnder = false).isImported(defaultImports, excludedImports) } + val importPrioritizer = ImportPrioritizer(element.containingKtFile, isImported) + val expressionImportWeigher = ExpressionImportWeigher.createWeigher(element) + + val sortedImportCandidateSymbolsWithPriorities = importCandidateSymbols + .map { it to createPriorityForImportableSymbol(importPrioritizer, expressionImportWeigher, it) } + .sortedBy { (_, priority) -> priority } + + val sortedImportInfos = sortedImportCandidateSymbolsWithPriorities.mapNotNull { (candidateSymbol, priority) -> + val kind = candidateSymbol.getImportKind() ?: return@mapNotNull null + val name = candidateSymbol.getImportName() + ImportFixHelper.ImportInfo(kind, name, priority) + } + + val text = ImportFixHelper.calculateTextForFix( + sortedImportInfos, + suggestions = sortedImportCandidateSymbolsWithPriorities.map { (symbol, _) -> symbol.getFqName() }.distinct() + ) + + val sortedImportVariants = sortedImportCandidateSymbolsWithPriorities + .map { (symbol, priority) -> + SymbolBasedAutoImportVariant( + symbol.getFqName(), + symbol.psi, + getIconFor(symbol), + renderSymbol(symbol), + priority.statisticsInfo, + ) + } + + return ImportQuickFix(element, text, sortedImportVariants) + } + + context(KtAnalysisSession) + private fun KtDeclarationSymbol.getImportKind(): ImportFixHelper.ImportKind? = when { + this is KtPropertySymbol && isExtension -> ImportFixHelper.ImportKind.EXTENSION_PROPERTY + this is KtPropertySymbol -> ImportFixHelper.ImportKind.PROPERTY + + this is KtFunctionSymbol && isOperator -> ImportFixHelper.ImportKind.OPERATOR + this is KtFunctionSymbol && isExtension -> ImportFixHelper.ImportKind.EXTENSION_FUNCTION + this is KtFunctionSymbol -> ImportFixHelper.ImportKind.FUNCTION + + this is KtNamedClassOrObjectSymbol && classKind.isObject -> ImportFixHelper.ImportKind.OBJECT + this is KtNamedClassOrObjectSymbol -> ImportFixHelper.ImportKind.CLASS + + else -> null + } + + context(KtAnalysisSession) + private fun KtDeclarationSymbol.getImportName(): String = buildString { + if (this@getImportName !is KtNamedSymbol) error("Unexpected anonymous declaration") + + if (this@getImportName is KtCallableSymbol) { + val classSymbol = if (receiverType != null) receiverType?.expandedClassSymbol else originalContainingClassForOverride + classSymbol?.name?.let { append(it.asString()) } + } + + if (this.isNotEmpty()) append('.') + append(name.asString()) + } + + context(KtAnalysisSession) + private fun KtDeclarationSymbol.getFqName(): FqName = + getFqNameIfPackageOrNonLocal() ?: error("Unexpected null for fully-qualified name of importable symbol") + + context(KtAnalysisSession) + private fun createPriorityForImportableSymbol( + prioritizer: ImportPrioritizer, + expressionImportWeigher: ExpressionImportWeigher, + symbol: KtDeclarationSymbol + ): ImportPrioritizer.Priority = + prioritizer.Priority( + declaration = symbol.psi, + statisticsInfo = K2StatisticsInfoProvider.forDeclarationSymbol(symbol), + isDeprecated = symbol.deprecationStatus != null, + fqName = symbol.getFqName(), + expressionWeight = expressionImportWeigher.weigh(symbol), + ) + fun KtAnalysisSession.createImportNameFix( indexProvider: KtSymbolFromIndexProvider, element: KtReferenceExpression, @@ -194,10 +344,7 @@ class ImportQuickFix( val callableCandidates = collectCallableCandidates(indexProvider, unresolvedName, isVisible) val typeCandidates = collectTypesCandidates(indexProvider, unresolvedName, isVisible) - val importCandidates = (callableCandidates + typeCandidates).distinct() - if (importCandidates.isEmpty()) return null - - return ImportQuickFix(element, importCandidates) + return createImportFix(element, callableCandidates + typeCandidates) } private fun KtAnalysisSession.createImportTypeFix( @@ -210,24 +357,20 @@ class ImportQuickFix( val isVisible: (KtNamedClassOrObjectSymbol) -> Boolean = { isVisible(it, firFile, null, element) } - val acceptableClasses = collectTypesCandidates(indexProvider, unresolvedName, isVisible).distinct() - if (acceptableClasses.isEmpty()) return null - - return ImportQuickFix(element, acceptableClasses) + return createImportFix(element, collectTypesCandidates(indexProvider, unresolvedName, isVisible)) } private fun KtAnalysisSession.collectCallableCandidates( indexProvider: KtSymbolFromIndexProvider, unresolvedName: Name, isVisible: (KtCallableSymbol) -> Boolean - ): List { + ): List { val callablesCandidates = indexProvider.getKotlinCallableSymbolsByName(unresolvedName) { it.canBeImported() } + - indexProvider.getJavaCallableSymbolsByName(unresolvedName) { it.canBeImported() } + indexProvider.getJavaCallableSymbolsByName(unresolvedName) { it.canBeImported() } return callablesCandidates - .filter(isVisible) - .mapNotNull { it.callableIdIfNonLocal?.asSingleFqName() } + .filter { isVisible(it) && it.callableIdIfNonLocal != null } .toList() } @@ -235,14 +378,13 @@ class ImportQuickFix( indexProvider: KtSymbolFromIndexProvider, unresolvedName: Name, isVisible: (KtNamedClassOrObjectSymbol) -> Boolean - ): List { + ): List { val classesCandidates = indexProvider.getKotlinClassesByName(unresolvedName) { it.canBeImported() } + indexProvider.getJavaClassesByName(unresolvedName) { it.canBeImported() } return classesCandidates - .filter(isVisible) - .mapNotNull { it.classIdIfNonLocal?.asSingleFqName() } + .filter { isVisible(it) && it.classIdIfNonLocal != null } .toList() } } diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/WrapWithSafeLetCallFixFactories.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/WrapWithSafeLetCallFixFactories.kt index eb51ccb26242..c58cf50d5150 100644 --- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/WrapWithSafeLetCallFixFactories.kt +++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/WrapWithSafeLetCallFixFactories.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.analysis.api.calls.* import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KtFirDiagnostic import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.receiverType +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.codeinsight.api.applicators.KotlinApplicator import org.jetbrains.kotlin.idea.codeinsight.api.applicators.KotlinApplicatorInput @@ -76,7 +77,7 @@ object WrapWithSafeLetCallFixFactories { fun getNewExpression(nullableExpressionText: String, expressionUnderLetText: String): KtExpression { return when (suggestedVariableName) { - "it" -> psiFactory.createExpressionByPattern("$0?.let { $1 }", nullableExpressionText, expressionUnderLetText) + StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier -> psiFactory.createExpressionByPattern("$0?.let { $1 }", nullableExpressionText, expressionUnderLetText) else -> psiFactory.createExpressionByPattern( "$0?.let { $1 -> $2 }", nullableExpressionText, @@ -211,7 +212,7 @@ object WrapWithSafeLetCallFixFactories { // Note, the order of the candidate matters. We would prefer the default `it` so the generated code won't need to declare the // variable explicitly. - val candidateNames = listOfNotNull("it", getDeclaredParameterNameForArgument(nullableExpression)) + val candidateNames = listOfNotNull(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier, getDeclaredParameterNameForArgument(nullableExpression)) val suggestedName = FirKotlinNameSuggester.suggestNameByMultipleNames(candidateNames) { it !in existingNames } return listOf( KotlinApplicatorBasedQuickFix( diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/actions/AbstractK2AddImportActionTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/actions/AbstractK2AddImportActionTest.kt new file mode 100644 index 000000000000..3405b9da76c5 --- /dev/null +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/actions/AbstractK2AddImportActionTest.kt @@ -0,0 +1,21 @@ +// 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.actions + +import org.jetbrains.kotlin.idea.actions.AbstractAddImportActionTestBase +import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor +import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.test.utils.IgnoreTests + +abstract class AbstractK2AddImportActionTest : AbstractAddImportActionTestBase() { + override fun isFirPlugin(): Boolean = true + + override fun getDefaultProjectDescriptor(): KotlinLightProjectDescriptor { + return KotlinWithJdkAndRuntimeLightProjectDescriptor.getInstance() + } + + override fun doTest(unused: String) { + IgnoreTests.runTestIfEnabledByFileDirective(dataFilePath(), IgnoreTests.DIRECTIVES.FIR_COMPARISON) { + super.doTest(unused) + } + } +} \ No newline at end of file diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/actions/K2AddImportActionTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/actions/K2AddImportActionTestGenerated.java new file mode 100644 index 000000000000..5a362a41465a --- /dev/null +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/actions/K2AddImportActionTestGenerated.java @@ -0,0 +1,195 @@ +// 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.actions; + +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("fir") +@TestDataPath("$CONTENT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +@TestMetadata("../idea/tests/testData/idea/actions/kotlinAddImportAction") +public class K2AddImportActionTestGenerated extends AbstractK2AddImportActionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("Class1.kt") + public void testClass1() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/Class1.kt"); + } + + @TestMetadata("Class2.kt") + public void testClass2() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/Class2.kt"); + } + + @TestMetadata("ClassWhenExtIsImported.kt") + public void testClassWhenExtIsImported() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/ClassWhenExtIsImported.kt"); + } + + @TestMetadata("ConstructorOverloadsPresent.kt") + public void testConstructorOverloadsPresent() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/ConstructorOverloadsPresent.kt"); + } + + @TestMetadata("ExtReceiver.kt") + public void testExtReceiver() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver.kt"); + } + + @TestMetadata("ExtReceiver2.kt") + public void testExtReceiver2() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver2.kt"); + } + + @TestMetadata("ExtReceiver3.kt") + public void testExtReceiver3() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver3.kt"); + } + + @TestMetadata("ExtReceiver4.kt") + public void testExtReceiver4() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver4.kt"); + } + + @TestMetadata("ExtendingClass1.kt") + public void testExtendingClass1() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/ExtendingClass1.kt"); + } + + @TestMetadata("ExtendingClass2.kt") + public void testExtendingClass2() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/ExtendingClass2.kt"); + } + + @TestMetadata("KotlinDurations.kt") + public void testKotlinDurations() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations.kt"); + } + + @TestMetadata("KotlinDurations2.kt") + public void testKotlinDurations2() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations2.kt"); + } + + @TestMetadata("KotlinMinCollections.kt") + public void testKotlinMinCollections() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinCollections.kt"); + } + + @TestMetadata("KotlinMinInt.kt") + public void testKotlinMinInt() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinInt.kt"); + } + + @TestMetadata("MultipleMethodsAvailable.kt") + public void testMultipleMethodsAvailable() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable.kt"); + } + + @TestMetadata("MultipleMethodsAvailable2.kt") + public void testMultipleMethodsAvailable2() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable2.kt"); + } + + @TestMetadata("Nullable1.kt") + public void testNullable1() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/Nullable1.kt"); + } + + @TestMetadata("Nullable2.kt") + public void testNullable2() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/Nullable2.kt"); + } + + @TestMetadata("Nullable3.kt") + public void testNullable3() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/Nullable3.kt"); + } + + @TestMetadata("OverloadsPresent.kt") + public void testOverloadsPresent() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/OverloadsPresent.kt"); + } + + @TestMetadata("PlusAssignOperator.kt") + public void testPlusAssignOperator() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/PlusAssignOperator.kt"); + } + + @TestMetadata("PlusAssignOperator2.kt") + public void testPlusAssignOperator2() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/PlusAssignOperator2.kt"); + } + + @TestMetadata("PlusAssignOperatorCall.kt") + public void testPlusAssignOperatorCall() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/PlusAssignOperatorCall.kt"); + } + + @TestMetadata("PlusAssignOperatorCall2.kt") + public void testPlusAssignOperatorCall2() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/PlusAssignOperatorCall2.kt"); + } + + @TestMetadata("PlusOperator.kt") + public void testPlusOperator() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/PlusOperator.kt"); + } + + @TestMetadata("PlusOperator1.kt") + public void testPlusOperator1() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/PlusOperator1.kt"); + } + + @TestMetadata("PlusOperatorCall1.kt") + public void testPlusOperatorCall1() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/PlusOperatorCall1.kt"); + } + + @TestMetadata("SingleMethodAvailable.kt") + public void testSingleMethodAvailable() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/SingleMethodAvailable.kt"); + } + + @TestMetadata("TypeAlias.kt") + public void testTypeAlias() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/TypeAlias.kt"); + } + + @TestMetadata("VarargSpreadOperator.kt") + public void testVarargSpreadOperator() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.kt"); + } + + @TestMetadata("Varargs.kt") + public void testVarargs() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs.kt"); + } + + @TestMetadata("Varargs2.kt") + public void testVarargs2() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs2.kt"); + } + + @TestMetadata("Varargs3.kt") + public void testVarargs3() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs3.kt"); + } + + @TestMetadata("WithStatisticsInfo.kt") + public void testWithStatisticsInfo() throws Exception { + runTest("../idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.kt"); + } +} diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/codeInsight/FirKotlinIconProviderTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/codeInsight/FirKotlinIconProviderTest.kt new file mode 100644 index 000000000000..e7fe40f37c20 --- /dev/null +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/codeInsight/FirKotlinIconProviderTest.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.codeInsight +import com.intellij.openapi.util.Iconable +import com.intellij.psi.search.searches.ClassInheritorsSearch +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.ui.icons.RowIcon +import com.intellij.util.PsiIconUtil +import com.intellij.util.ThrowableRunnable +import org.jetbrains.kotlin.idea.fir.invalidateCaches +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.idea.test.runAll +import org.jetbrains.kotlin.utils.addToStdlib.safeAs +import javax.swing.Icon + +class FirKotlinIconProviderTest : KotlinLightCodeInsightFixtureTestCase() { + override fun isFirPlugin(): Boolean { + return true + } + + override fun getProjectDescriptor(): LightProjectDescriptor { + return KotlinWithJdkAndRuntimeLightProjectDescriptor.getInstance() + } + + override fun tearDown() { + runAll( + ThrowableRunnable { project.invalidateCaches() }, + ThrowableRunnable { super.tearDown() } + ) + } + + fun testJavaBase() { + val aClass = myFixture.addClass("public class BaseJavaClass {}") + myFixture.addFileToProject("foo.kt", "class Foo : BaseJavaClass() {}") + val psiClass = ClassInheritorsSearch.search(aClass).findFirst()!! + val icon = PsiIconUtil.getProvidersIcon(psiClass, Iconable.ICON_FLAG_VISIBILITY or Iconable.ICON_FLAG_READ_STATUS) + val iconString = (icon.safeAs()?.allIcons?.joinToString(transform = Icon::toString) ?: icon)?.toString() + assertEquals("org/jetbrains/kotlin/idea/icons/classKotlin.svg", iconString) + } +} \ No newline at end of file diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/FirCompletionOutsideSourceRootTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/FirCompletionOutsideSourceRootTest.kt index adee6bd0d665..51806881e206 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/FirCompletionOutsideSourceRootTest.kt +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/completion/FirCompletionOutsideSourceRootTest.kt @@ -1,17 +1,25 @@ // 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.completion +import com.intellij.testFramework.common.runAll import com.intellij.testFramework.LightProjectDescriptor import java.nio.charset.Charset +import org.jetbrains.kotlin.idea.fir.invalidateCaches import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor class FirCompletionOutsideSourceRootTest : KotlinLightCodeInsightFixtureTestCase() { - fun testFunctionName() { - val tempFile = createTempFile("kt", null, "fun ", Charset.defaultCharset()) - myFixture.configureFromExistingVirtualFile(tempFile) - myFixture.completeBasic() - } + fun testFunctionName() { + val tempFile = createTempFile("kt", null, "fun ", Charset.defaultCharset()) + myFixture.configureFromExistingVirtualFile(tempFile) + myFixture.completeBasic() + } + + fun testOverrideHandler() { + val tempFile = createTempFile("kt", null, "interface A {fu}", Charset.defaultCharset()) + myFixture.configureFromExistingVirtualFile(tempFile) + myFixture.completeBasic() + } override fun isFirPlugin(): Boolean { return true @@ -20,4 +28,11 @@ class FirCompletionOutsideSourceRootTest : KotlinLightCodeInsightFixtureTestCase override fun getProjectDescriptor(): LightProjectDescriptor { return KotlinWithJdkAndRuntimeLightProjectDescriptor.getInstance() } + + override fun tearDown() { + runAll( + { project.invalidateCaches() }, + { super.tearDown() } + ) + } } \ No newline at end of file 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 23acfcebbbcc..08a6df6f6cc2 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 @@ -1623,6 +1623,11 @@ public abstract class HighLevelJvmBasicCompletionTestGenerated extends AbstractH runTest("../completion/testData/basic/common/parameterNameAndType/ByAbbreviation.kt"); } + @TestMetadata("FunctionCall.kt") + public void testFunctionCall() throws Exception { + runTest("../completion/testData/basic/common/parameterNameAndType/FunctionCall.kt"); + } + @TestMetadata("InSecondaryConstructor.kt") public void testInSecondaryConstructor() throws Exception { runTest("../completion/testData/basic/common/parameterNameAndType/InSecondaryConstructor.kt"); diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/documentation/AbstractFirQuickDocTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/documentation/AbstractFirQuickDocTest.kt index 16bee7b3b46a..9701fa4eeaba 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/documentation/AbstractFirQuickDocTest.kt +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/documentation/AbstractFirQuickDocTest.kt @@ -17,7 +17,7 @@ abstract class AbstractFirQuickDocTest : AbstractQuickDocProviderTest() { } override fun getProjectDescriptor(): KotlinLightProjectDescriptor { - return KotlinWithJdkAndRuntimeLightProjectDescriptor.getInstance() + return KotlinWithJdkAndRuntimeLightProjectDescriptor.getInstanceNoSources() } override fun isFirPlugin(): Boolean { diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/documentation/FirQuickDocTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/documentation/FirQuickDocTestGenerated.java index 8544af106075..61be0ad69ee5 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/documentation/FirQuickDocTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/documentation/FirQuickDocTestGenerated.java @@ -68,6 +68,11 @@ public class FirQuickDocTestGenerated extends AbstractFirQuickDocTest { runTest("testData/quickDoc/ConstructorVarParameter.kt"); } + @TestMetadata("DecompiledSuper.kt") + public void testDecompiledSuper() throws Exception { + runTest("testData/quickDoc/DecompiledSuper.kt"); + } + @TestMetadata("DefinitelyNonNullType.kt") public void testDefinitelyNonNullType() throws Exception { runTest("testData/quickDoc/DefinitelyNonNullType.kt"); diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/findUsages/FindUsagesFirTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/findUsages/FindUsagesFirTestGenerated.java index 1840cfbf3800..2241f0cf0f43 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/findUsages/FindUsagesFirTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/findUsages/FindUsagesFirTestGenerated.java @@ -1266,6 +1266,11 @@ public abstract class FindUsagesFirTestGenerated extends AbstractFindUsagesFirTe KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("classAlias.0.kt") + public void testClassAlias() throws Exception { + runTest("../idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.0.kt"); + } + @TestMetadata("objectAlias.0.kt") public void testObjectAlias() throws Exception { runTest("../idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/objectAlias.0.kt"); @@ -1289,6 +1294,11 @@ public abstract class FindUsagesFirTestGenerated extends AbstractFindUsagesFirTe runTest("../idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinFunctionTypeParameterUsages.0.kt"); } + @TestMetadata("kotlinReifiedTypeParameterUsages.0.kt") + public void testKotlinReifiedTypeParameterUsages() throws Exception { + runTest("../idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.0.kt"); + } + @TestMetadata("propertyWithTypeParameter.0.kt") public void testPropertyWithTypeParameter() throws Exception { runTest("../idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/propertyWithTypeParameter.0.kt"); diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/AbstractHighLevelQuickFixMultiModuleTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/AbstractHighLevelQuickFixMultiModuleTest.kt new file mode 100644 index 000000000000..bbe13d78ae23 --- /dev/null +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/AbstractHighLevelQuickFixMultiModuleTest.kt @@ -0,0 +1,21 @@ +// 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.quickfix + +import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixMultiModuleTest +import org.jetbrains.kotlin.idea.test.findFileWithCaret +import org.jetbrains.kotlin.test.utils.IgnoreTests + +abstract class AbstractHighLevelQuickFixMultiModuleTest : AbstractQuickFixMultiModuleTest() { + override fun isFirPlugin(): Boolean = true + + override fun doQuickFixTest(dirPath: String) { + val actionFile = project.findFileWithCaret() + val actionFilePath = actionFile.virtualFile.toNioPath() + IgnoreTests.runTestIfEnabledByFileDirective( + actionFilePath, + enableTestDirective = IgnoreTests.DIRECTIVES.FIR_COMPARISON, + ) { + super.doQuickFixTest(dirPath) + } + } +} \ No newline at end of file diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixMultiFileTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixMultiFileTestGenerated.java index e074dee6c703..4e578d396106 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixMultiFileTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixMultiFileTestGenerated.java @@ -300,6 +300,11 @@ public abstract class HighLevelQuickFixMultiFileTestGenerated extends AbstractHi runTest("../idea/tests/testData/quickfix/autoImports/functionImport.before.Main.kt"); } + @TestMetadata("functionPreferNotDeprecated.test") + public void testFunctionPreferNotDeprecated() throws Exception { + runTest("../idea/tests/testData/quickfix/autoImports/functionPreferNotDeprecated.test"); + } + @TestMetadata("importAliasClassAlreadyExists.before.Main.kt") public void testImportAliasClassAlreadyExists() throws Exception { runTest("../idea/tests/testData/quickfix/autoImports/importAliasClassAlreadyExists.before.Main.kt"); diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixMultiModuleTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixMultiModuleTestGenerated.java new file mode 100644 index 000000000000..1b4bd3a07b01 --- /dev/null +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/quickfix/HighLevelQuickFixMultiModuleTestGenerated.java @@ -0,0 +1,1465 @@ +// 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.quickfix; + +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("fir") +@TestDataPath("$CONTENT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +@TestMetadata("../idea/tests/testData/multiModuleQuickFix") +public abstract class HighLevelQuickFixMultiModuleTestGenerated extends AbstractHighLevelQuickFixMultiModuleTest { + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker") + public static class AccessibilityChecker extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("annotationOnClass") + public void testAnnotationOnClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/annotationOnClass/"); + } + + @TestMetadata("classPrimaryConstructor") + public void testClassPrimaryConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/classPrimaryConstructor/"); + } + + @TestMetadata("classSecondaryConstructor") + public void testClassSecondaryConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/classSecondaryConstructor/"); + } + + @TestMetadata("classUpperBounds") + public void testClassUpperBounds() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/classUpperBounds/"); + } + + @TestMetadata("errorType") + public void testErrorType() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/errorType/"); + } + + @TestMetadata("memberFunction") + public void testMemberFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/memberFunction/"); + } + + @TestMetadata("memberFunctionAndNestedClass") + public void testMemberFunctionAndNestedClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/memberFunctionAndNestedClass/"); + } + + @TestMetadata("memberFunctionParentType") + public void testMemberFunctionParentType() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/memberFunctionParentType/"); + } + + @TestMetadata("memberFunctionParentType2") + public void testMemberFunctionParentType2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/memberFunctionParentType2/"); + } + + @TestMetadata("nestedClassWithTypeParam") + public void testNestedClassWithTypeParam() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/nestedClassWithTypeParam/"); + } + + @TestMetadata("topLevelFunParameter") + public void testTopLevelFunParameter() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/topLevelFunParameter/"); + } + + @TestMetadata("topLevelFunReturnType") + public void testTopLevelFunReturnType() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/topLevelFunReturnType/"); + } + + @TestMetadata("topLevelFunTypeParameter") + public void testTopLevelFunTypeParameter() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/topLevelFunTypeParameter/"); + } + + @TestMetadata("topLevelFunUpperBounds") + public void testTopLevelFunUpperBounds() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/topLevelFunUpperBounds/"); + } + + @TestMetadata("topLevelFunUpperBounds2") + public void testTopLevelFunUpperBounds2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/topLevelFunUpperBounds2/"); + } + + @TestMetadata("topLevelProperty") + public void testTopLevelProperty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/topLevelProperty/"); + } + + @TestMetadata("topLevelPropertyTypeParam2") + public void testTopLevelPropertyTypeParam2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/topLevelPropertyTypeParam2/"); + } + + @TestMetadata("topLevelPropertyTypeParamBound") + public void testTopLevelPropertyTypeParamBound() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/accessibilityChecker/topLevelPropertyTypeParamBound/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/addDependency") + public static class AddDependency extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("class") + public void testClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addDependency/class/"); + } + + @TestMetadata("topLevelFunction") + public void testTopLevelFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addDependency/topLevelFunction/"); + } + + @TestMetadata("topLevelFunction2") + public void testTopLevelFunction2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addDependency/topLevelFunction2/"); + } + + @TestMetadata("topLevelProperty") + public void testTopLevelProperty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addDependency/topLevelProperty/"); + } + + @TestMetadata("topLevelProperty2") + public void testTopLevelProperty2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addDependency/topLevelProperty2/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers") + public static class AddMissingActualMembers extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("classFunction") + public void testClassFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/classFunction/"); + } + + @TestMetadata("classFunctionSameSignature") + public void testClassFunctionSameSignature() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/classFunctionSameSignature/"); + } + + @TestMetadata("classFunctionWithConstructor") + public void testClassFunctionWithConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/classFunctionWithConstructor/"); + } + + @TestMetadata("classFunctionWithConstructorAndParameters") + public void testClassFunctionWithConstructorAndParameters() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/classFunctionWithConstructorAndParameters/"); + } + + @TestMetadata("classFunctionWithIncompatibleConstructor") + public void testClassFunctionWithIncompatibleConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/classFunctionWithIncompatibleConstructor/"); + } + + @TestMetadata("classOverloadedFunction") + public void testClassOverloadedFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/classOverloadedFunction/"); + } + + @TestMetadata("classPropertyInConstructor") + public void testClassPropertyInConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/classPropertyInConstructor/"); + } + + @TestMetadata("classSomeProperties") + public void testClassSomeProperties() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/classSomeProperties/"); + } + + @TestMetadata("classWithIncompilableFunction") + public void testClassWithIncompilableFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/classWithIncompilableFunction/"); + } + + @TestMetadata("companionAbsence") + public void testCompanionAbsence() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/companionAbsence/"); + } + + @TestMetadata("membersWithIncorrectType") + public void testMembersWithIncorrectType() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/membersWithIncorrectType/"); + } + + @TestMetadata("primaryConstructorAbsence") + public void testPrimaryConstructorAbsence() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/primaryConstructorAbsence/"); + } + + @TestMetadata("propertyWithIncorrectType") + public void testPropertyWithIncorrectType() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/propertyWithIncorrectType/"); + } + + @TestMetadata("secondaryConstructorAbsence") + public void testSecondaryConstructorAbsence() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addMissingActualMembers/secondaryConstructorAbsence/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/addThrowAnnotation") + public static class AddThrowAnnotation extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("common") + public void testCommon() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addThrowAnnotation/common/"); + } + + @TestMetadata("js") + public void testJs() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addThrowAnnotation/js/"); + } + + @TestMetadata("jvm") + public void testJvm() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addThrowAnnotation/jvm/"); + } + + @TestMetadata("jvmWithoutStdlib") + public void testJvmWithoutStdlib() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/addThrowAnnotation/jvmWithoutStdlib/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/canSealedSubClassBeObject") + public static class CanSealedSubClassBeObject extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("notConvertActualSubClass") + public void testNotConvertActualSubClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/canSealedSubClassBeObject/notConvertActualSubClass/"); + } + + @TestMetadata("notConvertExpectSubClass") + public void testNotConvertExpectSubClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/canSealedSubClassBeObject/notConvertExpectSubClass/"); + } + + @TestMetadata("notConvertImplicitExpectSubClass") + public void testNotConvertImplicitExpectSubClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/canSealedSubClassBeObject/notConvertImplicitExpectSubClass/"); + } + + @TestMetadata("notGenerateEqualsAndHashCodeForSealedInCommon") + public void testNotGenerateEqualsAndHashCodeForSealedInCommon() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/canSealedSubClassBeObject/notGenerateEqualsAndHashCodeForSealedInCommon/"); + } + + @TestMetadata("notGenerateEqualsAndHashCodeForSealedInJvmForExpect") + public void testNotGenerateEqualsAndHashCodeForSealedInJvmForExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/canSealedSubClassBeObject/notGenerateEqualsAndHashCodeForSealedInJvmForExpect/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/changeModifier") + public static class ChangeModifier extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("internal") + public void testInternal() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/changeModifier/internal/"); + } + + @TestMetadata("public") + public void testPublic() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/changeModifier/public/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/changeSignature") + public static class ChangeSignature extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("actual") + public void testActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/changeSignature/actual/"); + } + + @TestMetadata("expect") + public void testExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/changeSignature/expect/"); + } + + @TestMetadata("override") + public void testOverride() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/changeSignature/override/"); + } + + @TestMetadata("override2") + public void testOverride2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/changeSignature/override2/"); + } + + @TestMetadata("override3") + public void testOverride3() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/changeSignature/override3/"); + } + + @TestMetadata("override4") + public void testOverride4() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/changeSignature/override4/"); + } + + @TestMetadata("override5") + public void testOverride5() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/changeSignature/override5/"); + } + + @TestMetadata("override6") + public void testOverride6() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/changeSignature/override6/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/createActual") + public static class CreateActual extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("abstract") + public void testAbstract() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/abstract/"); + } + + @TestMetadata("abstractClassWithJdk") + public void testAbstractClassWithJdk() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/abstractClassWithJdk/"); + } + + @TestMetadata("annotation") + public void testAnnotation() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/annotation/"); + } + + @TestMetadata("annotationOptionalExpectation") + public void testAnnotationOptionalExpectation() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/annotationOptionalExpectation/"); + } + + @TestMetadata("annotationOptionalExpectationNoDir") + public void testAnnotationOptionalExpectationNoDir() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/annotationOptionalExpectationNoDir/"); + } + + @TestMetadata("annotationWithComment") + public void testAnnotationWithComment() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/annotationWithComment/"); + } + + @TestMetadata("class") + public void testClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/class/"); + } + + @TestMetadata("classWithBase") + public void testClassWithBase() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/classWithBase/"); + } + + @TestMetadata("classWithJdk") + public void testClassWithJdk() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/classWithJdk/"); + } + + @TestMetadata("classWithSuperTypeFromOtherPackage") + public void testClassWithSuperTypeFromOtherPackage() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/classWithSuperTypeFromOtherPackage/"); + } + + @TestMetadata("constructorWithDelegation") + public void testConstructorWithDelegation() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/constructorWithDelegation/"); + } + + @TestMetadata("constructorWithJdk") + public void testConstructorWithJdk() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/constructorWithJdk/"); + } + + @TestMetadata("createWithImport") + public void testCreateWithImport() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/createWithImport/"); + } + + @TestMetadata("defaultParameterInExpected") + public void testDefaultParameterInExpected() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpected/"); + } + + @TestMetadata("defaultParameterInExpectedClass") + public void testDefaultParameterInExpectedClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedClass/"); + } + + @TestMetadata("defaultParameterInExpectedConstructor") + public void testDefaultParameterInExpectedConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/defaultParameterInExpectedConstructor/"); + } + + @TestMetadata("enum") + public void testEnum() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/enum/"); + } + + @TestMetadata("expectSealedInCommonWhen") + public void testExpectSealedInCommonWhen() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/expectSealedInCommonWhen/"); + } + + @TestMetadata("forbiddenForLeafSourceSets") + public void testForbiddenForLeafSourceSets() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/forbiddenForLeafSourceSets/"); + } + + @TestMetadata("function") + public void testFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/function/"); + } + + @TestMetadata("functionSameFile") + public void testFunctionSameFile() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/functionSameFile/"); + } + + @TestMetadata("inlineClass") + public void testInlineClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/inlineClass/"); + } + + @TestMetadata("interface") + public void testInterface() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/interface/"); + } + + @TestMetadata("nested") + public void testNested() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/nested/"); + } + + @TestMetadata("object") + public void testObject() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/object/"); + } + + @TestMetadata("package") + public void testPackage() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/package/"); + } + + @TestMetadata("packageIncorrect") + public void testPackageIncorrect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/packageIncorrect/"); + } + + @TestMetadata("packageIncorrectEmpty") + public void testPackageIncorrectEmpty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/packageIncorrectEmpty/"); + } + + @TestMetadata("primaryConstructor") + public void testPrimaryConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/primaryConstructor/"); + } + + @TestMetadata("property") + public void testProperty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/property/"); + } + + @TestMetadata("sealed") + public void testSealed() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/sealed/"); + } + + @TestMetadata("sealedInCommonWhen") + public void testSealedInCommonWhen() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/sealedInCommonWhen/"); + } + + @TestMetadata("sealedSubclass") + public void testSealedSubclass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/sealedSubclass/"); + } + + @TestMetadata("valueClass") + public void testValueClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/valueClass/"); + } + + @TestMetadata("valueClassWithGenerics") + public void testValueClassWithGenerics() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/valueClassWithGenerics/"); + } + + @TestMetadata("withFakeJvm") + public void testWithFakeJvm() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/withFakeJvm/"); + } + + @TestMetadata("withRootPackage") + public void testWithRootPackage() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/withRootPackage/"); + } + + @TestMetadata("withTest") + public void testWithTest() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/withTest/"); + } + + @TestMetadata("withTestDummy") + public void testWithTestDummy() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActual/withTestDummy/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/createActualExplicitApi") + public static class CreateActualExplicitApi extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("class") + public void testClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActualExplicitApi/class/"); + } + + @TestMetadata("function") + public void testFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createActualExplicitApi/function/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/createExpect") + public static class CreateExpect extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("annotation") + public void testAnnotation() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/annotation/"); + } + + @TestMetadata("annotation2") + public void testAnnotation2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/annotation2/"); + } + + @TestMetadata("class") + public void testClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/class/"); + } + + @TestMetadata("classWithAnnotation") + public void testClassWithAnnotation() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/classWithAnnotation/"); + } + + @TestMetadata("classWithSuperClassAndTypeParameter") + public void testClassWithSuperClassAndTypeParameter() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/classWithSuperClassAndTypeParameter/"); + } + + @TestMetadata("classWithSuperTypeFromOtherPackage") + public void testClassWithSuperTypeFromOtherPackage() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/classWithSuperTypeFromOtherPackage/"); + } + + @TestMetadata("commented") + public void testCommented() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/commented/"); + } + + @TestMetadata("companion") + public void testCompanion() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/companion/"); + } + + @TestMetadata("createWithImport") + public void testCreateWithImport() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/createWithImport/"); + } + + @TestMetadata("dataClass") + public void testDataClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/dataClass/"); + } + + @TestMetadata("dataObject") + public void testDataObject() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/dataObject/"); + } + + @TestMetadata("enum") + public void testEnum() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/enum/"); + } + + @TestMetadata("enumComplex") + public void testEnumComplex() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/enumComplex/"); + } + + @TestMetadata("enumEmpty") + public void testEnumEmpty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/enumEmpty/"); + } + + @TestMetadata("funWithAccessibleAlias") + public void testFunWithAccessibleAlias() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/funWithAccessibleAlias/"); + } + + @TestMetadata("funWithAccessibleExpansion") + public void testFunWithAccessibleExpansion() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/funWithAccessibleExpansion/"); + } + + @TestMetadata("funWithAccessibleParameter") + public void testFunWithAccessibleParameter() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/funWithAccessibleParameter/"); + } + + @TestMetadata("funWithAccessibleTypeFromCommon") + public void testFunWithAccessibleTypeFromCommon() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/funWithAccessibleTypeFromCommon/"); + } + + @TestMetadata("funWithJdk") + public void testFunWithJdk() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/funWithJdk/"); + } + + @TestMetadata("funWithPrivateModifier") + public void testFunWithPrivateModifier() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/funWithPrivateModifier/"); + } + + @TestMetadata("function") + public void testFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/function/"); + } + + @TestMetadata("function2") + public void testFunction2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/function2/"); + } + + @TestMetadata("functionInInterface") + public void testFunctionInInterface() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/functionInInterface/"); + } + + @TestMetadata("functionWithImplementationInInterface") + public void testFunctionWithImplementationInInterface() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/functionWithImplementationInInterface/"); + } + + @TestMetadata("functionWithImplementationInInterface2") + public void testFunctionWithImplementationInInterface2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/functionWithImplementationInInterface2/"); + } + + @TestMetadata("hierarchy") + public void testHierarchy() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/hierarchy/"); + } + + @TestMetadata("inlineClass") + public void testInlineClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/inlineClass/"); + } + + @TestMetadata("inlineClass2") + public void testInlineClass2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/inlineClass2/"); + } + + @TestMetadata("innerClassWithTypeParam") + public void testInnerClassWithTypeParam() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/innerClassWithTypeParam/"); + } + + @TestMetadata("innerClassWithTypeParam2") + public void testInnerClassWithTypeParam2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/innerClassWithTypeParam2/"); + } + + @TestMetadata("innerEnum") + public void testInnerEnum() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/innerEnum/"); + } + + @TestMetadata("memberFunctionAndNestedClass") + public void testMemberFunctionAndNestedClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/memberFunctionAndNestedClass/"); + } + + @TestMetadata("nestedClass") + public void testNestedClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/nestedClass/"); + } + + @TestMetadata("noAccessOnMember") + public void testNoAccessOnMember() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/noAccessOnMember/"); + } + + @TestMetadata("onMember") + public void testOnMember() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/onMember/"); + } + + @TestMetadata("primaryConstructor") + public void testPrimaryConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/primaryConstructor/"); + } + + @TestMetadata("property") + public void testProperty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/property/"); + } + + @TestMetadata("property2") + public void testProperty2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/property2/"); + } + + @TestMetadata("propertyInConstructor") + public void testPropertyInConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/propertyInConstructor/"); + } + + @TestMetadata("propertyWithConstModifier") + public void testPropertyWithConstModifier() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/propertyWithConstModifier/"); + } + + @TestMetadata("propertyWithLateinitModifier") + public void testPropertyWithLateinitModifier() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/propertyWithLateinitModifier/"); + } + + @TestMetadata("propertyWithPrivateModifier") + public void testPropertyWithPrivateModifier() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/propertyWithPrivateModifier/"); + } + + @TestMetadata("sealedClass") + public void testSealedClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/sealedClass/"); + } + + @TestMetadata("stdlibWithJavaAlias") + public void testStdlibWithJavaAlias() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/stdlibWithJavaAlias/"); + } + + @TestMetadata("superTypeFromStdlib") + public void testSuperTypeFromStdlib() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/superTypeFromStdlib/"); + } + + @TestMetadata("topLevelFunctionWithAnnotations") + public void testTopLevelFunctionWithAnnotations() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/topLevelFunctionWithAnnotations/"); + } + + @TestMetadata("topLevelPropertyWithTypeParam") + public void testTopLevelPropertyWithTypeParam() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/topLevelPropertyWithTypeParam/"); + } + + @TestMetadata("typeAlias") + public void testTypeAlias() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/typeAlias/"); + } + + @TestMetadata("withAliases") + public void testWithAliases() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/withAliases/"); + } + + @TestMetadata("withAnnotations") + public void testWithAnnotations() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/withAnnotations/"); + } + + @TestMetadata("withConstructorWithParametersWithoutValVar") + public void testWithConstructorWithParametersWithoutValVar() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/withConstructorWithParametersWithoutValVar/"); + } + + @TestMetadata("withInitializer") + public void testWithInitializer() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/withInitializer/"); + } + + @TestMetadata("withPlatformNested") + public void testWithPlatformNested() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/withPlatformNested/"); + } + + @TestMetadata("withRootPackage") + public void testWithRootPackage() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/withRootPackage/"); + } + + @TestMetadata("withSecondaryConstructor") + public void testWithSecondaryConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/withSecondaryConstructor/"); + } + + @TestMetadata("withSecondaryConstructor2") + public void testWithSecondaryConstructor2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/withSecondaryConstructor2/"); + } + + @TestMetadata("withSupertype") + public void testWithSupertype() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/withSupertype/"); + } + + @TestMetadata("withVararg") + public void testWithVararg() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/createExpect/withVararg/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/fixNativeThrowsErrors") + public static class FixNativeThrowsErrors extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("addCancellationException1") + public void testAddCancellationException1() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/fixNativeThrowsErrors/addCancellationException1/"); + } + + @TestMetadata("addCancellationException2") + public void testAddCancellationException2() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/fixNativeThrowsErrors/addCancellationException2/"); + } + + @TestMetadata("addCancellationException3") + public void testAddCancellationException3() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/fixNativeThrowsErrors/addCancellationException3/"); + } + + @TestMetadata("addCancellationException4") + public void testAddCancellationException4() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/fixNativeThrowsErrors/addCancellationException4/"); + } + + @TestMetadata("removeEmptyThrows") + public void testRemoveEmptyThrows() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/fixNativeThrowsErrors/removeEmptyThrows/"); + } + + @TestMetadata("removeThrowsOnIncompatibleOverride") + public void testRemoveThrowsOnIncompatibleOverride() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/fixNativeThrowsErrors/removeThrowsOnIncompatibleOverride/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter") + public static class FunctionTypeReceiverToParameter extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("classFunctionConstructor") + public void testClassFunctionConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter/classFunctionConstructor/"); + } + + @TestMetadata("classFunctionParameter") + public void testClassFunctionParameter() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter/classFunctionParameter/"); + } + + @TestMetadata("classFunctionReturn") + public void testClassFunctionReturn() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter/classFunctionReturn/"); + } + + @TestMetadata("classProperty") + public void testClassProperty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter/classProperty/"); + } + + @TestMetadata("functionParameter") + public void testFunctionParameter() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter/functionParameter/"); + } + + @TestMetadata("functionReturn") + public void testFunctionReturn() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter/functionReturn/"); + } + + @TestMetadata("interfaceFunctionParameter") + public void testInterfaceFunctionParameter() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter/interfaceFunctionParameter/"); + } + + @TestMetadata("interfaceFunctionReturn") + public void testInterfaceFunctionReturn() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter/interfaceFunctionReturn/"); + } + + @TestMetadata("interfaceProperty") + public void testInterfaceProperty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter/interfaceProperty/"); + } + + @TestMetadata("property") + public void testProperty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/functionTypeReceiverToParameter/property/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/initializeProperty") + public static class InitializeProperty extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("notInitializeNonActualParameterWithConstructorParameter") + public void testNotInitializeNonActualParameterWithConstructorParameter() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/initializeProperty/notInitializeNonActualParameterWithConstructorParameter/"); + } + + @TestMetadata("notInitializeWithConstructorParameter") + public void testNotInitializeWithConstructorParameter() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/initializeProperty/notInitializeWithConstructorParameter/"); + } + + @TestMetadata("notMoveNonActualParamterToActualConstructor") + public void testNotMoveNonActualParamterToActualConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/initializeProperty/notMoveNonActualParamterToActualConstructor/"); + } + + @TestMetadata("notMoveToActualConstructor") + public void testNotMoveToActualConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/initializeProperty/notMoveToActualConstructor/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/inlineToValue") + public static class InlineToValue extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("commonWithJvm") + public void testCommonWithJvm() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/inlineToValue/commonWithJvm/"); + } + + @TestMetadata("genericParameter") + public void testGenericParameter() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/inlineToValue/genericParameter/"); + } + + @TestMetadata("JS") + public void testJS() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/inlineToValue/JS/"); + } + + @TestMetadata("JVM") + public void testJVM() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/inlineToValue/JVM/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/makeOverridenMemberOpen") + public static class MakeOverridenMemberOpen extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("actual") + public void testActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/makeOverridenMemberOpen/actual/"); + } + + @TestMetadata("expect") + public void testExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/makeOverridenMemberOpen/expect/"); + } + + @TestMetadata("hasAbstract") + public void testHasAbstract() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/makeOverridenMemberOpen/hasAbstract/"); + } + + @TestMetadata("hasOpen") + public void testHasOpen() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/makeOverridenMemberOpen/hasOpen/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/other") + public static class Other extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("actualImplementAsConstructorParam") + public void testActualImplementAsConstructorParam() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/actualImplementAsConstructorParam/"); + } + + @TestMetadata("actualNoImplementAsConstructorParam") + public void testActualNoImplementAsConstructorParam() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/actualNoImplementAsConstructorParam/"); + } + + @TestMetadata("actualWithoutExpect") + public void testActualWithoutExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/actualWithoutExpect/"); + } + + @TestMetadata("addActualToClass") + public void testAddActualToClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/addActualToClass/"); + } + + @TestMetadata("addActualToClassMember") + public void testAddActualToClassMember() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/addActualToClassMember/"); + } + + @TestMetadata("addActualToTopLevelMember") + public void testAddActualToTopLevelMember() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/addActualToTopLevelMember/"); + } + + @TestMetadata("addAnnotationTargetToActual") + public void testAddAnnotationTargetToActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/addAnnotationTargetToActual/"); + } + + @TestMetadata("addAnnotationTargetToExpect") + public void testAddAnnotationTargetToExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/addAnnotationTargetToExpect/"); + } + + @TestMetadata("addFunctionToCommonClassFromJavaUsage") + public void testAddFunctionToCommonClassFromJavaUsage() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/addFunctionToCommonClassFromJavaUsage/"); + } + + @TestMetadata("addOperatorByActual") + public void testAddOperatorByActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/addOperatorByActual/"); + } + + @TestMetadata("addOperatorByExpect") + public void testAddOperatorByExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/addOperatorByExpect/"); + } + + @TestMetadata("cancelMakeAbstractFromActual") + public void testCancelMakeAbstractFromActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/cancelMakeAbstractFromActual/"); + } + + @TestMetadata("convertActualEnumToSealedClass") + public void testConvertActualEnumToSealedClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/convertActualEnumToSealedClass/"); + } + + @TestMetadata("convertActualSealedClassToEnum") + public void testConvertActualSealedClassToEnum() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/convertActualSealedClassToEnum/"); + } + + @TestMetadata("convertExpectEnumToSealedClass") + public void testConvertExpectEnumToSealedClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/convertExpectEnumToSealedClass/"); + } + + @TestMetadata("convertExpectSealedClassToEnum") + public void testConvertExpectSealedClassToEnum() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/convertExpectSealedClassToEnum/"); + } + + @TestMetadata("convertPropertyGetterToInitializer") + public void testConvertPropertyGetterToInitializer() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/convertPropertyGetterToInitializer/"); + } + + @TestMetadata("convertPropertyToFunction") + public void testConvertPropertyToFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/convertPropertyToFunction/"); + } + + @TestMetadata("createClassFromUsageImport") + public void testCreateClassFromUsageImport() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/createClassFromUsageImport/"); + } + + @TestMetadata("createClassFromUsageRef") + public void testCreateClassFromUsageRef() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/createClassFromUsageRef/"); + } + + @TestMetadata("createFunInExpectClass") + public void testCreateFunInExpectClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/createFunInExpectClass/"); + } + + @TestMetadata("createTestOnExpect") + public void testCreateTestOnExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/createTestOnExpect/"); + } + + @TestMetadata("createValInExpectClass") + public void testCreateValInExpectClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/createValInExpectClass/"); + } + + @TestMetadata("createVarInExpectClass") + public void testCreateVarInExpectClass() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/createVarInExpectClass/"); + } + + @TestMetadata("deprecatedHeader") + public void testDeprecatedHeader() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/deprecatedHeader/"); + } + + @TestMetadata("deprecatedHeaderImpl") + public void testDeprecatedHeaderImpl() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/deprecatedHeaderImpl/"); + } + + @TestMetadata("deprecatedImpl") + public void testDeprecatedImpl() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/deprecatedImpl/"); + } + + @TestMetadata("deprecatedImplHeader") + public void testDeprecatedImplHeader() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/deprecatedImplHeader/"); + } + + @TestMetadata("functionTypeParameterToReceiverByHeader") + public void testFunctionTypeParameterToReceiverByHeader() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/functionTypeParameterToReceiverByHeader/"); + } + + @TestMetadata("functionTypeParameterToReceiverByImpl") + public void testFunctionTypeParameterToReceiverByImpl() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/functionTypeParameterToReceiverByImpl/"); + } + + @TestMetadata("functionTypeReceiverToParameterByHeader") + public void testFunctionTypeReceiverToParameterByHeader() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/functionTypeReceiverToParameterByHeader/"); + } + + @TestMetadata("functionTypeReceiverToParameterByImpl") + public void testFunctionTypeReceiverToParameterByImpl() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/functionTypeReceiverToParameterByImpl/"); + } + + @TestMetadata("generateEqualsInExpect") + public void testGenerateEqualsInExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/generateEqualsInExpect/"); + } + + @TestMetadata("generateHashCodeInExpect") + public void testGenerateHashCodeInExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/generateHashCodeInExpect/"); + } + + @TestMetadata("implementAbstractExpectMemberInheritedFromInterface") + public void testImplementAbstractExpectMemberInheritedFromInterface() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/implementAbstractExpectMemberInheritedFromInterface/"); + } + + @TestMetadata("implementMembersInActualClassNoExpectMember") + public void testImplementMembersInActualClassNoExpectMember() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/implementMembersInActualClassNoExpectMember/"); + } + + @TestMetadata("implementMembersInImplClassNonImplInheritor") + public void testImplementMembersInImplClassNonImplInheritor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/implementMembersInImplClassNonImplInheritor/"); + } + + @TestMetadata("importClassInCommon") + public void testImportClassInCommon() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/importClassInCommon/"); + } + + @TestMetadata("importClassInFromProductionInCommonTests") + public void testImportClassInFromProductionInCommonTests() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/importClassInFromProductionInCommonTests/"); + } + + @TestMetadata("importCommonClassInJs") + public void testImportCommonClassInJs() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/importCommonClassInJs/"); + } + + @TestMetadata("importCommonClassInJvm") + public void testImportCommonClassInJvm() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/importCommonClassInJvm/"); + } + + @TestMetadata("importCommonFunInJvm") + public void testImportCommonFunInJvm() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/importCommonFunInJvm/"); + } + + @TestMetadata("importExpectClassWithActualInJvm") + public void testImportExpectClassWithActualInJvm() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/importExpectClassWithActualInJvm/"); + } + + @TestMetadata("importExpectClassWithoutActualInJvm") + public void testImportExpectClassWithoutActualInJvm() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/importExpectClassWithoutActualInJvm/"); + } + + @TestMetadata("importFunInCommon") + public void testImportFunInCommon() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/importFunInCommon/"); + } + + @TestMetadata("makeAbstractFromActual") + public void testMakeAbstractFromActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/makeAbstractFromActual/"); + } + + @TestMetadata("makeInlineFromExpect") + public void testMakeInlineFromExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/makeInlineFromExpect/"); + } + + @TestMetadata("makeInternalFromExpect") + public void testMakeInternalFromExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/makeInternalFromExpect/"); + } + + @TestMetadata("makeOpenFromActual") + public void testMakeOpenFromActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/makeOpenFromActual/"); + } + + @TestMetadata("makeOpenFromExpect") + public void testMakeOpenFromExpect() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/makeOpenFromExpect/"); + } + + @TestMetadata("mayBeConstantWithActual") + public void testMayBeConstantWithActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/mayBeConstantWithActual/"); + } + + @TestMetadata("memberFunParameterToReceiverByHeader") + public void testMemberFunParameterToReceiverByHeader() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/memberFunParameterToReceiverByHeader/"); + } + + @TestMetadata("memberFunParameterToReceiverByImpl") + public void testMemberFunParameterToReceiverByImpl() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/memberFunParameterToReceiverByImpl/"); + } + + @TestMetadata("memberFunReceiverToParameterByHeader") + public void testMemberFunReceiverToParameterByHeader() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/memberFunReceiverToParameterByHeader/"); + } + + @TestMetadata("memberFunReceiverToParameterByImpl") + public void testMemberFunReceiverToParameterByImpl() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/memberFunReceiverToParameterByImpl/"); + } + + @TestMetadata("memberFunToExtensionByHeader") + public void testMemberFunToExtensionByHeader() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/memberFunToExtensionByHeader/"); + } + + @TestMetadata("memberFunToExtensionByImpl") + public void testMemberFunToExtensionByImpl() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/memberFunToExtensionByImpl/"); + } + + @TestMetadata("memberValToExtensionByHeader") + public void testMemberValToExtensionByHeader() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/memberValToExtensionByHeader/"); + } + + @TestMetadata("memberValToExtensionByHeaderWithInapplicableImpl") + public void testMemberValToExtensionByHeaderWithInapplicableImpl() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/memberValToExtensionByHeaderWithInapplicableImpl/"); + } + + @TestMetadata("memberValToExtensionByImpl") + public void testMemberValToExtensionByImpl() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/memberValToExtensionByImpl/"); + } + + @TestMetadata("moveActualPropertyToExistentConstructor") + public void testMoveActualPropertyToExistentConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/moveActualPropertyToExistentConstructor/"); + } + + @TestMetadata("movePropertyToConstructor") + public void testMovePropertyToConstructor() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/movePropertyToConstructor/"); + } + + @TestMetadata("notMakeAbstractFromActual") + public void testNotMakeAbstractFromActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/notMakeAbstractFromActual/"); + } + + @TestMetadata("orderHeader") + public void testOrderHeader() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/orderHeader/"); + } + + @TestMetadata("orderImpl") + public void testOrderImpl() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/orderImpl/"); + } + + @TestMetadata("safeDeleteForbiddenFromActual") + public void testSafeDeleteForbiddenFromActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/safeDeleteForbiddenFromActual/"); + } + + @TestMetadata("safeDeleteFromActual") + public void testSafeDeleteFromActual() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/safeDeleteFromActual/"); + } + + @TestMetadata("safeDeleteUsedInAnotherPlatform") + public void testSafeDeleteUsedInAnotherPlatform() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/other/safeDeleteUsedInAnotherPlatform/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/packageDirectoryMismatch") + public static class PackageDirectoryMismatch extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("moveFileToAnotherPackage") + public void testMoveFileToAnotherPackage() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/packageDirectoryMismatch/moveFileToAnotherPackage/"); + } + + @TestMetadata("moveFileToCommonSourceRoot") + public void testMoveFileToCommonSourceRoot() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/packageDirectoryMismatch/moveFileToCommonSourceRoot/"); + } + + @TestMetadata("moveFileToJvmSourceRoot") + public void testMoveFileToJvmSourceRoot() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/packageDirectoryMismatch/moveFileToJvmSourceRoot/"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../idea/tests/testData/multiModuleQuickFix/redundantNullableReturnType") + public static class RedundantNullableReturnType extends AbstractHighLevelQuickFixMultiModuleTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("actualMethod") + public void testActualMethod() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/redundantNullableReturnType/actualMethod/"); + } + + @TestMetadata("actualTopLevelFunction") + public void testActualTopLevelFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/redundantNullableReturnType/actualTopLevelFunction/"); + } + + @TestMetadata("actualTopLevelProperty") + public void testActualTopLevelProperty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/redundantNullableReturnType/actualTopLevelProperty/"); + } + + @TestMetadata("expectMemberProperty") + public void testExpectMemberProperty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/redundantNullableReturnType/expectMemberProperty/"); + } + + @TestMetadata("expectTopLevelFunction") + public void testExpectTopLevelFunction() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/redundantNullableReturnType/expectTopLevelFunction/"); + } + + @TestMetadata("expectTopLevelProperty") + public void testExpectTopLevelProperty() throws Exception { + runTest("../idea/tests/testData/multiModuleQuickFix/redundantNullableReturnType/expectTopLevelProperty/"); + } + } +} diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractFirInLibraryResolveEverythingTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractFirInLibraryResolveEverythingTest.kt new file mode 100644 index 000000000000..3abfd396fc75 --- /dev/null +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractFirInLibraryResolveEverythingTest.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.fir.resolve + +import com.intellij.extapi.psi.StubBasedPsiElementBase +import com.intellij.psi.stubs.StubElement +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.util.ThrowableRunnable +import org.jetbrains.kotlin.idea.fir.invalidateCaches +import org.jetbrains.kotlin.idea.test.* +import org.jetbrains.kotlin.psi.KtElement +import java.io.File + +abstract class AbstractFirInLibraryResolveEverythingTest : KotlinLightCodeInsightFixtureTestCase() { + private val mockLibraryFacility = MockLibraryFacility( + source = IDEA_TEST_DATA_DIR.resolve("resolve/compiled/_library"), + attachSources = false + ) + + override fun isFirPlugin(): Boolean { + return true + } + + override fun getProjectDescriptor(): LightProjectDescriptor = + KotlinWithJdkAndRuntimeLightProjectDescriptor.getInstance() + + override fun setUp() { + super.setUp() + mockLibraryFacility.setUp(module) + } + + fun doTest(filePath: String) { + myFixture.configureByFile(filePath) + val resolve = myFixture.getReferenceAtCaretPosition()!!.resolve() as KtElement + val ktFileStub = resolve.containingKtFile.stub!! + val builder = StringBuilder() + checkStubs(ktFileStub, builder) + KotlinTestUtils.assertEqualsToFile(File("$filePath.txt"), builder.toString()) + } + + private fun checkStubs(stubElement: StubElement<*>, builder: StringBuilder) { + stubElement.childrenStubs.forEach { stub -> + val psi = stub.psi as StubBasedPsiElementBase<*> + val reference = psi.reference + val resolve = reference?.resolve() + if (resolve != null) { + builder.append(resolve.toString()).append("\n") + } + assertNotNull(psi.stub) + checkStubs(stub, builder) + } + } + + override fun tearDown() { + runAll( + ThrowableRunnable { project.invalidateCaches() }, + ThrowableRunnable { mockLibraryFacility.tearDown(module) }, + ThrowableRunnable { super.tearDown() } + ) + } +} diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/FirInLibraryResolveEverythingTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/FirInLibraryResolveEverythingTestGenerated.java new file mode 100644 index 000000000000..378e20697801 --- /dev/null +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/FirInLibraryResolveEverythingTestGenerated.java @@ -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.resolve; + +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("fir") +@TestDataPath("$CONTENT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +@TestMetadata("../idea/tests/testData/resolve/compiled/sources") +public class FirInLibraryResolveEverythingTestGenerated extends AbstractFirInLibraryResolveEverythingTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("QualifiedParts.kt") + public void testQualifiedParts() throws Exception { + runTest("../idea/tests/testData/resolve/compiled/sources/QualifiedParts.kt"); + } +} diff --git a/plugins/kotlin/fir/testData/quickDoc/DecompiledSuper.kt b/plugins/kotlin/fir/testData/quickDoc/DecompiledSuper.kt new file mode 100644 index 000000000000..df5607549ed9 --- /dev/null +++ b/plugins/kotlin/fir/testData/quickDoc/DecompiledSuper.kt @@ -0,0 +1,7 @@ +enum class C : List<*> { +} +fun f() { + C.values() +} + +//INFO:
enum class C : List<*>
 DecompiledSuper.kt
diff --git a/plugins/kotlin/frontend-independent/kotlin.fir.frontend-independent.iml b/plugins/kotlin/frontend-independent/kotlin.fir.frontend-independent.iml index 67e2238eab9a..bb7a55b7c09d 100644 --- a/plugins/kotlin/frontend-independent/kotlin.fir.frontend-independent.iml +++ b/plugins/kotlin/frontend-independent/kotlin.fir.frontend-independent.iml @@ -30,5 +30,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/actions/KotlinAddImportActionInfo.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/actions/KotlinAddImportActionInfo.kt new file mode 100644 index 000000000000..45e0c3e8b111 --- /dev/null +++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/actions/KotlinAddImportActionInfo.kt @@ -0,0 +1,24 @@ +// 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.actions + +import com.intellij.openapi.Disposable +import com.intellij.openapi.util.Disposer +import org.jetbrains.annotations.TestOnly +import org.jetbrains.kotlin.idea.quickfix.AutoImportVariant + +/** Test hooks allowing inspection of data used for KotlinAddImportAction. **/ +object KotlinAddImportActionInfo { + interface ExecuteListener { + fun onExecute(variants: List) + } + + @Volatile + var executeListener: ExecuteListener? = null + + @TestOnly + fun setExecuteListener(disposable: Disposable, listener: ExecuteListener) { + assert(executeListener == null) + executeListener = listener + Disposer.register(disposable) { executeListener = null } + } +} \ No newline at end of file diff --git a/plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/ImportableFqNameClassifier.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/base/utils/fqname/ImportableFqNameClassifier.kt similarity index 90% rename from plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/ImportableFqNameClassifier.kt rename to plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/base/utils/fqname/ImportableFqNameClassifier.kt index 9b642183dc6f..be37aa770e84 100644 --- a/plugins/kotlin/completion/impl-shared/src/org/jetbrains/kotlin/idea/completion/implCommon/ImportableFqNameClassifier.kt +++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/base/utils/fqname/ImportableFqNameClassifier.kt @@ -1,9 +1,6 @@ -/* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ +// 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 +package org.jetbrains.kotlin.idea.base.utils.fqname import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/base/utils/fqname/fqNameUtil.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/base/utils/fqname/fqNameUtil.kt index a57a2cbb7981..e444126e9d4d 100644 --- a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/base/utils/fqname/fqNameUtil.kt +++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/base/utils/fqname/fqNameUtil.kt @@ -57,3 +57,6 @@ val KotlinType.fqName: FqName? is AbbreviatedType -> abbreviation.fqName else -> constructor.declarationDescriptor?.fqNameOrNull() } + +fun FqName.isJavaClassNotToBeUsedInKotlin(): Boolean = + JavaToKotlinClassMap.isJavaPlatformClass(this) || this in javaToKotlinNameMap \ No newline at end of file diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AutoImportVariant.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AutoImportVariant.kt new file mode 100644 index 000000000000..a9887ea2a6be --- /dev/null +++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AutoImportVariant.kt @@ -0,0 +1,15 @@ +// 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.quickfix + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.name.FqName +import javax.swing.Icon + +interface AutoImportVariant { + val hint: String + val icon: Icon? + val declarationToImport: PsiElement? + val fqName: FqName + + val debugRepresentation: String +} \ No newline at end of file diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/ImportFixHelper.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/ImportFixHelper.kt new file mode 100644 index 000000000000..abb5b5abe1fd --- /dev/null +++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/ImportFixHelper.kt @@ -0,0 +1,179 @@ +// 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.quickfix + +import com.intellij.codeInsight.daemon.impl.actions.AddImportAction +import com.intellij.codeInspection.util.IntentionName +import com.intellij.ide.util.DefaultPsiElementCellRenderer +import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.ui.popup.JBPopupFactory +import com.intellij.openapi.ui.popup.ListPopup +import com.intellij.openapi.ui.popup.PopupStep +import com.intellij.openapi.ui.popup.util.BaseListPopupStep +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.idea.base.resources.KotlinBundle +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.parentOrNull +import java.awt.BorderLayout +import java.util.* +import javax.swing.JPanel +import javax.swing.ListCellRenderer + +object ImportFixHelper { + enum class ImportKind(private val key: String, val groupedByPackage: Boolean = false) { + CLASS("text.class.0", true), + PROPERTY("text.property.0"), + OBJECT("text.object.0", true), + FUNCTION("text.function.0"), + EXTENSION_PROPERTY("text.extension.property.0"), + EXTENSION_FUNCTION("text.extension.function.0"), + OPERATOR("text.operator.0"); + + fun toText(number: Int) = KotlinBundle.message(key, if (number == 1) 1 else 2) + } + + class ImportInfo>(val kind: ImportKind, val name: String, val priority: T) + + @IntentionName + fun > calculateTextForFix(importInfos: Iterable>, suggestions: Iterable): String { + val importNamesGroupedByKind = importInfos.groupBy(keySelector = { it.kind }) { it } + + return if (importNamesGroupedByKind.size == 1) { + val (kind, names) = importNamesGroupedByKind.entries.first() + val sortedImportInfos = TreeSet>(compareBy({ it.priority }, { it.name })) + sortedImportInfos.addAll(names) + val firstName = sortedImportInfos.first().name + val singlePackage = suggestions.groupBy { it.parentOrNull() ?: FqName.ROOT }.size == 1 + + if (singlePackage) { + val sortedByName = sortedImportInfos.toSortedSet(compareBy { it.name }) + val size = sortedByName.size + if (size == 2) { + KotlinBundle.message( + "fix.import.kind.0.name.1.and.name.2", + kind.toText(size), + sortedByName.first().name, + sortedByName.last().name + ) + } else { + KotlinBundle.message("fix.import.kind.0.name.1.2", kind.toText(size), firstName, size - 1) + } + } else if (kind.groupedByPackage) { + KotlinBundle.message("fix.import.kind.0.name.1.2", kind.toText(1), firstName, 0) + } else { + val groupBy = sortedImportInfos.map { it.name }.toSortedSet().groupBy { it.substringBefore('.') } + val value = groupBy.entries.first().value + val first = value.first() + val multiple = if (value.size == 1) 0 else 1 + when { + groupBy.size != 1 -> KotlinBundle.message( + "fix.import.kind.0.name.1.2", + kind.toText(1), + first.substringAfter('.'), + multiple + ) + + value.size == 2 -> KotlinBundle.message( + "fix.import.kind.0.name.1.and.name.2", + kind.toText(value.size), + first, + value.last() + ) + + else -> KotlinBundle.message("fix.import.kind.0.name.1.2", kind.toText(1), first, multiple) + } + } + } else { + KotlinBundle.message("fix.import") + } + } + + fun calculateWeightBasedOnFqName(fqName: FqName, sourceDeclaration: PsiElement?): Int { + val fqNameString = fqName.asString() + return when { + /** + * package rating calculation rule: + * - (highest) current project source + * - `kotlin.` and `kotlinx.` + * - `java.` + * - (lowest) all other 3rd party libs + */ + fqNameString.startsWith("kotlin.") -> 6 + fqNameString.startsWith("kotlinx.") -> 5 + fqNameString.startsWith("java.") -> 2 + sourceDeclaration != null -> { + val virtualFile = sourceDeclaration.containingFile?.virtualFile + val fileIndex = ProjectRootManager.getInstance(sourceDeclaration.project).fileIndex + // project source higher than libs + if (virtualFile != null && fileIndex.isInSourceContent(virtualFile)) 7 else 0 + } + + else -> 0 + } + } + + fun createListPopupWithImportVariants( + project: Project, + variants: List, + addImport: (AutoImportVariant) -> Unit, + ): ListPopup = + JBPopupFactory.getInstance().createListPopup(project, getVariantSelectionPopup(project, variants, addImport)) { + val psiRenderer = DefaultPsiElementCellRenderer() + + ListCellRenderer { list, value, index, isSelected, cellHasFocus -> + JPanel(BorderLayout()).apply { + add( + psiRenderer.getListCellRendererComponent( + list, + value.declarationToImport, + index, + isSelected, + cellHasFocus + ) + ) + } + } + } + + private fun getVariantSelectionPopup( + project: Project, + variants: List, + addImport: (AutoImportVariant) -> Unit, + ): BaseListPopupStep { + return object : BaseListPopupStep(KotlinBundle.message("action.add.import.chooser.title"), variants) { + override fun isAutoSelectionEnabled(): Boolean = false + + override fun isSpeedSearchEnabled(): Boolean = true + + override fun onChosen(selectedValue: AutoImportVariant?, finalChoice: Boolean): PopupStep? { + if (selectedValue == null || project.isDisposed) return null + + if (finalChoice) { + addImport(selectedValue) + return null + } + + val toExclude = AddImportAction.getAllExcludableStrings(selectedValue.fqName.asString()) + + return object : BaseListPopupStep(null, toExclude) { + override fun getTextFor(value: String): String { + return KotlinBundle.message("fix.import.exclude", value) + } + + override fun onChosen(selectedValue: String, finalChoice: Boolean): PopupStep? { + if (finalChoice && !project.isDisposed) { + AddImportAction.excludeFromImport(project, selectedValue) + } + return null + } + } + } + + override fun hasSubstep(selectedValue: AutoImportVariant?) = true + override fun getTextFor(value: AutoImportVariant) = value.hint + override fun getIconFor(value: AutoImportVariant) = value.icon + } + } +} + + diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/ImportPrioritizer.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/ImportPrioritizer.kt new file mode 100644 index 000000000000..8ec0ce2182d9 --- /dev/null +++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/ImportPrioritizer.kt @@ -0,0 +1,82 @@ +// 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.quickfix + +import com.intellij.psi.PsiElement +import com.intellij.psi.WeighingComparable +import com.intellij.psi.WeighingService +import com.intellij.psi.statistics.StatisticsInfo +import com.intellij.psi.statistics.StatisticsManager +import com.intellij.psi.util.ProximityLocation +import com.intellij.psi.util.proximity.PsiProximityComparator +import org.jetbrains.kotlin.idea.base.util.module +import org.jetbrains.kotlin.idea.base.utils.fqname.ImportableFqNameClassifier +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtFile + +interface ImportComparablePriority : Comparable + +class ImportPrioritizer( + val file: KtFile, + isImportedByDefault: (FqName) -> Boolean, + private val compareNames: Boolean = true +) { + private val classifier = ImportableFqNameClassifier(file, isImportedByDefault) + private val statsManager = StatisticsManager.getInstance() + private val proximityLocation = ProximityLocation(file, file.module) + + inner class Priority( + declaration: PsiElement?, + val statisticsInfo: StatisticsInfo, + private val isDeprecated: Boolean, + private val fqName: FqName, + private val expressionWeight: Int, + ) : ImportComparablePriority { + private val classification: ImportableFqNameClassifier.Classification = classifier.classify(fqName, false) + private val lastUseRecency: Int = statsManager.getLastUseRecency(statisticsInfo) + private val proximityWeight: WeighingComparable = + WeighingService.weigh(PsiProximityComparator.WEIGHER_KEY, declaration, proximityLocation) + + override fun compareTo(other: ImportComparablePriority): Int { + other as Priority + + if (isDeprecated != other.isDeprecated) { + return if (isDeprecated) +1 else -1 + } + + val c1 = expressionWeight.compareTo(other.expressionWeight) + if (c1 != 0) { + // callExpressionWeigh is non-negative number + // Comparator contract says that if `a.compareTo(b)` returns -1 then `a` appears earlier than `b` + return -c1 + } + + val c2 = classification.compareTo(other.classification) + if (c2 != 0) return c2 + + val c3 = lastUseRecency.compareTo(other.lastUseRecency) + if (c3 != 0) return c3 + + val c4 = proximityWeight.compareTo(other.proximityWeight) + if (c4 != 0) return -c4 // n.b. reversed + + return if (compareNames) { + fqName.asString().compareTo(other.fqName.asString()) + } else { + 0 + } + } + } + + inner class GroupPriority(private val priorities: List) : ImportComparablePriority { + private val groupPriority = priorities.max() + + override fun compareTo(other: ImportComparablePriority): Int { + other as GroupPriority + + val c1 = groupPriority.compareTo(other.groupPriority) + if (c1 != 0) return c1 + + return other.priorities.size - priorities.size + } + } +} \ No newline at end of file diff --git a/plugins/kotlin/gradle/gradle-java/tests/test/org/jetbrains/kotlin/idea/codeInsight/gradle/ConversionToKotlinTest.kt b/plugins/kotlin/gradle/gradle-java/tests/test/org/jetbrains/kotlin/idea/codeInsight/gradle/ConversionToKotlinTest.kt index 336121b25562..a1e91a7af9e3 100644 --- a/plugins/kotlin/gradle/gradle-java/tests/test/org/jetbrains/kotlin/idea/codeInsight/gradle/ConversionToKotlinTest.kt +++ b/plugins/kotlin/gradle/gradle-java/tests/test/org/jetbrains/kotlin/idea/codeInsight/gradle/ConversionToKotlinTest.kt @@ -25,7 +25,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule), @@ -50,7 +50,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule), @@ -75,7 +75,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), @@ -98,7 +98,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), @@ -121,7 +121,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), @@ -144,7 +144,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule), @@ -169,7 +169,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule), @@ -194,7 +194,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule), @@ -220,7 +220,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule, rootModule), @@ -246,7 +246,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule, rootModule), @@ -271,7 +271,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule), @@ -296,7 +296,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule), @@ -321,7 +321,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), @@ -344,7 +344,7 @@ class ConversionToKotlinTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), diff --git a/plugins/kotlin/gradle/gradle-java/tests/test/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleConfiguratorTest.kt b/plugins/kotlin/gradle/gradle-java/tests/test/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleConfiguratorTest.kt index 5593d1f644ac..f77ce7d8b4b8 100644 --- a/plugins/kotlin/gradle/gradle-java/tests/test/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleConfiguratorTest.kt +++ b/plugins/kotlin/gradle/gradle-java/tests/test/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleConfiguratorTest.kt @@ -156,7 +156,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -180,7 +180,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -203,7 +203,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -226,7 +226,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -250,7 +250,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -274,7 +274,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -298,7 +298,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -322,7 +322,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -346,7 +346,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -370,7 +370,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -395,7 +395,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule, subModule), @@ -421,7 +421,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule, subModule), @@ -446,7 +446,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), @@ -471,7 +471,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), @@ -496,7 +496,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule), @@ -521,7 +521,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val subModule = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(subModule), @@ -549,7 +549,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project.app")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -571,7 +571,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val module = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(module), @@ -1090,7 +1090,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), @@ -1113,7 +1113,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), @@ -1136,7 +1136,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), @@ -1159,7 +1159,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), @@ -1182,7 +1182,7 @@ class GradleConfiguratorTest : KotlinGradleImportingTestCase() { val rootModule = ModuleManager.getInstance(myProject).findModuleByName("project")!! val configurator = findGradleModuleConfigurator() val collector = NotificationMessageCollector.create(myProject) - val kotlinVersionsAndModules = getKotlinVersionsAndModules(myProject, configurator) + val (kotlinVersionsAndModules, rootModuleKotlinVersion) = getKotlinVersionsAndModules(myProject, configurator) configurator.configureWithVersion( myProject, listOf(rootModule), diff --git a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java b/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java index 50dc8c468e0b..93c351f26fd2 100644 --- a/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java +++ b/plugins/kotlin/highlighting/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightingMetaInfoTestGenerated.java @@ -19,6 +19,29 @@ import org.junit.runner.RunWith; @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../idea/tests/testData/highlighterMetaInfo") public abstract class K2HighlightingMetaInfoTestGenerated extends AbstractK2HighlightingMetaInfoTest { + @RunWith(JUnit3RunnerWithInners.class) + @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); + } + + @TestMetadata("classRedeclaration.kt") + public void testClassRedeclaration() throws Exception { + runTest("../idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt"); + } + + @TestMetadata("javaCodeInKotlinFile1.kt") + public void testJavaCodeInKotlinFile1() throws Exception { + runTest("../idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt"); + } + + @TestMetadata("mppIsNotEnabled.kt") + public void testMppIsNotEnabled() throws Exception { + runTest("../idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../idea/tests/testData/highlighterMetaInfo/dsl") public static class Dsl extends AbstractK2HighlightingMetaInfoTest { diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/KotlinDocumentationProvider.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/KotlinDocumentationProvider.kt index 956c968abffe..f55131d30edc 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/KotlinDocumentationProvider.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/KotlinDocumentationProvider.kt @@ -28,6 +28,7 @@ import com.intellij.util.io.HttpRequests import org.jetbrains.annotations.Nls import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.base.util.KotlinPlatformUtils @@ -337,7 +338,7 @@ class KotlinDocumentationProvider : AbstractDocumentationProvider(), ExternalDoc @Nls private fun getTextImpl(element: PsiElement, originalElement: PsiElement?, quickNavigation: Boolean): String? { if (element is PsiWhiteSpace) { - val itElement = findElementWithText(originalElement, "it") + val itElement = findElementWithText(originalElement, StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier) val itReference = itElement?.getParentOfType(false) if (itReference != null) { return getTextImpl(itReference, originalElement, quickNavigation) @@ -377,7 +378,7 @@ class KotlinDocumentationProvider : AbstractDocumentationProvider(), ExternalDoc } } else if (element is KtDeclaration) { return renderKotlinDeclaration(element, quickNavigation) - } else if (element is KtNameReferenceExpression && element.getReferencedName() == "it") { + } else if (element is KtNameReferenceExpression && element.getReferencedNameAsName() == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME) { return renderKotlinImplicitLambdaParameter(element, quickNavigation) } else if (element is KtLightDeclaration<*, *>) { val origin = element.kotlinOrigin ?: return null diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/ExpressionWeigher.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/ExpressionWeigher.kt index 9db14e92a9f5..3751b0bddf3d 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/ExpressionWeigher.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/ExpressionWeigher.kt @@ -1,7 +1,6 @@ // 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.actions -import com.intellij.openapi.roots.ProjectRootManager import com.intellij.psi.PsiElement import org.jetbrains.kotlin.backend.jvm.ir.psiElement import org.jetbrains.kotlin.descriptors.* @@ -11,6 +10,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.safeAnalyze import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.inspections.dfa.getArrayElementType import org.jetbrains.kotlin.idea.intentions.receiverType +import org.jetbrains.kotlin.idea.quickfix.ImportFixHelper import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType @@ -24,6 +24,9 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections +/** + * Implementation in K2: [org.jetbrains.kotlin.idea.quickfix.fixes.ExpressionImportWeigher] + */ internal interface ExpressionWeigher { fun weigh(descriptor: DeclarationDescriptor): Int @@ -45,28 +48,8 @@ internal object EmptyExpressionWeigher: ExpressionWeigher { internal abstract class AbstractExpressionWeigher: ExpressionWeigher { override fun weigh(descriptor: DeclarationDescriptor): Int { - val base = descriptor.importableFqName?.asString()?.let { fqName -> - when { - /** - * package rating calculation rule: - * - (highest) current project source - * - `kotlin.` and `kotlinx.` - * - `java.` - * - (lowest) all other 3rd party libs - */ - fqName.startsWith("kotlin.") -> 6 - fqName.startsWith("kotlinx.") -> 5 - fqName.startsWith("java.") -> 2 - descriptor is DeclarationDescriptorWithSource -> run { - val psiElement = descriptor.psiElement - val virtualFile = psiElement?.containingFile?.virtualFile ?: return@run 0 - val fileIndex = ProjectRootManager.getInstance(psiElement.project).fileIndex - // project source higher than libs - if (fileIndex.isInSourceContent(virtualFile)) 7 else 0 - } - - else -> 0 - } + val base = descriptor.importableFqName?.let { fqName -> + ImportFixHelper.calculateWeightBasedOnFqName(fqName, (descriptor as? DeclarationDescriptorWithSource)?.psiElement) } ?: 0 return base + ownWeigh(descriptor) diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt index 5fee1375ab9f..8ab9aac08207 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt @@ -53,7 +53,7 @@ import kotlin.io.path.notExists import kotlin.system.measureTimeMillis class JavaToKotlinAction : AnAction() { - companion object { + object Handler { private fun uniqueKotlinFileName(javaFile: VirtualFile): String { val nioFile = javaFile.fileSystem.getNioPath(javaFile) @@ -227,10 +227,24 @@ class JavaToKotlinAction : AnAction() { newFiles } } + + internal fun selectedJavaFiles(e: AnActionEvent): Sequence { + val virtualFiles = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY) ?: return sequenceOf() + val project = e.project ?: return sequenceOf() + return allJavaFiles(virtualFiles, project) + } + + private fun allJavaFiles(filesOrDirs: Array, project: Project): Sequence { + val manager = PsiManager.getInstance(project) + return getAllFilesRecursively(filesOrDirs) + .asSequence() + .mapNotNull { manager.findFile(it) as? PsiJavaFile } + .filter { it.fileType == JavaFileType.INSTANCE } // skip .jsp files + } } override fun actionPerformed(e: AnActionEvent) { - val javaFiles = selectedJavaFiles(e).filter { it.isWritable }.toList() + val javaFiles = Handler.selectedJavaFiles(e).filter { it.isWritable }.toList() val project = CommonDataKeys.PROJECT.getData(e.dataContext) ?: return val module = e.getData(PlatformCoreDataKeys.MODULE) ?: return @@ -262,7 +276,7 @@ class JavaToKotlinAction : AnAction() { if (Messages.showOkCancelDialog( project, question, - title, + Handler.title, okText, cancelText, Messages.getWarningIcon() @@ -273,7 +287,7 @@ class JavaToKotlinAction : AnAction() { } } - convertFiles(javaFiles, project, module) + Handler.convertFiles(javaFiles, project, module) } override fun getActionUpdateThread() = ActionUpdateThread.BGT @@ -309,18 +323,4 @@ class JavaToKotlinAction : AnAction() { return files.any(::isWritableJavaFile) } - - private fun selectedJavaFiles(e: AnActionEvent): Sequence { - val virtualFiles = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY) ?: return sequenceOf() - val project = e.project ?: return sequenceOf() - return allJavaFiles(virtualFiles, project) - } - - private fun allJavaFiles(filesOrDirs: Array, project: Project): Sequence { - val manager = PsiManager.getInstance(project) - return getAllFilesRecursively(filesOrDirs) - .asSequence() - .mapNotNull { manager.findFile(it) as? PsiJavaFile } - .filter { it.fileType == JavaFileType.INSTANCE } // skip .jsp files - } } \ No newline at end of file diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/KotlinAddImportAction.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/KotlinAddImportAction.kt index cabc6acfcdd9..17ff8cdff859 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/KotlinAddImportAction.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/KotlinAddImportAction.kt @@ -4,38 +4,30 @@ package org.jetbrains.kotlin.idea.actions import com.intellij.codeInsight.daemon.QuickFixBundle import com.intellij.codeInsight.daemon.impl.ShowAutoImportPass -import com.intellij.codeInsight.daemon.impl.actions.AddImportAction import com.intellij.codeInsight.hint.HintManager import com.intellij.codeInsight.hint.QuestionAction -import com.intellij.ide.util.DefaultPsiElementCellRenderer -import com.intellij.openapi.Disposable import com.intellij.openapi.application.runReadAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.popup.JBPopupFactory -import com.intellij.openapi.ui.popup.PopupStep -import com.intellij.openapi.ui.popup.util.BaseListPopupStep -import com.intellij.openapi.util.Disposer import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement -import com.intellij.psi.WeighingService import com.intellij.psi.statistics.StatisticsManager -import com.intellij.psi.util.ProximityLocation -import com.intellij.psi.util.proximity.PsiProximityComparator -import org.jetbrains.annotations.TestOnly -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.PackageViewDescriptor import org.jetbrains.kotlin.idea.KotlinDescriptorIconProvider import org.jetbrains.kotlin.idea.base.projectStructure.languageVersionSettings import org.jetbrains.kotlin.idea.base.resources.KotlinBundle -import org.jetbrains.kotlin.idea.base.util.module import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde -import org.jetbrains.kotlin.idea.completion.ImportableFqNameClassifier import org.jetbrains.kotlin.idea.completion.KotlinStatisticsInfo import org.jetbrains.kotlin.idea.completion.isDeprecatedAtCallSite import org.jetbrains.kotlin.idea.core.util.runSynchronouslyWithProgress import org.jetbrains.kotlin.idea.imports.importableFqName +import org.jetbrains.kotlin.idea.quickfix.AutoImportVariant +import org.jetbrains.kotlin.idea.quickfix.ImportComparablePriority +import org.jetbrains.kotlin.idea.quickfix.ImportFixHelper +import org.jetbrains.kotlin.idea.quickfix.ImportPrioritizer import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors @@ -46,14 +38,15 @@ import org.jetbrains.kotlin.idea.util.application.underModalProgressOrUnderWrite import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.isOneSegmentFQN import org.jetbrains.kotlin.name.parentOrNull -import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.ImportPath -import java.awt.BorderLayout +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import javax.swing.Icon -import javax.swing.JPanel -import javax.swing.ListCellRenderer internal fun createSingleImportAction( project: Project, @@ -62,10 +55,12 @@ internal fun createSingleImportAction( fqNames: Collection ): KotlinAddImportAction { val file = element.containingKtFile - val prioritizer = Prioritizer(file, element) + val prioritizer = createPrioritizerForFile(file) + val expressionWeigher = ExpressionWeigher.createWeigher(element) + val variants = fqNames.asSequence().mapNotNull { fqName -> val sameFqNameDescriptors = file.resolveImportReference(fqName) - createVariantWithPriority(fqName, sameFqNameDescriptors, file, prioritizer, project) + createVariantWithPriority(fqName, sameFqNameDescriptors, prioritizer, expressionWeigher, project) }.sortedWith(compareBy({ it.priority }, { it.variant.hint })) return KotlinAddImportAction(project, editor, element, variants) @@ -78,12 +73,14 @@ internal fun createSingleImportActionForConstructor( fqNames: Collection ): KotlinAddImportAction { val file = element.containingKtFile - val prioritizer = Prioritizer(file) + val prioritizer = createPrioritizerForFile(file) + val expressionWeigher = ExpressionWeigher.createWeigher(element) + val variants = fqNames.asSequence().mapNotNull { fqName -> val sameFqNameDescriptors = file.resolveImportReference(fqName.parent()) .filterIsInstance() .flatMap { it.constructors } - createVariantWithPriority(fqName, sameFqNameDescriptors, file, prioritizer, project) + createVariantWithPriority(fqName, sameFqNameDescriptors, prioritizer, expressionWeigher, project) } return KotlinAddImportAction(project, editor, element, variants) @@ -92,12 +89,12 @@ internal fun createSingleImportActionForConstructor( private fun createVariantWithPriority( fqName: FqName, sameFqNameDescriptors: Collection, - file: KtFile, - prioritizer: Prioritizer, + prioritizer: ImportPrioritizer, + expressionWeigher: ExpressionWeigher, project: Project ): VariantWithPriority? { val descriptorsWithPriority = - sameFqNameDescriptors.map { it to prioritizer.priority(it, file.languageVersionSettings) }.sortedBy { it.second } + sameFqNameDescriptors.map { it to createDescriptorPriority(prioritizer, expressionWeigher, it) }.sortedBy { it.second } val priority = descriptorsWithPriority.firstOrNull()?.second ?: return null return VariantWithPriority(SingleImportVariant(fqName, descriptorsWithPriority.map { it.first }, project), priority) @@ -111,7 +108,9 @@ internal fun createGroupedImportsAction( fqNames: Collection ): KotlinAddImportAction { val file = element.containingKtFile - val prioritizer = DescriptorGroupPrioritizer(file) + val prioritizer = createPrioritizerForFile(file) + val expressionWeigher = ExpressionWeigher.createWeigher(element) + val variants = fqNames.groupBy { it.parentOrNull() ?: FqName.ROOT }.asSequence().map { val samePackageFqNames = it.value val descriptors = samePackageFqNames.flatMap { fqName -> file.resolveImportReference(fqName) } @@ -121,7 +120,7 @@ internal fun createGroupedImportsAction( SingleImportVariant(samePackageFqNames.first(), descriptors, project) } - val priority = prioritizer.priority(descriptors, file.languageVersionSettings) + val priority = createDescriptorGroupPriority(prioritizer, expressionWeigher, descriptors) VariantWithPriority(variant, priority) } @@ -138,9 +137,9 @@ class KotlinAddImportAction internal constructor( private val element: KtElement, private val variants: Sequence ) : QuestionAction { - private var singleImportVariant: AutoImportVariant? = null + private var singleImportVariant: DescriptorBasedAutoImportVariant? = null - private fun variantsList(): List { + private fun variantsList(): List { if (singleImportVariant != null && !isUnitTestMode()) return listOf(singleImportVariant!!) val variantsList = { @@ -180,7 +179,7 @@ class KotlinAddImportAction internal constructor( if (!element.isValid) return false val variantsList = variantsList() - KotlinAddImportActionInfo.executeListener?.onExecute(variantsList.map { it.descriptorsToImport.toList() }) + KotlinAddImportActionInfo.executeListener?.onExecute(variantsList) if (variantsList.isEmpty()) return false @@ -189,64 +188,14 @@ class KotlinAddImportAction internal constructor( return true } - JBPopupFactory.getInstance().createListPopup(project, getVariantSelectionPopup(variantsList)) { - val psiRenderer = DefaultPsiElementCellRenderer() - - ListCellRenderer { list, value, index, isSelected, cellHasFocus -> - JPanel(BorderLayout()).apply { - add( - psiRenderer.getListCellRendererComponent( - list, - value.declarationToImport, - index, - isSelected, - cellHasFocus - ) - ) - } - } - }.showInBestPositionFor(editor) + ImportFixHelper.createListPopupWithImportVariants(project, variantsList, ::addImport).showInBestPositionFor(editor) return true } - private fun getVariantSelectionPopup(variants: List): BaseListPopupStep { - return object : BaseListPopupStep(KotlinBundle.message("action.add.import.chooser.title"), variants) { - override fun isAutoSelectionEnabled() = false - - override fun isSpeedSearchEnabled() = true - - override fun onChosen(selectedValue: AutoImportVariant?, finalChoice: Boolean): PopupStep? { - if (selectedValue == null || project.isDisposed) return null - - if (finalChoice) { - addImport(selectedValue) - return null - } - - val toExclude = AddImportAction.getAllExcludableStrings(selectedValue.excludeFqNameCheck.asString()) - - return object : BaseListPopupStep(null, toExclude) { - override fun getTextFor(value: String): String { - return KotlinBundle.message("fix.import.exclude", value) - } - - override fun onChosen(selectedValue: String, finalChoice: Boolean): PopupStep? { - if (finalChoice && !project.isDisposed) { - AddImportAction.excludeFromImport(project, selectedValue) - } - return null - } - } - } - - override fun hasSubstep(selectedValue: AutoImportVariant?) = true - override fun getTextFor(value: AutoImportVariant) = value.hint - override fun getIconFor(value: AutoImportVariant) = value.icon - } - } - private fun addImport(variant: AutoImportVariant) { + require(variant is DescriptorBasedAutoImportVariant) + val psiDocumentManager = PsiDocumentManager.getInstance(project) psiDocumentManager.commitAllDocuments() @@ -294,145 +243,88 @@ class KotlinAddImportAction internal constructor( } } -internal interface ComparablePriority : Comparable +internal data class VariantWithPriority(val variant: DescriptorBasedAutoImportVariant, val priority: ImportComparablePriority) -internal data class VariantWithPriority(val variant: AutoImportVariant, val priority: ComparablePriority) - - -internal class Prioritizer( - private val file: KtFile, - element: PsiElement? = null, - private val compareNames: Boolean = true -) { - private val classifier = ImportableFqNameClassifier(file) { - ImportInsertHelper.getInstance(file.project).isImportedWithDefault(ImportPath(it, false), file) +internal fun createPrioritizerForFile(file: KtFile, compareNames: Boolean = true): ImportPrioritizer { + val isImportedByDefault = { fqName: FqName -> + ImportInsertHelper.getInstance(file.project).isImportedWithDefault(ImportPath(fqName, isAllUnder = false), file) } - private val statsManager = StatisticsManager.getInstance() - private val proximityLocation = ProximityLocation(file, file.module) - private val expressionWeigher = ExpressionWeigher.createWeigher(element) - - inner class Priority(descriptor: DeclarationDescriptor, languageVersionSettings: LanguageVersionSettings) : ComparablePriority { - private val isDeprecated = isDeprecatedAtCallSite(descriptor) { languageVersionSettings } - private val fqName = descriptor.importableFqName!! - private val classification = classifier.classify(fqName, false) - private val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, descriptor) - private val lastUseRecency = statsManager.getLastUseRecency(KotlinStatisticsInfo.forDescriptor(descriptor)) - private val proximityWeight = WeighingService.weigh(PsiProximityComparator.WEIGHER_KEY, declaration, proximityLocation) - private val callExpressionWeigh = expressionWeigher.weigh(descriptor) - - override fun compareTo(other: ComparablePriority): Int { - other as Priority - - if (isDeprecated != other.isDeprecated) { - return if (isDeprecated) +1 else -1 - } - - val c1 = callExpressionWeigh.compareTo(other.callExpressionWeigh) - if (c1 != 0) { - // callExpressionWeigh is non-negative number - // Comparator contract says that if `a.compareTo(b)` returns -1 then `a` appears earlier than `b` - return -c1 - } - - val c2 = classification.compareTo(other.classification) - if (c2 != 0) return c2 - - val c3 = lastUseRecency.compareTo(other.lastUseRecency) - if (c3 != 0) return c3 - - val c4 = proximityWeight.compareTo(other.proximityWeight) - if (c4 != 0) return -c4 // n.b. reversed - - return if (compareNames) { - fqName.asString().compareTo(other.fqName.asString()) - } else { - 0 - } - } - } - - fun priority( - descriptor: DeclarationDescriptor, - languageVersionSettings: LanguageVersionSettings, - ) = Priority(descriptor, languageVersionSettings) + return ImportPrioritizer(file, isImportedByDefault, compareNames) } -private class DescriptorGroupPrioritizer(file: KtFile) { - private val prioritizer = Prioritizer(file, compareNames = false) +internal fun createDescriptorPriority( + prioritizer: ImportPrioritizer, + expressionWeigher: ExpressionWeigher, + descriptor: DeclarationDescriptor +): ImportPrioritizer.Priority { + val languageVersionSettings = prioritizer.file.languageVersionSettings - inner class Priority( - val descriptors: List, - languageVersionSettings: LanguageVersionSettings - ) : ComparablePriority { - val ownDescriptorsPriority = descriptors.maxOf { prioritizer.priority(it, languageVersionSettings) } - - override fun compareTo(other: ComparablePriority): Int { - other as Priority - - val c1 = ownDescriptorsPriority.compareTo(other.ownDescriptorsPriority) - if (c1 != 0) return c1 - - return other.descriptors.size - descriptors.size - } - } - - fun priority( - descriptors: List, - languageVersionSettings: LanguageVersionSettings - ) = Priority(descriptors, languageVersionSettings) + return prioritizer.Priority( + declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(prioritizer.file.project, descriptor), + statisticsInfo = KotlinStatisticsInfo.forDescriptor(descriptor), + isDeprecated = isDeprecatedAtCallSite(descriptor) { languageVersionSettings }, + fqName = descriptor.importableFqName ?: error("Unexpected null for fully-qualified name of importable declaration"), + expressionWeight = expressionWeigher.weigh(descriptor), + ) } -internal abstract class AutoImportVariant( +internal fun createDescriptorGroupPriority( + prioritizer: ImportPrioritizer, + expressionWeigher: ExpressionWeigher, + descriptors: List +): ImportPrioritizer.GroupPriority = + prioritizer.GroupPriority(descriptors.map { createDescriptorPriority(prioritizer, expressionWeigher, it) }) + +internal abstract class DescriptorBasedAutoImportVariant( val descriptorsToImport: Collection, - val excludeFqNameCheck: FqName, + override val fqName: FqName, project: Project, -) { - abstract val hint: String - val declarationToImport: PsiElement? = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptorsToImport.first()) - val icon: Icon? = KotlinDescriptorIconProvider.getIcon(descriptorsToImport.first(), declarationToImport, 0) +) : AutoImportVariant { + override val declarationToImport: PsiElement? = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptorsToImport.first()) + override val icon: Icon? = KotlinDescriptorIconProvider.getIcon(descriptorsToImport.first(), declarationToImport, 0) + + override val debugRepresentation: String + get() = descriptorsToImport.first().variantNameForDebug() + + companion object { + private val debugRenderer = DescriptorRenderer.DEBUG_TEXT.withOptions { + annotationFilter = { false } + } + + private fun DeclarationDescriptor.variantNameForDebug() = when (this) { + is ClassDescriptor -> + fqNameOrNull()?.toString()?.let { "class $it" } ?: debugRenderer.render(this) + + else -> + debugRenderer.render(this) + } + } } private class GroupedImportVariant( val autoImportDescription: String, descriptors: Collection, project: Project -) : AutoImportVariant( +) : DescriptorBasedAutoImportVariant( descriptorsToImport = descriptors, - excludeFqNameCheck = descriptors.first().importableFqName!!.parent(), + fqName = descriptors.first().importableFqName!!.parent(), project = project, ) { - override val hint: String get() = KotlinBundle.message("0.from.1", autoImportDescription, excludeFqNameCheck) + override val hint: String get() = KotlinBundle.message("0.from.1", autoImportDescription, fqName) } private class SingleImportVariant( - excludeFqNameCheck: FqName, + fqName: FqName, descriptors: Collection, project: Project -) : AutoImportVariant( +) : DescriptorBasedAutoImportVariant( descriptorsToImport = listOf( descriptors.singleOrNull() ?: descriptors.minByOrNull { if (it is ClassDescriptor) 0 else 1 } ?: error("we create the class with not-empty descriptors always") ), - excludeFqNameCheck = excludeFqNameCheck, + fqName = fqName, project = project, ) { - override val hint: String get() = excludeFqNameCheck.asString() -} - -/** Test hooks allowing inspection of data used for KotlinAddImportAction. **/ -object KotlinAddImportActionInfo { - interface ExecuteListener { - fun onExecute(variants: List>) - } - - @Volatile - internal var executeListener: ExecuteListener? = null - - @TestOnly - fun setExecuteListener(disposable: Disposable, listener: ExecuteListener) { - assert(executeListener == null) - executeListener = listener - Disposer.register(disposable) { executeListener = null } - } -} + override val hint: String get() = fqName.asString() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateEqualsAndHashcodeAction.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateEqualsAndHashcodeAction.kt index d1f08cdf2a61..14f5460f9da8 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateEqualsAndHashcodeAction.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateEqualsAndHashcodeAction.kt @@ -10,6 +10,7 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiNameIdentifierOwner import com.intellij.util.IncorrectOperationException import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -267,7 +268,7 @@ class KotlinGenerateEqualsAndHashcodeAction : KotlinGenerateMemberActionBase { val canUseArrayContentFunctions = targetClass.canUseArrayContentFunctions() val shouldWrapInLet = isNullable && !canUseArrayContentFunctions - val hashCodeArg = if (shouldWrapInLet) "it" else ref + val hashCodeArg = if (shouldWrapInLet) StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier else ref val hashCodeCall = generateArrayHashCodeCall(this, canUseArrayContentFunctions, hashCodeArg) if (shouldWrapInLet) "$ref?.let { $hashCodeCall }" else hashCodeCall } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt index 3f0bc192f26c..076c393e18bf 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.idea.codeInliner import com.intellij.psi.util.elementType +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.isExtensionFunctionType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.diagnostics.Errors @@ -225,7 +226,7 @@ class CodeToInlineBuilder( last = KtFunctionLiteral::class ) val hasUnresolvedItOrThis = factory == Errors.UNRESOLVED_REFERENCE && - element.text == "it" && + element.text == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier && element.getStrictParentOfType() == functionLiteral hasCantInferParameter || hasUnresolvedItOrThis diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/codeInliner/introduceValue.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/codeInliner/introduceValue.kt index 8b0959ed4807..0b7f26bab887 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/codeInliner/introduceValue.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/codeInliner/introduceValue.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlin.idea.codeInliner +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.idea.base.fe10.codeInsight.newDeclaration.Fe10KotlinNameSuggester import org.jetbrains.kotlin.idea.caches.resolve.computeTypeInContext @@ -94,8 +95,8 @@ internal fun MutableCodeToInline.introduceValue( statementsBefore.add(0, value) } } else { - val useIt = !isNameUsed("it") - val name = if (useIt) Name.identifier("it") else suggestName { !isNameUsed(it) } + val useIt = !isNameUsed(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier) + val name = if (useIt) StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME else suggestName { !isNameUsed(it) } replaceUsages(name) mainExpression = psiFactory.buildExpression { diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt index 24df78d74f2b..11a481985ea8 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt @@ -257,7 +257,7 @@ internal fun ElementAndTextList.convertCodeToKotlin(project: Project, targetModu ThrowableComputable { runReadAction { converter.elementsToKotlin(inputElements) } }, - JavaToKotlinAction.title, + JavaToKotlinAction.Handler.title, true, project ) diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/findUsages/similarity/KotlinSimilarityFeaturesExtractor.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/findUsages/similarity/KotlinSimilarityFeaturesExtractor.kt index e76299a356f6..c85f43440822 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/findUsages/similarity/KotlinSimilarityFeaturesExtractor.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/findUsages/similarity/KotlinSimilarityFeaturesExtractor.kt @@ -6,6 +6,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.usages.similarity.bag.Bag import com.intellij.usages.similarity.features.UsageSimilarityFeaturesRecorder +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.psi.* class KotlinSimilarityFeaturesExtractor(element: PsiElement, private val context: PsiElement) : KtTreeVisitorVoid() { @@ -127,7 +128,7 @@ class KotlinSimilarityFeaturesExtractor(element: PsiElement, private val context private fun collectFunctionParametersNames(function: KtFunction) { if (function is KtFunctionLiteral) { - variableNames += "it" + variableNames += StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier } for (valueParameter in function.valueParameters) { diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinDefaultHighlightingSettingsProvider.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinDefaultHighlightingSettingsProvider.kt index 6ad71fa67627..ae224c67d4de 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinDefaultHighlightingSettingsProvider.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinDefaultHighlightingSettingsProvider.kt @@ -21,9 +21,14 @@ class KotlinDefaultHighlightingSettingsProvider : DefaultHighlightingSettingProv return null } + val psiFile = file.toPsiFile(project) ?: return null return when { - file.toPsiFile(project) !is KtFile -> null - RootKindFilter.libraryFiles.matches(project, file) -> FileHighlightingSetting.SKIP_INSPECTION + psiFile is KtFile -> + when { + psiFile.isCompiled -> FileHighlightingSetting.SKIP_INSPECTION + RootKindFilter.libraryFiles.matches(project, file) -> FileHighlightingSetting.SKIP_INSPECTION + else -> null + } file.isKotlinDecompiledFile -> FileHighlightingSetting.SKIP_HIGHLIGHTING else -> null } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightImplicitItHandlerFactory.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightImplicitItHandlerFactory.kt index 9040530d38c2..2aaa111d70bc 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightImplicitItHandlerFactory.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightImplicitItHandlerFactory.kt @@ -9,7 +9,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.util.Consumer -import org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter.Companion.getLambdaByImplicitItReference +import org.jetbrains.kotlin.idea.codeinsight.utils.getFunctionLiteralByImplicitLambdaParameter import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtNameReferenceExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression @@ -19,7 +19,7 @@ class KotlinHighlightImplicitItHandlerFactory : HighlightUsagesHandlerFactoryBas override fun createHighlightUsagesHandler(editor: Editor, file: PsiFile, target: PsiElement): HighlightUsagesHandlerBase<*>? { if (!(target is LeafPsiElement && target.elementType == KtTokens.IDENTIFIER)) return null val refExpr = target.parent as? KtNameReferenceExpression ?: return null - val lambda = getLambdaByImplicitItReference(refExpr) ?: return null + val lambda = refExpr.getFunctionLiteralByImplicitLambdaParameter() ?: return null return object : HighlightUsagesHandlerBase(editor, file) { override fun getTargets() = listOf(refExpr) @@ -32,7 +32,7 @@ class KotlinHighlightImplicitItHandlerFactory : HighlightUsagesHandlerFactoryBas lambda.accept( object : KtTreeVisitorVoid() { override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) { - if (expression is KtNameReferenceExpression && getLambdaByImplicitItReference(expression) == lambda) { + if (expression is KtNameReferenceExpression && expression.getFunctionLiteralByImplicitLambdaParameter() == lambda) { addOccurrence(expression) } } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinRainbowVisitor.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinRainbowVisitor.kt index 74a89a06bf7c..65070ca8dfed 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinRainbowVisitor.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinRainbowVisitor.kt @@ -8,6 +8,7 @@ import com.intellij.openapi.editor.colors.TextAttributesKey import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors.* import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.search.ideaExtensions.FE10KotlinTargetElementEvaluator @@ -47,7 +48,7 @@ class KotlinRainbowVisitor : RainbowVisitor() { if (targetElement.isRainbowDeclaration()) { addRainbowHighlight(targetElement, element) } - } else if (element.getReferencedName() == "it") { + } else if (element.getReferencedNameAsName() == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME) { val itTargetElement = KOTLIN_TARGET_ELEMENT_EVALUATOR.getElementByReference(reference, TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED) diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/LiftReturnOrAssignmentInspection.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/LiftReturnOrAssignmentInspection.kt index 02ee5da2441c..5f87ca38a751 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/LiftReturnOrAssignmentInspection.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/LiftReturnOrAssignmentInspection.kt @@ -5,17 +5,24 @@ package org.jetbrains.kotlin.idea.inspections import com.intellij.codeInspection.* import com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING import com.intellij.codeInspection.ProblemHighlightType.INFORMATION +import com.intellij.codeInspection.options.OptPane +import com.intellij.codeInspection.options.OptPane.checkbox +import com.intellij.codeInspection.options.OptPane.pane import com.intellij.openapi.project.Project +import com.intellij.psi.PsiComment import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.idea.base.psi.getLineCount import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractKotlinInspection import org.jetbrains.kotlin.idea.codeinsight.utils.findExistingEditor -import org.jetbrains.kotlin.idea.base.psi.getLineCount +import org.jetbrains.kotlin.idea.codeinsight.utils.getBooleanTestOption import org.jetbrains.kotlin.idea.intentions.branchedTransformations.BranchedFoldingUtils import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isElseIf +import org.jetbrains.kotlin.idea.util.application.isUnitTestMode import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType +import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode @@ -23,10 +30,21 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode class LiftReturnOrAssignmentInspection @JvmOverloads constructor(private val skipLongExpressions: Boolean = true) : AbstractKotlinInspection() { + @JvmField + var reportOnlyIfSingleStatement = true + + override fun getOptionsPane(): OptPane { + return pane( + checkbox("reportOnlyIfSingleStatement", KotlinBundle.message("inspection.lift.return.or.assignment.option.only.single.statement")), + ) + } + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) = object : KtVisitorVoid() { override fun visitExpression(expression: KtExpression) { - val states = getState(expression, skipLongExpressions) ?: return + initOptionsInUnitTestMode(expression.containingKtFile) + + val states = getState(expression, skipLongExpressions, reportOnlyIfSingleStatement) ?: return if (expression.isUsedAsExpression(expression.analyze(BodyResolveMode.PARTIAL_WITH_CFA))) return states.forEach { state -> registerProblem( @@ -64,6 +82,14 @@ class LiftReturnOrAssignmentInspection @JvmOverloads constructor(private val ski } + private fun initOptionsInUnitTestMode(testDataFile: KtFile) { + if (isUnitTestMode()) { + testDataFile.getBooleanTestOption("ONLY_SINGLE_STATEMENT")?.let { + reportOnlyIfSingleStatement = it + } + } + } + private class LiftReturnOutFix(private val keyword: String) : LocalQuickFix { override fun getName() = KotlinBundle.message("lift.return.out.fix.text.0", keyword) @@ -88,19 +114,28 @@ class LiftReturnOrAssignmentInspection @JvmOverloads constructor(private val ski companion object { private const val LINES_LIMIT = 15 - fun getState(expression: KtExpression, skipLongExpressions: Boolean) = when (expression) { - is KtWhenExpression -> getStateForWhenOrTry(expression, expression.whenKeyword, skipLongExpressions) - is KtIfExpression -> getStateForWhenOrTry(expression, expression.ifKeyword, skipLongExpressions) - is KtTryExpression -> expression.tryKeyword?.let { - getStateForWhenOrTry(expression, it, skipLongExpressions) - } + fun getState( + expression: KtExpression, + skipLongExpressions: Boolean, + reportOnlyIfSingleStatement: Boolean = true + ): List? = when (expression) { + is KtWhenExpression -> + getStateForWhenOrTry(expression, expression.whenKeyword, skipLongExpressions, reportOnlyIfSingleStatement) + + is KtIfExpression -> + getStateForWhenOrTry(expression, expression.ifKeyword, skipLongExpressions, reportOnlyIfSingleStatement) + + is KtTryExpression -> + expression.tryKeyword?.let { getStateForWhenOrTry(expression, it, skipLongExpressions, reportOnlyIfSingleStatement) } + else -> null } private fun getStateForWhenOrTry( expression: KtExpression, keyword: PsiElement, - skipLongExpressions: Boolean + skipLongExpressions: Boolean, + reportOnlyIfSingleStatement: Boolean, ): List? { if (skipLongExpressions && expression.getLineCount() > LINES_LIMIT) return null if (expression.isElseIf()) return null @@ -108,20 +143,26 @@ class LiftReturnOrAssignmentInspection @JvmOverloads constructor(private val ski val foldableReturns = BranchedFoldingUtils.getFoldableReturns(expression) if (foldableReturns?.isNotEmpty() == true) { val hasOtherReturns = expression.anyDescendantOfType { it !in foldableReturns } - val isSerious = !hasOtherReturns && foldableReturns.size > 1 - return foldableReturns.map { - LiftState(keyword, isSerious, LiftType.LIFT_RETURN_OUT, it, INFORMATION) - } + LiftState(keyword, isSerious, LiftType.LIFT_RETURN_OUT) + val allBranchesAreSingleStatement = foldableReturns.none { it.hasSiblings() } + val isSerious = !hasOtherReturns && + foldableReturns.size > 1 && + (allBranchesAreSingleStatement || !reportOnlyIfSingleStatement) + return foldableReturns.map { LiftState(keyword, isSerious, LiftType.LIFT_RETURN_OUT, it, INFORMATION) } + + LiftState(keyword, isSerious, LiftType.LIFT_RETURN_OUT) } - val assignmentNumber = BranchedFoldingUtils.getFoldableAssignmentNumber(expression) - if (assignmentNumber > 0) { - val isSerious = assignmentNumber > 1 + val assignments = BranchedFoldingUtils.getFoldableAssignments(expression) + if (assignments.isNotEmpty()) { + val allBranchesAreSingleStatement = assignments.none { it.hasSiblings() } + val isSerious = assignments.size > 1 && (allBranchesAreSingleStatement || !reportOnlyIfSingleStatement) return listOf(LiftState(keyword, isSerious, LiftType.LIFT_ASSIGNMENT_OUT)) } return null } + private fun KtExpression.hasSiblings(): Boolean = + (parent as? KtBlockExpression)?.statements.orEmpty().size > 1 + enum class LiftType { LIFT_RETURN_OUT, LIFT_ASSIGNMENT_OUT } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/NestedLambdaShadowedImplicitParameterInspection.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/NestedLambdaShadowedImplicitParameterInspection.kt index e95885fa91b7..17cd343b8db6 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/NestedLambdaShadowedImplicitParameterInspection.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/NestedLambdaShadowedImplicitParameterInspection.kt @@ -6,6 +6,7 @@ import com.intellij.codeInspection.* import com.intellij.openapi.project.Project import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElementVisitor +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.caches.resolve.analyze @@ -46,7 +47,7 @@ class NestedLambdaShadowedImplicitParameterInspection : AbstractKotlinInspection if (qualifiedExpression != null) { val receiver = qualifiedExpression.receiverExpression val call = qualifiedExpression.callExpression - if (receiver.text == "it" && call?.isCalling(scopeFunctions, context) == true) return + if (receiver.text == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier && call?.isCalling(scopeFunctions, context) == true) return } val containingFile = lambda.containingFile @@ -74,7 +75,7 @@ class NestedLambdaShadowedImplicitParameterInspection : AbstractKotlinInspection val lambda = implicitParameterReference.getStrictParentOfType() ?: return val parentLambda = lambda.getParentImplicitParameterLambda() ?: return val parameter = parentLambda.functionLiteral.getOrCreateParameterList().addParameterBefore( - KtPsiFactory(project).createLambdaParameterList("it").parameters.first(), null + KtPsiFactory(project).createLambdaParameterList(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier).parameters.first(), null ) val editor = parentLambda.findExistingEditor() ?: return PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document) @@ -103,7 +104,7 @@ private fun KtNameReferenceExpression.isImplicitParameterReference( implicitParameter: ValueParameterDescriptor, context: BindingContext ): Boolean { - return text == "it" + return text == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier && getStrictParentOfType() == lambda && getResolvedCall(context)?.resultingDescriptor == implicitParameter } \ No newline at end of file diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLambdaArrowInspection.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLambdaArrowInspection.kt index 6b00bde45a6e..8f259c270b02 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLambdaArrowInspection.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLambdaArrowInspection.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall +import org.jetbrains.kotlin.builtins.StandardNames class RedundantLambdaArrowInspection : AbstractKotlinInspection() { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { @@ -32,7 +33,7 @@ class RedundantLambdaArrowInspection : AbstractKotlinInspection() { val parameters = functionLiteral.valueParameters val singleParameter = parameters.singleOrNull() if (singleParameter?.typeReference != null) return - if (parameters.isNotEmpty() && singleParameter?.name != "it") { + if (parameters.isNotEmpty() && singleParameter?.nameAsName != StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME) { return } @@ -42,7 +43,7 @@ class RedundantLambdaArrowInspection : AbstractKotlinInspection() { val callExpression = lambdaExpression.parent?.parent as? KtCallExpression if (callExpression != null) { val callee = callExpression.calleeExpression as? KtNameReferenceExpression - if (callee != null && callee.getReferencedName() == "forEach" && singleParameter?.name != "it") return + if (callee != null && callee.getReferencedName() == "forEach" && singleParameter?.nameAsName != StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME) return } val lambdaContext = lambdaExpression.analyze() @@ -55,7 +56,7 @@ class RedundantLambdaArrowInspection : AbstractKotlinInspection() { val functionLiteralDescriptor = functionLiteral.descriptor if (functionLiteralDescriptor != null) { if (functionLiteral.anyDescendantOfType { - it.text == "it" && it.resolveToCall()?.resultingDescriptor?.containingDeclaration != functionLiteralDescriptor + it.text == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier && it.resolveToCall()?.resultingDescriptor?.containingDeclaration != functionLiteralDescriptor }) return } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLetInspection.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLetInspection.kt index 8d98845a142d..3ffea90dc45e 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLetInspection.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLetInspection.kt @@ -6,6 +6,7 @@ import com.intellij.codeInspection.ProblemHighlightType import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.idea.base.psi.isMultiLine @@ -227,7 +228,7 @@ private fun KtDotQualifiedExpression.hasLambdaExpression() = selectorExpression? private fun KtLambdaExpression.getParameterName(): String? { val parameters = valueParameters if (parameters.size > 1) return null - return if (parameters.size == 1) parameters[0].text else "it" + return if (parameters.size == 1) parameters[0].text else StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier } private fun KtExpression.nameUsed(name: String, except: KtNameReferenceExpression? = null): Boolean = diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt index b0f8ed1ccc46..eefbb7a13bce 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt @@ -9,6 +9,7 @@ import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement import com.intellij.psi.PsiElementVisitor import com.intellij.psi.SmartPsiElementPointer +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.idea.base.resources.KotlinBundle @@ -188,7 +189,7 @@ class ConvertScopeFunctionToParameter(counterpartName: String) : ConvertScopeFun val lambdaExtensionReceiver = lambdaDescriptor.extensionReceiverParameter val lambdaDispatchReceiver = lambdaDescriptor.dispatchReceiverParameter - var parameterName = "it" + var parameterName = StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier val scopes = mutableSetOf() if (functionLiteral != null && needUniqueNameForParameter(lambda, scopes)) { val parameterType = lambdaExtensionReceiver?.type ?: lambdaDispatchReceiver?.type @@ -255,7 +256,7 @@ class ConvertScopeFunctionToParameter(counterpartName: String) : ConvertScopeFun val resolutionScope = lambdaArgument.getResolutionScope() scopes.add(resolutionScope) var needUniqueName = false - if (resolutionScope.findVariable(Name.identifier("it"), NoLookupLocation.FROM_IDE) != null) { + if (resolutionScope.findVariable(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME, NoLookupLocation.FROM_IDE) != null) { needUniqueName = true // Don't return here - we still need to gather the list of nested scopes } @@ -274,7 +275,7 @@ class ConvertScopeFunctionToParameter(counterpartName: String) : ConvertScopeFun private fun checkNeedUniqueName(dcl: KtElement) { val nestedResolutionScope = dcl.getResolutionScope() scopes.add(nestedResolutionScope) - if (nestedResolutionScope.findVariable(Name.identifier("it"), NoLookupLocation.FROM_IDE) != null) { + if (nestedResolutionScope.findVariable(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME, NoLookupLocation.FROM_IDE) != null) { needUniqueName = true } } @@ -310,7 +311,7 @@ class ConvertScopeFunctionToReceiver(counterpartName: String) : ConvertScopeFunc lambda.accept(object : KtTreeVisitorVoid() { override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) { super.visitSimpleNameExpression(expression) - if (expression.getReferencedName() == "it") { + if (expression.getReferencedNameAsName() == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME) { val result = expression.resolveMainReferenceToDescriptors().singleOrNull() if (result is ValueParameterDescriptor && result.containingDeclaration == lambdaDescriptor) { replacements.add(expression) { createThisExpression() } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/SimplifyNestedEachInScopeFunctionInspection.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/SimplifyNestedEachInScopeFunctionInspection.kt index 74f7dc07fcf0..bf0c9abb800f 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/SimplifyNestedEachInScopeFunctionInspection.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/SimplifyNestedEachInScopeFunctionInspection.kt @@ -7,6 +7,7 @@ import com.intellij.codeInspection.ProblemDescriptor import com.intellij.codeInspection.ProblemHighlightType import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.idea.base.resources.KotlinBundle @@ -133,10 +134,10 @@ class SimplifyNestedEachInScopeFunctionInspection : AbstractKotlinInspection() { if (innerExpression !is KtDotQualifiedExpression) return val receiverExpression = innerExpression.receiverExpression if (receiverExpression !is KtReferenceExpression) return - val parameterName = lambdaExpression.valueParameters.singleOrNull()?.name ?: "it" + val parameterName = lambdaExpression.valueParameters.singleOrNull()?.name ?: StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier if (!receiverExpression.textMatches(parameterName)) return - if (forEachLambda != null && (forEachLambda.valueParameters.singleOrNull()?.name ?: "it") == parameterName) { + if (forEachLambda != null && (forEachLambda.valueParameters.singleOrNull()?.name ?: StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier) == parameterName) { null // Parameter from outer lambda is shadowed } else { val lambdaDescriptor = lambdaExpression.descriptor(context) ?: return diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifiableCallInspection.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifiableCallInspection.kt index 5d6fb906d9d4..7e710044db5b 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifiableCallInspection.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/collections/SimplifiableCallInspection.kt @@ -10,6 +10,7 @@ import com.intellij.openapi.project.Project import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isArray import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveArray +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall @@ -143,7 +144,7 @@ private fun KtLambdaExpression.singleStatement(): KtExpression? = bodyExpression private fun KtLambdaExpression.singleLambdaParameterName(): String? { val lambdaParameters = valueParameters - return if (lambdaParameters.isNotEmpty()) lambdaParameters.singleOrNull()?.name else "it" + return if (lambdaParameters.isNotEmpty()) lambdaParameters.singleOrNull()?.name else StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier } private fun KtExpression.isNameReferenceTo(name: String): Boolean = diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/dfa/KtVariableDescriptor.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/dfa/KtVariableDescriptor.kt index 527e6428b23f..890b3d5068e5 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/dfa/KtVariableDescriptor.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/dfa/KtVariableDescriptor.kt @@ -8,6 +8,7 @@ import com.intellij.codeInspection.dataFlow.value.DfaVariableValue import com.intellij.psi.PsiElement import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor @@ -151,7 +152,7 @@ class KtVariableDescriptor(val variable: KtCallableDeclaration) : JvmVariableDes } } } - if (expr.textMatches("it")) { + if (expr.textMatches(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier)) { val descriptor = expr.resolveMainReferenceToDescriptors().singleOrNull() if (descriptor is ValueParameterDescriptor) { val fn = (descriptor.containingDeclaration.toSourceElement as? KotlinSourceElement)?.psi diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertForEachToForLoopIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertForEachToForLoopIntention.kt index 88f45ac55db8..be8a289959d4 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertForEachToForLoopIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertForEachToForLoopIntention.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.openapi.editor.Editor +import org.jetbrains.kotlin.builtins.StandardNames import com.intellij.psi.PsiDocumentManager import org.jetbrains.kotlin.idea.base.fe10.codeInsight.newDeclaration.Fe10KotlinNameSuggester import org.jetbrains.kotlin.idea.base.resources.KotlinBundle @@ -145,7 +146,7 @@ class ConvertForEachToForLoopIntention : SelfTargetingOffsetIndependentIntention } else { psiFactory.createExpressionByPattern( "${loopLabel}for($0 in $1){ $2 }", - parameters.singleOrNull() ?: "it", + parameters.singleOrNull() ?: StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier, loopRange, body.allChildren ) diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt index 7b925c9ff6a6..5961394080d5 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt @@ -13,6 +13,7 @@ import com.intellij.psi.search.LocalSearchScope import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.refactoring.util.RefactoringUIUtil import com.intellij.util.containers.MultiMap +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic @@ -155,7 +156,7 @@ class ConvertFunctionTypeReceiverToParameterIntention : SelfTargetingRangeIntent val lambdaParameterList = lambda.getOrCreateParameterList() if (lambda.valueParameters.isEmpty() && lambdaDescriptor.valueParameters.isNotEmpty()) { - val parameterToAdd = psiFactory.createLambdaParameterList("it").parameters.first() + val parameterToAdd = psiFactory.createLambdaParameterList(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier).parameters.first() lambdaParameterList.addParameterBefore(parameterToAdd, lambdaParameterList.parameters.firstOrNull()) } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReferenceToLambdaIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReferenceToLambdaIntention.kt index 35683dbf6728..539251af5ab9 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReferenceToLambdaIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReferenceToLambdaIntention.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.openapi.editor.Editor import com.intellij.psi.util.elementType import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames.KOTLIN_REFLECT_FQ_NAME import org.jetbrains.kotlin.builtins.isExtensionFunctionType import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor @@ -110,7 +111,7 @@ class ConvertReferenceToLambdaIntention : SelfTargetingOffsetIndependentIntentio val lambdaExpression = if (valueArgumentParent != null && lambdaParameterNamesAndTypes.size == 1 && - receiverExpression?.text != "it" + receiverExpression?.text != StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier ) { val body = if (acceptsReceiverAsParameter) { if (targetDescriptor is PropertyDescriptor) "it.$targetName" diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToIndexedFunctionCallIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToIndexedFunctionCallIntention.kt index e70af7749b70..cf5fafca5d13 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToIndexedFunctionCallIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToIndexedFunctionCallIntention.kt @@ -5,10 +5,11 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange import com.intellij.psi.codeStyle.CodeStyleManager +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.base.codeInsight.KotlinNameSuggestionProvider import org.jetbrains.kotlin.idea.base.fe10.codeInsight.newDeclaration.Fe10KotlinNameSuggester import org.jetbrains.kotlin.idea.base.fe10.codeInsight.newDeclaration.Fe10KotlinNewDeclarationNameValidator -import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.codeinsight.api.classic.intentions.SelfTargetingRangeIntention import org.jetbrains.kotlin.idea.core.CollectingNameValidator @@ -66,7 +67,7 @@ class ConvertToIndexedFunctionCallIntention : SelfTargetingRangeIntention( KotlinBundle.lazyMessage("use.destructuring.declaration") ) { override fun applyTo(element: KtDeclaration, editor: Editor?) { - val (usagesToRemove, removeSelectorInLoopRange) = collectUsagesToRemove(element) ?: return - val psiFactory = KtPsiFactory(element.project) - val parent = element.parent - val (container, anchor) = if (parent is KtParameterList) parent.parent to null else parent to element - val validator = Fe10KotlinNewDeclarationNameValidator( - container = container, anchor = anchor, target = KotlinNameSuggestionProvider.ValidatorTarget.VARIABLE, - excludedDeclarations = usagesToRemove.map { - (it.declarationToDrop as? KtDestructuringDeclaration)?.entries ?: listOfNotNull(it.declarationToDrop) - }.flatten() - ) - - val names = ArrayList() - val underscoreSupported = element.languageVersionSettings.supportsFeature(LanguageFeature.SingleUnderscoreForParameterName) - // For all unused we generate normal names, not underscores - val allUnused = usagesToRemove.all { (_, usagesToReplace, variableToDrop) -> - usagesToReplace.isEmpty() && variableToDrop == null - } - - usagesToRemove.forEach { (descriptor, usagesToReplace, variableToDrop, name) -> - val suggestedName = - if (usagesToReplace.isEmpty() && variableToDrop == null && underscoreSupported && !allUnused) { - "_" - } else { - Fe10KotlinNameSuggester.suggestNameByName(name ?: descriptor.name.asString(), validator) - } - - runWriteActionIfPhysical(element) { - variableToDrop?.delete() - usagesToReplace.forEach { - it.replace(psiFactory.createExpression(suggestedName)) - } - } - names.add(suggestedName) - } - - val joinedNames = names.joinToString() - when (element) { - is KtParameter -> { - val loopRange = (element.parent as? KtForExpression)?.loopRange - runWriteActionIfPhysical(element) { - val type = element.typeReference?.let { ": ${it.text}" } ?: "" - element.replace(psiFactory.createDestructuringParameter("($joinedNames)$type")) - if (removeSelectorInLoopRange && loopRange is KtDotQualifiedExpression) { - loopRange.replace(loopRange.receiverExpression) - } - } - } - - is KtFunctionLiteral -> { - val lambda = element.parent as KtLambdaExpression - SpecifyExplicitLambdaSignatureIntention().applyTo(lambda, editor) - runWriteActionIfPhysical(element) { - lambda.functionLiteral.valueParameters.singleOrNull()?.replace( - psiFactory.createDestructuringParameter("($joinedNames)") - ) - } - } - - is KtVariableDeclaration -> { - val rangeAfterEq = PsiChildRange(element.initializer, element.lastChild) - val modifierList = element.modifierList?.copied() - runWriteActionIfPhysical(element) { - val result = element.replace( - psiFactory.createDestructuringDeclarationByPattern( - "val ($joinedNames) = $0", rangeAfterEq - ) - ) as KtModifierListOwner - - if (modifierList != null) { - result.setModifierList(modifierList) - } - } - } - } + Holder.applyTo(element, editor) } - override fun applicabilityRange(element: KtDeclaration): TextRange? { - if (!element.isSuitableDeclaration()) return null + override fun applicabilityRange(element: KtDeclaration): TextRange? = + Holder.applicabilityRange(element) - val usagesToRemove = collectUsagesToRemove(element)?.data ?: return null - if (usagesToRemove.isEmpty()) return null + object Holder { + fun applicabilityRange(element: KtDeclaration): TextRange? { + if (!element.isSuitableDeclaration()) return null - return when (element) { - is KtFunctionLiteral -> element.lBrace.textRange - is KtNamedDeclaration -> element.nameIdentifier?.textRange - else -> null + val usagesToRemove = collectUsagesToRemove(element)?.data ?: return null + if (usagesToRemove.isEmpty()) return null + + return when (element) { + is KtFunctionLiteral -> element.lBrace.textRange + is KtNamedDeclaration -> element.nameIdentifier?.textRange + else -> null + } + } + + fun applyTo(element: KtDeclaration, editor: Editor? = null) { + val (usagesToRemove, removeSelectorInLoopRange) = collectUsagesToRemove(element) ?: return + val psiFactory = KtPsiFactory(element.project) + val parent = element.parent + val (container, anchor) = if (parent is KtParameterList) parent.parent to null else parent to element + val validator = Fe10KotlinNewDeclarationNameValidator( + container = container, anchor = anchor, target = KotlinNameSuggestionProvider.ValidatorTarget.VARIABLE, + excludedDeclarations = usagesToRemove.map { + (it.declarationToDrop as? KtDestructuringDeclaration)?.entries ?: listOfNotNull(it.declarationToDrop) + }.flatten() + ) + + val names = ArrayList() + val underscoreSupported = element.languageVersionSettings.supportsFeature(LanguageFeature.SingleUnderscoreForParameterName) + // For all unused we generate normal names, not underscores + val allUnused = usagesToRemove.all { (_, usagesToReplace, variableToDrop) -> + usagesToReplace.isEmpty() && variableToDrop == null + } + + usagesToRemove.forEach { (descriptor, usagesToReplace, variableToDrop, name) -> + val suggestedName = + if (usagesToReplace.isEmpty() && variableToDrop == null && underscoreSupported && !allUnused) { + "_" + } else { + Fe10KotlinNameSuggester.suggestNameByName(name ?: descriptor.name.asString(), validator) + } + + runWriteActionIfPhysical(element) { + variableToDrop?.delete() + usagesToReplace.forEach { + it.replace(psiFactory.createExpression(suggestedName)) + } + } + names.add(suggestedName) + } + + val joinedNames = names.joinToString() + when (element) { + is KtParameter -> { + val loopRange = (element.parent as? KtForExpression)?.loopRange + runWriteActionIfPhysical(element) { + val type = element.typeReference?.let { ": ${it.text}" } ?: "" + element.replace(psiFactory.createDestructuringParameter("($joinedNames)$type")) + if (removeSelectorInLoopRange && loopRange is KtDotQualifiedExpression) { + loopRange.replace(loopRange.receiverExpression) + } + } + } + + is KtFunctionLiteral -> { + val lambda = element.parent as KtLambdaExpression + SpecifyExplicitLambdaSignatureIntention().applyTo(lambda, editor) + runWriteActionIfPhysical(element) { + lambda.functionLiteral.valueParameters.singleOrNull()?.replace( + psiFactory.createDestructuringParameter("($joinedNames)") + ) + } + } + + is KtVariableDeclaration -> { + val rangeAfterEq = PsiChildRange(element.initializer, element.lastChild) + val modifierList = element.modifierList?.copied() + runWriteActionIfPhysical(element) { + val result = element.replace( + psiFactory.createDestructuringDeclarationByPattern( + "val ($joinedNames) = $0", rangeAfterEq + ) + ) as KtModifierListOwner + + if (modifierList != null) { + result.setModifierList(modifierList) + } + } + } + } } } } @@ -185,7 +195,7 @@ internal fun collectUsagesToRemove(declaration: KtDeclaration): UsagesToRemove? val nameToSearch = when (declaration) { is KtParameter -> declaration.nameAsName is KtVariableDeclaration -> declaration.nameAsName - else -> Name.identifier("it") + else -> StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME } ?: return null // Note: list should contain properties in order to create destructuring declaration diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveEmptyPrimaryConstructorIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveEmptyPrimaryConstructorIntention.kt index effea3e3dc81..42a8ad7577e4 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveEmptyPrimaryConstructorIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveEmptyPrimaryConstructorIntention.kt @@ -22,15 +22,20 @@ class RemoveEmptyPrimaryConstructorIntention : SelfTargetingOffsetIndependentInt KotlinBundle.lazyMessage("remove.empty.primary.constructor") ) { - override fun applyTo(element: KtPrimaryConstructor, editor: Editor?) = element.delete() + override fun applyTo(element: KtPrimaryConstructor, editor: Editor?) { + element.delete() + } - override fun isApplicableTo(element: KtPrimaryConstructor) = when { - element.containingClass()?.mustHaveNonEmptyPrimaryConstructor() == true -> false - element.valueParameters.isNotEmpty() -> false - element.annotations.isNotEmpty() -> false - element.modifierList?.text?.isBlank() == false -> false - element.containingClass()?.secondaryConstructors?.isNotEmpty() == true -> false - element.isExpectDeclaration() -> false - else -> true + override fun isApplicableTo(element: KtPrimaryConstructor): Boolean { + val containingClass = element.containingClass() ?: return false + return when { + element.valueParameters.isNotEmpty() -> false + element.annotations.isNotEmpty() -> false + element.modifierList?.text?.isBlank() == false -> false + element.isExpectDeclaration() -> false + containingClass.mustHaveNonEmptyPrimaryConstructor() -> false + containingClass.secondaryConstructors.isNotEmpty() -> false + else -> true + } } } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceExplicitFunctionLiteralParamWithItIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceExplicitFunctionLiteralParamWithItIntention.kt index 2b31a57844f3..8fcb34f331e8 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceExplicitFunctionLiteralParamWithItIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceExplicitFunctionLiteralParamWithItIntention.kt @@ -10,6 +10,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.refactoring.rename.RenameProcessor import com.intellij.usageView.UsageInfo +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.idea.base.resources.KotlinBundle @@ -35,7 +36,7 @@ class ReplaceExplicitFunctionLiteralParamWithItIntention : PsiElementBaseIntenti if (parameter.destructuringDeclaration != null) return false if (functionLiteral.anyDescendantOfType { literal -> - literal.usesName(element.text) && (!literal.hasParameterSpecification() || literal.usesName("it")) + literal.usesName(element.text) && (!literal.hasParameterSpecification() || literal.usesName(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier)) }) return false val lambda = functionLiteral.parent as? KtLambdaExpression ?: return false @@ -93,7 +94,7 @@ class ReplaceExplicitFunctionLiteralParamWithItIntention : PsiElementBaseIntenti ) : RenameProcessor( editor.project!!, functionLiteral.valueParameters.single(), - "it", + StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier, false, false ) { diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt index 2a8095052e48..2b4b91927bb8 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceItWithExplicitFunctionLiteralParamIntention.kt @@ -3,27 +3,35 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.codeInsight.FileModificationService +import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.editor.Editor import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.codeinsight.api.classic.intentions.SelfTargetingOffsetIndependentIntention -import org.jetbrains.kotlin.idea.refactoring.rename.KotlinVariableInplaceRenameHandler -import org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter.Companion.convertImplicitItToExplicit -import org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter.Companion.isAutoCreatedItUsage +import org.jetbrains.kotlin.idea.codeinsight.utils.isReferenceToImplicitLambdaParameter +import org.jetbrains.kotlin.idea.refactoring.rename.handlers.RenameKotlinImplicitLambdaParameter import org.jetbrains.kotlin.psi.KtNameReferenceExpression class ReplaceItWithExplicitFunctionLiteralParamIntention : SelfTargetingOffsetIndependentIntention( KtNameReferenceExpression::class.java, KotlinBundle.lazyMessage("replace.it.with.explicit.parameter") ) { - override fun isApplicableTo(element: KtNameReferenceExpression) = isAutoCreatedItUsage(element) + override fun isApplicableTo(element: KtNameReferenceExpression) = element.isReferenceToImplicitLambdaParameter() override fun startInWriteAction(): Boolean = false override fun applyTo(element: KtNameReferenceExpression, editor: Editor?) { if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return if (editor == null) throw IllegalArgumentException("This intention requires an editor") - val paramToRename = convertImplicitItToExplicit(element, editor) ?: return editor.caretModel.moveToOffset(element.textOffset) - KotlinVariableInplaceRenameHandler().doRename(paramToRename, editor, null) + val ktFile = element.containingKtFile + + val dataContext = DataContext { id -> + when { + CommonDataKeys.PSI_ELEMENT.`is`(id) -> element + else -> null + } + } + RenameKotlinImplicitLambdaParameter().invoke(ktFile.project, editor, ktFile, dataContext) } } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyInDestructuringAssignmentIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyInDestructuringAssignmentIntention.kt index 492d70a0b8fc..be916c9b029e 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyInDestructuringAssignmentIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyInDestructuringAssignmentIntention.kt @@ -2,7 +2,6 @@ package org.jetbrains.kotlin.idea.intentions -import com.intellij.codeInsight.intention.LowPriorityAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange import org.jetbrains.kotlin.idea.base.resources.KotlinBundle @@ -10,6 +9,7 @@ import org.jetbrains.kotlin.idea.codeinsight.api.classic.intentions.SelfTargetin import org.jetbrains.kotlin.idea.core.setType import org.jetbrains.kotlin.psi.KtCodeFragment import org.jetbrains.kotlin.psi.KtDestructuringDeclaration +import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry import org.jetbrains.kotlin.psi.KtParameterList import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.getParentOfType @@ -18,24 +18,27 @@ import org.jetbrains.kotlin.types.isError class SpecifyTypeExplicitlyInDestructuringAssignmentIntention : SelfTargetingRangeIntention( KtDestructuringDeclaration::class.java, KotlinBundle.lazyMessage("specify.all.types.explicitly.in.destructuring.declaration") -), LowPriorityAction { +) { override fun applicabilityRange(element: KtDestructuringDeclaration): TextRange? { if (element.containingFile is KtCodeFragment) return null - val entries = element.noTypeReferenceEntries() + val entries = element.entriesWithoutExplicitTypes() if (entries.isEmpty()) return null if (entries.any { SpecifyTypeExplicitlyIntention.getTypeForDeclaration(it).isError }) return null - return TextRange(element.startOffset, element.initializer?.let { it.startOffset - 1 } ?: element.endOffset) + val endOffset = element.initializer?.let { it.startOffset - 1 } ?: element.endOffset + return TextRange(element.startOffset, endOffset) } override fun applyTo(element: KtDestructuringDeclaration, editor: Editor?) { - val entries = element.noTypeReferenceEntries() - if (editor != null && element.getParentOfType(false) == null) + val entries = element.entriesWithoutExplicitTypes() + if (editor != null && element.getParentOfType(strict = false) == null) { SpecifyTypeExplicitlyIntention.addTypeAnnotationWithTemplate(editor, entries.iterator()) - else - entries.forEach { - it.setType(SpecifyTypeExplicitlyIntention.getTypeForDeclaration(it)) + } else { + for (entry in entries) { + entry.setType(SpecifyTypeExplicitlyIntention.getTypeForDeclaration(entry)) } + } } } -private fun KtDestructuringDeclaration.noTypeReferenceEntries() = entries.filter { it.typeReference == null } +private fun KtDestructuringDeclaration.entriesWithoutExplicitTypes(): List = + entries.filter { it.typeReference == null } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt index bf6b735479b1..128c227df011 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt @@ -46,6 +46,8 @@ class SpecifyTypeExplicitlyIntention : SelfTargetingRangeIntention } override fun inspectionTarget(element: KtExpression): PsiElement? { + initOptionsInUnitTestMode(element.containingKtFile) + return element.callOrReferenceOrNull(KtCallExpression::getCalleeExpression, KtCallableReferenceExpression::getCallableReference) + } + + private fun initOptionsInUnitTestMode(testDataFile: KtFile) { if (isUnitTestMode()) { - val reportNonTrivialAccessors = element.containingKtFile - .findDescendantOfType { it.text.startsWith("// REPORT_NON_TRIVIAL_ACCESSORS") } - ?.let { it.text.removePrefix("// REPORT_NON_TRIVIAL_ACCESSORS:").trim().toBoolean() } - if (reportNonTrivialAccessors != null) { - this.reportNonTrivialAccessors = reportNonTrivialAccessors + testDataFile.getBooleanTestOption("REPORT_NON_TRIVIAL_ACCESSORS")?.let { + reportNonTrivialAccessors = it } } - return element.callOrReferenceOrNull(KtCallExpression::getCalleeExpression, KtCallableReferenceExpression::getCallableReference) } override fun inspectionProblemText(element: KtExpression): String? = diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/BranchedFoldingUtils.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/BranchedFoldingUtils.kt index 546d927f8933..a12e898f2ead 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/BranchedFoldingUtils.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/BranchedFoldingUtils.kt @@ -71,7 +71,11 @@ object BranchedFoldingUtils { } internal fun getFoldableAssignmentNumber(expression: KtExpression?): Int { - expression ?: return -1 + return getFoldableAssignments(expression).size + } + + internal fun getFoldableAssignments(expression: KtExpression?): Set { + expression ?: return emptySet() val assignments = linkedSetOf() fun collectAssignmentsAndCheck(e: KtExpression?): Boolean = when (e) { is KtWhenExpression -> { @@ -102,12 +106,12 @@ object BranchedFoldingUtils { is KtThrowExpression, is KtReturnExpression -> true else -> false } - if (!collectAssignmentsAndCheck(expression)) return -1 - val firstAssignment = assignments.firstOrNull { !it.right.isNullExpression() } ?: assignments.firstOrNull() ?: return 0 - val leftType = firstAssignment.left?.let { it.getType(it.analyze(BodyResolveMode.PARTIAL)) } ?: return 0 - val rightTypeConstructor = firstAssignment.rightType()?.constructor ?: return -1 + if (!collectAssignmentsAndCheck(expression)) return emptySet() + val firstAssignment = assignments.firstOrNull { !it.right.isNullExpression() } ?: assignments.firstOrNull() ?: return emptySet() + val leftType = firstAssignment.left?.let { it.getType(it.analyze(BodyResolveMode.PARTIAL)) } ?: return emptySet() + val rightTypeConstructor = firstAssignment.rightType()?.constructor ?: return emptySet() if (assignments.any { !firstAssignment.checkAssignmentsMatch(it, leftType, rightTypeConstructor) }) { - return -1 + return emptySet() } if (expression.anyDescendantOfType( predicate = { @@ -121,9 +125,9 @@ object BranchedFoldingUtils { } ) ) { - return -1 + return emptySet() } - return assignments.size + return assignments } private fun getFoldableReturns(branches: List): List? = diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt index 1b84c049d2ce..13912ebd998d 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.util.TextRange import com.intellij.psi.search.LocalSearchScope import com.intellij.psi.search.searches.ReferencesSearch import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.idea.base.fe10.codeInsight.newDeclaration.Fe10KotlinNameSuggester @@ -287,7 +288,7 @@ data class IfThenToSelectData( receiver: KtExpression, factory: KtPsiFactory ): KtExpression { - val needExplicitParameter = valueArguments.any { it.getArgumentExpression()?.text == "it" } + val needExplicitParameter = valueArguments.any { it.getArgumentExpression()?.text == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier } val parameterName = if (needExplicitParameter) { val scope = getResolutionScope() Fe10KotlinNameSuggester.suggestNameByName("it") { scope.findVariable(Name.identifier(it), NoLookupLocation.FROM_IDE) == null } @@ -352,7 +353,7 @@ internal fun KtIfExpression.buildSelectTransformationData(): IfThenToSelectData? internal fun KtExpression?.isClauseTransformableToLetOnly(receiver: KtExpression?) = this is KtCallExpression && (resolveToCall()?.getImplicitReceiverValue() == null || receiver !is KtThisExpression) -internal fun KtIfExpression.shouldBeTransformed(): Boolean = when (val condition = condition) { +fun KtIfExpression.shouldBeTransformed(): Boolean = when (val condition = condition) { is KtBinaryExpression -> { val baseClause = (if (condition.operationToken == KtTokens.EQEQ) `else` else then)?.unwrapBlockOrParenthesis() !baseClause.isClauseTransformableToLetOnly(condition.checkedExpression()) diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt index cf48207a6467..59a55e6240d0 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/utils.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.idea.intentions.loopToCallChain import com.intellij.openapi.util.Key import com.intellij.openapi.util.UserDataHolderBase import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor @@ -40,14 +41,14 @@ fun generateLambda(inputVariable: KtCallableDeclaration, expression: KtExpressio ) as KtLambdaExpression val isItUsedInside = expression.anyDescendantOfType { - it.getQualifiedExpressionForSelector() == null && it.getReferencedName() == "it" + it.getQualifiedExpressionForSelector() == null && it.getReferencedNameAsName() == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME } if (isItUsedInside) return lambdaExpression val usages = lambdaExpression.findParameterUsages(lambdaExpression.valueParameters.single(), inputVariable) - val itExpr = psiFactory.createSimpleName("it") + val itExpr = psiFactory.createSimpleName(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier) for (usage in usages) { val replaced = usage.replaced(itExpr) diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/AbstractImportFix.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/AbstractImportFix.kt index 3914b3fa5aee..42d4d5bd4f57 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/AbstractImportFix.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/AbstractImportFix.kt @@ -18,11 +18,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.IntellijInternalApi import com.intellij.packageDependencies.DependencyValidationManager -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiErrorElement -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiModifier -import com.intellij.psi.SmartPsiElementPointer +import com.intellij.psi.* import com.intellij.psi.util.PsiModificationTracker import com.intellij.psi.util.elementType import com.intellij.util.Processors @@ -57,7 +53,6 @@ import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.name.parentOrNull import org.jetbrains.kotlin.platform.jvm.isJvm import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.KtPsiUtil.isSelectorInQualified @@ -81,7 +76,6 @@ import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments import org.jetbrains.kotlin.utils.addToStdlib.safeAs -import java.util.* /** * Check possibility and perform fix for unresolved references. @@ -145,19 +139,19 @@ abstract class ImportFixBase protected constructor( suggestionDescriptors.mapTo(hashSetOf()) { it.original }.takeIf { it.isNotEmpty() } ?: return "" val ktFile = element?.containingKtFile ?: return KotlinBundle.message("fix.import") - val languageVersionSettings = ktFile.languageVersionSettings - val prioritizer = Prioritizer(ktFile, element) + val prioritizer = createPrioritizerForFile(ktFile) + val expressionWeigher = ExpressionWeigher.createWeigher(element) - val kindNameGroupedByKind = descriptors.mapNotNull { descriptor -> + val importInfos = descriptors.mapNotNull { descriptor -> val kind = when { - descriptor.isExtensionProperty -> ImportKind.EXTENSION_PROPERTY - descriptor is PropertyDescriptor -> ImportKind.PROPERTY - descriptor is ClassConstructorDescriptor -> ImportKind.CLASS - descriptor is FunctionDescriptor && descriptor.isOperator -> ImportKind.OPERATOR - descriptor is FunctionDescriptor && descriptor.isExtension -> ImportKind.EXTENSION_FUNCTION - descriptor is FunctionDescriptor -> ImportKind.FUNCTION - DescriptorUtils.isObject(descriptor) -> ImportKind.OBJECT - descriptor is ClassDescriptor -> ImportKind.CLASS + descriptor.isExtensionProperty -> ImportFixHelper.ImportKind.EXTENSION_PROPERTY + descriptor is PropertyDescriptor -> ImportFixHelper.ImportKind.PROPERTY + descriptor is ClassConstructorDescriptor -> ImportFixHelper.ImportKind.CLASS + descriptor is FunctionDescriptor && descriptor.isOperator -> ImportFixHelper.ImportKind.OPERATOR + descriptor is FunctionDescriptor && descriptor.isExtension -> ImportFixHelper.ImportKind.EXTENSION_FUNCTION + descriptor is FunctionDescriptor -> ImportFixHelper.ImportKind.FUNCTION + DescriptorUtils.isObject(descriptor) -> ImportFixHelper.ImportKind.OBJECT + descriptor is ClassDescriptor -> ImportFixHelper.ImportKind.CLASS else -> null } ?: return@mapNotNull null @@ -180,54 +174,11 @@ abstract class ImportFixBase protected constructor( append(it.asString()) } } - ImportName(kind, name, prioritizer.priority(descriptor, languageVersionSettings)) - }.groupBy(keySelector = { it.kind }) { it } + val priority = createDescriptorPriority(prioritizer, expressionWeigher, descriptor) - return if (kindNameGroupedByKind.size == 1) { - val (kind, names) = kindNameGroupedByKind.entries.first() - val sortedImportNames = TreeSet(compareBy({ it.priority }, { it.name })) - sortedImportNames.addAll(names) - val firstName = sortedImportNames.first().name - val singlePackage = suggestions.groupBy { it.parentOrNull() ?: FqName.ROOT }.size == 1 - - if (singlePackage) { - val sortedByName = sortedImportNames.toSortedSet(compareBy { it.name }) - val size = sortedByName.size - if (size == 2) { - KotlinBundle.message("fix.import.kind.0.name.1.and.name.2", kind.toText(size), sortedByName.first().name, sortedByName.last().name) - } else { - KotlinBundle.message("fix.import.kind.0.name.1.2", kind.toText(size), firstName, size - 1) - } - } else if (kind.groupedByPackage) { - KotlinBundle.message("fix.import.kind.0.name.1.2", kind.toText(1), firstName, 0) - } else { - val groupBy = sortedImportNames.map { it.name }.toSortedSet().groupBy { it.substringBefore('.') } - val value = groupBy.entries.first().value - val first = value.first() - val multiple = if (value.size == 1) 0 else 1 - when { - groupBy.size != 1 -> KotlinBundle.message("fix.import.kind.0.name.1.2", kind.toText(1), first.substringAfter('.'), multiple) - value.size == 2 -> KotlinBundle.message("fix.import.kind.0.name.1.and.name.2", kind.toText(value.size), first, value.last()) - else -> KotlinBundle.message("fix.import.kind.0.name.1.2", kind.toText(1), first, multiple) - } - } - } else { - KotlinBundle.message("fix.import") + ImportFixHelper.ImportInfo(kind, name, priority) } - } - - private class ImportName(val kind: ImportKind, val name: String, val priority: ComparablePriority) - - private enum class ImportKind(private val key: String, val groupedByPackage: Boolean = false) { - CLASS("text.class.0", true), - PROPERTY("text.property.0"), - OBJECT("text.object.0", true), - FUNCTION("text.function.0"), - EXTENSION_PROPERTY("text.extension.property.0"), - EXTENSION_FUNCTION("text.extension.function.0"), - OPERATOR("text.operator.0"); - - fun toText(number: Int) = KotlinBundle.message(key, if (number == 1) 1 else 2) + return ImportFixHelper.calculateTextForFix(importInfos, suggestions) } override fun getText(): String = text diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeFunctionSignatureFix.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeFunctionSignatureFix.kt index 0499a6dbf710..d334692d0fcb 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeFunctionSignatureFix.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeFunctionSignatureFix.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.idea.quickfix import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED import org.jetbrains.kotlin.descriptors.ConstructorDescriptor @@ -69,7 +70,7 @@ abstract class ChangeFunctionSignatureFix( } private fun isSpecialName(name: String): Boolean { - return name == "it" || name == "field" + return name == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier || name == "field" } companion object : KotlinSingleIntentionActionFactoryWithDelegate() { diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/WrapWithSafeLetCallFix.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/WrapWithSafeLetCallFix.kt index fd86a580817b..af598c9d11d6 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/WrapWithSafeLetCallFix.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/WrapWithSafeLetCallFix.kt @@ -6,6 +6,7 @@ import com.intellij.codeInsight.intention.HighPriorityAction import com.intellij.codeInsight.intention.IntentionAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.idea.base.resources.KotlinBundle @@ -51,7 +52,7 @@ class WrapWithSafeLetCallFix( nullableExpression, KotlinNameSuggestionProvider.ValidatorTarget.PARAMETER ) - val name = Fe10KotlinNameSuggester.suggestNameByName("it", validator) + val name = Fe10KotlinNameSuggester.suggestNameByName(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier, validator) nullableExpression.replace(psiFactory.createExpression(name)) val underLetExpression = when { diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/K1KotlinRenameRefactoringSupport.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/K1KotlinRenameRefactoringSupport.kt index 113cc8734040..88f824db92d3 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/K1KotlinRenameRefactoringSupport.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/K1KotlinRenameRefactoringSupport.kt @@ -71,10 +71,6 @@ internal class K1RenameRefactoringSupport : KotlinRenameRefactoringSupport { return descriptor.overriddenDescriptors.mapNotNull { it.source.getPsi() } } - override fun getModuleNameSuffixForMangledName(mangledName: String): String? { - return KotlinTypeMapper.InternalNameMapper.getModuleNameSuffix(mangledName) - } - override fun mangleInternalName(name: String, moduleName: String): String { return KotlinTypeMapper.InternalNameMapper.mangleInternalName(name, moduleName) } diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameBackingFieldReferenceHandler.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameBackingFieldReferenceHandler.kt deleted file mode 100644 index 7ef24924bf53..000000000000 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameBackingFieldReferenceHandler.kt +++ /dev/null @@ -1,39 +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.rename - -import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.refactoring.RefactoringBundle -import com.intellij.refactoring.util.CommonRefactoringUtil -import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor -import org.jetbrains.kotlin.idea.base.resources.KotlinBundle -import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall -import org.jetbrains.kotlin.psi.KtSimpleNameExpression - -class RenameBackingFieldReferenceHandler : KotlinVariableInplaceRenameHandler() { - override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean { - val refExpression = file.findElementForRename(editor.caretModel.offset) ?: return false - if (refExpression.text != "field") return false - return refExpression.resolveToCall()?.resultingDescriptor is SyntheticFieldDescriptor - } - - override fun invoke(project: Project, editor: Editor?, file: PsiFile?, dataContext: DataContext) { - editor?.let { - CommonRefactoringUtil.showErrorHint( - project, - editor, - KotlinBundle.message("text.rename.not.applicable.to.backing.field.reference"), - RefactoringBundle.message("rename.title"), - null - ) - } - } - - override fun invoke(project: Project, elements: Array, dataContext: DataContext) { - // Do nothing: this method is called not from editor - } -} diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinImplicitLambdaParameter.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinImplicitLambdaParameter.kt deleted file mode 100644 index e0f6550a1880..000000000000 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinImplicitLambdaParameter.kt +++ /dev/null @@ -1,83 +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.rename - -import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.application.runWriteAction -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiDocumentManager -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import org.jetbrains.kotlin.idea.base.resources.KotlinBundle -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.safeAnalyzeNonSourceRootCode -import org.jetbrains.kotlin.idea.references.mainReference -import org.jetbrains.kotlin.idea.references.resolveToDescriptors -import org.jetbrains.kotlin.idea.util.application.executeWriteCommand -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.resolve.source.getPsi - -class RenameKotlinImplicitLambdaParameter : KotlinVariableInplaceRenameHandler() { - override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean { - val nameExpression = findElementToRename(file, editor) - return nameExpression != null && isAutoCreatedItUsage(nameExpression) - } - - override fun invoke(project: Project, editor: Editor?, file: PsiFile?, dataContext: DataContext) { - if (editor == null || file == null) return - val itExpression = findElementToRename(file, editor) ?: return - val explicitItParameter = project.executeWriteCommand( - KotlinBundle.message("text.convert._it_.to.explicit.lambda.parameter"), - groupId = null, - command = { convertImplicitItToExplicit(itExpression, editor) }, - ) ?: return - - doRename(explicitItParameter, editor, dataContext) - } - - private fun findElementToRename( - file: PsiFile, - editor: Editor, - ) = file.findElementForRename(editor.caretModel.offset) - - override fun invoke(project: Project, elements: Array, dataContext: DataContext) { - // Do nothing: this method is called not from editor - } - - companion object { - fun isAutoCreatedItUsage(expression: KtNameReferenceExpression) = resolveToAutoCreatedItDescriptor(expression) != null - fun convertImplicitItToExplicit(itExpression: KtNameReferenceExpression, editor: Editor): KtParameter? { - val target = itExpression.mainReference.resolveToDescriptors(itExpression.analyze()).single() - val containingDescriptor = target.containingDeclaration ?: return null - val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(containingDescriptor) as? KtFunctionLiteral ?: return null - val newExpr = KtPsiFactory(itExpression.project).createExpression("{ it -> }") as KtLambdaExpression - val arrow = newExpr.functionLiteral.arrow ?: return null - runWriteAction { - functionLiteral.addRangeAfter( - newExpr.functionLiteral.valueParameterList, - arrow, - functionLiteral.lBrace, - ) - } - - PsiDocumentManager.getInstance(itExpression.project).doPostponedOperationsAndUnblockDocument(editor.document) - - return functionLiteral.valueParameters.singleOrNull() - } - - fun getLambdaByImplicitItReference(expression: KtNameReferenceExpression) = - resolveToAutoCreatedItDescriptor(expression)?.containingDeclaration?.source?.getPsi() as? KtFunctionLiteral - - private fun resolveToAutoCreatedItDescriptor(expression: KtNameReferenceExpression): ValueParameterDescriptor? { - if (expression.getReferencedName() != "it") return null - val context = expression.safeAnalyzeNonSourceRootCode(BodyResolveMode.PARTIAL) - val target = expression.mainReference.resolveToDescriptors(context).singleOrNull() as? ValueParameterDescriptor ?: return null - return if (context[BindingContext.AUTO_CREATED_IT, target] == true) target else null - } - } -} diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameOnSecondaryConstructorHandler.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameOnSecondaryConstructorHandler.kt deleted file mode 100644 index c99bbf0a3267..000000000000 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameOnSecondaryConstructorHandler.kt +++ /dev/null @@ -1,52 +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.rename - -import com.intellij.openapi.actionSystem.CommonDataKeys -import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.psi.util.PsiTreeUtil -import com.intellij.refactoring.RefactoringBundle -import com.intellij.refactoring.rename.RenameHandler -import com.intellij.refactoring.util.CommonRefactoringUtil -import org.jetbrains.kotlin.idea.base.resources.KotlinBundle -import org.jetbrains.kotlin.psi.* - - -class RenameOnSecondaryConstructorHandler : RenameHandler { - override fun isAvailableOnDataContext(dataContext: DataContext): Boolean { - val editor = CommonDataKeys.EDITOR.getData(dataContext) ?: return false - val file = CommonDataKeys.PSI_FILE.getData(dataContext) ?: return false - - val element = PsiTreeUtil.findElementOfClassAtOffsetWithStopSet( - file, - editor.caretModel.offset, - KtSecondaryConstructor::class.java, - false, - KtBlockExpression::class.java, - KtValueArgumentList::class.java, - KtParameterList::class.java, - KtConstructorDelegationCall::class.java - ) - return element != null - } - - override fun isRenaming(dataContext: DataContext): Boolean = isAvailableOnDataContext(dataContext) - - override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) { - CommonRefactoringUtil.showErrorHint( - project, - editor, - KotlinBundle.message("text.rename.is.not.applicable.to.secondary.constructors"), - RefactoringBundle.message("rename.title"), - null - ) - } - - override fun invoke(project: Project, elements: Array, dataContext: DataContext?) { - // Do nothing: this method is called not from editor - } -} diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameSyntheticDeclarationByReferenceHandler.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameSyntheticDeclarationByReferenceHandler.kt deleted file mode 100644 index eb4e85e94327..000000000000 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameSyntheticDeclarationByReferenceHandler.kt +++ /dev/null @@ -1,45 +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.rename - -import com.intellij.openapi.actionSystem.CommonDataKeys -import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.refactoring.RefactoringBundle -import com.intellij.refactoring.rename.RenameHandler -import com.intellij.refactoring.util.CommonRefactoringUtil -import org.jetbrains.kotlin.idea.base.resources.KotlinBundle -import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.resolve.calls.tower.isSynthesized -import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor - -class RenameSyntheticDeclarationByReferenceHandler : RenameHandler { - override fun isAvailableOnDataContext(dataContext: DataContext): Boolean { - val file = CommonDataKeys.PSI_FILE.getData(dataContext) ?: return false - val editor = CommonDataKeys.EDITOR.getData(dataContext) ?: return false - val refExpression = file.findElementForRename(editor.caretModel.offset) ?: return false - val descriptor = refExpression.resolveToCall()?.resultingDescriptor ?: return false - // SamConstructorDescriptor is synthetic but it can be renamed - return descriptor !is SamConstructorDescriptor && descriptor.isSynthesized - } - - override fun isRenaming(dataContext: DataContext) = isAvailableOnDataContext(dataContext) - - override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) { - CommonRefactoringUtil.showErrorHint( - project, - editor, - KotlinBundle.message("text.rename.is.not.applicable.to.synthetic.declarations"), - RefactoringBundle.message("rename.title"), - null - ) - } - - override fun invoke(project: Project, elements: Array, dataContext: DataContext?) { - // Do nothing: this method is not called from editor - } -} diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/FE10KotlinTargetElementEvaluator.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/FE10KotlinTargetElementEvaluator.kt index 809cc451cc07..a1879bd5f3ba 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/FE10KotlinTargetElementEvaluator.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/FE10KotlinTargetElementEvaluator.kt @@ -6,23 +6,24 @@ package org.jetbrains.kotlin.idea.search.ideaExtensions import com.intellij.psi.PsiElement import com.intellij.psi.PsiReference +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource -import org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter.Companion.isAutoCreatedItUsage import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtLambdaExpression import org.jetbrains.kotlin.psi.KtNameReferenceExpression import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.source.getPsi +import org.jetbrains.kotlin.idea.codeinsight.utils.isReferenceToImplicitLambdaParameter class FE10KotlinTargetElementEvaluator : KotlinTargetElementEvaluator() { companion object { fun findLambdaOpenLBraceForGeneratedIt(ref: PsiReference): PsiElement? { val element: PsiElement = ref.element - if (element.text != "it") return null + if (element.text != StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier) return null - if (element !is KtNameReferenceExpression || !isAutoCreatedItUsage(element)) return null + if (element !is KtNameReferenceExpression || !element.isReferenceToImplicitLambdaParameter()) return null val itDescriptor = element.resolveMainReferenceToDescriptors().singleOrNull() ?: return null val descriptorWithSource = itDescriptor.containingDeclaration as? DeclarationDescriptorWithSource ?: return null diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/slicer/InflowSlicer.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/slicer/InflowSlicer.kt index 67100f673743..e75695dc3047 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/slicer/InflowSlicer.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/slicer/InflowSlicer.kt @@ -9,6 +9,7 @@ import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.slicer.SliceUsage import com.intellij.usageView.UsageInfo import com.intellij.util.Processor +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.* @@ -231,7 +232,7 @@ class InflowSlicer( is ValueParameterDescriptor -> { if (accessedDeclaration == null) { val anonymousFunction = accessedDescriptor.containingDeclaration as? AnonymousFunctionDescriptor - if (anonymousFunction != null && accessedDescriptor.name.asString() == "it") { + if (anonymousFunction != null && accessedDescriptor.name == StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME) { val functionLiteral = anonymousFunction.source.getPsi() as KtFunctionLiteral val parameterDescriptor = anonymousFunction.valueParameters.first() processCalls(functionLiteral, false, ArgumentSliceProducer(parameterDescriptor)) @@ -379,7 +380,7 @@ class InflowSlicer( private fun KtFunctionLiteral.implicitItUsages(): Collection { return collectDescendantsOfType(fun(expression: KtSimpleNameExpression): Boolean { - if (expression.getQualifiedExpressionForSelector() != null || expression.getReferencedName() != "it") return false + if (expression.getQualifiedExpressionForSelector() != null || expression.getReferencedNameAsName() != StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME) return false val lBrace = FE10KotlinTargetElementEvaluator.findLambdaOpenLBraceForGeneratedIt(expression.mainReference) ?: return false return lBrace == this.lBrace.node.treeNext.psi }) diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/testIntegration/KotlinCreateTestIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/testIntegration/KotlinCreateTestIntention.kt index 3fb796d2908a..b0981b6999fc 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/testIntegration/KotlinCreateTestIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/testIntegration/KotlinCreateTestIntention.kt @@ -195,7 +195,7 @@ class KotlinCreateTestIntention : SelfTargetingRangeIntention + \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/asJava/classes/IdeLightClassesByFqNameTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/asJava/classes/IdeLightClassesByFqNameTestGenerated.java index b885f526a23d..db2365c970d8 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/asJava/classes/IdeLightClassesByFqNameTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/asJava/classes/IdeLightClassesByFqNameTestGenerated.java @@ -83,6 +83,21 @@ public abstract class IdeLightClassesByFqNameTestGenerated extends AbstractIdeLi runTest(compilerTestData("compiler/testData/asJava/lightClasses/lightClassByFqName/compilationErrors/ExpectedNestedClassInObject.kt")); } + @TestMetadata("FieldWithoutName.kt") + public void testFieldWithoutName() throws Exception { + runTest(compilerTestData("compiler/testData/asJava/lightClasses/lightClassByFqName/compilationErrors/FieldWithoutName.kt")); + } + + @TestMetadata("FieldWithoutName2.kt") + public void testFieldWithoutName2() throws Exception { + runTest(compilerTestData("compiler/testData/asJava/lightClasses/lightClassByFqName/compilationErrors/FieldWithoutName2.kt")); + } + + @TestMetadata("FieldWithoutName3.kt") + public void testFieldWithoutName3() throws Exception { + runTest(compilerTestData("compiler/testData/asJava/lightClasses/lightClassByFqName/compilationErrors/FieldWithoutName3.kt")); + } + @TestMetadata("FunctionWithoutName.kt") public void testFunctionWithoutName() throws Exception { runTest(compilerTestData("compiler/testData/asJava/lightClasses/lightClassByFqName/compilationErrors/FunctionWithoutName.kt")); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/asJava/classes/IdeLightClassesByPsiTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/asJava/classes/IdeLightClassesByPsiTestGenerated.java index 7a85192a2644..b69c7c8521a3 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/asJava/classes/IdeLightClassesByPsiTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/asJava/classes/IdeLightClassesByPsiTestGenerated.java @@ -83,6 +83,11 @@ public abstract class IdeLightClassesByPsiTestGenerated extends AbstractIdeLight runTest(compilerTestData("compiler/testData/asJava/lightClasses/lightClassByPsi/facades/properties.kt")); } + @TestMetadata("reifiedInlineReturnsObject.kt") + public void testReifiedInlineReturnsObject() throws Exception { + runTest(compilerTestData("compiler/testData/asJava/lightClasses/lightClassByPsi/facades/reifiedInlineReturnsObject.kt")); + } + @TestMetadata("simpleFunctions.kt") public void testSimpleFunctions() throws Exception { runTest(compilerTestData("compiler/testData/asJava/lightClasses/lightClassByPsi/facades/simpleFunctions.kt")); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/findUsages/FindUsagesTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/findUsages/FindUsagesTestGenerated.java index 6c06b5d5b5ed..69a1f75cb743 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/findUsages/FindUsagesTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/findUsages/FindUsagesTestGenerated.java @@ -1266,6 +1266,11 @@ public abstract class FindUsagesTestGenerated extends AbstractFindUsagesTest { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("classAlias.0.kt") + public void testClassAlias() throws Exception { + runTest("testData/findUsages/kotlin/findTypeAliasUsages/classAlias.0.kt"); + } + @TestMetadata("objectAlias.0.kt") public void testObjectAlias() throws Exception { runTest("testData/findUsages/kotlin/findTypeAliasUsages/objectAlias.0.kt"); @@ -1289,6 +1294,11 @@ public abstract class FindUsagesTestGenerated extends AbstractFindUsagesTest { runTest("testData/findUsages/kotlin/findTypeParameterUsages/kotlinFunctionTypeParameterUsages.0.kt"); } + @TestMetadata("kotlinReifiedTypeParameterUsages.0.kt") + public void testKotlinReifiedTypeParameterUsages() throws Exception { + runTest("testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.0.kt"); + } + @TestMetadata("propertyWithTypeParameter.0.kt") public void testPropertyWithTypeParameter() throws Exception { runTest("testData/findUsages/kotlin/findTypeParameterUsages/propertyWithTypeParameter.0.kt"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/KotlinIconProviderTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/KotlinIconProviderTest.kt index cc330428faa9..ee17058d5ace 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/KotlinIconProviderTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/KotlinIconProviderTest.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlin.idea import com.intellij.openapi.util.Iconable +import com.intellij.psi.search.searches.ClassInheritorsSearch import com.intellij.ui.icons.RowIcon import com.intellij.util.PsiIconUtil import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase @@ -41,6 +42,15 @@ class KotlinIconProviderTest: KotlinLightCodeInsightFixtureTestCase() { createFileAndCheckIcon("Foo.kt", fileBody, "org/jetbrains/kotlin/idea/icons/kotlin_file.svg") } + fun testJavaBase() { + val aClass = myFixture.addClass("public class BaseJavaClass {}") + myFixture.addFileToProject("foo.kt", "class Foo : BaseJavaClass() {}") + val psiClass = ClassInheritorsSearch.search(aClass).findFirst()!! + val icon = PsiIconUtil.getProvidersIcon(psiClass, Iconable.ICON_FLAG_VISIBILITY or Iconable.ICON_FLAG_READ_STATUS) + val iconString = (icon.safeAs()?.allIcons?.joinToString(transform = Icon::toString) ?: icon)?.toString() + assertEquals("org/jetbrains/kotlin/idea/icons/classKotlin.svg", iconString) + } + private fun createFileAndCheckIcon(fileName: String, fileBody: String, vararg icons: String) { val psiFile = myFixture.configureByText(fileName, fileBody) val icon = PsiIconUtil.getProvidersIcon(psiFile, Iconable.ICON_FLAG_VISIBILITY or Iconable.ICON_FLAG_READ_STATUS) diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/AbstractKotlinAddImportActionTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/AbstractAddImportActionTestBase.kt similarity index 61% rename from plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/AbstractKotlinAddImportActionTest.kt rename to plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/AbstractAddImportActionTestBase.kt index 3d736c9110d7..20a000dfb85e 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/AbstractKotlinAddImportActionTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/AbstractAddImportActionTestBase.kt @@ -2,17 +2,17 @@ package org.jetbrains.kotlin.idea.actions import com.intellij.openapi.util.io.FileUtil -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import com.intellij.psi.statistics.StatisticsInfo +import com.intellij.psi.statistics.StatisticsManager +import com.intellij.psi.statistics.impl.StatisticsManagerImpl +import org.jetbrains.kotlin.idea.quickfix.AutoImportVariant import org.jetbrains.kotlin.idea.test.InTextDirectivesUtils import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase -import org.jetbrains.kotlin.renderer.DescriptorRenderer -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import java.io.File -abstract class AbstractKotlinAddImportActionTest : KotlinLightCodeInsightFixtureTestCase() { +abstract class AbstractAddImportActionTestBase : KotlinLightCodeInsightFixtureTestCase() { - protected fun doTest(unused: String) { + protected open fun doTest(unused: String) { val fixture = myFixture val dependencySuffixes = listOf(".dependency.kt", ".dependency1.kt", ".dependency2.kt") @@ -29,30 +29,33 @@ abstract class AbstractKotlinAddImportActionTest : KotlinLightCodeInsightFixture fixture.configureByFile(fileName()) - var actualVariants: List>? = null + var actualVariants: List? = null val executeListener = object : KotlinAddImportActionInfo.ExecuteListener { - override fun onExecute(variants: List>) { + override fun onExecute(variants: List) { assertNull(actualVariants) actualVariants = variants } } KotlinAddImportActionInfo.setExecuteListener(testRootDisposable, executeListener) + (StatisticsManager.getInstance() as StatisticsManagerImpl).enableStatistics(myFixture.testRootDisposable) + increaseUseCountOf(InTextDirectivesUtils.findListWithPrefixes(fixture.file.text, INCREASE_USE_COUNT_DIRECTIVE)) + val importFix = myFixture.availableIntentions.singleOrNull { it.familyName == "Import" } ?: error("No import fix available") importFix.invoke(project, editor, file) assertNotNull(actualVariants) - val expectedVariantNames = InTextDirectivesUtils.findListWithPrefixes(fixture.file.text, "EXPECT_VARIANT_IN_ORDER") - val expectedAbsentVariantNames = InTextDirectivesUtils.findListWithPrefixes(fixture.file.text, "EXPECT_VARIANT_NOT_PRESENT") + val expectedVariantNames = InTextDirectivesUtils.findListWithPrefixes(fixture.file.text, EXPECT_VARIANT_IN_ORDER_DIRECTIVE) + val expectedAbsentVariantNames = InTextDirectivesUtils.findListWithPrefixes(fixture.file.text, EXPECT_VARIANT_NOT_PRESENT_DIRECTIVE) if (expectedVariantNames.isNotEmpty() || expectedAbsentVariantNames.isNotEmpty()) { - val actualVariantNames = actualVariants!!.flatten().map { it.variantName() } + val actualVariantNames = actualVariants.orEmpty().map { it.debugRepresentation } for (i in expectedVariantNames.indices) { assertTrue( "mismatch at #$i: '${actualVariantNames[i]}' should start with '${expectedVariantNames[i]}'\nactual:\n${ - actualVariantNames.joinToString("\n") { "// EXPECT_VARIANT_IN_ORDER \"$it\"" } + actualVariantNames.joinToString("\n") { "// ${EXPECT_VARIANT_IN_ORDER_DIRECTIVE} \"$it\"" } }", actualVariantNames[i].contains(expectedVariantNames[i]) ) @@ -67,10 +70,15 @@ abstract class AbstractKotlinAddImportActionTest : KotlinLightCodeInsightFixture myFixture.checkResultByFile("${fileName()}.after") } - private fun DeclarationDescriptor.variantName() = when(this) { - is ClassDescriptor -> - fqNameOrNull()?.toString()?.let { "class $it" } ?: DescriptorRenderer.DEBUG_TEXT.render(this) - else -> - DescriptorRenderer.DEBUG_TEXT.render(this) + private fun increaseUseCountOf(statisticsInfoValues: List) { + statisticsInfoValues.forEach { value -> + StatisticsManager.getInstance().incUseCount(StatisticsInfo("", value)) + } + } + + companion object { + private const val EXPECT_VARIANT_IN_ORDER_DIRECTIVE: String = "EXPECT_VARIANT_IN_ORDER" + private const val EXPECT_VARIANT_NOT_PRESENT_DIRECTIVE: String = "EXPECT_VARIANT_NOT_PRESENT" + private const val INCREASE_USE_COUNT_DIRECTIVE: String = "INCREASE_USE_COUNT" } } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/AbstractK1AddImportActionTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/AbstractK1AddImportActionTest.kt new file mode 100644 index 000000000000..ad33d4b03454 --- /dev/null +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/AbstractK1AddImportActionTest.kt @@ -0,0 +1,4 @@ +// 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.actions + +abstract class AbstractK1AddImportActionTest : AbstractAddImportActionTestBase() \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/KotlinAddImportActionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/K1AddImportActionTestGenerated.java similarity index 93% rename from plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/KotlinAddImportActionTestGenerated.java rename to plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/K1AddImportActionTestGenerated.java index 6734d864822a..84ddbe74b36d 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/KotlinAddImportActionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/actions/K1AddImportActionTestGenerated.java @@ -18,7 +18,7 @@ import org.junit.runner.RunWith; @TestDataPath("$CONTENT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("testData/idea/actions/kotlinAddImportAction") -public class KotlinAddImportActionTestGenerated extends AbstractKotlinAddImportActionTest { +public class K1AddImportActionTestGenerated extends AbstractK1AddImportActionTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -168,6 +168,11 @@ public class KotlinAddImportActionTestGenerated extends AbstractKotlinAddImportA runTest("testData/idea/actions/kotlinAddImportAction/TypeAlias.kt"); } + @TestMetadata("VarargSpreadOperator.kt") + public void testVarargSpreadOperator() throws Exception { + runTest("testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.kt"); + } + @TestMetadata("Varargs.kt") public void testVarargs() throws Exception { runTest("testData/idea/actions/kotlinAddImportAction/Varargs.kt"); @@ -182,4 +187,9 @@ public class KotlinAddImportActionTestGenerated extends AbstractKotlinAddImportA public void testVarargs3() throws Exception { runTest("testData/idea/actions/kotlinAddImportAction/Varargs3.kt"); } + + @TestMetadata("WithStatisticsInfo.kt") + public void testWithStatisticsInfo() throws Exception { + runTest("testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.kt"); + } } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/CompiledFilesHighlightingTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/CompiledFilesHighlightingTest.kt index cc9a49adb9be..29d0423e66b7 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/CompiledFilesHighlightingTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/CompiledFilesHighlightingTest.kt @@ -8,6 +8,7 @@ import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.psi.PsiManager import com.intellij.rt.execution.junit.FileComparisonFailure import com.intellij.testFramework.ExpectedHighlightingData import com.intellij.testFramework.TestDataPath @@ -15,7 +16,9 @@ import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.idea.base.plugin.artifacts.TestKotlinArtifacts import org.jetbrains.kotlin.idea.base.test.TestRoot +import org.jetbrains.kotlin.idea.jvmDecompiler.KotlinBytecodeDecompilerTask import org.jetbrains.kotlin.idea.test.* +import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.TestMetadata import org.junit.runner.RunWith import java.io.File @@ -40,7 +43,18 @@ class CompiledFilesHighlightingTest: KotlinLightCodeInsightFixtureTestCase() { doTestWithLibraryFile(TestKotlinArtifacts.kotlinStdlibNative) } - private fun doTestWithLibraryFile(libraryFile: File) { + @TestMetadata("kotlin/annotations/OptIn.kt") + fun testDecompiledCodeKotlinAnnotationsOptInKt() { + withLibrary(TestKotlinArtifacts.kotlinStdlib) { + doTestWithLibraryFile(TestKotlinArtifacts.kotlinStdlibCommonSources) { + val file = PsiManager.getInstance(project).findFile(it) ?: error("unable to locate PSI for $it") + val ktFile = file as? KtFile ?: error("file expected to be KtFile") + KotlinBytecodeDecompilerTask(ktFile).generateDecompiledVirtualFile() ?: error("unable to generate decompiled file") + } + } + } + + private fun doTestWithLibraryFile(libraryFile: File, openFileAction: (VirtualFile) -> VirtualFile = { it }) { val libraryVirtualFile = if (libraryFile.extension == "jar") { StandardFileSystems.jar().findFileByPath(libraryFile.absolutePath + URLUtil.JAR_SEPARATOR) @@ -51,13 +65,20 @@ class CompiledFilesHighlightingTest: KotlinLightCodeInsightFixtureTestCase() { for (childName in fileName().split("/")) { virtualFile = virtualFile.findChild(childName) ?: error("unable to locate $childName in $virtualFile") } + withLibrary(libraryFile) { + val fileToOpen = openFileAction(virtualFile) + myFixture.openFileInEditor(fileToOpen) + doTest() + } + } + + private fun withLibrary(libraryFile: File, block: () -> Unit) { val libraryName = "library ${libraryFile.name}" ConfigLibraryUtil.addLibrary(module, libraryName) { addRoot(libraryFile, OrderRootType.CLASSES) } try { - myFixture.openFileInEditor(virtualFile) - doTest() + block() } finally { ConfigLibraryUtil.removeLibrary(module, libraryName) } @@ -68,7 +89,7 @@ class CompiledFilesHighlightingTest: KotlinLightCodeInsightFixtureTestCase() { try { withCustomCompilerOptions(fileText, project, module) { (myFixture as CodeInsightTestFixtureImpl).canChangeDocumentDuringHighlighting(false) - val data = ExpectedHighlightingData(DocumentImpl(fileText), true, true, true, true) + val data = ExpectedHighlightingData(DocumentImpl(fileText), true, true, true) data.init() (myFixture as CodeInsightTestFixtureImpl).collectAndCheckHighlighting(data) } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/K1HighlightingMetaInfoTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/K1HighlightingMetaInfoTestGenerated.java index 777d24c32f72..cd2fb1fe82cf 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/K1HighlightingMetaInfoTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/K1HighlightingMetaInfoTestGenerated.java @@ -19,6 +19,29 @@ import org.junit.runner.RunWith; @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("testData/highlighterMetaInfo") public abstract class K1HighlightingMetaInfoTestGenerated extends AbstractK1HighlightingMetaInfoTest { + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("testData/highlighterMetaInfo/diagnostics") + public static class Diagnostics extends AbstractK1HighlightingMetaInfoTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("classRedeclaration.kt") + public void testClassRedeclaration() throws Exception { + runTest("testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt"); + } + + @TestMetadata("javaCodeInKotlinFile1.kt") + public void testJavaCodeInKotlinFile1() throws Exception { + runTest("testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt"); + } + + @TestMetadata("mppIsNotEnabled.kt") + public void testMppIsNotEnabled() throws Exception { + runTest("testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("testData/highlighterMetaInfo/dsl") public static class Dsl extends AbstractK1HighlightingMetaInfoTest { diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 43dc1df79c27..0d08ed4d79cc 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -6554,6 +6554,21 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti runTest("testData/inspectionsLocal/liftOut/ifToAssignment/lambda2.kt"); } + @TestMetadata("multiStatement.kt") + public void testMultiStatement() throws Exception { + runTest("testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement.kt"); + } + + @TestMetadata("multiStatement2.kt") + public void testMultiStatement2() throws Exception { + runTest("testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement2.kt"); + } + + @TestMetadata("multiStatement3.kt") + public void testMultiStatement3() throws Exception { + runTest("testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement3.kt"); + } + @TestMetadata("multipleAssignments.kt") public void testMultipleAssignments() throws Exception { runTest("testData/inspectionsLocal/liftOut/ifToAssignment/multipleAssignments.kt"); @@ -6687,6 +6702,21 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti runTest("testData/inspectionsLocal/liftOut/ifToReturn/innerIfTransformed.kt"); } + @TestMetadata("multiStatement.kt") + public void testMultiStatement() throws Exception { + runTest("testData/inspectionsLocal/liftOut/ifToReturn/multiStatement.kt"); + } + + @TestMetadata("multiStatement2.kt") + public void testMultiStatement2() throws Exception { + runTest("testData/inspectionsLocal/liftOut/ifToReturn/multiStatement2.kt"); + } + + @TestMetadata("multiStatement3.kt") + public void testMultiStatement3() throws Exception { + runTest("testData/inspectionsLocal/liftOut/ifToReturn/multiStatement3.kt"); + } + @TestMetadata("onReturn.kt") public void testOnReturn() throws Exception { runTest("testData/inspectionsLocal/liftOut/ifToReturn/onReturn.kt"); 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 2be6ddac01bd..567f3a8fc331 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 @@ -17521,6 +17521,11 @@ public abstract class K1IntentionTestGenerated extends AbstractK1IntentionTest { runTest("testData/intentions/specifyTypeExplicitly/destructuringInLambda.kt"); } + @TestMetadata("destructuringInLoopParameter.kt") + public void testDestructuringInLoopParameter() throws Exception { + runTest("testData/intentions/specifyTypeExplicitly/destructuringInLoopParameter.kt"); + } + @TestMetadata("enumType.kt") public void testEnumType() throws Exception { runTest("testData/intentions/specifyTypeExplicitly/enumType.kt"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiModuleTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiModuleTest.kt index 87d962ead522..7842a179956a 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiModuleTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiModuleTest.kt @@ -55,7 +55,7 @@ abstract class AbstractQuickFixMultiModuleTest : AbstractMultiModuleTest(), Quic return null } - private fun doQuickFixTest(dirPath: String) { + protected open fun doQuickFixTest(dirPath: String) { val actionFile = project.findFileWithCaret() val virtualFile = actionFile.virtualFile!! val mainFile = virtualFile.toIOFile()?.takeIf(File::exists) ?: error("unable to lookup source io file") diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index 18433ae6254c..cc35e8e72e85 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -390,6 +390,11 @@ public abstract class QuickFixMultiFileTestGenerated extends AbstractQuickFixMul runTest("testData/quickfix/autoImports/functionImport.before.Main.kt"); } + @TestMetadata("functionPreferNotDeprecated.test") + public void testFunctionPreferNotDeprecated() throws Exception { + runTest("testData/quickfix/autoImports/functionPreferNotDeprecated.test"); + } + @TestMetadata("importAliasClassAlreadyExists.before.Main.kt") public void testImportAliasClassAlreadyExists() throws Exception { runTest("testData/quickfix/autoImports/importAliasClassAlreadyExists.before.Main.kt"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/InplaceRenameTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/InplaceRenameTest.kt index aa83601c3f66..027a3ef766ad 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/InplaceRenameTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/InplaceRenameTest.kt @@ -13,8 +13,8 @@ import com.intellij.testFramework.fixtures.CodeInsightTestUtil import junit.framework.TestCase import org.jetbrains.kotlin.idea.refactoring.rename.KotlinMemberInplaceRenameHandler import org.jetbrains.kotlin.idea.refactoring.rename.KotlinVariableInplaceRenameHandler -import org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter import org.jetbrains.kotlin.idea.refactoring.rename.findElementForRename +import org.jetbrains.kotlin.idea.refactoring.rename.handlers.RenameKotlinImplicitLambdaParameter import org.jetbrains.kotlin.idea.test.IDEA_TEST_DATA_DIR import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.psi.KtNameReferenceExpression diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt index bd09c0965ce9..1c81fb332aa3 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt @@ -33,7 +33,7 @@ import com.intellij.testFramework.PlatformTestUtil import com.intellij.testFramework.UsefulTestCase import com.intellij.testFramework.fixtures.CodeInsightTestUtil import org.jetbrains.kotlin.asJava.finder.KtLightPackage -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies import org.jetbrains.kotlin.idea.base.plugin.artifacts.TestKotlinArtifacts import org.jetbrains.kotlin.idea.base.util.allScope import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks 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 1c99dff06c0a..e6d950ed7e95 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 @@ -23,6 +23,11 @@ public class RenameTestGenerated extends AbstractRenameTest { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("abstractFunction/abstractFunction.test") + public void testAbstractFunction_AbstractFunction() throws Exception { + runTest("testData/refactoring/rename/abstractFunction/abstractFunction.test"); + } + @TestMetadata("ambiguousClassFunImportRenameClass/ambiguousClassFunImportRenameClass.test") public void testAmbiguousClassFunImportRenameClass_AmbiguousClassFunImportRenameClass() throws Exception { runTest("testData/refactoring/rename/ambiguousClassFunImportRenameClass/ambiguousClassFunImportRenameClass.test"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/structureView/KotlinFileStructureTestBase.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/structureView/KotlinFileStructureTestBase.kt index bc2435b676c1..c952f4e2ec8f 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/structureView/KotlinFileStructureTestBase.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/structureView/KotlinFileStructureTestBase.kt @@ -39,7 +39,7 @@ abstract class KotlinFileStructureTestBase : KotlinLightCodeInsightFixtureTestCa ) } - protected fun getFileName(ext: String): String { + protected open fun getFileName(ext: String): String { return getTestName(false) + if (StringUtil.isEmpty(ext)) "" else ".$ext" } diff --git a/plugins/kotlin/idea/tests/testData/editor/optimizeImports/common/ComponentFunction.kt b/plugins/kotlin/idea/tests/testData/editor/optimizeImports/common/ComponentFunction.kt index bae53998698b..dd5a4dbadbd6 100644 --- a/plugins/kotlin/idea/tests/testData/editor/optimizeImports/common/ComponentFunction.kt +++ b/plugins/kotlin/idea/tests/testData/editor/optimizeImports/common/ComponentFunction.kt @@ -6,3 +6,4 @@ import test1.component2 fun foo() { val (a, b) = MyClass() } +// FIR_COMPARISON \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/optimizeImports/common/ComponentFunction.kt.after b/plugins/kotlin/idea/tests/testData/editor/optimizeImports/common/ComponentFunction.kt.after index bae53998698b..374a3e18116e 100644 --- a/plugins/kotlin/idea/tests/testData/editor/optimizeImports/common/ComponentFunction.kt.after +++ b/plugins/kotlin/idea/tests/testData/editor/optimizeImports/common/ComponentFunction.kt.after @@ -6,3 +6,4 @@ import test1.component2 fun foo() { val (a, b) = MyClass() } +// FIR_COMPARISON diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.0.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.0.kt index cb6f401ffae1..5ab3dcaf9dae 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.0.kt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.0.kt @@ -10,6 +10,8 @@ open class A: X { } +typealias TA = A + interface Y : X { } diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.1.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.1.kt index 1cf9c865165d..8fdce7c49f78 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.1.kt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.1.kt @@ -16,3 +16,5 @@ open class Z : A() { class U : Z() { } + +class InheritTypeAlias : TA() diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.results.txt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.results.txt index 703b7ecfd4ec..f0191b16dab8 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.results.txt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findClassUsages/kotlinClassDerivedClasses.results.txt @@ -1,5 +1,6 @@ [kotlinClassDerivedClasses.1.kt] Unclassified 12 open class Z : A() { [kotlinClassDerivedClasses.1.kt] Unclassified 16 class U : Z() { +[kotlinClassDerivedClasses.1.kt] Unclassified 20 class InheritTypeAlias : TA() [kotlinClassDerivedClasses.1.kt] Unclassified 4 open class B : A() { [kotlinClassDerivedClasses.2.kt] Unclassified 1 open class SimpleClass : A() [kotlinClassDerivedClasses.3.kt] Unclassified 1 object abc : A() diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.0.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.0.kt new file mode 100644 index 000000000000..7b6966827ffc --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.0.kt @@ -0,0 +1,45 @@ +// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtTypeAlias +// OPTIONS: usages + +open class OOO { + + open fun opFun() {} + + companion object { + const val CONST = "" + } + +} +typealias Alias = OOO + +class Child : Alias() { + + override fun opFun() { + super.opFun() //not found in K2, see KTIJ-26095 + } +} + +class Child2 : OOO() + +class WithGeneric + +fun f2(par: Alias, par2: OOO) : Alias { + + val a: Alias + + a = Alias() //not found in K2, see KTIJ-26095 + + val b = WithGeneric() //not found in K2, see KTIJ-26095 + val b2 = WithGeneric() + + Alias.CONST //not found in K1, found in K2 + OOO.CONST + + if (par2 is Alias) {} + if (par2 is OOO) {} + + val c = par2 as Alias + val c2 = par2 as OOO + + return c +} \ No newline at end of file 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 new file mode 100644 index 000000000000..57ca5ef0fc98 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.fir.results.txt @@ -0,0 +1,7 @@ +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) {} +Usage in cast target type 41 val c = par2 as Alias diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.results.txt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.results.txt new file mode 100644 index 000000000000..b12d027d0615 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeAliasUsages/classAlias.results.txt @@ -0,0 +1,9 @@ +Function return types 26 fun f2(par: Alias, par2: OOO) : Alias { +Local variable declaration 28 val a: Alias +New instance creation 30 a = Alias() //not found in K2, see KTIJ-26095 +Parameter type 26 fun f2(par: Alias, par2: OOO) : Alias { +Super type qualifier 18 super.opFun() //not found in K2, see KTIJ-26095 +Supertype 15 class Child : Alias() { +Target type of 'is' operation 38 if (par2 is Alias) {} +Type parameter 32 val b = WithGeneric() //not found in K2, see KTIJ-26095 +Usage in cast target type 41 val c = par2 as Alias diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinClassTypeParameterUsages.0.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinClassTypeParameterUsages.0.kt index d2941e31f309..07aa799e208a 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinClassTypeParameterUsages.0.kt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinClassTypeParameterUsages.0.kt @@ -10,5 +10,7 @@ open class A<T>(foo: T, list: List) { val t: T = foo val T.d: Boolean get() = true fun bar(t: T): T = t + + fun ff() {} } diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinClassTypeParameterUsages.results.txt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinClassTypeParameterUsages.results.txt index 991a698720ab..7ca7b2f39d6e 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinClassTypeParameterUsages.results.txt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinClassTypeParameterUsages.results.txt @@ -4,4 +4,5 @@ Extension receiver type 5 fun T.bar() {} Function return types 12 fun bar(t: T): T = t Parameter type 12 fun bar(t: T): T = t Parameter type 3 open class A(foo: T, list: List) { +Type constraint 14 fun ff() {} Type parameter 3 open class A(foo: T, list: List) { 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 new file mode 100644 index 000000000000..246bb308f4a3 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.0.kt @@ -0,0 +1,7 @@ +// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtTypeParameter +// OPTIONS: usages + +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 +} \ 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 new file mode 100644 index 000000000000..ef5aa14d81eb --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.fir.results.txt @@ -0,0 +1,2 @@ +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 new file mode 100644 index 000000000000..70118629da9a --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findTypeParameterUsages/kotlinReifiedTypeParameterUsages.results.txt @@ -0,0 +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 diff --git a/plugins/kotlin/idea/tests/testData/highlighter/compiled/kotlin.annotations.OptIn.kt.txt b/plugins/kotlin/idea/tests/testData/highlighter/compiled/kotlin.annotations.OptIn.kt.txt new file mode 100644 index 000000000000..a14c43e4539f --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/highlighter/compiled/kotlin.annotations.OptIn.kt.txt @@ -0,0 +1,125 @@ +// SubclassOptInRequired.java +package kotlin; + +import java.lang.annotation.ElementType; +import java.lang.annotation.RetentionPolicy; +import kotlin.annotation.AnnotationRetention; +import kotlin.annotation.AnnotationTarget; +import kotlin.annotation.Retention; +import kotlin.annotation.Target; + +@Target( + allowedTargets = {AnnotationTarget.CLASS} +) +@Retention(AnnotationRetention.BINARY) +@java.lang.annotation.Retention(RetentionPolicy.CLASS) +@java.lang.annotation.Target({ElementType.TYPE}) +@Metadata( + mv = {1, 8, 0}, + k = 1, + d1 = {"\u0000\u0012\n\u0002\u0018\u0002\n\u0002\u0010\u001b\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0002\b\u0087\u0002\u0018\u00002\u00020\u0001B\u0010\u0012\u000e\u0010\u0002\u001a\n\u0012\u0006\b\u0001\u0012\u00020\u00010\u0003R\u0017\u0010\u0002\u001a\n\u0012\u0006\b\u0001\u0012\u00020\u00010\u0003¢\u0006\u0006\u001a\u0004\b\u0002\u0010\u0004¨\u0006\u0005"}, + d2 = {"Lkotlin/SubclassOptInRequired;", "", "markerClass", "Lkotlin/reflect/KClass;", "()Ljava/lang/Class;", "special module for files not under source root"} +) +@SinceKotlin( + version = "1.8" +) +@ExperimentalSubclassOptIn +public @interface SubclassOptInRequired { + Class markerClass(); +} +// OptIn.java +package kotlin; + +import java.lang.annotation.ElementType; +import java.lang.annotation.RetentionPolicy; +import kotlin.annotation.AnnotationRetention; +import kotlin.annotation.AnnotationTarget; +import kotlin.annotation.Retention; +import kotlin.annotation.Target; + +@Target( + allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.EXPRESSION, AnnotationTarget.FILE, AnnotationTarget.TYPEALIAS} +) +@Retention(AnnotationRetention.SOURCE) +@java.lang.annotation.Retention(RetentionPolicy.SOURCE) +@java.lang.annotation.Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE}) +@Metadata( + mv = {1, 8, 0}, + k = 1, + d1 = {"\u0000\u0016\n\u0002\u0018\u0002\n\u0002\u0010\u001b\n\u0000\n\u0002\u0010\u0011\n\u0002\u0018\u0002\n\u0002\b\u0002\b\u0087\u0002\u0018\u00002\u00020\u0001B$\u0012\"\u0010\u0002\u001a\u0012\u0012\u000e\b\u0001\u0012\n\u0012\u0006\b\u0001\u0012\u00020\u00010\u00040\u0003\"\n\u0012\u0006\b\u0001\u0012\u00020\u00010\u0004R\u001f\u0010\u0002\u001a\u0012\u0012\u000e\b\u0001\u0012\n\u0012\u0006\b\u0001\u0012\u00020\u00010\u00040\u0003¢\u0006\u0006\u001a\u0004\b\u0002\u0010\u0005¨\u0006\u0006"}, + d2 = {"Lkotlin/OptIn;", "", "markerClass", "", "Lkotlin/reflect/KClass;", "()[Ljava/lang/Class;", "special module for files not under source root"} +) +@SinceKotlin( + version = "1.3" +) +public @interface OptIn { + Class[] markerClass(); +} +// ExperimentalSubclassOptIn.java +package kotlin; + +import java.lang.annotation.ElementType; +import java.lang.annotation.RetentionPolicy; +import kotlin.annotation.AnnotationRetention; +import kotlin.annotation.AnnotationTarget; +import kotlin.annotation.Retention; +import kotlin.annotation.Target; + +@Target( + allowedTargets = {AnnotationTarget.CLASS} +) +@Retention(AnnotationRetention.BINARY) +@java.lang.annotation.Retention(RetentionPolicy.CLASS) +@java.lang.annotation.Target({ElementType.TYPE}) +@Metadata( + mv = {1, 8, 0}, + k = 1, + d1 = {"\u0000\n\n\u0002\u0018\u0002\n\u0002\u0010\u001b\n\u0000\b\u0087\u0002\u0018\u00002\u00020\u0001B\u0000¨\u0006\u0002"}, + d2 = {"Lkotlin/ExperimentalSubclassOptIn;", "", "special module for files not under source root"} +) +@SinceKotlin( + version = "1.8" +) +public @interface ExperimentalSubclassOptIn { +} +// RequiresOptIn.java +package kotlin; + +import java.lang.annotation.ElementType; +import java.lang.annotation.RetentionPolicy; +import kotlin.annotation.AnnotationRetention; +import kotlin.annotation.AnnotationTarget; +import kotlin.annotation.Retention; +import kotlin.annotation.Target; + +@Target( + allowedTargets = {AnnotationTarget.ANNOTATION_CLASS} +) +@Retention(AnnotationRetention.BINARY) +@java.lang.annotation.Retention(RetentionPolicy.CLASS) +@java.lang.annotation.Target({ElementType.ANNOTATION_TYPE}) +@Metadata( + mv = {1, 8, 0}, + k = 1, + d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u001b\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0004\b\u0087\u0002\u0018\u00002\u00020\u0001:\u0001\bB\u0014\u0012\b\b\u0002\u0010\u0002\u001a\u00020\u0003\u0012\b\b\u0002\u0010\u0004\u001a\u00020\u0005R\u000f\u0010\u0004\u001a\u00020\u0005¢\u0006\u0006\u001a\u0004\b\u0004\u0010\u0006R\u000f\u0010\u0002\u001a\u00020\u0003¢\u0006\u0006\u001a\u0004\b\u0002\u0010\u0007¨\u0006\t"}, + d2 = {"Lkotlin/RequiresOptIn;", "", "message", "", "level", "Lkotlin/RequiresOptIn$Level;", "()Lkotlin/RequiresOptIn$Level;", "()Ljava/lang/String;", "Level", "special module for files not under source root"} +) +@SinceKotlin( + version = "1.3" +) +public @interface RequiresOptIn { + String message() default ""; + + Level level() default RequiresOptIn.Level.ERROR; + + @Metadata( + mv = {1, 8, 0}, + k = 1, + d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0010\u0010\n\u0002\b\u0004\b\u0086\u0001\u0018\u00002\b\u0012\u0004\u0012\u00020\u00000\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002j\u0002\b\u0003j\u0002\b\u0004¨\u0006\u0005"}, + d2 = {"Lkotlin/RequiresOptIn$Level;", "", "(Ljava/lang/String;I)V", "WARNING", "ERROR", "special module for files not under source root"} + ) + public static enum Level { + WARNING, + ERROR; + } +} diff --git a/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt new file mode 100644 index 000000000000..ed690af83201 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt @@ -0,0 +1,7 @@ +// KTIJ-24026 +// ALLOW_ERRORS + +class ClassB {} + +class ClassA: ClassB() {} +class ClassA: ClassB() {} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt.highlighting b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt.highlighting new file mode 100644 index 000000000000..608f7ad37f1a --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt.highlighting @@ -0,0 +1,7 @@ +// KTIJ-24026 +// ALLOW_ERRORS + +class ClassB {} + +class ClassA: ClassB() {} +class ClassA: ClassB() {} diff --git a/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt.highlighting.fir b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt.highlighting.fir new file mode 100644 index 000000000000..3c953145e7ee --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/classRedeclaration.kt.highlighting.fir @@ -0,0 +1,7 @@ +// KTIJ-24026 +// ALLOW_ERRORS + +class ClassB {} + +class ClassA: ClassB() {} +class ClassA: ClassB() {} diff --git a/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt new file mode 100644 index 000000000000..5d82cde2912e --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt @@ -0,0 +1,9 @@ +// KTIJ-24099 +// ALLOW_ERRORS + +public class Hierarchy extends KotlinOnlyClass { + void companionMembers() { + Custom companionlateinitVariable = KotlinOnlyClass.companionlateinitVariable; + Custom companionlateinitStaticVariable = KotlinOnlyClass.companionlateinitStaticVariable; + + } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt.highlighting b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt.highlighting new file mode 100644 index 000000000000..121e4b85f2e6 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt.highlighting @@ -0,0 +1,9 @@ +// KTIJ-24099 +// ALLOW_ERRORS + +public class Hierarchy extends KotlinOnlyClass { + void companionMembers() { + Custom companionlateinitVariable = KotlinOnlyClass.companionlateinitVariable; + Custom companionlateinitStaticVariable = KotlinOnlyClass.companionlateinitStaticVariable; + + } diff --git a/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt.highlighting.fir b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt.highlighting.fir new file mode 100644 index 000000000000..7b6cb6187f1c --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/javaCodeInKotlinFile1.kt.highlighting.fir @@ -0,0 +1,9 @@ +// KTIJ-24099 +// ALLOW_ERRORS + +public class Hierarchy extends KotlinOnlyClass { + void companionMembers() { + Custom companionlateinitVariable = KotlinOnlyClass.companionlateinitVariable; + Custom companionlateinitStaticVariable = KotlinOnlyClass.companionlateinitStaticVariable; + + } diff --git a/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt new file mode 100644 index 000000000000..3e2654e7909e --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt @@ -0,0 +1,8 @@ +// KTIJ-24132 +// ALLOW_ERRORS + +public expect interface CompletionHandler { + public operator fun invoke(cause: Throwable?) +} + +public actual typealias CompletionHandler = (cause: Throwable?) -> Unit \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt.highlighting b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt.highlighting new file mode 100644 index 000000000000..aafeff69c3b0 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt.highlighting @@ -0,0 +1,8 @@ +// KTIJ-24132 +// ALLOW_ERRORS + +public expect interface CompletionHandler { + public operator fun invoke(cause: Throwable?) +} + +public actual typealias CompletionHandler = (cause: Throwable?) -> Unit diff --git a/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt.highlighting.fir b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt.highlighting.fir new file mode 100644 index 000000000000..17214e91a0b1 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/highlighterMetaInfo/diagnostics/mppIsNotEnabled.kt.highlighting.fir @@ -0,0 +1,8 @@ +// KTIJ-24132 +// ALLOW_ERRORS + +public expect interface CompletionHandler { + public operator fun invoke(cause: Throwable?) +} + + = Bar''")!>public actual typealias CompletionHandler = (cause: Throwable?) -> Unit diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class1.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class1.kt index eb3f0547016a..a5638566ab9f 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class1.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class1.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "class package2.MyClass" // EXPECT_VARIANT_IN_ORDER "class package3.MyClass" package root diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class1.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class1.kt.after index 52340ae09f92..1e15cec1ce92 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class1.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class1.kt.after @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "class package2.MyClass" // EXPECT_VARIANT_IN_ORDER "class package3.MyClass" package root diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class2.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class2.kt index fd46c9046ff5..1934fc4fccbb 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class2.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class2.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "class package3.MyClass" // EXPECT_VARIANT_IN_ORDER "class package2.MyClass" package root diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class2.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class2.kt.after index 3b9e2c03c28b..b756d6d37c3c 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class2.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Class2.kt.after @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "class package3.MyClass" // EXPECT_VARIANT_IN_ORDER "class package2.MyClass" package root diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ConstructorOverloadsPresent.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ConstructorOverloadsPresent.kt index c716b3ae92f7..4ba71525d591 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ConstructorOverloadsPresent.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ConstructorOverloadsPresent.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "class root.p.Bar" // EXPECT_VARIANT_IN_ORDER "class root.q.Bar" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ConstructorOverloadsPresent.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ConstructorOverloadsPresent.kt.after index 5a912ec967cd..60c224ae9971 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ConstructorOverloadsPresent.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ConstructorOverloadsPresent.kt.after @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "class root.p.Bar" // EXPECT_VARIANT_IN_ORDER "class root.q.Bar" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver3.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver3.kt index 59208f151718..85ff07aa6dc6 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver3.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver3.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // WITH_STDLIB // EXPECT_VARIANT_IN_ORDER "public fun sec(s: kotlin.String): kotlin.Unit defined in p1 in file ExtReceiver3.dependency.kt" // EXPECT_VARIANT_IN_ORDER "public fun root.A.sec(s: kotlin.String): kotlin.Unit defined in p2 in file ExtReceiver3.dependency1.kt" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver3.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver3.kt.after index 384ce347b901..104e54098188 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver3.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver3.kt.after @@ -1,3 +1,4 @@ +// FIR_COMPARISON // WITH_STDLIB // EXPECT_VARIANT_IN_ORDER "public fun sec(s: kotlin.String): kotlin.Unit defined in p1 in file ExtReceiver3.dependency.kt" // EXPECT_VARIANT_IN_ORDER "public fun root.A.sec(s: kotlin.String): kotlin.Unit defined in p2 in file ExtReceiver3.dependency1.kt" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver4.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver4.kt index f8cf867dbb61..c1f2334771cb 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver4.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver4.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // WITH_STDLIB // EXPECT_VARIANT_IN_ORDER "public fun kotlin.Int.sec(s: kotlin.String): kotlin.Unit defined in p2 in file ExtReceiver4.dependency1.kt" // EXPECT_VARIANT_IN_ORDER "public fun sec(s: kotlin.String): kotlin.Unit defined in p1 in file ExtReceiver4.dependency.kt" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver4.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver4.kt.after index 80876d736015..2455b1461628 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver4.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtReceiver4.kt.after @@ -1,3 +1,4 @@ +// FIR_COMPARISON // WITH_STDLIB // EXPECT_VARIANT_IN_ORDER "public fun kotlin.Int.sec(s: kotlin.String): kotlin.Unit defined in p2 in file ExtReceiver4.dependency1.kt" // EXPECT_VARIANT_IN_ORDER "public fun sec(s: kotlin.String): kotlin.Unit defined in p1 in file ExtReceiver4.dependency.kt" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtendingClass1.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtendingClass1.kt index 48ed0371a54a..18893ba73ae1 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtendingClass1.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtendingClass1.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "class package2.MyClass" // EXPECT_VARIANT_IN_ORDER "class package3.MyClass" package root diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtendingClass1.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtendingClass1.kt.after index 0127a2990e7e..cea0a5d2b090 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtendingClass1.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/ExtendingClass1.kt.after @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "class package2.MyClass" // EXPECT_VARIANT_IN_ORDER "class package3.MyClass" package root diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations.kt index 86101c64af10..290aaecee42a 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations.kt @@ -1,6 +1,6 @@ // WITH_STDLIB -// EXPECT_VARIANT_IN_ORDER "@kotlin.internal.InlineOnly public final val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time.Duration.Companion" -// EXPECT_VARIANT_IN_ORDER "@kotlin.Deprecated @kotlin.DeprecatedSinceKotlin @kotlin.SinceKotlin @kotlin.time.ExperimentalTime public val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time" +// EXPECT_VARIANT_IN_ORDER "public final val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time.Duration.Companion" +// EXPECT_VARIANT_IN_ORDER "public val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time" package root fun foo() { diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations.kt.after index cf3141ce2e97..194d95543492 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations.kt.after @@ -1,6 +1,6 @@ // WITH_STDLIB -// EXPECT_VARIANT_IN_ORDER "@kotlin.internal.InlineOnly public final val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time.Duration.Companion" -// EXPECT_VARIANT_IN_ORDER "@kotlin.Deprecated @kotlin.DeprecatedSinceKotlin @kotlin.SinceKotlin @kotlin.time.ExperimentalTime public val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time" +// EXPECT_VARIANT_IN_ORDER "public final val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time.Duration.Companion" +// EXPECT_VARIANT_IN_ORDER "public val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time" package root import kotlin.time.Duration.Companion.seconds diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations2.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations2.kt index 736d4170c616..6774ea29fc0e 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations2.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations2.kt @@ -1,6 +1,6 @@ // WITH_STDLIB -// EXPECT_VARIANT_IN_ORDER "@kotlin.internal.InlineOnly public final val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time.Duration.Companion" -// EXPECT_VARIANT_IN_ORDER "@kotlin.Deprecated @kotlin.DeprecatedSinceKotlin @kotlin.SinceKotlin @kotlin.time.ExperimentalTime public val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time" +// EXPECT_VARIANT_IN_ORDER "public final val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time.Duration.Companion" +// EXPECT_VARIANT_IN_ORDER "public val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time" package root fun foo(x: Int?) = x.seconds diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations2.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations2.kt.after index 60045c7dc963..67b5bd8cf631 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations2.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinDurations2.kt.after @@ -1,6 +1,6 @@ // WITH_STDLIB -// EXPECT_VARIANT_IN_ORDER "@kotlin.internal.InlineOnly public final val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time.Duration.Companion" -// EXPECT_VARIANT_IN_ORDER "@kotlin.Deprecated @kotlin.DeprecatedSinceKotlin @kotlin.SinceKotlin @kotlin.time.ExperimentalTime public val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time" +// EXPECT_VARIANT_IN_ORDER "public final val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time.Duration.Companion" +// EXPECT_VARIANT_IN_ORDER "public val kotlin.Int.seconds: kotlin.time.Duration defined in kotlin.time" package root import kotlin.time.Duration.Companion.seconds diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinCollections.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinCollections.kt index d9d33a080010..9f2d86c37846 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinCollections.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinCollections.kt @@ -1,6 +1,6 @@ // WITH_STDLIB -// EXPECT_VARIANT_IN_ORDER "public open fun min(@org.jetbrains.annotations.NotNull p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" -// EXPECT_VARIANT_IN_ORDER "@kotlin.SinceKotlin @kotlin.internal.InlineOnly public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" +// EXPECT_VARIANT_IN_ORDER "public open fun min(p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" +// EXPECT_VARIANT_IN_ORDER "public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Double, p1: kotlin.Double): kotlin.Double defined in java.lang.Double" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Float, p1: kotlin.Float): kotlin.Float defined in java.lang.Float" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Integer" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinCollections.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinCollections.kt.after index 4b88a3b861da..7beca397c378 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinCollections.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinCollections.kt.after @@ -1,6 +1,6 @@ // WITH_STDLIB -// EXPECT_VARIANT_IN_ORDER "public open fun min(@org.jetbrains.annotations.NotNull p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" -// EXPECT_VARIANT_IN_ORDER "@kotlin.SinceKotlin @kotlin.internal.InlineOnly public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" +// EXPECT_VARIANT_IN_ORDER "public open fun min(p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" +// EXPECT_VARIANT_IN_ORDER "public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Double, p1: kotlin.Double): kotlin.Double defined in java.lang.Double" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Float, p1: kotlin.Float): kotlin.Float defined in java.lang.Float" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Integer" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinInt.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinInt.kt index d25c897798df..ee2e9dff704b 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinInt.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinInt.kt @@ -1,9 +1,9 @@ // WITH_STDLIB -// EXPECT_VARIANT_IN_ORDER "@kotlin.SinceKotlin @kotlin.internal.InlineOnly public inline fun min(a: kotlin.Int, b: kotlin.Int): kotlin.Int defined in kotlin.math" +// EXPECT_VARIANT_IN_ORDER "public inline fun min(a: kotlin.Int, b: kotlin.Int): kotlin.Int defined in kotlin.math" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Integer" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Math" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.StrictMath" -// EXPECT_VARIANT_IN_ORDER "public open fun min(@org.jetbrains.annotations.NotNull p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?), @org.jetbrains.annotations.Nullable p1: (java.util.Comparator..java.util.Comparator?)): (T..T?) defined in java.util.Collections" +// EXPECT_VARIANT_IN_ORDER "public open fun min(p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?), p1: (java.util.Comparator..java.util.Comparator?)): (T..T?) defined in java.util.Collections" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Double, p1: kotlin.Double): kotlin.Double defined in java.lang.Double" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Float, p1: kotlin.Float): kotlin.Float defined in java.lang.Float" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Long, p1: kotlin.Long): kotlin.Long defined in java.lang.Long" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinInt.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinInt.kt.after index bb5faabf4272..66fc29779364 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinInt.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/KotlinMinInt.kt.after @@ -1,9 +1,9 @@ // WITH_STDLIB -// EXPECT_VARIANT_IN_ORDER "@kotlin.SinceKotlin @kotlin.internal.InlineOnly public inline fun min(a: kotlin.Int, b: kotlin.Int): kotlin.Int defined in kotlin.math" +// EXPECT_VARIANT_IN_ORDER "public inline fun min(a: kotlin.Int, b: kotlin.Int): kotlin.Int defined in kotlin.math" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Integer" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Math" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.StrictMath" -// EXPECT_VARIANT_IN_ORDER "public open fun min(@org.jetbrains.annotations.NotNull p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?), @org.jetbrains.annotations.Nullable p1: (java.util.Comparator..java.util.Comparator?)): (T..T?) defined in java.util.Collections" +// EXPECT_VARIANT_IN_ORDER "public open fun min(p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?), p1: (java.util.Comparator..java.util.Comparator?)): (T..T?) defined in java.util.Collections" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Double, p1: kotlin.Double): kotlin.Double defined in java.lang.Double" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Float, p1: kotlin.Float): kotlin.Float defined in java.lang.Float" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Long, p1: kotlin.Long): kotlin.Long defined in java.lang.Long" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable.kt index 98245183eff0..3fc116e2b9f1 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "public fun bar(): kotlin.Unit defined in root.q" // EXPECT_VARIANT_IN_ORDER "public fun bar(): kotlin.Unit defined in root.r" // EXPECT_VARIANT_IN_ORDER "public fun bar(): kotlin.Unit defined in root.p" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable.kt.after index 5ffdcb5a5d87..ca825dd3ecd0 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable.kt.after @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "public fun bar(): kotlin.Unit defined in root.q" // EXPECT_VARIANT_IN_ORDER "public fun bar(): kotlin.Unit defined in root.r" // EXPECT_VARIANT_IN_ORDER "public fun bar(): kotlin.Unit defined in root.p" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable2.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable2.kt index 7ba5ed54fa6f..9dd81a4706d4 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable2.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable2.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "public fun ref(s: kotlin.String): kotlin.Unit defined in kotlinpackage.two.s2 in file MultipleMethodsAvailable2.dependency1.kt" // EXPECT_VARIANT_IN_ORDER "public fun ref(s: kotlin.Int): kotlin.Unit defined in kotlinpackage.two in file MultipleMethodsAvailable2.dependency.kt" package kotlinpackage.two.s1 diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable2.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable2.kt.after index 893607a97c0c..0148a7941d04 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable2.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/MultipleMethodsAvailable2.kt.after @@ -1,3 +1,4 @@ +// FIR_COMPARISON // EXPECT_VARIANT_IN_ORDER "public fun ref(s: kotlin.String): kotlin.Unit defined in kotlinpackage.two.s2 in file MultipleMethodsAvailable2.dependency1.kt" // EXPECT_VARIANT_IN_ORDER "public fun ref(s: kotlin.Int): kotlin.Unit defined in kotlinpackage.two in file MultipleMethodsAvailable2.dependency.kt" package kotlinpackage.two.s1 diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/SingleMethodAvailable.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/SingleMethodAvailable.kt index 0675028f95f7..b1afcc1a1966 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/SingleMethodAvailable.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/SingleMethodAvailable.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package root fun foo() { diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/SingleMethodAvailable.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/SingleMethodAvailable.kt.after index 4e824cf25d08..be8a77c1966f 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/SingleMethodAvailable.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/SingleMethodAvailable.kt.after @@ -1,3 +1,4 @@ +// FIR_COMPARISON package root import root.p.bar diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.dependency1.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.dependency1.kt new file mode 100644 index 000000000000..5be394abaf5c --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.dependency1.kt @@ -0,0 +1,3 @@ +package pack1 + +fun foo(n: Int) {} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.dependency2.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.dependency2.kt new file mode 100644 index 000000000000..116c96e6f9cc --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.dependency2.kt @@ -0,0 +1,3 @@ +package pack2 + +fun foo(vararg n: Int) {} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.kt new file mode 100644 index 000000000000..ab67b89889ee --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.kt @@ -0,0 +1,9 @@ +// FIR_COMPARISON +// EXPECT_VARIANT_IN_ORDER "public fun foo(vararg n: kotlin.Int): kotlin.Unit defined in pack2 in file VarargSpreadOperator.dependency2.kt" +// EXPECT_VARIANT_IN_ORDER "public fun foo(n: kotlin.Int): kotlin.Unit defined in pack1 in file VarargSpreadOperator.dependency1.kt" +package root + +fun test() { + val a = intArrayOf(1, 1) + foo(*a) +} diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.kt.after new file mode 100644 index 000000000000..02ffe3005817 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/VarargSpreadOperator.kt.after @@ -0,0 +1,11 @@ +// FIR_COMPARISON +// EXPECT_VARIANT_IN_ORDER "public fun foo(vararg n: kotlin.Int): kotlin.Unit defined in pack2 in file VarargSpreadOperator.dependency2.kt" +// EXPECT_VARIANT_IN_ORDER "public fun foo(n: kotlin.Int): kotlin.Unit defined in pack1 in file VarargSpreadOperator.dependency1.kt" +package root + +import pack2.foo + +fun test() { + val a = intArrayOf(1, 1) + foo(*a) +} diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs.kt index 7d49f45cfc2e..c2cc232f4c6a 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs.kt @@ -1,10 +1,10 @@ // WITH_STDLIB // EXPECT_VARIANT_IN_ORDER "public fun min(vararg l: kotlin.Int): kotlin.Unit defined in foo in file Varargs.dependency.kt" -// EXPECT_VARIANT_IN_ORDER "@kotlin.SinceKotlin @kotlin.internal.InlineOnly public inline fun min(a: kotlin.Int, b: kotlin.Int): kotlin.Int defined in kotlin.math" +// EXPECT_VARIANT_IN_ORDER "public inline fun min(a: kotlin.Int, b: kotlin.Int): kotlin.Int defined in kotlin.math" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Integer" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Math" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.StrictMath" -// EXPECT_VARIANT_IN_ORDER "public open fun min(@org.jetbrains.annotations.NotNull p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" +// EXPECT_VARIANT_IN_ORDER "public open fun min(p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Double, p1: kotlin.Double): kotlin.Double defined in java.lang.Double" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Float, p1: kotlin.Float): kotlin.Float defined in java.lang.Float" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Long, p1: kotlin.Long): kotlin.Long defined in java.lang.Long" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs.kt.after index 07ad5b55dc42..536e4228e105 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs.kt.after @@ -1,10 +1,10 @@ // WITH_STDLIB // EXPECT_VARIANT_IN_ORDER "public fun min(vararg l: kotlin.Int): kotlin.Unit defined in foo in file Varargs.dependency.kt" -// EXPECT_VARIANT_IN_ORDER "@kotlin.SinceKotlin @kotlin.internal.InlineOnly public inline fun min(a: kotlin.Int, b: kotlin.Int): kotlin.Int defined in kotlin.math" +// EXPECT_VARIANT_IN_ORDER "public inline fun min(a: kotlin.Int, b: kotlin.Int): kotlin.Int defined in kotlin.math" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Integer" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Math" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.StrictMath" -// EXPECT_VARIANT_IN_ORDER "public open fun min(@org.jetbrains.annotations.NotNull p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" +// EXPECT_VARIANT_IN_ORDER "public open fun min(p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Double, p1: kotlin.Double): kotlin.Double defined in java.lang.Double" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Float, p1: kotlin.Float): kotlin.Float defined in java.lang.Float" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Long, p1: kotlin.Long): kotlin.Long defined in java.lang.Long" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs2.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs2.kt index 65e750f412fa..2751a3be2437 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs2.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs2.kt @@ -1,7 +1,7 @@ // WITH_STDLIB // EXPECT_VARIANT_IN_ORDER "public fun min(vararg l: kotlin.String): kotlin.Unit defined in foo in file Varargs2.dependency.kt" -// EXPECT_VARIANT_IN_ORDER "@kotlin.SinceKotlin @kotlin.internal.InlineOnly public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" -// EXPECT_VARIANT_IN_ORDER "public open fun min(@org.jetbrains.annotations.NotNull p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" +// EXPECT_VARIANT_IN_ORDER "public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" +// EXPECT_VARIANT_IN_ORDER "public open fun min(p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Double, p1: kotlin.Double): kotlin.Double defined in java.lang.Double" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Float, p1: kotlin.Float): kotlin.Float defined in java.lang.Float" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Integer" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs2.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs2.kt.after index 9caf51fca0fa..2c9b5883dd83 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs2.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs2.kt.after @@ -1,7 +1,7 @@ // WITH_STDLIB // EXPECT_VARIANT_IN_ORDER "public fun min(vararg l: kotlin.String): kotlin.Unit defined in foo in file Varargs2.dependency.kt" -// EXPECT_VARIANT_IN_ORDER "@kotlin.SinceKotlin @kotlin.internal.InlineOnly public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" -// EXPECT_VARIANT_IN_ORDER "public open fun min(@org.jetbrains.annotations.NotNull p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" +// EXPECT_VARIANT_IN_ORDER "public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" +// EXPECT_VARIANT_IN_ORDER "public open fun min(p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Double, p1: kotlin.Double): kotlin.Double defined in java.lang.Double" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Float, p1: kotlin.Float): kotlin.Float defined in java.lang.Float" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Integer" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs3.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs3.kt index 9f22337ed211..deb106353c80 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs3.kt +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs3.kt @@ -1,7 +1,7 @@ // WITH_STDLIB // EXPECT_VARIANT_IN_ORDER "public fun min(vararg l: kotlin.Int): kotlin.Unit defined in foo in file Varargs3.dependency.kt" -// EXPECT_VARIANT_IN_ORDER "@kotlin.SinceKotlin @kotlin.internal.InlineOnly public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" -// EXPECT_VARIANT_IN_ORDER "public open fun min(@org.jetbrains.annotations.NotNull p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" +// EXPECT_VARIANT_IN_ORDER "public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" +// EXPECT_VARIANT_IN_ORDER "public open fun min(p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Double, p1: kotlin.Double): kotlin.Double defined in java.lang.Double" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Float, p1: kotlin.Float): kotlin.Float defined in java.lang.Float" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Integer" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs3.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs3.kt.after index c1b2c740fd92..e52bc90d43eb 100644 --- a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs3.kt.after +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/Varargs3.kt.after @@ -1,7 +1,7 @@ // WITH_STDLIB // EXPECT_VARIANT_IN_ORDER "public fun min(vararg l: kotlin.Int): kotlin.Unit defined in foo in file Varargs3.dependency.kt" -// EXPECT_VARIANT_IN_ORDER "@kotlin.SinceKotlin @kotlin.internal.InlineOnly public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" -// EXPECT_VARIANT_IN_ORDER "public open fun min(@org.jetbrains.annotations.NotNull p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" +// EXPECT_VARIANT_IN_ORDER "public inline fun min(a: kotlin.Double, b: kotlin.Double): kotlin.Double defined in kotlin.math" +// EXPECT_VARIANT_IN_ORDER "public open fun min(p0: (kotlin.collections.MutableCollection..kotlin.collections.Collection<(T..T?)>?)): (T..T?) where T : (kotlin.Comparable<(T..T?)>..kotlin.Comparable<(T..T?)>?) defined in java.util.Collections" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Double, p1: kotlin.Double): kotlin.Double defined in java.lang.Double" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Float, p1: kotlin.Float): kotlin.Float defined in java.lang.Float" // EXPECT_VARIANT_IN_ORDER "public open fun min(p0: kotlin.Int, p1: kotlin.Int): kotlin.Int defined in java.lang.Integer" diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.dependency1.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.dependency1.kt new file mode 100644 index 000000000000..738479bb8f70 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.dependency1.kt @@ -0,0 +1,3 @@ +package pack1 + +fun bar(n: Int) {} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.dependency2.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.dependency2.kt new file mode 100644 index 000000000000..d2b8a31dd4a8 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.dependency2.kt @@ -0,0 +1,3 @@ +package pack2 + +fun bar(n: Int) {} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.kt b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.kt new file mode 100644 index 000000000000..c3b4ec5ba038 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.kt @@ -0,0 +1,9 @@ +// FIR_COMPARISON +// EXPECT_VARIANT_IN_ORDER "public fun bar(n: kotlin.Int): kotlin.Unit defined in pack2 in file WithStatisticsInfo.dependency2.kt" +// EXPECT_VARIANT_IN_ORDER "public fun bar(n: kotlin.Int): kotlin.Unit defined in pack1 in file WithStatisticsInfo.dependency1.kt" +// INCREASE_USE_COUNT pack2###bar(kotlin.Int) +package root + +fun test() { + bar(1) +} diff --git a/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.kt.after b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.kt.after new file mode 100644 index 000000000000..29c0093a24c8 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/idea/actions/kotlinAddImportAction/WithStatisticsInfo.kt.after @@ -0,0 +1,11 @@ +// FIR_COMPARISON +// EXPECT_VARIANT_IN_ORDER "public fun bar(n: kotlin.Int): kotlin.Unit defined in pack2 in file WithStatisticsInfo.dependency2.kt" +// EXPECT_VARIANT_IN_ORDER "public fun bar(n: kotlin.Int): kotlin.Unit defined in pack1 in file WithStatisticsInfo.dependency1.kt" +// INCREASE_USE_COUNT pack2###bar(kotlin.Int) +package root + +import pack2.bar + +fun test() { + bar(1) +} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement.kt new file mode 100644 index 000000000000..9bddee34f9dd --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement.kt @@ -0,0 +1,13 @@ +// ONLY_SINGLE_STATEMENT: true +// HIGHLIGHT: INFORMATION +fun test(b: Boolean) { + var x: Int + if (b) { + println(1) + x = 1 + } else { + x = 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement.kt.after new file mode 100644 index 000000000000..8fe8d5ee143d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement.kt.after @@ -0,0 +1,13 @@ +// ONLY_SINGLE_STATEMENT: true +// HIGHLIGHT: INFORMATION +fun test(b: Boolean) { + var x: Int + x = if (b) { + println(1) + 1 + } else { + 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement2.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement2.kt new file mode 100644 index 000000000000..7927931ebe4a --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement2.kt @@ -0,0 +1,13 @@ +// ONLY_SINGLE_STATEMENT: true +// HIGHLIGHT: INFORMATION +fun test(b: Boolean) { + var x: Int + if (b) { + x = 1 + } else { + println(2) + x = 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement2.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement2.kt.after new file mode 100644 index 000000000000..fea52063d4e9 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement2.kt.after @@ -0,0 +1,13 @@ +// ONLY_SINGLE_STATEMENT: true +// HIGHLIGHT: INFORMATION +fun test(b: Boolean) { + var x: Int + x = if (b) { + 1 + } else { + println(2) + 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement3.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement3.kt new file mode 100644 index 000000000000..a065d07f4c83 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement3.kt @@ -0,0 +1,14 @@ +// ONLY_SINGLE_STATEMENT: false +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(b: Boolean) { + var x: Int + if (b) { + println(1) + x = 1 + } else { + println(2) + x = 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement3.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement3.kt.after new file mode 100644 index 000000000000..e43a61953cd5 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToAssignment/multiStatement3.kt.after @@ -0,0 +1,14 @@ +// ONLY_SINGLE_STATEMENT: false +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(b: Boolean) { + var x: Int + x = if (b) { + println(1) + 1 + } else { + println(2) + 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement.kt new file mode 100644 index 000000000000..eb2b1136a4e4 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement.kt @@ -0,0 +1,12 @@ +// ONLY_SINGLE_STATEMENT: true +// HIGHLIGHT: INFORMATION +fun test(b: Boolean): Int { + if (b) { + println(1) + return 1 + } else { + return 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement.kt.after new file mode 100644 index 000000000000..772183566fe8 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement.kt.after @@ -0,0 +1,12 @@ +// ONLY_SINGLE_STATEMENT: true +// HIGHLIGHT: INFORMATION +fun test(b: Boolean): Int { + return if (b) { + println(1) + 1 + } else { + 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement2.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement2.kt new file mode 100644 index 000000000000..4110dffbff15 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement2.kt @@ -0,0 +1,12 @@ +// ONLY_SINGLE_STATEMENT: true +// HIGHLIGHT: INFORMATION +fun test(b: Boolean): Int { + if (b) { + return 1 + } else { + println(2) + return 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement2.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement2.kt.after new file mode 100644 index 000000000000..4752724f849c --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement2.kt.after @@ -0,0 +1,12 @@ +// ONLY_SINGLE_STATEMENT: true +// HIGHLIGHT: INFORMATION +fun test(b: Boolean): Int { + return if (b) { + 1 + } else { + println(2) + 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement3.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement3.kt new file mode 100644 index 000000000000..2ff538000177 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement3.kt @@ -0,0 +1,13 @@ +// ONLY_SINGLE_STATEMENT: false +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(b: Boolean): Int { + if (b) { + println(1) + return 1 + } else { + println(2) + return 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement3.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement3.kt.after new file mode 100644 index 000000000000..72d1ecec8be3 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/ifToReturn/multiStatement3.kt.after @@ -0,0 +1,13 @@ +// ONLY_SINGLE_STATEMENT: false +// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +fun test(b: Boolean): Int { + return if (b) { + println(1) + 1 + } else { + println(2) + 2 + } +} + +fun println(i: Int) {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToAssignment/block.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToAssignment/block.kt index ebe301b9d96e..3b8bd2b6d8c7 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToAssignment/block.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToAssignment/block.kt @@ -1,4 +1,4 @@ -// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +// HIGHLIGHT: INFORMATION fun doSomething() {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToAssignment/block.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToAssignment/block.kt.after index 3d210c002cf1..0bd9407ee384 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToAssignment/block.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToAssignment/block.kt.after @@ -1,4 +1,4 @@ -// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +// HIGHLIGHT: INFORMATION fun doSomething() {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToReturn/block.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToReturn/block.kt index 15a33efef2cb..5fbd7fc618e1 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToReturn/block.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToReturn/block.kt @@ -1,4 +1,4 @@ -// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +// HIGHLIGHT: INFORMATION fun doSomething() {} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToReturn/block.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToReturn/block.kt.after index 4ae23d81b6a9..5d24c208b7f5 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToReturn/block.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/liftOut/tryToReturn/block.kt.after @@ -1,4 +1,4 @@ -// HIGHLIGHT: GENERIC_ERROR_OR_WARNING +// HIGHLIGHT: INFORMATION fun doSomething() {} diff --git a/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/backticked.kt b/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/backticked.kt index e5ca237bf273..66be7b9ab5f2 100644 --- a/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/backticked.kt +++ b/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/backticked.kt @@ -1,3 +1,2 @@ -// IGNORE_FIR class `1` val x = `1`() \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/backticked.kt.after b/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/backticked.kt.after index f817cb01821a..500593f51973 100644 --- a/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/backticked.kt.after +++ b/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/backticked.kt.after @@ -1,3 +1,2 @@ -// IGNORE_FIR class `1` -val x: `1` = `1`() \ No newline at end of file +val x: `1` = `1`() diff --git a/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/destructuringInLoopParameter.kt b/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/destructuringInLoopParameter.kt new file mode 100644 index 000000000000..60da2de76882 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/specifyTypeExplicitly/destructuringInLoopParameter.kt @@ -0,0 +1,7 @@ +// IS_APPLICABLE: false +// WITH_STDLIB +fun test(array: IntArray) { + for ((index, value) in array.withIndex()) { + println("the element at $index is $value") + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/ambiguousNamePreferWithImportsFromPackage.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/ambiguousNamePreferWithImportsFromPackage.after.kt index e6f857daed3d..523841b3ed80 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/ambiguousNamePreferWithImportsFromPackage.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/ambiguousNamePreferWithImportsFromPackage.after.kt @@ -6,5 +6,3 @@ import dependency2.YYY fun foo(x: XXX) { } - -/* IGNORE_FIR */ \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/ambiguousNamePreferWithImportsFromPackage.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/ambiguousNamePreferWithImportsFromPackage.before.Main.kt index 52b6fd2c350b..42ba0fad6edd 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/ambiguousNamePreferWithImportsFromPackage.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/ambiguousNamePreferWithImportsFromPackage.before.Main.kt @@ -5,5 +5,3 @@ import dependency2.YYY fun foo(x: XXX) { } - -/* IGNORE_FIR */ \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/classImport.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/classImport.after.kt index f0f615eee03f..a483957800e7 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/classImport.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/classImport.after.kt @@ -5,5 +5,4 @@ import TestData.TestSample fun test() { val a = TestSample -} -/* IGNORE_FIR */ \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/classImport.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/classImport.before.Main.kt index 9528aa3f9f20..51abdef165e6 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/classImport.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/classImport.before.Main.kt @@ -3,5 +3,4 @@ fun test() { val a = TestSample -} -/* IGNORE_FIR */ \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/constructorParameterAnnotation.test b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/constructorParameterAnnotation.test index e6043aa76df3..4c01c4f501d3 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/constructorParameterAnnotation.test +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/constructorParameterAnnotation.test @@ -1,7 +1,6 @@ // FILE: first.before.kt // "Import class 'SomeAnnotation'" "true" // ERROR: Unresolved reference: SomeAnnotation -/* IGNORE_FIR */ package some class X(@set:SomeAnnotation var field: Int) @@ -15,7 +14,6 @@ annotation class SomeAnnotation // FILE: first.after.kt // "Import class 'SomeAnnotation'" "true" // ERROR: Unresolved reference: SomeAnnotation -/* IGNORE_FIR */ package some import other.SomeAnnotation diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/extensionFunctionImportImplicitReceiver.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/extensionFunctionImportImplicitReceiver.after.kt index 3945e95d98ee..d11caaef8146 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/extensionFunctionImportImplicitReceiver.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/extensionFunctionImportImplicitReceiver.after.kt @@ -6,5 +6,4 @@ import testingExtensionFunctionsImport.data.someFun fun String.some() { someFun() -} -/* IGNORE_FIR */ \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/extensionFunctionImportImplicitReceiver.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/extensionFunctionImportImplicitReceiver.before.Main.kt index 2cc23f982b15..0e9f4a62e549 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/extensionFunctionImportImplicitReceiver.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/extensionFunctionImportImplicitReceiver.before.Main.kt @@ -4,5 +4,4 @@ package testingExtensionFunctionsImport fun String.some() { someFun() -} -/* IGNORE_FIR */ \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/functionPreferNotDeprecated.test b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/functionPreferNotDeprecated.test new file mode 100644 index 000000000000..6aadedcdcc5c --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/functionPreferNotDeprecated.test @@ -0,0 +1,43 @@ +// FILE: first.before.kt +// "Import function 'xxx'" "true" +// ERROR: Unresolved reference: xxx + +package testing + +fun test() { + xxx() +} +//----------------------- + + +// FILE: second.kt + +package dependency + +@Deprecated("Use xxx from other") +fun xxx() {} + +//----------------------- + + +// FILE: other_second.kt + +package other + +fun xxx() {} + +//----------------------- + + +// FILE: first.after.kt +// "Import function 'xxx'" "true" +// ERROR: Unresolved reference: xxx + +package testing + +import other.xxx + +fun test() { + xxx() +} +//----------------------- diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasClassAlreadyExistsCollision.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasClassAlreadyExistsCollision.after.kt index d2ffcf62d6a6..137245680fec 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasClassAlreadyExistsCollision.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasClassAlreadyExistsCollision.after.kt @@ -6,5 +6,4 @@ import editor.completion.apx.ImportedClass as Class2 fun context() { class Class2 val c: ImportedClass -} -/* IGNORE_FIR */ \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasClassAlreadyExistsCollision.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasClassAlreadyExistsCollision.before.Main.kt index 70cb3b07d3c5..644169f32df5 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasClassAlreadyExistsCollision.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasClassAlreadyExistsCollision.before.Main.kt @@ -5,5 +5,4 @@ import editor.completion.apx.ImportedClass as Class2 fun context() { class Class2 val c: ImportedClass -} -/* IGNORE_FIR */ \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasFunctionAlreadyExistsCollision.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasFunctionAlreadyExistsCollision.after.kt index dab33bdef515..b47058478f5f 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasFunctionAlreadyExistsCollision.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasFunctionAlreadyExistsCollision.after.kt @@ -1,6 +1,5 @@ // "Import function 'importedFunA'" "true" // ERROR: Unresolved reference: importedFunA -/* IGNORE_FIR */ import editor.completion.apx.importedFunA import editor.completion.apx.importedFunA as funA fun context() { diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasFunctionAlreadyExistsCollision.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasFunctionAlreadyExistsCollision.before.Main.kt index 0212e7a1fe8a..da680408521c 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasFunctionAlreadyExistsCollision.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importAliasFunctionAlreadyExistsCollision.before.Main.kt @@ -1,6 +1,5 @@ // "Import function 'importedFunA'" "true" // ERROR: Unresolved reference: importedFunA -/* IGNORE_FIR */ import editor.completion.apx.importedFunA as funA fun context() { fun funA() {} diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importClass.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importClass.after.kt index bda2d67e1ee7..f89ecd2af762 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importClass.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importClass.after.kt @@ -9,5 +9,3 @@ import kotlinpackage.two.Some fun test() { var x by Some("OK") } - -/* IGNORE_FIR */ \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importClass.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importClass.before.Main.kt index f587d80740ef..88a430af27eb 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importClass.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importClass.before.Main.kt @@ -7,5 +7,3 @@ package kotlinpackage.one fun test() { var x by Some("OK") } - -/* IGNORE_FIR */ \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importFromRoot.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importFromRoot.after.kt index ad54086a7a55..a59247e18440 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importFromRoot.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importFromRoot.after.kt @@ -6,5 +6,4 @@ import RootClass fun test() { RootClass() -} -/* IGNORE_FIR */ \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importFromRoot.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importFromRoot.before.Main.kt index e1d39c86a0b2..baa32904479c 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importFromRoot.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importFromRoot.before.Main.kt @@ -4,5 +4,4 @@ package non.root.name fun test() { RootClass() -} -/* IGNORE_FIR */ \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInFirstPartInQualifiedExpression.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInFirstPartInQualifiedExpression.after.kt index 201e40cd8c57..83ed7ae9f037 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInFirstPartInQualifiedExpression.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInFirstPartInQualifiedExpression.after.kt @@ -8,4 +8,3 @@ import some.Some fun testing() { Some.test() } -/* IGNORE_FIR */ diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInFirstPartInQualifiedExpression.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInFirstPartInQualifiedExpression.before.Main.kt index 12653c5c875c..90e5e6b1e0c9 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInFirstPartInQualifiedExpression.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInFirstPartInQualifiedExpression.before.Main.kt @@ -6,4 +6,3 @@ package testing fun testing() { Some.test() } -/* IGNORE_FIR */ diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInterface.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInterface.after.kt index 3e07da20dd59..37c26e9fee22 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInterface.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInterface.after.kt @@ -6,4 +6,3 @@ import importInterface.data.TestInterface fun test() { val a = TestInterface } -/* IGNORE_FIR */ diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInterface.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInterface.before.Main.kt index df082bfb7de0..c5ce21f2a121 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInterface.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importInterface.before.Main.kt @@ -4,4 +4,3 @@ fun test() { val a = TestInterface } -/* IGNORE_FIR */ diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importNullableInterfaceWithGenerics.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importNullableInterfaceWithGenerics.after.kt index 1d69359da011..f31b54a26ede 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importNullableInterfaceWithGenerics.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importNullableInterfaceWithGenerics.after.kt @@ -6,4 +6,3 @@ import importInterface.data.TestInterface fun test() { val a: TestInterface? = null } -/* IGNORE_FIR */ diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importNullableInterfaceWithGenerics.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importNullableInterfaceWithGenerics.before.Main.kt index 796b5aa4aa23..e91dff81e028 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importNullableInterfaceWithGenerics.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/importNullableInterfaceWithGenerics.before.Main.kt @@ -4,4 +4,3 @@ fun test() { val a: TestInterface? = null } -/* IGNORE_FIR */ diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberImportFunction.test b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberImportFunction.test index db25ef440371..679eab461aa5 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberImportFunction.test +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberImportFunction.test @@ -1,7 +1,6 @@ // FILE: main.before.kt // "Import function 'Foo.foobar'" "true" // ERROR: Unresolved reference: foobar -/* IGNORE_FIR */ //KT-9009 package foo @@ -22,7 +21,6 @@ object Foo { // FILE: main.after.kt // "Import function 'Foo.foobar'" "true" // ERROR: Unresolved reference: foobar -/* IGNORE_FIR */ //KT-9009 package foo diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberImportProperty.test b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberImportProperty.test index 1f73530f9f76..455d1b6f8fd3 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberImportProperty.test +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberImportProperty.test @@ -1,7 +1,6 @@ // FILE: main.before.kt // "Import property 'Foo.foobar'" "true" // ERROR: Unresolved reference: foobar -/* IGNORE_FIR */ //KT-9009 package foo @@ -21,7 +20,6 @@ object Foo { // FILE: main.after.kt // "Import property 'Foo.foobar'" "true" // ERROR: Unresolved reference: foobar -/* IGNORE_FIR */ //KT-9009 package foo diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberWithTopLevelConflict.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberWithTopLevelConflict.after.kt index 9315b3d256e9..3189c45713de 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberWithTopLevelConflict.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberWithTopLevelConflict.after.kt @@ -4,7 +4,6 @@ import p1.sleep // WITH_STDLIB // FULL_JDK // ERROR: Unresolved reference: sleep -/* IGNORE_FIR */ fun usage() { sleep() diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Main.kt index dfe751f4fcb7..628c22e4ecc7 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Main.kt @@ -2,7 +2,6 @@ // WITH_STDLIB // FULL_JDK // ERROR: Unresolved reference: sleep -/* IGNORE_FIR */ fun usage() { sleep() diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noFunctionImportOnSimpleName.test b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noFunctionImportOnSimpleName.test index 307451b1d905..cfdbe7fa597e 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noFunctionImportOnSimpleName.test +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noFunctionImportOnSimpleName.test @@ -22,4 +22,3 @@ package bar fun foobar() { } -/* IGNORE_FIR */ diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.after.kt index dbeb9a919afc..2622c46bac5d 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.after.kt @@ -3,5 +3,4 @@ package testing -class Some: testing.SomeTest -/* IGNORE_FIR */ \ No newline at end of file +class Some: testing.SomeTest \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.before.Main.kt index c4f4014c3a37..7740c6cc414a 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.before.Main.kt @@ -6,4 +6,3 @@ package testing class Some: testing.SomeTest -/* IGNORE_FIR */ diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForClassInExcludedPackage.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForClassInExcludedPackage.before.Main.kt index af85ea7df9d5..603002ae7a57 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForClassInExcludedPackage.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForClassInExcludedPackage.before.Main.kt @@ -6,5 +6,4 @@ // ACTION: Rename reference // ERROR: Unresolved reference: SomeClass -val x = SomeClass() -/* IGNORE_FIR */ \ No newline at end of file +val x = SomeClass() \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForExcludedClass.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForExcludedClass.before.Main.kt index 85327b2432a5..5389e3dba78e 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForExcludedClass.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForExcludedClass.before.Main.kt @@ -6,5 +6,4 @@ // ACTION: Rename reference // ERROR: Unresolved reference: ExcludedClass -val x = ExcludedClass() -/* IGNORE_FIR */ \ No newline at end of file +val x = ExcludedClass() \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForFunctionInExcludedPackage.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForFunctionInExcludedPackage.before.Main.kt index dc89b13e1f32..688de4033ce6 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForFunctionInExcludedPackage.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noImportsForFunctionInExcludedPackage.before.Main.kt @@ -5,5 +5,4 @@ // ACTION: Rename reference // ERROR: Unresolved reference: someFunction -val x = someFunction() -/* IGNORE_FIR */ \ No newline at end of file +val x = someFunction() \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noMemberFunctionImportOnSimpleName.test b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noMemberFunctionImportOnSimpleName.test index 0fca6abe9209..81ae6fb1bf31 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noMemberFunctionImportOnSimpleName.test +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/noMemberFunctionImportOnSimpleName.test @@ -23,5 +23,3 @@ object Foo { fun foobar() { } } - -/* IGNORE_FIR */ \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/notExcludedClass.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/notExcludedClass.after.kt index 9c1f0df537bd..305877a4ac15 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/notExcludedClass.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/notExcludedClass.after.kt @@ -3,5 +3,4 @@ import somePackage.NotExcludedClass // "Import class 'NotExcludedClass'" "true" // ERROR: Unresolved reference: NotExcludedClass -val x = NotExcludedClass() -/* IGNORE_FIR */ \ No newline at end of file +val x = NotExcludedClass() \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/notExcludedClass.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/notExcludedClass.before.Main.kt index 299e69ddfad1..5b5dd94090ee 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/notExcludedClass.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/notExcludedClass.before.Main.kt @@ -1,5 +1,4 @@ // "Import class 'NotExcludedClass'" "true" // ERROR: Unresolved reference: NotExcludedClass -val x = NotExcludedClass() -/* IGNORE_FIR */ \ No newline at end of file +val x = NotExcludedClass() \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectImport.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectImport.after.kt index c08d688f19b2..b57f595d0bf6 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectImport.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectImport.after.kt @@ -5,5 +5,4 @@ package ccc import bbb.TestObject -val x = TestObject -/* IGNORE_FIR */ \ No newline at end of file +val x = TestObject \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectImport.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectImport.before.Main.kt index 36404644e9c0..31f3baf1ce3c 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectImport.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectImport.before.Main.kt @@ -3,5 +3,4 @@ package ccc -val x = TestObject -/* IGNORE_FIR */ \ No newline at end of file +val x = TestObject \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectMemberFunctionImportWhenReceiverPresent.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectMemberFunctionImportWhenReceiverPresent.after.kt index 14b7a2cf88da..db935d0fd198 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectMemberFunctionImportWhenReceiverPresent.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectMemberFunctionImportWhenReceiverPresent.after.kt @@ -1,6 +1,5 @@ // "Import function 'Some.foobar'" "true" // ERROR: Unresolved reference: foobar -/* IGNORE_FIR */ package p2 import p1.Some.foobar diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectMemberFunctionImportWhenReceiverPresent.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectMemberFunctionImportWhenReceiverPresent.before.Main.kt index d48b13335a2c..3b45d8f5c226 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectMemberFunctionImportWhenReceiverPresent.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/objectMemberFunctionImportWhenReceiverPresent.before.Main.kt @@ -1,6 +1,5 @@ // "Import function 'Some.foobar'" "true" // ERROR: Unresolved reference: foobar -/* IGNORE_FIR */ package p2 class A { diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/propertyImport.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/propertyImport.after.kt index 71a748405ab3..1466be14f07a 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/propertyImport.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/propertyImport.after.kt @@ -1,6 +1,5 @@ // "Import property 'someTestProp'" "true" // ERROR: Unresolved reference: someTestProp -/* IGNORE_FIR */ package test import test.data.someTestProp diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/propertyImport.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/propertyImport.before.Main.kt index 6cc4bfb7bf76..3b6c2c90c886 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/propertyImport.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/propertyImport.before.Main.kt @@ -1,6 +1,5 @@ // "Import property 'someTestProp'" "true" // ERROR: Unresolved reference: someTestProp -/* IGNORE_FIR */ package test fun foo() { diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sameModuleImportPriority.after.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sameModuleImportPriority.after.kt index d2cca3a61f8b..647a8981ec51 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sameModuleImportPriority.after.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sameModuleImportPriority.after.kt @@ -7,5 +7,4 @@ import some.Delegates fun foo() { val d = Delegates() -} -/* IGNORE_FIR */ \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sameModuleImportPriority.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sameModuleImportPriority.before.Main.kt index 021e67e46abd..b606f3a67854 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sameModuleImportPriority.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sameModuleImportPriority.before.Main.kt @@ -5,5 +5,4 @@ package testing fun foo() { val d = Delegates() -} -/* IGNORE_FIR */ \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sealedClass.test b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sealedClass.test index 0187fe2ff0af..5075f118ac31 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sealedClass.test +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sealedClass.test @@ -1,7 +1,6 @@ // FILE: first.before.kt // "Import class 'ClassToImport'" "true" // ERROR: Unresolved reference: ClassToImport -/* IGNORE_FIR */ package testing @@ -24,7 +23,6 @@ sealed class ClassToImport // FILE: first.after.kt // "Import class 'ClassToImport'" "true" // ERROR: Unresolved reference: ClassToImport -/* IGNORE_FIR */ package testing diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sealedClass2.test b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sealedClass2.test index 45c99c0302dc..1084249a0cc9 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sealedClass2.test +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/sealedClass2.test @@ -1,7 +1,6 @@ // FILE: first.before.kt // "Import class 'Class2'" "true" // ERROR: Unresolved reference: Class2 -/* IGNORE_FIR */ package testing @@ -25,7 +24,6 @@ class Class2: ClassToImport() // FILE: first.after.kt // "Import class 'Class2'" "true" // ERROR: Unresolved reference: Class2 -/* IGNORE_FIR */ package testing diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/FullyQualified.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/FullyQualified.kt new file mode 100644 index 000000000000..2378cae83efb --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/FullyQualified.kt @@ -0,0 +1,10 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +class A { } + +class B { } + +fun foo() { + val x = org.jetbrains.A() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/FullyQualified.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/FullyQualified.kt.after new file mode 100644 index 000000000000..c938fa3a18db --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/FullyQualified.kt.after @@ -0,0 +1,10 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +class A { } + +class B { } + +fun foo() { + val x = B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/RootPkg.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/RootPkg.kt new file mode 100644 index 000000000000..db15982c9e02 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/RootPkg.kt @@ -0,0 +1,8 @@ +// BIND_TO B +class A { } + +class B { } + +fun foo() { + val x = A() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/RootPkg.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/RootPkg.kt.after new file mode 100644 index 000000000000..d7f9a64c052e --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/RootPkg.kt.after @@ -0,0 +1,8 @@ +// BIND_TO B +class A { } + +class B { } + +fun foo() { + val x = B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/TypeArgument.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/TypeArgument.kt new file mode 100644 index 000000000000..3d09fc2466e9 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/TypeArgument.kt @@ -0,0 +1,8 @@ +// BIND_TO B +class A { } + +class B { } + +fun foo() { + val x = A() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/TypeArgument.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/TypeArgument.kt.after new file mode 100644 index 000000000000..00192082a0ca --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/TypeArgument.kt.after @@ -0,0 +1,8 @@ +// BIND_TO B +class A { } + +class B { } + +fun foo() { + val x = B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/UnQualified.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/UnQualified.kt new file mode 100644 index 000000000000..e426c2137e7b --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/UnQualified.kt @@ -0,0 +1,10 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +class A { } + +class B { } + +fun foo() { + val x = A() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/UnQualified.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/UnQualified.kt.after new file mode 100644 index 000000000000..c938fa3a18db --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/call/UnQualified.kt.after @@ -0,0 +1,10 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +class A { } + +class B { } + +fun foo() { + val x = B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/FullyQualified.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/FullyQualified.kt new file mode 100644 index 000000000000..11b42d47f02f --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/FullyQualified.kt @@ -0,0 +1,14 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +class A { + fun foo() { } +} + +class B { + fun foo() { } +} + +fun foo() { + val x = org.jetbrains.A::foo +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/FullyQualified.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/FullyQualified.kt.after new file mode 100644 index 000000000000..cdee721f78d9 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/FullyQualified.kt.after @@ -0,0 +1,14 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +class A { + fun foo() { } +} + +class B { + fun foo() { } +} + +fun foo() { + val x = B::foo +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/RootPkg.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/RootPkg.kt new file mode 100644 index 000000000000..a78ba938081f --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/RootPkg.kt @@ -0,0 +1,12 @@ +// BIND_TO B +class A { + fun foo() { } +} + +class B { + fun foo() { } +} + +fun foo() { + val x = A::foo +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/RootPkg.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/RootPkg.kt.after new file mode 100644 index 000000000000..3b7ee7ae1bec --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/RootPkg.kt.after @@ -0,0 +1,12 @@ +// BIND_TO B +class A { + fun foo() { } +} + +class B { + fun foo() { } +} + +fun foo() { + val x = B::foo +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/UnQualified.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/UnQualified.kt new file mode 100644 index 000000000000..b8af557bb967 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/UnQualified.kt @@ -0,0 +1,14 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +class A { + fun foo() { } +} + +class B { + fun foo() { } +} + +fun foo() { + val x = A::foo +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/UnQualified.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/UnQualified.kt.after new file mode 100644 index 000000000000..cdee721f78d9 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/callableReference/UnQualified.kt.after @@ -0,0 +1,14 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +class A { + fun foo() { } +} + +class B { + fun foo() { } +} + +fun foo() { + val x = B::foo +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/ChangeImports.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/ChangeImports.kt new file mode 100644 index 000000000000..04471fe7db6a --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/ChangeImports.kt @@ -0,0 +1,8 @@ +// BIND_TO test.bar.A +package test + +import test.foo.A + +fun foo() { + val x = A() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/ChangeImports.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/ChangeImports.kt.after new file mode 100644 index 000000000000..da55454a82b4 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/ChangeImports.kt.after @@ -0,0 +1,9 @@ +// BIND_TO test.bar.A +package test + + +import test.bar.A + +fun foo() { + val x = A() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/bar/A.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/bar/A.kt new file mode 100644 index 000000000000..a58cee7b163e --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/bar/A.kt @@ -0,0 +1,3 @@ +package test.bar + +class A { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/foo/A.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/foo/A.kt new file mode 100644 index 000000000000..5fe27344ee39 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/import/foo/A.kt @@ -0,0 +1,3 @@ +package test.foo + +class A { } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/FullyQualified.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/FullyQualified.kt new file mode 100644 index 000000000000..adced0a354b2 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/FullyQualified.kt @@ -0,0 +1,10 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +interface A { } + +class B : A { } + +fun foo() { + val x: org.jetbrains.A = B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/FullyQualified.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/FullyQualified.kt.after new file mode 100644 index 000000000000..6613edf678f9 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/FullyQualified.kt.after @@ -0,0 +1,10 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +interface A { } + +class B : A { } + +fun foo() { + val x: B = B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/RootPkg.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/RootPkg.kt new file mode 100644 index 000000000000..ec0c779803ba --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/RootPkg.kt @@ -0,0 +1,8 @@ +// BIND_TO B +interface A { } + +class B : A { } + +fun foo() { + val x: A = B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/RootPkg.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/RootPkg.kt.after new file mode 100644 index 000000000000..ac5af471ff0d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/RootPkg.kt.after @@ -0,0 +1,8 @@ +// BIND_TO B +interface A { } + +class B : A { } + +fun foo() { + val x: B = B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/UnQualified.kt b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/UnQualified.kt new file mode 100644 index 000000000000..2110070208dc --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/UnQualified.kt @@ -0,0 +1,10 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +interface A { } + +class B : A { } + +fun foo() { + val x: A = B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/UnQualified.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/UnQualified.kt.after new file mode 100644 index 000000000000..6613edf678f9 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/bindToElement/type/UnQualified.kt.after @@ -0,0 +1,10 @@ +// BIND_TO org.jetbrains.B +package org.jetbrains + +interface A { } + +class B : A { } + +fun foo() { + val x: B = B() +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/idWithRequiredBackticks.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/idWithRequiredBackticks.kt index d3a9827f62d2..c9dc3e7bf311 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/idWithRequiredBackticks.kt +++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/idWithRequiredBackticks.kt @@ -1,5 +1,5 @@ // PARAM_TYPES: kotlin.Int -// PARAM_DESCRIPTOR: val 0: kotlin.Int defined in test +// PARAM_DESCRIPTOR: val `0`: kotlin.Int defined in test fun test() { val `0` = 0 `0`plus 1 diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/idWithRequiredBackticks.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/idWithRequiredBackticks.kt.after index 51c1f596f9cc..2e165057f829 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/idWithRequiredBackticks.kt.after +++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/idWithRequiredBackticks.kt.after @@ -1,5 +1,5 @@ // PARAM_TYPES: kotlin.Int -// PARAM_DESCRIPTOR: val 0: kotlin.Int defined in test +// PARAM_DESCRIPTOR: val `0`: kotlin.Int defined in test fun test() { val `0` = 0 __dummyTestFun__(`0`) @@ -7,4 +7,4 @@ fun test() { private fun __dummyTestFun__(`0`: Int) { `0` plus 1 -} \ No newline at end of file +} diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/abstractFunction/abstractFunction.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/abstractFunction/abstractFunction.test new file mode 100644 index 000000000000..cd8c516d4141 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/abstractFunction/abstractFunction.test @@ -0,0 +1,8 @@ +{ + "type": "KOTLIN_FUNCTION", + "classId": "/A.B", + "oldName": "absFun", + "newName": "absFun2", + "mainFile": "toBeRenamed.kt", + "enabledInK2": true +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/abstractFunction/after/toBeRenamed.kt b/plugins/kotlin/idea/tests/testData/refactoring/rename/abstractFunction/after/toBeRenamed.kt new file mode 100644 index 000000000000..2bddea685918 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/abstractFunction/after/toBeRenamed.kt @@ -0,0 +1,7 @@ +sealed class A { + internal abstract fun absFun2(x:Int): Int + + abstract class B : A() { + override fun absFun2(x: Int): Int = 1 + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/abstractFunction/before/toBeRenamed.kt b/plugins/kotlin/idea/tests/testData/refactoring/rename/abstractFunction/before/toBeRenamed.kt new file mode 100644 index 000000000000..d1565e34898b --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/abstractFunction/before/toBeRenamed.kt @@ -0,0 +1,7 @@ +sealed class A { + internal abstract fun absFun(x:Int): Int + + abstract class B : A() { + override fun absFun(x: Int): Int = 1 + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObject/companionObject.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObject/companionObject.test index 1b98ee318cbd..25fb85367544 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObject/companionObject.test +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObject/companionObject.test @@ -2,5 +2,6 @@ "type": "KOTLIN_CLASS", "classId": "/Foo.Bar", "newName": "Baz", - "mainFile": "toBeRenamed.kt" + "mainFile": "toBeRenamed.kt", + "enabledInK2": true } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObjectWithDefaultName/companionObject.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObjectWithDefaultName/companionObject.test index 14e771ff5f7a..fdc001860e36 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObjectWithDefaultName/companionObject.test +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObjectWithDefaultName/companionObject.test @@ -2,5 +2,6 @@ "type": "KOTLIN_CLASS", "classId": "/Foo.Companion", "newName": "Baz", - "mainFile": "toBeRenamed.kt" + "mainFile": "toBeRenamed.kt", + "enabledInK2": true } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObjectWithNameMatchingClass/companionObject.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObjectWithNameMatchingClass/companionObject.test index 898429766284..87b1a85ab20d 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObjectWithNameMatchingClass/companionObject.test +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/companionObjectWithNameMatchingClass/companionObject.test @@ -2,5 +2,6 @@ "type": "KOTLIN_CLASS", "classId": "/Foo.Foo", "newName": "Bar", - "mainFile": "toBeRenamed.kt" + "mainFile": "toBeRenamed.kt", + "enabledInK2": true } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/dataClassComponentN/dataClassComponentN.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/dataClassComponentN/dataClassComponentN.test index 136def502e0c..f1e4e3fb64a6 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/dataClassComponentN/dataClassComponentN.test +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/dataClassComponentN/dataClassComponentN.test @@ -3,5 +3,6 @@ "mainFile": "test.kt", "newName": "component123", "withRuntime": "true", - "hint": "Rename is not applicable to synthetic declaration" + "hint": "Rename is not applicable to synthetic declaration", + "enabledInK2": true } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/dataClassCopy/dataClassCopy.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/dataClassCopy/dataClassCopy.test index 0d6c55fab1ba..cb9cc7c83647 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/dataClassCopy/dataClassCopy.test +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/dataClassCopy/dataClassCopy.test @@ -3,5 +3,6 @@ "mainFile": "test.kt", "newName": "copyNew", "withRuntime": "true", - "hint": "Rename is not applicable to synthetic declaration" + "hint": "Rename is not applicable to synthetic declaration", + "enabledInK2": true } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/enumValueOf/enumValueOf.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/enumValueOf/enumValueOf.test index 81a1a57cb22a..a319638e0c39 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/enumValueOf/enumValueOf.test +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/enumValueOf/enumValueOf.test @@ -3,5 +3,6 @@ "mainFile": "test.kt", "newName": "valueOfNew", "withRuntime": "true", - "hint": "Rename is not applicable to synthetic declaration" + "hint": "Rename is not applicable to synthetic declaration", + "enabledInK2": true } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/internalFunWithOverrides/internalFunWithOverrides.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/internalFunWithOverrides/internalFunWithOverrides.test index eaf15b1ef731..d8456e7b985c 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/internalFunWithOverrides/internalFunWithOverrides.test +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/internalFunWithOverrides/internalFunWithOverrides.test @@ -1,5 +1,6 @@ { "type": "MARKED_ELEMENT", "mainFile": "test.kt", - "newName": "newOverridableMethod" + "newName": "newOverridableMethod", + "enabledInK2": true } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/internalVarWithOverrides/internalFunWithOverrides.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/internalVarWithOverrides/internalFunWithOverrides.test index 0d430d008746..c047f9ca4120 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/internalVarWithOverrides/internalFunWithOverrides.test +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/internalVarWithOverrides/internalFunWithOverrides.test @@ -1,5 +1,6 @@ { "type": "MARKED_ELEMENT", "mainFile": "test.kt", - "newName": "newOverridableVar" + "newName": "newOverridableVar", + "enabledInK2": true } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/rename/javaEnumValueOf/javaEnumValueOf.test b/plugins/kotlin/idea/tests/testData/refactoring/rename/javaEnumValueOf/javaEnumValueOf.test index 81a1a57cb22a..8cd61d3dfd0c 100644 --- a/plugins/kotlin/idea/tests/testData/refactoring/rename/javaEnumValueOf/javaEnumValueOf.test +++ b/plugins/kotlin/idea/tests/testData/refactoring/rename/javaEnumValueOf/javaEnumValueOf.test @@ -3,5 +3,6 @@ "mainFile": "test.kt", "newName": "valueOfNew", "withRuntime": "true", - "hint": "Rename is not applicable to synthetic declaration" + "hint": "Rename is not applicable to synthetic declaration", + "enabledInK2": true } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/resolve/compiled/_library/library/Qualifiers.kt b/plugins/kotlin/idea/tests/testData/resolve/compiled/_library/library/Qualifiers.kt new file mode 100644 index 000000000000..cbf0f1d319d9 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/resolve/compiled/_library/library/Qualifiers.kt @@ -0,0 +1,8 @@ +import java.util.List +import java.util.Set +import java.util.Map +import java.util.HashSet + +interface Qualifiers : List { + fun > foo(p: Map) : HashSet +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/resolve/compiled/sources/QualifiedParts.kt b/plugins/kotlin/idea/tests/testData/resolve/compiled/sources/QualifiedParts.kt new file mode 100644 index 000000000000..6c75b3f7559e --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/resolve/compiled/sources/QualifiedParts.kt @@ -0,0 +1,3 @@ +import library.Qualifiers + +class QualifiedParts: Qualifiers {} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/resolve/compiled/sources/QualifiedParts.kt.txt b/plugins/kotlin/idea/tests/testData/resolve/compiled/sources/QualifiedParts.kt.txt new file mode 100644 index 000000000000..6eaeaee61ba2 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/resolve/compiled/sources/QualifiedParts.kt.txt @@ -0,0 +1,17 @@ +PsiPackage:java +PsiPackage:java.util +PsiClass:List +TYPE_PARAMETER +PsiPackage:java +PsiPackage:java.util +PsiClass:Set +TYPE_PARAMETER +PsiPackage:java +PsiPackage:java.util +PsiClass:Map +TYPE_PARAMETER +TYPE_PARAMETER +PsiPackage:java +PsiPackage:java.util +PsiClass:HashSet +TYPE_PARAMETER diff --git a/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedJavaMembers.fir.after b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedJavaMembers.fir.after new file mode 100644 index 000000000000..8a913667ac07 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedJavaMembers.fir.after @@ -0,0 +1,8 @@ +-InheritedJavaMembers.kt + -InheritedJavaMembers + call(): String? location=→Callable + constructor InheritedJavaMembers() + equals(Any?): Boolean location=→Any + hashCode(): Int location=→Any + test(): Unit + toString(): String location=→Any \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembers.after b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembers.after index 310b334b4513..50d4a74adb89 100644 --- a/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembers.after +++ b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembers.after @@ -2,5 +2,6 @@ -Test equals(Any?): Boolean location=→Any hashCode(): Int location=→Any + run(): Unit location=→Runnable test(): Unit - toString(): String location=→Any + toString(): String location=→Any \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembers.kt b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembers.kt index 540c361d06ae..ca41c13b56a3 100644 --- a/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembers.kt +++ b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembers.kt @@ -1,4 +1,4 @@ -class Test: Runable { +class Test: Runnable { fun test() { } diff --git a/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembersOfEnum.fir.after b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembersOfEnum.fir.after new file mode 100644 index 000000000000..a54337caaaed --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedMembersOfEnum.fir.after @@ -0,0 +1,13 @@ +-InheritedMembersOfEnum.kt + -Test + clone(): Any location=→Enum + compareTo(E): Int location=→Enum + equals(Any?): Boolean location=→Enum + finalize(): Unit location=→Enum + FIRST + getDeclaringClass(): Class location=→Enum + hashCode(): Int location=→Enum + name: String location=→Enum + ordinal: Int location=→Enum + SECOND + toString(): String location=→Enum \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.fir.after b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.fir.after new file mode 100644 index 000000000000..d757ce6bf245 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/InheritedSynthesizedFromDataClass.fir.after @@ -0,0 +1,7 @@ +-InheritedSynthesizedFromDataClass.kt + -Derived + a: Int + field: Int + some(): Unit location=→TestData + -TestData + constructor TestData(Int) \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/structureView/fileStructure/Render.fir.after b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/Render.fir.after new file mode 100644 index 000000000000..0b46bbfc316a --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/structureView/fileStructure/Render.fir.after @@ -0,0 +1,45 @@ +-Render.kt + A1 + -A2 + a: Int + b: String + constructor A2(Int, String) + -A3 + a: Int + b: String + constructor A3(Int) + -A4 + constructor A4(T?) + t: T? + -A5 + Inner1 + Inner2 + -A6 + -companion object + test(): Unit + -A7 + + a: Int + a: Int + -b: Any + object + Comparable.a: String + Comparable.extension2(): Unit + -Enum1 + FIRST + SECOND + Interface + Interface1 + String.extension1(): Unit + test1(): Unit + test2(String?): Unit + test3(T, U): Unit + test4(T): Unit + test5(): String + test6(): Comparable + TestWithWhere + testWithWhere(): Unit + withDefaulArgs(Int, String): Unit + -WithDefaultArgs + a: Int + constructor WithDefaultArgs(Int, String) \ No newline at end of file diff --git a/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/conversions/BuiltinMembersConversion.kt b/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/conversions/BuiltinMembersConversion.kt index 1226a8a878f9..02e7299ef0af 100644 --- a/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/conversions/BuiltinMembersConversion.kt +++ b/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/conversions/BuiltinMembersConversion.kt @@ -553,7 +553,7 @@ private class ConversionsHolder(private val symbolProvider: JKSymbolProvider, pr JKExpressionStatement( JKBinaryExpression( //TODO replace with `it` parameter - JKFieldAccessExpression(JKUnresolvedField("it", typeFactory)), + JKFieldAccessExpression(JKUnresolvedField(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier, typeFactory)), JKLiteralExpression("' '", JKLiteralExpression.LiteralType.CHAR), JKKtOperatorImpl(JKOperatorToken.LTEQ, typeFactory.types.boolean) ) diff --git a/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/printing/JKCodeBuilder.kt b/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/printing/JKCodeBuilder.kt index d1e112b0accc..406dfd7f5629 100644 --- a/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/printing/JKCodeBuilder.kt +++ b/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/printing/JKCodeBuilder.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlin.nj2k.printing +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.nj2k.* import org.jetbrains.kotlin.nj2k.printing.JKPrinterBase.ParenthesisKind import org.jetbrains.kotlin.nj2k.symbols.getDisplayFqName @@ -579,7 +580,7 @@ internal class JKCodeBuilder(context: NewJ2kConverterContext) { } override fun visitKtItExpressionRaw(ktItExpression: JKKtItExpression) { - printer.print("it") + printer.print(StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME.identifier) } override fun visitClassBodyRaw(classBody: JKClassBody) { diff --git a/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/tree/GroovyDeclarationHighlightingPassFactory.kt b/plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/tree/declarations.kt similarity index 100% rename from plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/tree/GroovyDeclarationHighlightingPassFactory.kt rename to plugins/kotlin/j2k/new/src/org/jetbrains/kotlin/nj2k/tree/declarations.kt diff --git a/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterMultiFileTestGenerated.java b/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterMultiFileTestGenerated.java index ac79a7bf0924..308343d8bd34 100644 --- a/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterMultiFileTestGenerated.java +++ b/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterMultiFileTestGenerated.java @@ -88,6 +88,11 @@ public class NewJavaToKotlinConverterMultiFileTestGenerated extends AbstractNewJ runTest("testData/multiFile/KT11952/"); } + @TestMetadata("NoDestructuringForPlainVariables") + public void testNoDestructuringForPlainVariables() throws Exception { + runTest("testData/multiFile/NoDestructuringForPlainVariables/"); + } + @TestMetadata("NullabilityByDFa") public void testNullabilityByDFa() throws Exception { runTest("testData/multiFile/NullabilityByDFa/"); diff --git a/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java b/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java index c900d261dca1..6e43f9317d7f 100644 --- a/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java +++ b/plugins/kotlin/j2k/new/tests/test/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java @@ -3539,11 +3539,6 @@ public abstract class NewJavaToKotlinConverterSingleFileTestGenerated extends Ab runTest("testData/newJ2k/issues/kt-871.java"); } - @TestMetadata("kt-879.java") - public void testKt_879() throws Exception { - runTest("testData/newJ2k/issues/kt-879.java"); - } - @TestMetadata("kt-893.java") public void testKt_893() throws Exception { runTest("testData/newJ2k/issues/kt-893.java"); @@ -4941,6 +4936,26 @@ public abstract class NewJavaToKotlinConverterSingleFileTestGenerated extends Ab runTest("testData/newJ2k/postProcessing/java8MapForEachWithFullJdk.java"); } + @TestMetadata("LiftAssignmentComplex.java") + public void testLiftAssignmentComplex() throws Exception { + runTest("testData/newJ2k/postProcessing/LiftAssignmentComplex.java"); + } + + @TestMetadata("LiftAssignmentSingleStatement.java") + public void testLiftAssignmentSingleStatement() throws Exception { + runTest("testData/newJ2k/postProcessing/LiftAssignmentSingleStatement.java"); + } + + @TestMetadata("LiftReturnComplex.java") + public void testLiftReturnComplex() throws Exception { + runTest("testData/newJ2k/postProcessing/LiftReturnComplex.java"); + } + + @TestMetadata("LiftReturnSingleStatement.java") + public void testLiftReturnSingleStatement() throws Exception { + runTest("testData/newJ2k/postProcessing/LiftReturnSingleStatement.java"); + } + @TestMetadata("MapGetOrDefault.java") public void testMapGetOrDefault() throws Exception { runTest("testData/newJ2k/postProcessing/MapGetOrDefault.java"); diff --git a/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.expected.kt b/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.expected.kt index 7d8a9aa2da86..37b88fe20109 100644 --- a/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.expected.kt +++ b/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.expected.kt @@ -1,7 +1,7 @@ class A { fun foo() { val list = ArrayList() - list.add(1) + list.add("1") } fun bar() {} diff --git a/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.to.kt.expected b/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.to.kt.expected deleted file mode 100644 index 9515b31e1d97..000000000000 --- a/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.to.kt.expected +++ /dev/null @@ -1,3 +0,0 @@ -class A { - -} \ No newline at end of file diff --git a/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.txt b/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.txt index b028b2d8735b..9c186610212e 100644 --- a/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.txt +++ b/plugins/kotlin/j2k/new/tests/testData/copyPastePlainText/MembersIntoClass.txt @@ -1,6 +1,6 @@ void foo() { ArrayList list = new ArrayList(); - list.add(1); + list.add("1"); } void bar() { diff --git a/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/Main.java b/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/Main.java new file mode 100644 index 000000000000..6511af670aa9 --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/Main.java @@ -0,0 +1,9 @@ +public class J { + public void test() { + Pojo pojo = new Pojo("a", "b"); + doSomething(pojo.getFieldB()); + } + + private void doSomething(String myString) { + } +} \ No newline at end of file diff --git a/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/Main.kt b/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/Main.kt new file mode 100644 index 000000000000..b2e2322645ac --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/Main.kt @@ -0,0 +1,8 @@ +class J { + fun test() { + val pojo = Pojo("a", "b") + doSomething(pojo.fieldB) + } + + private fun doSomething(myString: String) {} +} diff --git a/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/external/A.kt b/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/external/A.kt new file mode 100644 index 000000000000..3d3c51915034 --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/external/A.kt @@ -0,0 +1 @@ +data class Pojo(val fieldA: String, val fieldB: String) \ No newline at end of file diff --git a/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/external/A.kt.expected b/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/external/A.kt.expected new file mode 100644 index 000000000000..3d3c51915034 --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/multiFile/NoDestructuringForPlainVariables/external/A.kt.expected @@ -0,0 +1 @@ +data class Pojo(val fieldA: String, val fieldB: String) \ No newline at end of file diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/ifStatement/withBlocks.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/ifStatement/withBlocks.kt index 1d6e7ef3083a..b015040554ab 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/ifStatement/withBlocks.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/ifStatement/withBlocks.kt @@ -1,6 +1,6 @@ -return if (1 > 0) { +if (1 > 0) { val n = 1 - n + return n } else { - 0 + return 0 } diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/issues/kt-19340.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/issues/kt-19340.kt index 53d2490189fc..40091722e81d 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/issues/kt-19340.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/issues/kt-19340.kt @@ -3,7 +3,7 @@ package test.nullabilityOnClassBoundaries class Item { private var s1: String? = null private var s2: String? = null - operator fun set(s1: String?, s2: String?) { + fun set(s1: String?, s2: String?) { this.s1 = s1 this.s2 = s2 } @@ -12,7 +12,7 @@ class Item { class Reader { fun readItem(n: Int): Item { val item = Item() - item[readString(n)] = null + item.set(readString(n), null) return item } diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/newJavaFeatures/switchExpression/returnsAndThrows.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/newJavaFeatures/switchExpression/returnsAndThrows.kt index 36b7b764a708..cd4d2e02d6cd 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/newJavaFeatures/switchExpression/returnsAndThrows.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/newJavaFeatures/switchExpression/returnsAndThrows.kt @@ -1,13 +1,13 @@ fun foo(a: Int): Int { - val b: Int = return when (a) { + val b: Int = when (a) { 1 -> { println("1") - 1 + return 1 } 2 -> { println("2") - 2 + return 2 } 3 -> { @@ -17,7 +17,7 @@ fun foo(a: Int): Int { else -> { println("default") - 0 + return 0 } } } diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull2.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull2.kt index 030e81cd44fd..fd82538dbd58 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull2.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull2.kt @@ -5,6 +5,8 @@ internal interface I { internal class C { fun foo(i: I) { val result = i.string - result?.let { print(it) } + if (result != null) { + print(result) + } } -} \ No newline at end of file +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull3.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull3.kt index 030e81cd44fd..fd82538dbd58 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull3.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull3.kt @@ -5,6 +5,8 @@ internal interface I { internal class C { fun foo(i: I) { val result = i.string - result?.let { print(it) } + if (result != null) { + print(result) + } } -} \ No newline at end of file +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull4.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull4.kt index 5dd087d712e6..b0deb74e5312 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull4.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/MethodResultComparedWithNull4.kt @@ -6,6 +6,8 @@ internal class C { fun foo(i: I, b: Boolean) { var result = i.string if (b) result = null - result?.let { print(it) } + if (result != null) { + print(result) + } } -} \ No newline at end of file +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/ParameterComparedWithNull.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/ParameterComparedWithNull.kt index 3fc71b3e365e..36220527aa42 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/ParameterComparedWithNull.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/ParameterComparedWithNull.kt @@ -1,3 +1,5 @@ fun foo(s: String?) { - s?.let { zoo(it) } -} \ No newline at end of file + if (s != null) { + zoo(s) + } +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/VariableComparedWithNull.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/VariableComparedWithNull.kt index e04b405c60ff..bbd47b6f3c71 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/VariableComparedWithNull.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/nullability/VariableComparedWithNull.kt @@ -5,5 +5,7 @@ fun bar(): String? { fun foo() { val s: String? = bar() - s?.let { zoo(it) } -} \ No newline at end of file + if (s != null) { + zoo(s) + } +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/GetOperator.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/GetOperator.kt index e4fbe0708122..b04b9e0ac007 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/GetOperator.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/GetOperator.kt @@ -2,7 +2,7 @@ import javaApi.JavaClass import kotlinApi.KotlinClass internal class X { - operator fun get(index: Int): Int { + fun get(index: Int): Int { return 0 } } @@ -13,7 +13,7 @@ internal class C { } fun foo(x: X): Int { - return x[0] + return x.get(0) } fun foo(kotlinClass: KotlinClass): Int { @@ -23,4 +23,4 @@ internal class C { fun foo(javaClass: JavaClass): Int { return javaClass[0] } -} \ No newline at end of file +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentComplex.java b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentComplex.java new file mode 100644 index 000000000000..37427614f2ae --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentComplex.java @@ -0,0 +1,14 @@ +class Test { + public static void test(int i) { + int x; + if (i == 1) { + System.out.println(1); + x = 1; + } else if (i == 2) { + System.out.println(2); + x = 2; + } else { + x = 3; + } + } +} \ No newline at end of file diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentComplex.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentComplex.kt new file mode 100644 index 000000000000..99010a59f3da --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentComplex.kt @@ -0,0 +1,14 @@ +internal object Test { + fun test(i: Int) { + val x: Int + if (i == 1) { + println(1) + x = 1 + } else if (i == 2) { + println(2) + x = 2 + } else { + x = 3 + } + } +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentSingleStatement.java b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentSingleStatement.java new file mode 100644 index 000000000000..54fbf2f900d4 --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentSingleStatement.java @@ -0,0 +1,12 @@ +class Test { + public static void test(int i) { + int x; + if (i == 1) { + x = 1; + } else if (i == 2) { + x = 2; + } else { + x = 3; + } + } +} \ No newline at end of file diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentSingleStatement.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentSingleStatement.kt new file mode 100644 index 000000000000..ada79d76a53c --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftAssignmentSingleStatement.kt @@ -0,0 +1,12 @@ +internal object Test { + fun test(i: Int) { + val x: Int + x = if (i == 1) { + 1 + } else if (i == 2) { + 2 + } else { + 3 + } + } +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/issues/kt-879.java b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnComplex.java similarity index 69% rename from plugins/kotlin/j2k/new/tests/testData/newJ2k/issues/kt-879.java rename to plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnComplex.java index c9cbe1b36041..b59e4ba449c0 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/issues/kt-879.java +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnComplex.java @@ -1,15 +1,12 @@ -//file class Test { public static int getInt(int i) { switch (i) { case 0: + System.out.println(0); return 0; case 1: + System.out.println(1); return 1; - case 2: - return 2; - case 3: - return 3; default: return -1; } diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnComplex.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnComplex.kt new file mode 100644 index 000000000000..fa20038f5ef7 --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnComplex.kt @@ -0,0 +1,17 @@ +internal object Test { + fun getInt(i: Int): Int { + when (i) { + 0 -> { + println(0) + return 0 + } + + 1 -> { + println(1) + return 1 + } + + else -> return -1 + } + } +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnSingleStatement.java b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnSingleStatement.java new file mode 100644 index 000000000000..20e7a9cf9fda --- /dev/null +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnSingleStatement.java @@ -0,0 +1,12 @@ +class Test { + public static int getInt(int i) { + switch (i) { + case 0: + return 0; + case 1: + return 1; + default: + return -1; + } + } +} \ No newline at end of file diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/issues/kt-879.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnSingleStatement.kt similarity index 80% rename from plugins/kotlin/j2k/new/tests/testData/newJ2k/issues/kt-879.kt rename to plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnSingleStatement.kt index 3a65749bb813..01a35a5d8c05 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/issues/kt-879.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/LiftReturnSingleStatement.kt @@ -3,8 +3,6 @@ internal object Test { return when (i) { 0 -> 0 1 -> 1 - 2 -> 2 - 3 -> 3 else -> -1 } } diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/MapGetOrDefault.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/MapGetOrDefault.kt index 0fe19f7ce37f..9a70124ea876 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/MapGetOrDefault.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/postProcessing/MapGetOrDefault.kt @@ -1,5 +1,5 @@ internal class C { private fun foo(map: Map): String { - return map[1] ?: "bar" + return map.getOrDefault(1, "bar") } -} \ No newline at end of file +} diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/switch/nestedSwitchFallback.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/switch/nestedSwitchFallback.kt index 83c20f9cbf60..b5ae6f9c9362 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/switch/nestedSwitchFallback.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/switch/nestedSwitchFallback.kt @@ -1,14 +1,14 @@ fun foo(i: Int, j: Int): String { - return when (i) { + when (i) { 0 -> { when (j) { 1 -> return "0, 1" 2 -> return "0, 2" } - "1, x" + return "1, x" } - 1 -> "1, x" - else -> "x, x" + 1 -> return "1, x" + else -> return "x, x" } } diff --git a/plugins/kotlin/j2k/new/tests/testData/newJ2k/switch/returnsAndThrows.kt b/plugins/kotlin/j2k/new/tests/testData/newJ2k/switch/returnsAndThrows.kt index a510789e1a06..2ca9ac934e2e 100644 --- a/plugins/kotlin/j2k/new/tests/testData/newJ2k/switch/returnsAndThrows.kt +++ b/plugins/kotlin/j2k/new/tests/testData/newJ2k/switch/returnsAndThrows.kt @@ -1,13 +1,13 @@ fun foo(a: Int): Int { - return when (a) { + when (a) { 1 -> { println("1") - 1 + return 1 } 2 -> { println("2") - 2 + return 2 } 3 -> { @@ -17,7 +17,7 @@ fun foo(a: Int): Int { else -> { println("default") - 0 + return 0 } } } diff --git a/plugins/kotlin/j2k/post-processing/src/org/jetbrains/kotlin/idea/j2k/post/processing/J2kPostProcessor.kt b/plugins/kotlin/j2k/post-processing/src/org/jetbrains/kotlin/idea/j2k/post/processing/J2kPostProcessor.kt index 60c6f8fa7ca4..f57f54f3964d 100644 --- a/plugins/kotlin/j2k/post-processing/src/org/jetbrains/kotlin/idea/j2k/post/processing/J2kPostProcessor.kt +++ b/plugins/kotlin/j2k/post-processing/src/org/jetbrains/kotlin/idea/j2k/post/processing/J2kPostProcessor.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.idea.intentions.* import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.FoldIfToReturnAsymmetricallyIntention import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.FoldIfToReturnIntention import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isTrivialStatementBody +import org.jetbrains.kotlin.idea.intentions.branchedTransformations.shouldBeTransformed import org.jetbrains.kotlin.idea.j2k.post.processing.processings.* import org.jetbrains.kotlin.idea.quickfix.* import org.jetbrains.kotlin.idea.util.ImportInsertHelper @@ -171,7 +172,6 @@ private val addOrRemoveModifiersProcessingGroup = processings = listOf( RemoveRedundantVisibilityModifierProcessing(), RemoveRedundantModalityModifierProcessing(), - inspectionBasedProcessing(AddOperatorModifierInspection(), writeActionNeeded = false), ) ) @@ -201,7 +201,6 @@ private val inspectionLikePostProcessingGroup = JavaObjectEqualsToEqOperatorProcessing(), RemoveExplicitPropertyTypeProcessing(), RemoveRedundantNullabilityProcessing(), - CanBeValInspectionBasedProcessing(), inspectionBasedProcessing(FoldInitializerAndIfToElvisInspection(), writeActionNeeded = false), inspectionBasedProcessing(JavaMapForEachInspection()), intentionBasedProcessing(FoldIfToReturnIntention()) { it.then.isTrivialStatementBody() && it.`else`.isTrivialStatementBody() }, @@ -210,22 +209,25 @@ private val inspectionLikePostProcessingGroup = it ) as KtReturnExpression).returnedExpression.isTrivialStatementBody() }, - inspectionBasedProcessing(IfThenToSafeAccessInspection(inlineWithPrompt = false), writeActionNeeded = false), - inspectionBasedProcessing(IfThenToElvisInspection(highlightStatement = true, inlineWithPrompt = false), writeActionNeeded = false), + inspectionBasedProcessing(IfThenToSafeAccessInspection(inlineWithPrompt = false), writeActionNeeded = false) { + it.shouldBeTransformed() + }, + inspectionBasedProcessing(IfThenToElvisInspection(highlightStatement = true, inlineWithPrompt = false), writeActionNeeded = false) { + it.shouldBeTransformed() + }, inspectionBasedProcessing(KotlinInspectionFacade.instance.simplifyNegatedBinaryExpression) { it.canBeSimplifiedWithoutChangingSemantics() }, inspectionBasedProcessing(ReplaceGetOrSetInspection()), intentionBasedProcessing(ObjectLiteralToLambdaIntention(), writeActionNeeded = true), intentionBasedProcessing(RemoveUnnecessaryParenthesesIntention()), - intentionBasedProcessing(DestructureIntention(), writeActionNeeded = false), + DestructureForLoopParameterProcessing(), inspectionBasedProcessing(SimplifyAssertNotNullInspection()), LiftReturnInspectionBasedProcessing(), LiftAssignmentInspectionBasedProcessing(), intentionBasedProcessing(RemoveEmptyPrimaryConstructorIntention()), MayBeConstantInspectionBasedProcessing(), RemoveForExpressionLoopParameterTypeProcessing(), - intentionBasedProcessing(ReplaceMapGetOrDefaultIntention()), inspectionBasedProcessing(ReplaceGuardClauseWithFunctionCallInspection()), inspectionBasedProcessing(KotlinInspectionFacade.instance.sortModifiers), intentionBasedProcessing(ConvertToRawStringTemplateIntention(), additionalChecker = ::shouldConvertToRawString), @@ -246,8 +248,8 @@ private val processings: List = listOf( listOf( InspectionLikeProcessingGroup( processings = listOf( - VarToValProcessing(), - CanBeValInspectionBasedProcessing() + PrivateVarToValProcessing(), + LocalVarToValInspectionBasedProcessing() ), runSingleTime = true ), @@ -259,7 +261,6 @@ private val processings: List = listOf( NamedPostProcessingGroup( KotlinNJ2KServicesBundle.message("processing.step.cleaning.up.code"), listOf( - InspectionLikeProcessingGroup(VarToValProcessing()), ConvertGettersAndSettersToPropertyProcessing(), InspectionLikeProcessingGroup(RemoveExplicitAccessorInspectionBasedProcessing()), MergePropertyWithConstructorParameterProcessing(), diff --git a/plugins/kotlin/j2k/post-processing/src/org/jetbrains/kotlin/idea/j2k/post/processing/inspectionLikePostProcessings.kt b/plugins/kotlin/j2k/post-processing/src/org/jetbrains/kotlin/idea/j2k/post/processing/inspectionLikePostProcessings.kt index 9a6b24f6def4..0ed0b8630dcd 100644 --- a/plugins/kotlin/j2k/post-processing/src/org/jetbrains/kotlin/idea/j2k/post/processing/inspectionLikePostProcessings.kt +++ b/plugins/kotlin/j2k/post-processing/src/org/jetbrains/kotlin/idea/j2k/post/processing/inspectionLikePostProcessings.kt @@ -11,6 +11,7 @@ import com.intellij.profile.codeInspection.InspectionProfileManager import com.intellij.psi.PsiElement import com.intellij.psi.PsiRecursiveElementVisitor import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractApplicabilityBasedInspection +import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractKotlinInspection import org.jetbrains.kotlin.idea.codeinsight.api.classic.intentions.SelfTargetingRangeIntention import org.jetbrains.kotlin.idea.util.application.isUnitTestMode import org.jetbrains.kotlin.j2k.ConverterSettings @@ -166,17 +167,7 @@ internal inline fun Boolean = { true } ) = object : InspectionLikeProcessingForElement(E::class.java) { override fun isApplicableTo(element: E, settings: ConverterSettings?): Boolean = - isInspectionEnabledInCurrentProfile(element.project) && inspection.isApplicable(element) && additionalChecker(element) - - private fun isInspectionEnabledInCurrentProfile(project: Project): Boolean { - if (isUnitTestMode()) { - // there is no real inspection profile in J2K tests, consider all inspections to be enabled in tests - return true - } - val inspectionProfile = InspectionProfileManager.getInstance(project).getCurrentProfile() - val highlightDisplayKey = HighlightDisplayKey.findById(inspection.getID()) - return inspectionProfile.isToolEnabled(highlightDisplayKey) - } + isInspectionEnabledInCurrentProfile(inspection, element.project) && inspection.isApplicable(element) && additionalChecker(element) override fun apply(element: E) { inspection.applyTo(element) @@ -184,3 +175,13 @@ internal inline fun (KtProperty::class.java) { override fun isApplicableTo(element: KtProperty, settings: ConverterSettings?): Boolean { if (element.isMember && !element.isPrivate()) return false @@ -176,12 +185,14 @@ internal class RemoveRedundantCastToNullableProcessing : } } -internal class RemoveRedundantSamAdaptersProcessing : - InspectionLikeProcessingForElement(KtCallExpression::class.java) { +internal class RemoveRedundantSamAdaptersProcessing : InspectionLikeProcessingForElement(KtCallExpression::class.java) { + private val inspection = RedundantSamConstructorInspection() + override val writeActionNeeded = false override fun isApplicableTo(element: KtCallExpression, settings: ConverterSettings?): Boolean = - RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element).isNotEmpty() + isInspectionEnabledInCurrentProfile(inspection, element.project) && + RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element).isNotEmpty() override fun apply(element: KtCallExpression) { val callsToBeConverted = RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element) @@ -230,7 +241,7 @@ internal class UnresolvedVariableReferenceFromInitializerToThisReferenceProcessi } } -internal class VarToValProcessing : InspectionLikeProcessingForElement(KtProperty::class.java) { +internal class PrivateVarToValProcessing : InspectionLikeProcessingForElement(KtProperty::class.java) { companion object { private val JPA_COLUMN_ANNOTATIONS: Set = setOf( FqName("javax.persistence.Column"), @@ -293,7 +304,6 @@ internal class JavaObjectEqualsToEqOperatorProcessing : InspectionLikeProcessing } } - internal class RemoveForExpressionLoopParameterTypeProcessing : InspectionLikeProcessingForElement(KtForExpression::class.java) { override fun isApplicableTo(element: KtForExpression, settings: ConverterSettings?): Boolean { @@ -322,19 +332,24 @@ internal class RemoveRedundantModalityModifierProcessing : InspectionLikeProcess } } - internal class RemoveRedundantVisibilityModifierProcessing : InspectionLikeProcessingForElement(KtDeclaration::class.java) { + private val inspection = RedundantVisibilityModifierInspection() + override fun isApplicableTo(element: KtDeclaration, settings: ConverterSettings?): Boolean = - RedundantVisibilityModifierInspection.Holder.getRedundantVisibility(element) != null + isInspectionEnabledInCurrentProfile(inspection, element.project) && + RedundantVisibilityModifierInspection.Holder.getRedundantVisibility(element) != null override fun apply(element: KtDeclaration) { element.visibilityModifierType()?.let { element.removeModifier(it) } } } -internal class CanBeValInspectionBasedProcessing : InspectionLikeProcessingForElement(KtDeclaration::class.java) { +internal class LocalVarToValInspectionBasedProcessing : InspectionLikeProcessingForElement(KtDeclaration::class.java) { + private val inspection = CanBeValInspection() + override fun isApplicableTo(element: KtDeclaration, settings: ConverterSettings?): Boolean = - CanBeValInspection.canBeVal(element, ignoreNotUsedVals = false) + isInspectionEnabledInCurrentProfile(inspection, element.project) && + CanBeValInspection.canBeVal(element, ignoreNotUsedVals = false) override fun apply(element: KtDeclaration) { val project = element.project @@ -343,14 +358,14 @@ internal class CanBeValInspectionBasedProcessing : InspectionLikeProcessingForEl } } - internal class MayBeConstantInspectionBasedProcessing : InspectionLikeProcessingForElement(KtProperty::class.java) { - override fun isApplicableTo(element: KtProperty, settings: ConverterSettings?): Boolean = - with(MayBeConstantInspection) { - val status = element.getStatus() - status == MayBeConstantInspection.Status.MIGHT_BE_CONST - || status == MayBeConstantInspection.Status.JVM_FIELD_MIGHT_BE_CONST - } + private val inspection = MayBeConstantInspection() + + override fun isApplicableTo(element: KtProperty, settings: ConverterSettings?): Boolean { + if (!isInspectionEnabledInCurrentProfile(inspection, element.project)) return false + val status = element.getStatus() + return status == MIGHT_BE_CONST || status == JVM_FIELD_MIGHT_BE_CONST + } override fun apply(element: KtProperty) { AddConstModifierFix.addConstModifier(element) @@ -367,50 +382,65 @@ internal class RemoveExplicitAccessorInspectionBasedProcessing : } } -internal class ExplicitThisInspectionBasedProcessing : - InspectionLikeProcessingForElement(KtExpression::class.java) { +internal class ExplicitThisInspectionBasedProcessing : InspectionLikeProcessingForElement(KtExpression::class.java) { + private val inspection = ExplicitThisInspection() + override fun isApplicableTo(element: KtExpression, settings: ConverterSettings?): Boolean = - ExplicitThisInspection.hasExplicitThis(element) + isInspectionEnabledInCurrentProfile(inspection, element.project) && + ExplicitThisInspection.hasExplicitThis(element) override fun apply(element: KtExpression) { - ExplicitThisExpressionFix.removeExplicitThisExpression( - with(ExplicitThisInspection) { - element.thisAsReceiverOrNull() ?: return - } - ) + val thisExpression = element.thisAsReceiverOrNull() ?: return + ExplicitThisExpressionFix.removeExplicitThisExpression(thisExpression) } } -internal class LiftReturnInspectionBasedProcessing : - InspectionLikeProcessingForElement(KtExpression::class.java) { - override fun isApplicableTo(element: KtExpression, settings: ConverterSettings?): Boolean = - LiftReturnOrAssignmentInspection.getState(element, false)?.any { - it.liftType == LiftReturnOrAssignmentInspection.Companion.LiftType.LIFT_RETURN_OUT - } ?: false +internal class LiftReturnInspectionBasedProcessing : InspectionLikeProcessingForElement(KtExpression::class.java) { + private val inspection = LiftReturnOrAssignmentInspection() + + override fun isApplicableTo(element: KtExpression, settings: ConverterSettings?): Boolean { + if (!isInspectionEnabledInCurrentProfile(inspection, element.project)) return false + val state = LiftReturnOrAssignmentInspection.getState(element, skipLongExpressions = false) ?: return false + return state.any { it.liftType == LIFT_RETURN_OUT && it.isSerious } + } override fun apply(element: KtExpression) { BranchedFoldingUtils.foldToReturn(element) } } -internal class LiftAssignmentInspectionBasedProcessing : - InspectionLikeProcessingForElement(KtExpression::class.java) { - override fun isApplicableTo(element: KtExpression, settings: ConverterSettings?): Boolean = - LiftReturnOrAssignmentInspection.getState(element, false)?.any { - it.liftType == LiftReturnOrAssignmentInspection.Companion.LiftType.LIFT_ASSIGNMENT_OUT - } ?: false +internal class LiftAssignmentInspectionBasedProcessing : InspectionLikeProcessingForElement(KtExpression::class.java) { + private val inspection = LiftReturnOrAssignmentInspection() + + override fun isApplicableTo(element: KtExpression, settings: ConverterSettings?): Boolean { + if (!isInspectionEnabledInCurrentProfile(inspection, element.project)) return false + val state = LiftReturnOrAssignmentInspection.getState(element, skipLongExpressions = false) ?: return false + return state.any { it.liftType == LIFT_ASSIGNMENT_OUT && it.isSerious } + } override fun apply(element: KtExpression) { BranchedFoldingUtils.tryFoldToAssignment(element) } } -internal class MoveLambdaOutsideParenthesesProcessing : - InspectionLikeProcessingForElement(KtCallExpression::class.java) { +internal class MoveLambdaOutsideParenthesesProcessing : InspectionLikeProcessingForElement(KtCallExpression::class.java) { + private val inspection = MoveLambdaOutsideParenthesesInspection() + override fun isApplicableTo(element: KtCallExpression, settings: ConverterSettings?): Boolean = - element.canMoveLambdaOutsideParentheses() + isInspectionEnabledInCurrentProfile(inspection, element.project) && + element.canMoveLambdaOutsideParentheses() override fun apply(element: KtCallExpression) { element.moveFunctionLiteralOutsideParentheses() } +} + +// Don't destructure regular variables, it will lose the original variable name and may hurt code readability +internal class DestructureForLoopParameterProcessing : InspectionLikeProcessingForElement(KtParameter::class.java) { + override fun isApplicableTo(element: KtParameter, settings: ConverterSettings?): Boolean = + element.parent is KtForExpression && DestructureIntention.Holder.applicabilityRange(element) != null + + override fun apply(element: KtParameter) { + DestructureIntention.Holder.applyTo(element) + } } \ No newline at end of file diff --git a/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/core/ClassNameProvider.kt b/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/core/ClassNameProvider.kt index 64cecccdba42..341af3e32f4e 100644 --- a/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/core/ClassNameProvider.kt +++ b/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/core/ClassNameProvider.kt @@ -168,7 +168,14 @@ class ClassNameProvider( ProgressManager.getInstance().runProcessWithProgressSynchronously(task, progressMessage, true, project) } else { try { - ProgressManager.getInstance().runProcess(task, ProgressIndicatorBase()) + // We should not create new indicator when already running in a process, + // as it will make the outer process not cancellable + val currentIndicator = ProgressManager.getInstance().progressIndicator + if (currentIndicator != null) { + task.run() + } else { + ProgressManager.getInstance().runProcess(task, ProgressIndicatorBase()) + } true } catch (e: InterruptedException) { false diff --git a/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/core/KotlinPositionManager.kt b/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/core/KotlinPositionManager.kt index e95ab99fa7fa..d2a651552b33 100644 --- a/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/core/KotlinPositionManager.kt +++ b/plugins/kotlin/jvm-debugger/core/src/org/jetbrains/kotlin/idea/debugger/core/KotlinPositionManager.kt @@ -16,11 +16,13 @@ import com.intellij.debugger.impl.DebuggerUtilsAsync import com.intellij.debugger.impl.DebuggerUtilsEx import com.intellij.debugger.jdi.StackFrameProxyImpl import com.intellij.debugger.requests.ClassPrepareRequestor +import com.intellij.debugger.ui.breakpoints.Breakpoint import com.intellij.debugger.ui.impl.watch.StackFrameDescriptorImpl import com.intellij.openapi.application.ReadAction import com.intellij.openapi.application.runReadAction import com.intellij.openapi.components.serviceOrNull import com.intellij.openapi.fileTypes.FileType +import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.util.registry.Registry import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiElement @@ -31,8 +33,10 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.childrenOfType import com.intellij.psi.util.parentOfType import com.intellij.util.ThreeState +import com.intellij.util.asSafely import com.intellij.util.concurrency.annotations.RequiresReadLock import com.intellij.xdebugger.frame.XStackFrame +import com.intellij.xdebugger.impl.XDebugSessionImpl import com.jetbrains.jdi.LocalVariableImpl import com.sun.jdi.* import com.sun.jdi.request.ClassPrepareRequest @@ -563,7 +567,7 @@ class KotlinPositionManager(private val debugProcess: DebugProcess) : MultiReque } val isInsideProjectWithCompose = position.isInsideProjectWithCompose() - return ReadAction.nonBlocking> { + var nonBlocking = ReadAction.nonBlocking> { val kotlinRequests = createKotlinClassPrepareRequests(requestor, position) if (isInsideProjectWithCompose) { val singletonRequest = getClassPrepareRequestForComposableSingletons(debugProcess, requestor, file) @@ -574,7 +578,19 @@ class KotlinPositionManager(private val debugProcess: DebugProcess) : MultiReque } else { kotlinRequests } - }.inSmartMode(debugProcess.project).executeSynchronously() + } + .inSmartMode(debugProcess.project) + + val xBreakpoint = requestor.safeAs>()?.xBreakpoint + val xSession = debugProcess.asSafely()?.xdebugProcess?.session.asSafely() + if (xBreakpoint != null && xSession != null) { + nonBlocking = nonBlocking.expireWhen { !xSession.isBreakpointActive(xBreakpoint) } + } + try { + return nonBlocking.executeSynchronously() + } catch (_: ProcessCanceledException) { + return emptyList() + } } @RequiresReadLock diff --git a/plugins/kotlin/jvm-debugger/test/testData/stepping/stepInto/accessors.kt b/plugins/kotlin/jvm-debugger/test/testData/stepping/stepInto/accessors.kt index 35ec74dcb467..3764c1b763e5 100644 --- a/plugins/kotlin/jvm-debugger/test/testData/stepping/stepInto/accessors.kt +++ b/plugins/kotlin/jvm-debugger/test/testData/stepping/stepInto/accessors.kt @@ -28,6 +28,4 @@ class A { } // STEP_INTO: 17 -// SKIP_SYNTHETIC_METHODS: false -// IGNORE_FOR_K2_CODE -// Remove ignore after KT-57489 fix \ No newline at end of file +// SKIP_SYNTHETIC_METHODS: false \ No newline at end of file diff --git a/plugins/kotlin/jvm-debugger/test/testData/stepping/stepOver/coroutines/sequenceNested.k2.out b/plugins/kotlin/jvm-debugger/test/testData/stepping/stepOver/coroutines/sequenceNested.k2.out deleted file mode 100644 index 46f7187fdae3..000000000000 --- a/plugins/kotlin/jvm-debugger/test/testData/stepping/stepOver/coroutines/sequenceNested.k2.out +++ /dev/null @@ -1,12 +0,0 @@ -LineBreakpoint created at sequenceNested.kt:6 -Run Java -Connected to the target VM -sequenceNested.kt:6 -sequenceNested.kt:15 -sequenceNested.kt:14 -sequenceNested.kt:21 -sequenceNested.kt:23 -sequenceNested.kt:24 -Disconnected from the target VM - -Process finished with exit code 0 diff --git a/plugins/kotlin/jvm-decompiler/src/org/jetbrains/kotlin/idea/jvmDecompiler/KotlinDecompilerAdapter.kt b/plugins/kotlin/jvm-decompiler/src/org/jetbrains/kotlin/idea/jvmDecompiler/KotlinDecompilerAdapter.kt index a93971bd25e6..52f7131f4448 100644 --- a/plugins/kotlin/jvm-decompiler/src/org/jetbrains/kotlin/idea/jvmDecompiler/KotlinDecompilerAdapter.kt +++ b/plugins/kotlin/jvm-decompiler/src/org/jetbrains/kotlin/idea/jvmDecompiler/KotlinDecompilerAdapter.kt @@ -28,34 +28,44 @@ class KotlinBytecodeDecompilerTask(private val file: KtFile) : Task.Backgroundab KotlinBytecodeDecompiler.decompile(file) } catch (e: DecompileFailedException) { null + } ?: run { + ApplicationManager.getApplication().invokeLater { + Messages.showErrorDialog( + KotlinJvmDecompilerBundle.message("internal.error.text.cannot.decompile", file.name), + KotlinJvmDecompilerBundle.message("internal.title.decompiler.error") + ) + } + return } ApplicationManager.getApplication().invokeLater { - runWriteAction { - if (!file.isValid || file.project.isDisposed) return@runWriteAction - - if (decompiledText == null) { - ApplicationManager.getApplication().invokeLater { - Messages.showErrorDialog( - KotlinJvmDecompilerBundle.message("internal.error.text.cannot.decompile", file.name), - KotlinJvmDecompilerBundle.message("internal.title.decompiler.error") - ) - } - return@runWriteAction - } - - val root: VirtualFile = getOrCreateDummyRoot() - val decompiledFileName = FileUtil.getNameWithoutExtension(file.name) + ".decompiled.java" - val result = DummyFileSystem.getInstance().createChildFile(null, root, decompiledFileName) - VfsUtil.saveText(result, decompiledText) - - result.isKotlinDecompiledFile = true - - OpenFileDescriptor(file.project, result).navigate(true) + generateDecompiledVirtualFile(decompiledText)?.let { + OpenFileDescriptor(file.project, it).navigate(true) } } } + fun generateDecompiledVirtualFile(decompiledText: String? = null): VirtualFile? { + if (!file.isValid || file.project.isDisposed) return null + + val text = decompiledText ?: try { + KotlinBytecodeDecompiler.decompile(file) + } catch (e: DecompileFailedException) { + null + } ?: return null + + val virtualFile: VirtualFile = runWriteAction { + val root: VirtualFile = getOrCreateDummyRoot() + val decompiledFileName = FileUtil.getNameWithoutExtension(file.name) + ".decompiled.java" + val result = DummyFileSystem.getInstance().createChildFile(null, root, decompiledFileName) + VfsUtil.saveText(result, text) + result + } + + virtualFile.isKotlinDecompiledFile = true + return virtualFile + } + private fun getOrCreateDummyRoot(): VirtualFile = VirtualFileManager.getInstance().refreshAndFindFileByUrl(KOTLIN_DECOMPILED_ROOT) ?: DummyFileSystem.getInstance().createRoot(KOTLIN_DECOMPILED_FOLDER) diff --git a/plugins/kotlin/jvm/src/org/jetbrains/kotlin/idea/scratch/actions/RunScratchAction.kt b/plugins/kotlin/jvm/src/org/jetbrains/kotlin/idea/scratch/actions/RunScratchAction.kt index 952489164ef9..06e805723880 100644 --- a/plugins/kotlin/jvm/src/org/jetbrains/kotlin/idea/scratch/actions/RunScratchAction.kt +++ b/plugins/kotlin/jvm/src/org/jetbrains/kotlin/idea/scratch/actions/RunScratchAction.kt @@ -1,4 +1,4 @@ -// 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. +// 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.scratch.actions @@ -8,6 +8,7 @@ import com.intellij.openapi.keymap.KeymapManager import com.intellij.openapi.keymap.KeymapUtil import com.intellij.openapi.project.DumbService import com.intellij.task.ProjectTaskManager +import com.intellij.task.impl.ProjectTaskManagerImpl import org.jetbrains.kotlin.idea.KotlinJvmBundle import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager import org.jetbrains.kotlin.idea.core.script.configuration.CompositeScriptConfigurationManager @@ -64,6 +65,7 @@ class RunScratchAction : ScratchAction( log.printDebugMessage("Run Action: module = ${module?.name}") if (!isAutoRun && module != null && isMakeBeforeRun) { + ProjectTaskManagerImpl.putBuildOriginator(project, this.javaClass) ProjectTaskManager.getInstance(project).build(module).onSuccess { executionResult -> if (executionResult.isAborted || executionResult.hasErrors()) { executor.errorOccurs(KotlinJvmBundle.message("there.were.compilation.errors.in.module.0", module.name)) diff --git a/plugins/kotlin/kotlin.performanceExtendedPlugin/src/com/intellij/performance/performancePlugin/commands/CreateKotlinFileCommand.kt b/plugins/kotlin/kotlin.performanceExtendedPlugin/src/com/intellij/performance/performancePlugin/commands/CreateKotlinFileCommand.kt index 8bd46b15bab6..90993cfc7a2d 100644 --- a/plugins/kotlin/kotlin.performanceExtendedPlugin/src/com/intellij/performance/performancePlugin/commands/CreateKotlinFileCommand.kt +++ b/plugins/kotlin/kotlin.performanceExtendedPlugin/src/com/intellij/performance/performancePlugin/commands/CreateKotlinFileCommand.kt @@ -7,7 +7,7 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.project.guessProjectDir import com.intellij.openapi.ui.playback.PlaybackContext -import com.intellij.openapi.vfs.findFileOrDirectory +import com.intellij.openapi.vfs.findDirectory import com.intellij.platform.diagnostic.telemetry.helpers.useWithScope import com.intellij.psi.impl.PsiManagerImpl import com.intellij.psi.impl.file.PsiDirectoryImpl @@ -43,8 +43,8 @@ class CreateKotlinFileCommand(text: String, line: Int) : PerformanceCommandCorou val (fileName, filePath, fileType) = extractCommandArgument(PREFIX).replace("\\s","").split(",") val directory = PsiDirectoryImpl( PsiManagerImpl(context.project), - (context.project.guessProjectDir() ?: throw RuntimeException("'guessProjectDir' dir returned 'null'")) - .findFileOrDirectory(filePath) ?: throw RuntimeException("Can't find file $filePath") + (context.project.guessProjectDir() ?: throw RuntimeException("Root of the project was not found ")) + .findDirectory(filePath) ?: throw RuntimeException("Can't find file $filePath") ) val templateName = POSSIBLE_FILE_TYPES[fileType.lowercase()] @@ -58,7 +58,9 @@ class CreateKotlinFileCommand(text: String, line: Int) : PerformanceCommandCorou PerformanceTestSpan.TRACER.spanBuilder(NAME).useWithScope { val createdFile = CreateFileFromTemplateAction .createFileFromTemplate(fileName, template, directory, null, true) - createdFile?.let { LOG.info("Created kotlin file\n${createdFile.text}") } + createdFile?.let { + LOG.info("Created kotlin file\n${createdFile.text}") + } } })) diff --git a/plugins/kotlin/ml-completion/kotlin.ml-completion.iml b/plugins/kotlin/ml-completion/kotlin.ml-completion.iml index 4d27eeb519a1..6d249332b34f 100644 --- a/plugins/kotlin/ml-completion/kotlin.ml-completion.iml +++ b/plugins/kotlin/ml-completion/kotlin.ml-completion.iml @@ -19,7 +19,13 @@ - + + + + d410d83df200f3b9df5992c2653bbe2bff528a9bc9463cc4cacc644b5274029a + + + diff --git a/plugins/kotlin/plugin/common/resources/META-INF/refactorings.xml b/plugins/kotlin/plugin/common/resources/META-INF/refactorings.xml index bcc4069e2535..51f2ec4cf4ba 100644 --- a/plugins/kotlin/plugin/common/resources/META-INF/refactorings.xml +++ b/plugins/kotlin/plugin/common/resources/META-INF/refactorings.xml @@ -53,5 +53,10 @@ + + + + + \ No newline at end of file diff --git a/plugins/kotlin/plugin/common/resources/META-INF/scripting-base.xml b/plugins/kotlin/plugin/common/resources/META-INF/scripting-base.xml index 7a67b9ba4624..1d7c3a6d181f 100644 --- a/plugins/kotlin/plugin/common/resources/META-INF/scripting-base.xml +++ b/plugins/kotlin/plugin/common/resources/META-INF/scripting-base.xml @@ -113,9 +113,10 @@ restartRequired="true"/> diff --git a/plugins/kotlin/plugin/k1/resources/META-INF/refactorings-fe10.xml b/plugins/kotlin/plugin/k1/resources/META-INF/refactorings-fe10.xml index 12307d105494..922e1c149a2c 100644 --- a/plugins/kotlin/plugin/k1/resources/META-INF/refactorings-fe10.xml +++ b/plugins/kotlin/plugin/k1/resources/META-INF/refactorings-fe10.xml @@ -151,14 +151,10 @@ - - - - diff --git a/plugins/kotlin/project-configuration/kotlin.project-configuration.iml b/plugins/kotlin/project-configuration/kotlin.project-configuration.iml index 39723fa8ca5a..bdce6644f29c 100644 --- a/plugins/kotlin/project-configuration/kotlin.project-configuration.iml +++ b/plugins/kotlin/project-configuration/kotlin.project-configuration.iml @@ -36,6 +36,5 @@ - \ No newline at end of file diff --git a/plugins/kotlin/project-configuration/resources/messages/KotlinProjectConfigurationBundle.properties b/plugins/kotlin/project-configuration/resources/messages/KotlinProjectConfigurationBundle.properties index da7974d5e0df..bd1c53ade43b 100644 --- a/plugins/kotlin/project-configuration/resources/messages/KotlinProjectConfigurationBundle.properties +++ b/plugins/kotlin/project-configuration/resources/messages/KotlinProjectConfigurationBundle.properties @@ -52,9 +52,13 @@ configure.kotlin.find.maven.versions=Find Kotlin Maven plugin versions configure.kotlin.loading=loading\u2026 configure.kotlin.cant.load.versions=Couldn't load versions list from search.maven.org -configure.kotlin.modules.fix.version.manually=With the chosen version of Kotlin, you will probably have to fix versions in other modules manually:\n -configure.kotlin.version.and.modules={0} in {1}\n +configure.kotlin.root.contains.another.kotlin=Your top level build script contains Kotlin {0}.
+configure.kotlin.root.should.contain.same.version=The top level and modules' build scripts should contain the same version.
+configure.kotlin.currently.there.are.versions=Currently, there are versions:
+configure.kotlin.version.and.modules={0} in {1}
configure.kotlin.version.and.modules.and.more=, and in {0} more. +configure.kotlin.choose.another.kotlin.version=
You can choose another Kotlin version or correct versions manually after the conversion.
+configure.kotlin.choose.the.same.kotlin.version=
Use the {0} Kotlin version or correct versions manually after the conversion.
kotlin.compiler.and.runtime.version=Kotlin compiler and runtime version: diff --git a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInProjectUtils.kt b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInProjectUtils.kt index b66c73b0a43d..1d93e0dfda63 100644 --- a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInProjectUtils.kt +++ b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInProjectUtils.kt @@ -7,11 +7,14 @@ import com.intellij.openapi.application.ReadAction import com.intellij.openapi.application.runReadAction import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.extensions.Extensions +import com.intellij.openapi.externalSystem.model.ProjectSystemId import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project +import com.intellij.openapi.project.guessProjectDir import com.intellij.openapi.project.modules import com.intellij.openapi.roots.DependencyScope import com.intellij.openapi.roots.LibraryOrderEntry @@ -20,12 +23,16 @@ import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.roots.impl.libraries.LibraryEx import com.intellij.openapi.roots.libraries.PersistentLibraryKind import com.intellij.openapi.util.ThrowableComputable +import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiManager import com.intellij.psi.search.DelegatingGlobalSearchScope import com.intellij.psi.search.FileTypeIndex import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.concurrency.annotations.RequiresBackgroundThread import com.intellij.util.indexing.DumbModeAccessType +import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider @@ -58,7 +65,9 @@ import org.jetbrains.kotlin.platform.isJs import org.jetbrains.kotlin.platform.isWasm import org.jetbrains.kotlin.platform.jvm.isJvm import org.jetbrains.kotlin.platform.konan.isNative -import org.jetbrains.plugins.gradle.util.GradleUtil +import java.nio.file.Path +import kotlin.io.path.Path +import kotlin.io.path.exists private val LOG = Logger.getInstance("#org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtils") @@ -440,9 +449,11 @@ typealias KotlinVersionsAndModules = Map { val configuredModules = getConfiguredModules(project, configurator) val kotlinVersionsAndModules: MutableMap> = mutableMapOf() + val rootModule = getRootModule(project) + var rootModuleVersion: String? = null for (moduleEntity in configuredModules) { val module = moduleEntity.value getKotlinCompilerArguments(module)?.pluginClasspaths?.let { pluginsClasspaths -> @@ -452,11 +463,40 @@ fun getKotlinVersionsAndModules( val modulesForThisVersion = kotlinVersionsAndModules.getOrDefault(version, mutableMapOf()) modulesForThisVersion[moduleEntity.key] = module kotlinVersionsAndModules[version] = modulesForThisVersion + + rootModule?.let { + if (rootModule.name == moduleEntity.key) { + rootModuleVersion = version + } + } } } } } - return kotlinVersionsAndModules + return Pair(kotlinVersionsAndModules, rootModuleVersion) +} + +fun getRootModule(project: Project): Module? { + val topLevelBuildScript = project.getTopLevelBuildScriptFile() + return topLevelBuildScript?.let { ModuleUtilCore.findModuleForPsiElement(it) } +} + +@NonNls +private const val DEFAULT_SCRIPT_NAME = "build.gradle" + +@NonNls +private const val KOTLIN_BUILD_SCRIPT_NAME = "build.gradle.kts" + +private fun Project.getTopLevelBuildScriptFile(): PsiFile? { + val projectDir = this.guessProjectDir() ?: return null + val filePath = listOf(DEFAULT_SCRIPT_NAME, KOTLIN_BUILD_SCRIPT_NAME).asSequence() + .map { Path("${projectDir.path}/$it") } + .firstOrNull(Path::exists) + return filePath?.let { path -> + VfsUtil.findFile(path, true)?.let { + PsiManager.getInstance(this).findFile(it) + } + } } typealias ModuleName = String @@ -486,7 +526,9 @@ fun getTargetBytecodeVersionFromModule( module: Module, kotlinVersion: IdeKotlinVersion ): String? { - return GradleUtil.findGradleModuleData(module)?.let { moduleDataNode -> + val projectPath = ExternalSystemApiUtil.getExternalProjectPath(module) ?: return null + val project = module.project + return ExternalSystemApiUtil.findModuleNode(project, ProjectSystemId("GRADLE"), projectPath)?.let { moduleDataNode -> val javaModuleData = ExternalSystemApiUtil.find(moduleDataNode, JavaModuleData.KEY) javaModuleData?.let { javaModuleData.data.targetBytecodeVersion diff --git a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/configuration/ui/CreateLibraryDialogWithModules.java b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/configuration/ui/CreateLibraryDialogWithModules.java index 373e4078d4c3..7ad5ab6f92e0 100644 --- a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/configuration/ui/CreateLibraryDialogWithModules.java +++ b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/configuration/ui/CreateLibraryDialogWithModules.java @@ -9,12 +9,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator; import org.jetbrains.kotlin.idea.framework.ui.ChooseModulePanel; +import org.jetbrains.kotlin.idea.framework.ui.ModulesChangedObserver; import javax.swing.*; import java.util.Collection; import java.util.List; -public class CreateLibraryDialogWithModules extends DialogWrapper { +public class CreateLibraryDialogWithModules extends DialogWrapper implements ModulesChangedObserver { private final ChooseModulePanel chooseModulePanel; public CreateLibraryDialogWithModules( @@ -37,4 +38,7 @@ public class CreateLibraryDialogWithModules extends DialogWrapper { protected @Nullable JComponent createCenterPanel() { return chooseModulePanel.getContentPane(); } + + @Override + public void onModulesChangedNotified() {} } \ No newline at end of file diff --git a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ChooseModulePanel.java b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ChooseModulePanel.java index c58f73613bea..80acdebe05f7 100644 --- a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ChooseModulePanel.java +++ b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ChooseModulePanel.java @@ -62,15 +62,6 @@ public class ChooseModulePanel { } singleModuleComboBox.setModel(comboBoxModel); - ActionListener listener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - updateComponents(); - } - }; - singleModuleRadioButton.addActionListener(listener); - allModulesWithKtRadioButton.addActionListener(listener); - allModulesRadioButton.addActionListener(listener); if (modulesWithKtFiles.size() > 2) { String firstName = modulesWithKtFiles.get(0).getName(); @@ -110,6 +101,27 @@ public class ChooseModulePanel { updateComponents(); } + public void setActionListeners(ModulesChangedObserver modulesChangedObserver) { + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateComponents(); + modulesChangedObserver.onModulesChangedNotified(); + } + }; + singleModuleRadioButton.addActionListener(listener); + allModulesWithKtRadioButton.addActionListener(listener); + allModulesRadioButton.addActionListener(listener); + + ActionListener singleModulesListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + modulesChangedObserver.onModulesChangedNotified(); + } + }; + singleModuleComboBox.addActionListener(singleModulesListener); + } + public JComponent getContentPane() { return contentPane; } @@ -128,7 +140,7 @@ public class ChooseModulePanel { return Collections.singletonList(ModuleManager.getInstance(project).findModuleByName(selectedItem)); } - public List getModules() { + public @NotNull List getModules() { return modules; } } diff --git a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ConfigureDialogWithModulesAndVersion.form b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ConfigureDialogWithModulesAndVersion.form index 02e31a22f1a7..0c4cd9f1b744 100644 --- a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ConfigureDialogWithModulesAndVersion.form +++ b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ConfigureDialogWithModulesAndVersion.form @@ -6,7 +6,7 @@ - + diff --git a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ConfigureDialogWithModulesAndVersion.java b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ConfigureDialogWithModulesAndVersion.java index 34ebc71387e3..a3d9a79cc85b 100644 --- a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ConfigureDialogWithModulesAndVersion.java +++ b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ConfigureDialogWithModulesAndVersion.java @@ -20,7 +20,6 @@ import com.intellij.util.net.HttpConfigurable; import com.intellij.util.text.VersionComparatorUtil; import com.intellij.util.ui.AsyncProcessIcon; import com.intellij.util.ui.UIUtil; -import kotlin.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.compiler.configuration.IdeKotlinVersion; @@ -29,7 +28,6 @@ import org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator; import org.jetbrains.kotlin.idea.projectConfiguration.KotlinProjectConfigurationBundle; import org.jetbrains.kotlin.idea.projectConfiguration.RepositoryDescription; import org.jetbrains.kotlin.idea.statistics.KotlinJ2KOnboardingFUSCollector; -import org.jetbrains.kotlin.tools.projectWizard.Versions; import javax.swing.*; import java.awt.*; @@ -44,13 +42,19 @@ import java.util.stream.Collectors; import static org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtilsKt.*; -public class ConfigureDialogWithModulesAndVersion extends DialogWrapper { +public class ConfigureDialogWithModulesAndVersion extends DialogWrapper implements ModulesChangedObserver { private static final String VERSIONS_LIST_URL = "https://search.maven.org/solrsearch/select?q=g:%22org.jetbrains.kotlin%22+AND+a:%22kotlin-stdlib%22&core=gav&rows=20&wt=json"; + /* We define the version here because we cannot properly use such a constant from org.jetbrains.kotlin.tools.projectWizard Versions + because the current package is not a plugin and there are dependency issues if trying to make it a plugin */ + private static final String DEFAULT_KOTLIN_VERSION = "1.8.21"; + @NotNull private final String minimumVersion; private final Map> kotlinVersionsAndModules; + @Nullable private final String rootNoduleVersion; + @Nullable private final Module rootModule; private final Map> jvmModulesTargetingUnsupportedJvm; private final Map modulesAndJvmTargets; @@ -76,7 +80,9 @@ public class ConfigureDialogWithModulesAndVersion extends DialogWrapper { KotlinJ2KOnboardingFUSCollector.Companion.logShowConfigureKtWindow(project); - kotlinVersionsAndModules = getKotlinVersionsAndModules(project, configurator); + var kotlinVersions = getKotlinVersionsAndModules(project, configurator); + kotlinVersionsAndModules = kotlinVersions.getFirst(); + rootNoduleVersion = kotlinVersions.getSecond(); setTitle(KotlinProjectConfigurationBundle.message("configure.kotlin.title", configurator.getPresentableText())); @@ -103,60 +109,94 @@ public class ConfigureDialogWithModulesAndVersion extends DialogWrapper { chooseModulePanel = new ChooseModulePanel(project, configurator, excludeModules); chooseModulesPanelPlace.add(chooseModulePanel.getContentPane(), BorderLayout.CENTER); - Pair>, Map> pair = + var jvmTargets = getModulesTargetingUnsupportedJvmAndTargetsForAllModules(chooseModulePanel.getModules(), - IdeKotlinVersion.get(Versions.INSTANCE.getKOTLIN().toString())); - jvmModulesTargetingUnsupportedJvm = pair.getFirst(); - modulesAndJvmTargets = pair.getSecond(); + IdeKotlinVersion.get(DEFAULT_KOTLIN_VERSION)); + jvmModulesTargetingUnsupportedJvm = jvmTargets.getFirst(); + modulesAndJvmTargets = jvmTargets.getSecond(); + + rootModule = getRootModule(project); + + chooseModulePanel.setActionListeners(this); kotlinVersionComboBox.addItemListener(e -> showWarningIfThereAreDifferentKotlinVersions()); showUnsupportedJvmTargetWarning(); updateComponents(); } + @Override + public void onModulesChangedNotified() { + showWarningIfThereAreDifferentKotlinVersions(); + } + private static final int MODULES_TO_DISPLAY_SIZE = 2; private static final String DELIMITER = ", "; private void showWarningIfThereAreDifferentKotlinVersions() { String currentSelectedKotlinVersion = getKotlinVersion(); - if (!kotlinVersionsAndModules.isEmpty() && - !(kotlinVersionsAndModules.size() == 1 && kotlinVersionsAndModules.containsKey(currentSelectedKotlinVersion))) { + List modulesToConfigure = chooseModulePanel.getModulesToConfigure(); + if (!kotlinVersionsAndModules.isEmpty() && currentSelectedKotlinVersion != null && !modulesToConfigure.isEmpty()) { listOfKotlinVersionsAndModules.setText(""); - final StringBuilder message = new StringBuilder(); - message.append(KotlinProjectConfigurationBundle.message("configure.kotlin.modules.fix.version.manually")); - kotlinVersionsAndModules.keySet().stream().filter(it -> !it.equals(currentSelectedKotlinVersion)).sorted() - .forEach(it -> { - Map modules = kotlinVersionsAndModules.get(it); - Set modulesNames = modules.keySet(); - StringBuilder modulesEnumeration = new StringBuilder(); - if (modulesNames.size() > MODULES_TO_DISPLAY_SIZE) { - modulesEnumeration.append( - modulesNames.stream().limit(MODULES_TO_DISPLAY_SIZE).sorted() - .collect(Collectors.joining(DELIMITER))); - modulesEnumeration.append( - KotlinProjectConfigurationBundle.message("configure.kotlin.version.and.modules.and.more", - modulesNames.size() - - MODULES_TO_DISPLAY_SIZE)); - } else { - modulesEnumeration.append(modulesNames.stream().sorted().collect(Collectors.joining(DELIMITER))); - } - message.append(KotlinProjectConfigurationBundle - .message("configure.kotlin.version.and.modules", it, - modulesEnumeration.toString())); - } - ); - // It's not hardcoded, we take strings from resources - //noinspection HardCodedStringLiteral - listOfKotlinVersionsAndModules.setText(message.toString()); - listOfKotlinVersionsAndModules.setVisible(true); + + if (modulesToConfigure.contains(rootModule) && + !(kotlinVersionsAndModules.size() == 1 && kotlinVersionsAndModules.containsKey(currentSelectedKotlinVersion))) { + createMessageAboutDifferentKotlinVersions(currentSelectedKotlinVersion); + } else if (rootNoduleVersion != null && + !IdeKotlinVersion.get(rootNoduleVersion).equals(IdeKotlinVersion.get(currentSelectedKotlinVersion))) { + createMessageThatTopLevelAndModulesShouldHaveSameVersion(); + } else { + listOfKotlinVersionsAndModules.setVisible(false); + } } else { listOfKotlinVersionsAndModules.setVisible(false); } } + private void createMessageThatTopLevelAndModulesShouldHaveSameVersion() { + String message = KotlinProjectConfigurationBundle.message("configure.kotlin.root.contains.another.kotlin", rootNoduleVersion) + + KotlinProjectConfigurationBundle.message("configure.kotlin.root.should.contain.same.version") + + KotlinProjectConfigurationBundle.message("configure.kotlin.choose.the.same.kotlin.version", rootNoduleVersion); + Messages.installHyperlinkSupport(listOfKotlinVersionsAndModules); + listOfKotlinVersionsAndModules.setText(message); + listOfKotlinVersionsAndModules.setVisible(true); + } + + private void createMessageAboutDifferentKotlinVersions(String currentSelectedKotlinVersion) { + final StringBuilder message = new StringBuilder(); + message.append(KotlinProjectConfigurationBundle.message("configure.kotlin.root.should.contain.same.version")); + message.append(KotlinProjectConfigurationBundle.message("configure.kotlin.currently.there.are.versions")); + + kotlinVersionsAndModules.keySet().stream().filter(it -> !it.equals(currentSelectedKotlinVersion)).sorted() + .forEach(it -> { + Map modules = kotlinVersionsAndModules.get(it); + Set modulesNames = modules.keySet(); + StringBuilder modulesEnumeration = new StringBuilder(); + if (modulesNames.size() > MODULES_TO_DISPLAY_SIZE) { + modulesEnumeration.append( + modulesNames.stream().limit(MODULES_TO_DISPLAY_SIZE).sorted() + .collect(Collectors.joining(DELIMITER))); + modulesEnumeration.append( + KotlinProjectConfigurationBundle.message("configure.kotlin.version.and.modules.and.more", + modulesNames.size() - + MODULES_TO_DISPLAY_SIZE)); + } else { + modulesEnumeration.append(modulesNames.stream().sorted().collect(Collectors.joining(DELIMITER))); + } + message.append(KotlinProjectConfigurationBundle + .message("configure.kotlin.version.and.modules", it, + modulesEnumeration.toString())); + } + ); + + message.append(KotlinProjectConfigurationBundle.message("configure.kotlin.choose.another.kotlin.version")); + Messages.installHyperlinkSupport(listOfKotlinVersionsAndModules); + // It's not hardcoded, we take strings from resources + //noinspection HardCodedStringLiteral + listOfKotlinVersionsAndModules.setText(message.toString()); + listOfKotlinVersionsAndModules.setVisible(true); + } + private void showUnsupportedJvmTargetWarning() { - //warningsSplitter.setEnabled(true); - //warningsSplitter.setVisible(true); if (!jvmModulesTargetingUnsupportedJvm.isEmpty()) { final StringBuilder message = new StringBuilder(); message.append(KotlinProjectConfigurationBundle.message("configurator.kotlin.jvm.targets.unsupported", "1.8")); diff --git a/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ModulesChangedObserver.java b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ModulesChangedObserver.java new file mode 100644 index 000000000000..6e44cfce5e7d --- /dev/null +++ b/plugins/kotlin/project-configuration/src/org/jetbrains/kotlin/idea/framework/ui/ModulesChangedObserver.java @@ -0,0 +1,7 @@ +// 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.framework.ui; + +public interface ModulesChangedObserver { + + void onModulesChangedNotified(); +} diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/kotlin.refactorings.common.iml b/plugins/kotlin/refactorings/kotlin.refactorings.common/kotlin.refactorings.common.iml index 838d0a045a1e..c8669bb14b17 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.common/kotlin.refactorings.common.iml +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/kotlin.refactorings.common.iml @@ -1,5 +1,21 @@ + + + + + + + + + + + + + + + @@ -27,5 +43,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KotlinRenameRefactoringSupport.kt b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KotlinRenameRefactoringSupport.kt index 152a69a8b976..e0d98a773643 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KotlinRenameRefactoringSupport.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KotlinRenameRefactoringSupport.kt @@ -54,7 +54,10 @@ interface KotlinRenameRefactoringSupport { fun getAllOverridenFunctions(function: KtNamedFunction): List - fun getModuleNameSuffixForMangledName(mangledName: String): String? + fun getModuleNameSuffixForMangledName(mangledName: String): String? { + val indexOfDollar = mangledName.indexOf('$') + return if (indexOfDollar >= 0) mangledName.substring(indexOfDollar + 1) else null + } fun mangleInternalName(name: String, moduleName: String): String diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/AbstractForbidRenamingSymbolByReferenceHandler.kt b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/AbstractForbidRenamingSymbolByReferenceHandler.kt new file mode 100644 index 000000000000..80876d1a8e2b --- /dev/null +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/AbstractForbidRenamingSymbolByReferenceHandler.kt @@ -0,0 +1,59 @@ +// 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.refactoring.rename.handlers + +import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.NlsContexts.DialogMessage +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.refactoring.RefactoringBundle +import com.intellij.refactoring.rename.RenameHandler +import com.intellij.refactoring.util.CommonRefactoringUtil +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.lifetime.allowAnalysisOnEdt +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin +import org.jetbrains.kotlin.idea.base.resources.KotlinBundle +import org.jetbrains.kotlin.idea.refactoring.rename.findElementForRename +import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.psi.KtSimpleNameExpression + +internal abstract class AbstractForbidRenamingSymbolByReferenceHandler : RenameHandler { + override fun isAvailableOnDataContext(dataContext: DataContext): Boolean { + val file = CommonDataKeys.PSI_FILE.getData(dataContext) ?: return false + val editor = CommonDataKeys.EDITOR.getData(dataContext) ?: return false + val refExpression = file.findElementForRename(editor.caretModel.offset) ?: return false + @OptIn(KtAllowAnalysisOnEdt::class) + allowAnalysisOnEdt { + analyze(refExpression) { + val target = refExpression.mainReference.resolveToSymbol() ?: return false + return shouldForbidRenaming(target) + } + } + } + + context(KtAnalysisSession) + abstract fun shouldForbidRenaming(symbol: KtSymbol): Boolean + + abstract fun getErrorMessage(): @DialogMessage String + + override fun isRenaming(dataContext: DataContext) = isAvailableOnDataContext(dataContext) + + override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + getErrorMessage(), + RefactoringBundle.message("rename.title"), + null + ) + } + + override fun invoke(project: Project, elements: Array, dataContext: DataContext?) { + // Do nothing: this method is not called from editor + } +} diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameBackingFieldReferenceHandler.kt b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameBackingFieldReferenceHandler.kt new file mode 100644 index 000000000000..f3be22191316 --- /dev/null +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameBackingFieldReferenceHandler.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.refactoring.rename.handlers + +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.refactoring.RefactoringBundle +import com.intellij.refactoring.util.CommonRefactoringUtil +import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt +import org.jetbrains.kotlin.analysis.api.analyze +import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt +import org.jetbrains.kotlin.analysis.api.symbols.KtBackingFieldSymbol +import org.jetbrains.kotlin.idea.base.resources.KotlinBundle +import org.jetbrains.kotlin.idea.refactoring.rename.KotlinVariableInplaceRenameHandler +import org.jetbrains.kotlin.idea.refactoring.rename.findElementForRename +import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.psi.KtSimpleNameExpression + +class RenameBackingFieldReferenceHandler : KotlinVariableInplaceRenameHandler() { + override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean { + val refExpression = file.findElementForRename(editor.caretModel.offset) ?: return false + if (refExpression.text != "field") return false + @OptIn(KtAllowAnalysisOnEdt::class) + allowAnalysisOnEdt { + analyze(refExpression) { + val target = refExpression.mainReference.resolveToSymbol() ?: return false + return target is KtBackingFieldSymbol + } + } + } + + override fun invoke(project: Project, editor: Editor?, file: PsiFile?, dataContext: DataContext) { + editor?.let { + CommonRefactoringUtil.showErrorHint( + project, + editor, + KotlinBundle.message("text.rename.not.applicable.to.backing.field.reference"), + RefactoringBundle.message("rename.title"), + null + ) + } + } + + override fun invoke(project: Project, elements: Array, dataContext: DataContext) { + // Do nothing: this method is called not from editor + } +} diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameCompilerPluginDeclarationByReferenceHandler.kt b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameCompilerPluginDeclarationByReferenceHandler.kt new file mode 100644 index 000000000000..b6a990095fed --- /dev/null +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameCompilerPluginDeclarationByReferenceHandler.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.refactoring.rename.handlers + +import com.intellij.openapi.util.NlsContexts.DialogMessage +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin +import org.jetbrains.kotlin.idea.base.resources.KotlinBundle + +internal class RenameCompilerPluginDeclarationByReferenceHandler : AbstractForbidRenamingSymbolByReferenceHandler() { + context(KtAnalysisSession) + override fun shouldForbidRenaming(symbol: KtSymbol): Boolean { + return symbol.origin == KtSymbolOrigin.PLUGIN + } + + override fun getErrorMessage(): @DialogMessage String { + return KotlinBundle.message("text.rename.is.not.applicable.to.compiler.plugin.generated.declarations") + } +} diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameKotlinImplicitLambdaParameter.kt b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameKotlinImplicitLambdaParameter.kt new file mode 100644 index 000000000000..385395350b57 --- /dev/null +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameKotlinImplicitLambdaParameter.kt @@ -0,0 +1,76 @@ +// 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.rename.handlers + +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.application.runWriteAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt +import org.jetbrains.kotlin.analysis.api.analyze +import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt +import org.jetbrains.kotlin.analysis.api.symbols.KtAnonymousFunctionSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.idea.base.resources.KotlinBundle +import org.jetbrains.kotlin.idea.codeinsight.utils.getFunctionLiteralByImplicitLambdaParameter +import org.jetbrains.kotlin.idea.codeinsight.utils.isReferenceToImplicitLambdaParameter +import org.jetbrains.kotlin.idea.refactoring.rename.KotlinVariableInplaceRenameHandler +import org.jetbrains.kotlin.idea.refactoring.rename.findElementForRename +import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.psi.* + +class RenameKotlinImplicitLambdaParameter : KotlinVariableInplaceRenameHandler() { + @OptIn(KtAllowAnalysisOnEdt::class) + override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean { + val nameExpression = findElementToRename(file, editor) + return nameExpression != null && nameExpression.isReferenceToImplicitLambdaParameter() + } + + override fun invoke(project: Project, editor: Editor?, file: PsiFile?, dataContext: DataContext) { + if (editor == null || file == null) return + val itExpression = findElementToRename(file, editor) ?: return + val explicitItParameter = project.executeWriteCommand( + KotlinBundle.message("text.convert._it_.to.explicit.lambda.parameter"), + groupId = null, + command = { itExpression.createExplicitLambdaParameterByImplicitOne(editor) }, + ) ?: return + + doRename(explicitItParameter, editor, dataContext) + } + + private fun findElementToRename( + file: PsiFile, + editor: Editor, + ) = file.findElementForRename(editor.caretModel.offset) + + override fun invoke(project: Project, elements: Array, dataContext: DataContext) { + // Do nothing: this method is called not from editor + } +} + + +private fun KtNameReferenceExpression.createExplicitLambdaParameterByImplicitOne(editor: Editor): KtParameter? { + if (getReferencedNameAsName() != StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME) return null + val functionLiteral = getFunctionLiteralByImplicitLambdaParameter() ?: return null + + val project = project + + val newExpr = KtPsiFactory(project).createExpression("{ it -> }") as KtLambdaExpression + val arrow = newExpr.functionLiteral.arrow ?: return null + runWriteAction { + functionLiteral.addRangeAfter( + newExpr.functionLiteral.valueParameterList, + arrow, + functionLiteral.lBrace, + ) + } + + PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document) + + return functionLiteral.valueParameters.singleOrNull() +} \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameOnSecondaryConstructorHandler.kt b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameOnSecondaryConstructorHandler.kt new file mode 100644 index 000000000000..0500263a56fa --- /dev/null +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameOnSecondaryConstructorHandler.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.refactoring.rename.handlers + + +import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.refactoring.RefactoringBundle +import com.intellij.refactoring.rename.RenameHandler +import com.intellij.refactoring.util.CommonRefactoringUtil +import org.jetbrains.kotlin.idea.base.resources.KotlinBundle +import org.jetbrains.kotlin.psi.* + + +class RenameOnSecondaryConstructorHandler : RenameHandler { + override fun isAvailableOnDataContext(dataContext: DataContext): Boolean { + val editor = CommonDataKeys.EDITOR.getData(dataContext) ?: return false + val file = CommonDataKeys.PSI_FILE.getData(dataContext) ?: return false + + val element = PsiTreeUtil.findElementOfClassAtOffsetWithStopSet( + file, + editor.caretModel.offset, + KtSecondaryConstructor::class.java, + /* strictStart = */ false, + KtBlockExpression::class.java, + KtValueArgumentList::class.java, + KtParameterList::class.java, + KtConstructorDelegationCall::class.java + ) + return element != null + } + + override fun isRenaming(dataContext: DataContext): Boolean = isAvailableOnDataContext(dataContext) + + override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + KotlinBundle.message("text.rename.is.not.applicable.to.secondary.constructors"), + RefactoringBundle.message("rename.title"), + null + ) + } + + override fun invoke(project: Project, elements: Array, dataContext: DataContext?) { + // Do nothing: this method is called not from editor + } +} + 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 new file mode 100644 index 000000000000..350df0b8698d --- /dev/null +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/handlers/RenameSyntheticDeclarationByReferenceHandler.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.refactoring.rename.handlers + +import com.intellij.openapi.util.NlsContexts.DialogMessage +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin +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 + } + + override fun getErrorMessage(): @DialogMessage String { + return KotlinBundle.message("text.rename.is.not.applicable.to.synthetic.declarations") + } +} diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/kotlin.refactorings.k2.iml b/plugins/kotlin/refactorings/kotlin.refactorings.k2/kotlin.refactorings.k2.iml index 7068c93db1ad..c9f28120eb6f 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/kotlin.refactorings.k2.iml +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/kotlin.refactorings.k2.iml @@ -22,5 +22,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/resources/kotlin.refactorings.k2.xml b/plugins/kotlin/refactorings/kotlin.refactorings.k2/resources/kotlin.refactorings.k2.xml index 54d4c0bc28b2..8f641b647b45 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/resources/kotlin.refactorings.k2.xml +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/resources/kotlin.refactorings.k2.xml @@ -9,6 +9,8 @@ serviceInterface="org.jetbrains.kotlin.idea.refactoring.KotlinCommonRefactoringSettings"/> + anchorElement.replaceWith(fqName) + is KtSimpleNameExpression -> anchorElement.replaceWith(fqName) + is KtDotQualifiedExpression -> anchorElement.replaceWith(fqName) + else -> return expression + } ?: return expression + + + val unusedImportsAfterChange = analyze(containingFile) { + analyseImports(containingFile) + }.unusedImports + val importsToRemove = unusedImportsAfterChange - unusedImportsBeforeChange + importsToRemove.forEach { + it.delete() + } + + val newShortenings = analyze(newElement) { collectPossibleReferenceShorteningsInElement(newElement) } + return newShortenings.invokeShortening().firstOrNull() ?: newElement + } + + private fun KtTypeReference.replaceWith(fqName: FqName): KtTypeReference { + val newReference = KtPsiFactory(project).createType(fqName.asString()) + return replaced(newReference) + } + + 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 KtCallElement -> { + val newName = psiFactory.createSimpleName(fqName.shortName().asString()) + selectorExpression.calleeExpression?.replace(newName) + val packageName = fqName.pathSegments().apply { removeLast() }.joinToString(".") { it.asString() } + psiFactory.createExpression("$packageName.${(selectorExpression as KtCallElement).text}") + } + else -> return null + } + return replaced(newExpression) + } + + private fun KtSimpleNameExpression.topMostQualified() = generateSequence(this) { elem -> + val parent = elem.parent + if (parent is KtDotQualifiedExpression) parent else null + }.lastOrNull() ?: this + + override fun SyntheticPropertyAccessorReference.renameTo(newElementName: String): KtElement? { + operationNotSupportedInK2Error() + } + + override fun KtDefaultAnnotationArgumentReference.renameTo(newElementName: String): KtValueArgument { + operationNotSupportedInK2Error() + } + + override fun replaceWithImplicitInvokeInvocation(newExpression: KtDotQualifiedExpression): KtExpression? = + OperatorToFunctionConverter.replaceExplicitInvokeCallWithImplicit(newExpression) + + private fun operationNotSupportedInK2Error(): Nothing { + throw IncorrectOperationException("K2 plugin does not yet support this operation") + } +} \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/memberInfo/K2MemberInfoSupport.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/memberInfo/K2MemberInfoSupport.kt index 96329202342e..739de81600d3 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/memberInfo/K2MemberInfoSupport.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/memberInfo/K2MemberInfoSupport.kt @@ -2,7 +2,7 @@ package org.jetbrains.kotlin.idea.k2.refactoring.memberInfo import org.jetbrains.kotlin.analysis.api.analyze -import org.jetbrains.kotlin.analysis.api.renderer.base.KtKeywordRenderer +import org.jetbrains.kotlin.analysis.api.renderer.base.KtKeywordsRenderer import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KtRendererAnnotationsFilter import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KtDeclarationRendererForSource import org.jetbrains.kotlin.analysis.api.renderer.declarations.renderers.callables.KtPropertyAccessorsRenderer @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.psi.KtNamedDeclaration class K2MemberInfoSupport : KotlinMemberInfoSupport { private val renderer = KtDeclarationRendererForSource.WITH_SHORT_NAMES.with { annotationRenderer = annotationRenderer.with { - keywordRender = KtKeywordRenderer.NONE + keywordsRenderer = KtKeywordsRenderer.NONE annotationFilter = KtRendererAnnotationsFilter.NONE superTypesFilter = KtSuperTypesFilter.NONE propertyAccessorsRenderer = KtPropertyAccessorsRenderer.NONE diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.move.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/move/K2MoveDescriptor.kt b/plugins/kotlin/refactorings/kotlin.refactorings.move.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/move/K2MoveDescriptor.kt index 99098c017ad5..038b024a0e34 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.move.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/move/K2MoveDescriptor.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.move.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/move/K2MoveDescriptor.kt @@ -3,10 +3,7 @@ package org.jetbrains.kotlin.idea.k2.refactoring.move import com.intellij.openapi.util.NlsContexts import com.intellij.refactoring.BaseRefactoringProcessor -import com.intellij.ui.dsl.builder.AlignX -import com.intellij.ui.dsl.builder.AlignY -import com.intellij.ui.dsl.builder.Panel -import com.intellij.ui.dsl.builder.bindSelected +import com.intellij.ui.dsl.builder.* import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.refactoring.KotlinCommonRefactoringSettings import javax.swing.JComponent @@ -46,7 +43,7 @@ sealed class K2MoveDescriptor { fun createComboBox() { row { checkBox(text).bindSelected(setting) - } + }.layout(RowLayout.PARENT_GRID) } } @@ -57,10 +54,10 @@ sealed class K2MoveDescriptor { row { panel { settings.firstOrNull()?.forEach { settings -> settings.createComboBox() } - }.align(AlignX.LEFT).align(AlignY.TOP) + }.align(AlignY.TOP + AlignX.LEFT) panel { settings.lastOrNull()?.forEach { settings -> settings.createComboBox() } - }.align(AlignX.RIGHT).align(AlignY.TOP) + }.align(AlignY.TOP + AlignX.RIGHT) } } diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.move.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/move/K2MoveSource.kt b/plugins/kotlin/refactorings/kotlin.refactorings.move.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/move/K2MoveSource.kt index f1610e38d83e..a7fc2f589d94 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.move.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/move/K2MoveSource.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.move.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/move/K2MoveSource.kt @@ -6,11 +6,15 @@ import com.intellij.platform.backend.presentation.TargetPresentation import com.intellij.refactoring.RefactoringBundle import com.intellij.ui.CollectionListModel import com.intellij.ui.components.JBList -import com.intellij.ui.dsl.builder.* +import com.intellij.ui.dsl.builder.Align +import com.intellij.ui.dsl.builder.BottomGap +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.TopGap import com.intellij.ui.list.createTargetPresentationRenderer import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfo import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionPanel import org.jetbrains.kotlin.psi.* +import javax.swing.Icon import javax.swing.JComponent sealed interface K2MoveSource { @@ -25,22 +29,30 @@ sealed interface K2MoveSource { context(Panel) override fun buildPanel(onError: (String?, JComponent) -> Unit) { + val project = elements.firstOrNull()?.project ?: return + + class FileInfo(val icon: Icon?, val file: KtFile) + + val fileInfos = ActionUtil.underModalProgress(project, RefactoringBundle.message("move.title")) { + elements.map { file -> FileInfo(file.getIcon(0), file) } + } + group(RefactoringBundle.message("move.files.group")) { - lateinit var list: JBList + lateinit var list: JBList row { - list = JBList(CollectionListModel(elements)) - list.cellRenderer = createTargetPresentationRenderer { file -> - TargetPresentation.builder(file.name) - .icon(file.getIcon(0)) - .locationText(file.virtualFile.parent.path) + list = JBList(CollectionListModel(fileInfos)) + list.cellRenderer = createTargetPresentationRenderer { fileInfo -> + TargetPresentation.builder(fileInfo.file.name) + .icon(fileInfo.icon) + .locationText(fileInfo.file.virtualFile.parent.path) .presentation() } cell(list).resizableColumn() } onApply { - elements = (list.model as CollectionListModel).items.toSet() + elements = (list.model as CollectionListModel).items.map { it.file }.toSet() } - }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).layout(RowLayout.PARENT_GRID).resizableRow() + }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).resizableRow() } } 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 5bdf093c7c6c..16bdcdd4f37c 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 @@ -12,5 +12,7 @@ + + \ 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 new file mode 100644 index 000000000000..32b6adacd8f0 --- /dev/null +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/AbstractK2BindToElementTest.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.k2.refactoring.safeDelete + +import com.intellij.openapi.command.WriteCommandAction +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiElement +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.util.parentOfType +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.test.InTextDirectivesUtils +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.test.ProjectDescriptorWithStdlibSources +import org.jetbrains.kotlin.psi.KtSimpleNameExpression +import java.nio.file.Path + +abstract class AbstractK2BindToElementTest : KotlinLightCodeInsightFixtureTestCase() { + override fun isFirPlugin() = true + + override fun getProjectDescriptor() = ProjectDescriptorWithStdlibSources.getInstanceWithStdlibSources() + + @OptIn(KtAllowAnalysisOnEdt::class) + protected fun doTest(path: String) { + val file = myFixture.configureByFile(path) + addAllFilesToProject(Path.of(path).parent) + val elem = file.findElementAt(myFixture.caretOffset) ?: error("Couldn't find element at caret") + val nameReference = elem.parentOfType(withSelf = true) + ?: error("Element at caret isn't of type 'KtSimpleNameExpression'") + val bindTarget = findElementToBind()?.unwrapped ?: error("Could not find element to bind") + WriteCommandAction.runWriteCommandAction(myFixture.project) { + allowAnalysisOnEdt { + nameReference.mainReference.bindToElement(bindTarget) + } + } + myFixture.checkResultByFile("${myFixture.file.name}.after") + } + + private fun addAllFilesToProject(rootDir: Path) { + rootDir.toFile().listFiles()?.forEach { + if (it.isDirectory) myFixture.copyDirectoryToProject(it.name, it.name) + } + PsiDocumentManager.getInstance(myFixture.project).commitAllDocuments() + } + + private fun findElementToBind(): PsiElement? { + val classToBind = InTextDirectivesUtils.findStringWithPrefixes(file.text, BIND_TO) + return if (classToBind != null) findClass(classToBind) else null + } + + 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" + } +} \ No newline at end of file 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 new file mode 100644 index 000000000000..111b6ed38910 --- /dev/null +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/safeDelete/K2BindToElementTestGenerated.java @@ -0,0 +1,107 @@ +// 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.refactoring.safeDelete; + +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("refactorings/kotlin.refactorings.tests.k2") +@TestDataPath("$CONTENT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public abstract class K2BindToElementTestGenerated extends AbstractK2BindToElementTest { + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/call") + public static class Call 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/call/FullyQualified.kt"); + } + + @TestMetadata("RootPkg.kt") + public void testRootPkg() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/call/RootPkg.kt"); + } + + @TestMetadata("TypeArgument.kt") + public void testTypeArgument() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/call/TypeArgument.kt"); + } + + @TestMetadata("UnQualified.kt") + public void testUnQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/call/UnQualified.kt"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/callableReference") + public static class CallableReference 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/callableReference/FullyQualified.kt"); + } + + @TestMetadata("RootPkg.kt") + public void testRootPkg() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/callableReference/RootPkg.kt"); + } + + @TestMetadata("UnQualified.kt") + public void testUnQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/callableReference/UnQualified.kt"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/type") + public static class Type 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/type/FullyQualified.kt"); + } + + @TestMetadata("RootPkg.kt") + public void testRootPkg() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/type/RootPkg.kt"); + } + + @TestMetadata("UnQualified.kt") + public void testUnQualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/type/UnQualified.kt"); + } + } + + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../../idea/tests/testData/refactoring/bindToElement/import") + public static class Import extends AbstractK2BindToElementTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("ChangeImports.kt") + public void testChangeImports() throws Exception { + runTest("../../idea/tests/testData/refactoring/bindToElement/import/ChangeImports.kt"); + } + } +} diff --git a/plugins/kotlin/refactorings/rename.k2/resources/kotlin.refactorings.rename.k2.xml b/plugins/kotlin/refactorings/rename.k2/resources/kotlin.refactorings.rename.k2.xml index c0952f73fe69..3de80acc54a0 100644 --- a/plugins/kotlin/refactorings/rename.k2/resources/kotlin.refactorings.rename.k2.xml +++ b/plugins/kotlin/refactorings/rename.k2/resources/kotlin.refactorings.rename.k2.xml @@ -4,11 +4,6 @@ - - - diff --git a/plugins/kotlin/refactorings/rename.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/rename/K2ReferenceMutateService.kt b/plugins/kotlin/refactorings/rename.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/rename/K2ReferenceMutateService.kt deleted file mode 100644 index fbc4c29ec2fb..000000000000 --- a/plugins/kotlin/refactorings/rename.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/rename/K2ReferenceMutateService.kt +++ /dev/null @@ -1,46 +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.refactoring.rename - -import com.intellij.psi.PsiElement -import com.intellij.util.IncorrectOperationException -import org.jetbrains.kotlin.idea.refactoring.intentions.OperatorToFunctionConverter -import org.jetbrains.kotlin.idea.refactoring.rename.KtReferenceMutateServiceBase -import org.jetbrains.kotlin.idea.references.KtDefaultAnnotationArgumentReference -import org.jetbrains.kotlin.idea.references.KtReferenceMutateService -import org.jetbrains.kotlin.idea.references.KtSimpleNameReference -import org.jetbrains.kotlin.idea.references.SyntheticPropertyAccessorReference -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.KtDotQualifiedExpression -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtValueArgument - -/** - * At the moment, this implementation of [KtReferenceMutateService] is not able to do any of required operations. It is OK and - * on purpose - this functionality will be added later. - */ -internal class K2ReferenceMutateService : KtReferenceMutateServiceBase() { - override fun bindToFqName( - simpleNameReference: KtSimpleNameReference, - fqName: FqName, - shorteningMode: KtSimpleNameReference.ShorteningMode, - targetElement: PsiElement? - ): PsiElement { - operationNotSupportedInK2Error() - } - - override fun SyntheticPropertyAccessorReference.renameTo(newElementName: String): KtElement? { - operationNotSupportedInK2Error() - } - - override fun KtDefaultAnnotationArgumentReference.renameTo(newElementName: String): KtValueArgument { - operationNotSupportedInK2Error() - } - - override fun replaceWithImplicitInvokeInvocation(newExpression: KtDotQualifiedExpression): KtExpression? = - OperatorToFunctionConverter.replaceExplicitInvokeCallWithImplicit(newExpression) - - private fun operationNotSupportedInK2Error(): Nothing { - throw IncorrectOperationException("K2 plugin does not yet support this operation") - } -} \ No newline at end of file diff --git a/plugins/kotlin/refactorings/rename.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/rename/K2RenameRefactoringSupport.kt b/plugins/kotlin/refactorings/rename.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/rename/K2RenameRefactoringSupport.kt index bc95f9f93b1e..d403fb436d3b 100644 --- a/plugins/kotlin/refactorings/rename.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/rename/K2RenameRefactoringSupport.kt +++ b/plugins/kotlin/refactorings/rename.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/rename/K2RenameRefactoringSupport.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.asJava.toLightMethods import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.idea.parameterInfo.getJvmName import org.jetbrains.kotlin.idea.refactoring.rename.KotlinRenameRefactoringSupport +import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.idea.searching.inheritors.findAllOverridings import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.NameUtils @@ -75,10 +76,6 @@ internal class K2RenameRefactoringSupport : KotlinRenameRefactoringSupport { } } - override fun getModuleNameSuffixForMangledName(mangledName: String): String? { - notImplementedInK2() - } - override fun mangleInternalName(name: String, moduleName: String): String { return name + "$" + NameUtils.sanitizeAsJavaIdentifier(moduleName) } @@ -105,7 +102,12 @@ internal class K2RenameRefactoringSupport : KotlinRenameRefactoringSupport { } override fun isCompanionObjectClassReference(psiReference: PsiReference): Boolean { - notImplementedInK2() + if (psiReference !is KtSimpleNameReference) { + return false + } + return analyze(psiReference.element) { + psiReference.isImplicitReferenceToCompanion() + } } override fun shortenReferencesLater(element: KtElement) { diff --git a/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/AbstractFirRenameTest.kt b/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/AbstractFirRenameTest.kt index b69f83969a83..fe4368807e10 100644 --- a/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/AbstractFirRenameTest.kt +++ b/plugins/kotlin/refactorings/rename.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/rename/AbstractFirRenameTest.kt @@ -37,41 +37,39 @@ abstract class AbstractFirRenameTest : AbstractRenameTest() { return KotlinWithJdkAndRuntimeLightProjectDescriptor.getInstance() } + @OptIn(KtAllowAnalysisOnEdt::class) override fun doTest(path: String) { val renameObject = loadTestConfiguration(dataFile()) val testIsEnabledInK2 = renameObject.get("enabledInK2")?.asBoolean == true if (!testIsEnabledInK2 && onlyRunEnabledTests) return - val result = runCatching { super.doTest(path) } + val result = allowAnalysisOnEdt { runCatching { super.doTest(path) } } result.fold( onSuccess = { require(testIsEnabledInK2) { "This test passes and should be enabled!" } }, onFailure = { exception -> if (testIsEnabledInK2) throw exception } ) } - @OptIn(KtAllowAnalysisOnEdt::class) - override fun findPsiDeclarationToRename(contextFile: KtFile, target: KotlinTarget): PsiElement = allowAnalysisOnEdt { - analyze(contextFile) { - when (target) { - is KotlinTarget.Classifier -> getClassOrObjectSymbolByClassId(target.classId)?.psi!! - is KotlinTarget.Callable -> { - val callableId = target.callableId + override fun findPsiDeclarationToRename(contextFile: KtFile, target: KotlinTarget): PsiElement = analyze(contextFile) { + when (target) { + is KotlinTarget.Classifier -> getClassOrObjectSymbolByClassId(target.classId)?.psi!! + is KotlinTarget.Callable -> { + val callableId = target.callableId - val scope = callableId.classId - ?.let { classId -> getClassOrObjectSymbolByClassId(classId)!!.getMemberScope() } - ?: getPackageSymbolIfPackageExists(callableId.packageName)!!.getPackageScope() + val scope = callableId.classId + ?.let { classId -> getClassOrObjectSymbolByClassId(classId)!!.getMemberScope() } + ?: getPackageSymbolIfPackageExists(callableId.packageName)!!.getPackageScope() - val callablesOfProperType = scope.getCallableSymbols(callableId.callableName) - .mapNotNull { - when (target.type) { - KotlinTarget.CallableType.FUNCTION -> it as? KtFunctionSymbol - KotlinTarget.CallableType.PROPERTY -> it as? KtPropertySymbol - } + val callablesOfProperType = scope.getCallableSymbols(callableId.callableName) + .mapNotNull { + when (target.type) { + KotlinTarget.CallableType.FUNCTION -> it as? KtFunctionSymbol + KotlinTarget.CallableType.PROPERTY -> it as? KtPropertySymbol } + } - callablesOfProperType.first().psi!! - } + callablesOfProperType.first().psi!! } } } 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 de9bf2521842..8e38681712d4 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 @@ -23,6 +23,11 @@ public class FirRenameTestGenerated extends AbstractFirRenameTest { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("abstractFunction/abstractFunction.test") + public void testAbstractFunction_AbstractFunction() throws Exception { + runTest("../../idea/tests/testData/refactoring/rename/abstractFunction/abstractFunction.test"); + } + @TestMetadata("ambiguousClassFunImportRenameClass/ambiguousClassFunImportRenameClass.test") public void testAmbiguousClassFunImportRenameClass_AmbiguousClassFunImportRenameClass() throws Exception { runTest("../../idea/tests/testData/refactoring/rename/ambiguousClassFunImportRenameClass/ambiguousClassFunImportRenameClass.test"); diff --git a/plugins/kotlin/repl/src/org/jetbrains/kotlin/console/ConsoleCompilerHelper.kt b/plugins/kotlin/repl/src/org/jetbrains/kotlin/console/ConsoleCompilerHelper.kt index c39c45eab70a..4553d1219e8c 100644 --- a/plugins/kotlin/repl/src/org/jetbrains/kotlin/console/ConsoleCompilerHelper.kt +++ b/plugins/kotlin/repl/src/org/jetbrains/kotlin/console/ConsoleCompilerHelper.kt @@ -1,4 +1,4 @@ -// 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. +// 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.console @@ -9,6 +9,7 @@ import com.intellij.openapi.compiler.CompilerManager import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.task.ProjectTaskManager +import com.intellij.task.impl.ProjectTaskManagerImpl class ConsoleCompilerHelper( private val project: Project, @@ -25,6 +26,7 @@ class ConsoleCompilerHelper( fun compileModule() { if (RunContentManager.getInstance(project).removeRunContent(executor, contentDescriptor)) { + ProjectTaskManagerImpl.putBuildOriginator(project, this.javaClass) ProjectTaskManager.getInstance(project).build(module).onSuccess { if (!module.isDisposed) { KotlinConsoleKeeper.getInstance(project).run(module, previousCompilationFailed = it.hasErrors()) diff --git a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt index 4f7c983646bd..73bb78938b70 100644 --- a/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt +++ b/plugins/kotlin/test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt @@ -316,7 +316,6 @@ abstract class KotlinLightCodeInsightFixtureTestCase : KotlinLightCodeInsightFix } protected open fun getDefaultProjectDescriptor(): KotlinLightProjectDescriptor = KotlinLightProjectDescriptor.INSTANCE - protected fun performNotWriteEditorAction(actionId: String): Boolean { val dataContext = (myFixture.editor as EditorEx).dataContext diff --git a/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/LightClassBehaviorTestBase.kt b/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/LightClassBehaviorTestBase.kt index a25d5c5f0ac3..ec5ee9e67455 100644 --- a/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/LightClassBehaviorTestBase.kt +++ b/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/LightClassBehaviorTestBase.kt @@ -170,20 +170,24 @@ interface LightClassBehaviorTestBase : UastPluginSelection { val upTo = uFile.findElementByTextFromPsi("upTo", strict = false) .orFail("can't find fun upTo") TestCase.assertTrue(upTo.javaPsi.hasModifier(JvmModifier.FINAL)) + TestCase.assertTrue(upTo.javaPsi.containingClass!!.hasModifier(JvmModifier.FINAL)) TestCase.assertTrue(upTo.javaPsi.parameterList.parameters[0].annotations.any { it.isNotNull }) val isFinished = uFile.findElementByTextFromPsi("isFinished", strict = false) .orFail("can't find accessor isFinished") TestCase.assertTrue(isFinished.javaPsi.hasModifier(JvmModifier.FINAL)) + TestCase.assertTrue(isFinished.javaPsi.containingClass!!.hasModifier(JvmModifier.FINAL)) val isAtLeast = uFile.findElementByTextFromPsi("isAtLeast", strict = false) .orFail("can't find fun isAtLeast") TestCase.assertTrue(isAtLeast.javaPsi.hasModifier(JvmModifier.FINAL)) + TestCase.assertTrue(isAtLeast.javaPsi.containingClass!!.hasModifier(JvmModifier.FINAL)) TestCase.assertTrue(isAtLeast.javaPsi.parameterList.parameters[0].annotations.any { it.isNotNull }) val done = uFile.findElementByTextFromPsi("done", strict = false) .orFail("can't find fun done") TestCase.assertTrue(done.javaPsi.hasModifier(JvmModifier.FINAL)) + TestCase.assertTrue(done.javaPsi.containingClass!!.hasModifier(JvmModifier.FINAL)) TestCase.assertTrue(done.javaPsi.parameterList.parameters[0].annotations.any { it.isNotNull }) } diff --git a/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastApiFixtureTestBase.kt b/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastApiFixtureTestBase.kt index 38b4b96d0f92..54c22cbab73b 100644 --- a/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastApiFixtureTestBase.kt +++ b/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastApiFixtureTestBase.kt @@ -689,4 +689,22 @@ interface UastApiFixtureTestBase : UastPluginSelection { val identifier = extensionReceiver.uastAnchor as? UIdentifier TestCase.assertNotNull(identifier) } + + fun checkReceiverTypeOfExtensionFunction(myFixture: JavaCodeInsightTestFixture) { + myFixture.configureByText( + "main.kt", """ + class Foo + class Bar { + fun Foo.ext() {} + + fun test(f: Foo) { + f.ext() + } + } + """.trimIndent() + ) + val uCallExpression = myFixture.file.findElementAt(myFixture.caretOffset).toUElement().getUCallExpression() + .orFail("cant convert to UCallExpression") + TestCase.assertEquals("Foo", uCallExpression.receiverType?.canonicalText) + } } \ No newline at end of file diff --git a/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinUastResolveProviderService.kt b/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinUastResolveProviderService.kt index df5897f1ae21..8bf998fa61c0 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinUastResolveProviderService.kt +++ b/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinUastResolveProviderService.kt @@ -267,7 +267,7 @@ interface FirKotlinUastResolveProviderService : BaseKotlinUastResolveProviderSer override fun isResolvedToExtension(ktCallElement: KtCallElement): Boolean { analyzeForUast(ktCallElement) { val ktCall = ktCallElement.resolveCall()?.singleFunctionCallOrNull() ?: return false - return isExtension(ktCall) + return ktCall.symbol.isExtension } } @@ -395,12 +395,15 @@ interface FirKotlinUastResolveProviderService : BaseKotlinUastResolveProviderSer fun resolveToPsiClassOrEnumEntry(classOrObject: KtClassOrObject): PsiElement? { analyzeForUast(ktExpression) { val ktType = when (classOrObject) { - is KtEnumEntry -> - classOrObject.getEnumEntrySymbol().callableIdIfNonLocal?.classId?.let { enumClassId -> - buildClassType(enumClassId) - } - else -> - classOrObject.getClassOrObjectSymbol()?.let(::buildClassType) + is KtEnumEntry -> { + classOrObject.getEnumEntrySymbol().callableIdIfNonLocal?.classId?.let(::buildClassType) + } + else -> { + // NB: Avoid symbol creation/retrieval + classOrObject.getClassId()?.let(::buildClassType) + // Fallback option for local class + ?: classOrObject.getClassOrObjectSymbol()?.let(::buildClassType) + } } ?: return null val psiClass = toPsiClass(ktType, source = null, classOrObject, classOrObject.typeOwnerKind) return when (classOrObject) { diff --git a/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/internal/firKotlinInternalUastUtils.kt b/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/internal/firKotlinInternalUastUtils.kt index bf353dbf479b..926bd478b336 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/internal/firKotlinInternalUastUtils.kt +++ b/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/internal/firKotlinInternalUastUtils.kt @@ -8,7 +8,6 @@ import com.intellij.psi.util.PsiTypesUtil import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.calls.KtCallableMemberCall -import org.jetbrains.kotlin.analysis.api.calls.symbol import org.jetbrains.kotlin.analysis.api.components.buildClassType import org.jetbrains.kotlin.analysis.api.getModule import org.jetbrains.kotlin.analysis.api.lifetime.KtAlwaysAccessibleLifetimeTokenFactory @@ -227,25 +226,14 @@ internal fun KtAnalysisSession.toPsiType( ) ?: UastErrorType } -internal fun KtAnalysisSession.isExtension( - ktCall: KtCallableMemberCall<*, *> -): Boolean { - return ktCall.symbol.isExtension -} - internal fun KtAnalysisSession.receiverType( ktCall: KtCallableMemberCall<*, *>, source: UElement, context: KtElement, ): PsiType? { - var ktType = ktCall.partiallyAppliedSymbol.signature.receiverType - if (ktType == null) { - ktType = - if (isExtension(ktCall)) - ktCall.partiallyAppliedSymbol.extensionReceiver?.type - else - ktCall.partiallyAppliedSymbol.dispatchReceiver?.type - } + val ktType = ktCall.partiallyAppliedSymbol.signature.receiverType + ?: ktCall.partiallyAppliedSymbol.extensionReceiver?.type + ?: ktCall.partiallyAppliedSymbol.dispatchReceiver?.type if (ktType == null || ktType is KtErrorType) return null return toPsiType( ktType, diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastApiFixtureTest.kt b/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastApiFixtureTest.kt index e2951a10721e..76bf1c9f0cd8 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastApiFixtureTest.kt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastApiFixtureTest.kt @@ -84,4 +84,8 @@ class FirUastApiFixtureTest : KotlinLightCodeInsightFixtureTestCase(), UastApiFi fun testIdentifierOfNullableExtensionReceiver() { checkIdentifierOfNullableExtensionReceiver(myFixture) } + + fun testReceiverTypeOfExtensionFunction() { + checkReceiverTypeOfExtensionFunction(myFixture) + } } \ No newline at end of file diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastDeclarationTestGenerated.java b/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastDeclarationTestGenerated.java index 5393391b8b3e..1c33fadaaf4b 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastDeclarationTestGenerated.java +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastDeclarationTestGenerated.java @@ -98,6 +98,11 @@ public class FirUastDeclarationTestGenerated extends AbstractFirUastDeclarationT runTest("testData/declaration/mangling.kt"); } + @TestMetadata("missingNames.kt") + public void testMissingNames() throws Exception { + runTest("testData/declaration/missingNames.kt"); + } + @TestMetadata("nullabilityOfTypeParameter.kt") public void testNullabilityOfTypeParameter() throws Exception { runTest("testData/declaration/nullabilityOfTypeParameter.kt"); diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.kt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.kt new file mode 100644 index 000000000000..3e0acce27a07 --- /dev/null +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.kt @@ -0,0 +1,19 @@ +// KTIJ-25335 +class SimpleClass(valOne: String, valTwo: Int) { + val +} + +class Foo(val name: String, val) + +// KTIJ-23584 +interface Foo { + val +} + +// KTIJ-24121 +class MyClass(val value: T) { + fun getValAsString(): T { + return value.toString() + } + val +} diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.log.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.log.fe10.txt new file mode 100644 index 000000000000..960460867048 --- /dev/null +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.log.fe10.txt @@ -0,0 +1,30 @@ +UFile (package = ) + UClass (name = SimpleClass) + UMethod (name = SimpleClass) + UParameter (name = valOne) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = valTwo) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UClass (name = Foo) + UField (name = name) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UMethod (name = getName) + UMethod (name = Foo) + UParameter (name = name) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = ) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UClass (name = Foo) + UClass (name = MyClass) + UField (name = value) + UMethod (name = getValAsString) + UBlockExpression + UReturnExpression + UQualifiedReferenceExpression + USimpleNameReferenceExpression (identifier = value) + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) + UIdentifier (Identifier (toString)) + USimpleNameReferenceExpression (identifier = toString, resolvesTo = null) + UMethod (name = getValue) + UMethod (name = MyClass) + UParameter (name = value) diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.log.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.log.fir.txt new file mode 100644 index 000000000000..4982f4679ef9 --- /dev/null +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.log.fir.txt @@ -0,0 +1,30 @@ +UFile (package = ) + UClass (name = SimpleClass) + UMethod (name = SimpleClass) + UParameter (name = valOne) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = valTwo) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UClass (name = Foo) + UField (name = name) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UMethod (name = getName) + UMethod (name = Foo) + UParameter (name = name) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = ) + UAnnotation (fqName = null) + UClass (name = Foo) + UClass (name = MyClass) + UField (name = value) + UMethod (name = getValAsString) + UBlockExpression + UReturnExpression + UQualifiedReferenceExpression + USimpleNameReferenceExpression (identifier = value) + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) + UIdentifier (Identifier (toString)) + USimpleNameReferenceExpression (identifier = toString, resolvesTo = null) + UMethod (name = getValue) + UMethod (name = MyClass) + UParameter (name = value) diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.render.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.render.fe10.txt new file mode 100644 index 000000000000..4185ad8852d9 --- /dev/null +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.render.fe10.txt @@ -0,0 +1,21 @@ +public final class SimpleClass { + public fun SimpleClass(@org.jetbrains.annotations.NotNull valOne: java.lang.String, @org.jetbrains.annotations.NotNull valTwo: int) = UastEmptyExpression +} + +public final class Foo { + @org.jetbrains.annotations.NotNull private final var name: java.lang.String + public final fun getName() : java.lang.String = UastEmptyExpression + public fun Foo(@org.jetbrains.annotations.NotNull name: java.lang.String, @org.jetbrains.annotations.NotNull : error.NonExistentClass) = UastEmptyExpression +} + +public abstract interface Foo { +} + +public final class MyClass { + private final var value: T + public final fun getValAsString() : T { + return value.toString() + } + public final fun getValue() : T = UastEmptyExpression + public fun MyClass(value: T) = UastEmptyExpression +} diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.render.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.render.fir.txt new file mode 100644 index 000000000000..16b420239bad --- /dev/null +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/declaration/missingNames.render.fir.txt @@ -0,0 +1,21 @@ +public final class SimpleClass { + public fun SimpleClass(@org.jetbrains.annotations.NotNull valOne: java.lang.String, @org.jetbrains.annotations.NotNull valTwo: int) = UastEmptyExpression +} + +public final class Foo { + @org.jetbrains.annotations.NotNull private final var name: java.lang.String + public final fun getName() : java.lang.String = UastEmptyExpression + public fun Foo(@org.jetbrains.annotations.NotNull name: java.lang.String, @null : error.NonExistentClass) = UastEmptyExpression +} + +public abstract interface Foo { +} + +public final class MyClass { + private final var value: T + public final fun getValAsString() : T { + return value.toString() + } + public final fun getValue() : T = UastEmptyExpression + public fun MyClass(value: T) = UastEmptyExpression +} diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/BrokenMethod.render.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/BrokenMethod.render.fir.txt index c3ce4458a262..5ede3753ffb3 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/BrokenMethod.render.fir.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/BrokenMethod.render.fir.txt @@ -10,17 +10,17 @@ public final class BrokenMethodKt { public fun hashCode() : int = UastEmptyExpression public fun equals(@org.jetbrains.annotations.Nullable other: java.lang.Object) : boolean = UastEmptyExpression public static final class Used { - @null public static final var Companion: TestUsed.Used.Companion + @null public static final var Companion: Companion @org.jetbrains.annotations.NotNull private final var parameter: java.lang.Object public final fun getParameter() : java.lang.Object = UastEmptyExpression public fun Used(@org.jetbrains.annotations.NotNull parameter: java.lang.Object) = UastEmptyExpression public final fun component1() : java.lang.Object = UastEmptyExpression - public final fun copy(@org.jetbrains.annotations.NotNull parameter: java.lang.Object) : TestUsed.Used = UastEmptyExpression + public final fun copy(@org.jetbrains.annotations.NotNull parameter: java.lang.Object) : Used = UastEmptyExpression public fun toString() : java.lang.String = UastEmptyExpression public fun hashCode() : int = UastEmptyExpression public fun equals(@org.jetbrains.annotations.Nullable other: java.lang.Object) : boolean = UastEmptyExpression public static final class Companion { - public final fun doStuff1(@org.jetbrains.annotations.NotNull $this$doStuff1: java.lang.Object) : TestUsed.Used { + public final fun doStuff1(@org.jetbrains.annotations.NotNull $this$doStuff1: java.lang.Object) : Used { return (this) } private fun Companion() = UastEmptyExpression diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/CommentOwners.render.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/CommentOwners.render.fe10.txt index 57e7629244bf..76989f296fa5 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/CommentOwners.render.fe10.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/CommentOwners.render.fe10.txt @@ -37,7 +37,7 @@ public final class TopLevelClass { } } -public enum MyBooleanEnum { +public final enum MyBooleanEnum { @null TRUE @null FALSE private fun MyBooleanEnum() = UastEmptyExpression diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValueMembers.render.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValueMembers.render.fe10.txt index 4fc1f29e9be0..63a94f43a397 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValueMembers.render.fe10.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValueMembers.render.fe10.txt @@ -1,4 +1,4 @@ -public enum Style { +public abstract enum Style { @org.jetbrains.annotations.NotNull private final var value: java.lang.String @null SHEET("foo") { public fun getExitAnimation() : java.lang.String { diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValueMembers.render.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValueMembers.render.fir.txt index ea24a0ec7d04..e35846764f59 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValueMembers.render.fir.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValueMembers.render.fir.txt @@ -1,4 +1,4 @@ -public final enum Style { +public abstract enum Style { @org.jetbrains.annotations.NotNull private final var value: java.lang.String @null SHEET("foo") { public fun getExitAnimation() : java.lang.String { diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValuesConstructors.render.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValuesConstructors.render.fe10.txt index ed5ab4620e13..99584c7dc177 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValuesConstructors.render.fe10.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyRenderLog/EnumValuesConstructors.render.fe10.txt @@ -1,4 +1,4 @@ -public enum Style { +public final enum Style { @org.jetbrains.annotations.Nullable private final var value: java.lang.String @null SYSTEM("system") @null USER("user") diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/BrokenMethod.types.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/BrokenMethod.types.fir.txt index b76b6896e012..d7a2f4dd06a4 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/BrokenMethod.types.fir.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/BrokenMethod.types.fir.txt @@ -22,7 +22,7 @@ UFile (package = ) [public final class BrokenMethodKt {...] UParameter (name = other) [@org.jetbrains.annotations.Nullable var other: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.Nullable) [@org.jetbrains.annotations.Nullable] UClass (name = Used) [public static final class Used {...}] - UField (name = Companion) [@null public static final var Companion: TestUsed.Used.Companion] + UField (name = Companion) [@null public static final var Companion: Companion] UAnnotation (fqName = null) [@null] UField (name = parameter) [@org.jetbrains.annotations.NotNull private final var parameter: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] @@ -31,7 +31,7 @@ UFile (package = ) [public final class BrokenMethodKt {...] UParameter (name = parameter) [@org.jetbrains.annotations.NotNull var parameter: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UMethod (name = component1) [public final fun component1() : java.lang.Object = UastEmptyExpression] - UMethod (name = copy) [public final fun copy(@org.jetbrains.annotations.NotNull parameter: java.lang.Object) : TestUsed.Used = UastEmptyExpression] + UMethod (name = copy) [public final fun copy(@org.jetbrains.annotations.NotNull parameter: java.lang.Object) : Used = UastEmptyExpression] UParameter (name = parameter) [@org.jetbrains.annotations.NotNull var parameter: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UMethod (name = toString) [public fun toString() : java.lang.String = UastEmptyExpression] @@ -40,7 +40,7 @@ UFile (package = ) [public final class BrokenMethodKt {...] UParameter (name = other) [@org.jetbrains.annotations.Nullable var other: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.Nullable) [@org.jetbrains.annotations.Nullable] UClass (name = Companion) [public static final class Companion {...}] - UMethod (name = doStuff1) [public final fun doStuff1(@org.jetbrains.annotations.NotNull $this$doStuff1: java.lang.Object) : TestUsed.Used {...}] + UMethod (name = doStuff1) [public final fun doStuff1(@org.jetbrains.annotations.NotNull $this$doStuff1: java.lang.Object) : Used {...}] UParameter (name = $this$doStuff1) [@org.jetbrains.annotations.NotNull var $this$doStuff1: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/CommentOwners.types.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/CommentOwners.types.fe10.txt index d7891bb72266..78978b0cc293 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/CommentOwners.types.fe10.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/CommentOwners.types.fe10.txt @@ -69,7 +69,7 @@ UFile (package = ) [public final class CommentOwnersKt {...] USimpleNameReferenceExpression (identifier = , resolvesTo = PsiClass: Object) [] UClass (name = NestedClass) [public static final class NestedClass {...}] UMethod (name = NestedClass) [public fun NestedClass() = UastEmptyExpression] - UClass (name = MyBooleanEnum) [public enum MyBooleanEnum {...}] + UClass (name = MyBooleanEnum) [public final enum MyBooleanEnum {...}] UEnumConstant (name = TRUE) [@null TRUE] UAnnotation (fqName = null) [@null] USimpleNameReferenceExpression (identifier = MyBooleanEnum) [MyBooleanEnum] diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValueMembers.types.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValueMembers.types.fe10.txt index 900012075231..5e214dabb9c1 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValueMembers.types.fe10.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValueMembers.types.fe10.txt @@ -1,5 +1,5 @@ -UFile (package = ) [public enum Style {...] - UClass (name = Style) [public enum Style {...}] +UFile (package = ) [public abstract enum Style {...] + UClass (name = Style) [public abstract enum Style {...}] UField (name = value) [@org.jetbrains.annotations.NotNull private final var value: java.lang.String] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UEnumConstant (name = SHEET) [@null SHEET("foo") {...}] diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValueMembers.types.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValueMembers.types.fir.txt index 0a38b56040e5..704a61c29a2f 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValueMembers.types.fir.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValueMembers.types.fir.txt @@ -1,5 +1,5 @@ -UFile (package = ) [public final enum Style {...] - UClass (name = Style) [public final enum Style {...}] +UFile (package = ) [public abstract enum Style {...] + UClass (name = Style) [public abstract enum Style {...}] UField (name = value) [@org.jetbrains.annotations.NotNull private final var value: java.lang.String] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UEnumConstant (name = SHEET) [@null SHEET("foo") {...}] diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValuesConstructors.types.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValuesConstructors.types.fe10.txt index b9b7912d5d32..fab88267ba24 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValuesConstructors.types.fe10.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyTypes/EnumValuesConstructors.types.fe10.txt @@ -1,5 +1,5 @@ -UFile (package = ) [public enum Style {...] - UClass (name = Style) [public enum Style {...}] +UFile (package = ) [public final enum Style {...] + UClass (name = Style) [public final enum Style {...}] UField (name = value) [@org.jetbrains.annotations.Nullable private final var value: java.lang.String] UAnnotation (fqName = org.jetbrains.annotations.Nullable) [@org.jetbrains.annotations.Nullable] UEnumConstant (name = SYSTEM) [@null SYSTEM("system")] diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/BrokenMethod.values.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/BrokenMethod.values.fir.txt index f45fb46ee492..8254989fc8b9 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/BrokenMethod.values.fir.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/BrokenMethod.values.fir.txt @@ -22,7 +22,7 @@ UFile (package = ) [public final class BrokenMethodKt {...] UParameter (name = other) [@org.jetbrains.annotations.Nullable var other: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.Nullable) [@org.jetbrains.annotations.Nullable] UClass (name = Used) [public static final class Used {...}] - UField (name = Companion) [@null public static final var Companion: TestUsed.Used.Companion] + UField (name = Companion) [@null public static final var Companion: Companion] UAnnotation (fqName = null) [@null] UField (name = parameter) [@org.jetbrains.annotations.NotNull private final var parameter: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] @@ -31,7 +31,7 @@ UFile (package = ) [public final class BrokenMethodKt {...] UParameter (name = parameter) [@org.jetbrains.annotations.NotNull var parameter: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UMethod (name = component1) [public final fun component1() : java.lang.Object = UastEmptyExpression] - UMethod (name = copy) [public final fun copy(@org.jetbrains.annotations.NotNull parameter: java.lang.Object) : TestUsed.Used = UastEmptyExpression] + UMethod (name = copy) [public final fun copy(@org.jetbrains.annotations.NotNull parameter: java.lang.Object) : Used = UastEmptyExpression] UParameter (name = parameter) [@org.jetbrains.annotations.NotNull var parameter: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UMethod (name = toString) [public fun toString() : java.lang.String = UastEmptyExpression] @@ -40,7 +40,7 @@ UFile (package = ) [public final class BrokenMethodKt {...] UParameter (name = other) [@org.jetbrains.annotations.Nullable var other: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.Nullable) [@org.jetbrains.annotations.Nullable] UClass (name = Companion) [public static final class Companion {...}] - UMethod (name = doStuff1) [public final fun doStuff1(@org.jetbrains.annotations.NotNull $this$doStuff1: java.lang.Object) : TestUsed.Used {...}] + UMethod (name = doStuff1) [public final fun doStuff1(@org.jetbrains.annotations.NotNull $this$doStuff1: java.lang.Object) : Used {...}] UParameter (name = $this$doStuff1) [@org.jetbrains.annotations.NotNull var $this$doStuff1: java.lang.Object] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UBlockExpression [{...}] = Nothing diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/CommentOwners.values.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/CommentOwners.values.fe10.txt index 09a788a2c9d3..f09bf4f4cd5b 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/CommentOwners.values.fe10.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/CommentOwners.values.fe10.txt @@ -69,7 +69,7 @@ UFile (package = ) [public final class CommentOwnersKt {...] USimpleNameReferenceExpression (identifier = , resolvesTo = PsiClass: Object) [] = external ()() UClass (name = NestedClass) [public static final class NestedClass {...}] UMethod (name = NestedClass) [public fun NestedClass() = UastEmptyExpression] - UClass (name = MyBooleanEnum) [public enum MyBooleanEnum {...}] + UClass (name = MyBooleanEnum) [public final enum MyBooleanEnum {...}] UEnumConstant (name = TRUE) [@null TRUE] = Undetermined UAnnotation (fqName = null) [@null] USimpleNameReferenceExpression (identifier = MyBooleanEnum) [MyBooleanEnum] = external MyBooleanEnum() diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValueMembers.values.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValueMembers.values.fe10.txt index 510f3862af68..54959b3f0435 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValueMembers.values.fe10.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValueMembers.values.fe10.txt @@ -1,5 +1,5 @@ -UFile (package = ) [public enum Style {...] - UClass (name = Style) [public enum Style {...}] +UFile (package = ) [public abstract enum Style {...] + UClass (name = Style) [public abstract enum Style {...}] UField (name = value) [@org.jetbrains.annotations.NotNull private final var value: java.lang.String] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UEnumConstant (name = SHEET) [@null SHEET("foo") {...}] = Undetermined diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValueMembers.values.fir.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValueMembers.values.fir.txt index 04cc79af6fae..935c75544c3e 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValueMembers.values.fir.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValueMembers.values.fir.txt @@ -1,5 +1,5 @@ -UFile (package = ) [public final enum Style {...] - UClass (name = Style) [public final enum Style {...}] +UFile (package = ) [public abstract enum Style {...] + UClass (name = Style) [public abstract enum Style {...}] UField (name = value) [@org.jetbrains.annotations.NotNull private final var value: java.lang.String] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UEnumConstant (name = SHEET) [@null SHEET("foo") {...}] = Undetermined diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValuesConstructors.values.fe10.txt b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValuesConstructors.values.fe10.txt index 0f3eae3c21e6..ef21789529d1 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValuesConstructors.values.fe10.txt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/testData/legacyValues/EnumValuesConstructors.values.fe10.txt @@ -1,5 +1,5 @@ -UFile (package = ) [public enum Style {...] - UClass (name = Style) [public enum Style {...}] +UFile (package = ) [public final enum Style {...] + UClass (name = Style) [public final enum Style {...}] UField (name = value) [@org.jetbrains.annotations.Nullable private final var value: java.lang.String] UAnnotation (fqName = org.jetbrains.annotations.Nullable) [@org.jetbrains.annotations.Nullable] UEnumConstant (name = SYSTEM) [@null SYSTEM("system")] = Undetermined diff --git a/plugins/kotlin/uast/uast-kotlin-idea/src/org/jetbrains/uast/kotlin/generate/KotlinUastCodeGenerationPlugin.kt b/plugins/kotlin/uast/uast-kotlin-idea/src/org/jetbrains/uast/kotlin/generate/KotlinUastCodeGenerationPlugin.kt index 80cadcaf3378..db24ee08f6b6 100644 --- a/plugins/kotlin/uast/uast-kotlin-idea/src/org/jetbrains/uast/kotlin/generate/KotlinUastCodeGenerationPlugin.kt +++ b/plugins/kotlin/uast/uast-kotlin-idea/src/org/jetbrains/uast/kotlin/generate/KotlinUastCodeGenerationPlugin.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses import org.jetbrains.kotlin.idea.intentions.ImportAllMembersIntention import org.jetbrains.kotlin.idea.refactoring.fqName.fqName import org.jetbrains.kotlin.idea.references.KtSimpleNameReference +import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.idea.util.resolveToKotlinType import org.jetbrains.kotlin.incremental.components.NoLookupLocation @@ -27,7 +28,6 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* -import org.jetbrains.kotlin.references.fe10.KtFe10SimpleNameReference import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier import org.jetbrains.uast.* import org.jetbrains.uast.generate.UParameterInfo @@ -83,8 +83,7 @@ class KotlinUastCodeGenerationPlugin : UastCodeGenerationPlugin { override fun bindToElement(reference: UReferenceExpression, element: PsiElement): PsiElement? { val sourcePsi = reference.sourcePsi ?: return null if (sourcePsi !is KtSimpleNameExpression) return null - return KtFe10SimpleNameReference(sourcePsi) - .bindToElement(element, KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING) + return sourcePsi.mainReference.bindToElement(element, KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING) } override fun shortenReference(reference: UReferenceExpression): UReferenceExpression? { diff --git a/plugins/kotlin/uast/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastResolveProviderService.kt b/plugins/kotlin/uast/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastResolveProviderService.kt index 21f924eae176..10ffd6ffbcd3 100644 --- a/plugins/kotlin/uast/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastResolveProviderService.kt +++ b/plugins/kotlin/uast/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastResolveProviderService.kt @@ -345,7 +345,7 @@ interface KotlinUastResolveProviderService : BaseKotlinUastResolveProviderServic override fun getReceiverType(ktCallElement: KtCallElement, source: UElement): PsiType? { val resolvedCall = ktCallElement.getResolvedCall(ktCallElement.analyze()) ?: return null - val receiver = resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver ?: return null + val receiver = resolvedCall.extensionReceiver ?: resolvedCall.dispatchReceiver ?: return null return receiver.type.toPsiType(source, ktCallElement, PsiTypeConversionConfiguration.create(ktCallElement, isBoxed = true)) } diff --git a/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastApiFixtureTest.kt b/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastApiFixtureTest.kt index c163202a5a3a..b55dc97eafdd 100644 --- a/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastApiFixtureTest.kt +++ b/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastApiFixtureTest.kt @@ -82,4 +82,8 @@ class FE1UastApiFixtureTest : KotlinLightCodeInsightFixtureTestCase(), UastApiFi fun testIdentifierOfNullableExtensionReceiver() { checkIdentifierOfNullableExtensionReceiver(myFixture) } + + fun testReceiverTypeOfExtensionFunction() { + checkReceiverTypeOfExtensionFunction(myFixture) + } } \ No newline at end of file diff --git a/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastDeclarationTestGenerated.java b/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastDeclarationTestGenerated.java index 71b0690e6703..56f92fa799bd 100644 --- a/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastDeclarationTestGenerated.java +++ b/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastDeclarationTestGenerated.java @@ -98,6 +98,11 @@ public class FE1UastDeclarationTestGenerated extends AbstractFE1UastDeclarationT runTest("../../uast-kotlin-fir/tests/testData/declaration/mangling.kt"); } + @TestMetadata("missingNames.kt") + public void testMissingNames() throws Exception { + runTest("../../uast-kotlin-fir/tests/testData/declaration/missingNames.kt"); + } + @TestMetadata("nullabilityOfTypeParameter.kt") public void testNullabilityOfTypeParameter() throws Exception { runTest("../../uast-kotlin-fir/tests/testData/declaration/nullabilityOfTypeParameter.kt"); diff --git a/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValueMembers.render-ide.txt b/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValueMembers.render-ide.txt index e1124ee6d106..462ed6a7147c 100644 --- a/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValueMembers.render-ide.txt +++ b/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValueMembers.render-ide.txt @@ -1,4 +1,4 @@ -public enum Style { +public abstract enum Style { @org.jetbrains.annotations.NotNull private final var value: java.lang.String @null SHEET("foo") { public fun getExitAnimation() : java.lang.String { diff --git a/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValueMembers.render.txt b/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValueMembers.render.txt index 4fc1f29e9be0..63a94f43a397 100644 --- a/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValueMembers.render.txt +++ b/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValueMembers.render.txt @@ -1,4 +1,4 @@ -public enum Style { +public abstract enum Style { @org.jetbrains.annotations.NotNull private final var value: java.lang.String @null SHEET("foo") { public fun getExitAnimation() : java.lang.String { diff --git a/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValuesConstructors.render-ide.txt b/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValuesConstructors.render-ide.txt index 637249179cc5..f8c0d81ca907 100644 --- a/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValuesConstructors.render-ide.txt +++ b/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValuesConstructors.render-ide.txt @@ -1,4 +1,4 @@ -public enum Style { +public final enum Style { @org.jetbrains.annotations.Nullable private final var value: java.lang.String @null SYSTEM("system") @null USER("user") diff --git a/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValuesConstructors.render.txt b/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValuesConstructors.render.txt index ed5ab4620e13..99584c7dc177 100644 --- a/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValuesConstructors.render.txt +++ b/plugins/kotlin/uast/uast-kotlin/tests/testData/EnumValuesConstructors.render.txt @@ -1,4 +1,4 @@ -public enum Style { +public final enum Style { @org.jetbrains.annotations.Nullable private final var value: java.lang.String @null SYSTEM("system") @null USER("user") diff --git a/plugins/kotlin/util/project-model-updater/resources/model.properties b/plugins/kotlin/util/project-model-updater/resources/model.properties index f2732e70cfed..b2d4b6b5265c 100644 --- a/plugins/kotlin/util/project-model-updater/resources/model.properties +++ b/plugins/kotlin/util/project-model-updater/resources/model.properties @@ -1,4 +1,4 @@ -kotlincVersion=1.9.20-dev-4794 +kotlincVersion=1.9.20-dev-5455 kotlincArtifactsMode=MAVEN jpsPluginVersion=1.8.21-release-380 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 9c90c983c3b9..2f5f96375148 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 @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.idea.AbstractExpressionSelectionTest import org.jetbrains.kotlin.idea.AbstractSmartSelectionTest import org.jetbrains.kotlin.idea.AbstractWorkSelectionTest import org.jetbrains.kotlin.idea.actions.AbstractGotoTestOrCodeActionTest -import org.jetbrains.kotlin.idea.actions.AbstractKotlinAddImportActionTest +import org.jetbrains.kotlin.idea.actions.AbstractK1AddImportActionTest import org.jetbrains.kotlin.idea.base.plugin.artifacts.TestKotlinArtifacts import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiModuleLineMarkerTest import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiPlatformHighlightingTest @@ -826,7 +826,7 @@ private fun assembleWorkspace(): TWorkspace = workspace { model("addImportAlias", pattern = KT_WITHOUT_DOTS) } - testClass { + testClass { model("idea/actions/kotlinAddImportAction", pattern = KT_WITHOUT_DOTS) } 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 eaab2b813b3d..2fd6db722116 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 @@ -4,6 +4,7 @@ package org.jetbrains.kotlin.fir.testGenerator 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.sessions.AbstractSessionsInvalidationTest import org.jetbrains.kotlin.idea.fir.analysis.providers.trackers.AbstractProjectWideOutOfBlockKotlinModificationTrackerTest @@ -21,9 +22,12 @@ import org.jetbrains.kotlin.idea.fir.findUsages.AbstractKotlinFindUsagesWithLibr import org.jetbrains.kotlin.idea.fir.findUsages.AbstractKotlinFindUsagesWithStdlibFirTest import org.jetbrains.kotlin.idea.fir.imports.AbstractFirJvmOptimizeImportsTest import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirLibraryModuleDeclarationResolveTest +import org.jetbrains.kotlin.idea.fir.navigation.AbstractFirGotoTypeDeclarationTest import org.jetbrains.kotlin.idea.fir.parameterInfo.AbstractFirParameterInfoTest import org.jetbrains.kotlin.idea.fir.quickfix.AbstractHighLevelQuickFixMultiFileTest +import org.jetbrains.kotlin.idea.fir.quickfix.AbstractHighLevelQuickFixMultiModuleTest import org.jetbrains.kotlin.idea.fir.quickfix.AbstractHighLevelQuickFixTest +import org.jetbrains.kotlin.idea.fir.resolve.* import org.jetbrains.kotlin.idea.fir.search.AbstractHLImplementationSearcherTest import org.jetbrains.kotlin.idea.fir.shortenRefs.AbstractFirShortenRefsTest import org.jetbrains.kotlin.idea.k2.refactoring.rename.AbstractFirRenameTest @@ -36,8 +40,6 @@ import org.jetbrains.kotlin.testGenerator.model.Patterns.KT_OR_KTS_WITHOUT_DOTS import org.jetbrains.kotlin.testGenerator.model.Patterns.KT_WITHOUT_DOTS import org.jetbrains.kotlin.testGenerator.model.Patterns.KT_WITHOUT_DOT_AND_FIR_PREFIX import org.jetbrains.kotlin.testGenerator.model.Patterns.KT_WITHOUT_FIR_PREFIX -import org.jetbrains.kotlin.idea.fir.resolve.* -import org.jetbrains.kotlin.idea.fir.navigation.AbstractFirGotoTypeDeclarationTest import org.jetbrains.kotlin.testGenerator.model.Patterns.TEST import org.jetbrains.kotlin.testGenerator.model.Patterns.KT_OR_KTS @@ -87,6 +89,10 @@ private fun assembleWorkspace(): TWorkspace = workspace { } testGroup("fir", testDataPath = "../idea/tests/testData") { + testClass { + model("idea/actions/kotlinAddImportAction", pattern = KT_WITHOUT_DOTS) + } + testClass { model("resolve/references", pattern = KT_WITHOUT_DOTS) } @@ -112,6 +118,10 @@ private fun assembleWorkspace(): TWorkspace = workspace { model("resolve/referenceInJava/binaryAndSource", pattern = JAVA) } + testClass { + model("resolve/compiled/sources") + } + testClass { model("navigation/gotoTypeDeclaration", pattern = TEST) } @@ -161,6 +171,9 @@ private fun assembleWorkspace(): TWorkspace = workspace { ) } + testClass { + model("multiModuleQuickFix", pattern = DIRECTORY, depth = 1) + } testClass { model("shortenRefsFir", pattern = KT_WITHOUT_DOTS, testMethodName = "doTestWithMuting") 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 2e3629336eee..4769c170dad7 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 @@ -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.fir.testGenerator +import org.jetbrains.kotlin.idea.k2.refactoring.safeDelete.AbstractK2BindToElementTest import org.jetbrains.kotlin.idea.k2.refactoring.safeDelete.AbstractK2SafeDeleteTest import org.jetbrains.kotlin.testGenerator.model.* @@ -29,6 +30,12 @@ internal fun MutableTWorkspace.generateK2RefactoringsTests() { model("refactoring/safeDelete/deleteValueParameter/kotlinValueParameterWithJava", testMethodName = "doValueParameterTestWithJava") model("refactoring/safeDelete/deleteValueParameter/javaParameterWithKotlin", pattern = Patterns.JAVA, testMethodName = "doJavaParameterTest") } + testClass { + model("refactoring/bindToElement/call") + model("refactoring/bindToElement/callableReference") + model("refactoring/bindToElement/type") + model("refactoring/bindToElement/import", isRecursive = false) + } } // TODO enable when move refactoring works diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2StructureViewTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2StructureViewTests.kt index f9ee22d5f79c..6ee5266d222d 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2StructureViewTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2StructureViewTests.kt @@ -8,7 +8,7 @@ import org.jetbrains.kotlin.testGenerator.model.* internal fun MutableTWorkspace.generateK2StructureViewTests() { testGroup("code-insight/kotlin.code-insight.k2") { testClass { - model("structureView/fileStructure", pattern = Patterns.KT_OR_KTS_WITHOUT_DOTS) + model("../../../idea/tests/testData/structureView/fileStructure", pattern = Patterns.KT_OR_KTS_WITHOUT_DOTS) } } } \ No newline at end of file diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterMayBeUsedInspection.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterMayBeUsedInspection.java index aaa66dbe5ee3..02d2ac274539 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterMayBeUsedInspection.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterMayBeUsedInspection.java @@ -1,337 +1,151 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package de.plushnikov.intellij.plugin.inspection; -import com.intellij.codeInspection.*; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.JavaCodeStyleManager; -import com.intellij.psi.javadoc.PsiDocComment; -import com.intellij.psi.javadoc.PsiDocTag; -import com.intellij.psi.javadoc.PsiDocToken; import com.intellij.psi.util.PsiTreeUtil; -import com.siyeh.ig.psiutils.CommentTracker; +import com.intellij.psi.util.PsiUtil; import de.plushnikov.intellij.plugin.LombokBundle; import de.plushnikov.intellij.plugin.LombokClassNames; import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Objects; import static com.intellij.util.ObjectUtils.tryCast; -public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase implements CleanupLocalInspectionTool { - - @NotNull +public class LombokGetterMayBeUsedInspection extends LombokGetterOrSetterMayBeUsedInspection { @Override - protected PsiElementVisitor createVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) { - return new LombokGetterMayBeUsedVisitor(holder, false); + @NotNull + protected String getTagName() { + return "return"; } - private static class LombokGetterMayBeUsedVisitor extends JavaElementVisitor { - private final @Nullable ProblemsHolder myHolder; - private final boolean myApplyFix; + @Override + @NotNull + protected String getJavaDocMethodMarkup() { + return "GETTER"; + } - private LombokGetterMayBeUsedVisitor(@Nullable ProblemsHolder holder, boolean applyFix) { - this.myHolder = holder; - myApplyFix = applyFix; + @Override + @NotNull + protected @NonNls String getAnnotationName() { + return LombokClassNames.GETTER; + } + + @Override + @NotNull + protected @Nls String getFieldErrorMessage(String fieldName) { + return LombokBundle.message("inspection.lombok.getter.may.be.used.display.field.message", + fieldName); + } + + @Override + @NotNull + protected @Nls String getClassErrorMessage(String className) { + return LombokBundle.message("inspection.lombok.getter.may.be.used.display.class.message", + className); + } + + @Override + protected boolean processMethod( + @NotNull PsiMethod method, + @NotNull List> instanceCandidates, + @NotNull List> staticCandidates + ) { + final PsiType returnType = method.getReturnType(); + if (!method.hasModifierProperty(PsiModifier.PUBLIC) + || method.isConstructor() + || method.hasParameters() + || method.getThrowsTypes().length != 0 + || method.hasModifierProperty(PsiModifier.FINAL) + || method.hasModifierProperty(PsiModifier.ABSTRACT) + || method.hasModifierProperty(PsiModifier.SYNCHRONIZED) + || method.hasModifierProperty(PsiModifier.NATIVE) + || method.hasModifierProperty(PsiModifier.STRICTFP) + || method.getAnnotations().length != 0 + || PsiTypes.voidType().equals(returnType) + || returnType == null + || returnType.getAnnotations().length != 0 + || !method.isWritable()) { + return false; + } + final String methodName = method.getName(); + final boolean isBooleanType = PsiTypes.booleanType().equals(returnType); + if (isBooleanType ? !methodName.startsWith("is") : !methodName.startsWith("get")) { + return false; } - @Override - public void visitJavaFile(@NotNull PsiJavaFile psiJavaFile) { + final String fieldName = StringUtil.getPropertyName(methodName); + if (StringUtil.isEmpty(fieldName)) { + return false; } - @Override - public void visitClass(@NotNull PsiClass psiClass) { - List annotatedFields = new ArrayList<>(); - List> instanceCandidates = new ArrayList<>(); - List> staticCandidates = new ArrayList<>(); - for (PsiMethod method : psiClass.getMethods()) { - processMethod(method, instanceCandidates, staticCandidates); - } - boolean isGetterAtClassLevel = true; - for (PsiField field : psiClass.getFields()) { - PsiAnnotation annotation = field.getAnnotation(LombokClassNames.GETTER); - if (annotation != null) { - if (!annotation.getAttributes().isEmpty()) { - isGetterAtClassLevel = false; - } - else { - annotatedFields.add(field); - } - break; - } - if (!field.hasModifierProperty(PsiModifier.STATIC)) { - boolean found = false; - for (Pair instanceCandidate : instanceCandidates) { - if (field.equals(instanceCandidate.getFirst())) { - found = true; - break; - } - } - isGetterAtClassLevel &= found; - } - } - List> allCandidates = new ArrayList<>(staticCandidates); - if (isGetterAtClassLevel && (!instanceCandidates.isEmpty() || !annotatedFields.isEmpty())) { - warnOrFix(psiClass, instanceCandidates, annotatedFields); - } - else { - allCandidates.addAll(instanceCandidates); - } - for (Pair candidate : allCandidates) { - warnOrFix(candidate.getFirst(), candidate.getSecond()); - } + if (method.getBody() == null) { + return false; } - - public void visitMethodForFix(@NotNull PsiMethod psiMethod) { - List> fieldsAndMethods = new ArrayList<>(); - if (!processMethod(psiMethod, fieldsAndMethods, fieldsAndMethods)) return; - if (!fieldsAndMethods.isEmpty()) { - final Pair psiFieldPsiMethodPair = fieldsAndMethods.get(0); - warnOrFix(psiFieldPsiMethodPair.getFirst(), psiFieldPsiMethodPair.getSecond()); - } + final PsiStatement @NotNull [] methodStatements = Arrays.stream(method.getBody().getStatements()).filter(e -> !(e instanceof PsiEmptyStatement)).toArray(PsiStatement[]::new); + if (methodStatements.length != 1) { + return false; } - - private static boolean processMethod( - @NotNull PsiMethod method, - @NotNull List> instanceCandidates, - @NotNull List> staticCandidates - ) { - final PsiType returnType = method.getReturnType(); - if (!method.hasModifierProperty(PsiModifier.PUBLIC) - || method.isConstructor() - || method.hasParameters() - || method.getThrowsTypes().length != 0 - || method.hasModifierProperty(PsiModifier.FINAL) - || method.hasModifierProperty(PsiModifier.ABSTRACT) - || method.hasModifierProperty(PsiModifier.SYNCHRONIZED) - || method.hasModifierProperty(PsiModifier.NATIVE) - || method.hasModifierProperty(PsiModifier.STRICTFP) - || method.getAnnotations().length != 0 - || PsiTypes.voidType().equals(returnType) - || returnType == null - || returnType.getAnnotations().length != 0 - || !method.isWritable()) { + final PsiReturnStatement returnStatement = tryCast(methodStatements[0], PsiReturnStatement.class); + if (returnStatement == null) { + return false; + } + final PsiReferenceExpression targetRef = tryCast( + PsiUtil.skipParenthesizedExprDown(returnStatement.getReturnValue()), PsiReferenceExpression.class); + if (targetRef == null) { + return false; + } + final @Nullable PsiExpression qualifier = targetRef.getQualifierExpression(); + final @Nullable PsiThisExpression thisExpression = tryCast(qualifier, PsiThisExpression.class); + final PsiClass psiClass = PsiTreeUtil.getParentOfType(method, PsiClass.class); + if (psiClass == null) { + return false; + } + if (qualifier != null) { + if (thisExpression == null) { return false; - } - - final String methodName = method.getName(); - final boolean isBooleanType = PsiTypes.booleanType().equals(returnType); - if (isBooleanType ? !methodName.startsWith("is") : !methodName.startsWith("get")) { - return false; - } - - final String fieldName = StringUtil.getPropertyName(methodName); - if (StringUtil.isEmpty(fieldName)) { - return false; - } - - if (method.getBody() == null) { - return false; - } - final PsiStatement @NotNull [] methodStatements = method.getBody().getStatements(); - if (methodStatements.length != 1) { - return false; - } - final PsiReturnStatement returnStatement = tryCast(methodStatements[0], PsiReturnStatement.class); - if (returnStatement == null) { - return false; - } - final PsiReferenceExpression fieldRef = tryCast(returnStatement.getReturnValue(), PsiReferenceExpression.class); - if (fieldRef == null) { - return false; - } - final @Nullable PsiExpression qualifier = fieldRef.getQualifierExpression(); - final @Nullable PsiThisExpression thisExpression = tryCast(qualifier, PsiThisExpression.class); - final PsiClass psiClass = PsiTreeUtil.getParentOfType(method, PsiClass.class); - if (psiClass == null) { - return false; - } - if (qualifier != null) { - if (thisExpression == null) { + } else if (thisExpression.getQualifier() != null) { + if (!thisExpression.getQualifier().isReferenceTo(psiClass)) { return false; } - else if (thisExpression.getQualifier() != null) { - if (!thisExpression.getQualifier().isReferenceTo(psiClass)) { - return false; - } - } - } - final @Nullable String identifier = fieldRef.getReferenceName(); - if (!fieldName.equals(identifier) && !StringUtil.capitalize(fieldName).equals(identifier)) { - return false; - } - - final boolean isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC); - final PsiField field = psiClass.findFieldByName(identifier, false); - if (field == null - || !field.isWritable() - || isMethodStatic != field.hasModifierProperty(PsiModifier.STATIC) - || !field.getType().equals(returnType)) { - return false; - } - if (isMethodStatic) { - staticCandidates.add(Pair.pair(field, method)); - } - else { - instanceCandidates.add(Pair.pair(field, method)); - } - return true; - } - - private void warnOrFix( - @NotNull PsiClass psiClass, - @NotNull List> fieldsAndMethods, - @NotNull List annotatedFields - ) { - if (myHolder != null) { - final LocalQuickFix fix = new LombokGetterMayBeUsedFix(Objects.requireNonNull(psiClass.getName())); - final PsiIdentifier psiClassNameIdentifier = psiClass.getNameIdentifier(); - myHolder.registerProblem(psiClass, - LombokBundle.message("inspection.lombok.getter.may.be.used.display.class.message", - psiClass.getName()), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - psiClassNameIdentifier != null ? psiClassNameIdentifier.getTextRangeInParent() : psiClass.getTextRange(), - fix); - } - else if (myApplyFix) { - LombokGetterMayBeUsedFix.effectivelyDoFix(psiClass, fieldsAndMethods, annotatedFields); } } - - private void warnOrFix(@NotNull PsiField field, @NotNull PsiMethod method) { - if (myHolder != null) { - final LocalQuickFix fix = new LombokGetterMayBeUsedFix(field.getName()); - myHolder.registerProblem(method, - LombokBundle.message("inspection.lombok.getter.may.be.used.display.field.message", - field.getName()), fix); - } - else if (myApplyFix) { - LombokGetterMayBeUsedFix.effectivelyDoFix(field, method); - } + final @Nullable String fieldIdentifier = targetRef.getReferenceName(); + if (!fieldName.equals(fieldIdentifier) && !StringUtil.capitalize(fieldName).equals(fieldIdentifier)) { + return false; } + + final boolean isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC); + final PsiField field = psiClass.findFieldByName(fieldIdentifier, false); + if (field == null + || !field.isWritable() + || isMethodStatic != field.hasModifierProperty(PsiModifier.STATIC) + || !field.getType().equals(returnType)) { + return false; + } + if (isMethodStatic) { + staticCandidates.add(Pair.pair(field, method)); + } else { + instanceCandidates.add(Pair.pair(field, method)); + } + return true; } - private static class LombokGetterMayBeUsedFix implements LocalQuickFix { - private final @NotNull String myText; - - private LombokGetterMayBeUsedFix(@NotNull String text) { - myText = text; - } - - @Nls(capitalization = Nls.Capitalization.Sentence) - @NotNull - @Override - public String getName() { - return LombokBundle.message("inspection.lombok.getter.may.be.used.display.fix.name", myText); - } - - @Nls(capitalization = Nls.Capitalization.Sentence) - @NotNull - @Override - public String getFamilyName() { - return LombokBundle.message("inspection.lombok.getter.may.be.used.display.fix.family.name"); - } - - @Override - public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - final PsiElement element = descriptor.getPsiElement(); - if (element instanceof PsiMethod) { - new LombokGetterMayBeUsedVisitor(null, true).visitMethodForFix((PsiMethod)element); - } - else if (element instanceof PsiClass) { - new LombokGetterMayBeUsedVisitor(null, true).visitClass((PsiClass)element); - } - } - - private static void effectivelyDoFix(@NotNull PsiField field, @NotNull PsiMethod method) { - final PsiModifierList modifierList = field.getModifierList(); - if (modifierList == null) { - return; - } - Project project = field.getProject(); - final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); - final PsiAnnotation annotation = factory.createAnnotationFromText("@" + LombokClassNames.GETTER, field); - JavaCodeStyleManager.getInstance(project).shortenClassReferences(annotation); - modifierList.addAfter(annotation, null); - removeMethodAndMoveJavaDoc(field, method); - } - - public static void effectivelyDoFix(@NotNull PsiClass aClass, @NotNull List> fieldsAndMethods, - @NotNull List annotatedFields) { - Project project = aClass.getProject(); - for (Pair fieldAndMethod : fieldsAndMethods) { - PsiField field = fieldAndMethod.getFirst(); - PsiMethod method = fieldAndMethod.getSecond(); - removeMethodAndMoveJavaDoc(field, method); - } - final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); - final PsiAnnotation newAnnotation = factory.createAnnotationFromText("@" + LombokClassNames.GETTER, aClass); - JavaCodeStyleManager.getInstance(project).shortenClassReferences(newAnnotation); - final PsiModifierList modifierList = aClass.getModifierList(); - if (modifierList == null) { - return; - } - modifierList.addAfter(newAnnotation, null); - for (PsiField annotatedField : annotatedFields) { - PsiAnnotation oldAnnotation = annotatedField.getAnnotation(LombokClassNames.GETTER); - if (oldAnnotation != null) { - new CommentTracker().deleteAndRestoreComments(oldAnnotation); - } - } - } - - private static void removeMethodAndMoveJavaDoc(@NotNull PsiField field, @NotNull PsiMethod method) { - final PsiElementFactory factory = JavaPsiFacade.getElementFactory(field.getProject()); - CommentTracker tracker = new CommentTracker(); - PsiDocComment methodJavaDoc = method.getDocComment(); - if (methodJavaDoc != null) { - tracker.text(methodJavaDoc); - PsiDocComment fieldJavaDoc = field.getDocComment(); - List methodJavaDocTokens = Arrays.stream(methodJavaDoc.getChildren()) - .filter(e -> e instanceof PsiDocToken) - .map(PsiElement::getText) - .filter(text -> !text.matches("\\s*\\*\\s*")) - .toList(); - methodJavaDocTokens = methodJavaDocTokens.subList(1, methodJavaDocTokens.size() - 1); - String javaDocGetterText = String.join("\n* ", methodJavaDocTokens); - PsiDocTag[] returnTags = methodJavaDoc.findTagsByName("return"); - if (fieldJavaDoc == null) { - if (javaDocGetterText.isEmpty()) { - fieldJavaDoc = factory.createDocCommentFromText("/**\n*/"); - } - else { - fieldJavaDoc = factory.createDocCommentFromText("/**\n* -- GETTER --\n* " + javaDocGetterText + "\n*/"); - } - for (PsiDocTag returnTag : returnTags) { - fieldJavaDoc.add(returnTag); - } - field.getParent().addBefore(fieldJavaDoc, field); - } - else { - @NotNull PsiElement @NotNull [] fieldJavaDocChildren = Arrays.stream(fieldJavaDoc.getChildren()) - .filter(e -> e instanceof PsiDocToken) - .toArray(PsiElement[]::new); - @NotNull PsiElement fieldJavaDocChild = fieldJavaDocChildren[fieldJavaDocChildren.length - 2]; - PsiDocComment newMethodJavaDoc = factory.createDocCommentFromText("/**\n* -- GETTER --\n* " + javaDocGetterText + "\n*/"); - PsiElement[] tokens = newMethodJavaDoc.getChildren(); - for (int i = tokens.length - 2; 0 < i; i--) { - fieldJavaDoc.addAfter(tokens[i], fieldJavaDocChild); - } - for (PsiDocTag returnTag : returnTags) { - fieldJavaDoc.add(returnTag); - } - } - methodJavaDoc.delete(); - } - tracker.delete(method); - tracker.insertCommentsBefore(field); - } + @Override + @NotNull + protected @Nls String getFixName(String text) { + return LombokBundle.message("inspection.lombok.getter.may.be.used.display.fix.name", text); } -} + + @Override + @NotNull + protected @Nls String getFixFamilyName() { + return LombokBundle.message("inspection.lombok.getter.may.be.used.display.fix.family.name"); + } +} \ No newline at end of file diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterOrSetterMayBeUsedInspection.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterOrSetterMayBeUsedInspection.java new file mode 100644 index 000000000000..c825372f6e9a --- /dev/null +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterOrSetterMayBeUsedInspection.java @@ -0,0 +1,279 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package de.plushnikov.intellij.plugin.inspection; + +import com.intellij.codeInspection.*; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.javadoc.PsiDocTag; +import com.intellij.psi.javadoc.PsiDocToken; +import com.siyeh.ig.psiutils.CommentTracker; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +public abstract class LombokGetterOrSetterMayBeUsedInspection extends LombokJavaInspectionBase implements CleanupLocalInspectionTool { + + @NotNull + @Override + protected PsiElementVisitor createVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) { + return new LombokGetterOrSetterMayBeUsedVisitor(holder, null); + } + + private class LombokGetterOrSetterMayBeUsedVisitor extends JavaElementVisitor { + private final @Nullable ProblemsHolder myHolder; + + private final @Nullable LombokGetterOrSetterMayBeUsedInspection.LombokGetterOrSetterMayBeUsedFix myLombokGetterOrSetterMayBeUsedFix; + + private LombokGetterOrSetterMayBeUsedVisitor( + @Nullable ProblemsHolder holder, + @Nullable LombokGetterOrSetterMayBeUsedInspection.LombokGetterOrSetterMayBeUsedFix lombokGetterOrSetterMayBeUsedFix + ) { + this.myHolder = holder; + this.myLombokGetterOrSetterMayBeUsedFix = lombokGetterOrSetterMayBeUsedFix; + } + + @Override + public void visitJavaFile(@NotNull PsiJavaFile psiJavaFile) { + } + + @Override + public void visitClass(@NotNull PsiClass psiClass) { + List annotatedFields = new ArrayList<>(); + List> instanceCandidates = new ArrayList<>(); + List> staticCandidates = new ArrayList<>(); + for (PsiMethod method : psiClass.getMethods()) { + processMethod(method, instanceCandidates, staticCandidates); + } + boolean isLombokAnnotationAtClassLevel = true; + for (PsiField field : psiClass.getFields()) { + PsiAnnotation annotation = field.getAnnotation(getAnnotationName()); + if (annotation != null) { + if (!annotation.getAttributes().isEmpty()) { + isLombokAnnotationAtClassLevel = false; + } + else { + annotatedFields.add(field); + } + } + else if (!field.hasModifierProperty(PsiModifier.STATIC)) { + boolean found = false; + for (Pair instanceCandidate : instanceCandidates) { + if (field.equals(instanceCandidate.getFirst())) { + found = true; + break; + } + } + isLombokAnnotationAtClassLevel = found; + } + + if (!isLombokAnnotationAtClassLevel) { + break; + } + } + List> allCandidates = new ArrayList<>(staticCandidates); + if (isLombokAnnotationAtClassLevel && (!instanceCandidates.isEmpty() || !annotatedFields.isEmpty())) { + warnOrFix(psiClass, instanceCandidates, annotatedFields); + } + else { + allCandidates.addAll(instanceCandidates); + } + for (Pair candidate : allCandidates) { + warnOrFix(candidate.getFirst(), candidate.getSecond()); + } + } + + public void visitMethodForFix(@NotNull PsiMethod psiMethod) { + List> fieldsAndMethods = new ArrayList<>(); + if (!processMethod(psiMethod, fieldsAndMethods, fieldsAndMethods)) return; + if (!fieldsAndMethods.isEmpty()) { + final Pair psiFieldPsiMethodPair = fieldsAndMethods.get(0); + warnOrFix(psiFieldPsiMethodPair.getFirst(), psiFieldPsiMethodPair.getSecond()); + } + } + + private void warnOrFix( + @NotNull PsiClass psiClass, + @NotNull List> fieldsAndMethods, + @NotNull List annotatedFields + ) { + if (myHolder != null) { + String className = psiClass.getName(); + final PsiIdentifier psiClassNameIdentifier = psiClass.getNameIdentifier(); + final LocalQuickFix fix = new LombokGetterOrSetterMayBeUsedFix(Objects.requireNonNull(className)); + myHolder.registerProblem(psiClass, + getClassErrorMessage(className), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + psiClassNameIdentifier != null ? psiClassNameIdentifier.getTextRangeInParent() : psiClass.getTextRange(), + fix); + } + else if (myLombokGetterOrSetterMayBeUsedFix != null) { + myLombokGetterOrSetterMayBeUsedFix.effectivelyDoFix(psiClass, fieldsAndMethods, annotatedFields); + } + } + + private void warnOrFix(@NotNull PsiField field, @NotNull PsiMethod method) { + if (myHolder != null) { + String fieldName = field.getName(); + final LocalQuickFix fix = new LombokGetterOrSetterMayBeUsedFix(fieldName); + myHolder.registerProblem(method, + getFieldErrorMessage(fieldName), fix); + } + else if (myLombokGetterOrSetterMayBeUsedFix != null) { + myLombokGetterOrSetterMayBeUsedFix.effectivelyDoFix(field, method); + } + } + } + + private class LombokGetterOrSetterMayBeUsedFix implements LocalQuickFix { + private final @NotNull String myText; + private Project project; + + private LombokGetterOrSetterMayBeUsedFix(@NotNull String text) { + myText = text; + } + + @Nls(capitalization = Nls.Capitalization.Sentence) + @NotNull + @Override + public String getName() { + return getFixName(myText); + } + + @Nls(capitalization = Nls.Capitalization.Sentence) + @NotNull + @Override + public String getFamilyName() { + return getFixFamilyName(); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + this.project = project; + final PsiElement element = descriptor.getPsiElement(); + if (element instanceof PsiMethod) { + new LombokGetterOrSetterMayBeUsedVisitor(null, this).visitMethodForFix((PsiMethod)element); + } + else if (element instanceof PsiClass) { + new LombokGetterOrSetterMayBeUsedVisitor(null, this).visitClass((PsiClass)element); + } + } + + private void effectivelyDoFix(@NotNull PsiField field, @NotNull PsiMethod method) { + if (!addLombokAnnotation(field)) return; + removeMethodAndMoveJavaDoc(field, method); + } + + public void effectivelyDoFix(@NotNull PsiClass aClass, @NotNull List> fieldsAndMethods, + @NotNull List annotatedFields) { + if (!addLombokAnnotation(aClass)) return; + for (Pair fieldAndMethod : fieldsAndMethods) { + PsiField field = fieldAndMethod.getFirst(); + PsiMethod method = fieldAndMethod.getSecond(); + removeMethodAndMoveJavaDoc(field, method); + } + for (PsiField annotatedField : annotatedFields) { + PsiAnnotation oldAnnotation = annotatedField.getAnnotation(getAnnotationName()); + if (oldAnnotation != null) { + new CommentTracker().deleteAndRestoreComments(oldAnnotation); + } + } + } + + private boolean addLombokAnnotation(@NotNull PsiModifierListOwner fieldOrClass) { + final PsiModifierList modifierList = fieldOrClass.getModifierList(); + if (modifierList == null) { + return false; + } + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + final PsiAnnotation annotation = factory.createAnnotationFromText("@" + getAnnotationName(), fieldOrClass); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(annotation); + modifierList.addAfter(annotation, null); + return true; + } + + private void removeMethodAndMoveJavaDoc(@NotNull PsiField field, @NotNull PsiMethod method) { + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + CommentTracker tracker = new CommentTracker(); + PsiDocComment methodJavaDoc = method.getDocComment(); + if (methodJavaDoc != null) { + tracker.text(methodJavaDoc); + PsiDocComment fieldJavaDoc = field.getDocComment(); + List methodJavaDocTokens = Arrays.stream(methodJavaDoc.getChildren()) + .filter(e -> e instanceof PsiDocToken) + .map(PsiElement::getText) + .filter(text -> !text.matches("\\s*\\*\\s*")) + .toList(); + methodJavaDocTokens = methodJavaDocTokens.subList(1, methodJavaDocTokens.size() - 1); + String javaDocMethodText = String.join("\n* ", methodJavaDocTokens); + PsiDocTag[] methodTags = methodJavaDoc.findTagsByName(getTagName()); + if (fieldJavaDoc == null) { + if (javaDocMethodText.isEmpty()) { + fieldJavaDoc = factory.createDocCommentFromText("/**\n*/"); + } + else { + fieldJavaDoc = + factory.createDocCommentFromText("/**\n* -- " + getJavaDocMethodMarkup() + " --\n* " + javaDocMethodText + "\n*/"); + } + for (PsiDocTag methodTag : methodTags) { + fieldJavaDoc.add(methodTag); + } + field.getParent().addBefore(fieldJavaDoc, field); + } + else { + @NotNull PsiElement @NotNull [] fieldJavaDocChildren = Arrays.stream(fieldJavaDoc.getChildren()) + .filter(e -> e instanceof PsiDocToken) + .toArray(PsiElement[]::new); + @NotNull PsiElement fieldJavaDocChild = fieldJavaDocChildren[fieldJavaDocChildren.length - 2]; + PsiDocComment newMethodJavaDoc = + factory.createDocCommentFromText("/**\n* -- " + getJavaDocMethodMarkup() + " --\n* " + javaDocMethodText + "\n*/"); + PsiElement[] tokens = newMethodJavaDoc.getChildren(); + for (int i = tokens.length - 2; 0 < i; i--) { + fieldJavaDoc.addAfter(tokens[i], fieldJavaDocChild); + } + for (PsiDocTag methodTag : methodTags) { + fieldJavaDoc.add(methodTag); + } + } + methodJavaDoc.delete(); + } + tracker.delete(method); + tracker.insertCommentsBefore(field); + } + } + + @NotNull + protected abstract String getTagName(); + + @NotNull + protected abstract String getJavaDocMethodMarkup(); + + @NotNull + protected abstract @NonNls String getAnnotationName(); + + @NotNull + protected abstract @Nls String getFieldErrorMessage(String fieldName); + + @NotNull + protected abstract @Nls String getClassErrorMessage(String className); + + protected abstract boolean processMethod( + @NotNull PsiMethod method, + @NotNull List> instanceCandidates, + @NotNull List> staticCandidates + ); + + @NotNull + protected abstract @Nls String getFixName(String text); + + @NotNull + protected abstract @Nls String getFixFamilyName(); +} diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayBeUsedInspection.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayBeUsedInspection.java new file mode 100644 index 000000000000..22d89cd3e647 --- /dev/null +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayBeUsedInspection.java @@ -0,0 +1,184 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package de.plushnikov.intellij.plugin.inspection; + +import com.intellij.lang.jvm.JvmModifier; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import de.plushnikov.intellij.plugin.LombokBundle; +import de.plushnikov.intellij.plugin.LombokClassNames; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.List; + +import static com.intellij.util.ObjectUtils.tryCast; + +public class LombokSetterMayBeUsedInspection extends LombokGetterOrSetterMayBeUsedInspection { + @Override + @NotNull + protected String getTagName() { + return "param"; + } + + @Override + @NotNull + protected String getJavaDocMethodMarkup() { + return "SETTER"; + } + + @Override + @NotNull + protected @NonNls String getAnnotationName() { + return LombokClassNames.SETTER; + } + + @Override + @NotNull + protected @Nls String getFieldErrorMessage(String fieldName) { + return LombokBundle.message("inspection.lombok.setter.may.be.used.display.field.message", + fieldName); + } + + @Override + @NotNull + protected @Nls String getClassErrorMessage(String className) { + return LombokBundle.message("inspection.lombok.setter.may.be.used.display.class.message", + className); + } + + @Override + protected boolean processMethod( + @NotNull PsiMethod method, + @NotNull List> instanceCandidates, + @NotNull List> staticCandidates + ) { + if (!method.hasModifierProperty(PsiModifier.PUBLIC) + || method.isConstructor() + || !method.hasParameters() + || method.getParameterList().getParameters().length != 1 + || 0 < method.getThrowsTypes().length + || method.hasModifierProperty(PsiModifier.FINAL) + || method.hasModifierProperty(PsiModifier.ABSTRACT) + || method.hasModifierProperty(PsiModifier.SYNCHRONIZED) + || method.hasModifierProperty(PsiModifier.NATIVE) + || method.hasModifierProperty(PsiModifier.STRICTFP) + || 0 < method.getAnnotations().length + || !PsiTypes.voidType().equals(method.getReturnType()) + || !method.isWritable()) { + return false; + } + final PsiParameter parameter = method.getParameterList().getParameters()[0]; + if ( + parameter.isVarArgs() + || ( + parameter.getModifierList() != null + && 0 < parameter.getModifierList().getChildren().length + && (parameter.getModifierList().getChildren().length != 1 || !parameter.hasModifier(JvmModifier.FINAL)) + ) + || 0 < parameter.getAnnotations().length + ) { + return false; + } + final PsiType parameterType = parameter.getType(); + + final String methodName = method.getName(); + if (!methodName.startsWith("set")) { + return false; + } + + final String fieldName = StringUtil.getPropertyName(methodName); + if (StringUtil.isEmpty(fieldName)) { + return false; + } + + if (method.getBody() == null) { + return false; + } + final PsiStatement @NotNull [] methodStatements = Arrays.stream(method.getBody().getStatements()).filter(e -> !(e instanceof PsiEmptyStatement)).toArray(PsiStatement[]::new); + if (methodStatements.length != 1) { + return false; + } + final PsiExpressionStatement assignmentStatement = tryCast(methodStatements[0], PsiExpressionStatement.class); + if (assignmentStatement == null) { + return false; + } + final PsiAssignmentExpression assignment = tryCast(assignmentStatement.getExpression(), PsiAssignmentExpression.class); + if (assignment == null || assignment.getOperationTokenType() != JavaTokenType.EQ) { + return false; + } + final PsiReferenceExpression sourceRef = tryCast(PsiUtil.skipParenthesizedExprDown(assignment.getRExpression()), PsiReferenceExpression.class); + if (sourceRef == null || sourceRef.getQualifierExpression() != null) { + return false; + } + final @Nullable String paramIdentifier = sourceRef.getReferenceName(); + if (paramIdentifier == null) { + return false; + } + if (!paramIdentifier.equals(parameter.getName())) { + return false; + } + final PsiReferenceExpression targetRef = tryCast(assignment.getLExpression(), PsiReferenceExpression.class); + if (targetRef == null) { + return false; + } + final @Nullable PsiExpression qualifier = targetRef.getQualifierExpression(); + final @Nullable PsiThisExpression thisExpression = tryCast(qualifier, PsiThisExpression.class); + final PsiClass psiClass = PsiTreeUtil.getParentOfType(method, PsiClass.class); + if (psiClass == null) { + return false; + } + if (qualifier != null) { + if (thisExpression == null) { + return false; + } else if (thisExpression.getQualifier() != null) { + if (!thisExpression.getQualifier().isReferenceTo(psiClass)) { + return false; + } + } + } + final @Nullable String fieldIdentifier = targetRef.getReferenceName(); + if (fieldIdentifier == null) { + return false; + } + if (!fieldName.equals(fieldIdentifier) && !StringUtil.capitalize(fieldName).equals(fieldIdentifier)) { + return false; + } + if (qualifier == null + && paramIdentifier.equals(fieldIdentifier)) { + return false; + } + + final boolean isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC); + final PsiField field = psiClass.findFieldByName(fieldIdentifier, false); + if (field == null + || !field.isWritable() + || isMethodStatic != field.hasModifierProperty(PsiModifier.STATIC) + || !field.getType().equals(parameterType)) { + return false; + } + if (isMethodStatic) { + staticCandidates.add(Pair.pair(field, method)); + } else { + instanceCandidates.add(Pair.pair(field, method)); + } + return true; + } + + @Override + @NotNull + protected @Nls String getFixName(String text) { + return LombokBundle.message("inspection.lombok.setter.may.be.used.display.fix.name", text); + } + + @Override + @NotNull + protected @Nls String getFixFamilyName() { + return LombokBundle.message("inspection.lombok.setter.may.be.used.display.fix.family.name"); + } +} diff --git a/plugins/lombok/src/main/resources/META-INF/plugin.xml b/plugins/lombok/src/main/resources/META-INF/plugin.xml index 873c72ca7fc6..77f798226c86 100644 --- a/plugins/lombok/src/main/resources/META-INF/plugin.xml +++ b/plugins/lombok/src/main/resources/META-INF/plugin.xml @@ -185,6 +185,11 @@ groupBundle="messages.InspectionsBundle" groupKey="group.names.verbose.or.redundant.code.constructs" implementationClass="de.plushnikov.intellij.plugin.inspection.LombokGetterMayBeUsedInspection" cleanupTool="true"/> + + + +Reports standard setter method that can be replaced by the lombok @Setter annotation. +

Example:

+

+  import java.util.Date;
+
+  public class MyClass {
+    /**
+     * The process date.
+     */
+    private Date processDate;
+
+    /**
+     * Sets the date.
+     *
+     * @param The date
+     */
+    public void setProcessDate(Date param) {
+      processDate = param;
+    }
+  }
+
+

After the quick-fix/cleanup is applied:

+

+  import lombok.Setter;
+  import java.util.Date;
+
+  @Setter
+  public class MyClass {
+    /**
+     * The process date.
+     * -- SETTER --
+     * Sets the date.
+     *
+     * @param The date
+     */
+    private Date processDate;
+  }
+
+

It only reports when the lombok library is configured. To unlombok, see the lombok site.

+ +

New in 2023.2

+ + \ No newline at end of file diff --git a/plugins/lombok/src/main/resources/messages/LombokBundle.properties b/plugins/lombok/src/main/resources/messages/LombokBundle.properties index 6f5f0c6a0fe5..7382beca0c9d 100644 --- a/plugins/lombok/src/main/resources/messages/LombokBundle.properties +++ b/plugins/lombok/src/main/resources/messages/LombokBundle.properties @@ -186,4 +186,9 @@ inspection.lombok.getter.may.be.used.display.name=Lombok @Getter may be used inspection.lombok.getter.may.be.used.display.class.message=Class ''{0}'' may use Lombok @Getter inspection.lombok.getter.may.be.used.display.field.message=Field ''{0}'' may have Lombok @Getter inspection.lombok.getter.may.be.used.display.fix.family.name=Replace explicit getter method with Lombok @Getter -inspection.lombok.getter.may.be.used.display.fix.name=Use lombok @Getter for ''{0}'' \ No newline at end of file +inspection.lombok.getter.may.be.used.display.fix.name=Use lombok @Getter for ''{0}'' +inspection.lombok.setter.may.be.used.display.name=Lombok @Setter may be used +inspection.lombok.setter.may.be.used.display.class.message=Class ''{0}'' may use Lombok @Setter +inspection.lombok.setter.may.be.used.display.field.message=Field ''{0}'' may have Lombok @Setter +inspection.lombok.setter.may.be.used.display.fix.family.name=Replace explicit setter method with Lombok @Setter +inspection.lombok.setter.may.be.used.display.fix.name=Use lombok @Setter for ''{0}'' \ No newline at end of file diff --git a/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayBeUsedFixTest.java b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayBeUsedFixTest.java new file mode 100644 index 000000000000..255f594b6658 --- /dev/null +++ b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayBeUsedFixTest.java @@ -0,0 +1,31 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package de.plushnikov.intellij.plugin.inspection; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase; +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.openapi.application.PathManager; +import com.intellij.testFramework.LightProjectDescriptor; +import de.plushnikov.intellij.plugin.LombokTestUtil; +import org.jetbrains.annotations.NotNull; + +public class LombokSetterMayBeUsedFixTest extends LightQuickFixParameterizedTestCase { + @Override + protected LocalInspectionTool @NotNull [] configureLocalInspectionTools() { + return new LocalInspectionTool[]{new LombokSetterMayBeUsedInspection()}; + } + + @Override + protected @NotNull String getTestDataPath() { + return PathManager.getCommunityHomePath() + "/plugins/lombok/testData"; + } + + @Override + protected String getBasePath() { + return "/inspection/lombokSetterMayBeUsed"; + } + + @Override + protected @NotNull LightProjectDescriptor getProjectDescriptor() { + return LombokTestUtil.LOMBOK_NEW_DESCRIPTOR; + } +} diff --git a/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayBeUsedInspectionTest.java b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayBeUsedInspectionTest.java new file mode 100644 index 000000000000..9c14647ca7a7 --- /dev/null +++ b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayBeUsedInspectionTest.java @@ -0,0 +1,43 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package de.plushnikov.intellij.plugin.inspection; + +import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.openapi.application.PathManager; +import com.intellij.testFramework.LightProjectDescriptor; +import de.plushnikov.intellij.plugin.LombokTestUtil; +import org.jetbrains.annotations.NotNull; + +public class LombokSetterMayBeUsedInspectionTest extends LightDaemonAnalyzerTestCase { + @Override + protected LocalInspectionTool @NotNull [] configureLocalInspectionTools() { + return new LocalInspectionTool[]{new LombokSetterMayBeUsedInspection()}; + } + + @Override + protected @NotNull LightProjectDescriptor getProjectDescriptor() { + return LombokTestUtil.LOMBOK_NEW_DESCRIPTOR; + } + + @Override + protected @NotNull String getTestDataPath() { + return PathManager.getCommunityHomePath() + "/plugins/lombok/testData"; + } + + @NotNull + private String getFilePath() { + return "/inspection/lombokSetterMayBeUsed/" + getTestName(false) + ".java"; + } + + private void doTest() { + doTest(getFilePath(), true, false); + } + + public void testFieldsWithSetter() { + doTest(); + } + + public void testInstanceAndStaticFields() { + doTest(); + } +} diff --git a/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayNotBeUsedWithoutLombokLibraryInspectionTest.java b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayNotBeUsedWithoutLombokLibraryInspectionTest.java new file mode 100644 index 000000000000..827cc7552b66 --- /dev/null +++ b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/inspection/LombokSetterMayNotBeUsedWithoutLombokLibraryInspectionTest.java @@ -0,0 +1,31 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package de.plushnikov.intellij.plugin.inspection; + +import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.openapi.application.PathManager; +import org.jetbrains.annotations.NotNull; + +public class LombokSetterMayNotBeUsedWithoutLombokLibraryInspectionTest extends LightDaemonAnalyzerTestCase { + @Override + protected LocalInspectionTool @NotNull [] configureLocalInspectionTools() { + return new LocalInspectionTool[]{new LombokSetterMayBeUsedInspection()}; + } + + @Override + protected @NotNull String getTestDataPath() { + return PathManager.getCommunityHomePath() + "/plugins/lombok/testData"; + } + @NotNull + private String getFilePath() { + return "/inspection/lombokSetterMayBeUsed/" + getTestName(false) + ".java"; + } + + private void doTest() { + doTest(getFilePath(), true, false); + } + + public void testNoLibrary() { + doTest(); + } +} diff --git a/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/afterEmptyStatement.java b/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/afterEmptyStatement.java new file mode 100644 index 000000000000..d6fd30594d87 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/afterEmptyStatement.java @@ -0,0 +1,18 @@ +// "Use lombok @Getter for 'field'" "true" + +import lombok.Getter; + +public class Foo { + private int fieldWithoutGetter; + /** + * The field. + * -- GETTER -- + * Returns The field. + * + * @return The field + + */ + @Getter + private int field; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/afterParentherizedValue.java b/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/afterParentherizedValue.java new file mode 100644 index 000000000000..e1c9085dc7d3 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/afterParentherizedValue.java @@ -0,0 +1,18 @@ +// "Use lombok @Getter for 'finalField'" "true" + +import lombok.Getter; + +public class Foo { + private int fieldWithoutGetter; + /** + * The final field. + * -- GETTER -- + * Returns The final field. + * + * @return The final field + + */ + @Getter + private final int finalField; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/beforeEmptyStatement.java b/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/beforeEmptyStatement.java new file mode 100644 index 000000000000..0fae03ef696c --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/beforeEmptyStatement.java @@ -0,0 +1,18 @@ +// "Use lombok @Getter for 'field'" "true" + +public class Foo { + private int fieldWithoutGetter; + /** + * The field. + */ + private int field; + + /** + * Returns The field. + * + * @return The field + */ + public int getField() { + return field;; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/beforeParentherizedValue.java b/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/beforeParentherizedValue.java new file mode 100644 index 000000000000..80aa43312944 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokGetterMayBeUsed/beforeParentherizedValue.java @@ -0,0 +1,18 @@ +// "Use lombok @Getter for 'finalField'" "true" + +public class Foo { + private int fieldWithoutGetter; + /** + * The final field. + */ + private final int finalField; + + /** + * Returns The final field. + * + * @return The final field + */ + public int getFinalField() { + return (finalField); + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/FieldsWithSetter.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/FieldsWithSetter.java new file mode 100644 index 000000000000..9ca8bd159a29 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/FieldsWithSetter.java @@ -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. + +public class FieldsWithSetter { + private int bar; + + public void setBar(int param) { + bar = param; + } + public class InstanceField { + private int bar; + private boolean Baz; + private int fooBar; + private int fieldWithoutSetter; + + public void setBar(int param) { + bar = param; + } + + public void setBaz(boolean param) { + this.Baz = param; + } + + public void setFooBar(int param) { + InstanceField.this.fooBar = param; + } + } + public class AllInstanceFields { + private int bar; + private boolean Baz; + private int fooBar; + private static int staticFieldWithoutSetter; + + public void setBar(int param) { + bar = param; + } + + public void setBaz(boolean param) { + this.Baz = param; + } + + public void setFooBar(int param) { + AllInstanceFields.this.fooBar = param; + } + } + public class StaticField { + private static int bar; + private int fieldWithoutSetter; + + public static void setBar(int param) { + bar = param; + } + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/InstanceAndStaticFields.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/InstanceAndStaticFields.java new file mode 100644 index 000000000000..10f4ca7e706f --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/InstanceAndStaticFields.java @@ -0,0 +1,14 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + +public class InstanceAndStaticFields { + private static int staticField; + private int instanceField; + + public static void setStaticField(int param) { + staticField = param; + } + + public void setInstanceField(int param) { + instanceField = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/NoLibrary.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/NoLibrary.java new file mode 100644 index 000000000000..5b706dec5d76 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/NoLibrary.java @@ -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. + +public class NoLibrary { + private int bar; + + public void setBar(int param) { + bar = param; + } + public class InstanceField { + private int bar; + private boolean PrimitiveBooleanValue; + private int fooBar; + private int fieldWithoutSetter; + + public void setBar(int param) { + bar = param; + } + + public void setPrimitiveBooleanValue(boolean param) { + PrimitiveBooleanValue = param; + } + + public void setFooBar(int param) { + InstanceField.this.fooBar = param; + } + } + public class AllInstanceFields { + private int bar; + private boolean Baz; + private int fooBar; + private static int staticFieldWithoutSetter; + + public void setBar(int param) { + bar = param; + } + + public void setBaz(boolean param) { + Baz = param; + } + + public void setFooBar(int param) { + AllInstanceFields.this.fooBar = param; + } + } + public class StaticField { + private static int number; + private int fieldWithoutSetter; + + public static void setNumber(int param) { + number = param; + } + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterAllFields.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterAllFields.java new file mode 100644 index 000000000000..1e6470a91acd --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterAllFields.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'Foo'" "true" + +import lombok.Setter; + +@Setter +public class Foo { + private int bar; + private boolean baz; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterAnnotatedField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterAnnotatedField.java new file mode 100644 index 000000000000..065f15113967 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterAnnotatedField.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'ClassWithAnnotatedField'" "true" + +import lombok.Setter; + +@Setter +public class ClassWithAnnotatedField { + private int canditateField; + private int annotatedField; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterBooleanField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterBooleanField.java new file mode 100644 index 000000000000..9369297f66fb --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterBooleanField.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'valid'" "true" + +import lombok.Setter; + +public class ClassWithBoolean { + private int fieldWithoutSetter; + @Setter + private boolean valid; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterEmptyStatement.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterEmptyStatement.java new file mode 100644 index 000000000000..ad0a1da16dd9 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterEmptyStatement.java @@ -0,0 +1,9 @@ +// "Use lombok @Setter for 'Foo'" "true" + +import lombok.Setter; + +@Setter +public class Foo { + Long bar; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFieldInInnerClass.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFieldInInnerClass.java new file mode 100644 index 000000000000..d0443c018d79 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFieldInInnerClass.java @@ -0,0 +1,12 @@ +// "Use lombok @Setter for 'InnerClass'" "true" + +import lombok.Setter; + +public class Foo { + @Setter + public class InnerClass { + // Keep this comment + private int bar; + + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFinalField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFinalField.java new file mode 100644 index 000000000000..df831fd2da4a --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFinalField.java @@ -0,0 +1,18 @@ +// "Use lombok @Setter for 'finalField'" "true" + +import lombok.Setter; + +public class Foo { + private int fieldWithoutSetter; + /** + * The final field. + * -- SETTER -- + * Sets The final field. + * + * @param The final field + + */ + @Setter + private final int finalField; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFinalParameter.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFinalParameter.java new file mode 100644 index 000000000000..a44a72105eac --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFinalParameter.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "true" + +import lombok.Setter; + +public class Foo { + @Setter + Long bar; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFullyQualifiedAnnotation.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFullyQualifiedAnnotation.java new file mode 100644 index 000000000000..3ebd4394894f --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFullyQualifiedAnnotation.java @@ -0,0 +1,11 @@ +// "Use lombok @Setter for 'candidateField'" "true" + +public class Setter { + @lombok.Setter + private int candidateField; + private int fieldWithoutSetter; + + public int completelyIrrevelantMethod() { + return 0; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFullyQualifiedThis.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFullyQualifiedThis.java new file mode 100644 index 000000000000..ab7672db0fee --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterFullyQualifiedThis.java @@ -0,0 +1,12 @@ +// "Use lombok @Setter for 'bar'" "true" + +package project; + +import lombok.Setter; + +public class OneFullyQualifiedClass { + @Setter + private int bar; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterInstanceField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterInstanceField.java new file mode 100644 index 000000000000..67dc044786a4 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterInstanceField.java @@ -0,0 +1,18 @@ +// "Use lombok @Setter for 'bar'" "true" + +import lombok.Setter; + +public class CommentedClass { + /*1*/ + /*2*/ + /*3*/ + /*4*/ + /*5*/ + /*6*/ + /*7*/ + /*8*/ + @Setter + private int bar; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterMergeJavaDoc.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterMergeJavaDoc.java new file mode 100644 index 000000000000..cb9dc15a648f --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterMergeJavaDoc.java @@ -0,0 +1,21 @@ +// "Use lombok @Setter for 'processDate'" "true" + +import lombok.Setter; + +import java.util.Date; + +public class MergeJavaDoc { + /** + * The process date. + * -- SETTER -- + * Sets The date. + * It's an instance field. + * + * @param The date + + */ + @Setter + private Date processDate; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterMoveJavaDoc.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterMoveJavaDoc.java new file mode 100644 index 000000000000..d3848c30e4a8 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterMoveJavaDoc.java @@ -0,0 +1,19 @@ +// "Use lombok @Setter for 'creationDate'" "true" + +import lombok.Setter; + +import java.util.Date; + +public class MoveJavaDoc { + /** + * -- SETTER -- + * Sets The date. + * It's an instance field. + * + * @param The date + */ + @Setter + private Date creationDate; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterParamTags.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterParamTags.java new file mode 100644 index 000000000000..43d2b938766e --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterParamTags.java @@ -0,0 +1,20 @@ +// "Use lombok @Setter for 'releaseDate'" "true" + +import lombok.Setter; + +import java.util.Date; + +public class Foo { + /** + * -- SETTER -- + * Sets The date. + * It's an instance field. + * + * @param The date + * @param The value + */ + @Setter + private Date releaseDate; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterParentherizedParameter.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterParentherizedParameter.java new file mode 100644 index 000000000000..a44a72105eac --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterParentherizedParameter.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "true" + +import lombok.Setter; + +public class Foo { + @Setter + Long bar; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterQualifiedThis.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterQualifiedThis.java new file mode 100644 index 000000000000..ed80607ac9f8 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterQualifiedThis.java @@ -0,0 +1,11 @@ +// "Use lombok @Setter for 'bar'" "true" + +import lombok.Setter; + +public class QualifiedClass { + //Keep this comment + @Setter + private int bar; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterStaticField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterStaticField.java new file mode 100644 index 000000000000..1302b3ad7b83 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterStaticField.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "true" + +import lombok.Setter; + +public class Foo { + @Setter + private static char bar; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterThisField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterThisField.java new file mode 100644 index 000000000000..a44a72105eac --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterThisField.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "true" + +import lombok.Setter; + +public class Foo { + @Setter + Long bar; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterUppercaseField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterUppercaseField.java new file mode 100644 index 000000000000..7070d141287e --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/afterUppercaseField.java @@ -0,0 +1,18 @@ +// "Use lombok @Setter for 'Bar'" "true" + +import lombok.Setter; + +import java.util.Date; + +public class Foo { + /** + * -- SETTER -- + * Sets The date. + * + * @param The date + */ + @Setter + private Date Bar; + private int fieldWithoutSetter; + +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAllFields.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAllFields.java new file mode 100644 index 000000000000..c22d08f7b179 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAllFields.java @@ -0,0 +1,14 @@ +// "Use lombok @Setter for 'Foo'" "true" + +public class Foo { + private int bar; + private boolean baz; + + public void setBar(int param) { + bar = param; + } + + public void setBaz(boolean param) { + baz = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnnotatedField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnnotatedField.java new file mode 100644 index 000000000000..967718495d1c --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnnotatedField.java @@ -0,0 +1,13 @@ +// "Use lombok @Setter for 'ClassWithAnnotatedField'" "true" + +import lombok.Setter; + +public class ClassWithAnnotatedField { + private int canditateField; + @Setter + private int annotatedField; + + public void setCanditateField(int param) { + canditateField = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnnotedMethod.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnnotedMethod.java new file mode 100644 index 000000000000..bd812b6c6461 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnnotedMethod.java @@ -0,0 +1,11 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + @Deprecated + public void setBar(int param) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnnoyingQualifier.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnnoyingQualifier.java new file mode 100644 index 000000000000..c309bbdb9d8d --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnnoyingQualifier.java @@ -0,0 +1,9 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + Long bar; + + public void setBar(Long bar) { + this.bar = this.bar; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnotherField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnotherField.java new file mode 100644 index 000000000000..096b552082fe --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAnotherField.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int anotherField; + private int fieldWithoutSetter; + + public void setBar(int param) { + anotherField = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAssignment.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAssignment.java new file mode 100644 index 000000000000..60f2c4987f1e --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeAssignment.java @@ -0,0 +1,9 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + public void setBar(int param) { + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeBadField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeBadField.java new file mode 100644 index 000000000000..d60f8d3409fe --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeBadField.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + public void setBar(int param) { + new Foo().bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeBadOperator.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeBadOperator.java new file mode 100644 index 000000000000..b288d0d399a4 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeBadOperator.java @@ -0,0 +1,9 @@ +// "Use lombok @Setter for 'Foo'" "false" + +public class Foo { + private int count; + + public void setCount(int increment) { + count += increment; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeBooleanField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeBooleanField.java new file mode 100644 index 000000000000..622769c369e7 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeBooleanField.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'valid'" "true" + +public class ClassWithBoolean { + private int fieldWithoutSetter; + private boolean valid; + + public void setValid(boolean param) { + valid = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeDifferentType.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeDifferentType.java new file mode 100644 index 000000000000..8fd364937f3f --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeDifferentType.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private char bar; + private int fieldWithoutSetter; + + public void setBar(int param) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeEmptyStatement.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeEmptyStatement.java new file mode 100644 index 000000000000..dca40199e320 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeEmptyStatement.java @@ -0,0 +1,9 @@ +// "Use lombok @Setter for 'Foo'" "true" + +public class Foo { + Long bar; + + public void setBar(Long param) { + this.bar = param;; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFieldInInnerClass.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFieldInInnerClass.java new file mode 100644 index 000000000000..297be0f81003 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFieldInInnerClass.java @@ -0,0 +1,11 @@ +// "Use lombok @Setter for 'InnerClass'" "true" + +public class Foo { + public class InnerClass { + private int bar; + + public void setBar(int param) { + bar = param; // Keep this comment + } + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFinalField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFinalField.java new file mode 100644 index 000000000000..866865483742 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFinalField.java @@ -0,0 +1,18 @@ +// "Use lombok @Setter for 'finalField'" "true" + +public class Foo { + private int fieldWithoutSetter; + /** + * The final field. + */ + private final int finalField; + + /** + * Sets The final field. + * + * @param The final field + */ + public void setFinalField(int param) { + finalField = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFinalMethod.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFinalMethod.java new file mode 100644 index 000000000000..97f441398b65 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFinalMethod.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + public final void setBar(int param) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFinalParameter.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFinalParameter.java new file mode 100644 index 000000000000..bdbd9c3670ac --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFinalParameter.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "true" + +public class Foo { + Long bar; + private int fieldWithoutSetter; + + public void setBar(final Long param) { + this.bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFullyQualifiedAnnotation.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFullyQualifiedAnnotation.java new file mode 100644 index 000000000000..3a23c7ebcd37 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFullyQualifiedAnnotation.java @@ -0,0 +1,14 @@ +// "Use lombok @Setter for 'candidateField'" "true" + +public class Setter { + private int candidateField; + private int fieldWithoutSetter; + + public void setCandidateField(int param) { + candidateField = param; + } + + public int completelyIrrevelantMethod() { + return 0; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFullyQualifiedThis.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFullyQualifiedThis.java new file mode 100644 index 000000000000..a0fef7a29908 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeFullyQualifiedThis.java @@ -0,0 +1,12 @@ +// "Use lombok @Setter for 'bar'" "true" + +package project; + +public class OneFullyQualifiedClass { + private int bar; + private int fieldWithoutSetter; + + public void setBar(int param) { + project.OneFullyQualifiedClass.this.bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeGetterMethod.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeGetterMethod.java new file mode 100644 index 000000000000..e5559a1170dd --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeGetterMethod.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + public int getBar() { + return bar; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeIgnoredParameter.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeIgnoredParameter.java new file mode 100644 index 000000000000..b1e1fc28cfe3 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeIgnoredParameter.java @@ -0,0 +1,9 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + + public void setBar(int param) { + bar = bar; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeInheritedField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeInheritedField.java new file mode 100644 index 000000000000..232ab0157c40 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeInheritedField.java @@ -0,0 +1,13 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo extends MotherClass { + + public class MotherClass { + private int bar; + private int fieldWithoutSetter; + } + + public void setBar(int param) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeInstanceField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeInstanceField.java new file mode 100644 index 000000000000..a67a2e04290a --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeInstanceField.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "true" + +public class CommentedClass { + private int bar; + private int fieldWithoutSetter; + + /*1*/public /*2*/void /*3*/setBar(int param) /*4*/{ + /*5*/bar/*6*/ = /*7*/param; + /*8*/} +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeMergeJavaDoc.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeMergeJavaDoc.java new file mode 100644 index 000000000000..5c7e17c870c4 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeMergeJavaDoc.java @@ -0,0 +1,22 @@ +// "Use lombok @Setter for 'processDate'" "true" + +import java.util.Date; + +public class MergeJavaDoc { + /** + * The process date. + */ + private Date processDate; + private int fieldWithoutSetter; + + /** + * Sets The date. + * + * It's an instance field. + * + * @param The date + */ + public void setProcessDate(Date param) { + processDate = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeMethodStartingWithDigit.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeMethodStartingWithDigit.java new file mode 100644 index 000000000000..0af9d2b3ffb6 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeMethodStartingWithDigit.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + public void set1Bar(int param) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeMoveJavaDoc.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeMoveJavaDoc.java new file mode 100644 index 000000000000..9749c0b3914a --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeMoveJavaDoc.java @@ -0,0 +1,19 @@ +// "Use lombok @Setter for 'creationDate'" "true" + +import java.util.Date; + +public class MoveJavaDoc { + private Date creationDate; + private int fieldWithoutSetter; + + /** + * Sets The date. + * + * It's an instance field. + * + * @param The date + */ + public void setCreationDate(Date param) { + creationDate = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNoFieldSet.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNoFieldSet.java new file mode 100644 index 000000000000..237c48f01a24 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNoFieldSet.java @@ -0,0 +1,9 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + Long bar; + + public void setBar(Long bar) { + bar = bar; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNonPublicGetter.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNonPublicGetter.java new file mode 100644 index 000000000000..b5fd9dba0670 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNonPublicGetter.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + void setBar(int param) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNonStaticMethod.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNonStaticMethod.java new file mode 100644 index 000000000000..5f7cbc7ea840 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNonStaticMethod.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private static int bar; + private int fieldWithoutSetter; + + public void setBar(int param) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNotWritableLog.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNotWritableLog.java new file mode 100644 index 000000000000..b018eb8a2865 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeNotWritableLog.java @@ -0,0 +1,12 @@ +// "Use lombok @Setter for 'log'" "false" + +import lombok.extern.java.Log; +import java.util.logging.Logger; + +@Log +public class Foo { + private int fieldWithoutSetter; + public void setLog(Logger param) { + log = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeParamTags.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeParamTags.java new file mode 100644 index 000000000000..9f006df9b629 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeParamTags.java @@ -0,0 +1,20 @@ +// "Use lombok @Setter for 'releaseDate'" "true" + +import java.util.Date; + +public class Foo { + private Date releaseDate; + private int fieldWithoutSetter; + + /** + * Sets The date. + * + * It's an instance field. + * + * @param The date + * @param The value + */ + public void setReleaseDate(Date param) { + releaseDate = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeParentherizedParameter.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeParentherizedParameter.java new file mode 100644 index 000000000000..60ea1e71071b --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeParentherizedParameter.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "true" + +public class Foo { + Long bar; + private int fieldWithoutSetter; + + public void setBar(Long param) { + this.bar = (param); + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeQualifiedThis.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeQualifiedThis.java new file mode 100644 index 000000000000..0b222bd472e3 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeQualifiedThis.java @@ -0,0 +1,11 @@ +// "Use lombok @Setter for 'bar'" "true" + +public class QualifiedClass { + private int bar; + private int fieldWithoutSetter; + + public void setBar(int param) { + //Keep this comment + QualifiedClass.this.bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeSetLiteral.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeSetLiteral.java new file mode 100644 index 000000000000..b201d7a4d1b5 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeSetLiteral.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + public void setBar(int param) { + bar = 0; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeShortMethodName.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeShortMethodName.java new file mode 100644 index 000000000000..c46374dcf5ac --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeShortMethodName.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + public void set(int param) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeStaticField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeStaticField.java new file mode 100644 index 000000000000..da64c27b49f0 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeStaticField.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "true" + +public class Foo { + private static char bar; + private int fieldWithoutSetter; + + public static void setBar(char param) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeThisField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeThisField.java new file mode 100644 index 000000000000..c76da09e5340 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeThisField.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "true" + +public class Foo { + Long bar; + private int fieldWithoutSetter; + + public void setBar(Long param) { + this.bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeThrowException.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeThrowException.java new file mode 100644 index 000000000000..704cee846c2f --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeThrowException.java @@ -0,0 +1,12 @@ +// "Use lombok @Setter for 'bar'" "false" + +import javax.validation.constraints.NotNull; + +public class Foo { + private Integer bar; + private int fieldWithoutSetter; + + public void setBar(@NotNull Integer param) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeTwoParameterMethod.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeTwoParameterMethod.java new file mode 100644 index 000000000000..0adb9c8ef030 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeTwoParameterMethod.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + public void setBar(int param, int dummy) { + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeTwoStatements.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeTwoStatements.java new file mode 100644 index 000000000000..83f734946913 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeTwoStatements.java @@ -0,0 +1,11 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + public void setBar(int param) { + bar++; + bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeUppercaseField.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeUppercaseField.java new file mode 100644 index 000000000000..cbe80e56222b --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeUppercaseField.java @@ -0,0 +1,18 @@ +// "Use lombok @Setter for 'Bar'" "true" + +import java.util.Date; + +public class Foo { + private Date Bar; + private int fieldWithoutSetter; + + /** + * Sets The date. + * + * @param The date + */ + + public void setBar(Date param) { + Bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeVarArgParameter.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeVarArgParameter.java new file mode 100644 index 000000000000..0b596ea32192 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeVarArgParameter.java @@ -0,0 +1,9 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + Object bar; + + public void setBar(Object param...) { + this.bar = param; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeZeroParameterMethod.java b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeZeroParameterMethod.java new file mode 100644 index 000000000000..8b4cdb798663 --- /dev/null +++ b/plugins/lombok/testData/inspection/lombokSetterMayBeUsed/beforeZeroParameterMethod.java @@ -0,0 +1,10 @@ +// "Use lombok @Setter for 'bar'" "false" + +public class Foo { + private int bar; + private int fieldWithoutSetter; + + public void setBar() { + bar = bar; + } +} \ No newline at end of file diff --git a/plugins/markdown/core/intellij.markdown.core.iml b/plugins/markdown/core/intellij.markdown.core.iml index e560c6fef3de..302033b920bf 100644 --- a/plugins/markdown/core/intellij.markdown.core.iml +++ b/plugins/markdown/core/intellij.markdown.core.iml @@ -38,6 +38,29 @@ + + + a606dcd52e961402296c9774e92e998becccc5eee0fba79d5d9f9df6862c4718 + + + 58eca9fb0a869391689ffc828b3bd0b19ac76042ff9fab4881eddf7fde76903f + + + 193edf97aefa28b93c5892bdc598bac34fa4c396588030084f290b1440e8b98a + + + 8196efaa89c5f73b00b2b48edad02fcd78524259407c37ab1860737988545cee + + + e395dd1765e3e6bceb0c610706bcf4128de84bd6e65cf1d4adbf998b4114161c + + + f1474d47f4b6b001558ad27b952e35eda5cc7146788877fc52938c6eba24b382 + + + 3ea995b55a4068be22989b70cc29a4d788c2d328d1d50613a7a9afd13fdd2d0a + + diff --git a/plugins/maven/artifact-resolver-m3/intellij.maven.artifactResolver.m3.iml b/plugins/maven/artifact-resolver-m3/intellij.maven.artifactResolver.m3.iml index c9dd7b955e58..d5a873f4c49b 100644 --- a/plugins/maven/artifact-resolver-m3/intellij.maven.artifactResolver.m3.iml +++ b/plugins/maven/artifact-resolver-m3/intellij.maven.artifactResolver.m3.iml @@ -9,7 +9,13 @@ - + + + + ae8dc80232771f8913febfa410c5719e9ba8ded81fb99788e214fd676dbbe13f + + + @@ -22,6 +28,71 @@ + + + ac8e617f951ecde3c4f6bca4922fdd7861500fe7d58289f26ad5adac443075bc + + + 876a76b663db6c7326ad234afe430c473d3261a06b3284f31d5eb4889d1c3084 + + + d8f9f237afc21d8202eedffa29cbf6e9d46c78b3c22b217d16267216988221b9 + + + ac0e62e26b7f690e265ba75667531973b8a2da12b3b0ff102a612f05b42b6faf + + + c867b4e075a4548bf27422542f96b159f94c4e7ffaaf6427b10433afd6a3a38c + + + c6d5e244dd2329971f91b8df666ffe9e0b00a7dd014d6ee073b6f6cb82877f5c + + + 469505f75b8526a338cfd7e0ec841655ae52ddbcc1b36482e97d72f52ce7d890 + + + 45a2c6ff76e12678eaf576bd7a68d028c5a5ba85fdc216a381ea86e9187e1b51 + + + c74327cd5d7b137c8be3591c766271ac8ace1a617518f0410b8a95579f9839b0 + + + d5de4e299be5a79feb1dbe8ff3814034c6e44314b4c00b92ffa8d97576ded5b3 + + + 865511994805827e88f327944a089142bb7f3d88cde271ba3dceb732cb137a93 + + + ae8dc80232771f8913febfa410c5719e9ba8ded81fb99788e214fd676dbbe13f + + + 687799a0ce988bee9e8eb9ae0ba870300adc0114248ad4a4327bdb625d27e010 + + + bf9083fb846993689409b2bdbc735048e53bac6cc32707cde7ef84817b6e9365 + + + 75819b29737c2bee1bfbda1011d455c7036738e0ef32ffbf85ba1d8fa157ceb2 + + + 7fc63378d3e84663619b9bedace9f9fe78b276c2be3c62ca2245449294c84176 + + + 8b909f4ca9788647942f883d4e559bcc642123f7c6bcd3846983a2e465469c33 + + + 259d528a29722cab6349d7e7d432e3fd4877c087ffcb04985a6612e97023bba8 + + + 4df7a6a7be64b35bbccf60b5c115697f9ea3421d22674ae67135dde375fcca1f + + + 3b0559bb8432f28937efe6ca193ef54a8506d0075d73fd7406b9b116c6a11063 + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + @@ -78,6 +149,17 @@ + + + a263933f43e9c273161e0b99f553c33a80a0416ec0bd5dca17d54cf38ae5956f + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + 9897e80ff6c08fc45b5b5ebd81d9e943a1087bdf0ad50cda457d616abbdaacd9 + + @@ -97,7 +179,16 @@ - + + + + c6d5e244dd2329971f91b8df666ffe9e0b00a7dd014d6ee073b6f6cb82877f5c + + + 8b909f4ca9788647942f883d4e559bcc642123f7c6bcd3846983a2e465469c33 + + + @@ -111,7 +202,13 @@ - + + + + 4df7a6a7be64b35bbccf60b5c115697f9ea3421d22674ae67135dde375fcca1f + + + diff --git a/plugins/maven/artifact-resolver-m31/intellij.maven.artifactResolver.m31.iml b/plugins/maven/artifact-resolver-m31/intellij.maven.artifactResolver.m31.iml index 7edb33b370b3..823d41b5abb5 100644 --- a/plugins/maven/artifact-resolver-m31/intellij.maven.artifactResolver.m31.iml +++ b/plugins/maven/artifact-resolver-m31/intellij.maven.artifactResolver.m31.iml @@ -10,6 +10,71 @@ + + + ac8e617f951ecde3c4f6bca4922fdd7861500fe7d58289f26ad5adac443075bc + + + 876a76b663db6c7326ad234afe430c473d3261a06b3284f31d5eb4889d1c3084 + + + d8f9f237afc21d8202eedffa29cbf6e9d46c78b3c22b217d16267216988221b9 + + + ac0e62e26b7f690e265ba75667531973b8a2da12b3b0ff102a612f05b42b6faf + + + c867b4e075a4548bf27422542f96b159f94c4e7ffaaf6427b10433afd6a3a38c + + + c6d5e244dd2329971f91b8df666ffe9e0b00a7dd014d6ee073b6f6cb82877f5c + + + 469505f75b8526a338cfd7e0ec841655ae52ddbcc1b36482e97d72f52ce7d890 + + + 45a2c6ff76e12678eaf576bd7a68d028c5a5ba85fdc216a381ea86e9187e1b51 + + + c74327cd5d7b137c8be3591c766271ac8ace1a617518f0410b8a95579f9839b0 + + + d5de4e299be5a79feb1dbe8ff3814034c6e44314b4c00b92ffa8d97576ded5b3 + + + 865511994805827e88f327944a089142bb7f3d88cde271ba3dceb732cb137a93 + + + ae8dc80232771f8913febfa410c5719e9ba8ded81fb99788e214fd676dbbe13f + + + 687799a0ce988bee9e8eb9ae0ba870300adc0114248ad4a4327bdb625d27e010 + + + bf9083fb846993689409b2bdbc735048e53bac6cc32707cde7ef84817b6e9365 + + + 75819b29737c2bee1bfbda1011d455c7036738e0ef32ffbf85ba1d8fa157ceb2 + + + 7fc63378d3e84663619b9bedace9f9fe78b276c2be3c62ca2245449294c84176 + + + 8b909f4ca9788647942f883d4e559bcc642123f7c6bcd3846983a2e465469c33 + + + 259d528a29722cab6349d7e7d432e3fd4877c087ffcb04985a6612e97023bba8 + + + 4df7a6a7be64b35bbccf60b5c115697f9ea3421d22674ae67135dde375fcca1f + + + 3b0559bb8432f28937efe6ca193ef54a8506d0075d73fd7406b9b116c6a11063 + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + @@ -66,6 +131,17 @@ + + + a263933f43e9c273161e0b99f553c33a80a0416ec0bd5dca17d54cf38ae5956f + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + 9897e80ff6c08fc45b5b5ebd81d9e943a1087bdf0ad50cda457d616abbdaacd9 + + @@ -85,7 +161,13 @@ - + + + + 4df7a6a7be64b35bbccf60b5c115697f9ea3421d22674ae67135dde375fcca1f + + + @@ -97,7 +179,13 @@ - + + + + e220097cffad96c2963ab12652ff8833ec6f40143d509f0a2ea59d22209b6ecd + + + diff --git a/plugins/maven/artifact-resolver/common/intellij.maven.artifactResolver.common.iml b/plugins/maven/artifact-resolver/common/intellij.maven.artifactResolver.common.iml index 14dfa36d34f1..b9ed47c2e7a1 100644 --- a/plugins/maven/artifact-resolver/common/intellij.maven.artifactResolver.common.iml +++ b/plugins/maven/artifact-resolver/common/intellij.maven.artifactResolver.common.iml @@ -9,7 +9,16 @@ - + + + + c6d5e244dd2329971f91b8df666ffe9e0b00a7dd014d6ee073b6f6cb82877f5c + + + 8b909f4ca9788647942f883d4e559bcc642123f7c6bcd3846983a2e465469c33 + + + diff --git a/plugins/maven/intellij.maven.iml b/plugins/maven/intellij.maven.iml index 6f2f2c80559b..3c2a90722ffe 100644 --- a/plugins/maven/intellij.maven.iml +++ b/plugins/maven/intellij.maven.iml @@ -41,7 +41,13 @@ - + + + + 779d4a6878026fdaae6786683e33883d58f77df245fe38a7b444da12772190fc + + + @@ -84,7 +90,13 @@ - + + + + b9e8bb167267aa21219d9319d568d3e48198dde3756368e6102879d638248931 + + + diff --git a/plugins/maven/maven-event-listener/intellij.maven.server.eventListener.iml b/plugins/maven/maven-event-listener/intellij.maven.server.eventListener.iml index db589106da5d..f948b477de1b 100644 --- a/plugins/maven/maven-event-listener/intellij.maven.server.eventListener.iml +++ b/plugins/maven/maven-event-listener/intellij.maven.server.eventListener.iml @@ -12,6 +12,86 @@ + + + 070d55ec5a6f3e4a785564283a9704bb39a93f1a2f89cdf60a3b899fde563bf9 + + + 15abde67fa7ea1e573e1f68c34921e995f0971351aaf1fb96790688ff510efcd + + + e4f569be53a076424e784222e7088f1827fcb2ef18d409132b3cda2fd92799e2 + + + b4da54d52e2996a8a77c4db1ca8e98fc31792f07eeff695776f00ecffc3d5b60 + + + 462a0d711a979c44791b97422ec4e91300ae555a598f684f116d725a2b9d297b + + + 6dbcc3d3d1dfb34df46c1ddb080fdd09fb899c80207016419cf13236c6b10399 + + + 1f702928f2233c6ecdf308fbd8f2932ea287c7062183d3c8364b0db7e9c4445d + + + 14cae18fd7125901b12fc914e30ea26ad9bd43dbd399dd6e8fcbc6c754ef2c9c + + + 6909cb229489e693df7960678528800a1759625835a1cb939c37b051c22193c3 + + + d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99 + + + f46962583d812cd4459a4cc963113b9c52f1f9b169172354693bc9efa0b3e3cb + + + 2cafa2629da49edd54eb4df6d15f628c2d80eec293f37cd561f1fe78e7bcff9d + + + 9a84f5863407acf2bf9cf280cd02f5a518952a386de61df3b8c5db8cfdec725d + + + 3f74c7c7b9c924769cf3c5b4d52d21aa63e9a2ccbf16f5d26c30ebb31b99699d + + + 9e9a57439a98034732e94d841bb7065b56e3a065654361ca9cc07135e9fbe17c + + + f5cfe0d88e8276971db4ecff0e4186d5f2ec5fdb1b6bb8c2f359fdc4b43eb8b2 + + + 1f10b2204cc77c919301f20ff90461c3df1b6e6cb148be1c2d22107f4851d423 + + + a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f + + + 66e87705a818da44eb080a7bb1fc431de987754b4f92aa85f69991bfc677d40d + + + aba7980581027ad5fc74a27ee4d64aad74932fdb32694967242d03fc50290d1f + + + 0f31c44b275f87e56d46a582ce96d03b9e2ab344cf87c4e268b34d3ad046beab + + + b2931d41740490a8d931cbe0cfe9ac20deb66cca606e679f52522f7f534c9fd7 + + + 2b3a6ca5f19a9ad490bc233f45e68d3093c8c01b4acc3c1d14bad4ca7c7ff438 + + + 3b0559bb8432f28937efe6ca193ef54a8506d0075d73fd7406b9b116c6a11063 + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + + 734c8356420cc8e30c795d64fd1fcd5d44ea9d90342a2cc3262c5158fbc6d98b + + @@ -79,6 +159,14 @@ + + + b378ffc35e7f7125b3c5f3a461d4591ae1685e3c781392f0c854ed7b7581d6d2 + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + diff --git a/plugins/maven/maven-server-indexer/intellij.maven.server.indexer.iml b/plugins/maven/maven-server-indexer/intellij.maven.server.indexer.iml index de6c9af66654..f240b1c9e9d3 100644 --- a/plugins/maven/maven-server-indexer/intellij.maven.server.indexer.iml +++ b/plugins/maven/maven-server-indexer/intellij.maven.server.indexer.iml @@ -12,6 +12,47 @@ + + + 7f69b1b75cc171ec37a9377cf590077c10b6153337236a7a766df70eb9ec7786 + + + d3ef575e3e4979678dc01bf1dcce51021493b4d11fb7f1be8ad982877c16a1c0 + + + 78a61d0b843c1cf1fe5be380a4d3a4c1602d3fbba4ca1185da8797c9bb115483 + + + 23abf022a19e609fe3ca421ab6b6868a3250974d31c5b92f9879d97c127a77b8 + + + 11fb2e90da5b4e6a6c26120bb80a2937a20a585d32236ed7c277048ba65f07ca + + + 28bee2711947cf3a9957f3f77132ce37457894c1fb468b0a20e9a95788b11c87 + + + 1cdcc5a2d9cf4ffaf12fbf24bc2a18f2469cd295b60470ae8b97d1aa85dbad6f + + + 38e72688eef81efffb9c5ea68918f4d1adb2eb0de64ce6a8222abee036eb63cf + + + c8e92e01b7443b2fd1698ac7b260b632197175143e13f0364b6f7258b9447307 + + + b948478fe2e8e7f94fa7f533a14a526720701fe98627214c93d924faa4be78de + + + 5c9df7e7f6122172d5d27ce3efb2bc58fc7f423c2fb7468bf75315d742ebb181 + + + 3468ec7ca9ee97878e61f26905546cdd709de778b8884777516a1af2d4a32e4e + + + 7c9eeb30ac1941ea9bdf76c08c162ed98c005913e5bff66de3f1027a304546dc + + @@ -52,7 +93,118 @@ - + + + + 4b518631aa5bda90a90ef122fba5288438bbf160fcd628246638092fe3050e10 + + + a5ce7648e89403e3b45a951648ee10d934b869001048ef05327be412860b50c5 + + + 5a80a24569a0eb383b4da05ea1d306b37753ae111e833bef3a2585c78555e0e0 + + + 6c93c6336365e59841f4b879d08e027ba8f853f83889e2b374ced4de9c667749 + + + 873139960c4c780176dda580b003a2c4bf82188bdce5bb99234e224ef7acfceb + + + 9a7f1b5c5a9effd61eadfd8731452a2f76a8e79111fac391ef75ea801bea203a + + + b2e17c30158bcabad967c29ccc4f2c4e10065b03eedefdb1d8f901ddd3d12ca5 + + + bb01f1d30929db0d8ab4bbce0e3ed3a924fa1c22dd0dc26b0ff7e39a067c2f8d + + + be0e20f86b22835a49a355de8912260dff0a7cd47c4605506cd286ed25a34508 + + + be2e329e86e7547d66d18fb206a2f8e06363774647aaf7da776cc19f589a0d4d + + + bb2baf84e3d6c584681220947160e6d53c2bca34208c0295bdc74ab4233d396c + + + 9f7a733bc6a8c91265c669e8a268e7800578cd43e1435088e07d73a9b067d1be + + + 17aaebe6e3e59df8cb5b4ec210196f7084637312b9bc4ff14cb77ad1ae3c381b + + + d0b28ed944058ba4f9be4b54c25d6d5269cc4f3f3c49aa450d4dc2f7e0d552f6 + + + 17441a39045ac19bc4a8068fb7284facebf6337754bf2bf8f26a76b5f98ed108 + + + cdcad9355b625743f40e4cead9a96353404e010c39c808d23b044be331afa251 + + + 7925d9c5a0e2040d24b8fae3f612eb399cbffe5838b33ba368777dc7bddf6dda + + + f877d304660ac2a142f3865badfc971dec7ed73c747c7f8d5d2f5139ca736513 + + + 7e4c61096d70826f20f7a7d55c59a5528e7aa5ad247ee2dfe544e4dd25f6a784 + + + 5909b396ca3a2be10d0eea32c74ef78d816e1b4ead21de1d78de1f890d033e04 + + + c5994010bcdce1d2bd603a4d50c47191ddbd7875d1157b23aaa26d33c82fda13 + + + 0f4f5fb28609a4d2b38b7f7128be7cf9b541f25283d71b4e56066d99683aafff + + + 0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08 + + + f7b8f8fed176b9cf6831b98cb07320d7fbe91d99b29999f752c3821dfe45bdc8 + + + 766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7 + + + a40b2ce6d8551e5b90b1bf637064303f32944d61b52ab2014e38699df573941b + + + 03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8 + + + 2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6 + + + 2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + 76d174792540e2775af94d03d10fb2d3c776e2cd0ac0ebf427d3e570072bb9ce + + + 52f77c5ec49f787c9c417ebed5d6efd9922f44a202f217376e4f94c0d74f3549 + + + b3b5412ce17889103ea564bcdfcf9fb3dfa540344ffeac6b538a73c9d7182662 + + + bde3617ce9b5bcf9584126046080043af6a4b3baea40a3b153f02e7bbc32acac + + + dac807f65b07698ff39b1b07bfef3d87ae3fd46d91bbf8a2bc02b2a831616f68 + + + 3624f8474c1af46d75f98bc097d7864a323c81b3808aa43689a6e1c601c027be + + + @@ -135,6 +287,11 @@ + + + c7daff38f15c754f609854a01365ced5ad182b5e12d88a6f6ad534c030147cca + + @@ -151,6 +308,119 @@ + + + 7816a7d7c9a5c64b77a7fd1ebe203a1ce92b924638dd2216f81ea5bcebea6abc + + + 2aa061856e5e124facf7bf16831069015f98406969a7ba534e1ee557950d6680 + + + a20edcd3b38675827209068c544426f2ef03ed506d226f1d4c99a734948f8e36 + + + 42106c60e08eb147c294722b9c26bad26a148636ef244ab8d6092f5a09fa409e + + + 2f4c835b52311df922f8a8eb057843de5485088b234ccd03e478b9066b5e6bfc + + + 405eef6fc9188241ec88579c3e473f5c8997455c69bcd62e142492aca15106bc + + + 1345f11ba606d15603d6740551a8c21947c0215640770ec67271fe78bea97cf5 + + + d20e5d26c19c04199c73fd4f0b6caebf4bbdc6b872a4504c5e71a192751d9464 + + + 3ba9c619893c767db0f9c3e826d5118b57c35229301bcd16d865a89cec16a7e5 + + + 1205a1f229999170dcadcfb885a278ad0bc2295540a251f4c438f887ead7bbd9 + + + 1c98a4ec9eb0cb86ecf01710aa75c0346ee3f96edc6edeabcb21ed984120e154 + + + 7fc63378d3e84663619b9bedace9f9fe78b276c2be3c62ca2245449294c84176 + + + 27e426d73f8662b47f60df0e43439b3dec2909c42b89175a6e4431dfed3edafd + + + c938e4d8cdf0674496749a87e6d3b29aa41b1b35a39898a1ade2bc9eae214c17 + + + 1c5c5ac5e8f29aefc8faa051ffa14eccd85b9e20f4bb35dc82fba7d5da50d326 + + + ff690ffc550b7ada3a4b79ef4ca89bf002b24f43a13a35d10195c3bba63d7654 + + + 288149850d8d131763df4151f7e443fd2739e48510a6e4cfe49ca082c76130fa + + + f54a0a28ce3d62af0e1cfe41dde616f645c28e452e77f77b78bc36e74d5e1a69 + + + 1ac88accde99ed71e65253bd130868c0e654f940f01ade073b895eb2f817cf06 + + + ba03294ee53e7ba31838e4950f280d033c7744c6c7b31253afc75aa351fbd989 + + + 3b1a46b4bc26a0176acaf99312ff2f3a631faf3224b0996af546aa48bd73c647 + + + e17e706c6f03c453f6000599cab607c2af5f1cc6e3a3b1e6fce27e5ef4999eab + + + f5ecc6eaa4a32ee0c115d31525f588f491b2cc75fdeb4ed3c0c662c12ac0c32f + + + a65e27aefbe74102d73cd7e3c5c7637021d294a9e7f33132f3c782a76714d0a3 + + + fb3160e1e3a7852b441016dbcc97a34e3cf4eeb8ceb9e82edf2729439858f080 + + + 240113a2f22fd1f0b182b32baecf0e7876b3a8e41f3c4da3335eeb9ffb24b9f4 + + + 7d95ad21733b060bfda2142b62439a196bde7644f9f127c299ae86d92179b518 + + + 3b0559bb8432f28937efe6ca193ef54a8506d0075d73fd7406b9b116c6a11063 + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + + 759079b9cf0cddae5ba06c96fd72347d82d0bc1d903c95d398c96522b139e470 + + + 82a584c58bd6a1b13861e2d4cc194b5afc09ca0adad9fda741f16337dcda2e96 + + + fe30825245d2336c859dc38d60c0fc5f3668dbf29cd586828d2b5667ec355b91 + + + eeeae917917144a68a741d4c0dff66aa5c5c5fd85593ff217bced3fc8ca783b8 + + + b4c4a0dbeacad54306a1ae230eff5ab45d58e3ab88c86ab7245d3a0772be57ab + + + ec92dae810034f4b46dbb16ef4364a4013b0efb24a8c5dd67435cae46a290d8e + + + 2c73b940c91250bc98346926270f13a6a10bb6e29d2c9316a70d134e382c873e + + + 2b4d8d4e098e86aa5f905ec81c46751d218b16afd3f7fc02b64f80dd20fffa20 + + diff --git a/plugins/maven/maven3-server-common/intellij.maven.server.m3.common.iml b/plugins/maven/maven3-server-common/intellij.maven.server.m3.common.iml index 6aa654ced581..123028003f45 100644 --- a/plugins/maven/maven3-server-common/intellij.maven.server.m3.common.iml +++ b/plugins/maven/maven3-server-common/intellij.maven.server.m3.common.iml @@ -13,6 +13,11 @@ + + + 171035740322f96bd8c155cfb6050962dd61d7976a494c0aac6d46b3c83174c4 + + @@ -30,6 +35,11 @@ + + + 9d43a28d0758914fdcea28a436601ac26d06a3b55d283bb6be0321ccd3631a58 + + @@ -54,6 +64,11 @@ + + + dbb8c53ccc0b16a9dd8370d6e7de63102468caedac1e5fa2eb418319a6875293 + + @@ -70,6 +85,20 @@ + + + 3a00a78157a82fff778334764255642585127443e0b3da56bcdb6f8a0f910220 + + + 112e06e6acc1405ad3ba518442e835d1d42758ef31f0bbbdb32aa1e15a17d10f + + + 162ff0cc80445307de05f5e0ce9c014e8cd22cfbd2ed610ae39806e4592c5255 + + + cf9bb9e523696557c20bd4c7f41b6adda6074c4da85a7070af2facbab28afaca + + @@ -103,6 +132,101 @@ + + + 8f1a5d4daff952dabeb3acaa0aa642903702a1aa8b442fcd7a07a8cf9e3db48b + + + a1bf0c7856afd1f1b9c81c22818328fb7a796b4047010e08f2e859d1896080a9 + + + a7295f062b54d0cbd513ffbb6d21c9bc9e21d9904547f299831236a988e50ab3 + + + 56affafea9c76168bbc5b8ee9d26dd2dbe95b8185b70d6b2a46dd9fc39d0dd53 + + + 053655dc2890f119cb13ddb90b1888b9cfcf1cea3a374c0656d53595b4f37542 + + + 271a82555c399d9b06c7751a802c3b919081a06b7c9b839bd70e93ea2df386e3 + + + da73e32b58132e64daf12269fd9d011c0b303f234840f179908725a632b6b57c + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + + 3d5a0e77cde76d386b18c7400db1eb16aacef02e031ecd0d954477aeccc92155 + + + dac807f65b07698ff39b1b07bfef3d87ae3fd46d91bbf8a2bc02b2a831616f68 + + + c7611780b8456e2b29284b8c0d37cdd5358facdc1091d64ab46a2feddd2cb6ae + + + 0062a08b463314a1b5f8eb1a56207efb830fbdf547c42a3191eb146c4db39b1a + + + d4d15a6d473d78608412818c091b3c01d37bdf4f0e453156a19724af843a03ea + + + 3ba9c619893c767db0f9c3e826d5118b57c35229301bcd16d865a89cec16a7e5 + + + a10418348d234968600ccb1d988efcbbd08716e1d96936ccc1880e7d22513474 + + + c6935e0b7d362ed4ca768c9b71d5d4d98788ff0a79c0d2bb954c221a078b166b + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + b2931d41740490a8d931cbe0cfe9ac20deb66cca606e679f52522f7f534c9fd7 + + + 3e7d265ef4e9ade0f5de998961c6cac634cbf3fbdb839bb50a3a50b2ffbba7f8 + + + 18c4a0095d5c1da6b817592e767bb23d29dd2f560ad74df75ff3961dbde25b79 + + + 21702a5beccf3731ecdd6ed87f8fd0ae2bb7856b12fe91585b5513840722b0c3 + + + 6be437d670dffa24bac4187bc1567c34fab04fc569836f8b45b9d79cbfd493ea + + + a7c2d81cd7d6df38e2997bf09507e0bca6fa85dfb635de4bf28a7c501cb574f4 + + + aaa41b53ed4fcc13b3d719d85f45b0fba21ee026dd4b625dd82210a28ee8e2fe + + + 0ffa0ad084ebff5712540a7b7ea0abda487c53d3a18f78c98d1a3675dab9bf61 + + + e003802501574637f7abdc4e83e6d509a31e9ff825d12da6d1e419acf9688705 + + + 98045f5ecd802d6a96ba00394f8cb61259f9ac781ec2cb51ca0cb7b2c94ac720 + + + 1f10b2204cc77c919301f20ff90461c3df1b6e6cb148be1c2d22107f4851d423 + + + a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f + + + a7fee9435db716bff593e9fb5622bcf9f25e527196485929b0cd4065c43e61df + + + 21beff005c5b5754911b85f3a60480341b29a2faf1cf3b56260e6b646081a54f + + @@ -179,6 +303,32 @@ + + + cb4a9a054a20f5b9fcdd9734e97804779714fa5d62b30a0f5b5e99084f9954b0 + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + f7b8f8fed176b9cf6831b98cb07320d7fbe91d99b29999f752c3821dfe45bdc8 + + + 766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7 + + + a40b2ce6d8551e5b90b1bf637064303f32944d61b52ab2014e38699df573941b + + + 03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8 + + + 2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6 + + + 2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d + + @@ -209,7 +359,13 @@ - + + + + b85d6c2a6b4c29e90fa7c5d94b21fe796f9c6857870268b56904765126bae718 + + + diff --git a/plugins/maven/maven3-server-impl/intellij.maven.server.m3.impl.iml b/plugins/maven/maven3-server-impl/intellij.maven.server.m3.impl.iml index 41233e0e722b..66df7cd7f4f6 100644 --- a/plugins/maven/maven3-server-impl/intellij.maven.server.m3.impl.iml +++ b/plugins/maven/maven3-server-impl/intellij.maven.server.m3.impl.iml @@ -14,6 +14,92 @@ + + + 2653f603b4aa7b521d8ad850c88a34dafd64aa79d7650399daa719de71cd1329 + + + 15abde67fa7ea1e573e1f68c34921e995f0971351aaf1fb96790688ff510efcd + + + 734c8356420cc8e30c795d64fd1fcd5d44ea9d90342a2cc3262c5158fbc6d98b + + + 6909cb229489e693df7960678528800a1759625835a1cb939c37b051c22193c3 + + + 462a0d711a979c44791b97422ec4e91300ae555a598f684f116d725a2b9d297b + + + d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99 + + + e4f569be53a076424e784222e7088f1827fcb2ef18d409132b3cda2fd92799e2 + + + 1f702928f2233c6ecdf308fbd8f2932ea287c7062183d3c8364b0db7e9c4445d + + + 070d55ec5a6f3e4a785564283a9704bb39a93f1a2f89cdf60a3b899fde563bf9 + + + b4da54d52e2996a8a77c4db1ca8e98fc31792f07eeff695776f00ecffc3d5b60 + + + 6dbcc3d3d1dfb34df46c1ddb080fdd09fb899c80207016419cf13236c6b10399 + + + 14cae18fd7125901b12fc914e30ea26ad9bd43dbd399dd6e8fcbc6c754ef2c9c + + + f46962583d812cd4459a4cc963113b9c52f1f9b169172354693bc9efa0b3e3cb + + + 2cafa2629da49edd54eb4df6d15f628c2d80eec293f37cd561f1fe78e7bcff9d + + + 9a84f5863407acf2bf9cf280cd02f5a518952a386de61df3b8c5db8cfdec725d + + + 3f74c7c7b9c924769cf3c5b4d52d21aa63e9a2ccbf16f5d26c30ebb31b99699d + + + 9e9a57439a98034732e94d841bb7065b56e3a065654361ca9cc07135e9fbe17c + + + b2931d41740490a8d931cbe0cfe9ac20deb66cca606e679f52522f7f534c9fd7 + + + 3b0559bb8432f28937efe6ca193ef54a8506d0075d73fd7406b9b116c6a11063 + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + + 0f31c44b275f87e56d46a582ce96d03b9e2ab344cf87c4e268b34d3ad046beab + + + aba7980581027ad5fc74a27ee4d64aad74932fdb32694967242d03fc50290d1f + + + f5cfe0d88e8276971db4ecff0e4186d5f2ec5fdb1b6bb8c2f359fdc4b43eb8b2 + + + 1f10b2204cc77c919301f20ff90461c3df1b6e6cb148be1c2d22107f4851d423 + + + a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f + + + 66e87705a818da44eb080a7bb1fc431de987754b4f92aa85f69991bfc677d40d + + + 2b3a6ca5f19a9ad490bc233f45e68d3093c8c01b4acc3c1d14bad4ca7c7ff438 + + + 930b2e409513be03864d7a66e22dfdf5c086725e22ba3cf57ad45ed8af02996d + + @@ -84,7 +170,13 @@ - + + + + dbb8c53ccc0b16a9dd8370d6e7de63102468caedac1e5fa2eb418319a6875293 + + + @@ -97,6 +189,86 @@ + + + 070d55ec5a6f3e4a785564283a9704bb39a93f1a2f89cdf60a3b899fde563bf9 + + + 15abde67fa7ea1e573e1f68c34921e995f0971351aaf1fb96790688ff510efcd + + + e4f569be53a076424e784222e7088f1827fcb2ef18d409132b3cda2fd92799e2 + + + b4da54d52e2996a8a77c4db1ca8e98fc31792f07eeff695776f00ecffc3d5b60 + + + 462a0d711a979c44791b97422ec4e91300ae555a598f684f116d725a2b9d297b + + + 6dbcc3d3d1dfb34df46c1ddb080fdd09fb899c80207016419cf13236c6b10399 + + + 1f702928f2233c6ecdf308fbd8f2932ea287c7062183d3c8364b0db7e9c4445d + + + 14cae18fd7125901b12fc914e30ea26ad9bd43dbd399dd6e8fcbc6c754ef2c9c + + + 6909cb229489e693df7960678528800a1759625835a1cb939c37b051c22193c3 + + + d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99 + + + f46962583d812cd4459a4cc963113b9c52f1f9b169172354693bc9efa0b3e3cb + + + 2cafa2629da49edd54eb4df6d15f628c2d80eec293f37cd561f1fe78e7bcff9d + + + 9a84f5863407acf2bf9cf280cd02f5a518952a386de61df3b8c5db8cfdec725d + + + 3f74c7c7b9c924769cf3c5b4d52d21aa63e9a2ccbf16f5d26c30ebb31b99699d + + + 9e9a57439a98034732e94d841bb7065b56e3a065654361ca9cc07135e9fbe17c + + + f5cfe0d88e8276971db4ecff0e4186d5f2ec5fdb1b6bb8c2f359fdc4b43eb8b2 + + + 1f10b2204cc77c919301f20ff90461c3df1b6e6cb148be1c2d22107f4851d423 + + + a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f + + + 66e87705a818da44eb080a7bb1fc431de987754b4f92aa85f69991bfc677d40d + + + aba7980581027ad5fc74a27ee4d64aad74932fdb32694967242d03fc50290d1f + + + 0f31c44b275f87e56d46a582ce96d03b9e2ab344cf87c4e268b34d3ad046beab + + + b2931d41740490a8d931cbe0cfe9ac20deb66cca606e679f52522f7f534c9fd7 + + + 2b3a6ca5f19a9ad490bc233f45e68d3093c8c01b4acc3c1d14bad4ca7c7ff438 + + + 3b0559bb8432f28937efe6ca193ef54a8506d0075d73fd7406b9b116c6a11063 + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + + 734c8356420cc8e30c795d64fd1fcd5d44ea9d90342a2cc3262c5158fbc6d98b + + @@ -163,7 +335,112 @@ - + + + + 6e1736c08f9798ed74efcdcdc435c640aca08af9b8c268dd7ea8ee8a3fef30a6 + + + e4f569be53a076424e784222e7088f1827fcb2ef18d409132b3cda2fd92799e2 + + + 070d55ec5a6f3e4a785564283a9704bb39a93f1a2f89cdf60a3b899fde563bf9 + + + 15abde67fa7ea1e573e1f68c34921e995f0971351aaf1fb96790688ff510efcd + + + b4da54d52e2996a8a77c4db1ca8e98fc31792f07eeff695776f00ecffc3d5b60 + + + 6dbcc3d3d1dfb34df46c1ddb080fdd09fb899c80207016419cf13236c6b10399 + + + 1f702928f2233c6ecdf308fbd8f2932ea287c7062183d3c8364b0db7e9c4445d + + + f46962583d812cd4459a4cc963113b9c52f1f9b169172354693bc9efa0b3e3cb + + + 2cafa2629da49edd54eb4df6d15f628c2d80eec293f37cd561f1fe78e7bcff9d + + + 9a84f5863407acf2bf9cf280cd02f5a518952a386de61df3b8c5db8cfdec725d + + + 3f74c7c7b9c924769cf3c5b4d52d21aa63e9a2ccbf16f5d26c30ebb31b99699d + + + 9e9a57439a98034732e94d841bb7065b56e3a065654361ca9cc07135e9fbe17c + + + 19393891be59b6feaf7e308bd8a3843b4e552c10cdb687ebffd7695634a250a8 + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + 0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08 + + + aba7980581027ad5fc74a27ee4d64aad74932fdb32694967242d03fc50290d1f + + + 14cae18fd7125901b12fc914e30ea26ad9bd43dbd399dd6e8fcbc6c754ef2c9c + + + 6909cb229489e693df7960678528800a1759625835a1cb939c37b051c22193c3 + + + 462a0d711a979c44791b97422ec4e91300ae555a598f684f116d725a2b9d297b + + + d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99 + + + 2653f603b4aa7b521d8ad850c88a34dafd64aa79d7650399daa719de71cd1329 + + + 930b2e409513be03864d7a66e22dfdf5c086725e22ba3cf57ad45ed8af02996d + + + 0f31c44b275f87e56d46a582ce96d03b9e2ab344cf87c4e268b34d3ad046beab + + + b2931d41740490a8d931cbe0cfe9ac20deb66cca606e679f52522f7f534c9fd7 + + + f5cfe0d88e8276971db4ecff0e4186d5f2ec5fdb1b6bb8c2f359fdc4b43eb8b2 + + + 1f10b2204cc77c919301f20ff90461c3df1b6e6cb148be1c2d22107f4851d423 + + + a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f + + + 66e87705a818da44eb080a7bb1fc431de987754b4f92aa85f69991bfc677d40d + + + 2b3a6ca5f19a9ad490bc233f45e68d3093c8c01b4acc3c1d14bad4ca7c7ff438 + + + 3b0559bb8432f28937efe6ca193ef54a8506d0075d73fd7406b9b116c6a11063 + + + 114859861ff10f987b880d6f34e3215274af3cc92b3a73831c84d596e37c6511 + + + fe30825245d2336c859dc38d60c0fc5f3668dbf29cd586828d2b5667ec355b91 + + + e7cd8951956d349b568b7ccfd4f5b2529a8c113e67c32b028f52ffda371259d9 + + + 734c8356420cc8e30c795d64fd1fcd5d44ea9d90342a2cc3262c5158fbc6d98b + + + @@ -242,6 +519,14 @@ + + + b378ffc35e7f7125b3c5f3a461d4591ae1685e3c781392f0c854ed7b7581d6d2 + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + @@ -260,7 +545,16 @@ - + + + + 112e06e6acc1405ad3ba518442e835d1d42758ef31f0bbbdb32aa1e15a17d10f + + + b7554a41499282e3b2226a22aff3ebe984f7e159798c461d917c1b829b130cd1 + + + @@ -275,6 +569,20 @@ + + + 3a00a78157a82fff778334764255642585127443e0b3da56bcdb6f8a0f910220 + + + 112e06e6acc1405ad3ba518442e835d1d42758ef31f0bbbdb32aa1e15a17d10f + + + 162ff0cc80445307de05f5e0ce9c014e8cd22cfbd2ed610ae39806e4592c5255 + + + cf9bb9e523696557c20bd4c7f41b6adda6074c4da85a7070af2facbab28afaca + + diff --git a/plugins/maven/maven30-server-impl/intellij.maven.server.m30.impl.iml b/plugins/maven/maven30-server-impl/intellij.maven.server.m30.impl.iml index b69da2f5e353..5f13b9a48c68 100644 --- a/plugins/maven/maven30-server-impl/intellij.maven.server.m30.impl.iml +++ b/plugins/maven/maven30-server-impl/intellij.maven.server.m30.impl.iml @@ -14,6 +14,71 @@ + + + ac8e617f951ecde3c4f6bca4922fdd7861500fe7d58289f26ad5adac443075bc + + + 876a76b663db6c7326ad234afe430c473d3261a06b3284f31d5eb4889d1c3084 + + + d8f9f237afc21d8202eedffa29cbf6e9d46c78b3c22b217d16267216988221b9 + + + ac0e62e26b7f690e265ba75667531973b8a2da12b3b0ff102a612f05b42b6faf + + + c867b4e075a4548bf27422542f96b159f94c4e7ffaaf6427b10433afd6a3a38c + + + c6d5e244dd2329971f91b8df666ffe9e0b00a7dd014d6ee073b6f6cb82877f5c + + + 469505f75b8526a338cfd7e0ec841655ae52ddbcc1b36482e97d72f52ce7d890 + + + 45a2c6ff76e12678eaf576bd7a68d028c5a5ba85fdc216a381ea86e9187e1b51 + + + c74327cd5d7b137c8be3591c766271ac8ace1a617518f0410b8a95579f9839b0 + + + d5de4e299be5a79feb1dbe8ff3814034c6e44314b4c00b92ffa8d97576ded5b3 + + + 865511994805827e88f327944a089142bb7f3d88cde271ba3dceb732cb137a93 + + + ae8dc80232771f8913febfa410c5719e9ba8ded81fb99788e214fd676dbbe13f + + + 687799a0ce988bee9e8eb9ae0ba870300adc0114248ad4a4327bdb625d27e010 + + + bf9083fb846993689409b2bdbc735048e53bac6cc32707cde7ef84817b6e9365 + + + 75819b29737c2bee1bfbda1011d455c7036738e0ef32ffbf85ba1d8fa157ceb2 + + + 7fc63378d3e84663619b9bedace9f9fe78b276c2be3c62ca2245449294c84176 + + + 8b909f4ca9788647942f883d4e559bcc642123f7c6bcd3846983a2e465469c33 + + + 259d528a29722cab6349d7e7d432e3fd4877c087ffcb04985a6612e97023bba8 + + + 4df7a6a7be64b35bbccf60b5c115697f9ea3421d22674ae67135dde375fcca1f + + + 3b0559bb8432f28937efe6ca193ef54a8506d0075d73fd7406b9b116c6a11063 + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + @@ -69,7 +134,13 @@ - + + + + b2931d41740490a8d931cbe0cfe9ac20deb66cca606e679f52522f7f534c9fd7 + + + @@ -82,6 +153,77 @@ + + + 1e821ef210f502d541741e950399bf7db385dfbb07d6b09ab9d65ff3ff0567fc + + + 876a76b663db6c7326ad234afe430c473d3261a06b3284f31d5eb4889d1c3084 + + + 45a2c6ff76e12678eaf576bd7a68d028c5a5ba85fdc216a381ea86e9187e1b51 + + + d8f9f237afc21d8202eedffa29cbf6e9d46c78b3c22b217d16267216988221b9 + + + c6d5e244dd2329971f91b8df666ffe9e0b00a7dd014d6ee073b6f6cb82877f5c + + + ac8e617f951ecde3c4f6bca4922fdd7861500fe7d58289f26ad5adac443075bc + + + ac0e62e26b7f690e265ba75667531973b8a2da12b3b0ff102a612f05b42b6faf + + + c867b4e075a4548bf27422542f96b159f94c4e7ffaaf6427b10433afd6a3a38c + + + 469505f75b8526a338cfd7e0ec841655ae52ddbcc1b36482e97d72f52ce7d890 + + + c74327cd5d7b137c8be3591c766271ac8ace1a617518f0410b8a95579f9839b0 + + + d5de4e299be5a79feb1dbe8ff3814034c6e44314b4c00b92ffa8d97576ded5b3 + + + 865511994805827e88f327944a089142bb7f3d88cde271ba3dceb732cb137a93 + + + ae8dc80232771f8913febfa410c5719e9ba8ded81fb99788e214fd676dbbe13f + + + 687799a0ce988bee9e8eb9ae0ba870300adc0114248ad4a4327bdb625d27e010 + + + 259d528a29722cab6349d7e7d432e3fd4877c087ffcb04985a6612e97023bba8 + + + 3b0559bb8432f28937efe6ca193ef54a8506d0075d73fd7406b9b116c6a11063 + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + + 8b909f4ca9788647942f883d4e559bcc642123f7c6bcd3846983a2e465469c33 + + + 7fc63378d3e84663619b9bedace9f9fe78b276c2be3c62ca2245449294c84176 + + + bf9083fb846993689409b2bdbc735048e53bac6cc32707cde7ef84817b6e9365 + + + 75819b29737c2bee1bfbda1011d455c7036738e0ef32ffbf85ba1d8fa157ceb2 + + + 4df7a6a7be64b35bbccf60b5c115697f9ea3421d22674ae67135dde375fcca1f + + + f65d8d59d71bca18ffa259b5a6de67697bc65b9ff1142c7bb4417ab4b1cacd92 + + @@ -142,6 +284,83 @@ + + + 020cdfeff9bc0f1eaba30ce87ecbe51ab25ceda5aba77d0f5aa560e35f3d55ce + + + d8f9f237afc21d8202eedffa29cbf6e9d46c78b3c22b217d16267216988221b9 + + + ac8e617f951ecde3c4f6bca4922fdd7861500fe7d58289f26ad5adac443075bc + + + 876a76b663db6c7326ad234afe430c473d3261a06b3284f31d5eb4889d1c3084 + + + ac0e62e26b7f690e265ba75667531973b8a2da12b3b0ff102a612f05b42b6faf + + + c867b4e075a4548bf27422542f96b159f94c4e7ffaaf6427b10433afd6a3a38c + + + c6d5e244dd2329971f91b8df666ffe9e0b00a7dd014d6ee073b6f6cb82877f5c + + + c74327cd5d7b137c8be3591c766271ac8ace1a617518f0410b8a95579f9839b0 + + + d5de4e299be5a79feb1dbe8ff3814034c6e44314b4c00b92ffa8d97576ded5b3 + + + 865511994805827e88f327944a089142bb7f3d88cde271ba3dceb732cb137a93 + + + ae8dc80232771f8913febfa410c5719e9ba8ded81fb99788e214fd676dbbe13f + + + 687799a0ce988bee9e8eb9ae0ba870300adc0114248ad4a4327bdb625d27e010 + + + 7fc63378d3e84663619b9bedace9f9fe78b276c2be3c62ca2245449294c84176 + + + 469505f75b8526a338cfd7e0ec841655ae52ddbcc1b36482e97d72f52ce7d890 + + + 45a2c6ff76e12678eaf576bd7a68d028c5a5ba85fdc216a381ea86e9187e1b51 + + + 1e821ef210f502d541741e950399bf7db385dfbb07d6b09ab9d65ff3ff0567fc + + + f65d8d59d71bca18ffa259b5a6de67697bc65b9ff1142c7bb4417ab4b1cacd92 + + + 8b909f4ca9788647942f883d4e559bcc642123f7c6bcd3846983a2e465469c33 + + + 259d528a29722cab6349d7e7d432e3fd4877c087ffcb04985a6612e97023bba8 + + + bf9083fb846993689409b2bdbc735048e53bac6cc32707cde7ef84817b6e9365 + + + 75819b29737c2bee1bfbda1011d455c7036738e0ef32ffbf85ba1d8fa157ceb2 + + + 4df7a6a7be64b35bbccf60b5c115697f9ea3421d22674ae67135dde375fcca1f + + + 3b0559bb8432f28937efe6ca193ef54a8506d0075d73fd7406b9b116c6a11063 + + + 114859861ff10f987b880d6f34e3215274af3cc92b3a73831c84d596e37c6511 + + + e7cd8951956d349b568b7ccfd4f5b2529a8c113e67c32b028f52ffda371259d9 + + @@ -206,6 +425,17 @@ + + + a263933f43e9c273161e0b99f553c33a80a0416ec0bd5dca17d54cf38ae5956f + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + 9897e80ff6c08fc45b5b5ebd81d9e943a1087bdf0ad50cda457d616abbdaacd9 + + @@ -225,7 +455,13 @@ - + + + + dbb8c53ccc0b16a9dd8370d6e7de63102468caedac1e5fa2eb418319a6875293 + + + diff --git a/plugins/maven/maven36-server-impl/intellij.maven.server.m36.impl.iml b/plugins/maven/maven36-server-impl/intellij.maven.server.m36.impl.iml index cf1fdb24c531..5060f33f6141 100644 --- a/plugins/maven/maven36-server-impl/intellij.maven.server.m36.impl.iml +++ b/plugins/maven/maven36-server-impl/intellij.maven.server.m36.impl.iml @@ -16,6 +16,101 @@ + + + 8f1a5d4daff952dabeb3acaa0aa642903702a1aa8b442fcd7a07a8cf9e3db48b + + + a1bf0c7856afd1f1b9c81c22818328fb7a796b4047010e08f2e859d1896080a9 + + + a7295f062b54d0cbd513ffbb6d21c9bc9e21d9904547f299831236a988e50ab3 + + + 56affafea9c76168bbc5b8ee9d26dd2dbe95b8185b70d6b2a46dd9fc39d0dd53 + + + 053655dc2890f119cb13ddb90b1888b9cfcf1cea3a374c0656d53595b4f37542 + + + 271a82555c399d9b06c7751a802c3b919081a06b7c9b839bd70e93ea2df386e3 + + + da73e32b58132e64daf12269fd9d011c0b303f234840f179908725a632b6b57c + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + + 3d5a0e77cde76d386b18c7400db1eb16aacef02e031ecd0d954477aeccc92155 + + + dac807f65b07698ff39b1b07bfef3d87ae3fd46d91bbf8a2bc02b2a831616f68 + + + c7611780b8456e2b29284b8c0d37cdd5358facdc1091d64ab46a2feddd2cb6ae + + + 0062a08b463314a1b5f8eb1a56207efb830fbdf547c42a3191eb146c4db39b1a + + + d4d15a6d473d78608412818c091b3c01d37bdf4f0e453156a19724af843a03ea + + + 3ba9c619893c767db0f9c3e826d5118b57c35229301bcd16d865a89cec16a7e5 + + + a10418348d234968600ccb1d988efcbbd08716e1d96936ccc1880e7d22513474 + + + c6935e0b7d362ed4ca768c9b71d5d4d98788ff0a79c0d2bb954c221a078b166b + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + b2931d41740490a8d931cbe0cfe9ac20deb66cca606e679f52522f7f534c9fd7 + + + 3e7d265ef4e9ade0f5de998961c6cac634cbf3fbdb839bb50a3a50b2ffbba7f8 + + + 18c4a0095d5c1da6b817592e767bb23d29dd2f560ad74df75ff3961dbde25b79 + + + 21702a5beccf3731ecdd6ed87f8fd0ae2bb7856b12fe91585b5513840722b0c3 + + + 6be437d670dffa24bac4187bc1567c34fab04fc569836f8b45b9d79cbfd493ea + + + a7c2d81cd7d6df38e2997bf09507e0bca6fa85dfb635de4bf28a7c501cb574f4 + + + aaa41b53ed4fcc13b3d719d85f45b0fba21ee026dd4b625dd82210a28ee8e2fe + + + 0ffa0ad084ebff5712540a7b7ea0abda487c53d3a18f78c98d1a3675dab9bf61 + + + e003802501574637f7abdc4e83e6d509a31e9ff825d12da6d1e419acf9688705 + + + 98045f5ecd802d6a96ba00394f8cb61259f9ac781ec2cb51ca0cb7b2c94ac720 + + + 1f10b2204cc77c919301f20ff90461c3df1b6e6cb148be1c2d22107f4851d423 + + + a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f + + + a7fee9435db716bff593e9fb5622bcf9f25e527196485929b0cd4065c43e61df + + + 21beff005c5b5754911b85f3a60480341b29a2faf1cf3b56260e6b646081a54f + + @@ -92,6 +187,32 @@ + + + cb4a9a054a20f5b9fcdd9734e97804779714fa5d62b30a0f5b5e99084f9954b0 + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + f7b8f8fed176b9cf6831b98cb07320d7fbe91d99b29999f752c3821dfe45bdc8 + + + 766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7 + + + a40b2ce6d8551e5b90b1bf637064303f32944d61b52ab2014e38699df573941b + + + 03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8 + + + 2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6 + + + 2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d + + @@ -121,7 +242,121 @@ - + + + + c7611780b8456e2b29284b8c0d37cdd5358facdc1091d64ab46a2feddd2cb6ae + + + a1bf0c7856afd1f1b9c81c22818328fb7a796b4047010e08f2e859d1896080a9 + + + 053655dc2890f119cb13ddb90b1888b9cfcf1cea3a374c0656d53595b4f37542 + + + 271a82555c399d9b06c7751a802c3b919081a06b7c9b839bd70e93ea2df386e3 + + + e003802501574637f7abdc4e83e6d509a31e9ff825d12da6d1e419acf9688705 + + + da73e32b58132e64daf12269fd9d011c0b303f234840f179908725a632b6b57c + + + 5a15fdba22669e0fdd06e10dcce6320879e1f7398fbc910cd0677b50672a78c4 + + + 56affafea9c76168bbc5b8ee9d26dd2dbe95b8185b70d6b2a46dd9fc39d0dd53 + + + 21702a5beccf3731ecdd6ed87f8fd0ae2bb7856b12fe91585b5513840722b0c3 + + + 3d5a0e77cde76d386b18c7400db1eb16aacef02e031ecd0d954477aeccc92155 + + + 0062a08b463314a1b5f8eb1a56207efb830fbdf547c42a3191eb146c4db39b1a + + + a7295f062b54d0cbd513ffbb6d21c9bc9e21d9904547f299831236a988e50ab3 + + + 3e7d265ef4e9ade0f5de998961c6cac634cbf3fbdb839bb50a3a50b2ffbba7f8 + + + 18c4a0095d5c1da6b817592e767bb23d29dd2f560ad74df75ff3961dbde25b79 + + + aaa41b53ed4fcc13b3d719d85f45b0fba21ee026dd4b625dd82210a28ee8e2fe + + + 6be437d670dffa24bac4187bc1567c34fab04fc569836f8b45b9d79cbfd493ea + + + d4d15a6d473d78608412818c091b3c01d37bdf4f0e453156a19724af843a03ea + + + a7c2d81cd7d6df38e2997bf09507e0bca6fa85dfb635de4bf28a7c501cb574f4 + + + 3ba9c619893c767db0f9c3e826d5118b57c35229301bcd16d865a89cec16a7e5 + + + a10418348d234968600ccb1d988efcbbd08716e1d96936ccc1880e7d22513474 + + + 98045f5ecd802d6a96ba00394f8cb61259f9ac781ec2cb51ca0cb7b2c94ac720 + + + 1f10b2204cc77c919301f20ff90461c3df1b6e6cb148be1c2d22107f4851d423 + + + a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f + + + c6935e0b7d362ed4ca768c9b71d5d4d98788ff0a79c0d2bb954c221a078b166b + + + 158fd8f52d2a4b4ce4293ac2b833bb2427f5ddfe30df4ae0fd4675a1038a3b79 + + + 0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08 + + + f7b8f8fed176b9cf6831b98cb07320d7fbe91d99b29999f752c3821dfe45bdc8 + + + 766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7 + + + a40b2ce6d8551e5b90b1bf637064303f32944d61b52ab2014e38699df573941b + + + 03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8 + + + 2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6 + + + 2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + 0ffa0ad084ebff5712540a7b7ea0abda487c53d3a18f78c98d1a3675dab9bf61 + + + b2931d41740490a8d931cbe0cfe9ac20deb66cca606e679f52522f7f534c9fd7 + + + a7fee9435db716bff593e9fb5622bcf9f25e527196485929b0cd4065c43e61df + + + dac807f65b07698ff39b1b07bfef3d87ae3fd46d91bbf8a2bc02b2a831616f68 + + + @@ -205,7 +440,127 @@ - + + + + e41b031c1e5bc23dc94b67f678644d549b15461361789d592c54cc3939829945 + + + 053655dc2890f119cb13ddb90b1888b9cfcf1cea3a374c0656d53595b4f37542 + + + 271a82555c399d9b06c7751a802c3b919081a06b7c9b839bd70e93ea2df386e3 + + + e003802501574637f7abdc4e83e6d509a31e9ff825d12da6d1e419acf9688705 + + + c7611780b8456e2b29284b8c0d37cdd5358facdc1091d64ab46a2feddd2cb6ae + + + 21702a5beccf3731ecdd6ed87f8fd0ae2bb7856b12fe91585b5513840722b0c3 + + + 3d5a0e77cde76d386b18c7400db1eb16aacef02e031ecd0d954477aeccc92155 + + + 3e7d265ef4e9ade0f5de998961c6cac634cbf3fbdb839bb50a3a50b2ffbba7f8 + + + aaa41b53ed4fcc13b3d719d85f45b0fba21ee026dd4b625dd82210a28ee8e2fe + + + d4d15a6d473d78608412818c091b3c01d37bdf4f0e453156a19724af843a03ea + + + c6935e0b7d362ed4ca768c9b71d5d4d98788ff0a79c0d2bb954c221a078b166b + + + 0062a08b463314a1b5f8eb1a56207efb830fbdf547c42a3191eb146c4db39b1a + + + a1bf0c7856afd1f1b9c81c22818328fb7a796b4047010e08f2e859d1896080a9 + + + a7295f062b54d0cbd513ffbb6d21c9bc9e21d9904547f299831236a988e50ab3 + + + 56affafea9c76168bbc5b8ee9d26dd2dbe95b8185b70d6b2a46dd9fc39d0dd53 + + + 6be437d670dffa24bac4187bc1567c34fab04fc569836f8b45b9d79cbfd493ea + + + a7c2d81cd7d6df38e2997bf09507e0bca6fa85dfb635de4bf28a7c501cb574f4 + + + 3ba9c619893c767db0f9c3e826d5118b57c35229301bcd16d865a89cec16a7e5 + + + a10418348d234968600ccb1d988efcbbd08716e1d96936ccc1880e7d22513474 + + + 158fd8f52d2a4b4ce4293ac2b833bb2427f5ddfe30df4ae0fd4675a1038a3b79 + + + 0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08 + + + f7b8f8fed176b9cf6831b98cb07320d7fbe91d99b29999f752c3821dfe45bdc8 + + + 766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7 + + + a40b2ce6d8551e5b90b1bf637064303f32944d61b52ab2014e38699df573941b + + + 03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8 + + + 2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6 + + + 2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f + + + 0ffa0ad084ebff5712540a7b7ea0abda487c53d3a18f78c98d1a3675dab9bf61 + + + b2931d41740490a8d931cbe0cfe9ac20deb66cca606e679f52522f7f534c9fd7 + + + 98045f5ecd802d6a96ba00394f8cb61259f9ac781ec2cb51ca0cb7b2c94ac720 + + + 1f10b2204cc77c919301f20ff90461c3df1b6e6cb148be1c2d22107f4851d423 + + + a7fee9435db716bff593e9fb5622bcf9f25e527196485929b0cd4065c43e61df + + + da73e32b58132e64daf12269fd9d011c0b303f234840f179908725a632b6b57c + + + 114859861ff10f987b880d6f34e3215274af3cc92b3a73831c84d596e37c6511 + + + 18c4a0095d5c1da6b817592e767bb23d29dd2f560ad74df75ff3961dbde25b79 + + + fd3c7c9545a9cdb2051d1f9155c4f76b1e4ac5a57304404a6eedb578ffba7328 + + + dac807f65b07698ff39b1b07bfef3d87ae3fd46d91bbf8a2bc02b2a831616f68 + + + @@ -293,7 +648,13 @@ - + + + + dbb8c53ccc0b16a9dd8370d6e7de63102468caedac1e5fa2eb418319a6875293 + + + diff --git a/plugins/maven/maven40-server-impl/intellij.maven.server.m40.iml b/plugins/maven/maven40-server-impl/intellij.maven.server.m40.iml index b20fb21fe182..9f1bb848f17d 100644 --- a/plugins/maven/maven40-server-impl/intellij.maven.server.m40.iml +++ b/plugins/maven/maven40-server-impl/intellij.maven.server.m40.iml @@ -10,104 +10,235 @@ - - + + + + + 81a06d512e4a1b68e227464d6d96fe3356518bede58198ad1ef22d8721796ab2 + + + ed63449dad9170c63170f491dfc9fad249acbede944b35fca53f6311f12b8d7c + + + b6a31e1ea51f06d78062ea4ded5a60618a3544d6b50fb737213532a005340a7b + + + 3388f4d0465f5a7e9a6264baf506da1b052c51f7cc10b7ce73f09723e6cf1d92 + + + c89323b70dd491a3ef21432dba4cad2b74e26caaafd77178b0f15313fe0bd5f0 + + + a5b13d1a8efb8e9240d9a32b7a7da87b5dfff563e7737f7005d334af861f1f62 + + + e1316fb941d660ec92885bcd407b23c2f6cafde2d65f2e20980d61313cce95cb + + + 270cd703b48c6e5c8c691f1875f22d62d22cfe072c73ae2f5814d83d68c1da0b + + + 6f7bb4fc853fd6f6bf115d0536862f03c639d43cc379467b31a2910db26a92b4 + + + 0636b12b3fb6924a5ecc9a0290387f00d9bb332b3531aebbd321a386dbbb0db1 + + + 60386af2373f63337a778adfb3fee9429bf4c52f46b5f1caa132d5e67468c77f + + + 4f5355706da95d9d0eab3cacd8b1d5a653cd44845d80e1c73ef358cf502a5a62 + + + 7368f6af6b963d46423ffad099dc645ab4e7ca468999dad50ce5c7333dab43a6 + + + 77277a532f540344c86ca85ef1b478e0ff4248099fb3374ca1d08aa7826ff172 + + + 1be0bedfcc9fbdb260bb764cb15f9c926bdc7d5457d6994ff0a5bc9ce1dfc908 + + + 56e0bbc15b10f7b0b8ee550b8b1f473bfe9d621f63fb0e714f8e2fc25649412b + + + 37a2fd46f515005f5410157f1e98e0fc42900ff8b3fc5b662d5095df1617ce5d + + + c4f6f3868f5b280cc7e268f0f95e1bb1d2a824afe92a8029e861be7ec48b1272 + + + 62a69d27a939ef29fe4a2b0da7d595418aa6057c783987a36b8c1c73e7ad9245 + + + d73b1c35e6f8d1af61e2bf2e4f4a3ab1866ab06d2e19eefd8556afec9968357c + + + bb417eb74dc47fda54f0f94a78dcae0db1d4771fcdc88b0364d2d3e0826622a1 + + + 9b62bcfc352a2ec87da8b01e37c952a54d358bbb1af3f212648aeafe7ab2dbb5 + + + 17fd8e65a16e61bb6dce6937c0cb69d772d7d5d08c30ed7565ea74a568c1222c + + + 37cde0eb7edaea329643ba5a6e95808cdf6678e17327042bfb6679b8f68ab72f + + + 01b5489914f198da93c66b0c1d159d0e0f948bfc80a2dd36d872b1bc1b6825d8 + + + 916bf00f01a10233cac87d2abb1b900279147af29e573f2cdde3e25cedd409dd + + + 12461c417ed4302e03412fcc4f0941bc6d5c26dc1bb0fac4ba2bd4000226d42f + + + a2c9970ce72afceece098433e5501c4dd332494389353a17d9e48072e32db80f + + + 5976b25b1400e35087d6eceb33d77e3f1cd50efd37725b290270f9f68aabbee0 + + + c90964538cfd79a02b77d61db9738c5e04d3844e5f2effb442b8be33622adcd2 + + + 4130e50bfac48099c860f0d903b91860c81a249c90f38245f8fed58fc817bc26 + + + 0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08 + + + e6dd072f9d3fe02a4600688380bd422bdac184caf6fe2418cfdd0934f09432aa + + + a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26 + + + 91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff + + + e04ba5195bcd555dc95650f7cc614d151e4bcd52d29a10b8aa2197f3ab89ab9b + + + 52f77c5ec49f787c9c417ebed5d6efd9922f44a202f217376e4f94c0d74f3549 + + + 9500d303ce467e26d129dda8559c3f3a91277d41ab49d2c4b4a5779536a62fc1 + + + bde3617ce9b5bcf9584126046080043af6a4b3baea40a3b153f02e7bbc32acac + + + 873139960c4c780176dda580b003a2c4bf82188bdce5bb99234e224ef7acfceb + + + 9a7f1b5c5a9effd61eadfd8731452a2f76a8e79111fac391ef75ea801bea203a + + + b3b5412ce17889103ea564bcdfcf9fb3dfa540344ffeac6b538a73c9d7182662 + + + d3ef575e3e4979678dc01bf1dcce51021493b4d11fb7f1be8ad982877c16a1c0 + + + bc8bb01fc0fad250385706e20f927ddcff6173f6339b387dc879237752567ac6 + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - diff --git a/plugins/maven/maven40-server-impl/src/com/intellij/maven/server/m40/Maven40ServerEmbedderImpl.java b/plugins/maven/maven40-server-impl/src/com/intellij/maven/server/m40/Maven40ServerEmbedderImpl.java index d2ddceb4ff9d..e540f097aed4 100644 --- a/plugins/maven/maven40-server-impl/src/com/intellij/maven/server/m40/Maven40ServerEmbedderImpl.java +++ b/plugins/maven/maven40-server-impl/src/com/intellij/maven/server/m40/Maven40ServerEmbedderImpl.java @@ -18,6 +18,7 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.InvalidRepositoryException; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.cli.MavenCli; import org.apache.maven.cli.internal.extension.model.CoreExtension; import org.apache.maven.execution.*; @@ -35,7 +36,6 @@ import org.apache.maven.plugin.LegacySupport; import org.apache.maven.plugin.internal.PluginDependenciesResolver; import org.apache.maven.project.MavenProject; import org.apache.maven.project.ProjectBuildingException; -import org.apache.maven.repository.RepositorySystem; import org.apache.maven.session.scope.internal.SessionScope; import org.apache.maven.settings.Settings; import org.apache.maven.settings.building.DefaultSettingsBuilderFactory; @@ -83,7 +83,7 @@ public class Maven40ServerEmbedderImpl extends MavenServerEmbeddedBase { private final boolean myAlwaysUpdateSnapshots; - @NotNull private final RepositorySystem myRepositorySystem; + @NotNull private final MavenRepositorySystem myRepositorySystem; @NotNull private final Maven40ImporterSpy myImporterSpy; @@ -194,7 +194,7 @@ public class Maven40ServerEmbedderImpl extends MavenServerEmbeddedBase { ReflectionUtilRt.getField(cliRequestClass, cliRequest, Properties.class, "userProperties") ); - myRepositorySystem = getComponent(RepositorySystem.class); + myRepositorySystem = getComponent(MavenRepositorySystem.class); Maven40ImporterSpy importerSpy = getComponentIfExists(Maven40ImporterSpy.class); @@ -442,6 +442,9 @@ public class Maven40ServerEmbedderImpl extends MavenServerEmbeddedBase { MavenExecutionRequest result = new DefaultMavenExecutionRequest(); try { + injectDefaultRepositories(result); + injectDefaultPluginRepositories(result); + getComponent(MavenExecutionRequestPopulator.class).populateFromSettings(result, myMavenSettings); result.setPom(file); @@ -476,6 +479,32 @@ public class Maven40ServerEmbedderImpl extends MavenServerEmbeddedBase { } } + private void injectDefaultRepositories(MavenExecutionRequest request) + throws MavenExecutionRequestPopulationException { + Set definedRepositories = myRepositorySystem.getRepoIds(request.getRemoteRepositories()); + + if (!definedRepositories.contains(MavenRepositorySystem.DEFAULT_REMOTE_REPO_ID)) { + try { + request.addRemoteRepository(myRepositorySystem.createDefaultRemoteRepository(request)); + } catch (Exception e) { + throw new MavenExecutionRequestPopulationException("Cannot create default remote repository.", e); + } + } + } + + private void injectDefaultPluginRepositories(MavenExecutionRequest request) + throws MavenExecutionRequestPopulationException { + Set definedRepositories = myRepositorySystem.getRepoIds(request.getPluginArtifactRepositories()); + + if (!definedRepositories.contains(MavenRepositorySystem.DEFAULT_REMOTE_REPO_ID)) { + try { + request.addPluginArtifactRepository(myRepositorySystem.createDefaultRemoteRepository(request)); + } catch (Exception e) { + throw new MavenExecutionRequestPopulationException("Cannot create default remote repository.", e); + } + } + } + @NotNull private static File getMultimoduleProjectDir(@Nullable File file) { File mavenMultiModuleProjectDirectory; @@ -926,8 +955,8 @@ public class Maven40ServerEmbedderImpl extends MavenServerEmbeddedBase { List result = map2ArtifactRepositories(repositories); if (getComponent(LegacySupport.class).getRepositorySession() == null) { myRepositorySystem.injectMirror(result, myMavenSettings.getMirrors()); - myRepositorySystem.injectProxy(result, myMavenSettings.getProxies()); - myRepositorySystem.injectAuthentication(result, myMavenSettings.getServers()); + //myRepositorySystem.injectProxy(result, myMavenSettings.getProxies()); + //myRepositorySystem.injectAuthentication(result, myMavenSettings.getServers()); } return result; } @@ -946,7 +975,7 @@ public class Maven40ServerEmbedderImpl extends MavenServerEmbeddedBase { } private ArtifactRepository buildArtifactRepository(Repository repo) throws InvalidRepositoryException { - RepositorySystem repositorySystem = myRepositorySystem; + MavenRepositorySystem repositorySystem = myRepositorySystem; RepositorySystemSession session = getComponent(LegacySupport.class).getRepositorySession(); ArtifactRepository repository = repositorySystem.buildArtifactRepository(repo); diff --git a/plugins/maven/maven40-server-impl/src/com/intellij/maven/server/m40/utils/Maven40ProfileUtil.java b/plugins/maven/maven40-server-impl/src/com/intellij/maven/server/m40/utils/Maven40ProfileUtil.java index 4d4030a3327b..7bf95ffd58ce 100644 --- a/plugins/maven/maven40-server-impl/src/com/intellij/maven/server/m40/utils/Maven40ProfileUtil.java +++ b/plugins/maven/maven40-server-impl/src/com/intellij/maven/server/m40/utils/Maven40ProfileUtil.java @@ -16,6 +16,7 @@ import org.apache.maven.model.profile.activation.JdkVersionProfileActivator; import org.apache.maven.model.profile.activation.OperatingSystemProfileActivator; import org.apache.maven.model.profile.activation.ProfileActivator; import org.apache.maven.model.profile.activation.PropertyProfileActivator; +import org.apache.maven.model.root.DefaultRootLocator; import org.apache.maven.project.MavenProject; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.model.MavenConstants; @@ -66,7 +67,8 @@ public final class Maven40ProfileUtil { if (expandedProfilesCache == null) { DefaultPathTranslator pathTranslator = new DefaultPathTranslator(); DefaultUrlNormalizer urlNormalizer = new DefaultUrlNormalizer(); - StringVisitorModelInterpolator interpolator = new StringVisitorModelInterpolator(pathTranslator, urlNormalizer); + DefaultRootLocator rootLocator = new DefaultRootLocator(); + StringVisitorModelInterpolator interpolator = new StringVisitorModelInterpolator(pathTranslator, urlNormalizer, rootLocator); expandedProfilesCache = doInterpolate(interpolator, nativeModel, basedir).getProfiles(); } Profile eachExpandedProfile = expandedProfilesCache.get(i); @@ -168,7 +170,8 @@ public final class Maven40ProfileUtil { Model nativeModel = Maven40ModelConverter.toNativeModel(model); DefaultPathTranslator pathTranslator = new DefaultPathTranslator(); DefaultUrlNormalizer urlNormalizer = new DefaultUrlNormalizer(); - StringVisitorModelInterpolator interpolator = new StringVisitorModelInterpolator(pathTranslator, urlNormalizer); + DefaultRootLocator rootLocator = new DefaultRootLocator(); + StringVisitorModelInterpolator interpolator = new StringVisitorModelInterpolator(pathTranslator, urlNormalizer, rootLocator); Model result = doInterpolate(interpolator, nativeModel, basedir); MyDefaultPathTranslator myPathTranslator = new MyDefaultPathTranslator(pathTranslator); myPathTranslator.alignToBaseDirectory(result, basedir); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compatibility/MavenCompatibilityProjectImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compatibility/MavenCompatibilityProjectImportingTest.java index ba2ac4820a9d..9db532c0d0a3 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compatibility/MavenCompatibilityProjectImportingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compatibility/MavenCompatibilityProjectImportingTest.java @@ -4,6 +4,7 @@ package org.jetbrains.idea.maven.compatibility; import com.intellij.maven.testFramework.MavenImportingTestCase; import com.intellij.maven.testFramework.MavenWrapperTestFixture; import com.intellij.openapi.module.LanguageLevelUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.VersionComparatorUtil; @@ -34,7 +35,7 @@ public class MavenCompatibilityProjectImportingTest extends MavenImportingTestCa @Parameterized.Parameters(name = "with Maven-{0}") public static List getMavenVersions() { return Arrays.asList( - new String[]{"4.0.0-alpha-5"}, + new String[]{"4.0.0-alpha-7"}, new String[]{"3.9.2"}, new String[]{"3.9.1"}, new String[]{"3.9.0"}, @@ -408,7 +409,17 @@ public class MavenCompatibilityProjectImportingTest extends MavenImportingTestCa """); assertModules("project"); - var expectedVersion = VersionComparatorUtil.compare(myMavenVersion, "3.9.0") >= 0 ? LanguageLevel.JDK_1_7 : LanguageLevel.JDK_1_5; + LanguageLevel expectedVersion; + if (isMaven4()) { + expectedVersion = VersionComparatorUtil.compare(myMavenVersion, "4.0.0-alpha-7") >= 0 ? LanguageLevel.JDK_1_8 : LanguageLevel.JDK_1_7; + } + else { + expectedVersion = VersionComparatorUtil.compare(myMavenVersion, "3.9.0") >= 0 ? LanguageLevel.JDK_1_7 : LanguageLevel.JDK_1_5; + } assertEquals(expectedVersion, LanguageLevelUtil.getCustomLanguageLevel(getModule("project"))); } + + protected boolean isMaven4() { + return StringUtil.compareVersionNumbers(myMavenVersion, "4.0") >= 0; + } } diff --git a/plugins/maven/testFramework/intellij.maven.testFramework.iml b/plugins/maven/testFramework/intellij.maven.testFramework.iml index 68aa99a9bfda..84047cacef21 100644 --- a/plugins/maven/testFramework/intellij.maven.testFramework.iml +++ b/plugins/maven/testFramework/intellij.maven.testFramework.iml @@ -11,7 +11,13 @@ - + + + + 164e026e01338638e3433e4f6efbda52ed9a64a94ced649c3d0bbe02a7c61282 + + + diff --git a/plugins/maven/testFramework/src/com/intellij/maven/testFramework/MavenMultiVersionImportingTestCase.java b/plugins/maven/testFramework/src/com/intellij/maven/testFramework/MavenMultiVersionImportingTestCase.java index aa057be27ed3..ffb1eb8be784 100644 --- a/plugins/maven/testFramework/src/com/intellij/maven/testFramework/MavenMultiVersionImportingTestCase.java +++ b/plugins/maven/testFramework/src/com/intellij/maven/testFramework/MavenMultiVersionImportingTestCase.java @@ -30,7 +30,7 @@ import java.util.List; @RunWith(Parameterized.class) public abstract class MavenMultiVersionImportingTestCase extends MavenImportingTestCase { - public static final String[] MAVEN_VERSIONS = new String[]{"bundled", "4.0.0-alpha-5"}; + public static final String[] MAVEN_VERSIONS = new String[]{"bundled", "4.0.0-alpha-7"}; @Parameterized.Parameter(0) public String myMavenVersion; @Nullable diff --git a/plugins/performanceTesting/intellij.performanceTesting.iml b/plugins/performanceTesting/intellij.performanceTesting.iml index abbadb862a5f..f5fa7fd677c7 100644 --- a/plugins/performanceTesting/intellij.performanceTesting.iml +++ b/plugins/performanceTesting/intellij.performanceTesting.iml @@ -25,6 +25,11 @@ + + + efbca93df18f3eb16964a92d8342f0674dd5d90da575ef8e04ef2e4eabec6910 + + diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java index 34f99b1094db..e6566740d9ef 100644 --- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java @@ -203,13 +203,13 @@ public class PropertiesUtil { @NotNull public static @Nls String getPresentableLocale(@NotNull Locale locale) { List names = new ArrayList<>(); - if (locale.getDisplayLanguage() != null) { + if (StringUtil.isNotEmpty(locale.getDisplayLanguage())) { names.add(locale.getDisplayLanguage()); } - if (locale.getDisplayCountry() != null) { + if (StringUtil.isNotEmpty(locale.getDisplayCountry())) { names.add(locale.getDisplayCountry()); } - if (locale.getDisplayVariant() != null) { + if (StringUtil.isNotEmpty(locale.getDisplayVariant())) { names.add(locale.getDisplayVariant()); } return names.isEmpty() ? "" : " (" + StringUtil.join(names, "/") + ")"; diff --git a/plugins/refactoring-detector/intellij.vcs.refactoring.detector.iml b/plugins/refactoring-detector/intellij.vcs.refactoring.detector.iml index 728b6450ef2c..6b145cabaf6b 100644 --- a/plugins/refactoring-detector/intellij.vcs.refactoring.detector.iml +++ b/plugins/refactoring-detector/intellij.vcs.refactoring.detector.iml @@ -20,6 +20,17 @@ + + + 4f82b5f024ce886685560b3a4f7467d164e707956da0d9a822b03b2df6f53e32 + + + 97ea3971d83a4503799375bd7b33ec590081476f6e2999cf1cb9fec5c6f3411e + + + 48c13df97048b3535fe1c044bafa31629f23f9c01259f215127edccc1467aa1b + + diff --git a/plugins/search-everywhere-ml/ranking/intellij.searchEverywhereMl.ranking.iml b/plugins/search-everywhere-ml/ranking/intellij.searchEverywhereMl.ranking.iml index 53a54df21b79..ccbc49aecfdc 100644 --- a/plugins/search-everywhere-ml/ranking/intellij.searchEverywhereMl.ranking.iml +++ b/plugins/search-everywhere-ml/ranking/intellij.searchEverywhereMl.ranking.iml @@ -24,7 +24,13 @@ - + + + + e0717acecdebc0c23e71a73a16c7a4287fd790a800cc6e2f2213e018a315bfcb + + + @@ -36,7 +42,13 @@ - + + + + 7411cc9090801d3e8684ca170846de4aa60ce27da70d1b0af2c23e7d3efb1f05 + + + @@ -48,7 +60,13 @@ - + + + + 36728a93eed083d88318628ecc341a8d0928ec934d9b56e07f81610e7996c74b + + + @@ -60,7 +78,13 @@ - + + + + fc794f0ec27897a11c43075ec94e2fc2df4e5c5b6d50f1e22312efd1d343597b + + + @@ -72,7 +96,13 @@ - + + + + 8269c5e164ad03387ef0df89197d9c3444f8a1c039e52ebfbfff37ca69a380f4 + + + @@ -84,7 +114,13 @@ - + + + + a2ca8c6aeb54677fee7375083901ad157e35db98e81616ceef3049afc1775682 + + + @@ -96,7 +132,13 @@ - + + + + b8de4c4b9d7baf979279f562b094cf85ed106bb00d04535d9dc4206c5625dd59 + + + diff --git a/plugins/search-everywhere-ml/typos/intellij.searchEverywhereMl.typos.iml b/plugins/search-everywhere-ml/typos/intellij.searchEverywhereMl.typos.iml index c7d6007679d3..a876f8c4ac95 100644 --- a/plugins/search-everywhere-ml/typos/intellij.searchEverywhereMl.typos.iml +++ b/plugins/search-everywhere-ml/typos/intellij.searchEverywhereMl.typos.iml @@ -17,7 +17,13 @@ - + + + + 311f4f1dc664878ce175cd85dee3165c87058c0dbff5a2c8dbb7de19e161b328 + + + diff --git a/plugins/settings-repository/intellij.settingsRepository.iml b/plugins/settings-repository/intellij.settingsRepository.iml index 1a9e21cdf20b..5d47abe700b7 100644 --- a/plugins/settings-repository/intellij.settingsRepository.iml +++ b/plugins/settings-repository/intellij.settingsRepository.iml @@ -13,6 +13,14 @@ + + + d9b12a3323f6447a7ca8de3d781166224f11c3505fe43dc0a9dfb1f33eb3cf04 + + + 4c0fda2b1d317750d7ea324e36c70b2bc48310c0aaae67b98df0915d696d7111 + + @@ -38,7 +46,13 @@ - + + + + d492b15a6d2ea3f1cc39c422c953c40c12289073dbe8360d98c0f6f9ec74fc44 + + + diff --git a/plugins/settings-sync/intellij.settingsSync.iml b/plugins/settings-sync/intellij.settingsSync.iml index d3eac829d616..5e21574e356f 100644 --- a/plugins/settings-sync/intellij.settingsSync.iml +++ b/plugins/settings-sync/intellij.settingsSync.iml @@ -37,6 +37,14 @@ + + + d9b12a3323f6447a7ca8de3d781166224f11c3505fe43dc0a9dfb1f33eb3cf04 + + + 4c0fda2b1d317750d7ea324e36c70b2bc48310c0aaae67b98df0915d696d7111 + + diff --git a/plugins/stats-collector/intellij.statsCollector.iml b/plugins/stats-collector/intellij.statsCollector.iml index d1f95bc7cd1f..c95548503a27 100644 --- a/plugins/stats-collector/intellij.statsCollector.iml +++ b/plugins/stats-collector/intellij.statsCollector.iml @@ -17,7 +17,13 @@ - + + + + f6f453ba3dc824d16ae0911e403dcde8e18e0ea7406c91e2832e8b6248a1f404 + + + diff --git a/plugins/stats-collector/intellij.statsCollector.tests.iml b/plugins/stats-collector/intellij.statsCollector.tests.iml index f4c6201e0ac6..24a19afee73d 100644 --- a/plugins/stats-collector/intellij.statsCollector.tests.iml +++ b/plugins/stats-collector/intellij.statsCollector.tests.iml @@ -16,7 +16,13 @@ - + + + + f6f453ba3dc824d16ae0911e403dcde8e18e0ea7406c91e2832e8b6248a1f404 + + + diff --git a/plugins/tasks/tasks-core/intellij.tasks.core.iml b/plugins/tasks/tasks-core/intellij.tasks.core.iml index 3e7f55e13969..af0a5cb77ae4 100644 --- a/plugins/tasks/tasks-core/intellij.tasks.core.iml +++ b/plugins/tasks/tasks-core/intellij.tasks.core.iml @@ -40,7 +40,13 @@ - + + + + 97d264e2f98821c4cd39eacfd597b4dc7c19d4232cf1f335fc2eab389b2d92fd + + + diff --git a/plugins/turboComplete/languages/kotlin/intellij.turboComplete.languages.kotlin.iml b/plugins/turboComplete/languages/kotlin/intellij.turboComplete.languages.kotlin.iml index af16f979060a..9a6af25319bc 100644 --- a/plugins/turboComplete/languages/kotlin/intellij.turboComplete.languages.kotlin.iml +++ b/plugins/turboComplete/languages/kotlin/intellij.turboComplete.languages.kotlin.iml @@ -13,7 +13,13 @@ - + + + + f8b9b802decae658447475325ae341efd07b2f6e3915312c9b51c5168e158012 + + + diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassAnnotator.java b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassAnnotator.java index ce550f737ee8..3e0661a26d23 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassAnnotator.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassAnnotator.java @@ -1,20 +1,18 @@ -// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.uiDesigner.binding; -import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.daemon.impl.quickfix.DeleteElementFix; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.ui.UIBundle; import com.intellij.uiDesigner.UIDesignerBundle; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import java.util.List; +import java.util.Objects; public class FormClassAnnotator implements Annotator { @@ -30,7 +28,7 @@ public class FormClassAnnotator implements Annotator { } else if (psiElement instanceof PsiClass aClass) { final List formsBoundToClass = FormClassIndex.findFormsBoundToClass(aClass.getProject(), aClass); - if (formsBoundToClass.size() > 0) { + if (!formsBoundToClass.isEmpty()) { holder.newSilentAnnotation(HighlightSeverity.INFORMATION).range(aClass.getNameIdentifier()).gutterIconRenderer(new BoundIconRenderer(aClass)).create(); } } @@ -54,37 +52,9 @@ public class FormClassAnnotator implements Annotator { if (field.hasInitializer()) { final String message = UIDesignerBundle.message("field.is.overwritten.by.generated.code", field.getName()); - holder.newAnnotation(HighlightSeverity.WARNING, message).range(field.getInitializer()) - .withFix(new IntentionAction() { - @Override - @NotNull - public String getText() { - return message; - } - - @Override - @NotNull - public String getFamilyName() { - return UIBundle.message("remove.field.initializer.quick.fix"); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return field.getInitializer() != null; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - final PsiExpression initializer = field.getInitializer(); - LOG.assertTrue(initializer != null); - initializer.delete(); - } - - @Override - public boolean startInWriteAction() { - return true; - } - }).create(); + PsiExpression initializer = Objects.requireNonNull(field.getInitializer()); + holder.newAnnotation(HighlightSeverity.WARNING, message).range(initializer) + .withFix(new DeleteElementFix(initializer, UIBundle.message("remove.field.initializer.quick.fix"))).create(); } } } diff --git a/plugins/xslt-debugger/engine/impl/intellij.xslt.debugger.impl.rt.iml b/plugins/xslt-debugger/engine/impl/intellij.xslt.debugger.impl.rt.iml index d8452852974a..cf1e1c7b3a23 100644 --- a/plugins/xslt-debugger/engine/impl/intellij.xslt.debugger.impl.rt.iml +++ b/plugins/xslt-debugger/engine/impl/intellij.xslt.debugger.impl.rt.iml @@ -31,6 +31,14 @@ + + + a44bd80e82cb0f4cfac0dac8575746223802514e3cec9dc75235bc0de646af14 + + + e8f5b4340d3b12a0cfa44ac2db4be4e0639e479ae847df04c4ed8b521734bb4a + + diff --git a/python/intellij.python.community.impl.iml b/python/intellij.python.community.impl.iml index 06c448f33992..efed064220c6 100644 --- a/python/intellij.python.community.impl.iml +++ b/python/intellij.python.community.impl.iml @@ -45,6 +45,11 @@ + + + 8924b199c8cc52530de2b250670806d8b046fa5ae9d32a9f27a9b224e934a1ad + + @@ -74,6 +79,14 @@ + + + b7331e02e955b6b962a8fa89eb8d7db0960d0b232880bfc60e8602fb3fed36ad + + + 43516d19beae35909e04d06af6c0c58c17bc94e0070c85e8dc9929ca640dc91d + + diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyDictLiteralCompletionContributor.kt b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyDictLiteralCompletionContributor.kt index 8ad5d27712ad..e9a17d91ca2c 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyDictLiteralCompletionContributor.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyDictLiteralCompletionContributor.kt @@ -54,7 +54,7 @@ private class DictLiteralCompletionProvider : CompletionProvider? = null - /** Parameters that return [REMOVE_ARGUMENT] are removed from the resulting argument list. */ + /** Parameters that return [SKIP_ARGUMENT] are removed from the resulting argument list. */ val parameters: MutableList> = mutableListOf() val envs: MutableMap> = mutableMapOf() @@ -28,7 +29,7 @@ sealed class PythonExecution { addParameter(constant(value)) } - /** If the function returns [REMOVE_ARGUMENT], the parameter will be removed from the resulting argument list. */ + /** If the function returns [SKIP_ARGUMENT], the parameter will be removed from the resulting argument list. */ fun addParameter(value: TargetEnvironmentFunction) { parameters.add(value) } @@ -67,7 +68,7 @@ sealed class PythonExecution { companion object { /** See docs for [parameters]. */ // python -c 'print(repr(__import__("random").randbytes(16))[2:-1])' - const val REMOVE_ARGUMENT = """\xdc'S>\x02\x03%\x14\xee\xc0\xa1`\xcb\r\xf0\x95""" + const val SKIP_ARGUMENT = """\xdc'S>\x02\x03%\x14\xee\xc0\xa1`\xcb\r\xf0\x95""" } } diff --git a/python/src/com/jetbrains/python/run/PythonScripts.kt b/python/src/com/jetbrains/python/run/PythonScripts.kt index c780822e4f04..a2cabf9511f9 100644 --- a/python/src/com/jetbrains/python/run/PythonScripts.kt +++ b/python/src/com/jetbrains/python/run/PythonScripts.kt @@ -58,7 +58,7 @@ fun PythonExecution.buildTargetedCommandLine(targetEnvironment: TargetEnvironmen } for (parameter in parameters) { val resolvedParameter = parameter.apply(targetEnvironment) - if (resolvedParameter != PythonExecution.REMOVE_ARGUMENT) { + if (resolvedParameter != PythonExecution.SKIP_ARGUMENT) { commandLineBuilder.addParameter(resolvedParameter) } } diff --git a/python/src/com/jetbrains/python/testing/AbstractPythonTestRunConfiguration.kt b/python/src/com/jetbrains/python/testing/AbstractPythonTestRunConfiguration.kt index 6624ab5be30b..99645f29ffd5 100644 --- a/python/src/com/jetbrains/python/testing/AbstractPythonTestRunConfiguration.kt +++ b/python/src/com/jetbrains/python/testing/AbstractPythonTestRunConfiguration.kt @@ -90,7 +90,7 @@ protected constructor(project: Project, factory: ConfigurationFactory, private v val sdk = sdk if (sdk == null) { // No SDK -- no tests - logger>().warn("SDK is null") + logger>().warn("Failed to detect test framework: SDK is null") return false } val requiredPackage = this.requiredPackage ?: return true // Installed by default diff --git a/python/src/com/jetbrains/python/testing/autoDetectTests/PyAutoDetectTestConfiguration.kt b/python/src/com/jetbrains/python/testing/autoDetectTests/PyAutoDetectTestConfiguration.kt index 494c9e994af8..8db61ef10b17 100644 --- a/python/src/com/jetbrains/python/testing/autoDetectTests/PyAutoDetectTestConfiguration.kt +++ b/python/src/com/jetbrains/python/testing/autoDetectTests/PyAutoDetectTestConfiguration.kt @@ -4,6 +4,7 @@ package com.jetbrains.python.testing.autoDetectTests import com.intellij.execution.Executor import com.intellij.execution.configurations.RunProfileState import com.intellij.execution.runners.ExecutionEnvironment +import com.intellij.openapi.module.Module import com.intellij.openapi.options.SettingsEditor import com.intellij.openapi.project.Project import com.intellij.util.xmlb.BeanBinding @@ -19,7 +20,9 @@ class PyAutoDetectTestConfiguration(project: Project, factory: PyAutoDetectionCo override val useFrameworkNameInConfiguration: Boolean = false override fun getState(executor: Executor, environment: ExecutionEnvironment): RunProfileState? { - val conf = detectedConfiguration() ?: return null + val runProfile = environment.runProfile + val module = (runProfile as? PyAbstractTestConfiguration)?.module + val conf = detectedConfiguration(module) ?: return null copyTo(getProperties(conf)) for (accessor in BeanBinding.getAccessors(PyAbstractTestConfiguration::class.java)) { @@ -32,10 +35,12 @@ class PyAutoDetectTestConfiguration(project: Project, factory: PyAutoDetectionCo return conf.getState(executor, environment) } - fun detectedConfiguration(): PyAbstractTestConfiguration? { + fun detectedConfiguration(module: Module?): PyAbstractTestConfiguration? { return PyAutoDetectionConfigurationFactory.factoriesExcludingThis .asSequence().map { - it.createTemplateConfiguration(project) + it.createTemplateConfiguration(project).apply { + this.module = module + } }.filter { it.isFrameworkInstalled() }.firstOrNull() diff --git a/python/testSrc/com/jetbrains/env/PyProcessWithConsoleTestTask.java b/python/testSrc/com/jetbrains/env/PyProcessWithConsoleTestTask.java index 6c01f4a99a55..ff18c433f605 100644 --- a/python/testSrc/com/jetbrains/env/PyProcessWithConsoleTestTask.java +++ b/python/testSrc/com/jetbrains/env/PyProcessWithConsoleTestTask.java @@ -132,7 +132,7 @@ public abstract class PyProcessWithConsoleTestTask failed = new Ref<>(false); final Ref processHandlerRef = new Ref<>(); diff --git a/spellchecker/intellij.spellchecker.iml b/spellchecker/intellij.spellchecker.iml index f3525ea1ad4a..2c7e970a1cc0 100644 --- a/spellchecker/intellij.spellchecker.iml +++ b/spellchecker/intellij.spellchecker.iml @@ -23,7 +23,13 @@ - + + + + 311f4f1dc664878ce175cd85dee3165c87058c0dbff5a2c8dbb7de19e161b328 + + + @@ -35,7 +41,13 @@ - + + + + eb8884328f5968fda666efe49ba691bb8bf8903b5b14fcdc9cf97bc4f50569a4 + + + @@ -47,7 +59,13 @@ - + + + + a3165827008fb198af477ece61f1961c2be0a3a14290637cb783e832006e00db + + + @@ -59,7 +77,13 @@ - + + + + 66b9ca18e5b2b583905acee46eb1730af2ff58cfcfa5162a9d67348308c31806 + + + @@ -71,7 +95,13 @@ - + + + + 2cd794e233b637498bf453ded2763a95a5b38e881009e621340c529c8eebd76c + + + @@ -83,7 +113,13 @@ - + + + + 7d21779a19dc3ccb037a1a5b85543162e358dbc656bea4926703315fdc125315 + + + @@ -95,7 +131,13 @@ - + + + + 90b65e69c4a1f7375bd32a3a2a7598c142436aef45e97add1b7e86cc5eafba80 + + + @@ -107,7 +149,13 @@ - + + + + 4cbf17f5c7049077cc1b8f885cb332b8d2271c7d3cd71d1501cda3e9328936d6 + + + @@ -119,7 +167,13 @@ - + + + + a14eb5ef82a23d6c7146a9e63bf503092bfe8e01ba6fa90ba4081a05a69565dc + + + @@ -131,7 +185,13 @@ - + + + + 04c678713b197343c44bd744f8a3eebb26ab40067612c5170c14dd0a0f6ed507 + + + @@ -143,7 +203,13 @@ - + + + + 88ba4475ec92a7f1a40a44dc6f631e4426952f5f943174edcb7be10b9e773166 + + + @@ -155,7 +221,13 @@ - + + + + 189b594c1c874500d55bfe4258a0b796371d61a42b705eec91abd2280fb2901c + + + @@ -167,7 +239,13 @@ - + + + + 069b982734bfe22e81d6f833415db3b6a2f3ef83efa080f0409a058052a2f532 + + + @@ -179,7 +257,13 @@ - + + + + 4aff241f00efbe7c17960a3a3efb1ba046586a562b53a25a68d2964fafff48d7 + + + @@ -191,7 +275,13 @@ - + + + + cbc2a1339391d3ea1e059b192e7424dfff8593bcc5a1b674359714a817f4b705 + + + @@ -203,7 +293,13 @@ - + + + + 87675985e637d231b5783d1fea0bd947e71267bf557adc93ce3daec8a519bd22 + + + diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java index 37162a481e7a..109f78da6d35 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java @@ -8,6 +8,7 @@ import com.intellij.ide.highlighter.XmlFileType; import com.intellij.lang.*; import com.intellij.lang.xml.XMLLanguage; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; @@ -280,11 +281,31 @@ public abstract class AbstractXmlBlock extends AbstractBlock { } ); } + else if (child.getElementType() == XmlTokenType.XML_DATA_CHARACTERS + && child.getTreeParent().getElementType() != XmlElementType.XML_CDATA + && child.textContains('\n')) { + result.add(createRawTextChild(child, indent, wrap, alignment)); + } else { result.add(createSimpleChild(child, indent, wrap, alignment, null)); } } + protected @NotNull XmlBlock createRawTextChild(@NotNull ASTNode child, @Nullable Indent indent, + @Nullable Wrap wrap, @Nullable Alignment alignment) { + var text = child.getText(); + var textStart = StringUtil.skipWhitespaceOrNewLineForward(text, 0); + var textEnd = StringUtil.skipWhitespaceOrNewLineBackward(text, text.length()); + TextRange textRange; + if (textStart < textEnd) { + textRange = child.getTextRange(); + textRange = new TextRange(textRange.getStartOffset() + textStart, textRange.getStartOffset() + textEnd); + } else { + textRange = null; + } + return new XmlBlock(child, wrap, alignment, myXmlFormattingPolicy, indent, textRange, isPreserveSpace()); + } + protected @NotNull XmlBlock createSimpleChild(@NotNull ASTNode child, @Nullable Indent indent, @Nullable Wrap wrap, @Nullable Alignment alignment, @Nullable TextRange range) { return new XmlBlock(child, wrap, alignment, myXmlFormattingPolicy, indent, range, isPreserveSpace()); diff --git a/xml/relaxng/intellij.relaxng.iml b/xml/relaxng/intellij.relaxng.iml index 37c70620c7e2..7fa028f06e2b 100644 --- a/xml/relaxng/intellij.relaxng.iml +++ b/xml/relaxng/intellij.relaxng.iml @@ -27,7 +27,13 @@ - + + + + 3427152431cf7f967f92e69e5cac16147c5d8fb4b4e5a8a72f5291788efcff8c + + + @@ -46,7 +52,13 @@ - + + + + 600acd9ebd37dd46e3a006bc6e748d68dfeb31cbf4881a84d06e6dc5cc5eed26 + + + diff --git a/xml/tests/src/com/intellij/psi/formatter/HtmlFormatterTest.java b/xml/tests/src/com/intellij/psi/formatter/HtmlFormatterTest.java index 3919c1fff4d1..caa514263f55 100644 --- a/xml/tests/src/com/intellij/psi/formatter/HtmlFormatterTest.java +++ b/xml/tests/src/com/intellij/psi/formatter/HtmlFormatterTest.java @@ -37,7 +37,7 @@ public class HtmlFormatterTest extends XmlFormatterTestBase { protected String getFileExtension() { return "html"; } - + public void test1() throws Exception { final HtmlCodeStyleSettings settings = getHtmlSettings(); settings.HTML_KEEP_BLANK_LINES = 0; @@ -49,7 +49,7 @@ public class HtmlFormatterTest extends XmlFormatterTestBase { settings.HTML_KEEP_LINE_BREAKS_IN_TEXT = false; settings.HTML_KEEP_WHITESPACES = false; - doTest(); + doTest(); } public void test2() throws Exception { @@ -261,7 +261,11 @@ public class HtmlFormatterTest extends XmlFormatterTestBase { public void testTableformatting() throws Exception { doTest(); } - + + public void testUnknownScriptFormatting() throws Exception { + doTest(); + } + public void testHtmlReformatDoesntProduceAssertion() { @NonNls String fileText = """ @@ -298,7 +302,7 @@ public class HtmlFormatterTest extends XmlFormatterTestBase { bodyTag.getTextRange().getEndOffset()); } - + public void testInvalidChar() throws Exception { doTest(); } @@ -435,7 +439,7 @@ public class HtmlFormatterTest extends XmlFormatterTestBase { protected boolean doCheckDocumentUpdate() { return "Performance".equals(getTestName(false)); } - + public void test10809() { doTextTest( """ @@ -519,7 +523,7 @@ public class HtmlFormatterTest extends XmlFormatterTestBase { settings.HTML_ENFORCE_QUOTES = enforce; } } - + public void testWeb18213() { doTextTest( """ diff --git a/xml/tests/testData/psi/formatter/html/unknownScriptFormatting.html b/xml/tests/testData/psi/formatter/html/unknownScriptFormatting.html new file mode 100644 index 000000000000..57c798d2ef5f --- /dev/null +++ b/xml/tests/testData/psi/formatter/html/unknownScriptFormatting.html @@ -0,0 +1,16 @@ + + +
+ div/div +
+
+ +
+ diff --git a/xml/tests/testData/psi/formatter/html/unknownScriptFormatting_after.html b/xml/tests/testData/psi/formatter/html/unknownScriptFormatting_after.html new file mode 100644 index 000000000000..507159541aef --- /dev/null +++ b/xml/tests/testData/psi/formatter/html/unknownScriptFormatting_after.html @@ -0,0 +1,16 @@ + + +
+ div/div +
+
+ +
+ diff --git a/xml/xml-psi-impl/src/com/intellij/lexer/BaseHtmlLexer.java b/xml/xml-psi-impl/src/com/intellij/lexer/BaseHtmlLexer.java index dbd451b3be54..671f90820343 100644 --- a/xml/xml-psi-impl/src/com/intellij/lexer/BaseHtmlLexer.java +++ b/xml/xml-psi-impl/src/com/intellij/lexer/BaseHtmlLexer.java @@ -214,6 +214,10 @@ public abstract class BaseHtmlLexer extends DelegateLexer implements Restartable return true; } + public boolean isPossiblyCustomTagName(@NotNull CharSequence tagName) { + return false; + } + private static class HtmlLexerPosition implements LexerPosition { private final int myOffset; diff --git a/xml/xml-psi-impl/src/com/intellij/lexer/HtmlDefaultEmbeddedContentSupport.kt b/xml/xml-psi-impl/src/com/intellij/lexer/HtmlDefaultEmbeddedContentSupport.kt index 78bae922e1f1..b2f9ca0c3b13 100644 --- a/xml/xml-psi-impl/src/com/intellij/lexer/HtmlDefaultEmbeddedContentSupport.kt +++ b/xml/xml-psi-impl/src/com/intellij/lexer/HtmlDefaultEmbeddedContentSupport.kt @@ -18,10 +18,12 @@ class HtmlDefaultEmbeddedContentSupport : HtmlEmbeddedContentSupport { } -class HtmlRawTextTagContentProvider(lexer: BaseHtmlLexer) : HtmlTagEmbeddedContentProvider(lexer) { +open class HtmlRawTextTagContentProvider(lexer: BaseHtmlLexer) : HtmlTagEmbeddedContentProvider(lexer) { override fun isInterestedInTag(tagName: CharSequence): Boolean = - namesEqual(tagName, HtmlUtil.TITLE_TAG_NAME) - || namesEqual(tagName, HtmlUtil.TEXTAREA_TAG_NAME) + (namesEqual(tagName, HtmlUtil.TITLE_TAG_NAME) + || namesEqual(tagName, HtmlUtil.TEXTAREA_TAG_NAME)) + && !lexer.isPossiblyCustomTagName(tagName) + override fun isInterestedInAttribute(attributeName: CharSequence): Boolean = false override fun createEmbedmentInfo(): HtmlEmbedmentInfo = HtmlEmbeddedContentProvider.RAW_TEXT_FORMATTABLE_EMBEDMENT diff --git a/xml/xmlbeans/intellij.xml.xmlbeans.iml b/xml/xmlbeans/intellij.xml.xmlbeans.iml index 539995bde345..209bc99f5ef6 100644 --- a/xml/xmlbeans/intellij.xml.xmlbeans.iml +++ b/xml/xmlbeans/intellij.xml.xmlbeans.iml @@ -11,7 +11,13 @@ - + + + + 5f484a78bed71cbffe3709678b6bdd3463781a7c61c6d9872330aecbf150762a + + + @@ -24,6 +30,14 @@ + + + 88e731d7f455da59dfa08769527f87d6c496053a712637df7b999f6977933a2c + + + 2f43eea679ea66f14ca0f13fec2a8600ac124f5a5231dcb4df8393eddcb97550 + +