From a90562c0da1fe48fba31383befcb02cc28a8f180 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 23 Oct 2023 17:08:09 +0200 Subject: [PATCH] [Analysis API] support creating KtSymbol by K/JS dynamic scope ^KT-61257 fixed --- ...Fe10SymbolContainingDeclarationProvider.kt | 5 ++ .../KtFe10DescFunctionSymbol.kt | 32 +++++++- .../KtFe10DescKotlinPropertySymbol.kt | 16 +++- ...DynamicFunctionDescValueParameterSymbol.kt | 81 +++++++++++++++++++ .../descriptorBased/base/Kt1DescUtils.kt | 8 +- ...eModuleSymbolByReferenceTestGenerated.java | 28 +++++++ ...tFirSymbolContainingDeclarationProvider.kt | 11 ++- .../api/fir/symbols/KtFirFunctionSymbol.kt | 2 + .../fir/symbols/KtFirKotlinPropertySymbol.kt | 3 + .../analysis/api/fir/symbols/KtFirSymbol.kt | 6 +- .../api/fir/symbols/firSymbolUtils.kt | 21 ++++- ...eModuleSymbolByReferenceTestGenerated.java | 10 +++ ...eModuleSymbolByReferenceTestGenerated.java | 28 +++++++ ...eModuleSymbolByReferenceTestGenerated.java | 28 +++++++ .../kotlin/analysis/api/symbols/KtSymbol.kt | 8 ++ .../functionFromJsDynamicScopeNoArguments.kt | 6 ++ ...onFromJsDynamicScopeNoArguments.pretty.txt | 1 + .../functionFromJsDynamicScopeNoArguments.txt | 55 +++++++++++++ ...functionFromJsDynamicScopeWithArguments.kt | 6 ++ ...FromJsDynamicScopeWithArguments.pretty.txt | 1 + ...unctionFromJsDynamicScopeWithArguments.txt | 55 +++++++++++++ .../js/propertyFromJsDynamicScope.kt | 6 ++ .../js/propertyFromJsDynamicScope.pretty.txt | 1 + .../js/propertyFromJsDynamicScope.txt | 40 +++++++++ .../kotlin/fir/scopes/impl/FirDynamicScope.kt | 1 + 25 files changed, 441 insertions(+), 18 deletions(-) create mode 100644 analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DynamicFunctionDescValueParameterSymbol.kt create mode 100644 analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.kt create mode 100644 analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.pretty.txt create mode 100644 analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.txt create mode 100644 analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.kt create mode 100644 analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.pretty.txt create mode 100644 analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.txt create mode 100644 analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.kt create mode 100644 analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.pretty.txt create mode 100644 analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.txt diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SymbolContainingDeclarationProvider.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SymbolContainingDeclarationProvider.kt index 9416b188b43..56913814a8d 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SymbolContainingDeclarationProvider.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SymbolContainingDeclarationProvider.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.analysis.api.components.KtSymbolContainingDeclaratio import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession import org.jetbrains.kotlin.analysis.api.descriptors.components.base.Fe10KtAnalysisSessionComponent import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.KtFe10DescDefaultBackingFieldSymbol +import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.KtFe10DynamicFunctionDescValueParameterSymbol import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getDescriptor import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtSymbol import org.jetbrains.kotlin.analysis.api.getModule @@ -66,6 +67,10 @@ internal class KtFe10SymbolContainingDeclarationProvider( return getContainingModule(symbol.owningProperty) } + if (symbol is KtFe10DynamicFunctionDescValueParameterSymbol) { + return getContainingModule(symbol.owner) + } + TODO(symbol::class.java.name) } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescFunctionSymbol.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescFunctionSymbol.kt index 58e58300a69..39cd3d1994f 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescFunctionSymbol.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescFunctionSymbol.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing +import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension internal class KtFe10DescFunctionSymbol private constructor( @@ -49,13 +50,24 @@ internal class KtFe10DescFunctionSymbol private constructor( } override val symbolKind: KtSymbolKind - get() = withValidityAssertion { descriptor.ktSymbolKind } + get() = withValidityAssertion { + if (descriptor.isDynamic()) { + return@withValidityAssertion KtSymbolKind.CLASS_MEMBER + } + descriptor.ktSymbolKind + } override val isSuspend: Boolean get() = withValidityAssertion { descriptor.isSuspend } override val isOperator: Boolean - get() = withValidityAssertion { descriptor.isOperator } + get() = withValidityAssertion { + if (descriptor.isDynamic()) { + // For consistency with the K2 implementation, see `FirDynamicMembersStorage` + return@withValidityAssertion true + } + descriptor.isOperator + } override val isExternal: Boolean get() = withValidityAssertion { descriptor.isExternal } @@ -67,7 +79,13 @@ internal class KtFe10DescFunctionSymbol private constructor( get() = withValidityAssertion { descriptor.isExplicitOverride } override val isInfix: Boolean - get() = withValidityAssertion { descriptor.isInfix } + get() = withValidityAssertion { + if (descriptor.isDynamic()) { + // For consistency with the K2 implementation, see `FirDynamicMembersStorage` + return@withValidityAssertion true + } + descriptor.isInfix + } override val isStatic: Boolean get() = withValidityAssertion { descriptor is JavaCallableMemberDescriptor && DescriptorUtils.isStaticDeclaration(descriptor) } @@ -82,7 +100,13 @@ internal class KtFe10DescFunctionSymbol private constructor( get() = withValidityAssertion { descriptor.isExpect } override val valueParameters: List - get() = withValidityAssertion { descriptor.valueParameters.map { KtFe10DescValueParameterSymbol(it, analysisContext) } } + get() = withValidityAssertion { + if (descriptor.isDynamic()) { + // For consistency with the K2 implementation, see `FirDynamicMembersStorage` + return@withValidityAssertion listOf(KtFe10DynamicFunctionDescValueParameterSymbol(this)) + } + descriptor.valueParameters.map { KtFe10DescValueParameterSymbol(it, analysisContext) } + } override val hasStableParameterNames: Boolean get() = withValidityAssertion { descriptor.ktHasStableParameterNames } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescKotlinPropertySymbol.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescKotlinPropertySymbol.kt index 50d59b5001d..0f62d3efa91 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescKotlinPropertySymbol.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescKotlinPropertySymbol.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension internal class KtFe10DescKotlinPropertySymbol( @@ -37,7 +38,12 @@ internal class KtFe10DescKotlinPropertySymbol( get() = withValidityAssertion { descriptor.name } override val symbolKind: KtSymbolKind - get() = withValidityAssertion { descriptor.ktSymbolKind } + get() = withValidityAssertion { + if (descriptor.isDynamic()) { + return@withValidityAssertion KtSymbolKind.CLASS_MEMBER + } + descriptor.ktSymbolKind + } override val isLateInit: Boolean get() = withValidityAssertion { descriptor.isLateInit } @@ -67,10 +73,10 @@ internal class KtFe10DescKotlinPropertySymbol( get() = withValidityAssertion { descriptor.isExpect } override val hasGetter: Boolean - get() = withValidityAssertion { true } + get() = withValidityAssertion { !descriptor.isDynamic() } override val hasSetter: Boolean - get() = withValidityAssertion { descriptor.isVar } + get() = withValidityAssertion { !descriptor.isDynamic() && !isVal } override val callableIdIfNonLocal: CallableId? get() = withValidityAssertion { descriptor.callableIdIfNotLocal } @@ -86,14 +92,16 @@ internal class KtFe10DescKotlinPropertySymbol( createKtInitializerValue(initializer, descriptor, analysisContext) } - override val getter: KtPropertyGetterSymbol + override val getter: KtPropertyGetterSymbol? get() = withValidityAssertion { + if (descriptor.isDynamic()) return null val getter = descriptor.getter ?: return KtFe10DescDefaultPropertyGetterSymbol(descriptor, analysisContext) return KtFe10DescPropertyGetterSymbol(getter, analysisContext) } override val setter: KtPropertySetterSymbol? get() = withValidityAssertion { + if (descriptor.isDynamic()) return null if (!descriptor.isVar) { return null } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DynamicFunctionDescValueParameterSymbol.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DynamicFunctionDescValueParameterSymbol.kt new file mode 100644 index 00000000000..d286b0c4987 --- /dev/null +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DynamicFunctionDescValueParameterSymbol.kt @@ -0,0 +1,81 @@ +/* + * Copyright 2010-2022 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.symbols.descriptorBased + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList +import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext +import org.jetbrains.kotlin.analysis.api.descriptors.symbols.base.KtFe10Symbol +import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtType +import org.jetbrains.kotlin.analysis.api.impl.base.annotations.KtEmptyAnnotationsList +import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken +import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin +import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol +import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.createDynamicType + +internal class KtFe10DynamicFunctionDescValueParameterSymbol( + val owner: KtFe10DescFunctionSymbol, +) : KtValueParameterSymbol(), KtFe10Symbol { + override val analysisContext: Fe10AnalysisContext + get() = owner.analysisContext + + override val token: KtLifetimeToken + get() = owner.token + + override val origin: KtSymbolOrigin + get() = withValidityAssertion { KtSymbolOrigin.JS_DYNAMIC } + + override val psi: PsiElement? + get() = withValidityAssertion { null } + + override val annotationsList: KtAnnotationsList + get() = withValidityAssertion { KtEmptyAnnotationsList(token) } + + override val name: Name + get() = withValidityAssertion { Name.identifier("args") } + + override val hasDefaultValue: Boolean + get() = withValidityAssertion { false } + + override val isVararg: Boolean + get() = withValidityAssertion { true } + + override val isCrossinline: Boolean + get() = withValidityAssertion { false } + + override val isNoinline: Boolean + get() = withValidityAssertion { false } + + override val isImplicitLambdaParameter: Boolean + get() = withValidityAssertion { false } + + override val returnType: KtType + get() = withValidityAssertion { createDynamicType(analysisContext.builtIns).toKtType(analysisContext) } + + context(KtAnalysisSession) + override fun createPointer(): KtSymbolPointer = withValidityAssertion { + Pointer(owner.createPointer()) + } + + override fun equals(other: Any?): Boolean = other is KtFe10DynamicFunctionDescValueParameterSymbol && other.owner == this.owner + override fun hashCode(): Int = owner.hashCode() + + + private class Pointer(val ownerPointer: KtSymbolPointer) : KtSymbolPointer() { + @Deprecated("Consider using org.jetbrains.kotlin.analysis.api.KtAnalysisSession.restoreSymbol") + override fun restoreSymbol(analysisSession: KtAnalysisSession): KtValueParameterSymbol? { + @Suppress("DEPRECATION") + val owner = ownerPointer.restoreSymbol(analysisSession) as? KtFe10DescFunctionSymbol ?: return null + return KtFe10DynamicFunctionDescValueParameterSymbol(owner) + } + } +} diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt index 4284806c93c..9e8d5d188dc 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt @@ -50,6 +50,7 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.inference.CapturedType +import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.resolve.constants.* import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass @@ -141,6 +142,7 @@ internal fun KtSymbol.getDescriptor(): DeclarationDescriptor? { is KtFe10PsiDefaultSetterParameterSymbol -> descriptor is KtFe10PsiDefaultPropertySetterSymbol -> null is KtFe10DescDefaultPropertySetterSymbol -> null + is KtFe10DynamicFunctionDescValueParameterSymbol -> null is KtFe10FileSymbol -> null is KtFe10DescDefaultPropertySetterSymbol.DefaultKtValueParameterSymbol -> descriptor is KtFe10PsiDefaultPropertySetterSymbol.DefaultKtValueParameterSymbol -> descriptor @@ -331,7 +333,11 @@ internal fun DeclarationDescriptor.getSymbolOrigin(analysisContext: Fe10Analysis is CallableMemberDescriptor -> when (kind) { CallableMemberDescriptor.Kind.DELEGATION -> return KtSymbolOrigin.DELEGATED CallableMemberDescriptor.Kind.SYNTHESIZED -> return KtSymbolOrigin.SOURCE_MEMBER_GENERATED - else -> {} + else -> { + if (isDynamic()) { + return KtSymbolOrigin.JS_DYNAMIC + } + } } } diff --git a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/symbols/Fe10IdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/symbols/Fe10IdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java index ce5c64d8b11..a0e883dd820 100644 --- a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/symbols/Fe10IdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java +++ b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/symbols/Fe10IdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java @@ -220,6 +220,34 @@ public class Fe10IdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated ext runTest("analysis/analysis-api/testData/symbols/symbolByReference/valueParameter.kt"); } + @Nested + @TestMetadata("analysis/analysis-api/testData/symbols/symbolByReference/js") + @TestDataPath("$PROJECT_ROOT") + public class Js { + @Test + public void testAllFilesPresentInJs() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/symbols/symbolByReference/js"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("functionFromJsDynamicScopeNoArguments.kt") + public void testFunctionFromJsDynamicScopeNoArguments() throws Exception { + runTest("analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.kt"); + } + + @Test + @TestMetadata("functionFromJsDynamicScopeWithArguments.kt") + public void testFunctionFromJsDynamicScopeWithArguments() throws Exception { + runTest("analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.kt"); + } + + @Test + @TestMetadata("propertyFromJsDynamicScope.kt") + public void testPropertyFromJsDynamicScope() throws Exception { + runTest("analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.kt"); + } + } + @Nested @TestMetadata("analysis/analysis-api/testData/symbols/symbolByReference/withTestCompilerPluginEnabled") @TestDataPath("$PROJECT_ROOT") diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSymbolContainingDeclarationProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSymbolContainingDeclarationProvider.kt index d63235fd549..7e2289b0c7f 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSymbolContainingDeclarationProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSymbolContainingDeclarationProvider.kt @@ -76,7 +76,16 @@ internal class KtFirSymbolContainingDeclarationProvider( is KtCallableSymbol -> { val outerFirClassifier = symbol.firSymbol.getContainingClassSymbol(symbol.firSymbol.llFirSession) - ?: return getParentSymbolByPsi() + if (outerFirClassifier == null) { + return when (firSymbol.origin) { + FirDeclarationOrigin.DynamicScope -> { + // A callable declaration from dynamic scope has no containing declaration as it comes from a dynamic type + // which is not based on a specific classifier + null + } + else -> getParentSymbolByPsi() + } + } firSymbolBuilder.buildSymbol(outerFirClassifier) as? KtDeclarationSymbol } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirFunctionSymbol.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirFunctionSymbol.kt index d2cae73ac65..0214c3364c8 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirFunctionSymbol.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirFunctionSymbol.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.containingClassLookupTag import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.isExtension @@ -92,6 +93,7 @@ internal class KtFirFunctionSymbol( override val symbolKind: KtSymbolKind get() = withValidityAssertion { when { + firSymbol.origin == FirDeclarationOrigin.DynamicScope -> KtSymbolKind.CLASS_MEMBER firSymbol.isLocal -> KtSymbolKind.LOCAL firSymbol.containingClassLookupTag()?.classId == null -> KtSymbolKind.TOP_LEVEL else -> KtSymbolKind.CLASS_MEMBER diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirKotlinPropertySymbol.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirKotlinPropertySymbol.kt index 8bd255ab50c..dd8e04ad476 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirKotlinPropertySymbol.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirKotlinPropertySymbol.kt @@ -68,6 +68,9 @@ internal class KtFirKotlinPropertySymbol( override val symbolKind: KtSymbolKind get() = withValidityAssertion { + if (firSymbol.origin == FirDeclarationOrigin.DynamicScope) { + return@withValidityAssertion KtSymbolKind.CLASS_MEMBER + } when (firSymbol.containingClassLookupTag()?.classId) { null -> KtSymbolKind.TOP_LEVEL else -> KtSymbolKind.CLASS_MEMBER diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbol.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbol.kt index 74028a00535..70c9da05b79 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbol.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbol.kt @@ -19,7 +19,6 @@ import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment -import org.jetbrains.kotlin.fir.containingClassForLocalAttr import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor @@ -27,7 +26,6 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectOrStaticData import org.jetbrains.kotlin.fir.scopes.impl.originalForWrappedIntegerOperator import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol internal interface KtFirSymbol> : KtSymbol, KtLifetimeOwner { val firSymbol: S @@ -98,9 +96,7 @@ internal tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (ori is FirDeclarationOrigin.Plugin -> KtSymbolOrigin.PLUGIN FirDeclarationOrigin.RenamedForOverride -> KtSymbolOrigin.JAVA is FirDeclarationOrigin.SubstitutionOverride -> KtSymbolOrigin.SUBSTITUTION_OVERRIDE - FirDeclarationOrigin.DynamicScope -> errorWithAttachment("Invalid FirDeclarationOrigin ${origin::class.simpleName}") { - withFirEntry("firToGetOrigin", this@ktSymbolOrigin) - } + FirDeclarationOrigin.DynamicScope -> KtSymbolOrigin.JS_DYNAMIC is FirDeclarationOrigin.ScriptCustomization -> KtSymbolOrigin.PLUGIN } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/firSymbolUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/firSymbolUtils.kt index 3a04baa3417..4b593019541 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/firSymbolUtils.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/firSymbolUtils.kt @@ -23,6 +23,8 @@ import org.jetbrains.kotlin.fir.references.impl.FirPropertyFromParameterResolved import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.types.ConeDynamicType +import org.jetbrains.kotlin.fir.types.create import org.jetbrains.kotlin.fir.types.toRegularClassSymbol import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry import org.jetbrains.kotlin.name.CallableId @@ -79,8 +81,13 @@ private fun createContextReceiver( builder.token ) -internal fun FirCallableSymbol<*>.getCallableIdIfNonLocal(): CallableId? = - callableId.takeUnless { it.isLocal } +internal fun FirCallableSymbol<*>.getCallableIdIfNonLocal(): CallableId? { + return when { + origin == FirDeclarationOrigin.DynamicScope -> null + callableId.isLocal -> null + else -> callableId + } +} internal fun FirClassLikeSymbol<*>.getClassIdIfNonLocal(): ClassId? = classId.takeUnless { it.isLocal } @@ -88,7 +95,15 @@ internal fun FirClassLikeSymbol<*>.getClassIdIfNonLocal(): ClassId? = internal fun FirCallableSymbol<*>.dispatchReceiverType( builder: KtSymbolByFirBuilder, ): KtType? { - return dispatchReceiverType?.let { builder.typeBuilder.buildKtType(it) } + val type = if ( + origin == FirDeclarationOrigin.DynamicScope + && (this is FirPropertySymbol || this is FirFunctionSymbol) + ) { + ConeDynamicType.create(builder.rootSession) + } else { + dispatchReceiverType + } + return type?.let { builder.typeBuilder.buildKtType(it) } } internal fun FirVariableSymbol<*>.getKtConstantInitializer(resolveSession: LLFirResolveSession): KtInitializerValue? { diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisScriptSourceModuleSymbolByReferenceTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisScriptSourceModuleSymbolByReferenceTestGenerated.java index 68674bf88ff..12d86fbe473 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisScriptSourceModuleSymbolByReferenceTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisScriptSourceModuleSymbolByReferenceTestGenerated.java @@ -58,6 +58,16 @@ public class FirIdeNormalAnalysisScriptSourceModuleSymbolByReferenceTestGenerate runTest("analysis/analysis-api/testData/symbols/symbolByReference/scriptResult.kts"); } + @Nested + @TestMetadata("analysis/analysis-api/testData/symbols/symbolByReference/js") + @TestDataPath("$PROJECT_ROOT") + public class Js { + @Test + public void testAllFilesPresentInJs() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/symbols/symbolByReference/js"), Pattern.compile("^(.+)\\.kts$"), null, true); + } + } + @Nested @TestMetadata("analysis/analysis-api/testData/symbols/symbolByReference/withTestCompilerPluginEnabled") @TestDataPath("$PROJECT_ROOT") diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java index 04321780754..76403071b6c 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java @@ -220,6 +220,34 @@ public class FirIdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated exte runTest("analysis/analysis-api/testData/symbols/symbolByReference/valueParameter.kt"); } + @Nested + @TestMetadata("analysis/analysis-api/testData/symbols/symbolByReference/js") + @TestDataPath("$PROJECT_ROOT") + public class Js { + @Test + public void testAllFilesPresentInJs() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/symbols/symbolByReference/js"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("functionFromJsDynamicScopeNoArguments.kt") + public void testFunctionFromJsDynamicScopeNoArguments() throws Exception { + runTest("analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.kt"); + } + + @Test + @TestMetadata("functionFromJsDynamicScopeWithArguments.kt") + public void testFunctionFromJsDynamicScopeWithArguments() throws Exception { + runTest("analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.kt"); + } + + @Test + @TestMetadata("propertyFromJsDynamicScope.kt") + public void testPropertyFromJsDynamicScope() throws Exception { + runTest("analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.kt"); + } + } + @Nested @TestMetadata("analysis/analysis-api/testData/symbols/symbolByReference/withTestCompilerPluginEnabled") @TestDataPath("$PROJECT_ROOT") diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java index d7091690a14..369bacca7e0 100644 --- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java @@ -219,4 +219,32 @@ public class FirStandaloneNormalAnalysisSourceModuleSymbolByReferenceTestGenerat public void testValueParameter() throws Exception { runTest("analysis/analysis-api/testData/symbols/symbolByReference/valueParameter.kt"); } + + @Nested + @TestMetadata("analysis/analysis-api/testData/symbols/symbolByReference/js") + @TestDataPath("$PROJECT_ROOT") + public class Js { + @Test + public void testAllFilesPresentInJs() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/symbols/symbolByReference/js"), Pattern.compile("^(.+)\\.kt$"), null, true, "withTestCompilerPluginEnabled"); + } + + @Test + @TestMetadata("functionFromJsDynamicScopeNoArguments.kt") + public void testFunctionFromJsDynamicScopeNoArguments() throws Exception { + runTest("analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.kt"); + } + + @Test + @TestMetadata("functionFromJsDynamicScopeWithArguments.kt") + public void testFunctionFromJsDynamicScopeWithArguments() throws Exception { + runTest("analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.kt"); + } + + @Test + @TestMetadata("propertyFromJsDynamicScope.kt") + public void testPropertyFromJsDynamicScope() throws Exception { + runTest("analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.kt"); + } + } } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbol.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbol.kt index dedf8c49c31..2654da347b7 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbol.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbol.kt @@ -154,4 +154,12 @@ public enum class KtSymbolOrigin { * @see org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin.Plugin */ PLUGIN, + + + /** + * Declaration from dynamic Kotlin/JS scope. + * + * See: [Dynamic type Kotlin documentation](https://kotlinlang.org/docs/dynamic-type.html) + */ + JS_DYNAMIC, } diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.kt b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.kt new file mode 100644 index 00000000000..ddd8ebfa5d7 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.kt @@ -0,0 +1,6 @@ +// TARGET_PLATFORM: JS +// DO_NOT_CHECK_SYMBOL_RESTORE + +fun foo(jsObject: dynamic) { + jsObject.dynamicFunctionCall() +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.pretty.txt b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.pretty.txt new file mode 100644 index 00000000000..ea5388c8815 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.pretty.txt @@ -0,0 +1 @@ +infix operator fun dynamicFunctionCall(vararg args: dynamic): dynamic diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.txt b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.txt new file mode 100644 index 00000000000..2bbce938c77 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeNoArguments.txt @@ -0,0 +1,55 @@ +KtFunctionSymbol: + annotationsList: [] + callableIdIfNonLocal: null + contextReceivers: [] + contractEffects: [] + hasStableParameterNames: true + isActual: false + isBuiltinFunctionInvoke: false + isExpect: false + isExtension: false + isExternal: false + isInfix: true + isInline: false + isOperator: true + isOverride: false + isStatic: false + isSuspend: false + modality: FINAL + name: dynamicFunctionCall + origin: JS_DYNAMIC + receiverParameter: null + returnType: KtDynamicType: + annotationsList: [] + type: dynamic + symbolKind: CLASS_MEMBER + typeParameters: [] + valueParameters: [ + KtValueParameterSymbol: + annotationsList: [] + callableIdIfNonLocal: null + contextReceivers: [] + generatedPrimaryConstructorProperty: null + hasDefaultValue: false + isCrossinline: false + isExtension: false + isImplicitLambdaParameter: false + isNoinline: false + isVararg: true + name: args + origin: JS_DYNAMIC + receiverParameter: null + returnType: KtDynamicType: + annotationsList: [] + type: dynamic + symbolKind: LOCAL + typeParameters: [] + getContainingModule: KtSourceModule "Sources of main" + deprecationStatus: null + ] + visibility: Public + getDispatchReceiver(): KtDynamicType: + annotationsList: [] + type: dynamic + getContainingModule: KtSourceModule "Sources of main" + deprecationStatus: null \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.kt b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.kt new file mode 100644 index 00000000000..85dddd9332f --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.kt @@ -0,0 +1,6 @@ +// TARGET_PLATFORM: JS +// DO_NOT_CHECK_SYMBOL_RESTORE + +fun foo(jsObject: dynamic) { + jsObject.dynamicFunctionCall(1, "str") +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.pretty.txt b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.pretty.txt new file mode 100644 index 00000000000..ea5388c8815 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.pretty.txt @@ -0,0 +1 @@ +infix operator fun dynamicFunctionCall(vararg args: dynamic): dynamic diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.txt b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.txt new file mode 100644 index 00000000000..2bbce938c77 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByReference/js/functionFromJsDynamicScopeWithArguments.txt @@ -0,0 +1,55 @@ +KtFunctionSymbol: + annotationsList: [] + callableIdIfNonLocal: null + contextReceivers: [] + contractEffects: [] + hasStableParameterNames: true + isActual: false + isBuiltinFunctionInvoke: false + isExpect: false + isExtension: false + isExternal: false + isInfix: true + isInline: false + isOperator: true + isOverride: false + isStatic: false + isSuspend: false + modality: FINAL + name: dynamicFunctionCall + origin: JS_DYNAMIC + receiverParameter: null + returnType: KtDynamicType: + annotationsList: [] + type: dynamic + symbolKind: CLASS_MEMBER + typeParameters: [] + valueParameters: [ + KtValueParameterSymbol: + annotationsList: [] + callableIdIfNonLocal: null + contextReceivers: [] + generatedPrimaryConstructorProperty: null + hasDefaultValue: false + isCrossinline: false + isExtension: false + isImplicitLambdaParameter: false + isNoinline: false + isVararg: true + name: args + origin: JS_DYNAMIC + receiverParameter: null + returnType: KtDynamicType: + annotationsList: [] + type: dynamic + symbolKind: LOCAL + typeParameters: [] + getContainingModule: KtSourceModule "Sources of main" + deprecationStatus: null + ] + visibility: Public + getDispatchReceiver(): KtDynamicType: + annotationsList: [] + type: dynamic + getContainingModule: KtSourceModule "Sources of main" + deprecationStatus: null \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.kt b/analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.kt new file mode 100644 index 00000000000..380698af987 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.kt @@ -0,0 +1,6 @@ +// TARGET_PLATFORM: JS +// DO_NOT_CHECK_SYMBOL_RESTORE + +fun foo(jsObject: dynamic) { + jsObject.dynamicPropertyAcess +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.pretty.txt b/analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.pretty.txt new file mode 100644 index 00000000000..a43a8c42017 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.pretty.txt @@ -0,0 +1 @@ +var dynamicPropertyAcess: dynamic \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.txt b/analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.txt new file mode 100644 index 00000000000..482a941855f --- /dev/null +++ b/analysis/analysis-api/testData/symbols/symbolByReference/js/propertyFromJsDynamicScope.txt @@ -0,0 +1,40 @@ +KtKotlinPropertySymbol: + annotationsList: [] + backingFieldSymbol: null + callableIdIfNonLocal: null + contextReceivers: [] + getter: null + hasBackingField: true + hasGetter: false + hasSetter: false + initializer: null + isActual: false + isConst: false + isDelegatedProperty: false + isExpect: false + isExtension: false + isFromPrimaryConstructor: false + isLateInit: false + isOverride: false + isStatic: false + isVal: false + modality: FINAL + name: dynamicPropertyAcess + origin: JS_DYNAMIC + receiverParameter: null + returnType: KtDynamicType: + annotationsList: [] + type: dynamic + setter: null + symbolKind: CLASS_MEMBER + typeParameters: [] + visibility: Public + getDispatchReceiver(): KtDynamicType: + annotationsList: [] + type: dynamic + getContainingModule: KtSourceModule "Sources of main" + deprecationStatus: null + getterDeprecationStatus: null + javaGetterName: getDynamicPropertyAcess + javaSetterName: setDynamicPropertyAcess + setterDeprecationStatus: null \ No newline at end of file diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirDynamicScope.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirDynamicScope.kt index 9f9e6c57d63..f3f75e56b55 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirDynamicScope.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirDynamicScope.kt @@ -165,6 +165,7 @@ class FirDynamicMembersStorage(val session: FirSession) : FirSessionComponent { moduleData = session.moduleData containingFunctionSymbol = this@buildSimpleFunction.symbol origin = FirDeclarationOrigin.DynamicScope + resolvePhase = FirResolvePhase.BODY_RESOLVE returnTypeRef = anyArrayTypeRef this.name = Name.identifier("args") this.symbol = FirValueParameterSymbol(this.name)