[FIR][AA] Rely more on isInBestCandidates flag KtFirReferenceShortener

After the KT-61568 has been fixed, `isInBestCandidates`
correctly works in more cases, and can be more
reliably used in `KtFirReferenceShortener`

^KTIJ-26808 Fixed
^KTIJ-26840 Fixed
This commit is contained in:
Roman Golyshev
2023-08-30 18:26:59 +02:00
committed by teamcity
parent ac102dedac
commit 1766c68e9c
7 changed files with 84 additions and 24 deletions
@@ -977,31 +977,10 @@ private class ElementsToShortenCollector(
if (candidates.mapNotNull { it.candidate.originScope }
.hasScopeCloserThan(scopeForQualifiedAccess, expressionInScope)) return false
val candidatesWithinSamePriorityScopes = candidates.filter { it.candidate.originScope == scopeForQualifiedAccess }
if (candidatesWithinSamePriorityScopes.isEmpty() || candidatesWithinSamePriorityScopes.size == 1) return true
/**
* This is a conservative decision to avoid false positives.
*
* TODO: Figure out the priorities among `candidatesWithinSamePriorityScopes` and determine if [firQualifiedAccess] matches the
* one with the highest priority. At this moment, we have some counter examples that [OverloadCandidate.isInBestCandidates] is true
* and its symbol matches [firQualifiedAccess], but we cannot shorten it.
*
* For example:
* package foo
* class Foo {
* fun test() {
* // It references FIRST. Removing `foo` lets it reference SECOND. However, the one has true for
* // [OverloadCandidate.isInBestCandidates] is FIRST. Therefore, making a decision based on `isInBestCandidates` can
* // cause false positives i.e., shortening changes the referenced symbol.
* <caret>foo.myRun {
* 42
* }
* }
* }
* inline fun <R> myRun(block: () -> R): R = block() // FIRST
* inline fun <T, R> T.myRun(block: T.() -> R): R = block() // SECOND
*/
return false
// TODO isInBestCandidates should probably be used more actively to filter candidates
return candidatesWithinSamePriorityScopes.isEmpty() ||
candidatesWithinSamePriorityScopes.singleOrNull()?.isInBestCandidates == true
}
private fun processPropertyAccess(firPropertyAccess: FirPropertyAccessExpression) {
@@ -298,6 +298,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/kdocUnresolved.kt");
}
@Test
@TestMetadata("memberVsCompanionObjectMemberConflict.kt")
public void testMemberVsCompanionObjectMemberConflict() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/memberVsCompanionObjectMemberConflict.kt");
}
@Test
@TestMetadata("multipleImport.kt")
public void testMultipleImport() throws Exception {
@@ -436,6 +442,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/shortenAlreadyImportedFunction4.kt");
}
@Test
@TestMetadata("staticMethodFromBaseClassConflict.kt")
public void testStaticMethodFromBaseClassConflict() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/staticMethodFromBaseClassConflict.kt");
}
@Test
@TestMetadata("superClass.kt")
public void testSuperClass() throws Exception {
@@ -298,6 +298,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/kdocUnresolved.kt");
}
@Test
@TestMetadata("memberVsCompanionObjectMemberConflict.kt")
public void testMemberVsCompanionObjectMemberConflict() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/memberVsCompanionObjectMemberConflict.kt");
}
@Test
@TestMetadata("multipleImport.kt")
public void testMultipleImport() throws Exception {
@@ -436,6 +442,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/shortenAlreadyImportedFunction4.kt");
}
@Test
@TestMetadata("staticMethodFromBaseClassConflict.kt")
public void testStaticMethodFromBaseClassConflict() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/staticMethodFromBaseClassConflict.kt");
}
@Test
@TestMetadata("superClass.kt")
public void testSuperClass() throws Exception {
@@ -0,0 +1,15 @@
package test
class MyClass {
companion object {
val prop = ""
}
object Other {
val prop = ""
fun usage() {
println(<expr>MyClass.prop</expr>)
}
}
}
@@ -0,0 +1,5 @@
Before shortening: MyClass.prop
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
with SHORTEN_AND_IMPORT:
with SHORTEN_AND_STAR_IMPORT:
@@ -0,0 +1,26 @@
// FILE: main.kt
package test
import dependency.Middle
import dependency.Base
class MyClass : Middle {
<expr>fun usage() {
Middle.test()
Base.test()
}</expr>
}
// FILE: dependency/Middle.java
package dependency;
public class Middle extends Base {
public static void test() {}
}
// FILE: dependency/Base.java
package dependency;
public class Base {
public static void test() {}
}
@@ -0,0 +1,11 @@
Before shortening: fun usage() {
Middle.test()
Base.test()
}
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] Middle.test()
with SHORTEN_AND_IMPORT:
[qualifier] Middle.test()
with SHORTEN_AND_STAR_IMPORT:
[qualifier] Middle.test()