From c10879be43ea46b305f5314921cb7dc9e867666f Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Mon, 11 Oct 2021 13:38:11 -0700 Subject: [PATCH] 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. --- .../components/KtFirExpressionTypeProvider.kt | 50 +++++++++++++------ .../HLExpressionTypeTestGenerated.java | 24 +++++++++ .../expressionType/resolvedSuper.kt | 9 ++++ .../expressionType/resolvedSuper.txt | 2 + .../unresolvedSuper_multipleSuperTypes.kt | 13 +++++ .../unresolvedSuper_multipleSuperTypes.txt | 2 + .../unresolvedSuper_noSuperType.kt | 5 ++ .../unresolvedSuper_noSuperType.txt | 2 + .../unresolvedSuper_singleSuperType.kt | 9 ++++ .../unresolvedSuper_singleSuperType.txt | 2 + 10 files changed, 103 insertions(+), 15 deletions(-) create mode 100644 analysis/analysis-api/testData/components/expressionType/resolvedSuper.kt create mode 100644 analysis/analysis-api/testData/components/expressionType/resolvedSuper.txt create mode 100644 analysis/analysis-api/testData/components/expressionType/unresolvedSuper_multipleSuperTypes.kt create mode 100644 analysis/analysis-api/testData/components/expressionType/unresolvedSuper_multipleSuperTypes.txt create mode 100644 analysis/analysis-api/testData/components/expressionType/unresolvedSuper_noSuperType.kt create mode 100644 analysis/analysis-api/testData/components/expressionType/unresolvedSuper_noSuperType.txt create mode 100644 analysis/analysis-api/testData/components/expressionType/unresolvedSuper_singleSuperType.kt create mode 100644 analysis/analysis-api/testData/components/expressionType/unresolvedSuper_singleSuperType.txt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionTypeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionTypeProvider.kt index 6f8d1b0cdba..f5336ceb90f 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionTypeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionTypeProvider.kt @@ -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 } diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/HLExpressionTypeTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/HLExpressionTypeTestGenerated.java index 7251c17423a..702d5432c45 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/HLExpressionTypeTestGenerated.java +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/HLExpressionTypeTestGenerated.java @@ -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 { diff --git a/analysis/analysis-api/testData/components/expressionType/resolvedSuper.kt b/analysis/analysis-api/testData/components/expressionType/resolvedSuper.kt new file mode 100644 index 00000000000..f4ea169dfe1 --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionType/resolvedSuper.kt @@ -0,0 +1,9 @@ +interface A { + fun foo() {} +} + +class B : A { + fun test() { + super.foo() + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/expressionType/resolvedSuper.txt b/analysis/analysis-api/testData/components/expressionType/resolvedSuper.txt new file mode 100644 index 00000000000..71ed2e6db70 --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionType/resolvedSuper.txt @@ -0,0 +1,2 @@ +expression: super +type: A diff --git a/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_multipleSuperTypes.kt b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_multipleSuperTypes.kt new file mode 100644 index 00000000000..e2b63ff5076 --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_multipleSuperTypes.kt @@ -0,0 +1,13 @@ +interface A { + fun foo() {} +} + +interface B { + fun bar() {} +} + +class C : A, B { + fun test() { + super.unresolved() + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_multipleSuperTypes.txt b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_multipleSuperTypes.txt new file mode 100644 index 00000000000..af0255678cd --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_multipleSuperTypes.txt @@ -0,0 +1,2 @@ +expression: super +type: (A&B) diff --git a/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_noSuperType.kt b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_noSuperType.kt new file mode 100644 index 00000000000..92f56f8890f --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_noSuperType.kt @@ -0,0 +1,5 @@ +class Foo { + fun test() { + super.unresolved() + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_noSuperType.txt b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_noSuperType.txt new file mode 100644 index 00000000000..abd5b7f18ba --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_noSuperType.txt @@ -0,0 +1,2 @@ +expression: super +type: kotlin.Any diff --git a/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_singleSuperType.kt b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_singleSuperType.kt new file mode 100644 index 00000000000..6fdcb9676ad --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_singleSuperType.kt @@ -0,0 +1,9 @@ +interface A { + fun foo() {} +} + +class B : A { + fun test() { + super.unresolved() + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_singleSuperType.txt b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_singleSuperType.txt new file mode 100644 index 00000000000..71ed2e6db70 --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionType/unresolvedSuper_singleSuperType.txt @@ -0,0 +1,2 @@ +expression: super +type: A