[Analysis API FIR] KtFirSymbolDeclarationOverridesProvider: unwrap fake overrides
We should unwrap substitution overrides as they sometimes cannot be
resolved on demand. We already have this in KDoc contract.
```kotlin
class MyClass {
val prop = object : LazySchemeProcessor<Int, Int>() {
override fun is<caret>SchemeFile(name: CharSequence) = name != "str"
}
}
abstract class LazySchemeProcessor<SCHEME : Number, MUTABLE_SCHEME : SCHEME> {
open fun isSchemeFile(name: CharSequence) = true
}
```
In this case, we will try to resolve fake override in the context of the
anonymous object, and it will fail because we cannot lazily resolve
local declarations as they are a part of the containing declarations
(KT-64243 for more details)
^KT-64108 Fixed
This commit is contained in:
committed by
Space Team
parent
e033fe5ba1
commit
b458d69689
+8
-4
@@ -27,12 +27,12 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymb
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverridePropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverridePropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
|
||||||
|
|
||||||
internal class KtFirSymbolDeclarationOverridesProvider(
|
internal class KtFirSymbolDeclarationOverridesProvider(
|
||||||
override val analysisSession: KtFirAnalysisSession,
|
override val analysisSession: KtFirAnalysisSession,
|
||||||
override val token: KtLifetimeToken
|
override val token: KtLifetimeToken
|
||||||
) : KtSymbolDeclarationOverridesProviderBase(), KtFirAnalysisSessionComponent {
|
) : KtSymbolDeclarationOverridesProviderBase(), KtFirAnalysisSessionComponent {
|
||||||
|
|
||||||
override fun <T : KtSymbol> getAllOverriddenSymbols(
|
override fun <T : KtSymbol> getAllOverriddenSymbols(
|
||||||
callableSymbol: T,
|
callableSymbol: T,
|
||||||
): List<KtCallableSymbol> {
|
): List<KtCallableSymbol> {
|
||||||
@@ -40,13 +40,15 @@ internal class KtFirSymbolDeclarationOverridesProvider(
|
|||||||
if (callableSymbol is KtValueParameterSymbol) {
|
if (callableSymbol is KtValueParameterSymbol) {
|
||||||
return callableSymbol.getAllOverriddenSymbols()
|
return callableSymbol.getAllOverriddenSymbols()
|
||||||
}
|
}
|
||||||
|
|
||||||
val overriddenElement = mutableSetOf<FirCallableSymbol<*>>()
|
val overriddenElement = mutableSetOf<FirCallableSymbol<*>>()
|
||||||
processOverrides(callableSymbol) { firTypeScope, firCallableDeclaration ->
|
processOverrides(callableSymbol) { firTypeScope, firCallableDeclaration ->
|
||||||
firTypeScope.processAllOverriddenDeclarations(firCallableDeclaration) { overriddenDeclaration ->
|
firTypeScope.processAllOverriddenDeclarations(firCallableDeclaration) { overriddenDeclaration ->
|
||||||
overriddenDeclaration.symbol.collectIntersectionOverridesSymbolsTo(overriddenElement)
|
overriddenDeclaration.symbol.collectIntersectionOverridesSymbolsTo(overriddenElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return overriddenElement.map { analysisSession.firSymbolBuilder.callableBuilder.buildCallableSymbol(it) }.distinct()
|
|
||||||
|
return overriddenElement.map { analysisSession.firSymbolBuilder.callableBuilder.buildCallableSymbol(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : KtSymbol> getDirectlyOverriddenSymbols(callableSymbol: T): List<KtCallableSymbol> {
|
override fun <T : KtSymbol> getDirectlyOverriddenSymbols(callableSymbol: T): List<KtCallableSymbol> {
|
||||||
@@ -54,13 +56,15 @@ internal class KtFirSymbolDeclarationOverridesProvider(
|
|||||||
if (callableSymbol is KtValueParameterSymbol) {
|
if (callableSymbol is KtValueParameterSymbol) {
|
||||||
return callableSymbol.getDirectlyOverriddenSymbols()
|
return callableSymbol.getDirectlyOverriddenSymbols()
|
||||||
}
|
}
|
||||||
|
|
||||||
val overriddenElement = mutableSetOf<FirCallableSymbol<*>>()
|
val overriddenElement = mutableSetOf<FirCallableSymbol<*>>()
|
||||||
processOverrides(callableSymbol) { firTypeScope, firCallableDeclaration ->
|
processOverrides(callableSymbol) { firTypeScope, firCallableDeclaration ->
|
||||||
firTypeScope.processDirectOverriddenDeclarations(firCallableDeclaration) { overriddenDeclaration ->
|
firTypeScope.processDirectOverriddenDeclarations(firCallableDeclaration) { overriddenDeclaration ->
|
||||||
overriddenDeclaration.symbol.collectIntersectionOverridesSymbolsTo(overriddenElement)
|
overriddenDeclaration.symbol.collectIntersectionOverridesSymbolsTo(overriddenElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return overriddenElement.map { analysisSession.firSymbolBuilder.callableBuilder.buildCallableSymbol(it) }.distinct()
|
|
||||||
|
return overriddenElement.map { analysisSession.firSymbolBuilder.callableBuilder.buildCallableSymbol(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirTypeScope.processCallableByName(declaration: FirDeclaration) = when (declaration) {
|
private fun FirTypeScope.processCallableByName(declaration: FirDeclaration) = when (declaration) {
|
||||||
@@ -144,7 +148,7 @@ internal class KtFirSymbolDeclarationOverridesProvider(
|
|||||||
intersections.forEach { it.collectIntersectionOverridesSymbolsTo(to) }
|
intersections.forEach { it.collectIntersectionOverridesSymbolsTo(to) }
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
to += this
|
to += this.fir.unwrapFakeOverrides().symbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-6
@@ -22,11 +22,13 @@ public abstract class KtSymbolDeclarationOverridesProvider : KtAnalysisSessionCo
|
|||||||
|
|
||||||
public interface KtSymbolDeclarationOverridesProviderMixIn : KtAnalysisSessionMixIn {
|
public interface KtSymbolDeclarationOverridesProviderMixIn : KtAnalysisSessionMixIn {
|
||||||
/**
|
/**
|
||||||
* Return a list of **all** symbols which are overridden by symbol
|
* Return a list of **all** explicitly declared symbols that are overridden by symbol
|
||||||
*
|
*
|
||||||
* E.g, if we have `A.foo` overrides `B.foo` overrides `C.foo`, all two super declarations `B.foo`, `C.foo` will be returned
|
* E.g., if we have `A.foo` overrides `B.foo` overrides `C.foo`, all two super declarations `B.foo`, `C.foo` will be returned
|
||||||
*
|
*
|
||||||
* Unwraps substituted overridden symbols (see [org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin.INTERSECTION_OVERRIDE])
|
* Unwraps substituted overridden symbols
|
||||||
|
* (see [INTERSECTION_OVERRIDE][org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin.INTERSECTION_OVERRIDE] and [SUBSTITUTION_OVERRIDE][org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin.SUBSTITUTION_OVERRIDE]),
|
||||||
|
* so such fake declaration won't be returned.
|
||||||
*
|
*
|
||||||
* @see getDirectlyOverriddenSymbols
|
* @see getDirectlyOverriddenSymbols
|
||||||
*/
|
*/
|
||||||
@@ -34,11 +36,13 @@ public interface KtSymbolDeclarationOverridesProviderMixIn : KtAnalysisSessionMi
|
|||||||
withValidityAssertion { analysisSession.symbolDeclarationOverridesProvider.getAllOverriddenSymbols(this) }
|
withValidityAssertion { analysisSession.symbolDeclarationOverridesProvider.getAllOverriddenSymbols(this) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a list of symbols which are **directly** overridden by symbol
|
* Return a list of explicitly declared symbols which are **directly** overridden by symbol
|
||||||
**
|
**
|
||||||
* E.g, if we have `A.foo` overrides `B.foo` overrides `C.foo`, only declarations directly overridden `B.foo` will be returned
|
* E.g., if we have `A.foo` overrides `B.foo` overrides `C.foo`, only declarations directly overridden `B.foo` will be returned
|
||||||
*
|
*
|
||||||
* Unwraps substituted overridden symbols (see [org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin.INTERSECTION_OVERRIDE])
|
* Unwraps substituted overridden symbols
|
||||||
|
* (see [INTERSECTION_OVERRIDE][org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin.INTERSECTION_OVERRIDE] and [SUBSTITUTION_OVERRIDE][org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin.SUBSTITUTION_OVERRIDE]),
|
||||||
|
* so such fake declaration won't be returned.
|
||||||
*
|
*
|
||||||
* @see getAllOverriddenSymbols
|
* @see getAllOverriddenSymbols
|
||||||
*/
|
*/
|
||||||
|
|||||||
-11
@@ -2,14 +2,3 @@ class MyList : ArrayList<Int>() {
|
|||||||
override val size<caret>: Int = 0
|
override val size<caret>: Int = 0
|
||||||
override fun get(index: Int): Int = 0
|
override fun get(index: Int): Int = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// RESULT
|
|
||||||
// ALL:
|
|
||||||
// java/util/ArrayList.size: Int
|
|
||||||
// java/util/AbstractList.size: Int
|
|
||||||
// java/util/AbstractCollection.size: Int
|
|
||||||
// List.size: Int
|
|
||||||
// Collection.size: Int
|
|
||||||
|
|
||||||
// DIRECT:
|
|
||||||
// java/util/ArrayList.size: Int
|
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
ALL:
|
ALL:
|
||||||
java/util/ArrayList.size: Int
|
java/util/ArrayList.size: Int
|
||||||
java/util/AbstractList.size: Int
|
|
||||||
java/util/AbstractCollection.size: Int
|
java/util/AbstractCollection.size: Int
|
||||||
kotlin/collections/List.size: Int
|
kotlin/collections/List.size: Int
|
||||||
kotlin/collections/Collection.size: Int
|
kotlin/collections/Collection.size: Int
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
ALL:
|
ALL:
|
||||||
java/util/ArrayList.size: Int
|
java/util/ArrayList.size: Int
|
||||||
java/util/AbstractList.size: Int
|
|
||||||
java/util/AbstractCollection.size: Int
|
java/util/AbstractCollection.size: Int
|
||||||
List.size: Int
|
List.size: Int
|
||||||
Collection.size: Int
|
Collection.size: Int
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_FIR
|
|
||||||
class MyClass {
|
class MyClass {
|
||||||
lateinit var d: IntermediateClass<Int>
|
lateinit var d: IntermediateClass<Int>
|
||||||
val prop = object : IntermediateClass<Int> by d {
|
val prop = object : IntermediateClass<Int> by d {
|
||||||
|
|||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
ALL:
|
|
||||||
BaseClass.isSchemeFile(name: CharSequence): Boolean
|
|
||||||
DIRECT:
|
|
||||||
BaseClass.isSchemeFile(name: CharSequence): Boolean
|
|
||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
ALL:
|
ALL:
|
||||||
BaseClass.isSchemeFile(name: CharSequence): Boolean
|
BaseClass.isSchemeFile(name: CharSequence): Boolean
|
||||||
BaseClass.isSchemeFile(name: CharSequence): Boolean
|
|
||||||
DIRECT:
|
DIRECT:
|
||||||
BaseClass.isSchemeFile(name: CharSequence): Boolean
|
BaseClass.isSchemeFile(name: CharSequence): Boolean
|
||||||
|
|||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
ALL:
|
||||||
|
DIRECT:
|
||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_FIR
|
|
||||||
package second
|
package second
|
||||||
|
|
||||||
class MyClass {
|
class MyClass {
|
||||||
|
|||||||
+3
@@ -1,2 +1,5 @@
|
|||||||
ALL:
|
ALL:
|
||||||
|
C.foo(x: T): Unit
|
||||||
|
D.foo(x: F): Unit
|
||||||
DIRECT:
|
DIRECT:
|
||||||
|
C.foo(x: T): Unit
|
||||||
|
|||||||
+1
-4
@@ -1,8 +1,5 @@
|
|||||||
ALL:
|
ALL:
|
||||||
C.foo(x: String): Unit
|
|
||||||
C.foo(x: T): Unit
|
|
||||||
D.foo(x: T): Unit
|
|
||||||
C.foo(x: T): Unit
|
C.foo(x: T): Unit
|
||||||
D.foo(x: F): Unit
|
D.foo(x: F): Unit
|
||||||
DIRECT:
|
DIRECT:
|
||||||
C.foo(x: String): Unit
|
C.foo(x: T): Unit
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_FIR
|
|
||||||
package second
|
package second
|
||||||
|
|
||||||
class MyClass {
|
class MyClass {
|
||||||
|
|||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
ALL:
|
|
||||||
LazySchemeProcessor.isSchemeFile(name: CharSequence): Boolean
|
|
||||||
DIRECT:
|
|
||||||
LazySchemeProcessor.isSchemeFile(name: CharSequence): Boolean
|
|
||||||
+1
-2
@@ -1,5 +1,4 @@
|
|||||||
ALL:
|
ALL:
|
||||||
LazySchemeProcessor.isSchemeFile(name: CharSequence): Boolean
|
LazySchemeProcessor.isSchemeFile(name: CharSequence): Boolean
|
||||||
LazySchemeProcessor.isSchemeFile(name: CharSequence): Boolean
|
|
||||||
DIRECT:
|
DIRECT:
|
||||||
LazySchemeProcessor.isSchemeFile(name: CharSequence): Boolean
|
LazySchemeProcessor.isSchemeFile(name: CharSequence): Boolean
|
||||||
|
|||||||
Reference in New Issue
Block a user