diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtParameter.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtParameter.java index bd49aceb1eb..d09d68694ac 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtParameter.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtParameter.java @@ -140,8 +140,39 @@ public class KtParameter extends KtNamedDeclarationStub imp return getParent() instanceof KtForExpression; } + private boolean checkParentOfParentType(Class klass) { + // `parent` is supposed to be [KtParameterList] + PsiElement parent = getParent(); + if (parent == null) { + return false; + } + return klass.isInstance(parent.getParent()); + } + public boolean isCatchParameter() { - return getParent().getParent() instanceof KtCatchClause; + return checkParentOfParentType(KtCatchClause.class); + } + + /** + * For example, + * lambdaConsumer { lambdaParameter -> + * ... + * } + * + * @return [true] if this [KtParameter] is a parameter of a lambda. + */ + public boolean isLambdaParameter() { + return checkParentOfParentType(KtFunctionLiteral.class); + } + + /** + * For example, + * fun foo(lambdaArgument: (functionTypeParameter: T, ...) -> R) { ... } + * + * @return [true] if this [KtParameter] is a parameter of a function type. + */ + public boolean isFunctionTypeParameter() { + return checkParentOfParentType(KtFunctionType.class); } @Nullable diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt index 4402477562b..6c1bd812df4 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt @@ -57,6 +57,12 @@ public interface KtSymbolProviderMixIn : KtAnalysisSessionMixIn { public fun KtDeclaration.getSymbol(): KtSymbol = analysisSession.symbolProvider.getSymbol(this) + /** + * Creates [KtValueParameterSymbol] by [KtParameter] + * + * 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. + */ public fun KtParameter.getParameterSymbol(): KtValueParameterSymbol = analysisSession.symbolProvider.getParameterSymbol(this) @@ -117,4 +123,4 @@ public interface KtSymbolProviderMixIn : KtAnalysisSessionMixIn { @Suppress("PropertyName") public val ROOT_PACKAGE_SYMBOL: KtPackageSymbol get() = analysisSession.symbolProvider.ROOT_PACKAGE_SYMBOL -} \ No newline at end of file +} diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt index 3dad120cc16..a5495afb0d9 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt @@ -35,6 +35,9 @@ internal class KtFirSymbolProvider( 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) } diff --git a/idea/idea-frontend-fir/testData/symbols/symbolByPsi/implicitReturnInLambda.kt b/idea/idea-frontend-fir/testData/symbols/symbolByPsi/implicitReturnInLambda.kt index c4146816b23..46836b8691c 100644 --- a/idea/idea-frontend-fir/testData/symbols/symbolByPsi/implicitReturnInLambda.kt +++ b/idea/idea-frontend-fir/testData/symbols/symbolByPsi/implicitReturnInLambda.kt @@ -11,6 +11,16 @@ fun foo() { else a - c } + + bar { + if (it > 5) return + val b = 1 + it + b + } +} + +private inline fun bar(lmbd: (Int) -> Int) { + lmbd(1) } // RESULT @@ -99,6 +109,25 @@ KtFirLocalVariableSymbol: receiverType: null symbolKind: LOCAL +KtFirLocalVariableSymbol: + annotatedType: [] kotlin/Int + callableIdIfNonLocal: null + isExtension: false + isVal: true + name: b + origin: SOURCE + receiverType: null + symbolKind: LOCAL + +KtFirAnonymousFunctionSymbol: + annotatedType: [] kotlin/Int + callableIdIfNonLocal: null + isExtension: false + origin: SOURCE + receiverType: null + symbolKind: LOCAL + valueParameters: [KtFirValueParameterSymbol(it)] + KtFirFunctionSymbol: annotatedType: [] kotlin/Unit annotationClassIds: [] @@ -121,4 +150,40 @@ KtFirFunctionSymbol: typeParameters: [] valueParameters: [] visibility: Public - */ + +KtFirValueParameterSymbol: + annotatedType: [] kotlin/Function1 + annotationClassIds: [] + annotations: [] + callableIdIfNonLocal: null + hasDefaultValue: false + isExtension: false + isVararg: false + name: lmbd + origin: SOURCE + receiverType: null + symbolKind: LOCAL + +KtFirFunctionSymbol: + annotatedType: [] kotlin/Unit + annotationClassIds: [] + annotations: [] + callableIdIfNonLocal: /bar + dispatchType: null + isExtension: false + isExternal: false + isInfix: false + isInline: true + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: FINAL + name: bar + origin: SOURCE + receiverType: null + symbolKind: TOP_LEVEL + typeParameters: [] + valueParameters: [KtFirValueParameterSymbol(lmbd)] + visibility: Private +*/ diff --git a/idea/idea-frontend-fir/testData/symbols/symbolByPsi/implicitReturnInLambda.txt b/idea/idea-frontend-fir/testData/symbols/symbolByPsi/implicitReturnInLambda.txt index 39b87dc871c..95cea9147b0 100644 --- a/idea/idea-frontend-fir/testData/symbols/symbolByPsi/implicitReturnInLambda.txt +++ b/idea/idea-frontend-fir/testData/symbols/symbolByPsi/implicitReturnInLambda.txt @@ -82,6 +82,25 @@ KtFirLocalVariableSymbol: receiverType: null symbolKind: LOCAL +KtFirLocalVariableSymbol: + annotatedType: [] kotlin/Int + callableIdIfNonLocal: null + isExtension: false + isVal: true + name: b + origin: SOURCE + receiverType: null + symbolKind: LOCAL + +KtFirAnonymousFunctionSymbol: + annotatedType: [] kotlin/Int + callableIdIfNonLocal: null + isExtension: false + origin: SOURCE + receiverType: null + symbolKind: LOCAL + valueParameters: [KtFirValueParameterSymbol(it)] + KtFirFunctionSymbol: annotatedType: [] kotlin/Unit annotationClassIds: [] @@ -104,3 +123,39 @@ KtFirFunctionSymbol: typeParameters: [] valueParameters: [] visibility: Public + +KtFirValueParameterSymbol: + annotatedType: [] kotlin/Function1 + annotationClassIds: [] + annotations: [] + callableIdIfNonLocal: null + hasDefaultValue: false + isExtension: false + isVararg: false + name: lmbd + origin: SOURCE + receiverType: null + symbolKind: LOCAL + +KtFirFunctionSymbol: + annotatedType: [] kotlin/Unit + annotationClassIds: [] + annotations: [] + callableIdIfNonLocal: /bar + dispatchType: null + isExtension: false + isExternal: false + isInfix: false + isInline: true + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: FINAL + name: bar + origin: SOURCE + receiverType: null + symbolKind: TOP_LEVEL + typeParameters: [] + valueParameters: [KtFirValueParameterSymbol(lmbd)] + visibility: Private diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/fir/frontend/api/symbols/AbstractSymbolByPsiTest.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/fir/frontend/api/symbols/AbstractSymbolByPsiTest.kt index 10ad09f86ea..69f06e09d10 100644 --- a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/fir/frontend/api/symbols/AbstractSymbolByPsiTest.kt +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/fir/frontend/api/symbols/AbstractSymbolByPsiTest.kt @@ -9,13 +9,21 @@ import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType import org.jetbrains.kotlin.test.services.TestServices abstract class AbstractSymbolByPsiTest : AbstractSymbolTest() { override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): List { - return ktFile.collectDescendantsOfType().map { declaration -> + return ktFile.collectDescendantsOfType { it.isValidForSymbolCreation }.map { declaration -> declaration.getSymbol() } } -} \ No newline at end of file + + private val KtDeclaration.isValidForSymbolCreation + get() = + when (this) { + is KtParameter -> !this.isFunctionTypeParameter + else -> true + } +}