FIR IDE: get type of unresovled super
FIR does not provide any type for unresolved super so we manually synthesize such types for completion to work.
This commit is contained in:
committed by
Ilya Kirillov
parent
a487e91124
commit
c10879be43
+35
-15
@@ -6,21 +6,6 @@
|
||||
package org.jetbrains.kotlin.analysis.api.fir.components
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirLabel
|
||||
import org.jetbrains.kotlin.fir.FirPackageDirective
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.constructFunctionalType
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtExpressionTypeProvider
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.getReferencedElementType
|
||||
@@ -29,6 +14,26 @@ import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtClassErrorType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe
|
||||
import org.jetbrains.kotlin.fir.FirLabel
|
||||
import org.jetbrains.kotlin.fir.FirPackageDirective
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.resolve.constructFunctionalType
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.ConeIntersectionType
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
@@ -39,6 +44,21 @@ internal class KtFirExpressionTypeProvider(
|
||||
|
||||
override fun getKtExpressionType(expression: KtExpression): KtType? = withValidityAssertion {
|
||||
when (val fir = expression.unwrap().getOrBuildFir(firResolveState)) {
|
||||
is FirPropertyAccessExpression -> {
|
||||
// For unresolved `super`, we manually create an intersection type so that IDE features like completion can work correctly.
|
||||
val containingClass =
|
||||
(fir.dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol as? FirClassSymbol<*>
|
||||
if (fir.calleeReference is FirSuperReference && fir.typeRef is FirErrorTypeRef && containingClass != null) {
|
||||
val superTypes = containingClass.superConeTypes
|
||||
when (superTypes.size) {
|
||||
0 -> analysisSession.builtinTypes.ANY
|
||||
1 -> superTypes.single().asKtType()
|
||||
else -> ConeIntersectionType(superTypes).asKtType()
|
||||
}
|
||||
} else {
|
||||
fir.typeRef.coneType.asKtType()
|
||||
}
|
||||
}
|
||||
is FirExpression -> fir.typeRef.coneType.asKtType()
|
||||
is FirNamedReference -> fir.getReferencedElementType(firResolveState).asKtType()
|
||||
is FirStatement -> with(analysisSession) { builtinTypes.UNIT }
|
||||
|
||||
+24
@@ -90,6 +90,12 @@ public class HLExpressionTypeTestGenerated extends AbstractHLExpressionTypeTest
|
||||
runTest("analysis/analysis-api/testData/components/expressionType/property.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("resolvedSuper.kt")
|
||||
public void testResolvedSuper() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/expressionType/resolvedSuper.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnExpression.kt")
|
||||
public void testReturnExpression() throws Exception {
|
||||
@@ -102,6 +108,24 @@ public class HLExpressionTypeTestGenerated extends AbstractHLExpressionTypeTest
|
||||
runTest("analysis/analysis-api/testData/components/expressionType/stringLiteral.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unresolvedSuper_multipleSuperTypes.kt")
|
||||
public void testUnresolvedSuper_multipleSuperTypes() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/expressionType/unresolvedSuper_multipleSuperTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unresolvedSuper_noSuperType.kt")
|
||||
public void testUnresolvedSuper_noSuperType() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/expressionType/unresolvedSuper_noSuperType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unresolvedSuper_singleSuperType.kt")
|
||||
public void testUnresolvedSuper_singleSuperType() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/expressionType/unresolvedSuper_singleSuperType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whileExpression.kt")
|
||||
public void testWhileExpression() throws Exception {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
interface A {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
class B : A {
|
||||
fun test() {
|
||||
<expr>super</expr>.foo()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
expression: super
|
||||
type: A
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
interface A {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
interface B {
|
||||
fun bar() {}
|
||||
}
|
||||
|
||||
class C : A, B {
|
||||
fun test() {
|
||||
<expr>super</expr>.unresolved()
|
||||
}
|
||||
}
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
expression: super
|
||||
type: (A&B)
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class Foo {
|
||||
fun test() {
|
||||
<expr>super</expr>.unresolved()
|
||||
}
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
expression: super
|
||||
type: kotlin.Any
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
interface A {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
class B : A {
|
||||
fun test() {
|
||||
<expr>super</expr>.unresolved()
|
||||
}
|
||||
}
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
expression: super
|
||||
type: A
|
||||
Reference in New Issue
Block a user