[Analysis API] Ignore FirClassUseSiteMemberScope scopes in KtFirReferenceShortener
Those scopes always contain all nested classifiers, while only some of them are available without explicit import. There are other, more reliable scopes (like FirNestedClassifierScopeWithSubstitution) which are stricter about which classifiers they recognise as valid ^KTIJ-24684 Fixed ^KTIJ-24662 Fixed
This commit is contained in:
+9
-3
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
@@ -601,8 +600,15 @@ private class ElementsToShortenCollector(
|
||||
// If its parent has a type parameter, we cannot shorten it because it will lose its type parameter.
|
||||
if (classSymbol.hasTypeParameterFromParent()) return false
|
||||
|
||||
/**
|
||||
* Class use-site member scopes may contain classifiers which are not actually available without explicit import.
|
||||
*
|
||||
* See KTIJ-24684 and KTIJ-24662 for examples.
|
||||
*/
|
||||
val scopes = positionScopes.filterNot { it is FirClassUseSiteMemberScope }
|
||||
|
||||
val name = classId.shortClassName
|
||||
val availableClassifiers = shorteningContext.findClassifiersInScopesByName(positionScopes, name)
|
||||
val availableClassifiers = shorteningContext.findClassifiersInScopesByName(scopes, name)
|
||||
val matchingAvailableSymbol = availableClassifiers.firstOrNull { it.availableSymbol.symbol == classId }
|
||||
val scopeForClass = matchingAvailableSymbol?.scope ?: return false
|
||||
|
||||
@@ -618,7 +624,7 @@ private class ElementsToShortenCollector(
|
||||
* my.component.foo::class.java // If we drop `my.component`, it will reference `B` instead of `A`
|
||||
* }
|
||||
*/
|
||||
if (shorteningContext.findPropertiesInScopes(positionScopes, name).isNotEmpty()) {
|
||||
if (shorteningContext.findPropertiesInScopes(scopes, name).isNotEmpty()) {
|
||||
val firForElement = element.getOrBuildFir(firResolveSession) as? FirQualifiedAccessExpression
|
||||
val typeArguments = firForElement?.typeArguments ?: emptyList()
|
||||
val qualifiedAccessCandidates = findCandidatesForPropertyAccess(classSymbol.annotations, typeArguments, name, element)
|
||||
|
||||
+36
@@ -196,6 +196,42 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClass3.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes.kt")
|
||||
public void testNestedClassFromSupertypes() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes2.kt")
|
||||
public void testNestedClassFromSupertypes2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes3.kt")
|
||||
public void testNestedClassFromSupertypes3() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes4.kt")
|
||||
public void testNestedClassFromSupertypes4() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes5.kt")
|
||||
public void testNestedClassFromSupertypes5() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes6.kt")
|
||||
public void testNestedClassFromSupertypes6() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("parameterTypeTopLevelTypeLoses.kt")
|
||||
public void testParameterTypeTopLevelTypeLoses() throws Exception {
|
||||
|
||||
+36
@@ -196,6 +196,42 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClass3.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes.kt")
|
||||
public void testNestedClassFromSupertypes() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes2.kt")
|
||||
public void testNestedClassFromSupertypes2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes3.kt")
|
||||
public void testNestedClassFromSupertypes3() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes4.kt")
|
||||
public void testNestedClassFromSupertypes4() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes5.kt")
|
||||
public void testNestedClassFromSupertypes5() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes6.kt")
|
||||
public void testNestedClassFromSupertypes6() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("parameterTypeTopLevelTypeLoses.kt")
|
||||
public void testParameterTypeTopLevelTypeLoses() throws Exception {
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// FILE: main.kt
|
||||
|
||||
interface MyInterface {
|
||||
class Nested
|
||||
}
|
||||
|
||||
class Foo : MyInterface {
|
||||
<expr>val prop: MyInterface.Nested = MyInterface.Nested()</expr>
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
Before shortening: val prop: MyInterface.Nested = MyInterface.Nested()
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] MyInterface.Nested
|
||||
[qualifier] MyInterface.Nested()
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] MyInterface.Nested
|
||||
[qualifier] MyInterface.Nested()
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// FILE: main.kt
|
||||
import MyInterface.Nested
|
||||
|
||||
interface MyInterface {
|
||||
class Nested
|
||||
}
|
||||
|
||||
class Foo : MyInterface {
|
||||
<expr>val prop: MyInterface.Nested = MyInterface.Nested()</expr>
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
Before shortening: val prop: MyInterface.Nested = MyInterface.Nested()
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
[type] MyInterface.Nested
|
||||
[qualifier] MyInterface.Nested()
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] MyInterface.Nested
|
||||
[qualifier] MyInterface.Nested()
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] MyInterface.Nested
|
||||
[qualifier] MyInterface.Nested()
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// FILE: main.kt
|
||||
open class MyBaseClass {
|
||||
class Nested
|
||||
}
|
||||
|
||||
class Foo : MyBaseClass() {
|
||||
<expr>val prop: MyBaseClass.Nested = MyBaseClass.Nested()</expr>
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
Before shortening: val prop: MyBaseClass.Nested = MyBaseClass.Nested()
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
[type] MyBaseClass.Nested
|
||||
[qualifier] MyBaseClass.Nested()
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] MyBaseClass.Nested
|
||||
[qualifier] MyBaseClass.Nested()
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] MyBaseClass.Nested
|
||||
[qualifier] MyBaseClass.Nested()
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// FILE: main.kt
|
||||
interface MyInterface {
|
||||
class Nested
|
||||
|
||||
<expr>val prop: MyInterface.Nested get() = MyInterface.Nested()</expr>
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
Before shortening: val prop: MyInterface.Nested get() = MyInterface.Nested()
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
[type] MyInterface.Nested
|
||||
[qualifier] MyInterface.Nested()
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] MyInterface.Nested
|
||||
[qualifier] MyInterface.Nested()
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] MyInterface.Nested
|
||||
[qualifier] MyInterface.Nested()
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// FILE: main.kt
|
||||
interface MyInterface {
|
||||
class Nested
|
||||
}
|
||||
|
||||
fun MyInterface.foo() {
|
||||
<expr>val prop: MyInterface.Nested = MyInterface.Nested()</expr>
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
Before shortening: val prop: MyInterface.Nested = MyInterface.Nested()
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] MyInterface.Nested
|
||||
[qualifier] MyInterface.Nested()
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] MyInterface.Nested
|
||||
[qualifier] MyInterface.Nested()
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// FILE: main.kt
|
||||
open class MyBaseClass {
|
||||
class Nested
|
||||
}
|
||||
|
||||
fun MyBaseClass.foo() {
|
||||
<expr>val prop: MyBaseClass.Nested = MyBaseClass.Nested()</expr>
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
Before shortening: val prop: MyBaseClass.Nested = MyBaseClass.Nested()
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] MyBaseClass.Nested
|
||||
[qualifier] MyBaseClass.Nested()
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] MyBaseClass.Nested
|
||||
[qualifier] MyBaseClass.Nested()
|
||||
Reference in New Issue
Block a user