diff --git a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclaration.kt b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclaration.kt index 2e47ca7948c..67a05d0072d 100644 --- a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclaration.kt +++ b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclaration.kt @@ -1,7 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.kotlin.analysis.decompiled.light.classes @@ -26,7 +23,7 @@ import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind import org.jetbrains.kotlin.psi.KtClassOrObject open class KtLightClassForDecompiledDeclaration( - clsDelegate: PsiClass, + override val clsDelegate: PsiClass, private val clsParent: PsiElement, private val file: KtClsFile, kotlinOrigin: KtClassOrObject? diff --git a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclarationBase.kt b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclarationBase.kt index 0714853d09b..63d29b9f657 100644 --- a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclarationBase.kt +++ b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclarationBase.kt @@ -1,7 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.kotlin.analysis.decompiled.light.classes @@ -12,7 +9,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightElementBase import org.jetbrains.kotlin.psi.KtClassOrObject abstract class KtLightClassForDecompiledDeclarationBase( - val clsDelegate: PsiClass, + override val clsDelegate: PsiClass, clsParent: PsiElement, final override val kotlinOrigin: KtClassOrObject? ) : KtLightElementBase(clsParent), PsiClass, KtExtensibleLightClass \ No newline at end of file diff --git a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightFieldForDecompiledDeclaration.kt b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightFieldForDecompiledDeclaration.kt index 12c81925d93..c619d578dd7 100644 --- a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightFieldForDecompiledDeclaration.kt +++ b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightFieldForDecompiledDeclaration.kt @@ -1,7 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.kotlin.analysis.decompiled.light.classes @@ -70,5 +67,7 @@ open class KtLightFieldForDecompiledDeclaration( override fun toString(): String = "${this.javaClass.simpleName} of $fldParent" + override val clsDelegate: PsiField = fldDelegate + override fun isValid(): Boolean = parent.isValid } \ No newline at end of file diff --git a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightMethodForDecompiledDeclaration.kt b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightMethodForDecompiledDeclaration.kt index a493b1efd96..014646fd15d 100644 --- a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightMethodForDecompiledDeclaration.kt +++ b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightMethodForDecompiledDeclaration.kt @@ -1,7 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.kotlin.analysis.decompiled.light.classes @@ -100,6 +97,8 @@ class KtLightMethodForDecompiledDeclaration( override fun toString(): String = "${this.javaClass.simpleName} of $funParent" + override val clsDelegate: PsiMethod = funDelegate + override fun isValid(): Boolean = parent.isValid } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/FirLightMemberImpl.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/FirLightMemberImpl.kt index d932cd93913..d44dfb478b4 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/FirLightMemberImpl.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/FirLightMemberImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -21,6 +21,9 @@ internal abstract class FirLightMemberImpl( private val containingClass: KtLightClass, ) : KtLightElementBase(containingClass), PsiMember, KtLightMember { + override val clsDelegate: T + get() = invalidAccess() + override fun hasModifierProperty(name: String): Boolean = modifierList?.hasModifierProperty(name) ?: false override fun toString(): String = "${this::class.java.simpleName}:$name" diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/FirLightAbstractAnnotation.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/FirLightAbstractAnnotation.kt index db0e0e0d7e6..e269d75056a 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/FirLightAbstractAnnotation.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/FirLightAbstractAnnotation.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -15,6 +15,9 @@ import org.jetbrains.kotlin.psi.* internal abstract class FirLightAbstractAnnotation(parent: PsiElement) : KtLightElementBase(parent), PsiAnnotation, KtLightElement { + override val clsDelegate: PsiAnnotation + get() = invalidAccess() + override fun getOwner() = parent as? PsiAnnotationOwner private val KtExpression.nameReference: KtNameReferenceExpression? diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassBase.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassBase.kt index 6f7cf663a8f..1303e509f54 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassBase.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassBase.kt @@ -1,6 +1,17 @@ /* - * 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. + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.light.classes.symbol @@ -19,16 +30,19 @@ import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.PsiUtil import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt -import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker -import org.jetbrains.kotlin.asJava.classes.* import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt +import org.jetbrains.kotlin.asJava.classes.* import org.jetbrains.kotlin.light.classes.symbol.classes.checkIsInheritor import javax.swing.Icon abstract class FirLightClassBase protected constructor( manager: PsiManager ) : LightElement(manager, KotlinLanguage.INSTANCE), PsiClass, KtExtensibleLightClass { + override val clsDelegate: PsiClass + get() = invalidAccess() + private class FirLightClassesLazyCreator(private val project: Project) : KotlinClassInnerStuffCache.LazyCreator() { @OptIn(KtAllowAnalysisOnEdt::class) override fun get(initializer: () -> T, dependencies: List): Lazy = object : Lazy { diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForFacade.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForFacade.kt index d0465789b5c..170d3b3bd0a 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForFacade.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForFacade.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -10,12 +10,6 @@ import com.intellij.psi.* import com.intellij.psi.impl.light.LightEmptyImplementsList import com.intellij.psi.impl.light.LightModifierList import org.jetbrains.annotations.NonNls -import org.jetbrains.kotlin.analysis.api.scopes.KtScope -import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtKotlinPropertySymbol -import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol -import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithVisibility import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass @@ -24,6 +18,12 @@ import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.analysis.api.scopes.KtScope +import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtKotlinPropertySymbol +import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol +import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithVisibility import org.jetbrains.kotlin.light.classes.symbol.classes.analyseForLightClasses import org.jetbrains.kotlin.light.classes.symbol.classes.createField import org.jetbrains.kotlin.light.classes.symbol.classes.createMethods @@ -50,6 +50,8 @@ class FirLightClassForFacade( private val firstFileInFacade by lazyPub { files.first() } + override val clsDelegate: PsiClass get() = invalidAccess() + private val fileSymbols by lazyPub { files.map { ktFile -> analyseForLightClasses(ktFile) { diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/decompiled/KtLightClassForDecompiledFacade.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/decompiled/KtLightClassForDecompiledFacade.kt index 7008469842a..7fe9e344fc8 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/decompiled/KtLightClassForDecompiledFacade.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/decompiled/KtLightClassForDecompiledFacade.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile internal class KtLightClassForDecompiledFacade( - clsDelegate: PsiClass, + override val clsDelegate: PsiClass, clsParent: PsiElement, file: KtClsFile, kotlinOrigin: KtClassOrObject?, diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightField.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightField.kt index aa93be97e31..b8b6f796deb 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightField.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightField.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -24,6 +24,9 @@ internal abstract class FirLightField protected constructor( private val containingClass: KtLightClass, lightMemberOrigin: LightMemberOrigin?, ) : FirLightMemberImpl(lightMemberOrigin, containingClass), KtLightField { + + override val clsDelegate: PsiField get() = invalidAccess() + override fun setInitializer(initializer: PsiExpression?) = cannotModify() override fun isEquivalentTo(another: PsiElement?): Boolean = diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/FirLightModifierList.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/FirLightModifierList.kt index 25fb4f9c6d2..bb1ff8363b7 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/FirLightModifierList.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/FirLightModifierList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -20,6 +20,9 @@ internal abstract class FirLightModifierList { + override val clsDelegate: PsiModifierListOwner + get() = invalidAccess() + override val kotlinOrigin: KtModifierList? get() = owner.kotlinOrigin?.modifierList diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameter.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameter.kt index 0d7e4eeb972..e2cfe6e1485 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameter.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -16,6 +16,9 @@ import org.jetbrains.kotlin.psi.KtParameter internal abstract class FirLightParameter(containingDeclaration: FirLightMethod) : PsiVariable, NavigationItem, KtLightElement, KtLightParameter, KtLightElementBase(containingDeclaration) { + override val clsDelegate: PsiParameter + get() = invalidAccess() + override val givenAnnotations: List get() = invalidAccess() diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterList.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterList.kt index e5d77291d9d..c48b3b105af 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterList.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -8,10 +8,10 @@ package org.jetbrains.kotlin.light.classes.symbol import com.intellij.psi.PsiParameter import com.intellij.psi.PsiParameterList import com.intellij.psi.impl.light.LightParameterListBuilder -import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.asJava.elements.KtLightElementBase +import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtParameterList @@ -28,7 +28,7 @@ internal class FirLightParameterList( override val kotlinOrigin: KtParameterList? get() = (parent.kotlinOrigin as? KtFunction)?.valueParameterList - private val clsDelegate: PsiParameterList by lazyPub { + override val clsDelegate: PsiParameterList by lazyPub { val builder = LightParameterListBuilder(manager, language) callableSymbol?.let { diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightTypeParameter.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightTypeParameter.kt index 011b9da0439..01c541c6747 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightTypeParameter.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightTypeParameter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -35,6 +35,8 @@ internal class FirLightTypeParameter( ) : LightElement(parent.manager, KotlinLanguage.INSTANCE), PsiTypeParameter, KtLightDeclaration { + override val clsDelegate: PsiTypeParameter get() = invalidAccess() + override val givenAnnotations: List? get() = invalidAccess() override val kotlinOrigin: KtTypeParameter? = typeParameterSymbol.psi as? KtTypeParameter diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt index 1b44d6ecd42..c7e4e2c4cee 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2000-2018 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. */ @@ -13,6 +13,7 @@ import com.intellij.psi.search.PsiSearchScopeUtil import com.intellij.util.SmartList import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.classes.* +import org.jetbrains.kotlin.config.JvmAnalysisFlags import org.jetbrains.kotlin.descriptors.PackageViewDescriptor import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.load.java.components.FilesByFacadeFqNameIndexer @@ -108,9 +109,11 @@ class CliKotlinAsJavaSupport( ).mapNotNull { member -> (member as? PackageViewDescriptor)?.fqName } } - override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = KtLightClassForSourceDeclaration.create(classOrObject) + override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = + KtLightClassForSourceDeclaration.create(classOrObject, traceHolder.languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)) - override fun getLightClassForScript(script: KtScript): KtLightClassForScript? = KtLightClassForScript.create(script) + override fun getLightClassForScript(script: KtScript): KtLightClassForScript? = + KtLightClassForScript.create(script) override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection { return ResolveSessionUtils.getClassDescriptorsByFqName(traceHolder.module, fqName).mapNotNull { @@ -127,5 +130,6 @@ class CliKotlinAsJavaSupport( }.orEmpty() } - override fun createFacadeForSyntheticFile(facadeClassFqName: FqName, file: KtFile): PsiClass = error("Should not be called") + override fun createFacadeForSyntheticFile(facadeClassFqName: FqName, file: KtFile): PsiClass = + error("Should not be called") } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt index d3a66ec3887..4ac6d6ea113 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt @@ -1,6 +1,17 @@ /* - * 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. + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.cli.jvm.compiler @@ -19,6 +30,7 @@ import org.jetbrains.kotlin.asJava.classes.tryGetPredefinedName import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.JvmCodegenUtil import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.config.JvmAnalysisFlags import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.DeclarationDescriptor @@ -93,6 +105,9 @@ class CliLightClassGenerationSupport( return ultraLightSupport } + override val useUltraLightClasses: Boolean + get() = !KtUltraLightSupport.forceUsingOldLightClasses && !traceHolder.languageVersionSettings.getFlag(JvmAnalysisFlags.disableUltraLightClasses) + override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass { //force resolve companion for light class generation traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt index 8f3afc4f54f..3877e32384c 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt @@ -1,13 +1,27 @@ /* - * 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. + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.asJava import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.project.Project +import com.intellij.psi.PsiConstantEvaluationHelper +import com.intellij.psi.PsiElement import com.intellij.psi.PsiManager +import com.intellij.psi.util.CachedValue import org.jetbrains.kotlin.asJava.builder.LightClassBuilderResult import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder @@ -45,11 +59,18 @@ abstract class LightClassGenerationSupport { ConstantExpressionEvaluator(moduleDescriptor, languageVersionSettings, expression.project) } - internal fun canCreateUltraLightClassForFacade(files: Collection): Boolean = files.none { it.isScript() } + abstract val useUltraLightClasses: Boolean + + internal fun canCreateUltraLightClassForFacade( + files: Collection, + ): Boolean { + return useUltraLightClasses && files.none { it.isScript() } + } fun createUltraLightClassForFacade( manager: PsiManager, facadeClassFqName: FqName, + lightClassDataCache: CachedValue, files: Collection, ): KtUltraLightClassForFacade? { if (!canCreateUltraLightClassForFacade(files)) return null @@ -61,12 +82,16 @@ abstract class LightClassGenerationSupport { return KtUltraLightClassForFacade( manager, facadeClassFqName, + lightClassDataCache, files, filesToSupports ) } fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass? { + + if (!useUltraLightClasses) return null + if (element.shouldNotBeVisibleAsLightClass()) { return null } @@ -92,8 +117,8 @@ abstract class LightClassGenerationSupport { } } - fun createUltraLightClassForScript(script: KtScript): KtUltraLightClassForScript = - KtUltraLightClassForScript(script, support = getUltraLightClassSupport(script)) + fun createUltraLightClassForScript(script: KtScript): KtUltraLightClassForScript? = + if (useUltraLightClasses) KtUltraLightClassForScript(script, support = getUltraLightClassSupport(script)) else null companion object { @JvmStatic diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassUtil.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassUtil.kt index 424196d09fa..66976ed1a52 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassUtil.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassUtil.kt @@ -1,14 +1,22 @@ /* - * 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. + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.asJava -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiField -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiNamedElement +import com.intellij.psi.* import com.intellij.psi.impl.java.stubs.PsiClassStub import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.stubs.PsiFileStub @@ -16,10 +24,7 @@ import com.intellij.psi.stubs.StubElement import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade -import org.jetbrains.kotlin.asJava.elements.KtLightElement -import org.jetbrains.kotlin.asJava.elements.KtLightField -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.asJava.elements.isSetter +import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.load.java.JvmAbi @@ -212,6 +217,23 @@ object LightClassUtil { ) } + fun buildLightTypeParameterList( + owner: PsiTypeParameterListOwner, + declaration: KtDeclaration + ): PsiTypeParameterList { + val builder = KotlinLightTypeParameterListBuilder(owner) + if (declaration is KtTypeParameterListOwner) { + val parameters = declaration.typeParameters + for (i in parameters.indices) { + val jetTypeParameter = parameters[i] + val name = jetTypeParameter.name + val safeName = name ?: "__no_name__" + builder.addParameter(KtLightTypeParameter(owner, i, safeName)) + } + } + return builder + } + class PropertyAccessorsPsiMethods( val getter: PsiMethod?, val setter: PsiMethod?, diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataHolder.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataHolder.kt index 7c27eec6a9d..c3383816287 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataHolder.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataHolder.kt @@ -1,20 +1,70 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2000-2017 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.asJava.builder +import com.intellij.openapi.diagnostic.ControlFlowException +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiClassType +import com.intellij.psi.impl.DebugUtil import com.intellij.psi.impl.java.stubs.PsiJavaFileStub +import com.intellij.psi.stubs.StubElement +import org.jetbrains.kotlin.asJava.LightClassUtil.findClass +import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject +import org.jetbrains.kotlin.asJava.elements.KtLightField +import org.jetbrains.kotlin.asJava.elements.KtLightFieldImpl +import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl +import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.debugText.getDebugText import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics +import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments interface LightClassDataHolder { val javaFileStub: PsiJavaFileStub val extraDiagnostics: Diagnostics - interface ForClass : LightClassDataHolder - interface ForFacade : LightClassDataHolder - interface ForScript : ForClass + fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass): LightClassData + + interface ForClass : LightClassDataHolder { + fun findDataForDefaultImpls(classOrObject: KtClassOrObject) = findData { + it.findDelegate(classOrObject).findInnerClassByName(JvmAbi.DEFAULT_IMPLS_CLASS_NAME, false) + ?: throw IllegalStateException("Couldn't get delegate for $this\n in ${DebugUtil.stubTreeToString(it)}") + } + + fun findDataForClassOrObject(classOrObject: KtClassOrObject): LightClassData = findData { it.findDelegate(classOrObject) } + } + + interface ForFacade : LightClassDataHolder { + fun findDataForFacade(classFqName: FqName): LightClassData = findData { it.findDelegate(classFqName) } + } + + interface ForScript : ForClass { + fun findDataForScript(scriptFqName: FqName): LightClassData = findData { it.findDelegate(scriptFqName) } + } +} + +interface LightClassData { + val clsDelegate: PsiClass + + val supertypes: Array + get() { + return clsDelegate.superTypes + } + + fun getOwnFields(containingClass: KtLightClass): List + fun getOwnMethods(containingClass: KtLightClass): List +} + +class LightClassDataImpl(override val clsDelegate: PsiClass) : LightClassData { + override fun getOwnFields(containingClass: KtLightClass) = KtLightFieldImpl.fromClsFields(clsDelegate, containingClass) + + override fun getOwnMethods(containingClass: KtLightClass) = KtLightMethodImpl.fromClsMethods(clsDelegate, containingClass) } object InvalidLightClassDataHolder : LightClassDataHolder.ForClass { @@ -24,10 +74,50 @@ object InvalidLightClassDataHolder : LightClassDataHolder.ForClass { override val extraDiagnostics: Diagnostics get() = shouldNotBeCalled() + override fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass) = shouldNotBeCalled() + private fun shouldNotBeCalled(): Nothing = throw UnsupportedOperationException("Should not be called") } class LightClassDataHolderImpl( override val javaFileStub: PsiJavaFileStub, override val extraDiagnostics: Diagnostics -) : LightClassDataHolder.ForClass, LightClassDataHolder.ForFacade, LightClassDataHolder.ForScript +) : LightClassDataHolder.ForClass, LightClassDataHolder.ForFacade, LightClassDataHolder.ForScript { + override fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass) = findDelegate(javaFileStub).let(::LightClassDataImpl) +} + +fun PsiJavaFileStub.findDelegate(classOrObject: KtClassOrObject): PsiClass { + findClass(this) { + ClsWrapperStubPsiFactory.getOriginalElement(it as StubElement<*>) == classOrObject + }?.let { return it } + + val outermostClassOrObject = getOutermostClassOrObject(classOrObject) + val ktFileText: String? = try { + outermostClassOrObject.containingFile.text + } catch (e: Exception) { + if (e is ControlFlowException) throw e + "Can't get text for outermost class" + } + + val stubFileText = DebugUtil.stubTreeToString(this) + throw KotlinExceptionWithAttachments("Couldn't get delegate for class") + .withAttachment(classOrObject.name ?: "unnamed class or object", classOrObject.getDebugText()) + .withAttachment("file.kt", ktFileText) + .withAttachment("stub text", stubFileText) +} + +fun PsiJavaFileStub.findDelegate(classFqName: FqName): PsiClass { + return findClass(this) { + classFqName.asString() == it.qualifiedName + } ?: throw IllegalStateException("Facade class $classFqName not found; classes in Java file stub: ${collectClassNames(this)}") +} + + +private fun collectClassNames(javaFileStub: PsiJavaFileStub): String { + val names = mutableListOf() + findClass(javaFileStub) { cls -> + names.add(cls.qualifiedName ?: "") + false + } + return names.joinToString(prefix = "[", postfix = "]") +} \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinClassInnerStuffCache.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinClassInnerStuffCache.kt index 29d916d3bf2..dabb59fac62 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinClassInnerStuffCache.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinClassInnerStuffCache.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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. */ @@ -11,9 +11,15 @@ import com.intellij.psi.* import com.intellij.psi.impl.PsiClassImplUtil import com.intellij.psi.impl.PsiImplUtil import com.intellij.psi.impl.PsiSuperMethodImplUtil +import com.intellij.psi.impl.compiled.ClsClassImpl +import com.intellij.psi.impl.compiled.InnerClassSourceStrategy +import com.intellij.psi.impl.compiled.StubBuildingVisitor +import com.intellij.psi.impl.java.stubs.PsiClassStub +import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl import com.intellij.psi.impl.light.* import com.intellij.psi.javadoc.PsiDocComment import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.stubs.StubElement import com.intellij.psi.util.* import com.intellij.util.ArrayUtil import com.intellij.util.IncorrectOperationException @@ -25,7 +31,10 @@ import org.jetbrains.kotlin.asJava.elements.KtLightParameter import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.org.objectweb.asm.Opcodes import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.HashMap class KotlinClassInnerStuffCache( private val myClass: KtExtensibleLightClass, @@ -191,6 +200,8 @@ private class KotlinEnumSyntheticMethod( val nameParameter = object : LightParameter("name", stringType, this, language, false), KtLightParameter { override val method: KtLightMethod get() = this@KotlinEnumSyntheticMethod override val kotlinOrigin: KtParameter? get() = null + override val clsDelegate: PsiParameter get() = this@KotlinEnumSyntheticMethod.clsDelegate.parameterList.parameters.single() + override fun getParent(): PsiElement = this@KotlinEnumSyntheticMethod override fun getContainingFile(): PsiFile = this@KotlinEnumSyntheticMethod.containingFile @@ -274,7 +285,52 @@ private class KotlinEnumSyntheticMethod( override fun getText(): String = "" override fun getTextRange(): TextRange = TextRange.EMPTY_RANGE + // As you can see, the implementation is quite dumb, yet it is still better than throwing an exception, + // as 'clsDelegate' is used for verifying light class consistency. + // See 'org.jetbrains.kotlin.idea.caches.resolve.LightClassLazinessChecker.LazinessInfo#checkConsistency' for more information. + override val clsDelegate: PsiMethod by lazy { + val emptyStrategy = object : InnerClassSourceStrategy { + override fun findInnerClass(innerName: String, outerClass: PsiClass): PsiClass? = null + override fun accept(innerClass: PsiClass, visitor: StubBuildingVisitor) {} + } + + val containingFile = enumClass.containingFile as PsiJavaFile + var parent = PsiJavaFileStubImpl(containingFile, containingFile.packageName, null, true) as StubElement<*> + + fun process(clazz: PsiClass): PsiClassStub<*> { + clazz.containingClass?.let { process(it) } + + val access = getAccess(clazz) + val superName = clazz.superClass?.let { ClassUtil.getJVMClassName(it) } ?: "java/lang/Object" + val interfaceNames = clazz.interfaces.mapNotNull { ClassUtil.getJVMClassName(it) }.toTypedArray() + + val stub = StubBuildingVisitor(clazz, emptyStrategy, parent, access, clazz.name).apply { + visit(Opcodes.V1_8, access, ClassUtil.getJVMClassName(clazz), null, superName, interfaceNames) + visitEnd() + }.result + + parent = stub + return stub + } + + ClsClassImpl(process(enumClass)).methods.single { it.name == name } + } + private companion object { + private fun getAccess(clazz: PsiClass): Int { + var result = 0 + if (clazz.hasModifierProperty(PsiModifier.PUBLIC)) result = result or Opcodes.ACC_PUBLIC + if (clazz.hasModifierProperty(PsiModifier.PROTECTED)) result = result or Opcodes.ACC_PROTECTED + if (clazz.hasModifierProperty(PsiModifier.PRIVATE)) result = result or Opcodes.ACC_PRIVATE + if (clazz.hasModifierProperty(PsiModifier.FINAL)) result = result or Opcodes.ACC_FINAL + if (clazz.hasModifierProperty(PsiModifier.ABSTRACT)) result = result or Opcodes.ACC_ABSTRACT + if (clazz.isDeprecated) result = result or Opcodes.ACC_DEPRECATED + if (clazz.isEnum) result = result or Opcodes.ACC_ENUM + if (clazz.isAnnotationType) result = result or Opcodes.ACC_ANNOTATION + if (clazz.isInterface) result = result or Opcodes.ACC_INTERFACE + return result + } + private fun makeNotNullAnnotation(context: PsiClass): PsiAnnotation { return PsiElementFactory.getInstance(context.project).createAnnotationFromText("@" + NotNull::class.java.name, context) } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtFakeLightClass.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtFakeLightClass.kt index 53a24a173c2..630f7f4fbf0 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtFakeLightClass.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtFakeLightClass.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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. */ @@ -33,6 +33,7 @@ abstract class KtFakeLightClass(override val kotlinOrigin: KtClassOrObject) : private val _delegate: PsiClass by lazy { DummyJavaPsiFactory.createDummyClass(kotlinOrigin.project) } + override val clsDelegate get() = _delegate override val originKind get() = LightClassOriginKind.SOURCE override fun getName(): String? = kotlinOrigin.name @@ -92,6 +93,7 @@ class KtFakeLightMethod private constructor( KotlinLanguage.INSTANCE ), KtLightElement { override val kotlinOrigin get() = ktDeclaration + override val clsDelegate get() = myMethod override fun getName() = ktDeclaration.name ?: "" diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLazyLightClass.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLazyLightClass.kt index 6bf058975be..bd3c6f974d8 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLazyLightClass.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLazyLightClass.kt @@ -1,10 +1,30 @@ /* - * 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. + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.asJava.classes +import com.intellij.psi.PsiClass import com.intellij.psi.PsiManager +import org.jetbrains.kotlin.asJava.builder.LightClassData -abstract class KtLazyLightClass(manager: PsiManager) : KtLightClassBase(manager) \ No newline at end of file +abstract class KtLazyLightClass(manager: PsiManager) : KtLightClassBase(manager) { + abstract val lightClassData: LightClassData + + override val clsDelegate: PsiClass by lazyPub { lightClassData.clsDelegate } + + override fun getOwnFields() = lightClassData.getOwnFields(this) + override fun getOwnMethods() = lightClassData.getOwnMethods(this) +} \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassBase.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassBase.kt index 120e76c53bb..a30457fecdb 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassBase.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassBase.kt @@ -1,18 +1,28 @@ /* - * 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. + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.asJava.classes import com.intellij.navigation.ItemPresentationProviders -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiField -import com.intellij.psi.PsiManager -import com.intellij.psi.PsiMethod +import com.intellij.psi.* import com.intellij.psi.impl.PsiClassImplUtil import com.intellij.psi.impl.light.AbstractLightClass import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService +import org.jetbrains.kotlin.asJava.elements.KtLightFieldImpl +import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl import org.jetbrains.kotlin.idea.KotlinLanguage abstract class KtLightClassBase protected constructor( @@ -24,7 +34,7 @@ abstract class KtLightClassBase protected constructor( lazyCreator = LightClassesLazyCreator(project) ) - override fun getDelegate() = invalidAccess() + override fun getDelegate() = clsDelegate override fun getFields() = myInnersCache.fields @@ -45,8 +55,10 @@ abstract class KtLightClassBase protected constructor( override fun findMethodsByName(name: String, checkBases: Boolean) = myInnersCache.findMethodsByName(name, checkBases) override fun findInnerClassByName(name: String, checkBases: Boolean) = myInnersCache.findInnerClassByName(name, checkBases) - abstract override fun getOwnFields(): List - abstract override fun getOwnMethods(): List + + override fun getOwnFields(): List = KtLightFieldImpl.fromClsFields(delegate, this) + + override fun getOwnMethods(): List = KtLightMethodImpl.fromClsMethods(delegate, this) override fun getText(): String { val origin = kotlinOrigin diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt new file mode 100644 index 00000000000..3ce55aa15c5 --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2019 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.asJava.classes + +import com.intellij.psi.* +import com.intellij.psi.impl.InheritanceImplUtil +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.reference.SoftReference +import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.resolve.DescriptorUtils + +internal open class KtLightClassForAnonymousDeclaration(classOrObject: KtClassOrObject) : + KtLightClassForLocalDeclaration(classOrObject), PsiAnonymousClass { + + private var cachedBaseType: SoftReference? = null + + override fun getBaseClassReference(): PsiJavaCodeReferenceElement { + return JavaPsiFacade.getElementFactory(classOrObject.project).createReferenceElementByType(baseClassType) + } + + @Synchronized + override fun getBaseClassType(): PsiClassType { + var type: PsiClassType? = null + if (cachedBaseType != null) type = cachedBaseType!!.get() + if (type != null && type.isValid) return type + + val firstSupertypeFQName = getFirstSupertypeFQNameForAnonymousDeclaration() + for (superType in superTypes) { + val superClass = superType.resolve() + if (superClass != null && firstSupertypeFQName == superClass.qualifiedName) { + type = superType + break + } + } + + if (type == null) { + val project = classOrObject.project + type = PsiType.getJavaLangObject(PsiManager.getInstance(project), GlobalSearchScope.allScope(project)) + } + + cachedBaseType = SoftReference(type) + return type + } + + override fun getArgumentList(): PsiExpressionList? = null + + override fun isInQualifiedNew(): Boolean { + return false + } + + override fun getName(): String? = null + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || this::class.java != other::class.java) return false + + val aClass = other as KtLightClassForAnonymousDeclaration + + return classOrObject == aClass.classOrObject + } + + override fun hashCode(): Int { + return classOrObject.hashCode() + } + + override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean { + if (baseClass is KtLightClassForSourceDeclaration) { + return super.isInheritor(baseClass, checkDeep) + } + + return InheritanceImplUtil.isInheritor(this, baseClass, checkDeep) + } + + override fun getNameIdentifier(): KtLightIdentifier? = null + override fun getModifierList(): PsiModifierList? = null + override fun hasModifierProperty(name: String): Boolean = name == PsiModifier.FINAL + override fun getExtendsList(): PsiReferenceList? = null + override fun getImplementsList(): PsiReferenceList? = null + override fun getContainingClass(): PsiClass? = null + override fun isInterface() = false + override fun isAnnotationType() = false + override fun getTypeParameterList(): PsiTypeParameterList? = null + override fun isEnum() = false + + override fun copy(): PsiElement = KtLightClassForAnonymousDeclaration(classOrObject) + + companion object { + fun KtLightClassForSourceDeclaration.getFirstSupertypeFQNameForAnonymousDeclaration(): String { + val descriptor = getDescriptor() ?: return CommonClassNames.JAVA_LANG_OBJECT + + val superTypes = descriptor.typeConstructor.supertypes + + if (superTypes.isEmpty()) return CommonClassNames.JAVA_LANG_OBJECT + + val superType = superTypes.iterator().next() + val superClassDescriptor = superType.constructor.declarationDescriptor + + if (superClassDescriptor === null) { + // return java.lang.Object for recovery + return CommonClassNames.JAVA_LANG_OBJECT + } + + return DescriptorUtils.getFqName(superClassDescriptor).asString() + } + } +} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForEnumEntry.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForEnumEntry.kt new file mode 100644 index 00000000000..7f758eb5e7e --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForEnumEntry.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.asJava.classes + +import com.intellij.psi.PsiEnumConstant +import com.intellij.psi.PsiEnumConstantInitializer +import org.jetbrains.kotlin.psi.KtEnumEntry + +internal class KtLightClassForEnumEntry( + enumEntry: KtEnumEntry, + private val enumConstant: PsiEnumConstant +): KtLightClassForAnonymousDeclaration(enumEntry), PsiEnumConstantInitializer { + override fun getEnumConstant(): PsiEnumConstant = enumConstant + override fun copy() = KtLightClassForEnumEntry(classOrObject as KtEnumEntry, enumConstant) + + override fun getParent() = enumConstant +} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacadeImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacadeImpl.kt index 53ab2a4a264..6de8783fa2a 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacadeImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacadeImpl.kt @@ -9,12 +9,17 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.TextRange import com.intellij.psi.* import com.intellij.psi.impl.PsiSuperMethodImplUtil +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub import com.intellij.psi.impl.light.LightEmptyImplementsList import com.intellij.psi.impl.light.LightModifierList import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.util.CachedValue +import com.intellij.psi.util.CachedValuesManager import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.LightClassGenerationSupport +import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder +import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForFileFacade import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName @@ -30,11 +35,21 @@ import org.jetbrains.kotlin.psi.KtStringTemplateExpression import org.jetbrains.kotlin.psi.psiUtil.siblings import javax.swing.Icon -abstract class KtLightClassForFacadeImpl constructor( +open class KtLightClassForFacadeImpl constructor( manager: PsiManager, override val facadeClassFqName: FqName, + myLightClassDataCache: CachedValue, override val files: Collection ) : KtLazyLightClass(manager), KtLightClassForFacade { + + protected open val lightClassDataCache: CachedValue = myLightClassDataCache + + protected open val javaFileStub: PsiJavaFileStub? + get() = lightClassDataCache.value.javaFileStub + + override val lightClassData + get() = lightClassDataCache.value.findDataForFacade(facadeClassFqName) + private val firstFileInFacade by lazyPub { files.iterator().next() } private val modifierList: PsiModifierList = @@ -47,7 +62,7 @@ abstract class KtLightClassForFacadeImpl constructor( FakeFileForLightClass( firstFileInFacade, lightClass = { this }, - stub = { null }, + stub = { javaFileStub }, packageFqName = facadeClassFqName.parent() ) } @@ -153,7 +168,8 @@ abstract class KtLightClassForFacadeImpl constructor( override fun isValid() = files.all { it.isValid && it.hasTopLevelCallables() && facadeClassFqName == it.javaFileFacadeFqName } - abstract override fun copy(): KtLightClassForFacade + override fun copy(): KtLightClassForFacade = + KtLightClassForFacadeImpl(manager, facadeClassFqName, lightClassDataCache, files) override fun getNavigationElement() = firstFileInFacade @@ -215,15 +231,22 @@ abstract class KtLightClassForFacadeImpl constructor( companion object { fun createForFacadeNoCache(fqName: FqName, searchScope: GlobalSearchScope, project: Project): KtLightClassForFacade? { + val sources = KotlinAsJavaSupport.getInstance(project).findFilesForFacade(fqName, searchScope) .filterNot { it.isCompiled || it.isScript() } if (sources.isEmpty()) return null + + val stubProvider = LightClassDataProviderForFileFacade.ByProjectSource(project, fqName, searchScope) + val stubValue = CachedValuesManager.getManager(project) + .createCachedValue(stubProvider, false) + val manager = PsiManager.getInstance(project) + return LightClassGenerationSupport.getInstance(project).run { - if (!canCreateUltraLightClassForFacade(sources)) return null - createUltraLightClassForFacade(manager, fqName, sources) + if (canCreateUltraLightClassForFacade(sources)) createUltraLightClassForFacade(manager, fqName, stubValue, sources) ?: error("Unable to create UL class for facade: $fqName for ${sources.joinToString { it.virtualFilePath }}") + else KtLightClassForFacadeImpl(manager, fqName, stubValue, sources) } } @@ -240,10 +263,11 @@ abstract class KtLightClassForFacadeImpl constructor( file: KtFile ): KtLightClassForFacade { val project = file.project - val manager = PsiManager.getInstance(project) - return LightClassGenerationSupport.getInstance(project).run { - createUltraLightClassForFacade(manager, facadeClassFqName, listOf(file)) ?: error { "Unable to create UL class for facade" } - } + // TODO: refactor, using cached value doesn't make sense for this case + val cachedValue = CachedValuesManager.getManager(project).createCachedValue( + LightClassDataProviderForFileFacade.ByFile(project, facadeClassFqName, file), false + ) + return KtLightClassForFacadeImpl(PsiManager.getInstance(project), facadeClassFqName, cachedValue, listOf(file)) } } } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForInterfaceDefaultImpls.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForInterfaceDefaultImpls.kt new file mode 100644 index 00000000000..772a85c4b11 --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForInterfaceDefaultImpls.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.asJava.classes + +import com.intellij.psi.* +import com.intellij.util.IncorrectOperationException +import org.jetbrains.kotlin.asJava.builder.LightClassData +import org.jetbrains.kotlin.config.JvmDefaultMode +import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.psi.KtClassOrObject + +class KtLightClassForInterfaceDefaultImpls(classOrObject: KtClassOrObject) + : KtLightClassForSourceDeclaration(classOrObject, JvmDefaultMode.DEFAULT) { + override fun getQualifiedName(): String? = containingClass?.qualifiedName?.let { it + ".${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}" } + + override fun getName() = JvmAbi.DEFAULT_IMPLS_CLASS_NAME + override fun getParent() = containingClass + + override fun copy(): PsiElement { + return KtLightClassForInterfaceDefaultImpls(classOrObject.copy() as KtClassOrObject) + } + + override fun findLightClassData(): LightClassData { + return getLightClassDataHolder().findDataForDefaultImpls(classOrObject) + } + + override fun getTypeParameterList(): PsiTypeParameterList? = null + override fun getTypeParameters(): Array = emptyArray() + + override fun computeModifiers() = publicStaticFinal + + override fun isInterface(): Boolean = false + override fun isDeprecated(): Boolean = false + override fun isAnnotationType(): Boolean = false + override fun isEnum(): Boolean = false + override fun hasTypeParameters(): Boolean = false + override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean = false + + @Throws(IncorrectOperationException::class) + override fun setName(name: String): PsiElement { + throw IncorrectOperationException("Impossible to rename DefaultImpls") + } + + override fun getContainingClass() = KtLightClassForSourceDeclaration.create(classOrObject, JvmDefaultMode.DEFAULT) + + override fun getOwnInnerClasses() = emptyList() +} + +private val publicStaticFinal = setOf(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL) \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForLocalDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForLocalDeclaration.kt new file mode 100644 index 00000000000..c6b66157c94 --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForLocalDeclaration.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2019 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.asJava.classes + +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import com.intellij.psi.impl.light.LightClass +import com.intellij.psi.impl.light.LightMethod +import org.jetbrains.kotlin.asJava.LightClassUtil +import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.config.JvmDefaultMode +import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType + +open class KtLightClassForLocalDeclaration( + classOrObject: KtClassOrObject +) : KtLightClassForSourceDeclaration(classOrObject, JvmDefaultMode.DEFAULT) { + + override fun copy(): PsiElement = KtLightClassForLocalDeclaration(classOrObject.copy() as KtClassOrObject) + + override fun getQualifiedName(): String? = null + + override fun getParent() = _parent + + private val _parent: PsiElement? by lazyPub { getParentForLocalDeclaration(classOrObject) } + + companion object { + fun getParentForLocalDeclaration(classOrObject: KtClassOrObject): PsiElement? { + + fun getParentByPsiMethod(method: PsiMethod?, name: String?, forceMethodWrapping: Boolean): PsiElement? { + if (method == null || name == null) return null + + var containingClass: PsiClass? = method.containingClass ?: return null + + val currentFileName = classOrObject.containingFile.name + + var createWrapper = forceMethodWrapping + // Use PsiClass wrapper instead of package light class to avoid names like "FooPackage" in Type Hierarchy and related views + if (containingClass is KtLightClassForFacade) { + containingClass = object : LightClass(containingClass as KtLightClassForFacade, KotlinLanguage.INSTANCE) { + override fun getName(): String? = currentFileName + } + createWrapper = true + } + + if (createWrapper) { + return object : LightMethod(classOrObject.manager, method, containingClass!!, KotlinLanguage.INSTANCE) { + override fun getParent(): PsiElement = getContainingClass() + override fun getName(): String = name + } + } + + return method + } + + var declaration: PsiElement? = KtPsiUtil.getTopmostParentOfTypes( + classOrObject, + KtNamedFunction::class.java, + KtConstructor::class.java, + KtProperty::class.java, + KtAnonymousInitializer::class.java, + KtParameter::class.java + ) + + if (declaration is KtParameter) { + declaration = declaration.getStrictParentOfType() + } + + if (declaration is KtFunction) { + return getParentByPsiMethod( + LightClassUtil.getLightClassMethod(declaration), + declaration.name, + forceMethodWrapping = false + ) + } + + // Represent the property as a fake method with the same name + if (declaration is KtProperty) { + return getParentByPsiMethod( + LightClassUtil.getLightClassPropertyMethods(declaration).getter, + declaration.name, + forceMethodWrapping = true + ) + } + + if (declaration is KtAnonymousInitializer) { + val parent = declaration.parent + val grandparent = parent.parent + + if (parent is KtClassBody && grandparent is KtClassOrObject) { + return grandparent.toLightClass() + } + } + + return if (declaration is KtClass) declaration.toLightClass() else null + } + } +} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForScript.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForScript.kt index 9707bb49403..9a140e4b9b6 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForScript.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForScript.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.asJava.classes import com.intellij.openapi.util.Key import com.intellij.psi.* import com.intellij.psi.impl.PsiSuperMethodImplUtil +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub import com.intellij.psi.impl.light.LightEmptyImplementsList import com.intellij.psi.impl.light.LightModifierList import com.intellij.psi.util.CachedValue @@ -17,9 +18,11 @@ import com.intellij.util.IncorrectOperationException import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService import org.jetbrains.kotlin.asJava.LightClassGenerationSupport +import org.jetbrains.kotlin.asJava.builder.LightClassData import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForScript import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass +import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind import org.jetbrains.kotlin.name.FqName @@ -28,7 +31,17 @@ import org.jetbrains.kotlin.psi.KtCodeFragment import org.jetbrains.kotlin.psi.KtScript import javax.swing.Icon -abstract class KtLightClassForScript(val script: KtScript) : KtLazyLightClass(script.manager) { +open class KtLightClassForScript(val script: KtScript) : KtLazyLightClass(script.manager) { + + protected open fun getLightClassDataHolder(): LightClassDataHolder.ForScript = + getLightClassCachedValue(script).value + + override val lightClassData: LightClassData + get() = getLightClassDataHolder().findDataForScript(script.fqName) + + protected open val javaFileStub: PsiJavaFileStub? + get() = getLightClassDataHolder().javaFileStub + private val modifierList: PsiModifierList = LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC) private val scriptImplementsList: LightEmptyImplementsList = LightEmptyImplementsList(manager) @@ -43,7 +56,7 @@ abstract class KtLightClassForScript(val script: KtScript) : KtLazyLightClass(sc FakeFileForLightClass( script.containingKtFile, lightClass = { this }, - stub = { null }, + stub = { javaFileStub }, packageFqName = fqName.parent(), ) } @@ -90,7 +103,7 @@ abstract class KtLightClassForScript(val script: KtScript) : KtLazyLightClass(sc // inner classes with null names can't be searched for and can't be used from java anyway // we can't prohibit creating light classes with null names either since they can contain members .filter { it.name != null } - .mapNotNull { KtLightClassForSourceDeclaration.create(it) } + .mapNotNull { KtLightClassForSourceDeclaration.create(it, JvmDefaultMode.DEFAULT) } } override fun getInitializers(): Array = PsiClassInitializer.EMPTY_ARRAY @@ -101,7 +114,7 @@ abstract class KtLightClassForScript(val script: KtScript) : KtLazyLightClass(sc override fun isValid() = script.isValid - abstract override fun copy(): PsiElement + override fun copy() = KtLightClassForScript(script) override fun getNavigationElement() = script @@ -171,21 +184,27 @@ abstract class KtLightClassForScript(val script: KtScript) : KtLazyLightClass(sc CachedValuesManager.getCachedValue(script) { CachedValueProvider.Result .create( - createNoCache(script), + createNoCache(script, KtUltraLightSupport.forceUsingOldLightClasses), KotlinModificationTrackerService.getInstance(script.project).outOfBlockModificationTracker, ) } - fun createNoCache(script: KtScript): KtLightClassForScript? { + fun createNoCache(script: KtScript, forceUsingOldLightClasses: Boolean): KtLightClassForScript? { val containingFile = script.containingFile if (containingFile is KtCodeFragment) { // Avoid building light classes for code fragments return null } - return LightClassGenerationSupport.getInstance(script.project).run { - createUltraLightClassForScript(script) + if (!forceUsingOldLightClasses) { + LightClassGenerationSupport.getInstance(script.project).run { + if (useUltraLightClasses) { + return createUltraLightClassForScript(script) ?: error("UL class cannot be created for script") + } + } } + + return KtLightClassForScript(script) } fun getLightClassCachedValue(script: KtScript): CachedValue { diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt index 33138cc671a..2828ccc9d07 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt @@ -24,17 +24,21 @@ import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.PsiUtilCore import com.intellij.util.IncorrectOperationException +import com.intellij.util.containers.ConcurrentFactoryMap import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService import org.jetbrains.kotlin.asJava.ImpreciseResolveResult import org.jetbrains.kotlin.asJava.ImpreciseResolveResult.UNSURE import org.jetbrains.kotlin.asJava.LightClassGenerationSupport +import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder +import org.jetbrains.kotlin.asJava.builder.LightClassData import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForClassOrObject import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier import org.jetbrains.kotlin.asJava.elements.KtLightModifierList +import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.config.JvmDefaultMode @@ -90,8 +94,8 @@ abstract class KtLightClassForSourceDeclaration( private val _implementsList by lazyPub { createImplementsList() } private val _deprecated by lazyPub { classOrObject.isDeprecated() } - protected abstract fun createExtendsList(): PsiReferenceList? - protected abstract fun createImplementsList(): PsiReferenceList? + protected open fun createExtendsList(): PsiReferenceList? = super.getExtendsList()?.let { KtLightPsiReferenceList(it, this) } + protected open fun createImplementsList(): PsiReferenceList? = super.getImplementsList()?.let { KtLightPsiReferenceList(it, this) } override val kotlinOrigin: KtClassOrObject = classOrObject @@ -99,6 +103,11 @@ abstract class KtLightClassForSourceDeclaration( abstract override fun getParent(): PsiElement? abstract override fun getQualifiedName(): String? + override val lightClassData: LightClassData + get() = findLightClassData() + + protected open fun findLightClassData() = getLightClassDataHolder().findDataForClassOrObject(classOrObject) + private fun getJavaFileStub(): PsiJavaFileStub = getLightClassDataHolder().javaFileStub fun getDescriptor() = @@ -115,7 +124,7 @@ abstract class KtLightClassForSourceDeclaration( private val _containingFile: PsiFile by lazyPub { object : FakeFileForLightClass( classOrObject.containingKtFile, - { if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject))!! }, + { if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject), jvmDefaultMode)!! }, { getJavaFileStub() } ) { override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset) @@ -172,7 +181,7 @@ abstract class KtLightClassForSourceDeclaration( val containingClassOrObject = (classOrObject.parent as? KtClassBody)?.parent as? KtClassOrObject if (containingClassOrObject != null) { - return create(containingClassOrObject) + return create(containingClassOrObject, jvmDefaultMode) } // TODO: should return null @@ -181,7 +190,7 @@ abstract class KtLightClassForSourceDeclaration( private val _typeParameterList: PsiTypeParameterList by lazyPub { buildTypeParameterList() } - protected abstract fun buildTypeParameterList(): PsiTypeParameterList + protected open fun buildTypeParameterList() = LightClassUtil.buildLightTypeParameterList(this, classOrObject) override fun getTypeParameterList(): PsiTypeParameterList? = _typeParameterList @@ -300,7 +309,10 @@ abstract class KtLightClassForSourceDeclaration( // we can't prohibit creating light classes with null names either since they can contain members .filter { it.name != null } .mapNotNullTo(result) { - create(it) + if (!forceUsingOldLightClasses) + create(it, jvmDefaultMode) + else + createNoCache(it, jvmDefaultMode, forceUsingOldLightClasses = true) } if (classOrObject.hasInterfaceDefaultImpls && jvmDefaultMode != JvmDefaultMode.ALL_INCOMPATIBLE) { @@ -310,7 +322,7 @@ abstract class KtLightClassForSourceDeclaration( return result } - protected abstract fun createClassForInterfaceDefaultImpls(): PsiClass + protected open fun createClassForInterfaceDefaultImpls(): PsiClass = KtLightClassForInterfaceDefaultImpls(classOrObject) override fun getUseScope(): SearchScope = kotlinOrigin.useScope @@ -336,15 +348,21 @@ abstract class KtLightClassForSourceDeclaration( FINAL_KEYWORD to PsiModifier.FINAL ) - fun create(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? = + fun create(classOrObject: KtClassOrObject, jvmDefaultMode: JvmDefaultMode): KtLightClassForSourceDeclaration? = CachedValuesManager.getCachedValue(classOrObject) { CachedValueProvider.Result.create( - createNoCache(classOrObject), + ConcurrentFactoryMap.createMap { defaultMode: JvmDefaultMode -> + createNoCache(classOrObject, defaultMode, KtUltraLightSupport.forceUsingOldLightClasses) + }, KotlinModificationTrackerService.getInstance(classOrObject.project).outOfBlockModificationTracker, ) - } + }[jvmDefaultMode] - fun createNoCache(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? { + fun createNoCache( + classOrObject: KtClassOrObject, + jvmDefaultMode: JvmDefaultMode, + forceUsingOldLightClasses: Boolean + ): KtLightClassForSourceDeclaration? { val containingFile = classOrObject.containingFile if (containingFile is KtCodeFragment) { // Avoid building light classes for code fragments @@ -355,8 +373,24 @@ abstract class KtLightClassForSourceDeclaration( return null } - return LightClassGenerationSupport.getInstance(classOrObject.project).run { - createUltraLightClass(classOrObject) + if (!forceUsingOldLightClasses) { + LightClassGenerationSupport.getInstance(classOrObject.project).run { + if (useUltraLightClasses) { + return createUltraLightClass(classOrObject) + ?: error { "Unable to create UL class for ${classOrObject.javaClass.name}" } + } + } + } + + return when { + classOrObject is KtObjectDeclaration && classOrObject.isObjectLiteral() -> + KtLightClassForAnonymousDeclaration(classOrObject) + + classOrObject.safeIsLocal() -> + KtLightClassForLocalDeclaration(classOrObject) + + else -> + KtLightClassImpl(classOrObject, jvmDefaultMode, forceUsingOldLightClasses) } } @@ -454,9 +488,19 @@ abstract class KtLightClassForSourceDeclaration( private val LOG = Logger.getInstance(KtLightClassForSourceDeclaration::class.java) } - abstract override fun getSupers(): Array + override fun getSupers(): Array { + if (classOrObject.superTypeListEntries.isEmpty()) { + return getSupertypeByPsi()?.let { arrayOf(it.resolve()!!) } ?: emptyArray() + } + return clsDelegate.supers + } - abstract override fun getSuperTypes(): Array + override fun getSuperTypes(): Array { + if (classOrObject.superTypeListEntries.isEmpty()) { + return getSupertypeByPsi()?.let { arrayOf(it) } ?: emptyArray() + } + return clsDelegate.superTypes + } private fun getSupertypeByPsi(): PsiImmediateClassType? { return classOrObject.defaultJavaAncestorQualifiedName()?.let { ancestorFqName -> @@ -481,7 +525,12 @@ abstract class KtLightClassForSourceDeclaration( override val originKind: LightClassOriginKind get() = LightClassOriginKind.SOURCE - abstract fun isFinal(isFinalByPsi: Boolean): Boolean + open fun isFinal(isFinalByPsi: Boolean): Boolean { + // annotations can make class open via 'allopen' plugin + if (!isPossiblyAffectedByAllOpen() || !isFinalByPsi) return isFinalByPsi + + return clsDelegate.hasModifierProperty(PsiModifier.FINAL) + } } fun KtLightClassForSourceDeclaration.isPossiblyAffectedByAllOpen() = diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt index 95670054d03..59be05e8259 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt @@ -1,16 +1,26 @@ /* - * 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. + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.asJava.classes -import com.intellij.psi.PsiElement import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.psi.KtClassOrObject // light class for top level or (inner/nested of top level) source declarations -abstract class KtLightClassImpl @JvmOverloads constructor( +open class KtLightClassImpl @JvmOverloads constructor( classOrObject: KtClassOrObject, jvmDefaultMode: JvmDefaultMode, forceUsingOldLightClasses: Boolean = false @@ -22,5 +32,5 @@ abstract class KtLightClassImpl @JvmOverloads constructor( else containingClass - abstract override fun copy(): PsiElement + override fun copy() = KtLightClassImpl(classOrObject.copy() as KtClassOrObject, jvmDefaultMode) } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForInterfaceDefaultImpls.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForInterfaceDefaultImpls.kt index f1984a262ba..e8967307333 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForInterfaceDefaultImpls.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForInterfaceDefaultImpls.kt @@ -59,7 +59,7 @@ class KtUltraLightClassForInterfaceDefaultImpls(classOrObject: KtClassOrObject, override fun setName(name: String): PsiElement = throw IncorrectOperationException("Impossible to rename ${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}") - override fun getContainingClass(): KtLightClassForSourceDeclaration? = create(classOrObject) + override fun getContainingClass(): KtLightClassForSourceDeclaration? = create(classOrObject, jvmDefaultMode) override fun getOwnInnerClasses() = emptyList() override fun getOwnMethods(): List = _ownMethods.value diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForRepeatableAnnotationContainer.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForRepeatableAnnotationContainer.kt index 809a9bbeb47..33894fba889 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForRepeatableAnnotationContainer.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtUltraLightClassForRepeatableAnnotationContainer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -22,7 +22,7 @@ class KtUltraLightClassForRepeatableAnnotationContainer(classOrObject: KtClassOr override fun getParent() = containingClass override fun getTypeParameterList(): PsiTypeParameterList? = null override fun getTypeParameters(): Array = emptyArray() - override fun getContainingClass(): KtLightClassForSourceDeclaration? = create(classOrObject) + override fun getContainingClass(): KtLightClassForSourceDeclaration? = create(classOrObject, jvmDefaultMode) override fun getScope(): PsiElement? = containingClass override fun getOwnInnerClasses() = emptyList() override fun getOwnFields(): List = emptyList() diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/LightClassesLazyCreator.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/LightClassesLazyCreator.kt index a0eacf74668..297628e4fdc 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/LightClassesLazyCreator.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/LightClassesLazyCreator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -16,10 +16,11 @@ class LightClassesLazyCreator(private val project: Project) : KotlinClassInnerSt override fun get(initializer: () -> T, dependencies: List) = object : Lazy { private val lock = ReentrantLock() private val holder = lazyPub { - PsiCachedValueImpl(PsiManager.getInstance(project)) { - val v = initializer() - CachedValueProvider.Result.create(v, dependencies) - } + PsiCachedValueImpl(PsiManager.getInstance(project), + CachedValueProvider { + val v = initializer() + CachedValueProvider.Result.create(v, dependencies) + }) } private fun computeValue(): T = holder.value.value ?: error("holder has not null in initializer") diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraKtLightClassForFacade.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraKtLightClassForFacade.kt index 8684af2a896..d711a004eb0 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraKtLightClassForFacade.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraKtLightClassForFacade.kt @@ -1,15 +1,16 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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.asJava.classes -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiManager -import com.intellij.psi.PsiModifier -import com.intellij.psi.PsiModifierList +import com.intellij.psi.* +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub import com.intellij.psi.impl.light.LightModifierList +import com.intellij.psi.util.CachedValue +import org.jetbrains.kotlin.asJava.builder.LightClassData +import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil.findAnnotationEntryOnFileNoResolve import org.jetbrains.kotlin.idea.KotlinLanguage @@ -25,9 +26,21 @@ import org.jetbrains.kotlin.psi.psiUtil.isPrivate class KtUltraLightClassForFacade( manager: PsiManager, facadeClassFqName: FqName, + lightClassDataCache: CachedValue, files: Collection, private val filesWithSupports: Collection> -) : KtLightClassForFacadeImpl(manager, facadeClassFqName, files) { +) : KtLightClassForFacadeImpl(manager, facadeClassFqName, lightClassDataCache, files) { + + override fun getDelegate(): PsiClass = invalidAccess() + + override val lightClassDataCache: CachedValue get() = invalidAccess() + + override val clsDelegate: PsiClass get() = invalidAccess() + + override val lightClassData: LightClassData get() = invalidAccess() + + override val javaFileStub: PsiJavaFileStub? = null + private val _modifierList: PsiModifierList by lazyPub { if (isMultiFileClass) LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL) @@ -46,7 +59,8 @@ class KtUltraLightClassForFacade( name = entry.shortName?.identifier, lazyQualifiedName = { entry.analyzeAnnotation()?.fqName?.asString() }, kotlinOrigin = entry, - parent = _modifierList + parent = _modifierList, + lazyClsDelegate = null ) } } @@ -87,7 +101,6 @@ class KtUltraLightClassForFacade( ktFunction = declaration, forceStatic = true ) - is KtProperty -> { if (!declaration.isPrivate() || declaration.accessors.isNotEmpty()) { creator.propertyAccessors( @@ -98,7 +111,6 @@ class KtUltraLightClassForFacade( ) } else emptyList() } - else -> emptyList() } result.addAll(methods) @@ -136,5 +148,5 @@ class KtUltraLightClassForFacade( override fun getOwnMethods() = _ownMethods override fun copy(): KtLightClassForFacade = - KtUltraLightClassForFacade(manager, facadeClassFqName, files, filesWithSupports) + KtUltraLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files, filesWithSupports) } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightAnnotations.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightAnnotations.kt index dc4b960c784..7d9859e6c40 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightAnnotations.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightAnnotations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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. */ @@ -46,7 +46,7 @@ class KtUltraLightSimpleAnnotation( private val ultraLightSupport: KtUltraLightSupport, parent: PsiElement, private val nameReferenceElementProvider: (() -> PsiJavaCodeReferenceElement?)? = null, -) : KtLightAbstractAnnotation(parent) { +) : KtLightAbstractAnnotation(parent, computeDelegate = null) { override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = nameReferenceElementProvider?.invoke() private val parameterList = ParameterListImpl() diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt index c708b04529c..7200a073b1b 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt @@ -15,6 +15,7 @@ import com.intellij.psi.impl.light.LightMethodBuilder import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager +import org.jetbrains.kotlin.asJava.builder.LightClassData import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtUltraLightModifierList @@ -78,6 +79,10 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor override fun isFinal(isFinalByPsi: Boolean) = isFinalByPsi + override fun findLightClassData(): LightClassData = invalidAccess() + + override fun getDelegate(): PsiClass = invalidAccess() + private val _modifierList: PsiModifierList? by lazyPub { KtUltraLightClassModifierList(this, support) { computeModifiers() } } @@ -295,7 +300,6 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor when (declaration) { is KtNamedFunction -> if (isJvmStatic(declaration)) result.addAll(membersBuilder.createMethods(declaration, forceStatic = true)) - is KtProperty -> result.addAll( membersBuilder.propertyAccessors( declaration, @@ -401,7 +405,6 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor declarationOriginKindForOrigin = JvmDeclarationOriginKind.DELEGATION ) } - is FunctionDescriptor -> result.add( createGeneratedMethodFromDescriptor( descriptor = delegate, @@ -483,7 +486,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor val containingBody = classOrObject.parent as? KtClassBody val containingClass = containingBody?.parent as? KtClassOrObject - containingClass?.let { return create(it) } + containingClass?.let { return create(it, jvmDefaultMode) } val containingBlock = classOrObject.parent as? KtBlockExpression val containingScript = containingBlock?.parent as? KtScript diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForAnonymousDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForAnonymousDeclaration.kt index c35ef5c781a..acf00090515 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForAnonymousDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForAnonymousDeclaration.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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. */ @@ -7,9 +7,9 @@ package org.jetbrains.kotlin.asJava.classes import com.intellij.psi.* import com.intellij.psi.impl.InheritanceImplUtil +import org.jetbrains.kotlin.asJava.classes.KtLightClassForAnonymousDeclaration.Companion.getFirstSupertypeFQNameForAnonymousDeclaration import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.resolve.DescriptorUtils open class KtUltraLightClassForAnonymousDeclaration(classOrObject: KtClassOrObject, support: KtUltraLightSupport) : KtUltraLightClassForLocalDeclaration(classOrObject, support), PsiAnonymousClass { @@ -18,6 +18,7 @@ open class KtUltraLightClassForAnonymousDeclaration(classOrObject: KtClassOrObje JavaPsiFacade.getElementFactory(classOrObject.project).createReferenceElementByType(baseClassType) private val _baseClassType by lazyPub { + val firstSupertypeFQName = getFirstSupertypeFQNameForAnonymousDeclaration() if (firstSupertypeFQName == CommonClassNames.JAVA_LANG_OBJECT) { @@ -63,22 +64,4 @@ open class KtUltraLightClassForAnonymousDeclaration(classOrObject: KtClassOrObje override fun isEnum() = false override fun copy() = KtUltraLightClassForAnonymousDeclaration(classOrObject, support) -} - -private fun KtLightClassForSourceDeclaration.getFirstSupertypeFQNameForAnonymousDeclaration(): String { - val descriptor = getDescriptor() ?: return CommonClassNames.JAVA_LANG_OBJECT - - val superTypes = descriptor.typeConstructor.supertypes - - if (superTypes.isEmpty()) return CommonClassNames.JAVA_LANG_OBJECT - - val superType = superTypes.iterator().next() - val superClassDescriptor = superType.constructor.declarationDescriptor - - if (superClassDescriptor === null) { - // return java.lang.Object for recovery - return CommonClassNames.JAVA_LANG_OBJECT - } - - return DescriptorUtils.getFqName(superClassDescriptor).asString() -} +} \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForLocalDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForLocalDeclaration.kt index fbb96e1fcb6..0e32ff33853 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForLocalDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForLocalDeclaration.kt @@ -1,20 +1,13 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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.asJava.classes -import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.impl.light.LightClass -import com.intellij.psi.impl.light.LightMethod -import org.jetbrains.kotlin.asJava.LightClassUtil -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.asJava.classes.KtLightClassForLocalDeclaration.Companion.getParentForLocalDeclaration +import org.jetbrains.kotlin.psi.KtClassOrObject open class KtUltraLightClassForLocalDeclaration( classOrObject: KtClassOrObject, @@ -28,73 +21,4 @@ open class KtUltraLightClassForLocalDeclaration( override fun getQualifiedName(): String? = null override fun getParent() = _parent -} - -private fun getParentForLocalDeclaration(classOrObject: KtClassOrObject): PsiElement? { - fun getParentByPsiMethod(method: PsiMethod?, name: String?, forceMethodWrapping: Boolean): PsiElement? { - if (method == null || name == null) return null - - var containingClass: PsiClass? = method.containingClass ?: return null - - val currentFileName = classOrObject.containingFile.name - - var createWrapper = forceMethodWrapping - // Use PsiClass wrapper instead of package light class to avoid names like "FooPackage" in Type Hierarchy and related views - if (containingClass is KtLightClassForFacade) { - containingClass = object : LightClass(containingClass as KtLightClassForFacade, KotlinLanguage.INSTANCE) { - override fun getName(): String = currentFileName - } - createWrapper = true - } - - if (createWrapper) { - return object : LightMethod(classOrObject.manager, method, containingClass!!, KotlinLanguage.INSTANCE) { - override fun getParent(): PsiElement = getContainingClass() - override fun getName(): String = name - } - } - - return method - } - - var declaration: PsiElement? = KtPsiUtil.getTopmostParentOfTypes( - classOrObject, - KtNamedFunction::class.java, - KtConstructor::class.java, - KtProperty::class.java, - KtAnonymousInitializer::class.java, - KtParameter::class.java - ) - - if (declaration is KtParameter) { - declaration = declaration.getStrictParentOfType() - } - - if (declaration is KtFunction) { - return getParentByPsiMethod( - LightClassUtil.getLightClassMethod(declaration), - declaration.name, - forceMethodWrapping = false - ) - } - - // Represent the property as a fake method with the same name - if (declaration is KtProperty) { - return getParentByPsiMethod( - LightClassUtil.getLightClassPropertyMethods(declaration).getter, - declaration.name, - forceMethodWrapping = true - ) - } - - if (declaration is KtAnonymousInitializer) { - val parent = declaration.parent - val grandparent = parent.parent - - if (parent is KtClassBody && grandparent is KtClassOrObject) { - return grandparent.toLightClass() - } - } - - return if (declaration is KtClass) declaration.toLightClass() else null } \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForScript.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForScript.kt index 0e5e4b2f525..3da2c265e2a 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForScript.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClassForScript.kt @@ -1,17 +1,21 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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.asJava.classes +import com.intellij.psi.PsiClass import com.intellij.psi.PsiModifier import com.intellij.psi.PsiType +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub import com.intellij.psi.impl.light.LightMethodBuilder import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService +import org.jetbrains.kotlin.asJava.builder.LightClassData +import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.psi.KtNamedFunction @@ -22,6 +26,15 @@ class KtUltraLightClassForScript( script: KtScript, private val support: KtUltraLightSupport, ) : KtLightClassForScript(script) { + + override val clsDelegate: PsiClass get() = invalidAccess() + + override val lightClassData: LightClassData get() = invalidAccess() + + override fun getLightClassDataHolder(): LightClassDataHolder.ForScript = invalidAccess() + + override val javaFileStub: PsiJavaFileStub? = null + private val membersBuilder by lazyPub { UltraLightMembersCreator( containingClass = this, diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightField.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightField.kt index 6269c3b0f5f..6fe780342e0 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightField.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightField.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -184,6 +184,8 @@ internal open class KtUltraLightFieldImpl protected constructor( override val kotlinOrigin = declaration + override val clsDelegate: PsiField get() = invalidAccess() + override val lightMemberOrigin = LightMemberOriginForDeclaration(declaration, JvmDeclarationOriginKind.OTHER) override fun setName(@NonNls name: String): PsiElement { diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt index 203f3a132e8..a65b0bb5569 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt @@ -10,14 +10,13 @@ import com.intellij.psi.impl.PsiImplUtil import com.intellij.psi.impl.PsiSuperMethodImplUtil import com.intellij.psi.impl.light.LightMethodBuilder import com.intellij.psi.impl.light.LightTypeParameterListBuilder -import com.intellij.psi.javadoc.PsiDocComment import com.intellij.psi.util.MethodSignature import com.intellij.psi.util.MethodSignatureBackedByPsiMethod +import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration import org.jetbrains.kotlin.asJava.builder.MemberIndex import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl -import org.jetbrains.kotlin.asJava.elements.KtUltraLightModifierList import org.jetbrains.kotlin.codegen.FunctionCodegen import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.descriptors.ConstructorDescriptor @@ -29,11 +28,9 @@ import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtTypeParameterListOwner -import org.jetbrains.kotlin.psi.psiUtil.hasBody import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.types.RawType -import org.jetbrains.kotlin.utils.addToStdlib.safeAs const val METHOD_INDEX_FOR_GETTER = 1 const val METHOD_INDEX_FOR_SETTER = 2 @@ -43,45 +40,22 @@ const val METHOD_INDEX_FOR_NON_ORIGIN_METHOD = 5 const val METHOD_INDEX_FOR_SCRIPT_MAIN = 6 const val METHOD_INDEX_BASE = 7 -private class KtUltraLightMethodModifierList( - support: KtUltraLightSupport, - owner: KtUltraLightMethod, - val delegate: PsiMethod, -) : KtUltraLightModifierList(owner, support) { - override fun hasModifierProperty(name: String) = when { - name == PsiModifier.ABSTRACT && isImplementationInInterface() -> false - // pretend this method behaves like a default method - name == PsiModifier.DEFAULT && isImplementationInInterface() -> true - name == PsiModifier.FINAL && - (owner.containingClass.safeAs()?.isPossiblyAffectedByAllOpen() == true) - -> delegate.hasModifierProperty(name) - - else -> delegate.hasModifierProperty(name) - } - - override fun hasExplicitModifier(name: String) = - // Kotlin methods can't be truly default atm, that way we can avoid being reported on by diagnostics, namely UAST - if (name == PsiModifier.DEFAULT) false else super.hasExplicitModifier(name) - - private fun isImplementationInInterface() = owner.containingClass.isInterface && owner.kotlinOrigin?.hasBody() == true - - override fun copy() = KtUltraLightMethodModifierList(support, owner, delegate) -} - internal abstract class KtUltraLightMethod( internal val delegate: PsiMethod, - lightMemberOrigin: LightMemberOriginForDeclaration?, + lightMemberOrigin: LightMemberOrigin?, protected val support: KtUltraLightSupport, containingClass: KtLightClass, private val methodIndex: Int ) : KtLightMethodImpl( + { delegate }, lightMemberOrigin, containingClass ), KtUltraLightElementWithNullabilityAnnotation { + private class KtUltraLightThrowsReferenceListBuilder(private val parentMethod: PsiMethod) : KotlinLightReferenceListBuilder(parentMethod.manager, parentMethod.language, PsiReferenceList.Role.THROWS_LIST) { - override fun getParent(): PsiMethod = parentMethod - override fun getContainingFile(): PsiFile? = parentMethod.containingFile + override fun getParent() = parentMethod + override fun getContainingFile() = parentMethod.containingFile } protected fun computeThrowsList(methodDescriptor: FunctionDescriptor?): PsiReferenceList { @@ -131,18 +105,9 @@ internal abstract class KtUltraLightMethod( // While here we only set return type for LightMethodBuilder (see org.jetbrains.kotlin.asJava.classes.KtUltraLightClass.asJavaMethod) override fun getReturnTypeElement(): PsiTypeElement? = null - override fun getReturnType(): PsiType? = delegate.returnType + override fun getReturnType(): PsiType? = clsDelegate.returnType - override fun buildParametersForList(): List = delegate.parameterList.parameters.toList() - - private val _modifierList by lazyPub { - KtUltraLightMethodModifierList(support, this, delegate) - } - - override fun hasModifierProperty(name: String): Boolean = _modifierList.hasModifierProperty(name) - override fun getModifierList(): PsiModifierList = _modifierList - override fun getDefaultValue(): PsiAnnotationMemberValue? = delegate.safeAs()?.defaultValue - override fun getName(): String = delegate.name + override fun buildParametersForList(): List = clsDelegate.parameterList.parameters.toList() // should be in super override fun isVarArgs() = PsiImplUtil.isVarArgs(this) @@ -177,15 +142,11 @@ internal abstract class KtUltraLightMethod( override fun hashCode(): Int = super.hashCode().times(31).plus(methodIndex.hashCode()) override fun isDeprecated(): Boolean = _deprecated - - override fun getDocComment(): PsiDocComment? = delegate.docComment - - override fun isConstructor(): Boolean = delegate.isConstructor } internal class KtUltraLightMethodForSourceDeclaration( delegate: PsiMethod, - lightMemberOrigin: LightMemberOriginForDeclaration?, + lightMemberOrigin: LightMemberOrigin?, support: KtUltraLightSupport, containingClass: KtLightClass, private val forceToSkipNullabilityAnnotation: Boolean = false, @@ -243,7 +204,7 @@ internal class KtUltraLightMethodForSourceDeclaration( internal class KtUltraLightMethodForDescriptor( methodDescriptor: FunctionDescriptor, delegate: LightMethodBuilder, - lightMemberOrigin: LightMemberOriginForDeclaration?, + lightMemberOrigin: LightMemberOrigin?, support: KtUltraLightSupport, containingClass: KtUltraLightClass ) : KtUltraLightMethod( diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightParameters.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightParameters.kt index 8c66173f2f5..9536a2e4b3d 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightParameters.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightParameters.kt @@ -44,6 +44,7 @@ internal class KtUltraLightSuspendContinuationParameter( override val psiTypeForNullabilityAnnotation: PsiType? get() = psiType override val kotlinOrigin: KtParameter? = null + override val clsDelegate: PsiParameter get() = invalidAccess() private val ktType: KotlinType? get() { @@ -93,6 +94,8 @@ internal abstract class KtUltraLightParameter( override fun isEquivalentTo(another: PsiElement?): Boolean = kotlinOrigin == another + override val clsDelegate: PsiParameter get() = invalidAccess() + private val lightModifierList by lazyPub { KtLightSimpleModifierList(this, emptySet()) } override fun getModifierList(): PsiModifierList = lightModifierList diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightSupport.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightSupport.kt index 69283799830..d57eb9320fd 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightSupport.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightSupport.kt @@ -1,15 +1,16 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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.asJava.classes +import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver interface KtUltraLightSupport { @@ -20,4 +21,12 @@ interface KtUltraLightSupport { val languageVersionSettings: LanguageVersionSettings fun possiblyHasAlias(file: KtFile, shortName: Name): Boolean + + companion object { + // This property may be removed once IntelliJ versions earlier than 2018.3 become unsupported + // And usages of that property may be replaced with relevant registry key + @Volatile + @get:TestOnly + var forceUsingOldLightClasses = false + } } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt index 1e60b21280c..ca15bfabda0 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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. */ @@ -601,6 +601,7 @@ internal fun List.toLightAnnotations( name = entry.shortName?.identifier, lazyQualifiedName = { entry.analyzeAnnotation()?.fqName?.asString() }, kotlinOrigin = entry, - parent = parent + parent = parent, + lazyClsDelegate = null ) } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/FakeFileForLightClass.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/FakeFileForLightClass.kt index c18576973d3..ec951f4fcc4 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/FakeFileForLightClass.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/FakeFileForLightClass.kt @@ -1,6 +1,17 @@ /* - * 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. + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.asJava.elements @@ -43,7 +54,7 @@ open class FakeFileForLightClass( override fun getPackageName() = packageFqName.asString() private fun createFakeJavaFileStub(): PsiJavaFileStub { - val javaFileStub = PsiJavaFileStubImpl(packageFqName.asString(), /* compiled = */true) + val javaFileStub = PsiJavaFileStubImpl(packageFqName.asString(), /*compiled = */true) javaFileStub.psiFactory = ClsStubPsiFactory.INSTANCE javaFileStub.psi = this return javaFileStub diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt index a3d800d3e6f..22538a51c36 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt @@ -1,6 +1,17 @@ /* - * 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. + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.asJava.elements @@ -24,6 +35,8 @@ interface KtLightElement : PsiElement { * Probably, it's a bit dirty solution. But, for now it's not clear how to make it better */ val givenAnnotations: List? get() = null + + val clsDelegate: D } interface KtLightDeclaration : KtLightElement, PsiNamedElement diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt new file mode 100644 index 00000000000..4f1c9655b4e --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt @@ -0,0 +1,125 @@ +/* + * 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.asJava.elements + +import com.intellij.psi.* +import com.intellij.psi.impl.PsiVariableEx +import org.jetbrains.annotations.NonNls +import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin +import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration +import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.asJava.classes.KtLightClassForEnumEntry +import org.jetbrains.kotlin.asJava.classes.cannotModify +import org.jetbrains.kotlin.asJava.classes.lazyPub +import org.jetbrains.kotlin.psi.KtEnumEntry +import org.jetbrains.kotlin.psi.KtNamedDeclaration + +sealed class KtLightFieldImpl( + override val lightMemberOrigin: LightMemberOrigin?, + computeRealDelegate: () -> D, + containingClass: KtLightClass, + dummyDelegate: PsiField? +) : KtLightMemberImpl(computeRealDelegate, lightMemberOrigin, containingClass, dummyDelegate), KtLightField { + + override val clsDelegate: D + @Suppress("UNCHECKED_CAST") + get() = super.clsDelegate as D + + override fun setInitializer(initializer: PsiExpression?) = cannotModify() + + override fun getType() = clsDelegate.type + + override fun getTypeElement() = clsDelegate.typeElement + + override fun getInitializer() = clsDelegate.initializer + + override fun hasInitializer() = clsDelegate.hasInitializer() + + override fun normalizeDeclaration() = cannotModify() + + override fun computeConstantValue() = clsDelegate.computeConstantValue() + + override fun setName(@NonNls name: String): PsiElement { + (kotlinOrigin as? KtNamedDeclaration)?.setName(name) + return this + } + + override fun equals(other: Any?): Boolean = this === other || + other is KtLightFieldImpl<*> && + this.name == other.name && + this.containingClass == other.containingClass + + override fun hashCode() = 31 * containingClass.hashCode() + name.hashCode() + + override fun computeConstantValue(visitedVars: MutableSet?): Any? { + return (clsDelegate as PsiVariableEx).computeConstantValue(visitedVars) + } + + override fun copy() = Factory.create(lightMemberOrigin?.copy(), clsDelegate, containingClass) + + + class KtLightEnumConstant( + origin: LightMemberOrigin?, + computeDelegate: () -> PsiEnumConstant, + containingClass: KtLightClass, + dummyDelegate: PsiField? + ) : KtLightFieldImpl(origin, computeDelegate, containingClass, dummyDelegate), PsiEnumConstant { + private val initializingClass by lazyPub { + val kotlinEnumEntry = (lightMemberOrigin as? LightMemberOriginForDeclaration)?.originalElement as? KtEnumEntry + if (kotlinEnumEntry != null && kotlinEnumEntry.declarations.isNotEmpty()) { + KtLightClassForEnumEntry(kotlinEnumEntry, clsDelegate) + } else null + } + + // NOTE: we don't use "delegation by" because the compiler would generate method calls to ALL of PsiEnumConstant members, + // but we need only members whose implementations are not present in KotlinLightField + override fun getArgumentList() = clsDelegate.argumentList + + override fun getInitializingClass(): PsiEnumConstantInitializer? = initializingClass + override fun getOrCreateInitializingClass(): PsiEnumConstantInitializer { + return initializingClass ?: throw UnsupportedOperationException("Can't create enum constant body: ${clsDelegate.name}") + } + + override fun resolveConstructor() = clsDelegate.resolveConstructor() + override fun resolveMethod() = clsDelegate.resolveMethod() + override fun resolveMethodGenerics() = clsDelegate.resolveMethodGenerics() + } + + class KtLightFieldForSourceDeclaration( + origin: LightMemberOrigin?, + computeDelegate: () -> PsiField, + containingClass: KtLightClass, + dummyDelegate: PsiField? + ) : + KtLightFieldImpl(origin, computeDelegate, containingClass, dummyDelegate), + KtLightFieldForSourceDeclarationSupport + + companion object Factory { + fun create(origin: LightMemberOrigin?, delegate: PsiField, containingClass: KtLightClass): KtLightField = when (delegate) { + is PsiEnumConstant -> KtLightEnumConstant(origin, { delegate }, containingClass, null) + else -> KtLightFieldForSourceDeclaration(origin, { delegate }, containingClass, null) + } + + fun lazy( + dummyDelegate: PsiField, + origin: LightMemberOriginForDeclaration?, + containingClass: KtLightClass, + computeRealDelegate: () -> PsiField + ): KtLightField { + if (dummyDelegate is PsiEnumConstant) { + @Suppress("UNCHECKED_CAST") + return KtLightEnumConstant(origin, computeRealDelegate as () -> PsiEnumConstant, containingClass, dummyDelegate) + } + return KtLightFieldForSourceDeclaration(origin, computeRealDelegate, containingClass, dummyDelegate) + } + + fun fromClsFields(delegateClass: PsiClass, containingClass: KtLightClass) = delegateClass.fields.map { + KtLightFieldImpl.create(getOrigin(it), it, containingClass) + } + + fun getOrigin(field: PsiField) = getMemberOrigin(field) + } +} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightIdentifier.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightIdentifier.kt index ac8772025b7..be6cadebb83 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightIdentifier.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightIdentifier.kt @@ -1,12 +1,25 @@ /* - * 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. + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.asJava.elements import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiCompiledElement import com.intellij.psi.PsiElement +import com.intellij.psi.PsiNameIdentifierOwner import com.intellij.psi.impl.light.LightIdentifier import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject @@ -22,7 +35,7 @@ abstract class KtLightIdentifierBase( override fun getTextOffset(): Int = origin?.textOffset ?: -1 } -open class KtLightIdentifier( +open class KtLightIdentifierWithOrigin( lightOwner: PsiElement, private val ktDeclaration: KtDeclaration? ) : KtLightIdentifierBase(lightOwner, ktDeclaration?.name) { @@ -32,9 +45,16 @@ open class KtLightIdentifier( is KtPrimaryConstructor -> ktDeclaration.getConstructorKeyword() ?: ktDeclaration.valueParameterList ?: ktDeclaration.containingClassOrObject?.nameIdentifier - is KtPropertyAccessor -> ktDeclaration.namePlaceholder is KtNamedDeclaration -> ktDeclaration.nameIdentifier else -> null } } + +class KtLightIdentifier( + private val lightOwner: PsiElement, + ktDeclaration: KtDeclaration? +) : KtLightIdentifierWithOrigin(lightOwner, ktDeclaration), PsiCompiledElement { + + override fun getMirror() = ((lightOwner as? KtLightElement<*, *>)?.clsDelegate as? PsiNameIdentifierOwner)?.nameIdentifier +} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt index f2bfcfdd8c1..363610efe5d 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt @@ -1,44 +1,69 @@ /* - * 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. + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.asJava.elements -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiIdentifier -import com.intellij.psi.PsiMember -import com.intellij.psi.PsiModifierList -import com.intellij.psi.javadoc.PsiDocComment +import com.intellij.openapi.util.UserDataHolder +import com.intellij.psi.* +import com.intellij.psi.impl.compiled.ClsRepositoryPsiElement +import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory.ORIGIN +import org.jetbrains.kotlin.asJava.builder.LightElementOrigin +import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration +import org.jetbrains.kotlin.asJava.classes.isPossiblyAffectedByAllOpen import org.jetbrains.kotlin.asJava.classes.lazyPub +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtNamedDeclaration +import org.jetbrains.kotlin.psi.psiUtil.hasBody abstract class KtLightMemberImpl( - override val lightMemberOrigin: LightMemberOriginForDeclaration?, + computeRealDelegate: () -> D, + override val lightMemberOrigin: LightMemberOrigin?, private val containingClass: KtLightClass, + private val dummyDelegate: D? ) : KtLightElementBase(containingClass), PsiMember, KtLightMember { + override val clsDelegate by lazyPub(computeRealDelegate) private val lightIdentifier by lazyPub { KtLightIdentifier(this, kotlinOrigin as? KtNamedDeclaration) } - abstract override fun hasModifierProperty(name: String): Boolean + private val _modifierList by lazyPub { + if (lightMemberOrigin is LightMemberOriginForDeclaration) + KtLightMemberModifierList(this, dummyDelegate?.modifierList) + else clsDelegate.modifierList!! + } - abstract override fun getModifierList(): PsiModifierList? + override fun hasModifierProperty(name: String) = _modifierList.hasModifierProperty(name) + + override fun getModifierList(): PsiModifierList = _modifierList override fun toString(): String = "${this::class.java.simpleName}:$name" override fun getContainingClass() = containingClass - abstract override fun getName(): String + override fun getName(): String = dummyDelegate?.name ?: clsDelegate.name!! override fun getNameIdentifier(): PsiIdentifier = lightIdentifier override val kotlinOrigin: KtDeclaration? get() = lightMemberOrigin?.originalElement - abstract override fun getDocComment(): PsiDocComment? + override fun getDocComment() = (clsDelegate as PsiDocCommentOwner).docComment - abstract override fun isDeprecated(): Boolean + override fun isDeprecated() = (clsDelegate as PsiDocCommentOwner).isDeprecated override fun isValid(): Boolean { return parent.isValid && lightMemberOrigin?.isValid() != false @@ -50,3 +75,46 @@ abstract class KtLightMemberImpl( another is KtLightMember<*> && lightMemberOrigin?.isEquivalentTo(another.lightMemberOrigin) == true } } + +internal fun getMemberOrigin(member: PsiMember): LightMemberOriginForDeclaration? { + if (member !is ClsRepositoryPsiElement<*>) return null + + val stubElement = member.stub as? UserDataHolder ?: return null + + return stubElement.getUserData(ORIGIN) as? LightMemberOriginForDeclaration ?: return null +} + +private val visibilityModifiers = arrayOf(PsiModifier.PRIVATE, PsiModifier.PACKAGE_LOCAL, PsiModifier.PROTECTED, PsiModifier.PUBLIC) + +private class KtLightMemberModifierList( + owner: KtLightMember<*>, private val dummyDelegate: PsiModifierList? +) : KtLightModifierList>(owner) { + override fun hasModifierProperty(name: String) = when { + name == PsiModifier.ABSTRACT && isImplementationInInterface() -> false + // pretend this method behaves like a default method + name == PsiModifier.DEFAULT && isImplementationInInterface() -> true + name == PsiModifier.FINAL && ((owner.containingClass as? KtLightClassForSourceDeclaration)?.isPossiblyAffectedByAllOpen() + ?: false) -> + clsDelegate.hasModifierProperty(name) + dummyDelegate != null -> { + when { + name in visibilityModifiers && isMethodOverride() -> + clsDelegate.hasModifierProperty(name) + else -> dummyDelegate.hasModifierProperty(name) + } + } + else -> clsDelegate.hasModifierProperty(name) + } + + override fun hasExplicitModifier(name: String) = + // Kotlin methods can't be truly default atm, that way we can avoid being reported on by diagnostics, namely UAST + if (name == PsiModifier.DEFAULT) false else super.hasExplicitModifier(name) + + private fun isMethodOverride() = owner is KtLightMethod && owner.kotlinOrigin?.hasModifier(KtTokens.OVERRIDE_KEYWORD) ?: false + + private fun isImplementationInInterface() = + owner.containingClass.isInterface && owner is KtLightMethod && owner.kotlinOrigin?.hasBody() ?: false + + override fun copy() = KtLightMemberModifierList(owner, dummyDelegate) +} + diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt index 855b3073034..86a08f76f56 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt @@ -7,38 +7,66 @@ package org.jetbrains.kotlin.asJava.elements import com.intellij.openapi.util.TextRange import com.intellij.psi.* +import com.intellij.psi.impl.compiled.ClsTypeElementImpl import com.intellij.psi.scope.PsiScopeProcessor import com.intellij.psi.util.MethodSignature import com.intellij.psi.util.MethodSignatureBackedByPsiMethod import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.asJava.* +import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration import org.jetbrains.kotlin.asJava.builder.MemberIndex +import org.jetbrains.kotlin.asJava.builder.memberIndex import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.cannotModify import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade -abstract class KtLightMethodImpl protected constructor( - lightMemberOrigin: LightMemberOriginForDeclaration?, +open class KtLightMethodImpl protected constructor( + computeRealDelegate: () -> PsiMethod, + lightMemberOrigin: LightMemberOrigin?, containingClass: KtLightClass, -) : KtLightMemberImpl(lightMemberOrigin, containingClass), KtLightMethod { + private val dummyDelegate: PsiMethod? = null +) : KtLightMemberImpl(computeRealDelegate, lightMemberOrigin, containingClass, dummyDelegate), KtLightMethod { + private val returnTypeElem by lazyPub { + val delegateTypeElement = clsDelegate.returnTypeElement as? ClsTypeElementImpl + delegateTypeElement?.let { ClsTypeElementImpl(this, it.canonicalText, /*ClsTypeElementImpl.VARIANCE_NONE */ 0.toChar()) } + } + private val calculatingReturnType = ThreadLocal() private val paramsList: PsiParameterList by lazyPub { - val parameters = buildParametersForList() - KtLightParameterList(this, parameters.size) { - parameters + KtLightParameterList(this, dummyDelegate?.parameterList?.parametersCount ?: clsDelegate.parameterList.parametersCount) { + buildParametersForList() } } - protected abstract fun buildParametersForList(): List + protected open fun buildParametersForList(): List { + val clsParameters by lazyPub { clsDelegate.parameterList.parameters } + return (dummyDelegate?.parameterList?.parameters ?: clsParameters).mapIndexed { index, dummyParameter -> + KtLightParameterImpl( + dummyParameter, + { clsParameters.getOrNull(index) }, + index, + this@KtLightMethodImpl + ) + } + } private val typeParamsList: PsiTypeParameterList? by lazyPub { buildTypeParameterList() } - protected abstract fun buildTypeParameterList(): PsiTypeParameterList? + protected open fun buildTypeParameterList(): PsiTypeParameterList? { + val origin = (lightMemberOrigin as? LightMemberOriginForDeclaration)?.originalElement + return when { + origin is KtClassOrObject -> KotlinLightTypeParameterListBuilder(this) + origin != null -> LightClassUtil.buildLightTypeParameterList(this, origin) + else -> clsDelegate.typeParameterList + } + } override fun accept(visitor: PsiElementVisitor) { if (visitor is JavaElementVisitor) { @@ -76,7 +104,12 @@ abstract class KtLightMethodImpl protected constructor( } ?: cannotModify() } - abstract override fun getModifierList(): PsiModifierList + override fun getModifierList(): PsiModifierList { + if (calculatingReturnType.get() == true) { + return KotlinJavaPsiFacade.getInstance(project).emptyModifierList + } + return super.getModifierList() + } override fun getParameterList() = paramsList @@ -87,7 +120,16 @@ abstract class KtLightMethodImpl protected constructor( override fun hasTypeParameters() = typeParameters.isNotEmpty() - abstract override fun getSignature(substitutor: PsiSubstitutor): MethodSignature + override fun getSignature(substitutor: PsiSubstitutor): MethodSignature { + if (substitutor == PsiSubstitutor.EMPTY) { + return clsDelegate.getSignature(substitutor) + } + return MethodSignatureBackedByPsiMethod.create(this, substitutor) + } + + override fun copy(): PsiElement { + return Factory.create(clsDelegate, lightMemberOrigin?.copy(), containingClass) + } override fun processDeclarations( processor: PsiScopeProcessor, @@ -98,7 +140,8 @@ abstract class KtLightMethodImpl protected constructor( return typeParameters.all { processor.execute(it, state) } } - protected abstract val memberIndex: MemberIndex? + protected open val memberIndex: MemberIndex? + get() = (dummyDelegate ?: clsDelegate).memberIndex /* comparing origin and member index should be enough to determine equality: for compiled elements origin contains delegate @@ -115,9 +158,11 @@ abstract class KtLightMethodImpl protected constructor( .times(31).plus(containingClass.hashCode()) .times(31).plus(memberIndex.hashCode()) - abstract override fun getDefaultValue(): PsiAnnotationMemberValue? + override fun getDefaultValue() = (clsDelegate as? PsiAnnotationMethod)?.defaultValue - abstract override fun getReturnTypeElement(): PsiTypeElement? + // override getReturnType() so return type resolves to type parameters of this method not delegate's + // which is relied upon by java type inference + override fun getReturnTypeElement(): PsiTypeElement? = returnTypeElem override fun getReturnType(): PsiType? { calculatingReturnType.set(true) @@ -146,28 +191,67 @@ abstract class KtLightMethodImpl protected constructor( return super.getTextRange() } - abstract override fun getThrowsList(): PsiReferenceList + companion object Factory { + private fun adjustMethodOrigin(origin: LightMemberOriginForDeclaration?): LightMemberOriginForDeclaration? { + val originalElement = origin?.originalElement + if (originalElement is KtPropertyAccessor) { + return origin.copy( + originalElement = originalElement.getStrictParentOfType()!!, + originKind = origin.originKind, + auxiliaryOriginalElement = originalElement + ) + } + return origin + } - abstract override fun isVarArgs(): Boolean + fun create( + delegate: PsiMethod, origin: LightMemberOrigin?, containingClass: KtLightClass + ): KtLightMethodImpl { + return KtLightMethodImpl({ delegate }, origin, containingClass) + } - abstract override fun isConstructor(): Boolean + fun lazy( + dummyDelegate: PsiMethod?, + containingClass: KtLightClass, + origin: LightMemberOriginForDeclaration?, + computeRealDelegate: () -> PsiMethod + ): KtLightMethodImpl { + return KtLightMethodImpl(computeRealDelegate, origin, containingClass, dummyDelegate) + } - abstract override fun getHierarchicalMethodSignature(): HierarchicalMethodSignature + fun fromClsMethods(delegateClass: PsiClass, containingClass: KtLightClass): List = buildList { + for (method in delegateClass.methods) { + if (isSyntheticValuesOrValueOfMethod(method)) continue + this += create(method, getOrigin(method), containingClass) + } + } - abstract override fun findSuperMethodSignaturesIncludingStatic(checkAccess: Boolean): List + fun getOrigin(method: PsiMethod) = adjustMethodOrigin(getMemberOrigin(method)) + } + + override fun getThrowsList() = clsDelegate.throwsList + + override fun isVarArgs() = (dummyDelegate ?: clsDelegate).isVarArgs + + override fun isConstructor() = dummyDelegate?.isConstructor ?: clsDelegate.isConstructor + + override fun getHierarchicalMethodSignature() = clsDelegate.hierarchicalMethodSignature + + override fun findSuperMethodSignaturesIncludingStatic(checkAccess: Boolean) = + clsDelegate.findSuperMethodSignaturesIncludingStatic(checkAccess) override fun getBody() = null @Suppress("DEPRECATION") - abstract override fun findDeepestSuperMethod(): PsiMethod? + override fun findDeepestSuperMethod() = clsDelegate.findDeepestSuperMethod() - abstract override fun findDeepestSuperMethods(): Array + override fun findDeepestSuperMethods() = clsDelegate.findDeepestSuperMethods() - abstract override fun findSuperMethods(): Array + override fun findSuperMethods() = clsDelegate.findSuperMethods() - abstract override fun findSuperMethods(checkAccess: Boolean): Array + override fun findSuperMethods(checkAccess: Boolean) = clsDelegate.findSuperMethods(checkAccess) - abstract override fun findSuperMethods(parentClass: PsiClass?): Array + override fun findSuperMethods(parentClass: PsiClass?) = clsDelegate.findSuperMethods(parentClass) } fun KtLightMethod.isTraitFakeOverride(): Boolean { diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightModifierList.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightModifierList.kt index f64377afc1c..356abf39282 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightModifierList.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightModifierList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.source.getPsi abstract class KtLightModifierList>( protected val owner: T ) : KtLightElementBase(owner), PsiModifierList, KtLightElement { + override val clsDelegate by lazyPub { owner.clsDelegate.modifierList!! } private val _annotations by lazyPub { val annotations = computeAnnotations() annotationsFilter?.let(annotations::filter) ?: annotations @@ -38,13 +39,9 @@ abstract class KtLightModifierList = annotations @@ -58,7 +55,14 @@ abstract class KtLightModifierList): List = emptyList() + protected open fun nonSourceAnnotationsForAnnotationType(sourceAnnotations: List): List { + + val annotations = parent.clsDelegate.modifierList?.annotations + + if (annotations.isNullOrEmpty()) return emptyList() + + return annotations.map { KtLightNonSourceAnnotation(this, it) } + } private fun computeAnnotations(): List { val annotationsForEntries = owner.givenAnnotations ?: lightAnnotationsForEntries(this) @@ -134,7 +138,21 @@ abstract class KtUltraLightModifierList>( owner: T -) : KtLightModifierList(owner) +) : KtLightModifierList(owner) { + + override val clsDelegate: PsiModifierList get() = invalidAccess() + + private fun throwInvalidOperation(): Nothing = throw IncorrectOperationException() + + override fun setModifierProperty(name: String, value: Boolean): Unit = throwInvalidOperation() + + override fun checkSetModifierProperty(name: String, value: Boolean): Unit = throwInvalidOperation() + + override fun addAnnotation(qualifiedName: String): PsiAnnotation = throwInvalidOperation() + + override fun nonSourceAnnotationsForAnnotationType(sourceAnnotations: List): List = + emptyList() +} class KtLightSimpleModifierList( owner: KtLightElement, private val modifiers: Set @@ -163,12 +181,23 @@ private fun lightAnnotationsForEntries(lightModifierList: KtLightModifierList<*> } .groupBy({ it.first }) { it.second } .flatMap { (fqName, entries) -> - entries.map { entry -> + entries.mapIndexed { index, entry -> + + val lazyClsDelegate = if (lightModifierList !is KtUltraLightModifierList) { + lazyPub { + lightModifierList.clsDelegate.annotations + .filter { it.qualifiedName == fqName } + .getOrNull(index) + ?: KtLightNonExistentAnnotation(lightModifierList) + } + } else null + KtLightAnnotationForSourceEntry( name = entry.shortName?.identifier, lazyQualifiedName = { fqName }, kotlinOrigin = entry, - parent = lightModifierList + parent = lightModifierList, + lazyClsDelegate = lazyClsDelegate ) } } @@ -201,8 +230,8 @@ private fun getAnnotationDescriptors( val annotatedDescriptor = when { descriptor is ClassDescriptor && annotatedLightElement is KtLightMethod && annotatedLightElement.isConstructor -> descriptor.unsubstitutedPrimaryConstructor - descriptor !is PropertyDescriptor -> descriptor + annotatedLightElement is KtLightFieldImpl.KtLightEnumConstant -> descriptor annotatedLightElement is KtLightField -> descriptor.backingField annotatedLightElement !is KtLightMethod -> descriptor annotatedLightElement.isGetter -> descriptor.getter diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightParameterImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightParameterImpl.kt new file mode 100644 index 00000000000..41cf5a78d16 --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightParameterImpl.kt @@ -0,0 +1,118 @@ +/* + * Copyright 2000-2017 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.asJava.elements + +import com.intellij.lang.Language +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.util.Computable +import com.intellij.openapi.util.TextRange +import com.intellij.psi.* +import com.intellij.psi.search.LocalSearchScope +import com.intellij.psi.search.SearchScope +import com.intellij.util.IncorrectOperationException +import org.jetbrains.annotations.NonNls +import org.jetbrains.kotlin.asJava.classes.lazyPub +import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration + +internal class KtLightParameterImpl( + private val dummyDelegate: PsiParameter, + private val clsDelegateProvider: () -> PsiParameter?, + private val index: Int, + method: KtLightMethod +) : LightParameter(dummyDelegate.name, dummyDelegate.type, method, KotlinLanguage.INSTANCE), + KtLightDeclaration, KtLightParameter { + + private val lazyDelegate by lazyPub { clsDelegateProvider() ?: dummyDelegate } + + override val clsDelegate: PsiParameter get() = lazyDelegate + + override fun getType(): PsiType = lazyDelegate.type + + override fun getName(): String = dummyDelegate.name + + private val lightModifierList by lazyPub { KtLightSimpleModifierList(this, emptySet()) } + + private val lightIdentifier: KtLightIdentifier? by lazyPub { + KtLightIdentifier(this, kotlinOrigin) + } + + override val kotlinOrigin: KtParameter? + get() { + val declaration = method.kotlinOrigin ?: return null + + val jetIndex = if (declaration.isExtensionDeclaration()) index - 1 else index + if (jetIndex < 0) return null + + if (declaration is KtFunction) { + val paramList = method.lightMemberOrigin?.parametersForJvmOverloads ?: declaration.valueParameters + return if (jetIndex < paramList.size) paramList[jetIndex] else null + } + + if (jetIndex != 0) return null + + val setter = when (declaration) { + is KtPropertyAccessor -> if (declaration.isSetter) declaration else null + is KtProperty -> declaration.setter + is KtParameter -> return declaration + else -> return null + } + + return setter?.parameter + } + + override fun getModifierList(): PsiModifierList = lightModifierList + + override fun getNavigationElement(): PsiElement = kotlinOrigin ?: super.getNavigationElement() + + override fun isValid(): Boolean = method.isValid + + @Throws(IncorrectOperationException::class) + override fun setName(@NonNls name: String): PsiElement { + kotlinOrigin?.setName(name) + return this + } + + override fun getContainingFile(): PsiFile = method.containingFile + + override fun getLanguage(): Language = KotlinLanguage.INSTANCE + + override fun getUseScope(): SearchScope { + return kotlinOrigin?.useScope ?: LocalSearchScope(this) + } + + override fun getText(): String = kotlinOrigin?.text ?: "" + + override fun getTextRange(): TextRange = kotlinOrigin?.textRange ?: TextRange.EMPTY_RANGE + + override fun getNameIdentifier(): PsiIdentifier? = lightIdentifier + + override fun getParent(): PsiElement = method.parameterList + + override fun isEquivalentTo(another: PsiElement?): Boolean { + if (this === another) return true + + return ApplicationManager.getApplication().runReadAction(Computable { + if (another is KtParameter) { + val kotlinOrigin = kotlinOrigin + if (kotlinOrigin?.isEquivalentTo(another) == true) return@Computable true + } + + if (another is KtLightParameterImpl) { + return@Computable kotlinOrigin != null && kotlinOrigin == another.kotlinOrigin && clsDelegate == another.clsDelegate + } + + false + }) + } + + override fun equals(other: Any?): Boolean { + return other is PsiElement && isEquivalentTo(other) + } + + override fun hashCode(): Int = kotlinOrigin?.hashCode() ?: 0 +} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiJavaCodeReferenceElement.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiJavaCodeReferenceElement.kt index 1da72a7b983..c863cbab736 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiJavaCodeReferenceElement.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiJavaCodeReferenceElement.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2018 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. */ @@ -14,31 +14,37 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub class KtLightPsiJavaCodeReferenceElement( private val ktElement: PsiElement, reference: () -> PsiReference?, + clsDelegateProvider: () -> PsiJavaCodeReferenceElement?, private val customReferenceName: String? = null, ) : PsiElement by ktElement, PsiReference by LazyPsiReferenceDelegate(ktElement, reference), PsiJavaCodeReferenceElement { - override fun advancedResolve(incompleteCode: Boolean): JavaResolveResult = JavaResolveResult.EMPTY + private val delegate by lazyPub(clsDelegateProvider) - override fun getReferenceNameElement(): PsiElement? = null + override fun advancedResolve(incompleteCode: Boolean): JavaResolveResult = + delegate?.advancedResolve(incompleteCode) ?: JavaResolveResult.EMPTY - override fun getTypeParameters(): Array = emptyArray() + override fun getReferenceNameElement(): PsiElement? = delegate?.referenceNameElement - override fun getReferenceName(): String? = customReferenceName + override fun getTypeParameters(): Array = delegate?.typeParameters ?: emptyArray() - override fun isQualified(): Boolean = false + override fun getReferenceName(): String? = customReferenceName ?: delegate?.referenceName - override fun processVariants(processor: PsiScopeProcessor) = Unit + override fun isQualified(): Boolean = delegate?.isQualified ?: false - override fun multiResolve(incompleteCode: Boolean): Array = emptyArray() + override fun processVariants(processor: PsiScopeProcessor) { + delegate?.processVariants(processor) + } - override fun getQualifiedName(): String? = null + override fun multiResolve(incompleteCode: Boolean): Array = delegate?.multiResolve(incompleteCode) ?: emptyArray() - override fun getQualifier(): PsiElement? = null + override fun getQualifiedName(): String? = delegate?.qualifiedName - override fun getParameterList(): PsiReferenceParameterList? = null + override fun getQualifier(): PsiElement? = delegate?.qualifier + + override fun getParameterList(): PsiReferenceParameterList? = delegate?.parameterList } private class LazyPsiReferenceDelegate( diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiReferenceList.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiReferenceList.kt new file mode 100644 index 00000000000..424caf1e995 --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiReferenceList.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.asJava.elements + +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiJavaCodeReferenceElement +import com.intellij.psi.PsiReferenceList +import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.asJava.classes.addSuperTypeEntry +import org.jetbrains.kotlin.asJava.classes.findEntry +import org.jetbrains.kotlin.asJava.classes.lazyPub +import org.jetbrains.kotlin.psi.KtSuperTypeList +import org.jetbrains.kotlin.psi.KtSuperTypeListEntry +import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext + +class KtLightPsiReferenceList( + override val clsDelegate: PsiReferenceList, + private val owner: KtLightClass +) : KtLightElement, PsiReferenceList by clsDelegate { + inner class KtLightSuperTypeReference( + override val clsDelegate: PsiJavaCodeReferenceElement + ) : KtLightElement, PsiJavaCodeReferenceElement by clsDelegate { + + override val kotlinOrigin by lazyPub { + clsDelegate.qualifiedName?.let { this@KtLightPsiReferenceList.kotlinOrigin?.findEntry(it) } + } + + override fun getParent() = this@KtLightPsiReferenceList + + override fun delete() { + val superTypeList = this@KtLightPsiReferenceList.kotlinOrigin ?: return + val entry = kotlinOrigin ?: return + superTypeList.removeEntry(entry) + } + + override fun getTextRange(): TextRange? = kotlinOrigin?.typeReference?.textRange ?: TextRange.EMPTY_RANGE + } + + override val kotlinOrigin: KtSuperTypeList? + get() = owner.kotlinOrigin?.getSuperTypeList() + + private val _referenceElements by lazyPub { + clsDelegate.referenceElements.map { KtLightSuperTypeReference(it) }.toTypedArray() + } + + override fun getParent() = owner + + override fun getReferenceElements() = _referenceElements + + override fun add(element: PsiElement): PsiElement? { + if (element !is KtLightSuperTypeReference) throw UnsupportedOperationException("Unexpected element: ${element.getElementTextWithContext()}") + + val superTypeList = kotlinOrigin ?: return element + val entry = element.kotlinOrigin ?: return element + + this.addSuperTypeEntry(superTypeList, entry, element) + + return element + } +} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightTypeParameter.java b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightTypeParameter.java new file mode 100644 index 00000000000..25d22318263 --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightTypeParameter.java @@ -0,0 +1,184 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.asJava.elements; + +import com.intellij.lang.Language; +import com.intellij.psi.*; +import com.intellij.psi.impl.light.AbstractLightClass; +import com.intellij.psi.search.SearchScope; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.asJava.LightClassUtilsKt; +import org.jetbrains.kotlin.asJava.classes.KtLightClass; +import org.jetbrains.kotlin.idea.KotlinLanguage; +import org.jetbrains.kotlin.psi.KtTypeParameter; +import org.jetbrains.kotlin.psi.KtTypeParameterListOwner; + +import java.util.List; + +public class KtLightTypeParameter + extends AbstractLightClass implements PsiTypeParameter, KtLightDeclaration { + private final PsiTypeParameterListOwner owner; + private final int index; + private final String name; + + public KtLightTypeParameter( + @NotNull PsiTypeParameterListOwner owner, + int index, + @NotNull String name + ) { + super(owner.getManager(), KotlinLanguage.INSTANCE); + this.owner = owner; + this.index = index; + this.name = name; + } + + @NotNull + @Override + public PsiTypeParameter getClsDelegate() { + return getOwnerDelegate().getTypeParameters()[index]; + } + + @NotNull + @Override + public PsiClass getDelegate() { + return getClsDelegate(); + } + + @NotNull + @Override + public KtTypeParameter getKotlinOrigin() { + KtTypeParameterListOwner jetOwner = (KtTypeParameterListOwner) LightClassUtilsKt.getUnwrapped(owner); + assert (jetOwner != null) : "Invalid type parameter owner: " + owner; + + return jetOwner.getTypeParameters().get(index); + } + + @NotNull + private PsiTypeParameterListOwner getOwnerDelegate() { + if (owner instanceof KtLightClass) return ((KtLightClass) owner).getClsDelegate(); + if (owner instanceof KtLightMethod) return ((KtLightMethod) owner).getClsDelegate(); + return owner; + } + + @NotNull + @Override + public PsiElement copy() { + return new KtLightTypeParameter(owner, index, name); + } + + @Override + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JavaElementVisitor) { + ((JavaElementVisitor) visitor).visitTypeParameter(this); + } + else { + super.accept(visitor); + } + } + + @Override + public String getText() { + return ""; + } + + @Nullable + @Override + public String getName() { + return name; + } + + @Override + public PsiTypeParameterListOwner getOwner() { + return owner; + } + + @Override + public int getIndex() { + return index; + } + + @NotNull + @Override + public PsiAnnotation[] getAnnotations() { + return getClsDelegate().getAnnotations(); + } + + @NotNull + @Override + public PsiAnnotation[] getApplicableAnnotations() { + return getClsDelegate().getApplicableAnnotations(); + } + + @Override + public PsiAnnotation findAnnotation(@NotNull String qualifiedName) { + return getClsDelegate().findAnnotation(qualifiedName); + } + + @NotNull + @Override + public PsiAnnotation addAnnotation(@NotNull String qualifiedName) { + return getClsDelegate().addAnnotation(qualifiedName); + } + + @Override + public String toString() { + return "KotlinLightTypeParameter:" + getName(); + } + + @NotNull + @Override + public PsiElement getNavigationElement() { + return getKotlinOrigin(); + } + + @NotNull + @Override + public Language getLanguage() { + return KotlinLanguage.INSTANCE; + } + + @NotNull + @Override + public SearchScope getUseScope() { + return getKotlinOrigin().getUseScope(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + return obj instanceof KtLightTypeParameter && getKotlinOrigin().equals(((KtLightTypeParameter) obj).getKotlinOrigin()); + } + + @Override + public boolean isEquivalentTo(PsiElement another) { + if (another instanceof PsiTypeParameter) { + PsiTypeParameter anotherTypeParameter = (PsiTypeParameter) another; + PsiTypeParameterListOwner owner = getOwner(); + if (owner != null) { + return owner.isEquivalentTo(anotherTypeParameter.getOwner()) && getIndex() == anotherTypeParameter.getIndex(); + } + } + return false; + } + + @Nullable + @Override + public List getGivenAnnotations() { + return null; + } +} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtToJvmAnnotationsConverter.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtToJvmAnnotationsConverter.kt index e3676007b7c..b4752c81383 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtToJvmAnnotationsConverter.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtToJvmAnnotationsConverter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -152,6 +152,7 @@ internal fun PsiAnnotation.tryConvertAsRepeatable( KtLightPsiJavaCodeReferenceElement( ktElement = it, reference = { null }, + clsDelegateProvider = { null }, customReferenceName = JAVA_LANG_ANNOTATION_REPEATABLE_SHORT_NAME, ) } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt index 19bd91bb9f1..613bf7c4623 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt @@ -1,14 +1,17 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.asJava.elements +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.diagnostic.Logger import com.intellij.psi.* import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable +import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.classes.cannotModify import org.jetbrains.kotlin.asJava.classes.lazyPub @@ -25,12 +28,12 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils +import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall +import org.jetbrains.kotlin.resolve.calls.util.getType import org.jetbrains.kotlin.resolve.calls.components.isVararg import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument -import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.util.getType import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.KotlinType @@ -40,14 +43,22 @@ import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.nullability -abstract class KtLightAbstractAnnotation(parent: PsiElement) : +private val LOG = Logger.getInstance("#org.jetbrains.kotlin.asJava.elements.lightAnnotations") + +abstract class KtLightAbstractAnnotation(parent: PsiElement, computeDelegate: Lazy?) : KtLightElementBase(parent), PsiAnnotation, KtLightElement { - abstract override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? + override val clsDelegate: PsiAnnotation by lazyPub { + if (!accessAnnotationsClsDelegateIsAllowed && ApplicationManager.getApplication().isUnitTestMode && this !is KtLightNonSourceAnnotation) + LOG.error("KtLightAbstractAnnotation clsDelegate requested for ${this.javaClass}") + computeDelegate?.value ?: throw IllegalStateException("Cannot get class delegate for annotation light class") + } + + override fun getNameReferenceElement() = clsDelegate.nameReferenceElement override fun getOwner(): PsiAnnotationOwner? = parent as? PsiAnnotationOwner - abstract override fun getParameterList(): PsiAnnotationParameterList + override fun getParameterList(): PsiAnnotationParameterList = clsDelegate.parameterList open fun fqNameMatches(fqName: String): Boolean = qualifiedName == fqName } @@ -56,8 +67,9 @@ class KtLightAnnotationForSourceEntry( private val name: String?, private val lazyQualifiedName: () -> String?, override val kotlinOrigin: KtCallElement, - parent: PsiElement -) : KtLightAbstractAnnotation(parent) { + parent: PsiElement, + private val lazyClsDelegate: Lazy? +) : KtLightAbstractAnnotation(parent, lazyClsDelegate) { private val _qualifiedName: String? by lazyPub { lazyQualifiedName() } @@ -89,7 +101,6 @@ class KtLightAnnotationForSourceEntry( when (val psiElement = callEntry.key.source.getPsi()) { is KtParameter -> return psiElement.defaultValue?.let { convertToLightAnnotationMemberValue(this, it) } - is PsiAnnotationMethod -> return psiElement.defaultValue } @@ -105,6 +116,7 @@ class KtLightAnnotationForSourceEntry( (kotlinOrigin as? KtAnnotationEntry)?.typeReference?.reference ?: (kotlinOrigin.calleeExpression?.nameReference)?.references?.firstOrNull() }, + { lazyClsDelegate?.value?.nameReferenceElement }, if (qualifiedName == CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE) JAVA_LANG_ANNOTATION_REPEATABLE_SHORT_NAME else null, ) @@ -220,13 +232,40 @@ class KtLightAnnotationForSourceEntry( override fun setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify() } +class KtLightNonSourceAnnotation( + parent: PsiElement, clsDelegate: PsiAnnotation +) : KtLightAbstractAnnotation(parent, lazyPub { clsDelegate }) { + override val kotlinOrigin: KtAnnotationEntry? get() = null + override fun getQualifiedName() = kotlinOrigin?.name ?: clsDelegate.qualifiedName + override fun setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify() + override fun findAttributeValue(attributeName: String?) = clsDelegate.findAttributeValue(attributeName) + override fun findDeclaredAttributeValue(attributeName: String?) = clsDelegate.findDeclaredAttributeValue(attributeName) +} + +class KtLightNonExistentAnnotation(parent: KtLightElement<*, *>) : KtLightElementBase(parent), PsiAnnotation { + override val kotlinOrigin: KtElement? get() = null + override fun toString(): String = this.javaClass.name + + override fun setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify() + + override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = null + override fun findAttributeValue(attributeName: String?): PsiAnnotationMemberValue? = null + override fun getQualifiedName(): String? = null + override fun getOwner(): PsiAnnotationOwner? = parent as? PsiAnnotationOwner + override fun findDeclaredAttributeValue(attributeName: String?): PsiAnnotationMemberValue? = null + override fun getParameterList(): KtLightEmptyAnnotationParameterList = KtLightEmptyAnnotationParameterList(this) +} + class KtLightEmptyAnnotationParameterList(parent: PsiElement) : KtLightElementBase(parent), PsiAnnotationParameterList { override val kotlinOrigin: KtElement? get() = null override fun getAttributes(): Array = emptyArray() } open class KtLightNullabilityAnnotation>(val member: D, parent: PsiElement) : - KtLightAbstractAnnotation(parent) { + KtLightAbstractAnnotation(parent, lazyPub { + // searching for last because nullability annotations are generated after backend generates source annotations + getClsNullabilityAnnotation(member) ?: KtLightNonExistentAnnotation(member) + }) { override fun fqNameMatches(fqName: String): Boolean { if (!isNullabilityAnnotation(fqName)) return false @@ -241,7 +280,7 @@ open class KtLightNullabilityAnnotation): PsiAnnotation? { + if (!accessAnnotationsClsDelegateIsAllowed && ApplicationManager.getApplication().isUnitTestMode && isFromSources(member) && member.kotlinOrigin != null) + LOG.error("nullability should be retrieved from `kotlinOrigin`") + return member.clsDelegate.modifierList?.annotations?.findLast { + isNullabilityAnnotation(it.qualifiedName) + } +} + internal fun isNullabilityAnnotation(qualifiedName: String?) = qualifiedName in backendNullabilityAnnotations private val backendNullabilityAnnotations = arrayOf(Nullable::class.java.name, NotNull::class.java.name) @@ -341,11 +388,9 @@ fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExp is KtClassLiteralExpression -> { return KtLightPsiClassObjectAccessExpression(argument, lightParent) } - is KtStringTemplateExpression, is KtConstantExpression -> { return KtLightPsiLiteral(argument, lightParent) } - is KtCallExpression -> { val arguments = argument.valueArguments val annotationName = argument.calleeExpression?.let { getAnnotationName(it) } @@ -354,7 +399,8 @@ fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExp name = annotationName, lazyQualifiedName = { annotationName }, kotlinOrigin = argument, - parent = lightParent + parent = lightParent, + lazyClsDelegate = null ) } val resolvedCall = argument.getResolvedCall() @@ -368,7 +414,6 @@ fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExp } } } - is KtCollectionLiteralExpression -> { val arguments = argument.getInnerExpressions() if (arguments.isNotEmpty()) @@ -406,3 +451,17 @@ private fun getAnnotationName(callee: KtExpression): String? { } return null } + +@get:TestOnly +var accessAnnotationsClsDelegateIsAllowed = false + +@TestOnly +fun withAllowedAnnotationsClsDelegate(body: () -> T): T { + val prev = accessAnnotationsClsDelegateIsAllowed + try { + accessAnnotationsClsDelegateIsAllowed = true + return body() + } finally { + accessAnnotationsClsDelegateIsAllowed = prev + } +} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/lightClassUtils.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/lightClassUtils.kt index 21f832eb968..b739bd49289 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/lightClassUtils.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/lightClassUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -229,7 +229,9 @@ fun KtLightMethod.checkIsMangled(): Boolean { } fun fastCheckIsNullabilityApplied(lightElement: KtLightElement<*, PsiModifierListOwner>): Boolean { - val elementIsApplicable = lightElement is KtLightMember<*> || lightElement is LightParameter + + val elementIsApplicable = + (lightElement is KtLightMember<*> && lightElement !is KtLightFieldImpl.KtLightEnumConstant) || lightElement is LightParameter if (!elementIsApplicable) return false val annotatedElement = lightElement.kotlinOrigin ?: return true diff --git a/compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassCoherenceTest.java b/compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassCoherenceTest.java new file mode 100644 index 00000000000..9ada04e4a10 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassCoherenceTest.java @@ -0,0 +1,215 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.asJava; + +import com.google.common.collect.Lists; +import com.intellij.openapi.util.Comparing; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.search.GlobalSearchScope; +import junit.framework.ComparisonFailure; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.asJava.classes.KtLightClass; +import org.jetbrains.kotlin.asJava.classes.KtUltraLightSupport; +import org.jetbrains.kotlin.name.SpecialNames; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; + + +public class KotlinLightClassCoherenceTest extends KotlinAsJavaTestBase { + + @Override + protected List getKotlinSourceRoots() { + return Lists.newArrayList( + new File("compiler/testData/asJava/lightClassStructure/Declared.kt"), + new File("compiler/testData/asJava/lightClassStructure/Package.kt"), + new File("compiler/testData/asJava/lightClassStructure/ClassObject.kt") + ); + } + + @NotNull + protected PsiClass doTest() { + return doTest("test." + getTestName(false)); + } + + @NotNull + protected PsiClass doTest(String qualifiedName) { + boolean forceFlag = KtUltraLightSupport.Companion.getForceUsingOldLightClasses(); + KtLightClass psiClass; + try { + KtUltraLightSupport.Companion.setForceUsingOldLightClasses(true); + psiClass = (KtLightClass) finder.findClass(qualifiedName, GlobalSearchScope.allScope(getProject())); + } finally { + KtUltraLightSupport.Companion.setForceUsingOldLightClasses(forceFlag); + } + + assertNotNull("Class not found: " + qualifiedName, psiClass); + + Asserter asserter = new Asserter(); + + asserter.assertModifiersCoherent(psiClass); + + asserter.assertPropertyCoherent(psiClass, "isInterface"); + asserter.assertPropertyCoherent(psiClass, "isAnnotationType"); + asserter.assertPropertyCoherent(psiClass, "isEnum"); + asserter.assertPropertyCoherent(psiClass, "hasTypeParameters"); + asserter.assertPropertyCoherent(psiClass, "isDeprecated"); + + asserter.reportFailures(); + + return psiClass; + } + + static class Asserter { + private final List failures = Lists.newArrayList(); + + private void assertEquals(String message, Object expected, Object actual) { + if (!Comparing.equal(expected, actual)) { + failures.add(new ComparisonFailure(message, String.valueOf(expected), String.valueOf(actual))); + } + } + + public void assertModifiersCoherent(KtLightClass lightClass) { + PsiClass delegate = lightClass.getClsDelegate(); + for (String modifier : PsiModifier.MODIFIERS) { + assertEquals("Incoherent modifier: " + modifier, + delegate.hasModifierProperty(modifier), + lightClass.hasModifierProperty(modifier)); + } + } + + public void assertPropertyCoherent(KtLightClass lightClass, String methodName) { + try { + Method method = PsiClass.class.getMethod(methodName); + Object lightResult = method.invoke(lightClass); + Object delegateResult = method.invoke(lightClass.getClsDelegate()); + assertEquals("Result of method " + methodName + "() differs in light class and its delegate", delegateResult, lightResult); + } + catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw new AssertionError(e); + } + } + + public void reportFailures() { + if (failures.size() == 1) { + throw failures.get(0); + } + if (!failures.isEmpty()) { + StringBuilder builder = new StringBuilder("\n"); + for (ComparisonFailure failure : failures) { + builder.append(failure.getMessage()).append("\n"); + } + fail(builder.toString()); + } + } + } + + public void testFileFacade() throws Exception { + doTest("test.PackageKt"); + } + + public void testNoModifiers() throws Exception { + doTest(); + } + + public void testPublic() throws Exception { + doTest(); + } + + public void testPrivate() throws Exception { + doTest(); + } + + public void testInternal() throws Exception { + doTest(); + } + + public void testNestedPublic() throws Exception { + doTest("test.Outer.Public"); + } + + public void testNestedProtected() throws Exception { + doTest("test.Outer.Protected"); + } + + public void testNestedInternal() throws Exception { + doTest("test.Outer.Internal"); + } + + public void testNestedPrivate() throws Exception { + doTest("test.Outer.Private"); + } + + public void testInner() throws Exception { + doTest("test.Outer.Inner"); + } + + public void testAbstract() throws Exception { + doTest(); + } + + public void testOpen() throws Exception { + doTest(); + } + + public void testFinal() throws Exception { + doTest(); + } + + public void testAnnotation() throws Exception { + doTest(); + } + + public void testEnum() throws Exception { + doTest(); + } + + public void testTrait() throws Exception { + doTest(); + } + + public void testDeprecatedClass() throws Exception { + doTest(); + } + + public void testDeprecatedFQN() throws Exception { + doTest(); + } + + public void testDeprecatedFQNSpaces() throws Exception { + doTest(); + } + + public void testDeprecatedWithBrackets() throws Exception { + doTest(); + } + + public void testDeprecatedWithBracketsFQN() throws Exception { + doTest(); + } + + public void testDeprecatedWithBracketsFQNSpaces() throws Exception { + doTest(); + } + + public void testClassObject() throws Exception { + doTest("test.WithClassObject." + SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.asString()); + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassTest.kt b/compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassTest.kt index 62f2d58e2bd..3f132a2ece4 100644 --- a/compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassTest.kt @@ -1,6 +1,17 @@ /* - * 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. + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.jetbrains.kotlin.asJava @@ -13,8 +24,8 @@ import java.io.File class KotlinLightClassTest : KotlinAsJavaTestBase() { override fun getKotlinSourceRoots(): List = listOf( - File("compiler/testData/asJava/lightClassStructure/ClassObject.kt"), - File("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.kt") + File("compiler/testData/asJava/lightClassStructure/ClassObject.kt"), + File("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.kt") ) private val key = Key.create("testKey")