From 9113ccb8fc487a46f541a5597cbb647abf22868e Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Thu, 7 Oct 2021 15:57:13 +0300 Subject: [PATCH] [FIR IDE] Properly support loop variables in `KtFirSymbolProvider` --- .../api/fir/symbols/KtFirSymbolProvider.kt | 19 ++++++---- .../fir/symbols/SymbolByPsiTestGenerated.java | 6 ++++ .../analysis/api/symbols/KtSymbolProvider.kt | 14 ++++++-- .../symbols/symbolByPsi/forLoopVariable.kt | 3 ++ .../symbols/symbolByPsi/forLoopVariable.txt | 35 +++++++++++++++++++ 5 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 analysis/analysis-api/testData/symbols/symbolByPsi/forLoopVariable.kt create mode 100644 analysis/analysis-api/testData/symbols/symbolByPsi/forLoopVariable.txt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt index 176f08c19fb..cb5275942a0 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt @@ -35,12 +35,19 @@ internal class KtFirSymbolProvider( ) : KtSymbolProvider(), ValidityTokenOwner { private val firSymbolProvider by weakRef(firSymbolProvider) - override fun getParameterSymbol(psi: KtParameter): KtValueParameterSymbol = withValidityAssertion { - if (psi.isFunctionTypeParameter) { - error("Creating KtValueParameterSymbol for function type parameter is not possible. Please see the KDoc of getParameterSymbol") - } - psi.withFirDeclarationOfType(resolveState) { - firSymbolBuilder.variableLikeBuilder.buildValueParameterSymbol(it) + override fun getParameterSymbol(psi: KtParameter): KtVariableLikeSymbol = withValidityAssertion { + when { + psi.isFunctionTypeParameter -> error( + "Creating KtValueParameterSymbol for function type parameter is not possible. Please see the KDoc of getParameterSymbol" + ) + + psi.isLoopParameter -> psi.withFirDeclarationOfType(resolveState) { + firSymbolBuilder.variableLikeBuilder.buildLocalVariableSymbol(it) + } + + else -> psi.withFirDeclarationOfType(resolveState) { + firSymbolBuilder.variableLikeBuilder.buildValueParameterSymbol(it) + } } } diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/symbols/SymbolByPsiTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/symbols/SymbolByPsiTestGenerated.java index c4158e2f6ef..3c0bd49d359 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/symbols/SymbolByPsiTestGenerated.java +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/symbols/SymbolByPsiTestGenerated.java @@ -102,6 +102,12 @@ public class SymbolByPsiTestGenerated extends AbstractSymbolByPsiTest { runTest("analysis/analysis-api/testData/symbols/symbolByPsi/extensionFunction.kt"); } + @Test + @TestMetadata("forLoopVariable.kt") + public void testForLoopVariable() throws Exception { + runTest("analysis/analysis-api/testData/symbols/symbolByPsi/forLoopVariable.kt"); + } + @Test @TestMetadata("function.kt") public void testFunction() throws Exception { diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbolProvider.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbolProvider.kt index b35aadccb40..241fd438fb8 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbolProvider.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbolProvider.kt @@ -31,7 +31,7 @@ public abstract class KtSymbolProvider : KtAnalysisSessionComponent() { else -> error("Cannot build symbol for ${psi::class}") } - public abstract fun getParameterSymbol(psi: KtParameter): KtValueParameterSymbol + public abstract fun getParameterSymbol(psi: KtParameter): KtVariableLikeSymbol public abstract fun getFileSymbol(psi: KtFile): KtFileSymbol public abstract fun getFunctionLikeSymbol(psi: KtNamedFunction): KtFunctionLikeSymbol public abstract fun getConstructorSymbol(psi: KtConstructor<*>): KtConstructorSymbol @@ -60,12 +60,20 @@ public interface KtSymbolProviderMixIn : KtAnalysisSessionMixIn { analysisSession.symbolProvider.getSymbol(this) /** - * Creates [KtValueParameterSymbol] by [KtParameter] + * Creates [KtVariableLikeSymbol] by [KtParameter]. + * + * Unfortunately, [KtParameter] in PSI stands for many things, and not all of them are represented by a single type of symbol, + * so this function does not work for all possible [KtParameter]s. * * If [KtParameter.isFunctionTypeParameter] is `true`, i.e., if the given [KtParameter] is used as a function type parameter, * it is not possible to create [KtValueParameterSymbol], hence an error will be raised. + * + * If [KtParameter.isLoopParameter] is `true`, i.e. if the given [KtParameter] is a loop variable in `for` expression, then the function + * returns [KtLocalVariableSymbol]. + * + * Otherwise, returns [KtValueParameterSymbol]. */ - public fun KtParameter.getParameterSymbol(): KtValueParameterSymbol = + public fun KtParameter.getParameterSymbol(): KtVariableLikeSymbol = analysisSession.symbolProvider.getParameterSymbol(this) /** diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/forLoopVariable.kt b/analysis/analysis-api/testData/symbols/symbolByPsi/forLoopVariable.kt new file mode 100644 index 00000000000..eb58fafb8c5 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/forLoopVariable.kt @@ -0,0 +1,3 @@ +fun usage() { + for (loopVariable in 1..10) {} +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/forLoopVariable.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/forLoopVariable.txt new file mode 100644 index 00000000000..654dcb72fea --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/forLoopVariable.txt @@ -0,0 +1,35 @@ +KtFirLocalVariableSymbol: + annotatedType: [] kotlin/Int + callableIdIfNonLocal: null + isExtension: false + isVal: true + name: loopVariable + origin: SOURCE + receiverType: null + symbolKind: LOCAL + deprecationStatus: null + +KtFirFunctionSymbol: + annotatedType: [] kotlin/Unit + annotationClassIds: [] + annotations: [] + callableIdIfNonLocal: /usage + dispatchType: null + hasStableParameterNames: true + isExtension: false + isExternal: false + isInfix: false + isInline: false + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: FINAL + name: usage + origin: SOURCE + receiverType: null + symbolKind: TOP_LEVEL + typeParameters: [] + valueParameters: [] + visibility: Public + deprecationStatus: null