Revert "[light classes] drop old light classes and backend: iteration #1"

This reverts commit 3cb2df9360.
This commit is contained in:
Dmitry Gridin
2022-06-28 13:52:11 +02:00
parent 43b4df74bc
commit 57de064251
61 changed files with 2000 additions and 387 deletions
@@ -1,7 +1,4 @@
/* // 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.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.decompiled.light.classes 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 import org.jetbrains.kotlin.psi.KtClassOrObject
open class KtLightClassForDecompiledDeclaration( open class KtLightClassForDecompiledDeclaration(
clsDelegate: PsiClass, override val clsDelegate: PsiClass,
private val clsParent: PsiElement, private val clsParent: PsiElement,
private val file: KtClsFile, private val file: KtClsFile,
kotlinOrigin: KtClassOrObject? kotlinOrigin: KtClassOrObject?
@@ -1,7 +1,4 @@
/* // 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.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.decompiled.light.classes 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 import org.jetbrains.kotlin.psi.KtClassOrObject
abstract class KtLightClassForDecompiledDeclarationBase( abstract class KtLightClassForDecompiledDeclarationBase(
val clsDelegate: PsiClass, override val clsDelegate: PsiClass,
clsParent: PsiElement, clsParent: PsiElement,
final override val kotlinOrigin: KtClassOrObject? final override val kotlinOrigin: KtClassOrObject?
) : KtLightElementBase(clsParent), PsiClass, KtExtensibleLightClass ) : KtLightElementBase(clsParent), PsiClass, KtExtensibleLightClass
@@ -1,7 +1,4 @@
/* // 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.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.decompiled.light.classes 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 fun toString(): String = "${this.javaClass.simpleName} of $fldParent"
override val clsDelegate: PsiField = fldDelegate
override fun isValid(): Boolean = parent.isValid override fun isValid(): Boolean = parent.isValid
} }
@@ -1,7 +1,4 @@
/* // 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.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.decompiled.light.classes package org.jetbrains.kotlin.analysis.decompiled.light.classes
@@ -100,6 +97,8 @@ class KtLightMethodForDecompiledDeclaration(
override fun toString(): String = "${this.javaClass.simpleName} of $funParent" override fun toString(): String = "${this.javaClass.simpleName} of $funParent"
override val clsDelegate: PsiMethod = funDelegate
override fun isValid(): Boolean = parent.isValid override fun isValid(): Boolean = parent.isValid
} }
@@ -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. * 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<T : PsiMember>(
private val containingClass: KtLightClass, private val containingClass: KtLightClass,
) : KtLightElementBase(containingClass), PsiMember, KtLightMember<T> { ) : KtLightElementBase(containingClass), PsiMember, KtLightMember<T> {
override val clsDelegate: T
get() = invalidAccess()
override fun hasModifierProperty(name: String): Boolean = modifierList?.hasModifierProperty(name) ?: false override fun hasModifierProperty(name: String): Boolean = modifierList?.hasModifierProperty(name) ?: false
override fun toString(): String = "${this::class.java.simpleName}:$name" override fun toString(): String = "${this::class.java.simpleName}:$name"
@@ -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. * 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) : internal abstract class FirLightAbstractAnnotation(parent: PsiElement) :
KtLightElementBase(parent), PsiAnnotation, KtLightElement<KtCallElement, PsiAnnotation> { KtLightElementBase(parent), PsiAnnotation, KtLightElement<KtCallElement, PsiAnnotation> {
override val clsDelegate: PsiAnnotation
get() = invalidAccess()
override fun getOwner() = parent as? PsiAnnotationOwner override fun getOwner() = parent as? PsiAnnotationOwner
private val KtExpression.nameReference: KtNameReferenceExpression? private val KtExpression.nameReference: KtNameReferenceExpression?
@@ -1,6 +1,17 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2016 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.light.classes.symbol
@@ -19,16 +30,19 @@ import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.PsiUtil import com.intellij.psi.util.PsiUtil
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt 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.analysis.providers.createProjectWideOutOfBlockModificationTracker
import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.idea.KotlinLanguage 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 org.jetbrains.kotlin.light.classes.symbol.classes.checkIsInheritor
import javax.swing.Icon import javax.swing.Icon
abstract class FirLightClassBase protected constructor( abstract class FirLightClassBase protected constructor(
manager: PsiManager manager: PsiManager
) : LightElement(manager, KotlinLanguage.INSTANCE), PsiClass, KtExtensibleLightClass { ) : LightElement(manager, KotlinLanguage.INSTANCE), PsiClass, KtExtensibleLightClass {
override val clsDelegate: PsiClass
get() = invalidAccess()
private class FirLightClassesLazyCreator(private val project: Project) : KotlinClassInnerStuffCache.LazyCreator() { private class FirLightClassesLazyCreator(private val project: Project) : KotlinClassInnerStuffCache.LazyCreator() {
@OptIn(KtAllowAnalysisOnEdt::class) @OptIn(KtAllowAnalysisOnEdt::class)
override fun <T : Any> get(initializer: () -> T, dependencies: List<Any>): Lazy<T> = object : Lazy<T> { override fun <T : Any> get(initializer: () -> T, dependencies: List<Any>): Lazy<T> = object : Lazy<T> {
@@ -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. * 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.LightEmptyImplementsList
import com.intellij.psi.impl.light.LightModifierList import com.intellij.psi.impl.light.LightModifierList
import org.jetbrains.annotations.NonNls 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.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass 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.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.idea.KotlinLanguage 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.analyseForLightClasses
import org.jetbrains.kotlin.light.classes.symbol.classes.createField import org.jetbrains.kotlin.light.classes.symbol.classes.createField
import org.jetbrains.kotlin.light.classes.symbol.classes.createMethods import org.jetbrains.kotlin.light.classes.symbol.classes.createMethods
@@ -50,6 +50,8 @@ class FirLightClassForFacade(
private val firstFileInFacade by lazyPub { files.first() } private val firstFileInFacade by lazyPub { files.first() }
override val clsDelegate: PsiClass get() = invalidAccess()
private val fileSymbols by lazyPub { private val fileSymbols by lazyPub {
files.map { ktFile -> files.map { ktFile ->
analyseForLightClasses(ktFile) { analyseForLightClasses(ktFile) {
@@ -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. * 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 import org.jetbrains.kotlin.psi.KtFile
internal class KtLightClassForDecompiledFacade( internal class KtLightClassForDecompiledFacade(
clsDelegate: PsiClass, override val clsDelegate: PsiClass,
clsParent: PsiElement, clsParent: PsiElement,
file: KtClsFile, file: KtClsFile,
kotlinOrigin: KtClassOrObject?, kotlinOrigin: KtClassOrObject?,
@@ -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. * 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, private val containingClass: KtLightClass,
lightMemberOrigin: LightMemberOrigin?, lightMemberOrigin: LightMemberOrigin?,
) : FirLightMemberImpl<PsiField>(lightMemberOrigin, containingClass), KtLightField { ) : FirLightMemberImpl<PsiField>(lightMemberOrigin, containingClass), KtLightField {
override val clsDelegate: PsiField get() = invalidAccess()
override fun setInitializer(initializer: PsiExpression?) = cannotModify() override fun setInitializer(initializer: PsiExpression?) = cannotModify()
override fun isEquivalentTo(another: PsiElement?): Boolean = override fun isEquivalentTo(another: PsiElement?): Boolean =
@@ -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. * 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<out T : KtLightElement<KtModifierLi
protected val owner: T protected val owner: T
) : KtLightElementBase(owner), PsiModifierList, KtLightElement<KtModifierList, PsiModifierListOwner> { ) : KtLightElementBase(owner), PsiModifierList, KtLightElement<KtModifierList, PsiModifierListOwner> {
override val clsDelegate: PsiModifierListOwner
get() = invalidAccess()
override val kotlinOrigin: KtModifierList? override val kotlinOrigin: KtModifierList?
get() = owner.kotlinOrigin?.modifierList get() = owner.kotlinOrigin?.modifierList
@@ -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. * 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, internal abstract class FirLightParameter(containingDeclaration: FirLightMethod) : PsiVariable, NavigationItem,
KtLightElement<KtParameter, PsiParameter>, KtLightParameter, KtLightElementBase(containingDeclaration) { KtLightElement<KtParameter, PsiParameter>, KtLightParameter, KtLightElementBase(containingDeclaration) {
override val clsDelegate: PsiParameter
get() = invalidAccess()
override val givenAnnotations: List<KtLightAbstractAnnotation> override val givenAnnotations: List<KtLightAbstractAnnotation>
get() = invalidAccess() get() = invalidAccess()
@@ -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. * 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.PsiParameter
import com.intellij.psi.PsiParameterList import com.intellij.psi.PsiParameterList
import com.intellij.psi.impl.light.LightParameterListBuilder 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.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase 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.KtFunction
import org.jetbrains.kotlin.psi.KtParameterList import org.jetbrains.kotlin.psi.KtParameterList
@@ -28,7 +28,7 @@ internal class FirLightParameterList(
override val kotlinOrigin: KtParameterList? override val kotlinOrigin: KtParameterList?
get() = (parent.kotlinOrigin as? KtFunction)?.valueParameterList get() = (parent.kotlinOrigin as? KtFunction)?.valueParameterList
private val clsDelegate: PsiParameterList by lazyPub { override val clsDelegate: PsiParameterList by lazyPub {
val builder = LightParameterListBuilder(manager, language) val builder = LightParameterListBuilder(manager, language)
callableSymbol?.let { callableSymbol?.let {
@@ -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. * 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, ) : LightElement(parent.manager, KotlinLanguage.INSTANCE), PsiTypeParameter,
KtLightDeclaration<KtTypeParameter, PsiTypeParameter> { KtLightDeclaration<KtTypeParameter, PsiTypeParameter> {
override val clsDelegate: PsiTypeParameter get() = invalidAccess()
override val givenAnnotations: List<KtLightAbstractAnnotation>? get() = invalidAccess() override val givenAnnotations: List<KtLightAbstractAnnotation>? get() = invalidAccess()
override val kotlinOrigin: KtTypeParameter? = typeParameterSymbol.psi as? KtTypeParameter override val kotlinOrigin: KtTypeParameter? = typeParameterSymbol.psi as? KtTypeParameter
@@ -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. * 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 com.intellij.util.SmartList
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.classes.* import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.load.java.components.FilesByFacadeFqNameIndexer import org.jetbrains.kotlin.load.java.components.FilesByFacadeFqNameIndexer
@@ -108,9 +109,11 @@ class CliKotlinAsJavaSupport(
).mapNotNull { member -> (member as? PackageViewDescriptor)?.fqName } ).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<KtClassOrObject> { override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject> {
return ResolveSessionUtils.getClassDescriptorsByFqName(traceHolder.module, fqName).mapNotNull { return ResolveSessionUtils.getClassDescriptorsByFqName(traceHolder.module, fqName).mapNotNull {
@@ -127,5 +130,6 @@ class CliKotlinAsJavaSupport(
}.orEmpty() }.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")
} }
@@ -1,6 +1,17 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2016 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 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.ClassBuilderMode
import org.jetbrains.kotlin.codegen.JvmCodegenUtil import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -93,6 +105,9 @@ class CliLightClassGenerationSupport(
return ultraLightSupport return ultraLightSupport
} }
override val useUltraLightClasses: Boolean
get() = !KtUltraLightSupport.forceUsingOldLightClasses && !traceHolder.languageVersionSettings.getFlag(JvmAnalysisFlags.disableUltraLightClasses)
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass { override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
//force resolve companion for light class generation //force resolve companion for light class generation
traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor
@@ -1,13 +1,27 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2016 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.asJava
import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project 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.PsiManager
import com.intellij.psi.util.CachedValue
import org.jetbrains.kotlin.asJava.builder.LightClassBuilderResult import org.jetbrains.kotlin.asJava.builder.LightClassBuilderResult
import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
@@ -45,11 +59,18 @@ abstract class LightClassGenerationSupport {
ConstantExpressionEvaluator(moduleDescriptor, languageVersionSettings, expression.project) ConstantExpressionEvaluator(moduleDescriptor, languageVersionSettings, expression.project)
} }
internal fun canCreateUltraLightClassForFacade(files: Collection<KtFile>): Boolean = files.none { it.isScript() } abstract val useUltraLightClasses: Boolean
internal fun canCreateUltraLightClassForFacade(
files: Collection<KtFile>,
): Boolean {
return useUltraLightClasses && files.none { it.isScript() }
}
fun createUltraLightClassForFacade( fun createUltraLightClassForFacade(
manager: PsiManager, manager: PsiManager,
facadeClassFqName: FqName, facadeClassFqName: FqName,
lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>,
files: Collection<KtFile>, files: Collection<KtFile>,
): KtUltraLightClassForFacade? { ): KtUltraLightClassForFacade? {
if (!canCreateUltraLightClassForFacade(files)) return null if (!canCreateUltraLightClassForFacade(files)) return null
@@ -61,12 +82,16 @@ abstract class LightClassGenerationSupport {
return KtUltraLightClassForFacade( return KtUltraLightClassForFacade(
manager, manager,
facadeClassFqName, facadeClassFqName,
lightClassDataCache,
files, files,
filesToSupports filesToSupports
) )
} }
fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass? { fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass? {
if (!useUltraLightClasses) return null
if (element.shouldNotBeVisibleAsLightClass()) { if (element.shouldNotBeVisibleAsLightClass()) {
return null return null
} }
@@ -92,8 +117,8 @@ abstract class LightClassGenerationSupport {
} }
} }
fun createUltraLightClassForScript(script: KtScript): KtUltraLightClassForScript = fun createUltraLightClassForScript(script: KtScript): KtUltraLightClassForScript? =
KtUltraLightClassForScript(script, support = getUltraLightClassSupport(script)) if (useUltraLightClasses) KtUltraLightClassForScript(script, support = getUltraLightClassSupport(script)) else null
companion object { companion object {
@JvmStatic @JvmStatic
@@ -1,14 +1,22 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2016 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.asJava
import com.intellij.psi.PsiClass import com.intellij.psi.*
import com.intellij.psi.PsiField
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiNamedElement
import com.intellij.psi.impl.java.stubs.PsiClassStub import com.intellij.psi.impl.java.stubs.PsiClassStub
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.PsiFileStub import com.intellij.psi.stubs.PsiFileStub
@@ -16,10 +24,7 @@ import com.intellij.psi.stubs.StubElement
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.asJava.elements.*
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.finder.JavaElementFinder import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.load.java.JvmAbi 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( class PropertyAccessorsPsiMethods(
val getter: PsiMethod?, val getter: PsiMethod?,
val setter: PsiMethod?, val setter: PsiMethod?,
@@ -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. * 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 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.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.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
interface LightClassDataHolder { interface LightClassDataHolder {
val javaFileStub: PsiJavaFileStub val javaFileStub: PsiJavaFileStub
val extraDiagnostics: Diagnostics val extraDiagnostics: Diagnostics
interface ForClass : LightClassDataHolder fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass): LightClassData
interface ForFacade : LightClassDataHolder
interface ForScript : ForClass 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<PsiClassType>
get() {
return clsDelegate.superTypes
}
fun getOwnFields(containingClass: KtLightClass): List<KtLightField>
fun getOwnMethods(containingClass: KtLightClass): List<KtLightMethod>
}
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 { object InvalidLightClassDataHolder : LightClassDataHolder.ForClass {
@@ -24,10 +74,50 @@ object InvalidLightClassDataHolder : LightClassDataHolder.ForClass {
override val extraDiagnostics: Diagnostics override val extraDiagnostics: Diagnostics
get() = shouldNotBeCalled() get() = shouldNotBeCalled()
override fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass) = shouldNotBeCalled()
private fun shouldNotBeCalled(): Nothing = throw UnsupportedOperationException("Should not be called") private fun shouldNotBeCalled(): Nothing = throw UnsupportedOperationException("Should not be called")
} }
class LightClassDataHolderImpl( class LightClassDataHolderImpl(
override val javaFileStub: PsiJavaFileStub, override val javaFileStub: PsiJavaFileStub,
override val extraDiagnostics: Diagnostics 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<String>()
findClass(javaFileStub) { cls ->
names.add(cls.qualifiedName ?: "<null>")
false
}
return names.joinToString(prefix = "[", postfix = "]")
}
@@ -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. * 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.PsiClassImplUtil
import com.intellij.psi.impl.PsiImplUtil import com.intellij.psi.impl.PsiImplUtil
import com.intellij.psi.impl.PsiSuperMethodImplUtil 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.impl.light.*
import com.intellij.psi.javadoc.PsiDocComment import com.intellij.psi.javadoc.PsiDocComment
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubElement
import com.intellij.psi.util.* import com.intellij.psi.util.*
import com.intellij.util.ArrayUtil import com.intellij.util.ArrayUtil
import com.intellij.util.IncorrectOperationException 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.KtDeclaration
import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.org.objectweb.asm.Opcodes
import java.util.* import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
class KotlinClassInnerStuffCache( class KotlinClassInnerStuffCache(
private val myClass: KtExtensibleLightClass, private val myClass: KtExtensibleLightClass,
@@ -191,6 +200,8 @@ private class KotlinEnumSyntheticMethod(
val nameParameter = object : LightParameter("name", stringType, this, language, false), KtLightParameter { val nameParameter = object : LightParameter("name", stringType, this, language, false), KtLightParameter {
override val method: KtLightMethod get() = this@KotlinEnumSyntheticMethod override val method: KtLightMethod get() = this@KotlinEnumSyntheticMethod
override val kotlinOrigin: KtParameter? get() = null 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 getParent(): PsiElement = this@KotlinEnumSyntheticMethod
override fun getContainingFile(): PsiFile = this@KotlinEnumSyntheticMethod.containingFile override fun getContainingFile(): PsiFile = this@KotlinEnumSyntheticMethod.containingFile
@@ -274,7 +285,52 @@ private class KotlinEnumSyntheticMethod(
override fun getText(): String = "" override fun getText(): String = ""
override fun getTextRange(): TextRange = TextRange.EMPTY_RANGE 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<PsiClass> {
override fun findInnerClass(innerName: String, outerClass: PsiClass): PsiClass? = null
override fun accept(innerClass: PsiClass, visitor: StubBuildingVisitor<PsiClass>) {}
}
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 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 { private fun makeNotNullAnnotation(context: PsiClass): PsiAnnotation {
return PsiElementFactory.getInstance(context.project).createAnnotationFromText("@" + NotNull::class.java.name, context) return PsiElementFactory.getInstance(context.project).createAnnotationFromText("@" + NotNull::class.java.name, context)
} }
@@ -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. * 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) } private val _delegate: PsiClass by lazy { DummyJavaPsiFactory.createDummyClass(kotlinOrigin.project) }
override val clsDelegate get() = _delegate
override val originKind get() = LightClassOriginKind.SOURCE override val originKind get() = LightClassOriginKind.SOURCE
override fun getName(): String? = kotlinOrigin.name override fun getName(): String? = kotlinOrigin.name
@@ -92,6 +93,7 @@ class KtFakeLightMethod private constructor(
KotlinLanguage.INSTANCE KotlinLanguage.INSTANCE
), KtLightElement<KtNamedDeclaration, PsiMethod> { ), KtLightElement<KtNamedDeclaration, PsiMethod> {
override val kotlinOrigin get() = ktDeclaration override val kotlinOrigin get() = ktDeclaration
override val clsDelegate get() = myMethod
override fun getName() = ktDeclaration.name ?: "" override fun getName() = ktDeclaration.name ?: ""
@@ -1,10 +1,30 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2017 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.asJava.builder.LightClassData
abstract class KtLazyLightClass(manager: PsiManager) : KtLightClassBase(manager) 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)
}
@@ -1,18 +1,28 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2016 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.asJava.classes
import com.intellij.navigation.ItemPresentationProviders import com.intellij.navigation.ItemPresentationProviders
import com.intellij.psi.PsiElement import com.intellij.psi.*
import com.intellij.psi.PsiField
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiMethod
import com.intellij.psi.impl.PsiClassImplUtil import com.intellij.psi.impl.PsiClassImplUtil
import com.intellij.psi.impl.light.AbstractLightClass import com.intellij.psi.impl.light.AbstractLightClass
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService 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 import org.jetbrains.kotlin.idea.KotlinLanguage
abstract class KtLightClassBase protected constructor( abstract class KtLightClassBase protected constructor(
@@ -24,7 +34,7 @@ abstract class KtLightClassBase protected constructor(
lazyCreator = LightClassesLazyCreator(project) lazyCreator = LightClassesLazyCreator(project)
) )
override fun getDelegate() = invalidAccess() override fun getDelegate() = clsDelegate
override fun getFields() = myInnersCache.fields 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 findMethodsByName(name: String, checkBases: Boolean) = myInnersCache.findMethodsByName(name, checkBases)
override fun findInnerClassByName(name: String, checkBases: Boolean) = myInnersCache.findInnerClassByName(name, checkBases) override fun findInnerClassByName(name: String, checkBases: Boolean) = myInnersCache.findInnerClassByName(name, checkBases)
abstract override fun getOwnFields(): List<PsiField>
abstract override fun getOwnMethods(): List<PsiMethod> override fun getOwnFields(): List<PsiField> = KtLightFieldImpl.fromClsFields(delegate, this)
override fun getOwnMethods(): List<PsiMethod> = KtLightMethodImpl.fromClsMethods(delegate, this)
override fun getText(): String { override fun getText(): String {
val origin = kotlinOrigin val origin = kotlinOrigin
@@ -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<PsiClassType>? = 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<PsiClassType>(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()
}
}
}
@@ -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
}
@@ -9,12 +9,17 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.impl.PsiSuperMethodImplUtil 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.LightEmptyImplementsList
import com.intellij.psi.impl.light.LightModifierList import com.intellij.psi.impl.light.LightModifierList
import com.intellij.psi.search.GlobalSearchScope 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.annotations.NonNls
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport 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.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
@@ -30,11 +35,21 @@ import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.kotlin.psi.psiUtil.siblings import org.jetbrains.kotlin.psi.psiUtil.siblings
import javax.swing.Icon import javax.swing.Icon
abstract class KtLightClassForFacadeImpl constructor( open class KtLightClassForFacadeImpl constructor(
manager: PsiManager, manager: PsiManager,
override val facadeClassFqName: FqName, override val facadeClassFqName: FqName,
myLightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>,
override val files: Collection<KtFile> override val files: Collection<KtFile>
) : KtLazyLightClass(manager), KtLightClassForFacade { ) : KtLazyLightClass(manager), KtLightClassForFacade {
protected open val lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade> = 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 firstFileInFacade by lazyPub { files.iterator().next() }
private val modifierList: PsiModifierList = private val modifierList: PsiModifierList =
@@ -47,7 +62,7 @@ abstract class KtLightClassForFacadeImpl constructor(
FakeFileForLightClass( FakeFileForLightClass(
firstFileInFacade, firstFileInFacade,
lightClass = { this }, lightClass = { this },
stub = { null }, stub = { javaFileStub },
packageFqName = facadeClassFqName.parent() packageFqName = facadeClassFqName.parent()
) )
} }
@@ -153,7 +168,8 @@ abstract class KtLightClassForFacadeImpl constructor(
override fun isValid() = files.all { it.isValid && it.hasTopLevelCallables() && facadeClassFqName == it.javaFileFacadeFqName } 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 override fun getNavigationElement() = firstFileInFacade
@@ -215,15 +231,22 @@ abstract class KtLightClassForFacadeImpl constructor(
companion object { companion object {
fun createForFacadeNoCache(fqName: FqName, searchScope: GlobalSearchScope, project: Project): KtLightClassForFacade? { fun createForFacadeNoCache(fqName: FqName, searchScope: GlobalSearchScope, project: Project): KtLightClassForFacade? {
val sources = KotlinAsJavaSupport.getInstance(project).findFilesForFacade(fqName, searchScope) val sources = KotlinAsJavaSupport.getInstance(project).findFilesForFacade(fqName, searchScope)
.filterNot { it.isCompiled || it.isScript() } .filterNot { it.isCompiled || it.isScript() }
if (sources.isEmpty()) return null 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) val manager = PsiManager.getInstance(project)
return LightClassGenerationSupport.getInstance(project).run { return LightClassGenerationSupport.getInstance(project).run {
if (!canCreateUltraLightClassForFacade(sources)) return null if (canCreateUltraLightClassForFacade(sources)) createUltraLightClassForFacade(manager, fqName, stubValue, sources)
createUltraLightClassForFacade(manager, fqName, sources)
?: error("Unable to create UL class for facade: $fqName for ${sources.joinToString { it.virtualFilePath }}") ?: 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 file: KtFile
): KtLightClassForFacade { ): KtLightClassForFacade {
val project = file.project val project = file.project
val manager = PsiManager.getInstance(project) // TODO: refactor, using cached value doesn't make sense for this case
return LightClassGenerationSupport.getInstance(project).run { val cachedValue = CachedValuesManager.getManager(project).createCachedValue(
createUltraLightClassForFacade(manager, facadeClassFqName, listOf(file)) ?: error { "Unable to create UL class for facade" } LightClassDataProviderForFileFacade.ByFile(project, facadeClassFqName, file), false
} )
return KtLightClassForFacadeImpl(PsiManager.getInstance(project), facadeClassFqName, cachedValue, listOf(file))
} }
} }
} }
@@ -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<PsiTypeParameter> = 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<PsiClass>()
}
private val publicStaticFinal = setOf(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL)
@@ -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<KtNamedDeclaration>()
}
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
}
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.asJava.classes
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.impl.PsiSuperMethodImplUtil 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.LightEmptyImplementsList
import com.intellij.psi.impl.light.LightModifierList import com.intellij.psi.impl.light.LightModifierList
import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValue
@@ -17,9 +18,11 @@ import com.intellij.util.IncorrectOperationException
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport 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.LightClassDataHolder
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForScript import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForScript
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -28,7 +31,17 @@ import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtScript import org.jetbrains.kotlin.psi.KtScript
import javax.swing.Icon 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 modifierList: PsiModifierList = LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC)
private val scriptImplementsList: LightEmptyImplementsList = LightEmptyImplementsList(manager) private val scriptImplementsList: LightEmptyImplementsList = LightEmptyImplementsList(manager)
@@ -43,7 +56,7 @@ abstract class KtLightClassForScript(val script: KtScript) : KtLazyLightClass(sc
FakeFileForLightClass( FakeFileForLightClass(
script.containingKtFile, script.containingKtFile,
lightClass = { this }, lightClass = { this },
stub = { null }, stub = { javaFileStub },
packageFqName = fqName.parent(), 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 // 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 // we can't prohibit creating light classes with null names either since they can contain members
.filter { it.name != null } .filter { it.name != null }
.mapNotNull { KtLightClassForSourceDeclaration.create(it) } .mapNotNull { KtLightClassForSourceDeclaration.create(it, JvmDefaultMode.DEFAULT) }
} }
override fun getInitializers(): Array<PsiClassInitializer> = PsiClassInitializer.EMPTY_ARRAY override fun getInitializers(): Array<PsiClassInitializer> = PsiClassInitializer.EMPTY_ARRAY
@@ -101,7 +114,7 @@ abstract class KtLightClassForScript(val script: KtScript) : KtLazyLightClass(sc
override fun isValid() = script.isValid override fun isValid() = script.isValid
abstract override fun copy(): PsiElement override fun copy() = KtLightClassForScript(script)
override fun getNavigationElement() = script override fun getNavigationElement() = script
@@ -171,21 +184,27 @@ abstract class KtLightClassForScript(val script: KtScript) : KtLazyLightClass(sc
CachedValuesManager.getCachedValue(script) { CachedValuesManager.getCachedValue(script) {
CachedValueProvider.Result CachedValueProvider.Result
.create( .create(
createNoCache(script), createNoCache(script, KtUltraLightSupport.forceUsingOldLightClasses),
KotlinModificationTrackerService.getInstance(script.project).outOfBlockModificationTracker, KotlinModificationTrackerService.getInstance(script.project).outOfBlockModificationTracker,
) )
} }
fun createNoCache(script: KtScript): KtLightClassForScript? { fun createNoCache(script: KtScript, forceUsingOldLightClasses: Boolean): KtLightClassForScript? {
val containingFile = script.containingFile val containingFile = script.containingFile
if (containingFile is KtCodeFragment) { if (containingFile is KtCodeFragment) {
// Avoid building light classes for code fragments // Avoid building light classes for code fragments
return null return null
} }
return LightClassGenerationSupport.getInstance(script.project).run { if (!forceUsingOldLightClasses) {
createUltraLightClassForScript(script) 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<LightClassDataHolder.ForScript> { fun getLightClassCachedValue(script: KtScript): CachedValue<LightClassDataHolder.ForScript> {
@@ -24,17 +24,21 @@ import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiUtilCore import com.intellij.psi.util.PsiUtilCore
import com.intellij.util.IncorrectOperationException import com.intellij.util.IncorrectOperationException
import com.intellij.util.containers.ConcurrentFactoryMap
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult import org.jetbrains.kotlin.asJava.ImpreciseResolveResult
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult.UNSURE import org.jetbrains.kotlin.asJava.ImpreciseResolveResult.UNSURE
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport 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.InvalidLightClassDataHolder
import org.jetbrains.kotlin.asJava.builder.LightClassData
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForClassOrObject import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForClassOrObject
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.asJava.elements.KtLightModifierList import org.jetbrains.kotlin.asJava.elements.KtLightModifierList
import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.config.JvmDefaultMode
@@ -90,8 +94,8 @@ abstract class KtLightClassForSourceDeclaration(
private val _implementsList by lazyPub { createImplementsList() } private val _implementsList by lazyPub { createImplementsList() }
private val _deprecated by lazyPub { classOrObject.isDeprecated() } private val _deprecated by lazyPub { classOrObject.isDeprecated() }
protected abstract fun createExtendsList(): PsiReferenceList? protected open fun createExtendsList(): PsiReferenceList? = super.getExtendsList()?.let { KtLightPsiReferenceList(it, this) }
protected abstract fun createImplementsList(): PsiReferenceList? protected open fun createImplementsList(): PsiReferenceList? = super.getImplementsList()?.let { KtLightPsiReferenceList(it, this) }
override val kotlinOrigin: KtClassOrObject = classOrObject override val kotlinOrigin: KtClassOrObject = classOrObject
@@ -99,6 +103,11 @@ abstract class KtLightClassForSourceDeclaration(
abstract override fun getParent(): PsiElement? abstract override fun getParent(): PsiElement?
abstract override fun getQualifiedName(): String? abstract override fun getQualifiedName(): String?
override val lightClassData: LightClassData
get() = findLightClassData()
protected open fun findLightClassData() = getLightClassDataHolder().findDataForClassOrObject(classOrObject)
private fun getJavaFileStub(): PsiJavaFileStub = getLightClassDataHolder().javaFileStub private fun getJavaFileStub(): PsiJavaFileStub = getLightClassDataHolder().javaFileStub
fun getDescriptor() = fun getDescriptor() =
@@ -115,7 +124,7 @@ abstract class KtLightClassForSourceDeclaration(
private val _containingFile: PsiFile by lazyPub { private val _containingFile: PsiFile by lazyPub {
object : FakeFileForLightClass( object : FakeFileForLightClass(
classOrObject.containingKtFile, classOrObject.containingKtFile,
{ if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject))!! }, { if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject), jvmDefaultMode)!! },
{ getJavaFileStub() } { getJavaFileStub() }
) { ) {
override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset) override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset)
@@ -172,7 +181,7 @@ abstract class KtLightClassForSourceDeclaration(
val containingClassOrObject = (classOrObject.parent as? KtClassBody)?.parent as? KtClassOrObject val containingClassOrObject = (classOrObject.parent as? KtClassBody)?.parent as? KtClassOrObject
if (containingClassOrObject != null) { if (containingClassOrObject != null) {
return create(containingClassOrObject) return create(containingClassOrObject, jvmDefaultMode)
} }
// TODO: should return null // TODO: should return null
@@ -181,7 +190,7 @@ abstract class KtLightClassForSourceDeclaration(
private val _typeParameterList: PsiTypeParameterList by lazyPub { buildTypeParameterList() } 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 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 // we can't prohibit creating light classes with null names either since they can contain members
.filter { it.name != null } .filter { it.name != null }
.mapNotNullTo(result) { .mapNotNullTo(result) {
create(it) if (!forceUsingOldLightClasses)
create(it, jvmDefaultMode)
else
createNoCache(it, jvmDefaultMode, forceUsingOldLightClasses = true)
} }
if (classOrObject.hasInterfaceDefaultImpls && jvmDefaultMode != JvmDefaultMode.ALL_INCOMPATIBLE) { if (classOrObject.hasInterfaceDefaultImpls && jvmDefaultMode != JvmDefaultMode.ALL_INCOMPATIBLE) {
@@ -310,7 +322,7 @@ abstract class KtLightClassForSourceDeclaration(
return result return result
} }
protected abstract fun createClassForInterfaceDefaultImpls(): PsiClass protected open fun createClassForInterfaceDefaultImpls(): PsiClass = KtLightClassForInterfaceDefaultImpls(classOrObject)
override fun getUseScope(): SearchScope = kotlinOrigin.useScope override fun getUseScope(): SearchScope = kotlinOrigin.useScope
@@ -336,15 +348,21 @@ abstract class KtLightClassForSourceDeclaration(
FINAL_KEYWORD to PsiModifier.FINAL FINAL_KEYWORD to PsiModifier.FINAL
) )
fun create(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? = fun create(classOrObject: KtClassOrObject, jvmDefaultMode: JvmDefaultMode): KtLightClassForSourceDeclaration? =
CachedValuesManager.getCachedValue(classOrObject) { CachedValuesManager.getCachedValue(classOrObject) {
CachedValueProvider.Result.create( CachedValueProvider.Result.create(
createNoCache(classOrObject), ConcurrentFactoryMap.createMap { defaultMode: JvmDefaultMode ->
createNoCache(classOrObject, defaultMode, KtUltraLightSupport.forceUsingOldLightClasses)
},
KotlinModificationTrackerService.getInstance(classOrObject.project).outOfBlockModificationTracker, KotlinModificationTrackerService.getInstance(classOrObject.project).outOfBlockModificationTracker,
) )
} }[jvmDefaultMode]
fun createNoCache(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? { fun createNoCache(
classOrObject: KtClassOrObject,
jvmDefaultMode: JvmDefaultMode,
forceUsingOldLightClasses: Boolean
): KtLightClassForSourceDeclaration? {
val containingFile = classOrObject.containingFile val containingFile = classOrObject.containingFile
if (containingFile is KtCodeFragment) { if (containingFile is KtCodeFragment) {
// Avoid building light classes for code fragments // Avoid building light classes for code fragments
@@ -355,8 +373,24 @@ abstract class KtLightClassForSourceDeclaration(
return null return null
} }
return LightClassGenerationSupport.getInstance(classOrObject.project).run { if (!forceUsingOldLightClasses) {
createUltraLightClass(classOrObject) 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) private val LOG = Logger.getInstance(KtLightClassForSourceDeclaration::class.java)
} }
abstract override fun getSupers(): Array<PsiClass> override fun getSupers(): Array<PsiClass> {
if (classOrObject.superTypeListEntries.isEmpty()) {
return getSupertypeByPsi()?.let { arrayOf(it.resolve()!!) } ?: emptyArray()
}
return clsDelegate.supers
}
abstract override fun getSuperTypes(): Array<PsiClassType> override fun getSuperTypes(): Array<PsiClassType> {
if (classOrObject.superTypeListEntries.isEmpty()) {
return getSupertypeByPsi()?.let { arrayOf<PsiClassType>(it) } ?: emptyArray()
}
return clsDelegate.superTypes
}
private fun getSupertypeByPsi(): PsiImmediateClassType? { private fun getSupertypeByPsi(): PsiImmediateClassType? {
return classOrObject.defaultJavaAncestorQualifiedName()?.let { ancestorFqName -> return classOrObject.defaultJavaAncestorQualifiedName()?.let { ancestorFqName ->
@@ -481,7 +525,12 @@ abstract class KtLightClassForSourceDeclaration(
override val originKind: LightClassOriginKind override val originKind: LightClassOriginKind
get() = LightClassOriginKind.SOURCE 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() = fun KtLightClassForSourceDeclaration.isPossiblyAffectedByAllOpen() =
@@ -1,16 +1,26 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2016 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
// light class for top level or (inner/nested of top level) source declarations // 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, classOrObject: KtClassOrObject,
jvmDefaultMode: JvmDefaultMode, jvmDefaultMode: JvmDefaultMode,
forceUsingOldLightClasses: Boolean = false forceUsingOldLightClasses: Boolean = false
@@ -22,5 +32,5 @@ abstract class KtLightClassImpl @JvmOverloads constructor(
else else
containingClass containingClass
abstract override fun copy(): PsiElement override fun copy() = KtLightClassImpl(classOrObject.copy() as KtClassOrObject, jvmDefaultMode)
} }
@@ -59,7 +59,7 @@ class KtUltraLightClassForInterfaceDefaultImpls(classOrObject: KtClassOrObject,
override fun setName(name: String): PsiElement = override fun setName(name: String): PsiElement =
throw IncorrectOperationException("Impossible to rename ${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}") 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<PsiClass>() override fun getOwnInnerClasses() = emptyList<PsiClass>()
override fun getOwnMethods(): List<KtLightMethod> = _ownMethods.value override fun getOwnMethods(): List<KtLightMethod> = _ownMethods.value
@@ -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. * 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 getParent() = containingClass
override fun getTypeParameterList(): PsiTypeParameterList? = null override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getTypeParameters(): Array<PsiTypeParameter> = emptyArray() override fun getTypeParameters(): Array<PsiTypeParameter> = emptyArray()
override fun getContainingClass(): KtLightClassForSourceDeclaration? = create(classOrObject) override fun getContainingClass(): KtLightClassForSourceDeclaration? = create(classOrObject, jvmDefaultMode)
override fun getScope(): PsiElement? = containingClass override fun getScope(): PsiElement? = containingClass
override fun getOwnInnerClasses() = emptyList<PsiClass>() override fun getOwnInnerClasses() = emptyList<PsiClass>()
override fun getOwnFields(): List<KtLightField> = emptyList() override fun getOwnFields(): List<KtLightField> = emptyList()
@@ -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. * 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 <T : Any> get(initializer: () -> T, dependencies: List<Any>) = object : Lazy<T> { override fun <T : Any> get(initializer: () -> T, dependencies: List<Any>) = object : Lazy<T> {
private val lock = ReentrantLock() private val lock = ReentrantLock()
private val holder = lazyPub { private val holder = lazyPub {
PsiCachedValueImpl(PsiManager.getInstance(project)) { PsiCachedValueImpl(PsiManager.getInstance(project),
val v = initializer() CachedValueProvider<T> {
CachedValueProvider.Result.create(v, dependencies) val v = initializer()
} CachedValueProvider.Result.create(v, dependencies)
})
} }
private fun computeValue(): T = holder.value.value ?: error("holder has not null in initializer") private fun computeValue(): T = holder.value.value ?: error("holder has not null in initializer")
@@ -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. * 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 package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.PsiElement import com.intellij.psi.*
import com.intellij.psi.PsiManager import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiModifierList
import com.intellij.psi.impl.light.LightModifierList 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.asJava.elements.*
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil.findAnnotationEntryOnFileNoResolve import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil.findAnnotationEntryOnFileNoResolve
import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.KotlinLanguage
@@ -25,9 +26,21 @@ import org.jetbrains.kotlin.psi.psiUtil.isPrivate
class KtUltraLightClassForFacade( class KtUltraLightClassForFacade(
manager: PsiManager, manager: PsiManager,
facadeClassFqName: FqName, facadeClassFqName: FqName,
lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>,
files: Collection<KtFile>, files: Collection<KtFile>,
private val filesWithSupports: Collection<Pair<KtFile, KtUltraLightSupport>> private val filesWithSupports: Collection<Pair<KtFile, KtUltraLightSupport>>
) : KtLightClassForFacadeImpl(manager, facadeClassFqName, files) { ) : KtLightClassForFacadeImpl(manager, facadeClassFqName, lightClassDataCache, files) {
override fun getDelegate(): PsiClass = invalidAccess()
override val lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade> 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 { private val _modifierList: PsiModifierList by lazyPub {
if (isMultiFileClass) if (isMultiFileClass)
LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL) LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL)
@@ -46,7 +59,8 @@ class KtUltraLightClassForFacade(
name = entry.shortName?.identifier, name = entry.shortName?.identifier,
lazyQualifiedName = { entry.analyzeAnnotation()?.fqName?.asString() }, lazyQualifiedName = { entry.analyzeAnnotation()?.fqName?.asString() },
kotlinOrigin = entry, kotlinOrigin = entry,
parent = _modifierList parent = _modifierList,
lazyClsDelegate = null
) )
} }
} }
@@ -87,7 +101,6 @@ class KtUltraLightClassForFacade(
ktFunction = declaration, ktFunction = declaration,
forceStatic = true forceStatic = true
) )
is KtProperty -> { is KtProperty -> {
if (!declaration.isPrivate() || declaration.accessors.isNotEmpty()) { if (!declaration.isPrivate() || declaration.accessors.isNotEmpty()) {
creator.propertyAccessors( creator.propertyAccessors(
@@ -98,7 +111,6 @@ class KtUltraLightClassForFacade(
) )
} else emptyList() } else emptyList()
} }
else -> emptyList() else -> emptyList()
} }
result.addAll(methods) result.addAll(methods)
@@ -136,5 +148,5 @@ class KtUltraLightClassForFacade(
override fun getOwnMethods() = _ownMethods override fun getOwnMethods() = _ownMethods
override fun copy(): KtLightClassForFacade = override fun copy(): KtLightClassForFacade =
KtUltraLightClassForFacade(manager, facadeClassFqName, files, filesWithSupports) KtUltraLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files, filesWithSupports)
} }
@@ -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. * 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, private val ultraLightSupport: KtUltraLightSupport,
parent: PsiElement, parent: PsiElement,
private val nameReferenceElementProvider: (() -> PsiJavaCodeReferenceElement?)? = null, private val nameReferenceElementProvider: (() -> PsiJavaCodeReferenceElement?)? = null,
) : KtLightAbstractAnnotation(parent) { ) : KtLightAbstractAnnotation(parent, computeDelegate = null) {
override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = nameReferenceElementProvider?.invoke() override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = nameReferenceElementProvider?.invoke()
private val parameterList = ParameterListImpl() private val parameterList = ParameterListImpl()
@@ -15,6 +15,7 @@ import com.intellij.psi.impl.light.LightMethodBuilder
import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager 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.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.KtUltraLightModifierList 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 isFinal(isFinalByPsi: Boolean) = isFinalByPsi
override fun findLightClassData(): LightClassData = invalidAccess()
override fun getDelegate(): PsiClass = invalidAccess()
private val _modifierList: PsiModifierList? by lazyPub { private val _modifierList: PsiModifierList? by lazyPub {
KtUltraLightClassModifierList(this, support) { computeModifiers() } KtUltraLightClassModifierList(this, support) { computeModifiers() }
} }
@@ -295,7 +300,6 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
when (declaration) { when (declaration) {
is KtNamedFunction -> is KtNamedFunction ->
if (isJvmStatic(declaration)) result.addAll(membersBuilder.createMethods(declaration, forceStatic = true)) if (isJvmStatic(declaration)) result.addAll(membersBuilder.createMethods(declaration, forceStatic = true))
is KtProperty -> result.addAll( is KtProperty -> result.addAll(
membersBuilder.propertyAccessors( membersBuilder.propertyAccessors(
declaration, declaration,
@@ -401,7 +405,6 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
declarationOriginKindForOrigin = JvmDeclarationOriginKind.DELEGATION declarationOriginKindForOrigin = JvmDeclarationOriginKind.DELEGATION
) )
} }
is FunctionDescriptor -> result.add( is FunctionDescriptor -> result.add(
createGeneratedMethodFromDescriptor( createGeneratedMethodFromDescriptor(
descriptor = delegate, descriptor = delegate,
@@ -483,7 +486,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
val containingBody = classOrObject.parent as? KtClassBody val containingBody = classOrObject.parent as? KtClassBody
val containingClass = containingBody?.parent as? KtClassOrObject val containingClass = containingBody?.parent as? KtClassOrObject
containingClass?.let { return create(it) } containingClass?.let { return create(it, jvmDefaultMode) }
val containingBlock = classOrObject.parent as? KtBlockExpression val containingBlock = classOrObject.parent as? KtBlockExpression
val containingScript = containingBlock?.parent as? KtScript val containingScript = containingBlock?.parent as? KtScript
@@ -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. * 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.*
import com.intellij.psi.impl.InheritanceImplUtil 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.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.resolve.DescriptorUtils
open class KtUltraLightClassForAnonymousDeclaration(classOrObject: KtClassOrObject, support: KtUltraLightSupport) : open class KtUltraLightClassForAnonymousDeclaration(classOrObject: KtClassOrObject, support: KtUltraLightSupport) :
KtUltraLightClassForLocalDeclaration(classOrObject, support), PsiAnonymousClass { KtUltraLightClassForLocalDeclaration(classOrObject, support), PsiAnonymousClass {
@@ -18,6 +18,7 @@ open class KtUltraLightClassForAnonymousDeclaration(classOrObject: KtClassOrObje
JavaPsiFacade.getElementFactory(classOrObject.project).createReferenceElementByType(baseClassType) JavaPsiFacade.getElementFactory(classOrObject.project).createReferenceElementByType(baseClassType)
private val _baseClassType by lazyPub { private val _baseClassType by lazyPub {
val firstSupertypeFQName = getFirstSupertypeFQNameForAnonymousDeclaration() val firstSupertypeFQName = getFirstSupertypeFQNameForAnonymousDeclaration()
if (firstSupertypeFQName == CommonClassNames.JAVA_LANG_OBJECT) { if (firstSupertypeFQName == CommonClassNames.JAVA_LANG_OBJECT) {
@@ -64,21 +65,3 @@ open class KtUltraLightClassForAnonymousDeclaration(classOrObject: KtClassOrObje
override fun copy() = KtUltraLightClassForAnonymousDeclaration(classOrObject, support) 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()
}
@@ -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. * 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 package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod import org.jetbrains.kotlin.asJava.classes.KtLightClassForLocalDeclaration.Companion.getParentForLocalDeclaration
import com.intellij.psi.impl.light.LightClass import org.jetbrains.kotlin.psi.KtClassOrObject
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
open class KtUltraLightClassForLocalDeclaration( open class KtUltraLightClassForLocalDeclaration(
classOrObject: KtClassOrObject, classOrObject: KtClassOrObject,
@@ -29,72 +22,3 @@ open class KtUltraLightClassForLocalDeclaration(
override fun getParent() = _parent 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<KtNamedDeclaration>()
}
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
}
@@ -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. * 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 package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiModifier import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiType import com.intellij.psi.PsiType
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
import com.intellij.psi.impl.light.LightMethodBuilder import com.intellij.psi.impl.light.LightMethodBuilder
import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.CachedValuesManager
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService 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.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
@@ -22,6 +26,15 @@ class KtUltraLightClassForScript(
script: KtScript, script: KtScript,
private val support: KtUltraLightSupport, private val support: KtUltraLightSupport,
) : KtLightClassForScript(script) { ) : 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 { private val membersBuilder by lazyPub {
UltraLightMembersCreator( UltraLightMembersCreator(
containingClass = this, containingClass = this,
@@ -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. * 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 kotlinOrigin = declaration
override val clsDelegate: PsiField get() = invalidAccess()
override val lightMemberOrigin = LightMemberOriginForDeclaration(declaration, JvmDeclarationOriginKind.OTHER) override val lightMemberOrigin = LightMemberOriginForDeclaration(declaration, JvmDeclarationOriginKind.OTHER)
override fun setName(@NonNls name: String): PsiElement { override fun setName(@NonNls name: String): PsiElement {
@@ -10,14 +10,13 @@ import com.intellij.psi.impl.PsiImplUtil
import com.intellij.psi.impl.PsiSuperMethodImplUtil import com.intellij.psi.impl.PsiSuperMethodImplUtil
import com.intellij.psi.impl.light.LightMethodBuilder import com.intellij.psi.impl.light.LightMethodBuilder
import com.intellij.psi.impl.light.LightTypeParameterListBuilder import com.intellij.psi.impl.light.LightTypeParameterListBuilder
import com.intellij.psi.javadoc.PsiDocComment
import com.intellij.psi.util.MethodSignature import com.intellij.psi.util.MethodSignature
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod 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.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.builder.MemberIndex import org.jetbrains.kotlin.asJava.builder.MemberIndex
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl
import org.jetbrains.kotlin.asJava.elements.KtUltraLightModifierList
import org.jetbrains.kotlin.codegen.FunctionCodegen import org.jetbrains.kotlin.codegen.FunctionCodegen
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor 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.KtFunction
import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
import org.jetbrains.kotlin.psi.psiUtil.hasBody
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.types.RawType 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_GETTER = 1
const val METHOD_INDEX_FOR_SETTER = 2 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_FOR_SCRIPT_MAIN = 6
const val METHOD_INDEX_BASE = 7 const val METHOD_INDEX_BASE = 7
private class KtUltraLightMethodModifierList(
support: KtUltraLightSupport,
owner: KtUltraLightMethod,
val delegate: PsiMethod,
) : KtUltraLightModifierList<KtUltraLightMethod>(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<KtLightClassForSourceDeclaration>()?.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 abstract class KtUltraLightMethod(
internal val delegate: PsiMethod, internal val delegate: PsiMethod,
lightMemberOrigin: LightMemberOriginForDeclaration?, lightMemberOrigin: LightMemberOrigin?,
protected val support: KtUltraLightSupport, protected val support: KtUltraLightSupport,
containingClass: KtLightClass, containingClass: KtLightClass,
private val methodIndex: Int private val methodIndex: Int
) : KtLightMethodImpl( ) : KtLightMethodImpl(
{ delegate },
lightMemberOrigin, lightMemberOrigin,
containingClass containingClass
), KtUltraLightElementWithNullabilityAnnotation<KtDeclaration, PsiMethod> { ), KtUltraLightElementWithNullabilityAnnotation<KtDeclaration, PsiMethod> {
private class KtUltraLightThrowsReferenceListBuilder(private val parentMethod: PsiMethod) : private class KtUltraLightThrowsReferenceListBuilder(private val parentMethod: PsiMethod) :
KotlinLightReferenceListBuilder(parentMethod.manager, parentMethod.language, PsiReferenceList.Role.THROWS_LIST) { KotlinLightReferenceListBuilder(parentMethod.manager, parentMethod.language, PsiReferenceList.Role.THROWS_LIST) {
override fun getParent(): PsiMethod = parentMethod override fun getParent() = parentMethod
override fun getContainingFile(): PsiFile? = parentMethod.containingFile override fun getContainingFile() = parentMethod.containingFile
} }
protected fun computeThrowsList(methodDescriptor: FunctionDescriptor?): PsiReferenceList { 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) // While here we only set return type for LightMethodBuilder (see org.jetbrains.kotlin.asJava.classes.KtUltraLightClass.asJavaMethod)
override fun getReturnTypeElement(): PsiTypeElement? = null override fun getReturnTypeElement(): PsiTypeElement? = null
override fun getReturnType(): PsiType? = delegate.returnType override fun getReturnType(): PsiType? = clsDelegate.returnType
override fun buildParametersForList(): List<PsiParameter> = delegate.parameterList.parameters.toList() override fun buildParametersForList(): List<PsiParameter> = clsDelegate.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<PsiAnnotationMethod>()?.defaultValue
override fun getName(): String = delegate.name
// should be in super // should be in super
override fun isVarArgs() = PsiImplUtil.isVarArgs(this) 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 hashCode(): Int = super.hashCode().times(31).plus(methodIndex.hashCode())
override fun isDeprecated(): Boolean = _deprecated override fun isDeprecated(): Boolean = _deprecated
override fun getDocComment(): PsiDocComment? = delegate.docComment
override fun isConstructor(): Boolean = delegate.isConstructor
} }
internal class KtUltraLightMethodForSourceDeclaration( internal class KtUltraLightMethodForSourceDeclaration(
delegate: PsiMethod, delegate: PsiMethod,
lightMemberOrigin: LightMemberOriginForDeclaration?, lightMemberOrigin: LightMemberOrigin?,
support: KtUltraLightSupport, support: KtUltraLightSupport,
containingClass: KtLightClass, containingClass: KtLightClass,
private val forceToSkipNullabilityAnnotation: Boolean = false, private val forceToSkipNullabilityAnnotation: Boolean = false,
@@ -243,7 +204,7 @@ internal class KtUltraLightMethodForSourceDeclaration(
internal class KtUltraLightMethodForDescriptor( internal class KtUltraLightMethodForDescriptor(
methodDescriptor: FunctionDescriptor, methodDescriptor: FunctionDescriptor,
delegate: LightMethodBuilder, delegate: LightMethodBuilder,
lightMemberOrigin: LightMemberOriginForDeclaration?, lightMemberOrigin: LightMemberOrigin?,
support: KtUltraLightSupport, support: KtUltraLightSupport,
containingClass: KtUltraLightClass containingClass: KtUltraLightClass
) : KtUltraLightMethod( ) : KtUltraLightMethod(
@@ -44,6 +44,7 @@ internal class KtUltraLightSuspendContinuationParameter(
override val psiTypeForNullabilityAnnotation: PsiType? get() = psiType override val psiTypeForNullabilityAnnotation: PsiType? get() = psiType
override val kotlinOrigin: KtParameter? = null override val kotlinOrigin: KtParameter? = null
override val clsDelegate: PsiParameter get() = invalidAccess()
private val ktType: KotlinType? private val ktType: KotlinType?
get() { get() {
@@ -93,6 +94,8 @@ internal abstract class KtUltraLightParameter(
override fun isEquivalentTo(another: PsiElement?): Boolean = kotlinOrigin == another override fun isEquivalentTo(another: PsiElement?): Boolean = kotlinOrigin == another
override val clsDelegate: PsiParameter get() = invalidAccess()
private val lightModifierList by lazyPub { KtLightSimpleModifierList(this, emptySet()) } private val lightModifierList by lazyPub { KtLightSimpleModifierList(this, emptySet()) }
override fun getModifierList(): PsiModifierList = lightModifierList override fun getModifierList(): PsiModifierList = lightModifierList
@@ -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. * 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 package org.jetbrains.kotlin.asJava.classes
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
interface KtUltraLightSupport { interface KtUltraLightSupport {
@@ -20,4 +21,12 @@ interface KtUltraLightSupport {
val languageVersionSettings: LanguageVersionSettings val languageVersionSettings: LanguageVersionSettings
fun possiblyHasAlias(file: KtFile, shortName: Name): Boolean 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
}
} }
@@ -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. * 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<KtAnnotationEntry>.toLightAnnotations(
name = entry.shortName?.identifier, name = entry.shortName?.identifier,
lazyQualifiedName = { entry.analyzeAnnotation()?.fqName?.asString() }, lazyQualifiedName = { entry.analyzeAnnotation()?.fqName?.asString() },
kotlinOrigin = entry, kotlinOrigin = entry,
parent = parent parent = parent,
lazyClsDelegate = null
) )
} }
@@ -1,6 +1,17 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2016 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.asJava.elements
@@ -43,7 +54,7 @@ open class FakeFileForLightClass(
override fun getPackageName() = packageFqName.asString() override fun getPackageName() = packageFqName.asString()
private fun createFakeJavaFileStub(): PsiJavaFileStub { private fun createFakeJavaFileStub(): PsiJavaFileStub {
val javaFileStub = PsiJavaFileStubImpl(packageFqName.asString(), /* compiled = */true) val javaFileStub = PsiJavaFileStubImpl(packageFqName.asString(), /*compiled = */true)
javaFileStub.psiFactory = ClsStubPsiFactory.INSTANCE javaFileStub.psiFactory = ClsStubPsiFactory.INSTANCE
javaFileStub.psi = this javaFileStub.psi = this
return javaFileStub return javaFileStub
@@ -1,6 +1,17 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2016 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.asJava.elements
@@ -24,6 +35,8 @@ interface KtLightElement<out T : KtElement, out D : PsiElement> : PsiElement {
* Probably, it's a bit dirty solution. But, for now it's not clear how to make it better * Probably, it's a bit dirty solution. But, for now it's not clear how to make it better
*/ */
val givenAnnotations: List<KtLightAbstractAnnotation>? get() = null val givenAnnotations: List<KtLightAbstractAnnotation>? get() = null
val clsDelegate: D
} }
interface KtLightDeclaration<out T : KtDeclaration, out D : PsiElement> : KtLightElement<T, D>, PsiNamedElement interface KtLightDeclaration<out T : KtDeclaration, out D : PsiElement> : KtLightElement<T, D>, PsiNamedElement
@@ -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<D : PsiField>(
override val lightMemberOrigin: LightMemberOrigin?,
computeRealDelegate: () -> D,
containingClass: KtLightClass,
dummyDelegate: PsiField?
) : KtLightMemberImpl<PsiField>(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<PsiVariable>?): 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<PsiEnumConstant>(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<PsiField>(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)
}
}
@@ -1,12 +1,25 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2016 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.asJava.elements
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiCompiledElement
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.impl.light.LightIdentifier import com.intellij.psi.impl.light.LightIdentifier
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
@@ -22,7 +35,7 @@ abstract class KtLightIdentifierBase(
override fun getTextOffset(): Int = origin?.textOffset ?: -1 override fun getTextOffset(): Int = origin?.textOffset ?: -1
} }
open class KtLightIdentifier( open class KtLightIdentifierWithOrigin(
lightOwner: PsiElement, lightOwner: PsiElement,
private val ktDeclaration: KtDeclaration? private val ktDeclaration: KtDeclaration?
) : KtLightIdentifierBase(lightOwner, ktDeclaration?.name) { ) : KtLightIdentifierBase(lightOwner, ktDeclaration?.name) {
@@ -32,9 +45,16 @@ open class KtLightIdentifier(
is KtPrimaryConstructor -> ktDeclaration.getConstructorKeyword() is KtPrimaryConstructor -> ktDeclaration.getConstructorKeyword()
?: ktDeclaration.valueParameterList ?: ktDeclaration.valueParameterList
?: ktDeclaration.containingClassOrObject?.nameIdentifier ?: ktDeclaration.containingClassOrObject?.nameIdentifier
is KtPropertyAccessor -> ktDeclaration.namePlaceholder is KtPropertyAccessor -> ktDeclaration.namePlaceholder
is KtNamedDeclaration -> ktDeclaration.nameIdentifier is KtNamedDeclaration -> ktDeclaration.nameIdentifier
else -> null else -> null
} }
} }
class KtLightIdentifier(
private val lightOwner: PsiElement,
ktDeclaration: KtDeclaration?
) : KtLightIdentifierWithOrigin(lightOwner, ktDeclaration), PsiCompiledElement {
override fun getMirror() = ((lightOwner as? KtLightElement<*, *>)?.clsDelegate as? PsiNameIdentifierOwner)?.nameIdentifier
}
@@ -1,44 +1,69 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2017 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.asJava.elements
import com.intellij.psi.PsiElement import com.intellij.openapi.util.UserDataHolder
import com.intellij.psi.PsiIdentifier import com.intellij.psi.*
import com.intellij.psi.PsiMember import com.intellij.psi.impl.compiled.ClsRepositoryPsiElement
import com.intellij.psi.PsiModifierList import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory.ORIGIN
import com.intellij.psi.javadoc.PsiDocComment 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.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.classes.KtLightClass 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.asJava.classes.lazyPub
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedDeclaration import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.psiUtil.hasBody
abstract class KtLightMemberImpl<out D : PsiMember>( abstract class KtLightMemberImpl<out D : PsiMember>(
override val lightMemberOrigin: LightMemberOriginForDeclaration?, computeRealDelegate: () -> D,
override val lightMemberOrigin: LightMemberOrigin?,
private val containingClass: KtLightClass, private val containingClass: KtLightClass,
private val dummyDelegate: D?
) : KtLightElementBase(containingClass), PsiMember, KtLightMember<D> { ) : KtLightElementBase(containingClass), PsiMember, KtLightMember<D> {
override val clsDelegate by lazyPub(computeRealDelegate)
private val lightIdentifier by lazyPub { KtLightIdentifier(this, kotlinOrigin as? KtNamedDeclaration) } 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 toString(): String = "${this::class.java.simpleName}:$name"
override fun getContainingClass() = containingClass override fun getContainingClass() = containingClass
abstract override fun getName(): String override fun getName(): String = dummyDelegate?.name ?: clsDelegate.name!!
override fun getNameIdentifier(): PsiIdentifier = lightIdentifier override fun getNameIdentifier(): PsiIdentifier = lightIdentifier
override val kotlinOrigin: KtDeclaration? get() = lightMemberOrigin?.originalElement 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 { override fun isValid(): Boolean {
return parent.isValid && lightMemberOrigin?.isValid() != false return parent.isValid && lightMemberOrigin?.isValid() != false
@@ -50,3 +75,46 @@ abstract class KtLightMemberImpl<out D : PsiMember>(
another is KtLightMember<*> && lightMemberOrigin?.isEquivalentTo(another.lightMemberOrigin) == true 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<LightElementOrigin>(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<KtLightMember<*>>(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)
}
@@ -7,38 +7,66 @@ package org.jetbrains.kotlin.asJava.elements
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
import com.intellij.psi.scope.PsiScopeProcessor import com.intellij.psi.scope.PsiScopeProcessor
import com.intellij.psi.util.MethodSignature import com.intellij.psi.util.MethodSignature
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod import com.intellij.psi.util.MethodSignatureBackedByPsiMethod
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.asJava.* 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.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.builder.MemberIndex 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.KtLightClass
import org.jetbrains.kotlin.asJava.classes.cannotModify import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
abstract class KtLightMethodImpl protected constructor( open class KtLightMethodImpl protected constructor(
lightMemberOrigin: LightMemberOriginForDeclaration?, computeRealDelegate: () -> PsiMethod,
lightMemberOrigin: LightMemberOrigin?,
containingClass: KtLightClass, containingClass: KtLightClass,
) : KtLightMemberImpl<PsiMethod>(lightMemberOrigin, containingClass), KtLightMethod { private val dummyDelegate: PsiMethod? = null
) : KtLightMemberImpl<PsiMethod>(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<Boolean>() private val calculatingReturnType = ThreadLocal<Boolean>()
private val paramsList: PsiParameterList by lazyPub { private val paramsList: PsiParameterList by lazyPub {
val parameters = buildParametersForList() KtLightParameterList(this, dummyDelegate?.parameterList?.parametersCount ?: clsDelegate.parameterList.parametersCount) {
KtLightParameterList(this, parameters.size) { buildParametersForList()
parameters
} }
} }
protected abstract fun buildParametersForList(): List<PsiParameter> protected open fun buildParametersForList(): List<PsiParameter> {
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() } 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) { override fun accept(visitor: PsiElementVisitor) {
if (visitor is JavaElementVisitor) { if (visitor is JavaElementVisitor) {
@@ -76,7 +104,12 @@ abstract class KtLightMethodImpl protected constructor(
} ?: cannotModify() } ?: 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 override fun getParameterList() = paramsList
@@ -87,7 +120,16 @@ abstract class KtLightMethodImpl protected constructor(
override fun hasTypeParameters() = typeParameters.isNotEmpty() 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( override fun processDeclarations(
processor: PsiScopeProcessor, processor: PsiScopeProcessor,
@@ -98,7 +140,8 @@ abstract class KtLightMethodImpl protected constructor(
return typeParameters.all { processor.execute(it, state) } 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: /* comparing origin and member index should be enough to determine equality:
for compiled elements origin contains delegate for compiled elements origin contains delegate
@@ -115,9 +158,11 @@ abstract class KtLightMethodImpl protected constructor(
.times(31).plus(containingClass.hashCode()) .times(31).plus(containingClass.hashCode())
.times(31).plus(memberIndex.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? { override fun getReturnType(): PsiType? {
calculatingReturnType.set(true) calculatingReturnType.set(true)
@@ -146,28 +191,67 @@ abstract class KtLightMethodImpl protected constructor(
return super.getTextRange() 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<KtProperty>()!!,
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<KtLightMethodImpl> = buildList {
for (method in delegateClass.methods) {
if (isSyntheticValuesOrValueOfMethod(method)) continue
this += create(method, getOrigin(method), containingClass)
}
}
abstract override fun findSuperMethodSignaturesIncludingStatic(checkAccess: Boolean): List<MethodSignatureBackedByPsiMethod> 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 override fun getBody() = null
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
abstract override fun findDeepestSuperMethod(): PsiMethod? override fun findDeepestSuperMethod() = clsDelegate.findDeepestSuperMethod()
abstract override fun findDeepestSuperMethods(): Array<out PsiMethod> override fun findDeepestSuperMethods() = clsDelegate.findDeepestSuperMethods()
abstract override fun findSuperMethods(): Array<out PsiMethod> override fun findSuperMethods() = clsDelegate.findSuperMethods()
abstract override fun findSuperMethods(checkAccess: Boolean): Array<out PsiMethod> override fun findSuperMethods(checkAccess: Boolean) = clsDelegate.findSuperMethods(checkAccess)
abstract override fun findSuperMethods(parentClass: PsiClass?): Array<out PsiMethod> override fun findSuperMethods(parentClass: PsiClass?) = clsDelegate.findSuperMethods(parentClass)
} }
fun KtLightMethod.isTraitFakeOverride(): Boolean { fun KtLightMethod.isTraitFakeOverride(): Boolean {
@@ -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. * 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<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>( abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(
protected val owner: T protected val owner: T
) : KtLightElementBase(owner), PsiModifierList, KtLightElement<KtModifierList, PsiModifierList> { ) : KtLightElementBase(owner), PsiModifierList, KtLightElement<KtModifierList, PsiModifierList> {
override val clsDelegate by lazyPub { owner.clsDelegate.modifierList!! }
private val _annotations by lazyPub { private val _annotations by lazyPub {
val annotations = computeAnnotations() val annotations = computeAnnotations()
annotationsFilter?.let(annotations::filter) ?: annotations annotationsFilter?.let(annotations::filter) ?: annotations
@@ -38,13 +39,9 @@ abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, P
override fun hasExplicitModifier(name: String) = hasModifierProperty(name) override fun hasExplicitModifier(name: String) = hasModifierProperty(name)
private fun throwInvalidOperation(): Nothing = throw IncorrectOperationException() override fun setModifierProperty(name: String, value: Boolean) = clsDelegate.setModifierProperty(name, value)
override fun checkSetModifierProperty(name: String, value: Boolean) = clsDelegate.checkSetModifierProperty(name, value)
override fun setModifierProperty(name: String, value: Boolean): Unit = throwInvalidOperation() override fun addAnnotation(qualifiedName: String) = clsDelegate.addAnnotation(qualifiedName)
override fun checkSetModifierProperty(name: String, value: Boolean): Unit = throwInvalidOperation()
override fun addAnnotation(qualifiedName: String): PsiAnnotation = throwInvalidOperation()
override fun getApplicableAnnotations(): Array<out PsiAnnotation> = annotations override fun getApplicableAnnotations(): Array<out PsiAnnotation> = annotations
@@ -58,7 +55,14 @@ abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, P
override fun toString() = "Light modifier list of $owner" override fun toString() = "Light modifier list of $owner"
open fun nonSourceAnnotationsForAnnotationType(sourceAnnotations: List<PsiAnnotation>): List<KtLightAbstractAnnotation> = emptyList() protected open fun nonSourceAnnotationsForAnnotationType(sourceAnnotations: List<PsiAnnotation>): List<KtLightAbstractAnnotation> {
val annotations = parent.clsDelegate.modifierList?.annotations
if (annotations.isNullOrEmpty()) return emptyList()
return annotations.map { KtLightNonSourceAnnotation(this, it) }
}
private fun computeAnnotations(): List<KtLightAbstractAnnotation> { private fun computeAnnotations(): List<KtLightAbstractAnnotation> {
val annotationsForEntries = owner.givenAnnotations ?: lightAnnotationsForEntries(this) val annotationsForEntries = owner.givenAnnotations ?: lightAnnotationsForEntries(this)
@@ -134,7 +138,21 @@ abstract class KtUltraLightModifierList<out T : KtLightElement<KtModifierListOwn
abstract class KtUltraLightModifierListBase<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>( abstract class KtUltraLightModifierListBase<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(
owner: T owner: T
) : KtLightModifierList<T>(owner) ) : KtLightModifierList<T>(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<PsiAnnotation>): List<KtLightAbstractAnnotation> =
emptyList()
}
class KtLightSimpleModifierList( class KtLightSimpleModifierList(
owner: KtLightElement<KtModifierListOwner, PsiModifierListOwner>, private val modifiers: Set<String> owner: KtLightElement<KtModifierListOwner, PsiModifierListOwner>, private val modifiers: Set<String>
@@ -163,12 +181,23 @@ private fun lightAnnotationsForEntries(lightModifierList: KtLightModifierList<*>
} }
.groupBy({ it.first }) { it.second } .groupBy({ it.first }) { it.second }
.flatMap { (fqName, entries) -> .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( KtLightAnnotationForSourceEntry(
name = entry.shortName?.identifier, name = entry.shortName?.identifier,
lazyQualifiedName = { fqName }, lazyQualifiedName = { fqName },
kotlinOrigin = entry, kotlinOrigin = entry,
parent = lightModifierList parent = lightModifierList,
lazyClsDelegate = lazyClsDelegate
) )
} }
} }
@@ -201,8 +230,8 @@ private fun getAnnotationDescriptors(
val annotatedDescriptor = when { val annotatedDescriptor = when {
descriptor is ClassDescriptor && annotatedLightElement is KtLightMethod && annotatedLightElement.isConstructor -> descriptor is ClassDescriptor && annotatedLightElement is KtLightMethod && annotatedLightElement.isConstructor ->
descriptor.unsubstitutedPrimaryConstructor descriptor.unsubstitutedPrimaryConstructor
descriptor !is PropertyDescriptor -> descriptor descriptor !is PropertyDescriptor -> descriptor
annotatedLightElement is KtLightFieldImpl.KtLightEnumConstant -> descriptor
annotatedLightElement is KtLightField -> descriptor.backingField annotatedLightElement is KtLightField -> descriptor.backingField
annotatedLightElement !is KtLightMethod -> descriptor annotatedLightElement !is KtLightMethod -> descriptor
annotatedLightElement.isGetter -> descriptor.getter annotatedLightElement.isGetter -> descriptor.getter
@@ -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<KtParameter, PsiParameter>, 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<Boolean> {
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
}
@@ -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. * 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( class KtLightPsiJavaCodeReferenceElement(
private val ktElement: PsiElement, private val ktElement: PsiElement,
reference: () -> PsiReference?, reference: () -> PsiReference?,
clsDelegateProvider: () -> PsiJavaCodeReferenceElement?,
private val customReferenceName: String? = null, private val customReferenceName: String? = null,
) : ) :
PsiElement by ktElement, PsiElement by ktElement,
PsiReference by LazyPsiReferenceDelegate(ktElement, reference), PsiReference by LazyPsiReferenceDelegate(ktElement, reference),
PsiJavaCodeReferenceElement { 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<PsiType> = emptyArray() override fun getReferenceNameElement(): PsiElement? = delegate?.referenceNameElement
override fun getReferenceName(): String? = customReferenceName override fun getTypeParameters(): Array<PsiType> = 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<JavaResolveResult> = emptyArray() override fun processVariants(processor: PsiScopeProcessor) {
delegate?.processVariants(processor)
}
override fun getQualifiedName(): String? = null override fun multiResolve(incompleteCode: Boolean): Array<JavaResolveResult> = 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( private class LazyPsiReferenceDelegate(
@@ -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<KtSuperTypeList, PsiReferenceList>, PsiReferenceList by clsDelegate {
inner class KtLightSuperTypeReference(
override val clsDelegate: PsiJavaCodeReferenceElement
) : KtLightElement<KtSuperTypeListEntry, PsiJavaCodeReferenceElement>, 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
}
}
@@ -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<KtTypeParameter, PsiTypeParameter> {
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<KtLightAbstractAnnotation> getGivenAnnotations() {
return null;
}
}
@@ -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. * 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( KtLightPsiJavaCodeReferenceElement(
ktElement = it, ktElement = it,
reference = { null }, reference = { null },
clsDelegateProvider = { null },
customReferenceName = JAVA_LANG_ANNOTATION_REPEATABLE_SHORT_NAME, customReferenceName = JAVA_LANG_ANNOTATION_REPEATABLE_SHORT_NAME,
) )
} }
@@ -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. * 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 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.*
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable import org.jetbrains.annotations.Nullable
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.cannotModify import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub 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.psi.psiUtil.hasSuspendModifier
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils 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.components.isVararg
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument 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.descriptorUtil.declaresOrInheritsDefaultValue
import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.KotlinType 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.isUnit
import org.jetbrains.kotlin.types.typeUtil.nullability 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<PsiAnnotation>?) :
KtLightElementBase(parent), PsiAnnotation, KtLightElement<KtCallElement, PsiAnnotation> { KtLightElementBase(parent), PsiAnnotation, KtLightElement<KtCallElement, PsiAnnotation> {
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 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 open fun fqNameMatches(fqName: String): Boolean = qualifiedName == fqName
} }
@@ -56,8 +67,9 @@ class KtLightAnnotationForSourceEntry(
private val name: String?, private val name: String?,
private val lazyQualifiedName: () -> String?, private val lazyQualifiedName: () -> String?,
override val kotlinOrigin: KtCallElement, override val kotlinOrigin: KtCallElement,
parent: PsiElement parent: PsiElement,
) : KtLightAbstractAnnotation(parent) { private val lazyClsDelegate: Lazy<PsiAnnotation>?
) : KtLightAbstractAnnotation(parent, lazyClsDelegate) {
private val _qualifiedName: String? by lazyPub { lazyQualifiedName() } private val _qualifiedName: String? by lazyPub { lazyQualifiedName() }
@@ -89,7 +101,6 @@ class KtLightAnnotationForSourceEntry(
when (val psiElement = callEntry.key.source.getPsi()) { when (val psiElement = callEntry.key.source.getPsi()) {
is KtParameter -> is KtParameter ->
return psiElement.defaultValue?.let { convertToLightAnnotationMemberValue(this, it) } return psiElement.defaultValue?.let { convertToLightAnnotationMemberValue(this, it) }
is PsiAnnotationMethod -> is PsiAnnotationMethod ->
return psiElement.defaultValue return psiElement.defaultValue
} }
@@ -105,6 +116,7 @@ class KtLightAnnotationForSourceEntry(
(kotlinOrigin as? KtAnnotationEntry)?.typeReference?.reference (kotlinOrigin as? KtAnnotationEntry)?.typeReference?.reference
?: (kotlinOrigin.calleeExpression?.nameReference)?.references?.firstOrNull() ?: (kotlinOrigin.calleeExpression?.nameReference)?.references?.firstOrNull()
}, },
{ lazyClsDelegate?.value?.nameReferenceElement },
if (qualifiedName == CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE) JAVA_LANG_ANNOTATION_REPEATABLE_SHORT_NAME else null, if (qualifiedName == CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE) JAVA_LANG_ANNOTATION_REPEATABLE_SHORT_NAME else null,
) )
@@ -220,13 +232,40 @@ class KtLightAnnotationForSourceEntry(
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify() override fun <T : PsiAnnotationMemberValue?> 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 <T : PsiAnnotationMemberValue?> 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 <T : PsiAnnotationMemberValue?> 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 { class KtLightEmptyAnnotationParameterList(parent: PsiElement) : KtLightElementBase(parent), PsiAnnotationParameterList {
override val kotlinOrigin: KtElement? get() = null override val kotlinOrigin: KtElement? get() = null
override fun getAttributes(): Array<PsiNameValuePair> = emptyArray() override fun getAttributes(): Array<PsiNameValuePair> = emptyArray()
} }
open class KtLightNullabilityAnnotation<D : KtLightElement<*, PsiModifierListOwner>>(val member: D, parent: PsiElement) : open class KtLightNullabilityAnnotation<D : KtLightElement<*, PsiModifierListOwner>>(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 { override fun fqNameMatches(fqName: String): Boolean {
if (!isNullabilityAnnotation(fqName)) return false if (!isNullabilityAnnotation(fqName)) return false
@@ -241,7 +280,7 @@ open class KtLightNullabilityAnnotation<D : KtLightElement<*, PsiModifierListOwn
private val _qualifiedName: String? by lazyPub { private val _qualifiedName: String? by lazyPub {
val annotatedElement = member.takeIf(::isFromSources)?.kotlinOrigin val annotatedElement = member.takeIf(::isFromSources)?.kotlinOrigin
?: // it is out of our hands ?: // it is out of our hands
return@lazyPub null return@lazyPub getClsNullabilityAnnotation(member)?.qualifiedName
if (!fastCheckIsNullabilityApplied(member)) return@lazyPub null if (!fastCheckIsNullabilityApplied(member)) return@lazyPub null
@@ -323,6 +362,14 @@ open class KtLightNullabilityAnnotation<D : KtLightElement<*, PsiModifierListOwn
override fun findDeclaredAttributeValue(attributeName: String?): PsiAnnotationMemberValue? = null override fun findDeclaredAttributeValue(attributeName: String?): PsiAnnotationMemberValue? = null
} }
private fun getClsNullabilityAnnotation(member: KtLightElement<*, PsiModifierListOwner>): 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 internal fun isNullabilityAnnotation(qualifiedName: String?) = qualifiedName in backendNullabilityAnnotations
private val backendNullabilityAnnotations = arrayOf(Nullable::class.java.name, NotNull::class.java.name) private val backendNullabilityAnnotations = arrayOf(Nullable::class.java.name, NotNull::class.java.name)
@@ -341,11 +388,9 @@ fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExp
is KtClassLiteralExpression -> { is KtClassLiteralExpression -> {
return KtLightPsiClassObjectAccessExpression(argument, lightParent) return KtLightPsiClassObjectAccessExpression(argument, lightParent)
} }
is KtStringTemplateExpression, is KtConstantExpression -> { is KtStringTemplateExpression, is KtConstantExpression -> {
return KtLightPsiLiteral(argument, lightParent) return KtLightPsiLiteral(argument, lightParent)
} }
is KtCallExpression -> { is KtCallExpression -> {
val arguments = argument.valueArguments val arguments = argument.valueArguments
val annotationName = argument.calleeExpression?.let { getAnnotationName(it) } val annotationName = argument.calleeExpression?.let { getAnnotationName(it) }
@@ -354,7 +399,8 @@ fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExp
name = annotationName, name = annotationName,
lazyQualifiedName = { annotationName }, lazyQualifiedName = { annotationName },
kotlinOrigin = argument, kotlinOrigin = argument,
parent = lightParent parent = lightParent,
lazyClsDelegate = null
) )
} }
val resolvedCall = argument.getResolvedCall() val resolvedCall = argument.getResolvedCall()
@@ -368,7 +414,6 @@ fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExp
} }
} }
} }
is KtCollectionLiteralExpression -> { is KtCollectionLiteralExpression -> {
val arguments = argument.getInnerExpressions() val arguments = argument.getInnerExpressions()
if (arguments.isNotEmpty()) if (arguments.isNotEmpty())
@@ -406,3 +451,17 @@ private fun getAnnotationName(callee: KtExpression): String? {
} }
return null return null
} }
@get:TestOnly
var accessAnnotationsClsDelegateIsAllowed = false
@TestOnly
fun <T> withAllowedAnnotationsClsDelegate(body: () -> T): T {
val prev = accessAnnotationsClsDelegateIsAllowed
try {
accessAnnotationsClsDelegateIsAllowed = true
return body()
} finally {
accessAnnotationsClsDelegateIsAllowed = prev
}
}
@@ -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. * 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 { 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 if (!elementIsApplicable) return false
val annotatedElement = lightElement.kotlinOrigin ?: return true val annotatedElement = lightElement.kotlinOrigin ?: return true
@@ -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<File> 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<ComparisonFailure> 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());
}
}
@@ -1,6 +1,17 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2017 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. *
* 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 package org.jetbrains.kotlin.asJava
@@ -13,8 +24,8 @@ import java.io.File
class KotlinLightClassTest : KotlinAsJavaTestBase() { class KotlinLightClassTest : KotlinAsJavaTestBase() {
override fun getKotlinSourceRoots(): List<File> = listOf( override fun getKotlinSourceRoots(): List<File> = listOf(
File("compiler/testData/asJava/lightClassStructure/ClassObject.kt"), File("compiler/testData/asJava/lightClassStructure/ClassObject.kt"),
File("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.kt") File("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.kt")
) )
private val key = Key.create<String>("testKey") private val key = Key.create<String>("testKey")