From f9086daf4d02039a7683d43727556c24b2070097 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Fri, 7 Apr 2023 15:12:15 -0700 Subject: [PATCH] SLC: add support for .kts ^KTIJ-21108 ^KT-50241 ^KT-55626 Fixed --- .../api/fir/components/KtFirScopeProvider.kt | 19 +- .../api/components/KtScopeProvider.kt | 6 + .../analysis/api/symbols/KtScriptSymbol.kt | 3 +- .../kotlin/asJava/KotlinAsJavaSupportBase.kt | 11 ++ .../asJava/classes/KtLightClassForScript.kt | 6 +- .../level/api/fir/util/declarationUtils.kt | 7 +- .../symbol/SymbolKotlinAsJavaSupport.kt | 7 +- .../classes/SymbolLightClassForClassLike.kt | 12 +- .../classes/SymbolLightClassForScript.kt | 180 ++++++++++++++++++ .../methods/SymbolLightMethodForScript.kt | 109 +++++++++++ .../SymbolLightScriptMainParameter.kt | 49 +++++ .../base/service/symbolLightClassTestUtils.kt | 13 +- .../jvm/compiler/CliKotlinAsJavaSupport.kt | 10 - .../lightClassByFqName/script/HelloWorld.java | 2 +- .../script/InnerClasses.java | 2 +- .../scripts/FunsPropsAndFields.fir.java | 22 ++- .../scripts/FunsPropsAndFields.java | 2 +- .../scripts/HelloWorld.fir.java | 1 - .../lightClassByPsi/scripts/HelloWorld.java | 2 +- .../scripts/InnerClasses.fir.java | 1 - .../lightClassByPsi/scripts/InnerClasses.java | 2 +- .../lightClassByPsi/scripts/InnerClasses.kts | 2 - .../scripts/InnerClasses.lib.java | 16 +- 23 files changed, 436 insertions(+), 48 deletions(-) create mode 100644 analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForScript.kt create mode 100644 analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethodForScript.kt create mode 100644 analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightScriptMainParameter.kt delete mode 100644 compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/HelloWorld.fir.java delete mode 100644 compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.fir.java diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt index d5795746f12..779470c3609 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt @@ -10,10 +10,7 @@ import org.jetbrains.kotlin.analysis.api.components.* import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.analysis.api.fir.scopes.* -import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirAnonymousObjectSymbol -import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirEnumEntrySymbol -import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirFileSymbol -import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirNamedClassOrObjectSymbol +import org.jetbrains.kotlin.analysis.api.fir.symbols.* import org.jetbrains.kotlin.analysis.api.fir.types.KtFirType import org.jetbrains.kotlin.analysis.api.fir.utils.firSymbol import org.jetbrains.kotlin.analysis.api.impl.base.scopes.KtCompositeScope @@ -23,6 +20,7 @@ import org.jetbrains.kotlin.analysis.api.scopes.KtTypeScope import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntrySymbol import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPackageSymbol +import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithDeclarations import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession @@ -37,9 +35,6 @@ import org.jetbrains.kotlin.fir.declarations.utils.isCompanion import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression import org.jetbrains.kotlin.fir.java.JavaScopeProvider import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass -import org.jetbrains.kotlin.analysis.api.fir.scopes.JavaClassDeclaredMembersEnhancementScope -import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirPsiJavaClassSymbol -import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithDeclarations import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticPropertiesScope import org.jetbrains.kotlin.fir.resolve.scope @@ -110,8 +105,14 @@ internal class KtFirScopeProvider( } override fun getDeclaredMemberScope(classSymbol: KtSymbolWithMembers): KtScope { + val useSiteSession = analysisSession.useSiteSession + if (classSymbol is KtFirScriptSymbol) { + return KtFirDelegatingScope( + FirScriptDeclarationsScope(useSiteSession, classSymbol.firSymbol.fir), + builder + ) + } val firScope = classSymbol.withFirForScope { - val useSiteSession = analysisSession.useSiteSession when (val regularClass = classSymbol.firSymbol.fir) { is FirJavaClass -> buildJavaEnhancementDeclaredMemberScope(useSiteSession, regularClass.symbol, getScopeSession()) else -> useSiteSession.declaredMemberScope(it) @@ -239,6 +240,8 @@ internal class KtFirScopeProvider( is FirDefaultSimpleImportingScope -> KtScopeKind.DefaultSimpleImportingScope(indexInTower) is FirDefaultStarImportingScope -> KtScopeKind.DefaultStarImportingScope(indexInTower) + is FirScriptDeclarationsScope -> KtScopeKind.ScriptMemberScope(indexInTower) + else -> unexpectedElementError("scope", firScope) } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt index 975cff729c3..3d5615eb5d2 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt @@ -173,6 +173,7 @@ public sealed class KtScopeKind { * Represents [KtTypeScope], which doesn't include synthetic Java properties of corresponding type. */ public class SimpleTypeScope(override val indexInTower: Int) : TypeScope() + public class SyntheticJavaPropertiesScope(override val indexInTower: Int) : TypeScope() public sealed class NonLocalScope : KtScopeKind() @@ -216,6 +217,11 @@ public sealed class KtScopeKind { * Represents [KtScope] containing static members of a classifier. */ public class StaticMemberScope(override val indexInTower: Int) : NonLocalScope() + + /** + * Represents [KtScope] containing members of a script. + */ + public class ScriptMemberScope(override val indexInTower: Int) : NonLocalScope() } public data class KtScopeWithKind( diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtScriptSymbol.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtScriptSymbol.kt index e6d738cd8fe..72b621a70f3 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtScriptSymbol.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtScriptSymbol.kt @@ -8,9 +8,10 @@ package org.jetbrains.kotlin.analysis.api.symbols import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol +import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer -public abstract class KtScriptSymbol : KtDeclarationSymbol, KtAnnotatedSymbol, KtNamedSymbol { +public abstract class KtScriptSymbol : KtDeclarationSymbol, KtAnnotatedSymbol, KtNamedSymbol, KtSymbolWithMembers { context(KtAnalysisSession) abstract override fun createPointer(): KtSymbolPointer } \ No newline at end of file diff --git a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupportBase.kt b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupportBase.kt index 484d62c48ac..d6448660b24 100644 --- a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupportBase.kt +++ b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupportBase.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.asJava import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project import com.intellij.openapi.util.ModificationTracker +import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.CachedValueProvider @@ -200,6 +201,16 @@ abstract class KotlinAsJavaSupportBase(protected val project: Project) val tracker = lightClassCachedValue?.tracker ?: projectWideOutOfBlockModificationTracker() return CachedValueProvider.Result.createSingleDependency(value, tracker) } + + override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection { + if (scriptFqName.isRoot) { + return emptyList() + } + + return findFilesForPackage(scriptFqName.parent(), scope).mapNotNull { file -> + file.script?.takeIf { it.fqName == scriptFqName }?.let { getLightClassForScript(it) } + } + } } private inline fun ifValid(element: T, action: () -> V?): V? { diff --git a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForScript.kt b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForScript.kt index 81db9a2e4df..60dda7baaae 100644 --- a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForScript.kt +++ b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForScript.kt @@ -20,7 +20,11 @@ import org.jetbrains.kotlin.psi.KtScript import javax.swing.Icon abstract class KtLightClassForScript(val script: KtScript) : KtLightClassBase(script.manager) { - private val modifierList: PsiModifierList = LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC) + private val modifierList: PsiModifierList = LightModifierList( + manager, + KotlinLanguage.INSTANCE, + PsiModifier.PUBLIC, PsiModifier.FINAL + ) private val scriptImplementsList: LightEmptyImplementsList = LightEmptyImplementsList(manager) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt index aeba1bac43c..5482fefea5e 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt @@ -90,7 +90,12 @@ private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider( } else { val ktFile = containingKtFile val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(ktFile) - firFile.declarations + if (ktFile.isScript()) { + // .kts will have a single [FirScript] as a declaration. We need to unwrap statements in it. + (firFile.declarations.singleOrNull() as? FirScript)?.statements?.filterIsInstance() + } else { + firFile.declarations + } } val original = originalDeclaration diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolKotlinAsJavaSupport.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolKotlinAsJavaSupport.kt index 52bfa8c146e..d524e2aae3a 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolKotlinAsJavaSupport.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/SymbolKotlinAsJavaSupport.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolBasedFakeLightClass import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForFacade +import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForScript import org.jetbrains.kotlin.light.classes.symbol.classes.createSymbolLightClassNoCache import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -86,7 +87,9 @@ class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase = error("Should not be called") - override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection { val facadeKtFiles = project.createDeclarationProvider(scope).findInternalFilesForFacade(fqName) if (facadeKtFiles.isEmpty()) return emptyList() diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassLike.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassLike.kt index 46ccb6a2d1c..c77ba13ea1e 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassLike.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassLike.kt @@ -28,8 +28,8 @@ import org.jetbrains.kotlin.light.classes.symbol.* import org.jetbrains.kotlin.light.classes.symbol.annotations.hasDeprecatedAnnotation import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightTypeParameterList import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind -import org.jetbrains.kotlin.psi.KtClassBody import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtScript import org.jetbrains.kotlin.psi.debugText.getDebugText import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub import org.jetbrains.kotlin.utils.addToStdlib.ifTrue @@ -159,10 +159,12 @@ abstract class SymbolLightClassForClassLike prote override fun getSuperTypes(): Array = PsiClassImplUtil.getSuperTypes(this) override fun getContainingClass(): PsiClass? { - val containingBody = classOrObjectDeclaration?.parent as? KtClassBody - val containingClass = containingBody?.parent as? KtClassOrObject - containingClass?.let { return it.toLightClass() } - return null + val containingBody = classOrObjectDeclaration?.parent + return when (val parent = containingBody?.parent) { + is KtClassOrObject -> parent.toLightClass() + is KtScript -> parent.toLightClass() + else -> null + } } abstract override fun getParent(): PsiElement? diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForScript.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForScript.kt new file mode 100644 index 00000000000..f479b0fe73f --- /dev/null +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForScript.kt @@ -0,0 +1,180 @@ +/* + * Copyright 2010-2023 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.light.classes.symbol.classes + +import com.intellij.psi.* +import org.jetbrains.kotlin.analysis.api.symbols.KtScriptSymbol +import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.analysis.api.symbols.pointers.symbolPointerOfType +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.asJava.classes.* +import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass +import org.jetbrains.kotlin.asJava.elements.KtLightField +import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.light.classes.symbol.cachedValue +import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightMethodForScriptDefaultConstructor +import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightMethodForScriptMain +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.InitializedModifiersBox +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList +import org.jetbrains.kotlin.light.classes.symbol.withSymbol +import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtScript + +internal class SymbolLightClassForScript private constructor( + private val script: KtScript, + private val symbolPointer: KtSymbolPointer, + ktModule: KtModule, +) : SymbolLightClassBase(ktModule, script.manager) { + + internal constructor( + script: KtScript, + ktModule: KtModule, + ) : this( + script, + script.symbolPointerOfType(), + ktModule, + ) + + private fun MutableList.addScriptDefaultMethods() { + val defaultConstructor = SymbolLightMethodForScriptDefaultConstructor( + script, + this@SymbolLightClassForScript, + METHOD_INDEX_FOR_DEFAULT_CTOR + ) + add(defaultConstructor) + + val mainMethod = SymbolLightMethodForScriptMain( + script, + this@SymbolLightClassForScript, + METHOD_INDEX_FOR_SCRIPT_MAIN + ) + add(mainMethod) + } + + override fun getOwnMethods(): List = cachedValue { + val result = mutableListOf() + + result.addScriptDefaultMethods() + + symbolPointer.withSymbol(ktModule) { scriptSymbol -> + createMethods(scriptSymbol.getDeclaredMemberScope().getCallableSymbols(), result) + } + result + } + + override fun getOwnFields(): List = cachedValue { + buildList { + symbolPointer.withSymbol(ktModule) { scriptSymbol -> + addPropertyBackingFields(this@buildList, scriptSymbol) + } + } + } + + override fun getOwnInnerClasses(): List = cachedValue { + symbolPointer.withSymbol(ktModule) { scriptSymbol -> + scriptSymbol.createInnerClasses(manager, this@SymbolLightClassForScript, classOrObject = null) + } + } + + override fun copy(): SymbolLightClassForScript = + SymbolLightClassForScript(script, symbolPointer, ktModule) + + private val _modifierList: PsiModifierList by lazyPub { + SymbolLightClassModifierList( + containingDeclaration = this@SymbolLightClassForScript, + modifiersBox = InitializedModifiersBox(PsiModifier.PUBLIC, PsiModifier.FINAL) + ) + } + + override fun getModifierList(): PsiModifierList = _modifierList + + override fun hasModifierProperty(name: String): Boolean = _modifierList.hasModifierProperty(name) + + private val _containingFile by lazyPub { + FakeFileForLightClass( + script.containingKtFile, + lightClass = this, + packageFqName = script.fqName.parent(), + ) + } + + override fun getContainingFile() = _containingFile + + override fun getName() = script.fqName.shortName().asString() + + override fun equals(other: Any?): Boolean = this === other || other is SymbolLightClassForScript && other.script == script + + override fun hashCode(): Int = script.hashCode() + + override fun toString(): String = "${SymbolLightClassForScript::class.java.simpleName}:${script.fqName}" + + override fun getNameIdentifier(): PsiIdentifier? = null + + override fun getContainingClass(): PsiClass? = null + + override fun isDeprecated(): Boolean = false + + override fun getTypeParameters(): Array = PsiTypeParameter.EMPTY_ARRAY + + override fun getTypeParameterList(): PsiTypeParameterList? = null + + override fun getQualifiedName() = script.fqName.asString() + + override fun isInterface(): Boolean = false + + override fun isAnnotationType(): Boolean = false + + override fun isEnum(): Boolean = false + + private val _extendsList: PsiReferenceList by lazyPub { + KotlinSuperTypeListBuilder( + this, + kotlinOrigin = kotlinOrigin?.getSuperTypeList(), + manager = manager, + language = language, + role = PsiReferenceList.Role.EXTENDS_LIST, + ).apply { + addReference("kotlin.script.templates.standard.ScriptTemplateWithArgs") + } + } + + override fun getExtendsList(): PsiReferenceList = _extendsList + + private val _implementsList by lazyPub { + KotlinSuperTypeListBuilder( + this, + kotlinOrigin = kotlinOrigin?.getSuperTypeList(), + manager = manager, + language = language, + role = PsiReferenceList.Role.IMPLEMENTS_LIST, + ) + } + + override fun getImplementsList(): PsiReferenceList = _implementsList + + override fun getInterfaces(): Array = PsiClass.EMPTY_ARRAY + + override fun getSuperClass(): PsiClass? { + return JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope) + } + + override fun getSupers(): Array { + return superClass?.let { arrayOf(it) } ?: PsiClass.EMPTY_ARRAY + } + + override fun getSuperTypes(): Array { + return arrayOf(PsiType.getJavaLangObject(manager, resolveScope)) + } + + override fun getScope(): PsiElement = parent + + override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean = false + + override val kotlinOrigin: KtClassOrObject? = null + + override val originKind: LightClassOriginKind = LightClassOriginKind.SOURCE +} \ No newline at end of file diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethodForScript.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethodForScript.kt new file mode 100644 index 00000000000..8d45be64e86 --- /dev/null +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightMethodForScript.kt @@ -0,0 +1,109 @@ +/* + * Copyright 2010-2023 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.light.classes.symbol.methods + +import com.intellij.psi.* +import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration +import org.jetbrains.kotlin.asJava.classes.lazyPub +import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier +import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.InitializedModifiersBox +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList +import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightParameterList +import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightScriptMainParameter +import org.jetbrains.kotlin.psi.KtScript +import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind + +internal sealed class SymbolLightMethodForScript( + private val ktScript: KtScript, + containingClass: SymbolLightClassBase, + methodIndex: Int, +) : SymbolLightMethodBase( + LightMemberOriginForDeclaration(ktScript, JvmDeclarationOriginKind.OTHER), + containingClass, + methodIndex +) { + abstract override fun getName(): String + + override fun getNameIdentifier(): PsiIdentifier = KtLightIdentifier(this, ktDeclaration = null, name) + + override fun hasTypeParameters(): Boolean = false + override fun getTypeParameterList(): PsiTypeParameterList? = null + override fun getTypeParameters(): Array = PsiTypeParameter.EMPTY_ARRAY + + override fun getParameterList(): PsiParameterList = _parameterList + + private val _parameterList by lazyPub { + SymbolLightParameterList( + parent = this@SymbolLightMethodForScript + ) { builder -> + builder.addParameter( + SymbolLightScriptMainParameter("args", this@SymbolLightMethodForScript) + ) + } + } + + override fun equals(other: Any?): Boolean = other === this || + other is SymbolLightMethodForScript && + other.methodIndex == this.methodIndex && + other.ktScript == this.ktScript + + override fun hashCode(): Int = ktScript.hashCode().times(31).plus(methodIndex.hashCode()) +} + +internal class SymbolLightMethodForScriptDefaultConstructor( + ktScript: KtScript, + containingClass: SymbolLightClassBase, + methodIndex: Int, +) : SymbolLightMethodForScript( + ktScript, + containingClass, + methodIndex +) { + override fun getName(): String = containingClass.name ?: "" + + override fun getModifierList(): PsiModifierList = _modifierList + + private val _modifierList: PsiModifierList by lazyPub { + SymbolLightMemberModifierList( + containingDeclaration = this@SymbolLightMethodForScriptDefaultConstructor, + modifiersBox = InitializedModifiersBox(PsiModifier.PUBLIC) + ) + } + + override fun getReturnType(): PsiType? = null + + override fun isConstructor(): Boolean = true + override fun isOverride(): Boolean = false + override fun isDeprecated(): Boolean = false +} + +internal class SymbolLightMethodForScriptMain( + ktScript: KtScript, + containingClass: SymbolLightClassBase, + methodIndex: Int, +) : SymbolLightMethodForScript( + ktScript, + containingClass, + methodIndex +) { + override fun getName(): String = "main" + + override fun getModifierList(): PsiModifierList = _modifierList + + private val _modifierList: PsiModifierList by lazyPub { + SymbolLightMemberModifierList( + containingDeclaration = this@SymbolLightMethodForScriptMain, + modifiersBox = InitializedModifiersBox(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL) + ) + } + + override fun getReturnType(): PsiType = PsiType.VOID + + override fun isConstructor(): Boolean = false + override fun isOverride(): Boolean = false + override fun isDeprecated(): Boolean = false +} \ No newline at end of file diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightScriptMainParameter.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightScriptMainParameter.kt new file mode 100644 index 00000000000..7ef5a9f5a4b --- /dev/null +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightScriptMainParameter.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2023 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.light.classes.symbol.parameters + +import com.intellij.psi.PsiIdentifier +import com.intellij.psi.PsiModifierList +import com.intellij.psi.PsiType +import org.jetbrains.kotlin.asJava.classes.lazyPub +import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier +import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightMethodForScript +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList +import org.jetbrains.kotlin.psi.KtParameter + +internal class SymbolLightScriptMainParameter( + private val name: String, + private val containingMethod: SymbolLightMethodForScript, +) : SymbolLightParameterBase(containingMethod) { + + override val kotlinOrigin: KtParameter? = null + override fun getName(): String = name + + override fun getNameIdentifier(): PsiIdentifier = KtLightIdentifier(this, ktDeclaration = null, name) + + override fun getType(): PsiType { + return PsiType.getJavaLangString(manager, resolveScope).createArrayType() + } + + override fun equals(other: Any?): Boolean = other === this || + other is SymbolLightScriptMainParameter && + other.name == this.name && + other.containingMethod == this.containingMethod + + override fun hashCode(): Int = containingMethod.hashCode().times(31).plus(name.hashCode()) + + override fun getModifierList(): PsiModifierList = _modifierList + + private val _modifierList: PsiModifierList by lazyPub { + SymbolLightClassModifierList( + containingDeclaration = this, + ) + } + + override fun hasModifierProperty(name: String): Boolean = _modifierList.hasModifierProperty(name) + + override fun isVarArgs(): Boolean = false +} \ No newline at end of file diff --git a/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/base/service/symbolLightClassTestUtils.kt b/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/base/service/symbolLightClassTestUtils.kt index 587cca895ac..43058150fc3 100644 --- a/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/base/service/symbolLightClassTestUtils.kt +++ b/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/base/service/symbolLightClassTestUtils.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.light.classes.symbol.base.service import com.intellij.psi.PsiClass import com.intellij.psi.SyntaxTraverser import org.jetbrains.kotlin.asJava.PsiClassRenderer +import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.asJava.toLightElements import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile @@ -25,5 +26,15 @@ internal inline fun withExtendedTypeRenderer(testDataFile: Path, action: () internal fun getLightClassesFromFile(ktFile: KtFile): List { val ktClasses = SyntaxTraverser.psiTraverser(ktFile).filter(KtClassOrObject::class.java).toList() - return ktClasses.plus(ktFile).flatMap { it.toLightElements() }.filterIsInstance() + return ktClasses.plus(ktFile).flatMap { ktElement -> + if (ktElement is KtFile && ktElement.isScript()) { + // Regular [KtElement.toLightElements] will attempt to find a facade class for [KtFile], + // where we deliberately drop .kts as per KTIJ-22016 + // Thus, we need to invoke [KtScript.toLightClass] explicitly. + // That's how (U)LC tests do too: see [AbstractIdeLightClassesByPsiTest#doMultiFileTest] + listOfNotNull(ktElement.script?.toLightClass()) + } else { + ktElement.toLightElements() + } + }.filterIsInstance() } diff --git a/compiler/cli/cli-base/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt b/compiler/cli/cli-base/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt index 3ef2d719931..ec6400a4770 100644 --- a/compiler/cli/cli-base/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt +++ b/compiler/cli/cli-base/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt @@ -63,16 +63,6 @@ class CliKotlinAsJavaSupport(project: Project, private val traceHolder: CliTrace }.orEmpty() } - override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection { - if (scriptFqName.isRoot) { - return emptyList() - } - - return findFilesForPackage(scriptFqName.parent(), scope).mapNotNull { file -> - file.script?.takeIf { it.fqName == scriptFqName }?.let { getLightClassForScript(it) } - } - } - override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection = emptyList() override fun getFakeLightClass(classOrObject: KtClassOrObject): KtFakeLightClass = KtDescriptorBasedFakeLightClass(classOrObject) diff --git a/compiler/testData/asJava/lightClasses/lightClassByFqName/script/HelloWorld.java b/compiler/testData/asJava/lightClasses/lightClassByFqName/script/HelloWorld.java index 655f8b4a6d4..2e03992d191 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByFqName/script/HelloWorld.java +++ b/compiler/testData/asJava/lightClasses/lightClassByFqName/script/HelloWorld.java @@ -1,4 +1,4 @@ -public class HelloWorld /* HelloWorld*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { +public final class HelloWorld /* HelloWorld*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { public HelloWorld(java.lang.String[]);// .ctor(java.lang.String[]) public static final void main(java.lang.String[]);// main(java.lang.String[]) diff --git a/compiler/testData/asJava/lightClasses/lightClassByFqName/script/InnerClasses.java b/compiler/testData/asJava/lightClasses/lightClassByFqName/script/InnerClasses.java index b033a050494..6094cce0983 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByFqName/script/InnerClasses.java +++ b/compiler/testData/asJava/lightClasses/lightClassByFqName/script/InnerClasses.java @@ -1,4 +1,4 @@ -public class InnerClasses /* InnerClasses*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { +public final class InnerClasses /* InnerClasses*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { public InnerClasses(java.lang.String[]);// .ctor(java.lang.String[]) public static final void main(java.lang.String[]);// main(java.lang.String[]) diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/FunsPropsAndFields.fir.java b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/FunsPropsAndFields.fir.java index 1e1bc72eb77..c2c6d2045a6 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/FunsPropsAndFields.fir.java +++ b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/FunsPropsAndFields.fir.java @@ -1 +1,21 @@ -// NOT_GENERATED +public final class FunsPropsAndFields /* FunsPropsAndFields*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { + @kotlin.jvm.JvmField() + public final int testField = 42 /* initializer type: int */; + + private final int testPropVal = 42 /* initializer type: int */; + + private int testPropVar = 42 /* initializer type: int */; + + @org.jetbrains.annotations.NotNull() + public final java.lang.String testFun(int);// testFun(int) + + public FunsPropsAndFields(java.lang.String[]);// .ctor(java.lang.String[]) + + public final int getTestPropVal();// getTestPropVal() + + public final int getTestPropVar();// getTestPropVar() + + public final void setTestPropVar(int);// setTestPropVar(int) + + public static final void main(java.lang.String[]);// main(java.lang.String[]) +} diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/FunsPropsAndFields.java b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/FunsPropsAndFields.java index ca2250ac943..d4803cde03d 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/FunsPropsAndFields.java +++ b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/FunsPropsAndFields.java @@ -1,4 +1,4 @@ -public class FunsPropsAndFields /* FunsPropsAndFields*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { +public final class FunsPropsAndFields /* FunsPropsAndFields*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { @kotlin.jvm.JvmField() public final int testField; diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/HelloWorld.fir.java b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/HelloWorld.fir.java deleted file mode 100644 index 1e1bc72eb77..00000000000 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/HelloWorld.fir.java +++ /dev/null @@ -1 +0,0 @@ -// NOT_GENERATED diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/HelloWorld.java b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/HelloWorld.java index 655f8b4a6d4..2e03992d191 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/HelloWorld.java +++ b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/HelloWorld.java @@ -1,4 +1,4 @@ -public class HelloWorld /* HelloWorld*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { +public final class HelloWorld /* HelloWorld*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { public HelloWorld(java.lang.String[]);// .ctor(java.lang.String[]) public static final void main(java.lang.String[]);// main(java.lang.String[]) diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.fir.java b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.fir.java deleted file mode 100644 index 1e1bc72eb77..00000000000 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.fir.java +++ /dev/null @@ -1 +0,0 @@ -// NOT_GENERATED diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.java b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.java index cf1cc3134dd..848b4413b29 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.java +++ b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.java @@ -20,7 +20,7 @@ public static final class Baz /* InnerClasses.Bar.Baz*/ { public final void doSomething();// doSomething() } -public class InnerClasses /* InnerClasses*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { +public final class InnerClasses /* InnerClasses*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { public InnerClasses(java.lang.String[]);// .ctor(java.lang.String[]) public static final void main(java.lang.String[]);// main(java.lang.String[]) diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.kts b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.kts index d9740d72414..58fccbb1153 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.kts +++ b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.kts @@ -1,5 +1,3 @@ -// IGNORE_FIR -// KT-55626 class Bar(val a: Int) { val b: Int = { 0 }() diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.lib.java b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.lib.java index 425a16b689a..84b997a2454 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.lib.java +++ b/compiler/testData/asJava/lightClasses/lightClassByPsi/scripts/InnerClasses.lib.java @@ -1,11 +1,3 @@ -public final class InnerClasses /* InnerClasses*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { - public InnerClasses(@org.jetbrains.annotations.NotNull() java.lang.String[]);// .ctor(java.lang.String[]) - - public static final void main(@org.jetbrains.annotations.NotNull() java.lang.String[]);// main(java.lang.String[]) - - class Bar ... -} - public static final class Bar /* InnerClasses.Bar*/ { private final int a; @@ -27,3 +19,11 @@ public static final class Baz /* InnerClasses.Bar.Baz*/ { public final void doSomething();// doSomething() } + +public final class InnerClasses /* InnerClasses*/ extends kotlin.script.templates.standard.ScriptTemplateWithArgs { + public InnerClasses(@org.jetbrains.annotations.NotNull() java.lang.String[]);// .ctor(java.lang.String[]) + + public static final void main(@org.jetbrains.annotations.NotNull() java.lang.String[]);// main(java.lang.String[]) + + class Bar ... +}