From 197079c85cf292c9d62044efd03f5656ab53db97 Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Wed, 3 Nov 2021 10:34:49 -0700 Subject: [PATCH] FIR IDE: make smartcast API return unstable smartcasts --- .../components/KtFe10SmartCastProvider.kt | 24 ++++-- .../AbstractKtFe10HLSmartCastInfoTest.kt | 11 +++ .../KtFe10HLSmartCastInfoTestGenerated.java | 74 +++++++++++++++++++ .../fir/components/KtFirSmartcastProvider.kt | 30 ++++---- .../AbstractFirHLSmartCastInfoTest.kt | 11 +++ .../FirHLSmartCastInfoTestGenerated.java | 74 +++++++++++++++++++ .../components/AbstractHLSmartCastInfoTest.kt | 34 +++++++++ .../api/components/KtSmartCastProvider.kt | 11 ++- ...SmartcastAsReceiver_stable.descriptors.txt | 3 + .../multiSmartcastAsReceiver_stable.kt | 10 +++ .../multiSmartcastAsReceiver_stable.txt | 3 + ...artcastAsReceiver_unstable.descriptors.txt | 3 + .../multiSmartcastAsReceiver_unstable.kt | 11 +++ .../multiSmartcastAsReceiver_unstable.txt | 3 + .../multiSmartcast_stable.descriptors.txt | 3 + .../smartCastInfo/multiSmartcast_stable.kt | 8 ++ .../smartCastInfo/multiSmartcast_stable.txt | 3 + .../multiSmartcast_unstable.descriptors.txt | 3 + .../smartCastInfo/multiSmartcast_unstable.kt | 9 +++ .../smartCastInfo/multiSmartcast_unstable.txt | 3 + .../smartcastAsReceiver_stable.kt | 5 ++ .../smartcastAsReceiver_stable.txt | 3 + .../smartcastAsReceiver_unstable.kt | 6 ++ .../smartcastAsReceiver_unstable.txt | 3 + .../smartcast_stable.descriptors.txt | 3 + .../smartCastInfo/smartcast_stable.kt | 5 ++ .../smartCastInfo/smartcast_stable.txt | 3 + .../smartcast_unstable.descriptors.txt | 3 + .../smartCastInfo/smartcast_unstable.kt | 6 ++ .../smartCastInfo/smartcast_unstable.txt | 3 + .../analysis/api/GenerateAnalysisApiTests.kt | 8 ++ 31 files changed, 356 insertions(+), 23 deletions(-) create mode 100644 analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/descriptors/test/components/AbstractKtFe10HLSmartCastInfoTest.kt create mode 100644 analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/descriptors/test/components/KtFe10HLSmartCastInfoTestGenerated.java create mode 100644 analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractFirHLSmartCastInfoTest.kt create mode 100644 analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/FirHLSmartCastInfoTestGenerated.java create mode 100644 analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/components/AbstractHLSmartCastInfoTest.kt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.descriptors.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.kt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.descriptors.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.kt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.descriptors.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.kt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.descriptors.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.kt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_stable.kt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_stable.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_unstable.kt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_unstable.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.descriptors.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.kt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.descriptors.txt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.kt create mode 100644 analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.txt diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SmartCastProvider.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SmartCastProvider.kt index 5e7c15574b1..54cbcf009e4 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SmartCastProvider.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SmartCastProvider.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.api.descriptors.components import org.jetbrains.kotlin.analysis.api.ImplicitReceiverSmartCast import org.jetbrains.kotlin.analysis.api.ImplicitReceiverSmartcastKind import org.jetbrains.kotlin.analysis.api.components.KtSmartCastProvider +import org.jetbrains.kotlin.analysis.api.components.SmartCastInfo import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtType import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken @@ -15,6 +16,7 @@ import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.api.withValidityAssertion import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.smartcasts.ExplicitSmartCasts import org.jetbrains.kotlin.resolve.calls.smartcasts.MultipleSmartCasts import org.jetbrains.kotlin.types.TypeIntersector @@ -22,19 +24,29 @@ internal class KtFe10SmartCastProvider(override val analysisSession: KtFe10Analy override val token: ValidityToken get() = analysisSession.token - override fun getSmartCastedToType(expression: KtExpression): KtType? { + override fun getSmartCastedInfo(expression: KtExpression): SmartCastInfo? { withValidityAssertion { val bindingContext = analysisSession.analyze(expression) - val smartCasts = bindingContext[BindingContext.SMARTCAST, expression] ?: return null + val stableSmartCasts = bindingContext[BindingContext.SMARTCAST, expression] - if (smartCasts is MultipleSmartCasts) { - return TypeIntersector.intersectTypes(smartCasts.map.values)?.toKtType(analysisSession) + return when { + stableSmartCasts != null -> { + val type = stableSmartCasts.getKtType() ?: return null + SmartCastInfo(type, true) + } + // TODO: collect unstable smartcast here. + else -> null } - - return smartCasts.defaultType?.toKtType(analysisSession) } } + private fun ExplicitSmartCasts.getKtType(): KtType? { + if (this is MultipleSmartCasts) { + return TypeIntersector.intersectTypes(map.values)?.toKtType(analysisSession) + } + return defaultType?.toKtType(analysisSession) + } + override fun getImplicitReceiverSmartCast(expression: KtExpression): Collection { withValidityAssertion { val bindingContext = analysisSession.analyze(expression) diff --git a/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/descriptors/test/components/AbstractKtFe10HLSmartCastInfoTest.kt b/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/descriptors/test/components/AbstractKtFe10HLSmartCastInfoTest.kt new file mode 100644 index 00000000000..d97fcbe7f48 --- /dev/null +++ b/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/descriptors/test/components/AbstractKtFe10HLSmartCastInfoTest.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.descriptors.test.components + +import org.jetbrains.kotlin.analysis.api.descriptors.test.KtFe10FrontendApiTestConfiguratorService +import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractHLSmartCastInfoTest + +abstract class AbstractKtFe10HLSmartCastInfoTest : AbstractHLSmartCastInfoTest(KtFe10FrontendApiTestConfiguratorService) \ No newline at end of file diff --git a/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/descriptors/test/components/KtFe10HLSmartCastInfoTestGenerated.java b/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/descriptors/test/components/KtFe10HLSmartCastInfoTestGenerated.java new file mode 100644 index 00000000000..ed386bf1950 --- /dev/null +++ b/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/descriptors/test/components/KtFe10HLSmartCastInfoTestGenerated.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.descriptors.test.components; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("analysis/analysis-api/testData/components/smartCastInfo") +@TestDataPath("$PROJECT_ROOT") +public class KtFe10HLSmartCastInfoTestGenerated extends AbstractKtFe10HLSmartCastInfoTest { + @Test + public void testAllFilesPresentInSmartCastInfo() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/smartCastInfo"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("multiSmartcastAsReceiver_stable.kt") + public void testMultiSmartcastAsReceiver_stable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.kt"); + } + + @Test + @TestMetadata("multiSmartcastAsReceiver_unstable.kt") + public void testMultiSmartcastAsReceiver_unstable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.kt"); + } + + @Test + @TestMetadata("multiSmartcast_stable.kt") + public void testMultiSmartcast_stable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.kt"); + } + + @Test + @TestMetadata("multiSmartcast_unstable.kt") + public void testMultiSmartcast_unstable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.kt"); + } + + @Test + @TestMetadata("smartcastAsReceiver_stable.kt") + public void testSmartcastAsReceiver_stable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_stable.kt"); + } + + @Test + @TestMetadata("smartcastAsReceiver_unstable.kt") + public void testSmartcastAsReceiver_unstable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_unstable.kt"); + } + + @Test + @TestMetadata("smartcast_stable.kt") + public void testSmartcast_stable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.kt"); + } + + @Test + @TestMetadata("smartcast_unstable.kt") + public void testSmartcast_unstable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.kt"); + } +} diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSmartcastProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSmartcastProvider.kt index 1aa79bdcb68..34c5949c644 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSmartcastProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSmartcastProvider.kt @@ -5,31 +5,33 @@ package org.jetbrains.kotlin.analysis.api.fir.components +import org.jetbrains.kotlin.analysis.api.ImplicitReceiverSmartCast +import org.jetbrains.kotlin.analysis.api.ImplicitReceiverSmartcastKind +import org.jetbrains.kotlin.analysis.api.components.KtSmartCastProvider +import org.jetbrains.kotlin.analysis.api.components.SmartCastInfo +import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken +import org.jetbrains.kotlin.analysis.api.withValidityAssertion +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.fir.types.isStableSmartcast -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe -import org.jetbrains.kotlin.analysis.api.ImplicitReceiverSmartCast -import org.jetbrains.kotlin.analysis.api.ImplicitReceiverSmartcastKind -import org.jetbrains.kotlin.analysis.api.components.KtSmartCastProvider -import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession -import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken -import org.jetbrains.kotlin.analysis.api.types.KtType -import org.jetbrains.kotlin.analysis.api.withValidityAssertion import org.jetbrains.kotlin.psi.KtExpression internal class KtFirSmartcastProvider( override val analysisSession: KtFirAnalysisSession, override val token: ValidityToken, ) : KtSmartCastProvider(), KtFirAnalysisSessionComponent { - override fun getSmartCastedToType(expression: KtExpression): KtType? = withValidityAssertion { - expression.getOrBuildFirSafe(analysisSession.firResolveState) - ?.takeIf { it.isStable } - ?.typeRef - ?.coneTypeSafe() - ?.asKtType() + override fun getSmartCastedInfo(expression: KtExpression): SmartCastInfo? = withValidityAssertion { + val smartCastExpression = + expression.getOrBuildFirSafe(analysisSession.firResolveState) ?: return@withValidityAssertion null + SmartCastInfo( + smartCastExpression.smartcastType.coneTypeSafe()?.asKtType() ?: return@withValidityAssertion null, + smartCastExpression.isStable + ) + } @OptIn(ExperimentalStdlibApi::class) diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractFirHLSmartCastInfoTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractFirHLSmartCastInfoTest.kt new file mode 100644 index 00000000000..94e0649dfdd --- /dev/null +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractFirHLSmartCastInfoTest.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.fir.components + +import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService +import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractHLSmartCastInfoTest + +abstract class AbstractFirHLSmartCastInfoTest : AbstractHLSmartCastInfoTest(FirFrontendApiTestConfiguratorService) \ No newline at end of file diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/FirHLSmartCastInfoTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/FirHLSmartCastInfoTestGenerated.java new file mode 100644 index 00000000000..6a5b604ba27 --- /dev/null +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/FirHLSmartCastInfoTestGenerated.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.fir.components; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("analysis/analysis-api/testData/components/smartCastInfo") +@TestDataPath("$PROJECT_ROOT") +public class FirHLSmartCastInfoTestGenerated extends AbstractFirHLSmartCastInfoTest { + @Test + public void testAllFilesPresentInSmartCastInfo() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/smartCastInfo"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("multiSmartcastAsReceiver_stable.kt") + public void testMultiSmartcastAsReceiver_stable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.kt"); + } + + @Test + @TestMetadata("multiSmartcastAsReceiver_unstable.kt") + public void testMultiSmartcastAsReceiver_unstable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.kt"); + } + + @Test + @TestMetadata("multiSmartcast_stable.kt") + public void testMultiSmartcast_stable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.kt"); + } + + @Test + @TestMetadata("multiSmartcast_unstable.kt") + public void testMultiSmartcast_unstable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.kt"); + } + + @Test + @TestMetadata("smartcastAsReceiver_stable.kt") + public void testSmartcastAsReceiver_stable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_stable.kt"); + } + + @Test + @TestMetadata("smartcastAsReceiver_unstable.kt") + public void testSmartcastAsReceiver_unstable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_unstable.kt"); + } + + @Test + @TestMetadata("smartcast_stable.kt") + public void testSmartcast_stable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.kt"); + } + + @Test + @TestMetadata("smartcast_unstable.kt") + public void testSmartcast_unstable() throws Exception { + runTest("analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.kt"); + } +} diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/components/AbstractHLSmartCastInfoTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/components/AbstractHLSmartCastInfoTest.kt new file mode 100644 index 00000000000..6614c6cea45 --- /dev/null +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/components/AbstractHLSmartCastInfoTest.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.impl.base.test.components + +import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService +import org.jetbrains.kotlin.analysis.api.impl.barebone.test.expressionMarkerProvider +import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleFileTest +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.assertions + +abstract class AbstractHLSmartCastInfoTest(configurator: FrontendApiTestConfiguratorService) : AbstractHLApiSingleFileTest(configurator) { + override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) { + super.doTestByFileStructure(ktFile, module, testServices) + + val expression = testServices.expressionMarkerProvider.getSelectedElement(ktFile) as KtExpression + val actual = executeOnPooledThreadInReadAction { + analyseForTest(expression) { + val smartCastInfo = expression.getSmartCastInfo() + buildString { + appendLine("expression: ${expression.text}") + appendLine("isStable: ${smartCastInfo?.isStable}") + appendLine("smartCastType: ${smartCastInfo?.smartCastType?.render()}") + } + } + } + testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual) + } +} \ No newline at end of file diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSmartCastProvider.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSmartCastProvider.kt index 18598ccace2..f86e5c71444 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSmartCastProvider.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSmartCastProvider.kt @@ -10,13 +10,18 @@ import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.psi.KtExpression public abstract class KtSmartCastProvider : KtAnalysisSessionComponent() { - public abstract fun getSmartCastedToType(expression: KtExpression): KtType? + public abstract fun getSmartCastedInfo(expression: KtExpression): SmartCastInfo? public abstract fun getImplicitReceiverSmartCast(expression: KtExpression): Collection } +public class SmartCastInfo(public val smartCastType: KtType, public val isStable: Boolean) + public interface KtSmartCastProviderMixIn : KtAnalysisSessionMixIn { - public fun KtExpression.getSmartCast(): KtType? = - analysisSession.smartCastProvider.getSmartCastedToType(this) + /** + * Gets the smart-cast information of the given expression or null if the expression is not smart casted. + */ + public fun KtExpression.getSmartCastInfo(): SmartCastInfo? = + analysisSession.smartCastProvider.getSmartCastedInfo(this) public fun KtExpression.getImplicitReceiverSmartCast(): Collection = analysisSession.smartCastProvider.getImplicitReceiverSmartCast(this) diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.descriptors.txt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.descriptors.txt new file mode 100644 index 00000000000..50cbb6e17c6 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.descriptors.txt @@ -0,0 +1,3 @@ +expression: a +isStable: null +smartCastType: null diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.kt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.kt new file mode 100644 index 00000000000..5a40be8479b --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.kt @@ -0,0 +1,10 @@ +interface A +interface B + +fun T.foo() where T: A, T: B {} + +fun test(a: Any) { + if (a is A && a is B) { + a.foo() + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.txt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.txt new file mode 100644 index 00000000000..b8dad70637f --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_stable.txt @@ -0,0 +1,3 @@ +expression: a +isStable: true +smartCastType: (A&B) diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.descriptors.txt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.descriptors.txt new file mode 100644 index 00000000000..50cbb6e17c6 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.descriptors.txt @@ -0,0 +1,3 @@ +expression: a +isStable: null +smartCastType: null diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.kt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.kt new file mode 100644 index 00000000000..32ee243a32f --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.kt @@ -0,0 +1,11 @@ +interface A +interface B + +fun T.foo() where T: A, T: B {} + +var a: Any = 1 +fun test() { + if (a is A && a is B) { + a.foo() + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.txt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.txt new file mode 100644 index 00000000000..f22c2fd9521 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcastAsReceiver_unstable.txt @@ -0,0 +1,3 @@ +expression: a +isStable: false +smartCastType: (A&B) diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.descriptors.txt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.descriptors.txt new file mode 100644 index 00000000000..50cbb6e17c6 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.descriptors.txt @@ -0,0 +1,3 @@ +expression: a +isStable: null +smartCastType: null diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.kt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.kt new file mode 100644 index 00000000000..03f8c4d46f1 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.kt @@ -0,0 +1,8 @@ +interface A +interface B + +fun test(a: Any) { + if (a is A && a is B) { + a + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.txt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.txt new file mode 100644 index 00000000000..b8dad70637f --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_stable.txt @@ -0,0 +1,3 @@ +expression: a +isStable: true +smartCastType: (A&B) diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.descriptors.txt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.descriptors.txt new file mode 100644 index 00000000000..50cbb6e17c6 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.descriptors.txt @@ -0,0 +1,3 @@ +expression: a +isStable: null +smartCastType: null diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.kt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.kt new file mode 100644 index 00000000000..d24f84e0fc8 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.kt @@ -0,0 +1,9 @@ +interface A +interface B + +var a: Any = 1 +fun test() { + if (a is A && a is B) { + a + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.txt b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.txt new file mode 100644 index 00000000000..f22c2fd9521 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/multiSmartcast_unstable.txt @@ -0,0 +1,3 @@ +expression: a +isStable: false +smartCastType: (A&B) diff --git a/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_stable.kt b/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_stable.kt new file mode 100644 index 00000000000..6a07e02836d --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_stable.kt @@ -0,0 +1,5 @@ +fun test(a: Any) { + if (a is String) { + a.length + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_stable.txt b/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_stable.txt new file mode 100644 index 00000000000..7204410ba7b --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_stable.txt @@ -0,0 +1,3 @@ +expression: a +isStable: true +smartCastType: kotlin.String diff --git a/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_unstable.kt b/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_unstable.kt new file mode 100644 index 00000000000..ee87f5ed128 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_unstable.kt @@ -0,0 +1,6 @@ +var a: Any = 1 +fun test() { + if (a is String) { + a.length + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_unstable.txt b/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_unstable.txt new file mode 100644 index 00000000000..50cbb6e17c6 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/smartcastAsReceiver_unstable.txt @@ -0,0 +1,3 @@ +expression: a +isStable: null +smartCastType: null diff --git a/analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.descriptors.txt b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.descriptors.txt new file mode 100644 index 00000000000..50cbb6e17c6 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.descriptors.txt @@ -0,0 +1,3 @@ +expression: a +isStable: null +smartCastType: null diff --git a/analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.kt b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.kt new file mode 100644 index 00000000000..83b06340d2f --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.kt @@ -0,0 +1,5 @@ +fun test(a: Any) { + if (a is String) { + a + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.txt b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.txt new file mode 100644 index 00000000000..7204410ba7b --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_stable.txt @@ -0,0 +1,3 @@ +expression: a +isStable: true +smartCastType: kotlin.String diff --git a/analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.descriptors.txt b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.descriptors.txt new file mode 100644 index 00000000000..50cbb6e17c6 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.descriptors.txt @@ -0,0 +1,3 @@ +expression: a +isStable: null +smartCastType: null diff --git a/analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.kt b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.kt new file mode 100644 index 00000000000..7f6fa4440ff --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.kt @@ -0,0 +1,6 @@ +var a: Any = 1 +fun test() { + if (a is String) { + a + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.txt b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.txt new file mode 100644 index 00000000000..7b477c75631 --- /dev/null +++ b/analysis/analysis-api/testData/components/smartCastInfo/smartcast_unstable.txt @@ -0,0 +1,3 @@ +expression: a +isStable: false +smartCastType: kotlin.String diff --git a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/GenerateAnalysisApiTests.kt b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/GenerateAnalysisApiTests.kt index 23c93382d59..b18da52e98b 100644 --- a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/GenerateAnalysisApiTests.kt +++ b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/GenerateAnalysisApiTests.kt @@ -108,6 +108,10 @@ fun main(args: Array) { testClass { model("components/psiTypeProvider") } + + testClass { + model("components/smartCastInfo") + } } testGroup("analysis/analysis-api-fe10/tests", "analysis/analysis-api/testData") { @@ -162,6 +166,10 @@ fun main(args: Array) { testClass { model("components/hasCommonSubtype") } + + testClass { + model("components/smartCastInfo") + } } testGroup("analysis/low-level-api-fir/tests", "compiler/fir/raw-fir/psi2fir/testData") {