KT-63627 [AA] Properly handle object declarations when traversing scopes in KtFirReferenceShortener
`KtClass` denotes only classes, interfaces and enums. To handle object declarations, we now use `KtClassOrObject` PSI type ^KT-63627 Fixed
This commit is contained in:
+16
-5
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.AllCandidatesResolver
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.ContextCollector
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
@@ -66,6 +67,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
||||
import java.util.Arrays
|
||||
|
||||
internal class KtFirReferenceShortener(
|
||||
override val analysisSession: KtFirAnalysisSession,
|
||||
@@ -652,7 +654,7 @@ private class ElementsToShortenCollector(
|
||||
*
|
||||
* This function determines the distance based on [ClassId].
|
||||
*/
|
||||
private fun FirScope.isScopeForClassCloserThanAnotherScopeForClass(another: FirScope, from: KtClass): Boolean {
|
||||
private fun FirScope.isScopeForClassCloserThanAnotherScopeForClass(another: FirScope, from: KtClassOrObject): Boolean {
|
||||
// Make sure both are scopes for classes
|
||||
if (!isScopeForClass() || !another.isScopeForClass()) return false
|
||||
|
||||
@@ -673,12 +675,12 @@ private class ElementsToShortenCollector(
|
||||
* Travels all containing classes of [innerClass] and finds the one matching ClassId with one of [candidates]. Returns the matching
|
||||
* ClassId. If it does not have a matching ClassId, it returns null.
|
||||
*/
|
||||
private fun findMostInnerClassMatchingId(innerClass: KtClass, candidates: Set<ClassId>): ClassId? {
|
||||
var classInNestedClass: KtClass? = innerClass
|
||||
private fun findMostInnerClassMatchingId(innerClass: KtClassOrObject, candidates: Set<ClassId>): ClassId? {
|
||||
var classInNestedClass: KtClassOrObject? = innerClass
|
||||
while (classInNestedClass != null) {
|
||||
val containingClassId = classInNestedClass.getClassId()
|
||||
if (containingClassId in candidates) return containingClassId
|
||||
classInNestedClass = classInNestedClass.containingClass()
|
||||
classInNestedClass = classInNestedClass.findClassOrObjectParent()
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -745,7 +747,7 @@ private class ElementsToShortenCollector(
|
||||
*/
|
||||
private fun List<FirScope>.hasScopeCloserThan(base: FirScope, from: KtElement) = any { scope ->
|
||||
if (scope.isScopeForClass() && base.isScopeForClass()) {
|
||||
val classContainingFrom = from.containingClass() ?: return@any false
|
||||
val classContainingFrom = from.findClassOrObjectParent() ?: return@any false
|
||||
return@any scope.isScopeForClassCloserThanAnotherScopeForClass(base, classContainingFrom)
|
||||
}
|
||||
base.isWiderThan(scope)
|
||||
@@ -1494,3 +1496,12 @@ private fun KtElement.getQualifier(): KtElement? = when (this) {
|
||||
is KtThisExpression -> labelQualifier
|
||||
else -> error("Unexpected ${this::class}")
|
||||
}
|
||||
|
||||
/**
|
||||
* N.B. We don't use [containingClassOrObject] because it works only for [KtDeclaration]s,
|
||||
* and also check only the immediate (direct) parent.
|
||||
*
|
||||
* For this function, we want to find the parent [KtClassOrObject] declaration no matter
|
||||
* how far it is from the element.
|
||||
*/
|
||||
private fun KtElement.findClassOrObjectParent(): KtClassOrObject? = parentOfType()
|
||||
|
||||
+36
@@ -625,6 +625,42 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_inside.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_inside() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_inside.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_inside_companion.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_inside_companion() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_inside_companion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_inside_namedCompanion.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_inside_namedCompanion() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_inside_namedCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_outside.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_outside() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_outside.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_outside_companion.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_outside_companion() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_outside_companion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_outside_namedCompanion.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_outside_namedCompanion() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_outside_namedCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes1.kt")
|
||||
public void testNestedClassFromSupertypes1() throws Exception {
|
||||
|
||||
+36
@@ -625,6 +625,42 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_inside.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_inside() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_inside.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_inside_companion.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_inside_companion() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_inside_companion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_inside_namedCompanion.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_inside_namedCompanion() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_inside_namedCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_outside.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_outside() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_outside.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_outside_companion.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_outside_companion() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_outside_companion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classAndObjectHaveConflictingNestedClasses_outside_namedCompanion.kt")
|
||||
public void testClassAndObjectHaveConflictingNestedClasses_outside_namedCompanion() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classAndObjectHaveConflictingNestedClasses_outside_namedCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClassFromSupertypes1.kt")
|
||||
public void testNestedClassFromSupertypes1() throws Exception {
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
class OuterClass {
|
||||
class Nested
|
||||
|
||||
object NestedObject {
|
||||
class Nested
|
||||
|
||||
<expr>fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.NestedObject.Nested,
|
||||
) {}</expr>
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Before shortening: fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.NestedObject.Nested,
|
||||
) {}
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
[type] test.OuterClass
|
||||
[type] test.OuterClass.NestedObject.Nested
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] test.OuterClass
|
||||
[type] test.OuterClass.NestedObject.Nested
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] test.OuterClass
|
||||
[type] test.OuterClass.NestedObject.Nested
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
class OuterClass {
|
||||
class Nested
|
||||
|
||||
companion object {
|
||||
class Nested
|
||||
|
||||
<expr>fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.Companion.Nested,
|
||||
) {}</expr>
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Before shortening: fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.Companion.Nested,
|
||||
) {}
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
[type] test.OuterClass
|
||||
[type] test.OuterClass.Companion.Nested
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] test.OuterClass
|
||||
[type] test.OuterClass.Companion.Nested
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] test.OuterClass
|
||||
[type] test.OuterClass.Companion.Nested
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
class OuterClass {
|
||||
class Nested
|
||||
|
||||
companion object NamedCompanion {
|
||||
class Nested
|
||||
|
||||
<expr>fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.NamedCompanion.Nested,
|
||||
) {}</expr>
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Before shortening: fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.NamedCompanion.Nested,
|
||||
) {}
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
[type] test.OuterClass
|
||||
[type] test.OuterClass.NamedCompanion.Nested
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] test.OuterClass
|
||||
[type] test.OuterClass.NamedCompanion.Nested
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] test.OuterClass
|
||||
[type] test.OuterClass.NamedCompanion.Nested
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
class OuterClass {
|
||||
class Nested
|
||||
|
||||
object NestedObject {
|
||||
class Nested
|
||||
}
|
||||
|
||||
<expr>fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.NestedObject.Nested,
|
||||
) {}</expr>
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Before shortening: fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.NestedObject.Nested,
|
||||
) {}
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
[type] test.OuterClass.Nested
|
||||
[type] test.OuterClass.NestedObject
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] test.OuterClass.Nested
|
||||
[type] test.OuterClass.NestedObject
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] test.OuterClass.Nested
|
||||
[type] test.OuterClass.NestedObject
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
class OuterClass {
|
||||
class Nested
|
||||
|
||||
companion object {
|
||||
class Nested
|
||||
}
|
||||
|
||||
<expr>fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.Companion.Nested,
|
||||
) {}</expr>
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Before shortening: fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.Companion.Nested,
|
||||
) {}
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
[type] test.OuterClass.Nested
|
||||
[type] test.OuterClass.Companion
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] test.OuterClass.Nested
|
||||
[type] test.OuterClass.Companion
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] test.OuterClass.Nested
|
||||
[type] test.OuterClass.Companion
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
class OuterClass {
|
||||
class Nested
|
||||
|
||||
companion object NamedCompanion {
|
||||
class Nested
|
||||
}
|
||||
|
||||
<expr>fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.NamedCompanion.Nested,
|
||||
) {}</expr>
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Before shortening: fun usage(
|
||||
first: test.OuterClass.Nested,
|
||||
second: test.OuterClass.NamedCompanion.Nested,
|
||||
) {}
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
[type] test.OuterClass.Nested
|
||||
[type] test.OuterClass.NamedCompanion
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] test.OuterClass.Nested
|
||||
[type] test.OuterClass.NamedCompanion
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] test.OuterClass.Nested
|
||||
[type] test.OuterClass.NamedCompanion
|
||||
Reference in New Issue
Block a user