FIR IDE: move light classes to separate module

This commit is contained in:
Ilya Kirillov
2021-08-21 12:23:25 +03:00
parent abe2311372
commit c17a4a5a3b
66 changed files with 286 additions and 237 deletions
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.providers
import com.intellij.openapi.components.ServiceManager
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.psi.KtElement
public abstract class KotlinModuleInfoProvider {
public abstract fun getModuleInfo(element: KtElement): ModuleInfo
}
public fun KtElement.getModuleInfo(): ModuleInfo =
ServiceManager.getService(project, KotlinModuleInfoProvider::class.java).getModuleInfo(this)
@@ -0,0 +1,19 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
implementation(project(":compiler:psi"))
implementation(project(":compiler:frontend.java"))
implementation(project(":core:compiler.common"))
implementation(project(":compiler:light-classes"))
implementation(project(":analysis:analysis-api-providers"))
implementation(project(":idea-frontend-api"))
implementation(intellijCoreDep()) { includeJars("intellij-core", rootProject = rootProject) }
}
sourceSets {
"main" { projectDefault() }
"test" { none() }
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiElement
import com.intellij.psi.ResolveState
import com.intellij.psi.scope.PsiScopeProcessor
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.light.classes.symbol.classes.getOrCreateFirLightClass
import org.jetbrains.kotlin.psi.KtClassOrObject
class FirFakeFileImpl(private val classOrObject: KtClassOrObject, ktClass: KtLightClass) : FakeFileForLightClass(
classOrObject.containingKtFile,
{ if (classOrObject.isTopLevel()) ktClass else getOrCreateFirLightClass(getOutermostClassOrObject(classOrObject))!! },
{ null }
) {
override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset)
override fun processDeclarations(
processor: PsiScopeProcessor,
state: ResolveState,
lastParent: PsiElement?,
place: PsiElement
): Boolean {
if (!super.processDeclarations(processor, state, lastParent, place)) return false
// We have to explicitly process package declarations if current file belongs to default package
// so that Java resolve can find classes located in that package
val packageName = packageName
if (packageName.isNotEmpty()) return true
val aPackage = JavaPsiFacade.getInstance(classOrObject.project).findPackage(packageName)
if (aPackage != null && !aPackage.processDeclarations(processor, state, null, place)) return false
return true
}
}
@@ -0,0 +1,47 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiCompiledElement
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.impl.light.LightIdentifier
import org.jetbrains.kotlin.asJava.elements.PsiElementWithOrigin
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedSymbol
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
open class FirLightIdentifier(
private val lightOwner: PsiElement,
private val firSymbol: KtSymbol
) : LightIdentifier(
lightOwner.manager,
(firSymbol as? KtNamedSymbol)?.name?.identifierOrNullIfSpecial
), PsiCompiledElement, PsiElementWithOrigin<PsiElement> {
override val origin: PsiElement?
get() = when (val ktDeclaration = firSymbol.psi) {
is KtSecondaryConstructor -> ktDeclaration.getConstructorKeyword()
is KtPrimaryConstructor -> ktDeclaration.getConstructorKeyword()
?: ktDeclaration.valueParameterList
?: ktDeclaration.containingClassOrObject?.nameIdentifier
is KtPropertyAccessor -> ktDeclaration.namePlaceholder
is KtNamedDeclaration -> ktDeclaration.nameIdentifier
else -> null
}
override fun getMirror(): PsiElement? = null
override fun isPhysical(): Boolean = true
override fun getParent(): PsiElement = lightOwner
override fun getContainingFile(): PsiFile = lightOwner.containingFile
override fun getTextRange(): TextRange = origin?.textRange ?: TextRange.EMPTY_RANGE
override fun getTextOffset(): Int = origin?.textOffset ?: -1
}
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiIdentifier
import com.intellij.psi.PsiMember
import com.intellij.psi.PsiMethod
import com.intellij.psi.javadoc.PsiDocComment
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
import org.jetbrains.kotlin.asJava.elements.KtLightMember
import org.jetbrains.kotlin.psi.KtDeclaration
internal abstract class FirLightMemberImpl<T : PsiMember>(
override val lightMemberOrigin: LightMemberOrigin?,
private val containingClass: KtLightClass,
) : KtLightElementBase(containingClass), PsiMember, KtLightMember<T> {
override val clsDelegate: T
get() = invalidAccess()
override fun hasModifierProperty(name: String): Boolean = modifierList?.hasModifierProperty(name) ?: false
override fun toString(): String = "${this::class.java.simpleName}:$name"
override fun getContainingClass() = containingClass
abstract override fun getNameIdentifier(): PsiIdentifier?
override val kotlinOrigin: KtDeclaration? get() = lightMemberOrigin?.originalElement
override fun getDocComment(): PsiDocComment? = null //TODO()
abstract override fun isDeprecated(): Boolean
abstract override fun getName(): String
override fun isValid(): Boolean =
parent.isValid && lightMemberOrigin?.isValid() != false
override fun isEquivalentTo(another: PsiElement?): Boolean =
basicIsEquivalentTo(this, another as? PsiMethod)
abstract override fun hashCode(): Int
abstract override fun equals(other: Any?): Boolean
}
@@ -0,0 +1,74 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightElement
import com.intellij.psi.scope.PsiScopeProcessor
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithTypeParameters
import org.jetbrains.kotlin.light.classes.symbol.elements.FirLightTypeParameter
internal class FirLightTypeParameterListForSymbol(
internal val owner: PsiTypeParameterListOwner,
private val symbolWithTypeParameterList: KtSymbolWithTypeParameters,
private val innerShiftCount: Int
) : LightElement(owner.manager, KotlinLanguage.INSTANCE), PsiTypeParameterList {
override fun accept(visitor: PsiElementVisitor) {
if (visitor is JavaElementVisitor) {
visitor.visitTypeParameterList(this)
} else {
visitor.visitElement(this)
}
}
override fun processDeclarations(
processor: PsiScopeProcessor,
state: ResolveState,
lastParent: PsiElement?,
place: PsiElement
): Boolean {
return typeParameters.all { processor.execute(it, state) }
}
private val _typeParameters: Array<PsiTypeParameter> by lazyPub {
symbolWithTypeParameterList.typeParameters.let { list ->
list.take(list.count() - innerShiftCount).mapIndexed { index, parameter ->
FirLightTypeParameter(
parent = this@FirLightTypeParameterListForSymbol,
index = index,
typeParameterSymbol = parameter
)
}.toTypedArray()
}
}
override fun getTypeParameters(): Array<PsiTypeParameter> = _typeParameters
override fun getTypeParameterIndex(typeParameter: PsiTypeParameter?): Int =
_typeParameters.indexOf(typeParameter)
override fun toString(): String = "FirLightTypeParameterList"
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightTypeParameterListForSymbol && symbolWithTypeParameterList == other.symbolWithTypeParameterList)
override fun hashCode(): Int = symbolWithTypeParameterList.hashCode()
override fun isEquivalentTo(another: PsiElement?): Boolean =
basicIsEquivalentTo(this, another)
override fun getParent(): PsiElement = owner
override fun getContainingFile(): PsiFile = parent.containingFile
override fun getText(): String? = ""
override fun getTextOffset(): Int = 0
override fun getStartOffsetInParent(): Int = 0
}
@@ -0,0 +1,124 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
import org.jetbrains.kotlin.analysis.providers.createPackageProvider
import org.jetbrains.kotlin.analysis.providers.getModuleInfo
import org.jetbrains.kotlin.analyzer.LibraryModuleSourceInfoBase
import org.jetbrains.kotlin.analyzer.NonSourceModuleInfoBase
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.light.classes.symbol.classes.getOrCreateFirLightClass
import org.jetbrains.kotlin.light.classes.symbol.classes.getOrCreateFirLightFacade
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.parentOrNull
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
class IDEKotlinAsJavaFirSupport(private val project: Project) : KotlinAsJavaSupport() {
override fun findClassOrObjectDeclarationsInPackage(
packageFqName: FqName,
searchScope: GlobalSearchScope
): Collection<KtClassOrObject> = project.createDeclarationProvider(searchScope).run {
getClassNamesInPackage(packageFqName).flatMap {
getClassesByClassId(ClassId.topLevel(packageFqName.child(it)))
}
}
@OptIn(ExperimentalStdlibApi::class)
override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile> =
buildSet {
addAll(project.createDeclarationProvider(searchScope).getFacadeFilesInPackage(fqName))
findClassOrObjectDeclarationsInPackage(fqName, searchScope).mapTo(this) {
it.containingKtFile
}
}
private fun FqName.toClassIdSequence(): Sequence<ClassId> {
var currentName = shortNameOrSpecial()
if (currentName.isSpecial) return emptySequence()
var currentParent = parentOrNull() ?: return emptySequence()
var currentRelativeName = currentName.asString()
return sequence {
while (true) {
yield(ClassId(currentParent, FqName(currentRelativeName), false))
currentName = currentParent.shortNameOrSpecial()
if (currentName.isSpecial) break
currentParent = currentParent.parentOrNull() ?: break
currentRelativeName = "${currentName.asString()}.$currentRelativeName"
}
}
}
override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject> =
fqName.toClassIdSequence().flatMap {
project.createDeclarationProvider(searchScope).getClassesByClassId(it)
}.filter {
//TODO Do not return LC came from LibrarySources
when (it.getModuleInfo()) {
is LibraryModuleSourceInfoBase -> it.containingKtFile.isCompiled
is NonSourceModuleInfoBase -> false
else -> true
}
}.toSet()
override fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean =
project.createPackageProvider(scope).isPackageExists(fqName)
override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection<FqName> =
project.createPackageProvider(scope)
.getKotlinSubPackageFqNames(fqn)
.map { fqn.child(it) }
override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? =
getOrCreateFirLightClass(classOrObject)
override fun getLightClassForScript(script: KtScript): KtLightClass =
error("Should not be called")
override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> =
//TODO Split by modules
findFilesForFacade(facadeFqName, scope).ifNotEmpty {
listOfNotNull(getOrCreateFirLightFacade(this.toList(), facadeFqName))
} ?: emptyList()
override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> =
error("Should not be called")
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> =
emptyList() //TODO Implement if necessary for fir
override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> =
project.createDeclarationProvider(scope)
.getFacadeFilesInPackage(packageFqName)
.groupBy { it.javaFileFacadeFqName }
.mapNotNull { getOrCreateFirLightFacade(it.value, it.key) }
override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String> =
project.createDeclarationProvider(scope)
.getFacadeFilesInPackage(packageFqName)
.mapTo(mutableSetOf()) { it.javaFileFacadeFqName.shortName().asString() }
override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtFile> =
project.createDeclarationProvider(scope)
.findFilesForFacade(facadeFqName)
override fun getFakeLightClass(classOrObject: KtClassOrObject): KtFakeLightClass =
KtFirBasedFakeLightClass(classOrObject)
override fun createFacadeForSyntheticFile(facadeClassFqName: FqName, file: KtFile): PsiClass =
TODO("Not implemented")
}
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightIdentifier
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotationCall
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedConstantValue
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
import org.jetbrains.kotlin.psi.KtElement
internal class FirAnnotationParameterList(
parent: FirLightAbstractAnnotation,
private val annotationCall: KtAnnotationCall,
) : KtLightElementBase(parent), PsiAnnotationParameterList {
private val _attributes: Array<PsiNameValuePair> by lazyPub {
annotationCall.arguments.map {
FirNameValuePairForAnnotationArgument(it, this)
}.toTypedArray()
}
override fun getAttributes(): Array<PsiNameValuePair> = _attributes
override val kotlinOrigin: KtElement? get() = null
//TODO: EQ GHC EQIV
}
private class FirNameValuePairForAnnotationArgument(
private val constantValue: KtNamedConstantValue,
parent: PsiElement
) : KtLightElementBase(parent), PsiNameValuePair {
override val kotlinOrigin: KtElement? get() = null
private val _value by lazyPub {
(constantValue.expression as? KtSimpleConstantValue<*>)?.createPsiLiteral(this)
}
override fun setValue(p0: PsiAnnotationMemberValue) = cannotModify()
private val _nameIdentifier: PsiIdentifier by lazyPub {
LightIdentifier(parent.manager, constantValue.name)
}
override fun getNameIdentifier(): PsiIdentifier = _nameIdentifier
override fun getValue(): PsiAnnotationMemberValue? = _value
override fun getLiteralValue(): String? = (value as? PsiLiteralExpression)?.value?.toString()
override fun getName(): String = constantValue.name
}
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
import org.jetbrains.kotlin.psi.*
internal abstract class FirLightAbstractAnnotation(parent: PsiElement) :
KtLightElementBase(parent), PsiAnnotation, KtLightElement<KtCallElement, PsiAnnotation> {
override val clsDelegate: PsiAnnotation
get() = invalidAccess()
override fun getOwner() = parent as? PsiAnnotationOwner
private val KtExpression.nameReference: KtNameReferenceExpression?
get() = when (this) {
is KtConstructorCalleeExpression -> constructorReferenceExpression as? KtNameReferenceExpression
else -> this as? KtNameReferenceExpression
}
private val _nameReferenceElement: PsiJavaCodeReferenceElement by lazyPub {
val ktElement = kotlinOrigin?.navigationElement ?: this
val reference = (kotlinOrigin as? KtAnnotationEntry)?.typeReference?.reference
?: (kotlinOrigin?.calleeExpression?.nameReference)?.references?.firstOrNull()
if (reference != null) FirLightPsiJavaCodeReferenceElementWithReference(ktElement, reference)
else FirLightPsiJavaCodeReferenceElementWithNoReference(ktElement)
}
override fun getNameReferenceElement(): PsiJavaCodeReferenceElement = _nameReferenceElement
private class FirAnnotationParameterList(parent: PsiAnnotation) : KtLightElementBase(parent), PsiAnnotationParameterList {
override val kotlinOrigin: KtElement? = null
override fun getAttributes(): Array<PsiNameValuePair> = emptyArray() //TODO()
}
private val annotationParameterList: PsiAnnotationParameterList = FirAnnotationParameterList(this)
override fun getParameterList(): PsiAnnotationParameterList = annotationParameterList
override fun delete() {
kotlinOrigin?.delete()
}
override fun toString() = "@$qualifiedName"
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify()
}
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiAnnotationMemberValue
import com.intellij.psi.PsiAnnotationParameterList
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.PsiImplUtil
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotationCall
import org.jetbrains.kotlin.psi.KtCallElement
internal class FirLightAnnotationForAnnotationCall(
private val annotationCall: KtAnnotationCall,
parent: PsiElement,
) : FirLightAbstractAnnotation(parent) {
override fun findAttributeValue(attributeName: String?): PsiAnnotationMemberValue? =
PsiImplUtil.findAttributeValue(this, attributeName)
override fun findDeclaredAttributeValue(attributeName: String?) =
PsiImplUtil.findDeclaredAttributeValue(this, attributeName)
private val _parameterList: PsiAnnotationParameterList by lazyPub {
FirAnnotationParameterList(this@FirLightAnnotationForAnnotationCall, annotationCall)
}
override fun getParameterList(): PsiAnnotationParameterList = _parameterList
override val kotlinOrigin: KtCallElement? = annotationCall.psi
override fun getQualifiedName(): String? = annotationCall.classId?.asSingleFqName()?.asString()
override fun getName(): String? = qualifiedName
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightAnnotationForAnnotationCall &&
kotlinOrigin == other.kotlinOrigin &&
annotationCall == other.annotationCall)
override fun hashCode(): Int = kotlinOrigin.hashCode()
override fun isEquivalentTo(another: PsiElement?): Boolean =
basicIsEquivalentTo(this, another as? PsiAnnotation)
}
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.PsiAnnotationMemberValue
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtCallElement
internal class FirLightSimpleAnnotation(
private val fqName: String?,
parent: PsiElement
) : FirLightAbstractAnnotation(parent) {
override val kotlinOrigin: KtCallElement? = null
override fun getQualifiedName(): String? = fqName
override fun getName(): String? = fqName
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightSimpleAnnotation && fqName == other.fqName && parent == other.parent)
override fun hashCode(): Int = fqName.hashCode()
override fun findAttributeValue(attributeName: String?): PsiAnnotationMemberValue? = null
override fun findDeclaredAttributeValue(attributeName: String?): PsiAnnotationMemberValue? = null
}
@@ -0,0 +1,112 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.kotlin.descriptors.DeprecationLevelValue
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFileSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
import org.jetbrains.kotlin.name.StandardClassIds
internal fun KtAnnotatedSymbol.hasJvmSyntheticAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean =
hasAnnotation("kotlin/jvm/JvmSynthetic", annotationUseSiteTarget)
internal fun KtFileSymbol.hasJvmMultifileClassAnnotation(): Boolean =
hasAnnotation("kotlin/jvm/JvmMultifileClass", AnnotationUseSiteTarget.FILE)
internal fun KtAnnotatedSymbol.getJvmNameFromAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): String? {
val annotation = annotations.firstOrNull {
val siteTarget = it.useSiteTarget
(siteTarget == null || siteTarget == annotationUseSiteTarget) &&
it.classId?.asString() == "kotlin/jvm/JvmName"
}
return annotation?.let {
(it.arguments.firstOrNull()?.expression as? KtSimpleConstantValue<*>)?.value as? String
}
}
internal fun isHiddenByDeprecation(
project: Project,
symbol: KtAnnotatedSymbol,
annotationUseSiteTarget: AnnotationUseSiteTarget? = null
): Boolean {
return project.analyzeWithSymbolAsContext(symbol) {
symbol.deprecationStatus?.level == DeprecationLevelValue.HIDDEN
}
}
internal fun KtAnnotatedSymbol.isHiddenOrSynthetic(project: Project, annotationUseSiteTarget: AnnotationUseSiteTarget? = null) =
isHiddenByDeprecation(project, this, annotationUseSiteTarget) || hasJvmSyntheticAnnotation(annotationUseSiteTarget)
internal fun KtAnnotatedSymbol.hasJvmFieldAnnotation(): Boolean =
hasAnnotation("kotlin/jvm/JvmField", null)
internal fun KtAnnotatedSymbol.hasPublishedApiAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean =
hasAnnotation("kotlin/PublishedApi", annotationUseSiteTarget)
internal fun KtAnnotatedSymbol.hasDeprecatedAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean =
hasAnnotation("kotlin/Deprecated", annotationUseSiteTarget)
internal fun KtAnnotatedSymbol.hasJvmOverloadsAnnotation(): Boolean =
hasAnnotation("kotlin/jvm/JvmOverloads", null)
internal fun KtAnnotatedSymbol.hasJvmStaticAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean =
hasAnnotation("kotlin/jvm/JvmStatic", annotationUseSiteTarget)
internal fun KtAnnotatedSymbol.hasInlineOnlyAnnotation(): Boolean =
hasAnnotation("kotlin/internal/InlineOnly", null)
internal fun KtAnnotatedSymbol.hasAnnotation(classIdString: String, annotationUseSiteTarget: AnnotationUseSiteTarget?): Boolean =
annotations.any {
it.useSiteTarget == annotationUseSiteTarget && it.classId?.asString() == classIdString
}
internal fun KtAnnotatedSymbol.computeAnnotations(
parent: PsiElement,
nullability: NullabilityType,
annotationUseSiteTarget: AnnotationUseSiteTarget?,
includeAnnotationsWithoutSite: Boolean = true
): List<PsiAnnotation> {
if (nullability == NullabilityType.Unknown && annotations.isEmpty()) return emptyList()
val nullabilityAnnotation = when (nullability) {
NullabilityType.NotNull -> NotNull::class.java
NullabilityType.Nullable -> Nullable::class.java
else -> null
}?.let {
FirLightSimpleAnnotation(it.name, parent)
}
if (annotations.isEmpty()) {
return if (nullabilityAnnotation != null) listOf(nullabilityAnnotation) else emptyList()
}
val result = mutableListOf<PsiAnnotation>()
for (annotation in annotations) {
val siteTarget = annotation.useSiteTarget
if ((includeAnnotationsWithoutSite && siteTarget == null) ||
siteTarget == annotationUseSiteTarget
) {
result.add(FirLightAnnotationForAnnotationCall(annotation, parent))
}
}
if (nullabilityAnnotation != null) {
result.add(nullabilityAnnotation)
}
return result
}
@@ -0,0 +1,67 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReferenceList
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.isPrivateOrPrivateToThis
import org.jetbrains.kotlin.light.classes.symbol.FirLightClassForClassOrObjectSymbol
import org.jetbrains.kotlin.light.classes.symbol.analyzeWithSymbolAsContext
internal class FirLightAnnotationClassSymbol(
private val classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : FirLightInterfaceOrAnnotationClassSymbol(classOrObjectSymbol, manager) {
init {
require(classOrObjectSymbol.classKind == KtClassKind.ANNOTATION_CLASS)
}
override fun isAnnotationType(): Boolean = true
private val _ownFields: List<KtLightField> by lazyPub {
mutableListOf<KtLightField>().also {
addCompanionObjectFieldIfNeeded(it)
}
}
override fun getOwnFields(): List<KtLightField> = _ownFields
private val _ownMethods: List<KtLightMethod> by lazyPub {
val result = mutableListOf<KtLightMethod>()
analyzeWithSymbolAsContext(classOrObjectSymbol) {
val visibleDeclarations = classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
.filterNot { it is KtFunctionSymbol && it.visibility.isPrivateOrPrivateToThis() }
.filterNot { it is KtConstructorSymbol }
createMethods(visibleDeclarations, result)
}
result
}
override fun getOwnMethods(): List<PsiMethod> = _ownMethods
override fun getExtendsList(): PsiReferenceList? = null
override fun equals(other: Any?): Boolean =
other is FirLightAnnotationClassSymbol && classOrObjectSymbol == other.classOrObjectSymbol
override fun hashCode(): Int = classOrObjectSymbol.hashCode()
override fun isValid(): Boolean = super.isValid() && classOrObjectSymbol.isValid()
override fun copy(): FirLightClassForClassOrObjectSymbol = FirLightAnnotationClassSymbol(classOrObjectSymbol, manager)
}
@@ -0,0 +1,153 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.*
import com.intellij.psi.impl.InheritanceImplUtil
import com.intellij.psi.impl.PsiClassImplUtil
import com.intellij.psi.search.SearchScope
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.StubElement
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtAnonymousObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.light.classes.symbol.*
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.debugText.getDebugText
import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
internal class FirLightAnonymousClassForSymbol(
private val anonymousObjectSymbol: KtAnonymousObjectSymbol,
manager: PsiManager
) : FirLightClassBase(manager),
StubBasedPsiElement<KotlinClassOrObjectStub<out KtClassOrObject>>, PsiAnonymousClass {
private val _baseClassType: PsiClassType by lazyPub {
extendsListTypes.firstOrNull()
?: implementsListTypes.firstOrNull()
?: PsiType.getJavaLangObject(manager, resolveScope)
}
override fun getBaseClassReference(): PsiJavaCodeReferenceElement =
JavaPsiFacade.getElementFactory(manager.project).createReferenceElementByType(baseClassType)
override fun getBaseClassType(): PsiClassType = _baseClassType
private val _extendsList by lazyPub { createInheritanceList(forExtendsList = true, anonymousObjectSymbol.superTypes) }
private val _implementsList by lazyPub { createInheritanceList(forExtendsList = false, anonymousObjectSymbol.superTypes) }
override fun getExtendsList(): PsiReferenceList? = _extendsList
override fun getImplementsList(): PsiReferenceList? = _implementsList
override fun getOwnFields(): List<KtLightField> = _ownFields
override fun getOwnMethods(): List<PsiMethod> = _ownMethods
private val _ownMethods: List<KtLightMethod> by lazyPub {
val result = mutableListOf<KtLightMethod>()
analyzeWithSymbolAsContext(anonymousObjectSymbol) {
val declaredMemberScope = anonymousObjectSymbol.getDeclaredMemberScope()
createMethods(declaredMemberScope.getCallableSymbols(), result)
createConstructors(declaredMemberScope.getConstructors(), result)
}
result
}
private val _ownFields: List<KtLightField> by lazyPub {
val result = mutableListOf<KtLightField>()
val nameGenerator = FirLightField.FieldNameGenerator()
analyzeWithSymbolAsContext(anonymousObjectSymbol) {
anonymousObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtPropertySymbol>()
.forEach { propertySymbol ->
createField(
propertySymbol,
nameGenerator,
isTopLevel = false,
forceStatic = false,
takePropertyVisibility = propertySymbol.hasJvmFieldAnnotation(),
result
)
}
}
result
}
private val _ownInnerClasses: List<FirLightClassBase> by lazyPub {
anonymousObjectSymbol.createInnerClasses(manager)
}
override fun getOwnInnerClasses(): List<PsiClass> = _ownInnerClasses
override fun getScope(): PsiElement? = parent
override fun getInterfaces(): Array<PsiClass> = PsiClassImplUtil.getInterfaces(this)
override fun getSuperClass(): PsiClass? = PsiClassImplUtil.getSuperClass(this)
override fun getSupers(): Array<PsiClass> = PsiClassImplUtil.getSupers(this)
override fun getSuperTypes(): Array<PsiClassType> = PsiClassImplUtil.getSuperTypes(this)
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean =
InheritanceImplUtil.isInheritor(this, baseClass, checkDeep)
override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean =
baseClass?.let { InheritanceImplUtil.isInheritorDeep(this, it, classToByPass) } ?: false
override val kotlinOrigin: KtClassOrObject? = anonymousObjectSymbol.psi as? KtClassOrObject
override val originKind: LightClassOriginKind
get() = LightClassOriginKind.SOURCE
override fun getArgumentList(): PsiExpressionList? = null
override fun isInQualifiedNew(): Boolean = false
override fun getName(): String? = null
override fun getNameIdentifier(): KtLightIdentifier? = null
override fun getModifierList(): PsiModifierList? = null
override fun hasModifierProperty(name: String): Boolean = name == PsiModifier.FINAL
override fun getContainingClass(): PsiClass? = null
override fun isDeprecated(): Boolean = false //TODO
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
override fun isInterface() = false
override fun isAnnotationType() = false
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getQualifiedName(): String? = null
override fun isEnum() = false
override fun getUseScope(): SearchScope = kotlinOrigin?.useScope ?: TODO()
override fun getElementType(): IStubElementType<out StubElement<*>, *>? = kotlinOrigin?.elementType
override fun getStub(): KotlinClassOrObjectStub<out KtClassOrObject>? = kotlinOrigin?.stub
override fun isEquivalentTo(another: PsiElement?): Boolean = equals(another) //TODO
//TODO Make containing file not null for symbol without psi
private val _containingFile: PsiFile? by lazyPub {
val kotlinOrigin = kotlinOrigin ?: return@lazyPub null
FirFakeFileImpl(kotlinOrigin, this)
}
override fun getContainingFile(): PsiFile? = _containingFile
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightAnonymousClassForSymbol && anonymousObjectSymbol == other.anonymousObjectSymbol)
override fun hashCode(): Int = anonymousObjectSymbol.hashCode()
override fun copy() =
FirLightAnonymousClassForSymbol(anonymousObjectSymbol, manager)
override fun isValid(): Boolean = super.isValid() && anonymousObjectSymbol.isValid()
override fun toString() =
"${this::class.java.simpleName}:${kotlinOrigin?.getDebugText()}"
}
@@ -0,0 +1,172 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.navigation.ItemPresentation
import com.intellij.navigation.ItemPresentationProviders
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Pair
import com.intellij.psi.*
import com.intellij.psi.impl.PsiCachedValueImpl
import com.intellij.psi.impl.PsiClassImplUtil
import com.intellij.psi.impl.PsiImplUtil
import com.intellij.psi.impl.PsiSuperMethodImplUtil
import com.intellij.psi.impl.light.LightElement
import com.intellij.psi.impl.source.PsiExtensibleClass
import com.intellij.psi.javadoc.PsiDocComment
import com.intellij.psi.scope.PsiScopeProcessor
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.PsiUtil
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
import org.jetbrains.kotlin.asJava.classes.KotlinClassInnerStuffCache
import org.jetbrains.kotlin.asJava.classes.KotlinClassInnerStuffCache.Companion.processDeclarationsInEnum
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.frontend.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.idea.frontend.api.tokens.hackyAllowRunningOnEdt
import javax.swing.Icon
abstract class FirLightClassBase protected constructor(manager: PsiManager) : LightElement(manager, KotlinLanguage.INSTANCE), PsiClass,
KtLightClass, PsiExtensibleClass {
override val clsDelegate: PsiClass
get() = invalidAccess()
private class FirLightClassesLazyCreator(private val project: Project) : KotlinClassInnerStuffCache.LazyCreator() {
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
override fun <T : Any> get(initializer: () -> T, dependencies: List<Any>): Lazy<T> = lazyPub {
PsiCachedValueImpl(PsiManager.getInstance(project)) {
CachedValueProvider.Result.create(hackyAllowRunningOnEdt(initializer), dependencies)
}.value ?: error("initializer cannot return null")
}
}
private val myInnersCache = KotlinClassInnerStuffCache(
myClass = this@FirLightClassBase,
externalDependencies = listOf(manager.project.createProjectWideOutOfBlockModificationTracker()),
lazyCreator = FirLightClassesLazyCreator(project)
)
override fun getFields(): Array<PsiField> = myInnersCache.fields
override fun getMethods(): Array<PsiMethod> = myInnersCache.methods
override fun getConstructors(): Array<PsiMethod> = myInnersCache.constructors
override fun getInnerClasses(): Array<out PsiClass> = myInnersCache.innerClasses
override fun getAllFields(): Array<PsiField> = PsiClassImplUtil.getAllFields(this)
override fun getAllMethods(): Array<PsiMethod> = PsiClassImplUtil.getAllMethods(this)
override fun getAllInnerClasses(): Array<PsiClass> = PsiClassImplUtil.getAllInnerClasses(this)
override fun findFieldByName(name: String, checkBases: Boolean) =
myInnersCache.findFieldByName(name, checkBases)
override fun findMethodsByName(name: String, checkBases: Boolean): Array<PsiMethod> =
myInnersCache.findMethodsByName(name, checkBases)
override fun findInnerClassByName(name: String, checkBases: Boolean): PsiClass? =
myInnersCache.findInnerClassByName(name, checkBases)
override fun processDeclarations(
processor: PsiScopeProcessor, state: ResolveState, lastParent: PsiElement?, place: PsiElement
): Boolean {
if (isEnum && !processDeclarationsInEnum(processor, state, myInnersCache)) return false
return PsiClassImplUtil.processDeclarationsInClass(
this,
processor,
state,
null,
lastParent,
place,
PsiUtil.getLanguageLevel(place),
false
)
}
override fun getText(): String = kotlinOrigin?.text ?: ""
override fun getLanguage(): KotlinLanguage = KotlinLanguage.INSTANCE
override fun getPresentation(): ItemPresentation? =
ItemPresentationProviders.getItemPresentation(this)
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
override fun getContext(): PsiElement = parent
override fun isEquivalentTo(another: PsiElement?): Boolean =
PsiClassImplUtil.isClassEquivalentTo(this, another)
override fun getDocComment(): PsiDocComment? = null
override fun hasTypeParameters(): Boolean = PsiImplUtil.hasTypeParameters(this)
override fun getExtendsListTypes(): Array<PsiClassType?> =
PsiClassImplUtil.getExtendsListTypes(this)
override fun getImplementsListTypes(): Array<PsiClassType?> =
PsiClassImplUtil.getImplementsListTypes(this)
override fun findMethodBySignature(patternMethod: PsiMethod?, checkBases: Boolean): PsiMethod? =
patternMethod?.let { PsiClassImplUtil.findMethodBySignature(this, it, checkBases) }
override fun findMethodsBySignature(patternMethod: PsiMethod?, checkBases: Boolean): Array<PsiMethod?> =
patternMethod?.let { PsiClassImplUtil.findMethodsBySignature(this, it, checkBases) } ?: emptyArray()
override fun findMethodsAndTheirSubstitutorsByName(
@NonNls name: String?,
checkBases: Boolean
): List<Pair<PsiMethod?, PsiSubstitutor?>?> =
PsiClassImplUtil.findMethodsAndTheirSubstitutorsByName(this, name, checkBases)
override fun getAllMethodsAndTheirSubstitutors(): List<Pair<PsiMethod?, PsiSubstitutor?>?> {
return PsiClassImplUtil.getAllWithSubstitutorsByMap(this, PsiClassImplUtil.MemberType.METHOD)
}
override fun getRBrace(): PsiElement? = null
override fun getLBrace(): PsiElement? = null
override fun getInitializers(): Array<PsiClassInitializer> = PsiClassInitializer.EMPTY_ARRAY
override fun getElementIcon(flags: Int): Icon? =
throw UnsupportedOperationException("This should be done by KotlinFirIconProvider")
override fun getVisibleSignatures(): MutableCollection<HierarchicalMethodSignature> = PsiSuperMethodImplUtil.getVisibleSignatures(this)
override fun setName(name: String): PsiElement? = cannotModify()
abstract override fun copy(): PsiElement
override fun accept(visitor: PsiElementVisitor) {
if (visitor is JavaElementVisitor) {
visitor.visitClass(this)
} else {
visitor.visitElement(this)
}
}
}
@@ -0,0 +1,179 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import com.intellij.psi.impl.InheritanceImplUtil
import com.intellij.psi.impl.PsiClassImplUtil
import com.intellij.psi.search.SearchScope
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.StubElement
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.LightClassInheritanceHelper
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.light.classes.symbol.classes.checkIsInheritor
import org.jetbrains.kotlin.light.classes.symbol.classes.getOrCreateFirLightClass
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.psi.KtClassBody
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.debugText.getDebugText
import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
import org.jetbrains.kotlin.utils.addToStdlib.ifFalse
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
internal abstract class FirLightClassForClassOrObjectSymbol(
private val classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : FirLightClassBase(manager),
StubBasedPsiElement<KotlinClassOrObjectStub<out KtClassOrObject>> {
private val isTopLevel: Boolean = classOrObjectSymbol.symbolKind == KtSymbolKind.TOP_LEVEL
private val _isDeprecated: Boolean by lazyPub {
classOrObjectSymbol.hasDeprecatedAnnotation()
}
override fun isDeprecated(): Boolean = _isDeprecated
abstract override fun getModifierList(): PsiModifierList?
abstract override fun getOwnFields(): List<KtLightField>
abstract override fun getOwnMethods(): List<PsiMethod>
private val _identifier: PsiIdentifier by lazyPub {
FirLightIdentifier(this, classOrObjectSymbol)
}
override fun getNameIdentifier(): PsiIdentifier? = _identifier
abstract override fun getExtendsList(): PsiReferenceList?
abstract override fun getImplementsList(): PsiReferenceList?
private val _typeParameterList: PsiTypeParameterList? by lazyPub {
hasTypeParameters().ifTrue {
val shiftCount = classOrObjectSymbol.isInner.ifTrue {
(parent as? FirLightClassForClassOrObjectSymbol)?.classOrObjectSymbol?.typeParameters?.count()
} ?: 0
FirLightTypeParameterListForSymbol(
owner = this,
symbolWithTypeParameterList = classOrObjectSymbol,
innerShiftCount = shiftCount
)
}
}
override fun hasTypeParameters(): Boolean =
classOrObjectSymbol.typeParameters.isNotEmpty()
override fun getTypeParameterList(): PsiTypeParameterList? = _typeParameterList
override fun getTypeParameters(): Array<PsiTypeParameter> =
_typeParameterList?.typeParameters ?: PsiTypeParameter.EMPTY_ARRAY
abstract override fun getOwnInnerClasses(): List<PsiClass>
override fun getTextOffset(): Int = kotlinOrigin?.textOffset ?: 0
override fun getStartOffsetInParent(): Int = kotlinOrigin?.startOffsetInParent ?: 0
override fun isWritable() = false
override val kotlinOrigin: KtClassOrObject? = classOrObjectSymbol.psi as? KtClassOrObject
protected fun addCompanionObjectFieldIfNeeded(result: MutableList<KtLightField>) {
classOrObjectSymbol.companionObject?.run {
result.add(
FirLightFieldForObjectSymbol(
objectSymbol = this,
containingClass = this@FirLightClassForClassOrObjectSymbol,
name = name.asString(),
lightMemberOrigin = null
)
)
}
}
private val _containingFile: PsiFile? by lazyPub {
val kotlinOrigin = kotlinOrigin ?: return@lazyPub null
val containingClass = isTopLevel.ifFalse { getOrCreateFirLightClass(getOutermostClassOrObject(kotlinOrigin)) } ?: this
FirFakeFileImpl(kotlinOrigin, containingClass)
}
override fun getContainingFile(): PsiFile? = _containingFile
override fun getNavigationElement(): PsiElement = kotlinOrigin ?: this
override fun isEquivalentTo(another: PsiElement?): Boolean =
basicIsEquivalentTo(this, another) ||
another is PsiClass && qualifiedName != null && another.qualifiedName == qualifiedName
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
override fun getName(): String? = allowLightClassesOnEdt { classOrObjectSymbol.name.asString() }
override fun hasModifierProperty(@NonNls name: String): Boolean = modifierList?.hasModifierProperty(name) ?: false
abstract override fun isInterface(): Boolean
abstract override fun isAnnotationType(): Boolean
abstract override fun isEnum(): Boolean
override fun isValid(): Boolean = kotlinOrigin?.isValid ?: true
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean {
if (manager.areElementsEquivalent(baseClass, this)) return false
LightClassInheritanceHelper.getService(project).isInheritor(this, baseClass, checkDeep).ifSure { return it }
val thisClassOrigin = kotlinOrigin
val baseClassOrigin = (baseClass as? KtLightClass)?.kotlinOrigin
return if (baseClassOrigin != null && thisClassOrigin != null) {
thisClassOrigin.checkIsInheritor(baseClassOrigin, checkDeep)
} else {
InheritanceImplUtil.isInheritor(this, baseClass, checkDeep)
}
}
override fun toString() =
"${this::class.java.simpleName}:${kotlinOrigin?.getDebugText()}"
override fun getUseScope(): SearchScope = kotlinOrigin?.useScope ?: TODO()
override fun getElementType(): IStubElementType<out StubElement<*>, *>? = kotlinOrigin?.elementType
override fun getStub(): KotlinClassOrObjectStub<out KtClassOrObject>? = kotlinOrigin?.stub
override val originKind: LightClassOriginKind
get() = LightClassOriginKind.SOURCE
override fun getQualifiedName() = kotlinOrigin?.fqName?.asString()
override fun getInterfaces(): Array<PsiClass> = PsiClassImplUtil.getInterfaces(this)
override fun getSuperClass(): PsiClass? = PsiClassImplUtil.getSuperClass(this)
override fun getSupers(): Array<PsiClass> = PsiClassImplUtil.getSupers(this)
override fun getSuperTypes(): Array<PsiClassType> = PsiClassImplUtil.getSuperTypes(this)
override fun getContainingClass(): PsiClass? {
val containingBody = kotlinOrigin?.parent as? KtClassBody
val containingClass = containingBody?.parent as? KtClassOrObject
containingClass?.let { return getOrCreateFirLightClass(it) }
return null
}
override fun getParent(): PsiElement? = containingClass ?: containingFile
override fun getScope(): PsiElement? = parent
override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean =
baseClass?.let { InheritanceImplUtil.isInheritorDeep(this, it, classToByPass) } ?: false
abstract override fun copy(): FirLightClassForClassOrObjectSymbol
}
@@ -0,0 +1,143 @@
/*
* 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.PsiClassImplUtil
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol
import org.jetbrains.kotlin.light.classes.symbol.*
import org.jetbrains.kotlin.light.classes.symbol.classes.createConstructors
import org.jetbrains.kotlin.light.classes.symbol.classes.createMethods
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtClassOrObject
internal class FirLightClassForEnumEntry(
private val enumEntrySymbol: KtEnumEntrySymbol,
private val enumConstant: FirLightFieldForEnumEntry,
private val enumClass: FirLightClassForSymbol,
manager: PsiManager
) : FirLightClassBase(manager), PsiEnumConstantInitializer {
override fun getName(): String? = enumEntrySymbol.name.asString()
override fun getBaseClassType(): PsiClassType = enumConstant.type as PsiClassType //???TODO
override fun getBaseClassReference(): PsiJavaCodeReferenceElement =
FirLightPsiJavaCodeReferenceElementWithNoReference(enumConstant) //???TODO
override fun getArgumentList(): PsiExpressionList? = null
override fun getEnumConstant(): PsiEnumConstant = enumConstant
override fun isInQualifiedNew(): Boolean = false
override fun equals(other: Any?): Boolean =
other is FirLightClassForEnumEntry &&
this.enumEntrySymbol == other.enumEntrySymbol
override fun hashCode(): Int =
enumEntrySymbol.hashCode()
override fun copy(): PsiElement =
FirLightClassForEnumEntry(enumEntrySymbol, enumConstant, enumClass, manager)
override fun toString(): String = "FirLightClassForEnumEntry for $name"
override fun getNameIdentifier(): PsiIdentifier? = null //TODO
private val _modifierList: PsiModifierList by lazyPub {
FirLightClassModifierList(
containingDeclaration = this,
modifiers = setOf(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL),
annotations = emptyList()
)
}
override fun getModifierList(): PsiModifierList? = _modifierList
override fun hasModifierProperty(name: String): Boolean =
name == PsiModifier.PUBLIC || name == PsiModifier.STATIC || name == PsiModifier.FINAL
override fun getContainingClass(): PsiClass? = enumClass
override fun isDeprecated(): Boolean = false
override fun getTypeParameters(): Array<PsiTypeParameter> = emptyArray()
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getQualifiedName(): String? = "${enumConstant.containingClass.qualifiedName}.${enumConstant.name}"
override fun isInterface(): Boolean = false
override fun isAnnotationType(): Boolean = false
override fun isEnum(): Boolean = false
private val _extendsList: PsiReferenceList? by lazyPub {
val mappedType = analyzeWithSymbolAsContext(enumEntrySymbol) {
enumEntrySymbol.annotatedType
.type.asPsiType(this@FirLightClassForEnumEntry, TypeMappingMode.SUPER_TYPE) as? PsiClassType
?: return@lazyPub null
}
KotlinSuperTypeListBuilder(
kotlinOrigin = enumClass.kotlinOrigin?.getSuperTypeList(),
manager = manager,
language = language,
role = PsiReferenceList.Role.EXTENDS_LIST
).also {
it.addReference(mappedType)
}
}
override fun getExtendsList(): PsiReferenceList? = _extendsList
override fun getImplementsList(): PsiReferenceList? = null
override fun getSuperClass(): PsiClass? = enumClass
override fun getInterfaces(): Array<PsiClass> = PsiClass.EMPTY_ARRAY
override fun getSupers(): Array<PsiClass> = arrayOf(enumClass)
override fun getSuperTypes(): Array<PsiClassType> = PsiClassImplUtil.getSuperTypes(this)
override fun getParent(): PsiElement? = containingClass ?: containingFile
override fun getScope(): PsiElement? = parent
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean = false //TODO
override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean = false //TODO
override val kotlinOrigin: KtClassOrObject? = enumConstant.kotlinOrigin
override val originKind: LightClassOriginKind = LightClassOriginKind.SOURCE
override fun getOwnFields(): MutableList<PsiField> = mutableListOf()
override fun getOwnMethods(): MutableList<KtLightMethod> {
val result = mutableListOf<KtLightMethod>()
analyzeWithSymbolAsContext(enumEntrySymbol) {
val declaredMemberScope = enumEntrySymbol.getDeclaredMemberScope()
createMethods(declaredMemberScope.getCallableSymbols(), result)
createConstructors(declaredMemberScope.getConstructors(), result)
}
return result
}
override fun getOwnInnerClasses(): MutableList<PsiClass> = mutableListOf()
override fun isValid(): Boolean = super.isValid() && enumEntrySymbol.isValid()
}
@@ -0,0 +1,272 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.openapi.util.TextRange
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightEmptyImplementsList
import com.intellij.psi.impl.light.LightModifierList
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtDeclarationScope
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithDeclarations
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
import org.jetbrains.kotlin.light.classes.symbol.classes.analyseForLightClasses
import org.jetbrains.kotlin.light.classes.symbol.classes.createField
import org.jetbrains.kotlin.light.classes.symbol.classes.createMethods
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
class FirLightClassForFacade(
manager: PsiManager,
override val facadeClassFqName: FqName,
override val files: Collection<KtFile>
) : FirLightClassBase(manager), KtLightClassForFacade {
init {
require(files.isNotEmpty())
}
private val firstFileInFacade by lazyPub { files.first() }
override val clsDelegate: PsiClass get() = invalidAccess()
private val fileSymbols by lazyPub {
files.map { ktFile ->
analyseForLightClasses(ktFile) {
ktFile.getFileSymbol()
}
}
}
private val _modifierList: PsiModifierList by lazyPub {
if (multiFileClass)
return@lazyPub LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL)
val modifiers = setOf(PsiModifier.PUBLIC, PsiModifier.FINAL)
val annotations = fileSymbols.flatMap {
it.computeAnnotations(
this@FirLightClassForFacade,
NullabilityType.Unknown,
AnnotationUseSiteTarget.FILE,
includeAnnotationsWithoutSite = false
)
}
FirLightClassModifierList(this@FirLightClassForFacade, modifiers, annotations)
}
override fun getModifierList(): PsiModifierList = _modifierList
override fun getScope(): PsiElement = parent
private val _ownMethods: List<KtLightMethod> by lazyPub {
val result = mutableListOf<KtLightMethod>()
val methodsAndProperties = sequence<KtCallableSymbol> {
for (fileSymbol in fileSymbols) {
analyzeWithSymbolAsContext(fileSymbol) {
for (callableSymbol in fileSymbol.getFileScope().getCallableSymbols()) {
if (callableSymbol !is KtFunctionSymbol && callableSymbol !is KtKotlinPropertySymbol) continue
if (callableSymbol !is KtSymbolWithVisibility) continue
val isPrivate = callableSymbol.toPsiVisibilityForMember(isTopLevel = true) == PsiModifier.PRIVATE
if (isPrivate && multiFileClass) continue
yield(callableSymbol)
}
}
}
}
createMethods(methodsAndProperties, result, isTopLevel = true)
result
}
private val multiFileClass: Boolean by lazyPub {
files.size > 1 || fileSymbols.any { it.hasJvmMultifileClassAnnotation() }
}
private fun loadFieldsFromFile(
fileScope: KtDeclarationScope<KtSymbolWithDeclarations>,
nameGenerator: FirLightField.FieldNameGenerator,
result: MutableList<KtLightField>
) {
for (propertySymbol in fileScope.getCallableSymbols()) {
if (propertySymbol !is KtKotlinPropertySymbol) continue
if (propertySymbol.isConst && multiFileClass) continue
val isLateInitWithPublicAccessors = if (propertySymbol.isLateInit) {
val getterIsPublic = propertySymbol.getter?.toPsiVisibilityForMember(isTopLevel = true)
?.let { it == PsiModifier.PUBLIC } ?: true
val setterIsPublic = propertySymbol.setter?.toPsiVisibilityForMember(isTopLevel = true)
?.let { it == PsiModifier.PUBLIC } ?: true
getterIsPublic && setterIsPublic
} else false
val forceStaticAndPropertyVisibility = isLateInitWithPublicAccessors ||
(propertySymbol.isConst) ||
propertySymbol.hasJvmFieldAnnotation()
createField(
propertySymbol,
nameGenerator,
isTopLevel = true,
forceStatic = forceStaticAndPropertyVisibility,
takePropertyVisibility = forceStaticAndPropertyVisibility,
result
)
}
}
private val _ownFields: List<KtLightField> by lazyPub {
val result = mutableListOf<KtLightField>()
val nameGenerator = FirLightField.FieldNameGenerator()
for (fileSymbol in fileSymbols) {
analyzeWithSymbolAsContext(fileSymbol) {
loadFieldsFromFile(fileSymbol.getFileScope(), nameGenerator, result)
}
}
result
}
override fun getOwnFields() = _ownFields
override fun getOwnMethods() = _ownMethods
override fun copy(): FirLightClassForFacade =
FirLightClassForFacade(manager, facadeClassFqName, files)
private val packageFqName: FqName =
facadeClassFqName.parent()
private val modifierList: PsiModifierList =
LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL)
private val implementsList: LightEmptyImplementsList =
LightEmptyImplementsList(manager)
private val packageClsFile = FakeFileForLightClass(
firstFileInFacade,
lightClass = { this },
stub = { null },
packageFqName = packageFqName
)
override fun getParent(): PsiElement = containingFile
override val kotlinOrigin: KtClassOrObject? get() = null
val fqName: FqName
get() = facadeClassFqName
override fun hasModifierProperty(@NonNls name: String) = modifierList.hasModifierProperty(name)
override fun getExtendsList(): PsiReferenceList? = null
override fun isDeprecated() = false
override fun isInterface() = false
override fun isAnnotationType() = false
override fun isEnum() = false
override fun getContainingClass(): PsiClass? = null
override fun getContainingFile() = packageClsFile
override fun hasTypeParameters() = false
override fun getTypeParameters(): Array<out PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getImplementsList() = implementsList
override fun getInterfaces(): Array<out PsiClass> = PsiClass.EMPTY_ARRAY
override fun getInnerClasses(): Array<out PsiClass> = PsiClass.EMPTY_ARRAY
override fun getOwnInnerClasses(): List<PsiClass> = listOf()
override fun getAllInnerClasses(): Array<PsiClass> = PsiClass.EMPTY_ARRAY
override fun findInnerClassByName(@NonNls name: String, checkBases: Boolean): PsiClass? = null
override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean = false
override fun getName() = super<KtLightClassForFacade>.getName()
override fun getQualifiedName() = facadeClassFqName.asString()
override fun getNameIdentifier(): PsiIdentifier? = null
override fun isValid() = files.all { it.isValid && it.hasTopLevelCallables() && facadeClassFqName == it.javaFileFacadeFqName }
override fun getNavigationElement() = firstFileInFacade
override fun isEquivalentTo(another: PsiElement?): Boolean =
equals(another) || another is FirLightClassForFacade && another.qualifiedName == qualifiedName
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean {
return baseClass.qualifiedName == CommonClassNames.JAVA_LANG_OBJECT
}
override fun getSuperClass(): PsiClass? {
return JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope)
}
override fun getSupers(): Array<PsiClass> =
superClass?.let { arrayOf(it) } ?: arrayOf()
override fun getSuperTypes(): Array<PsiClassType> =
arrayOf(PsiType.getJavaLangObject(manager, resolveScope))
override fun equals(other: Any?): Boolean {
if (other !is FirLightClassForFacade) return false
if (this === other) return true
if (this.hashCode() != other.hashCode()) return false
if (manager != other.manager) return false
if (facadeClassFqName != other.facadeClassFqName) return false
if (!fileSymbols.containsAll(other.fileSymbols)) return false
if (!other.fileSymbols.containsAll(fileSymbols)) return false
return true
}
override fun hashCode() = facadeClassFqName.hashCode()
override fun toString() = "${FirLightClassForFacade::class.java.simpleName}:$facadeClassFqName"
override val originKind: LightClassOriginKind
get() = LightClassOriginKind.SOURCE
override fun getText() = firstFileInFacade.text ?: ""
override fun getTextRange(): TextRange = firstFileInFacade.textRange ?: TextRange.EMPTY_RANGE
override fun getTextOffset() = firstFileInFacade.textOffset
override fun getStartOffsetInParent() = firstFileInFacade.startOffsetInParent
override fun isWritable() = files.all { it.isWritable }
}
@@ -0,0 +1,224 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
import org.jetbrains.kotlin.light.classes.symbol.classes.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
internal class FirLightClassForSymbol(
private val classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : FirLightClassForClassOrObjectSymbol(classOrObjectSymbol, manager) {
init {
require(classOrObjectSymbol.classKind != KtClassKind.INTERFACE && classOrObjectSymbol.classKind != KtClassKind.ANNOTATION_CLASS)
}
internal fun tryGetEffectiveVisibility(symbol: KtCallableSymbol): Visibility? {
if (symbol !is KtPropertySymbol && symbol !is KtFunctionSymbol) return null
var visibility = (symbol as? KtSymbolWithVisibility)?.visibility
analyzeWithSymbolAsContext(symbol) {
for (overriddenSymbol in symbol.getAllOverriddenSymbols()) {
val newVisibility = (overriddenSymbol as? KtSymbolWithVisibility)?.visibility
if (newVisibility != null) {
visibility = newVisibility
}
}
}
return visibility
}
private val isTopLevel: Boolean = classOrObjectSymbol.symbolKind == KtSymbolKind.TOP_LEVEL
private val _modifierList: PsiModifierList? by lazyPub {
val modifiers = mutableSetOf(classOrObjectSymbol.toPsiVisibilityForClass(isTopLevel))
classOrObjectSymbol.computeSimpleModality()?.run {
modifiers.add(this)
}
if (!isTopLevel && !classOrObjectSymbol.isInner) {
modifiers.add(PsiModifier.STATIC)
}
val annotations = classOrObjectSymbol.computeAnnotations(
parent = this@FirLightClassForSymbol,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
FirLightClassModifierList(this@FirLightClassForSymbol, modifiers, annotations)
}
override fun getModifierList(): PsiModifierList? = _modifierList
override fun getOwnFields(): List<KtLightField> = _ownFields
override fun getOwnMethods(): List<PsiMethod> = _ownMethods
override fun getExtendsList(): PsiReferenceList? = _extendsList
override fun getImplementsList(): PsiReferenceList? = _implementsList
private val _ownInnerClasses: List<FirLightClassBase> by lazyPub {
classOrObjectSymbol.createInnerClasses(manager)
}
override fun getOwnInnerClasses(): List<PsiClass> = _ownInnerClasses
private val _extendsList by lazyPub { createInheritanceList(forExtendsList = true, classOrObjectSymbol.superTypes) }
private val _implementsList by lazyPub { createInheritanceList(forExtendsList = false, classOrObjectSymbol.superTypes) }
private val _ownMethods: List<KtLightMethod> by lazyPub {
val result = mutableListOf<KtLightMethod>()
analyzeWithSymbolAsContext(classOrObjectSymbol) {
val declaredMemberScope = classOrObjectSymbol.getDeclaredMemberScope()
val visibleDeclarations = declaredMemberScope.getCallableSymbols().applyIf(isEnum) {
filterNot { function ->
function is KtFunctionSymbol && function.name.asString().let { it == "values" || it == "valueOf" }
}
}.applyIf(classOrObjectSymbol.classKind == KtClassKind.OBJECT) {
filterNot {
it is KtKotlinPropertySymbol && it.isConst
}
}
val suppressStatic = classOrObjectSymbol.classKind == KtClassKind.COMPANION_OBJECT
createMethods(visibleDeclarations, result, suppressStaticForMethods = suppressStatic)
createConstructors(declaredMemberScope.getConstructors(), result)
}
addMethodsFromCompanionIfNeeded(result)
result
}
private fun addFieldsFromCompanionIfNeeded(result: MutableList<KtLightField>) {
classOrObjectSymbol.companionObject?.run {
analyzeWithSymbolAsContext(this) {
getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtPropertySymbol>()
.filter { it.hasJvmFieldAnnotation() || it.hasJvmStaticAnnotation() || it is KtKotlinPropertySymbol && it.isConst }
.mapTo(result) {
FirLightFieldForPropertySymbol(
propertySymbol = it,
fieldName = it.name.asString(),
containingClass = this@FirLightClassForSymbol,
lightMemberOrigin = null,
isTopLevel = false,
forceStatic = !it.hasJvmStaticAnnotation(),
takePropertyVisibility = true
)
}
}
}
}
private fun addMethodsFromCompanionIfNeeded(result: MutableList<KtLightMethod>) {
classOrObjectSymbol.companionObject?.run {
analyzeWithSymbolAsContext(this) {
val methods = getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtFunctionSymbol>()
.filter { it.hasJvmStaticAnnotation() }
createMethods(methods, result)
}
}
}
private fun addInstanceFieldIfNeeded(result: MutableList<KtLightField>) {
val isNamedObject = classOrObjectSymbol.classKind == KtClassKind.OBJECT
if (isNamedObject && classOrObjectSymbol.symbolKind != KtSymbolKind.LOCAL) {
result.add(
FirLightFieldForObjectSymbol(
objectSymbol = classOrObjectSymbol,
containingClass = this@FirLightClassForSymbol,
name = JvmAbi.INSTANCE_FIELD,
lightMemberOrigin = null
)
)
}
}
private fun addPropertyBackingFields(result: MutableList<KtLightField>) {
analyzeWithSymbolAsContext(classOrObjectSymbol) {
val propertySymbols = classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtPropertySymbol>()
.applyIf(classOrObjectSymbol.classKind == KtClassKind.COMPANION_OBJECT) {
filterNot { it.hasJvmFieldAnnotation() || it is KtKotlinPropertySymbol && it.isConst }
}
val nameGenerator = FirLightField.FieldNameGenerator()
val isObject = classOrObjectSymbol.classKind == KtClassKind.OBJECT
val isCompanionObject = classOrObjectSymbol.classKind == KtClassKind.COMPANION_OBJECT
for (propertySymbol in propertySymbols) {
val isJvmField = propertySymbol.hasJvmFieldAnnotation()
val isJvmStatic = propertySymbol.hasJvmStaticAnnotation()
val forceStatic = isObject && (propertySymbol is KtKotlinPropertySymbol && propertySymbol.isConst || isJvmStatic || isJvmField)
val takePropertyVisibility = !isCompanionObject && (isJvmField || forceStatic)
createField(
declaration = propertySymbol,
nameGenerator = nameGenerator,
isTopLevel = false,
forceStatic = forceStatic,
takePropertyVisibility = takePropertyVisibility,
result = result
)
}
if (isEnum) {
classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtEnumEntrySymbol>()
.mapTo(result) { FirLightFieldForEnumEntry(it, this@FirLightClassForSymbol, null) }
}
}
}
private val _ownFields: List<KtLightField> by lazyPub {
val result = mutableListOf<KtLightField>()
addCompanionObjectFieldIfNeeded(result)
addInstanceFieldIfNeeded(result)
addFieldsFromCompanionIfNeeded(result)
addPropertyBackingFields(result)
result
}
override fun hashCode(): Int = classOrObjectSymbol.hashCode()
override fun equals(other: Any?): Boolean =
this === other || (other is FirLightClassForSymbol && classOrObjectSymbol == other.classOrObjectSymbol)
override fun isInterface(): Boolean = false
override fun isAnnotationType(): Boolean = false
override fun isEnum(): Boolean =
classOrObjectSymbol.classKind == KtClassKind.ENUM_CLASS
override fun copy(): FirLightClassForSymbol =
FirLightClassForSymbol(classOrObjectSymbol, manager)
override fun isValid(): Boolean = super.isValid() && classOrObjectSymbol.isValid()
}
@@ -0,0 +1,72 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReferenceList
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.isPrivateOrPrivateToThis
import org.jetbrains.kotlin.light.classes.symbol.FirLightClassForClassOrObjectSymbol
import org.jetbrains.kotlin.light.classes.symbol.analyzeWithSymbolAsContext
internal class FirLightInterfaceClassSymbol(
private val classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : FirLightInterfaceOrAnnotationClassSymbol(classOrObjectSymbol, manager) {
init {
require(classOrObjectSymbol.classKind == KtClassKind.INTERFACE)
}
private val _ownFields: List<KtLightField> by lazyPub {
mutableListOf<KtLightField>().also {
addCompanionObjectFieldIfNeeded(it)
}
}
override fun getOwnFields(): List<KtLightField> = _ownFields
private val _ownMethods: List<KtLightMethod> by lazyPub {
val result = mutableListOf<KtLightMethod>()
analyzeWithSymbolAsContext(classOrObjectSymbol) {
val visibleDeclarations = classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
.filterNot { it is KtFunctionSymbol && it.visibility.isPrivateOrPrivateToThis() }
createMethods(visibleDeclarations, result)
}
result
}
override fun getOwnMethods(): List<PsiMethod> = _ownMethods
override fun equals(other: Any?): Boolean =
other === this || (other is FirLightInterfaceClassSymbol && classOrObjectSymbol == other.classOrObjectSymbol)
override fun hashCode(): Int = classOrObjectSymbol.hashCode()
override fun isAnnotationType(): Boolean = false
override fun copy(): FirLightClassForClassOrObjectSymbol =
FirLightInterfaceClassSymbol(classOrObjectSymbol, manager)
private val _extendsList: PsiReferenceList by lazyPub {
createInheritanceList(forExtendsList = false, classOrObjectSymbol.superTypes)
}
override fun getExtendsList(): PsiReferenceList? = _extendsList
override fun isValid(): Boolean = super.isValid() && classOrObjectSymbol.isValid()
}
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.light.classes.symbol.*
internal abstract class FirLightInterfaceOrAnnotationClassSymbol(
private val classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : FirLightClassForClassOrObjectSymbol(classOrObjectSymbol, manager) {
init {
require(
classOrObjectSymbol.classKind == KtClassKind.OBJECT ||
classOrObjectSymbol.classKind == KtClassKind.INTERFACE ||
classOrObjectSymbol.classKind == KtClassKind.ANNOTATION_CLASS
)
}
private val _modifierList: PsiModifierList? by lazyPub {
val isTopLevel: Boolean = classOrObjectSymbol.symbolKind == KtSymbolKind.TOP_LEVEL
val modifiers = mutableSetOf(classOrObjectSymbol.toPsiVisibilityForClass(isTopLevel), PsiModifier.ABSTRACT)
val annotations = classOrObjectSymbol.computeAnnotations(
parent = this@FirLightInterfaceOrAnnotationClassSymbol,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
FirLightClassModifierList(this@FirLightInterfaceOrAnnotationClassSymbol, modifiers, annotations)
}
override fun getModifierList(): PsiModifierList? = _modifierList
override fun getImplementsList(): PsiReferenceList? = null
override fun getOwnInnerClasses(): List<PsiClass> = emptyList()
override fun isInterface(): Boolean = true
override fun isEnum(): Boolean = false
override fun isValid(): Boolean = super.isValid() && classOrObjectSymbol.isValid()
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.LightClassInheritanceHelper
import org.jetbrains.kotlin.idea.frontend.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.light.classes.symbol.classes.checkIsInheritor
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
//TODO Make fake class symbol based
class KtFirBasedFakeLightClass(kotlinOrigin: KtClassOrObject) :
KtFakeLightClass(kotlinOrigin) {
override fun copy(): KtFakeLightClass = KtFirBasedFakeLightClass(kotlinOrigin)
private val _containingClass: KtFakeLightClass? by lazy {
kotlinOrigin.containingClassOrObject?.let { KtFirBasedFakeLightClass(it) }
}
override fun getContainingClass(): KtFakeLightClass? = _containingClass
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean {
if (manager.areElementsEquivalent(baseClass, this)) return false
LightClassInheritanceHelper.getService(project).isInheritor(this, baseClass, checkDeep).ifSure { return it }
val baseClassOrigin = (baseClass as? KtLightClass)?.kotlinOrigin ?: return false
return kotlinOrigin.checkIsInheritor(baseClassOrigin, checkDeep)
}
}
@@ -0,0 +1,14 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.classes
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.analyseWithCustomToken
import org.jetbrains.kotlin.idea.frontend.api.tokens.AlwaysAccessibleValidityTokenFactory
import org.jetbrains.kotlin.psi.KtElement
internal inline fun <R> analyseForLightClasses(context: KtElement, action: KtAnalysisSession.() -> R): R =
analyseWithCustomToken(context, AlwaysAccessibleValidityTokenFactory, action)
@@ -0,0 +1,367 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiReferenceList
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
import org.jetbrains.kotlin.asJava.classes.KotlinSuperTypeListBuilder
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_BASE
import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithMembers
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtTypeAndAnnotations
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.isPrivateOrPrivateToThis
import org.jetbrains.kotlin.idea.frontend.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.idea.frontend.api.tokens.hackyAllowRunningOnEdt
import org.jetbrains.kotlin.idea.frontend.api.types.KtNonErrorClassType
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.light.classes.symbol.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass
import java.util.*
fun getOrCreateFirLightClass(classOrObject: KtClassOrObject): KtLightClass? =
CachedValuesManager.getCachedValue(classOrObject) {
CachedValueProvider.Result
.create(
createFirLightClassNoCache(classOrObject),
classOrObject.project.createProjectWideOutOfBlockModificationTracker()
)
}
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
fun createFirLightClassNoCache(classOrObject: KtClassOrObject): KtLightClass? = hackyAllowRunningOnEdt {
val containingFile = classOrObject.containingFile
if (containingFile is KtCodeFragment) {
// Avoid building light classes for code fragments
return null
}
if (containingFile is KtFile && containingFile.isCompiled) return null
if (classOrObject.shouldNotBeVisibleAsLightClass()) {
return null
}
val anonymousObject = classOrObject.parent as? KtObjectLiteralExpression
if (anonymousObject != null) {
return analyseForLightClasses(anonymousObject) {
anonymousObject.getAnonymousObjectSymbol().createLightClassNoCache(anonymousObject.manager)
}
}
return when {
classOrObject is KtEnumEntry -> lightClassForEnumEntry(classOrObject)
classOrObject.hasModifier(KtTokens.INLINE_KEYWORD) -> return null //TODO
else -> {
analyseForLightClasses(classOrObject) {
classOrObject.getClassOrObjectSymbol().createLightClassNoCache(classOrObject.manager)
}
}
}
}
internal fun KtClassOrObjectSymbol.createLightClassNoCache(manager: PsiManager): FirLightClassBase = when (this) {
is KtAnonymousObjectSymbol -> FirLightAnonymousClassForSymbol(this, manager)
is KtNamedClassOrObjectSymbol -> when (classKind) {
KtClassKind.INTERFACE -> FirLightInterfaceClassSymbol(this, manager)
KtClassKind.ANNOTATION_CLASS -> FirLightAnnotationClassSymbol(this, manager)
else -> FirLightClassForSymbol(this, manager)
}
}
fun getOrCreateFirLightFacade(
ktFiles: List<KtFile>,
facadeClassFqName: FqName,
): FirLightClassForFacade? {
val firstFile = ktFiles.firstOrNull() ?: return null
//TODO Make caching keyed by all files
return CachedValuesManager.getCachedValue(firstFile) {
CachedValueProvider.Result
.create(
getOrCreateFirLightFacadeNoCache(ktFiles, facadeClassFqName),
firstFile.project.createProjectWideOutOfBlockModificationTracker()
)
}
}
fun getOrCreateFirLightFacadeNoCache(
ktFiles: List<KtFile>,
facadeClassFqName: FqName,
): FirLightClassForFacade? {
val firstFile = ktFiles.firstOrNull() ?: return null
return FirLightClassForFacade(firstFile.manager, facadeClassFqName, ktFiles)
}
private fun lightClassForEnumEntry(ktEnumEntry: KtEnumEntry): KtLightClass? {
if (ktEnumEntry.body == null) return null
val firClass = ktEnumEntry
.containingClass()
?.let { getOrCreateFirLightClass(it) } as? FirLightClassForSymbol
?: return null
val targetField = firClass.ownFields
.firstOrNull { it is FirLightFieldForEnumEntry && it.kotlinOrigin == ktEnumEntry }
?: return null
return (targetField as? FirLightFieldForEnumEntry)?.initializingClass as? KtLightClass
}
internal fun FirLightClassBase.createConstructors(
declarations: Sequence<KtConstructorSymbol>,
result: MutableList<KtLightMethod>
) {
for (declaration in declarations) {
if (declaration.isHiddenOrSynthetic(project)) continue
result.add(
FirLightConstructorForSymbol(
constructorSymbol = declaration,
lightMemberOrigin = null,
containingClass = this@createConstructors,
methodIndex = METHOD_INDEX_BASE
)
)
}
}
internal fun FirLightClassBase.createMethods(
declarations: Sequence<KtCallableSymbol>,
result: MutableList<KtLightMethod>,
isTopLevel: Boolean = false,
suppressStaticForMethods: Boolean = false
) {
val declarationGroups = declarations.groupBy { it is KtPropertySymbol && it.isFromPrimaryConstructor }
fun handleDeclaration(declaration: KtCallableSymbol) {
when (declaration) {
is KtFunctionSymbol -> {
if (declaration.isInline || declaration.isHiddenOrSynthetic(project)) return
var methodIndex = METHOD_INDEX_BASE
result.add(
FirLightSimpleMethodForSymbol(
functionSymbol = declaration,
lightMemberOrigin = null,
containingClass = this@createMethods,
isTopLevel = isTopLevel,
methodIndex = methodIndex,
suppressStatic = suppressStaticForMethods
)
)
if (declaration.hasJvmOverloadsAnnotation()) {
val skipMask = BitSet(declaration.valueParameters.size)
for (i in declaration.valueParameters.size - 1 downTo 0) {
if (!declaration.valueParameters[i].hasDefaultValue) continue
skipMask.set(i)
result.add(
FirLightSimpleMethodForSymbol(
functionSymbol = declaration,
lightMemberOrigin = null,
containingClass = this@createMethods,
isTopLevel = isTopLevel,
methodIndex = methodIndex++,
argumentsSkipMask = skipMask.copy()
)
)
}
}
}
is KtPropertySymbol -> {
if (declaration is KtKotlinPropertySymbol && declaration.isConst) return
if (declaration.visibility.isPrivateOrPrivateToThis() &&
declaration.getter?.hasBody == false &&
declaration.setter?.hasBody == false
) return
if (declaration.hasJvmFieldAnnotation()) return
fun KtPropertyAccessorSymbol.needToCreateAccessor(siteTarget: AnnotationUseSiteTarget): Boolean {
if (isInline) return false
if (!hasBody && visibility.isPrivateOrPrivateToThis()) return false
if (declaration.isHiddenOrSynthetic(project, siteTarget)) return false
if (isHiddenOrSynthetic(project)) return false
return true
}
val getter = declaration.getter?.takeIf {
it.needToCreateAccessor(AnnotationUseSiteTarget.PROPERTY_GETTER)
}
if (getter != null) {
result.add(
FirLightAccessorMethodForSymbol(
propertyAccessorSymbol = getter,
containingPropertySymbol = declaration,
lightMemberOrigin = null,
containingClass = this@createMethods,
isTopLevel = isTopLevel
)
)
}
val setter = declaration.setter?.takeIf {
!isAnnotationType && it.needToCreateAccessor(AnnotationUseSiteTarget.PROPERTY_SETTER)
}
if (setter != null) {
result.add(
FirLightAccessorMethodForSymbol(
propertyAccessorSymbol = setter,
containingPropertySymbol = declaration,
lightMemberOrigin = null,
containingClass = this@createMethods,
isTopLevel = isTopLevel
)
)
}
}
is KtConstructorSymbol -> error("Constructors should be handled separately and not passed to this function")
}
}
// Regular members
declarationGroups[false]?.forEach {
handleDeclaration(it)
}
// Then, properties from the primary constructor parameters
declarationGroups[true]?.forEach {
handleDeclaration(it)
}
}
internal fun FirLightClassBase.createField(
declaration: KtPropertySymbol,
nameGenerator: FirLightField.FieldNameGenerator,
isTopLevel: Boolean,
forceStatic: Boolean,
takePropertyVisibility: Boolean,
result: MutableList<KtLightField>
) {
fun hasBackingField(property: KtPropertySymbol): Boolean = when (property) {
is KtSyntheticJavaPropertySymbol -> true
is KtKotlinPropertySymbol -> when {
property.modality == Modality.ABSTRACT -> false
property.isHiddenOrSynthetic(project) -> false
property.isLateInit -> true
//TODO Fix it when KtFirConstructorValueParameterSymbol be ready
property.psi.let { it == null || it is KtParameter } -> true
property.hasJvmSyntheticAnnotation(AnnotationUseSiteTarget.FIELD) -> false
else -> property.hasBackingField
}
}
if (!hasBackingField(declaration)) return
result.add(
FirLightFieldForPropertySymbol(
propertySymbol = declaration,
fieldName = nameGenerator.generateUniqueFieldName(declaration.name.asString()),
containingClass = this,
lightMemberOrigin = null,
isTopLevel = isTopLevel,
forceStatic = forceStatic,
takePropertyVisibility = takePropertyVisibility
)
)
}
internal fun FirLightClassBase.createInheritanceList(forExtendsList: Boolean, superTypes: List<KtTypeAndAnnotations>): PsiReferenceList {
val role = if (forExtendsList) PsiReferenceList.Role.EXTENDS_LIST else PsiReferenceList.Role.IMPLEMENTS_LIST
val listBuilder = KotlinSuperTypeListBuilder(
kotlinOrigin = kotlinOrigin?.getSuperTypeList(),
manager = manager,
language = language,
role = role
)
fun KtType.needToAddTypeIntoList(): Boolean {
if (this !is KtNonErrorClassType) return false
// Do not add redundant "extends java.lang.Object" anywhere
if (this.classId == StandardClassIds.Any) return false
// We don't have Enum among enums supertype in sources neither we do for decompiled class-files and light-classes
if (isEnum && this.classId == StandardClassIds.Enum) return false
val isInterfaceType =
(this.classSymbol as? KtClassOrObjectSymbol)?.classKind == KtClassKind.INTERFACE
return forExtendsList == !isInterfaceType
}
//TODO Add support for kotlin.collections.
superTypes.asSequence()
.filter { it.type.needToAddTypeIntoList() }
.mapNotNull { typeAnnotated ->
val type = typeAnnotated.type
if (type !is KtNonErrorClassType) return@mapNotNull null
analyzeWithSymbolAsContext(type.classSymbol) {
mapSuperType(type, this@createInheritanceList, kotlinCollectionAsIs = true)
}
}
.forEach { listBuilder.addReference(it) }
return listBuilder
}
internal fun KtSymbolWithMembers.createInnerClasses(manager: PsiManager): List<FirLightClassBase> {
val result = ArrayList<FirLightClassBase>()
// workaround for ClassInnerStuffCache not supporting classes with null names, see KT-13927
// 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
manager.project.analyzeWithSymbolAsContext(this) {
getDeclaredMemberScope().getClassifierSymbols().filterIsInstance<KtNamedClassOrObjectSymbol>().mapTo(result) {
it.createLightClassNoCache(manager)
}
}
//TODO
//if (classOrObject.hasInterfaceDefaultImpls) {
// result.add(KtLightClassForInterfaceDefaultImpls(classOrObject))
//}
return result
}
internal fun KtClassOrObject.checkIsInheritor(baseClassOrigin: KtClassOrObject, checkDeep: Boolean): Boolean {
return analyseForLightClasses(this) {
val subClassSymbol = this@checkIsInheritor.getNamedClassOrObjectSymbol() ?: return false
val superClassSymbol = baseClassOrigin.getNamedClassOrObjectSymbol() ?: return false
if (subClassSymbol == superClassSymbol) return@analyseForLightClasses false
if (checkDeep) {
subClassSymbol.isSubClassOf(superClassSymbol)
} else {
subClassSymbol.isDirectSubClassOf(superClassSymbol)
}
}
}
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import com.intellij.psi.scope.PsiScopeProcessor
internal abstract class FirLightPsiJavaCodeReferenceElementBase(private val ktElement: PsiElement) :
PsiElement by ktElement,
PsiJavaCodeReferenceElement {
override fun multiResolve(incompleteCode: Boolean): Array<JavaResolveResult> = emptyArray()
override fun processVariants(processor: PsiScopeProcessor) { }
override fun advancedResolve(incompleteCode: Boolean): JavaResolveResult =
JavaResolveResult.EMPTY
override fun getQualifier(): PsiElement? = null
override fun getReferenceName(): String? = null
override fun getReferenceNameElement(): PsiElement? = null
override fun getParameterList(): PsiReferenceParameterList? = null
override fun getTypeParameters(): Array<PsiType> = emptyArray()
override fun isQualified(): Boolean = false
override fun getQualifiedName(): String? = null
}
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.util.IncorrectOperationException
internal class FirLightPsiJavaCodeReferenceElementWithNoReference(private val ktElement: PsiElement):
FirLightPsiJavaCodeReferenceElementBase(ktElement),
PsiReference {
override fun getElement(): PsiElement = ktElement
override fun getRangeInElement(): TextRange = ktElement.textRange
override fun resolve(): PsiElement? = null
override fun getCanonicalText(): String = "<no-text>"
override fun handleElementRename(newElementName: String): PsiElement = element
@Throws(IncorrectOperationException::class)
override fun bindToElement(element: PsiElement): PsiElement =
throw IncorrectOperationException("can't rename FirLightPsiJavaCodeReferenceElementWithNoReference")
override fun isReferenceTo(element: PsiElement): Boolean = false
override fun isSoft(): Boolean = false
}
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
internal class FirLightPsiJavaCodeReferenceElementWithReference(private val ktElement: PsiElement, reference: PsiReference):
FirLightPsiJavaCodeReferenceElementBase(ktElement),
PsiReference by reference {
override fun getElement(): PsiElement = ktElement
}
@@ -0,0 +1,97 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.lang.Language
import com.intellij.psi.*
import com.intellij.psi.impl.ElementPresentationUtil
import com.intellij.ui.IconManager
import com.intellij.util.IncorrectOperationException
import com.intellij.util.PlatformIcons
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import javax.swing.Icon
internal abstract class FirLightField protected constructor(
private val containingClass: KtLightClass,
lightMemberOrigin: LightMemberOrigin?,
) : FirLightMemberImpl<PsiField>(lightMemberOrigin, containingClass), KtLightField {
override val clsDelegate: PsiField get() = invalidAccess()
override fun setInitializer(initializer: PsiExpression?) = cannotModify()
override fun isEquivalentTo(another: PsiElement?): Boolean =
basicIsEquivalentTo(this, another as? PsiField)
override fun getLanguage(): Language = KotlinLanguage.INSTANCE
override fun getParent() = containingClass
override fun getContainingClass() = containingClass
override fun getContainingFile(): PsiFile? = containingClass.containingFile
override fun hasInitializer(): Boolean = initializer !== null
override fun computeConstantValue(): Any? = null //TODO _constantInitializer?.value
override fun computeConstantValue(visitedVars: MutableSet<PsiVariable>?): Any? = computeConstantValue()
override fun setName(@NonNls name: String): PsiElement {
(kotlinOrigin as? KtNamedDeclaration)?.setName(name)
return this
}
override fun toString(): String = "KtLightField:$name"
override fun getTypeElement(): PsiTypeElement? = null
@Throws(IncorrectOperationException::class)
override fun normalizeDeclaration() {
}
override fun isVisibilitySupported(): Boolean = true
override fun getElementIcon(flags: Int): Icon? {
val baseIcon = IconManager.getInstance().createLayeredIcon(
this,
PlatformIcons.VARIABLE_ICON, ElementPresentationUtil.getFlags(
this,
false
)
)
return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon)
}
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
override fun accept(visitor: PsiElementVisitor) {
if (visitor is JavaElementVisitor) {
visitor.visitField(this)
} else {
visitor.visitElement(this)
}
}
internal class FieldNameGenerator {
private val usedNames: MutableSet<String> = mutableSetOf()
fun generateUniqueFieldName(base: String): String {
if (usedNames.add(base)) return base
var i = 1
while (true) {
val suggestion = "$base$$i"
if (usedNames.add(suggestion)) return suggestion
i++
}
}
}
}
@@ -0,0 +1,90 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.FirLightClassForEnumEntry
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol
import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
internal class FirLightFieldForEnumEntry(
private val enumEntrySymbol: KtEnumEntrySymbol,
containingClass: FirLightClassForSymbol,
override val lightMemberOrigin: LightMemberOrigin?
) : FirLightField(containingClass, lightMemberOrigin), PsiEnumConstant {
private val _modifierList by lazyPub {
FirLightClassModifierList(
containingDeclaration = this@FirLightFieldForEnumEntry,
modifiers = setOf(PsiModifier.STATIC, PsiModifier.FINAL, PsiModifier.PUBLIC),
annotations = emptyList()
)
}
override fun getModifierList(): PsiModifierList = _modifierList
override val kotlinOrigin: KtEnumEntry? = enumEntrySymbol.psi as? KtEnumEntry
override fun isDeprecated(): Boolean = false
//TODO Make with KtSymbols
private val hasBody: Boolean get() = kotlinOrigin?.let { it.body != null } ?: true
private val _initializingClass: PsiEnumConstantInitializer? by lazyPub {
hasBody.ifTrue {
FirLightClassForEnumEntry(
enumEntrySymbol = enumEntrySymbol,
enumConstant = this@FirLightFieldForEnumEntry,
enumClass = containingClass,
manager = manager
)
}
}
override fun getInitializingClass(): PsiEnumConstantInitializer? = _initializingClass
override fun getOrCreateInitializingClass(): PsiEnumConstantInitializer =
_initializingClass ?: cannotModify()
override fun getArgumentList(): PsiExpressionList? = null
override fun resolveMethod(): PsiMethod? = null
override fun resolveConstructor(): PsiMethod? = null
override fun resolveMethodGenerics(): JavaResolveResult = JavaResolveResult.EMPTY
override fun hasInitializer() = true
override fun computeConstantValue(visitedVars: MutableSet<PsiVariable>?) = this
override fun getName(): String = enumEntrySymbol.name.asString()
private val _type: PsiType by lazyPub {
analyzeWithSymbolAsContext(enumEntrySymbol) {
enumEntrySymbol.annotatedType.type.asPsiType(this@FirLightFieldForEnumEntry)
}
}
override fun getType(): PsiType = _type
override fun getInitializer(): PsiExpression? = null
override fun hashCode(): Int = enumEntrySymbol.hashCode()
private val _identifier: PsiIdentifier by lazyPub {
FirLightIdentifier(this, enumEntrySymbol)
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
override fun isValid(): Boolean = super.isValid() && enumEntrySymbol.isValid()
override fun equals(other: Any?): Boolean =
other is FirLightFieldForEnumEntry &&
enumEntrySymbol == other.enumEntrySymbol
}
@@ -0,0 +1,67 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.psi.KtDeclaration
internal class FirLightFieldForObjectSymbol(
private val objectSymbol: KtNamedClassOrObjectSymbol,
containingClass: KtLightClass,
private val name: String,
lightMemberOrigin: LightMemberOrigin?,
) : FirLightField(containingClass, lightMemberOrigin) {
override val kotlinOrigin: KtDeclaration? = objectSymbol.psi as? KtDeclaration
override fun getName(): String = name
private val _modifierList: PsiModifierList by lazyPub {
val modifiers = setOf(objectSymbol.toPsiVisibilityForMember(isTopLevel = false), PsiModifier.STATIC, PsiModifier.FINAL)
val notNullAnnotation = FirLightSimpleAnnotation("org.jetbrains.annotations.NotNull", this)
FirLightClassModifierList(this, modifiers, listOf(notNullAnnotation))
}
private val _isDeprecated: Boolean by lazyPub {
objectSymbol.hasDeprecatedAnnotation()
}
override fun isDeprecated(): Boolean = _isDeprecated
override fun getModifierList(): PsiModifierList? = _modifierList
private val _type: PsiType by lazyPub {
analyzeWithSymbolAsContext(objectSymbol) {
objectSymbol.buildSelfClassType().asPsiType(this@FirLightFieldForObjectSymbol)
}
}
private val _identifier: PsiIdentifier by lazyPub {
FirLightIdentifier(this, objectSymbol)
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
override fun getType(): PsiType = _type
override fun getInitializer(): PsiExpression? = null //TODO
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightFieldForObjectSymbol &&
kotlinOrigin == other.kotlinOrigin &&
objectSymbol == other.objectSymbol)
override fun hashCode(): Int = kotlinOrigin.hashCode()
override fun isValid(): Boolean = super.isValid() && objectSymbol.isValid()
}
@@ -0,0 +1,117 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
import org.jetbrains.kotlin.psi.KtDeclaration
internal class FirLightFieldForPropertySymbol(
private val propertySymbol: KtPropertySymbol,
private val fieldName: String,
containingClass: FirLightClassBase,
lightMemberOrigin: LightMemberOrigin?,
isTopLevel: Boolean,
forceStatic: Boolean,
takePropertyVisibility: Boolean
) : FirLightField(containingClass, lightMemberOrigin) {
override val kotlinOrigin: KtDeclaration? = propertySymbol.psi as? KtDeclaration
private val _returnedType: PsiType by lazyPub {
analyzeWithSymbolAsContext(propertySymbol) {
propertySymbol.annotatedType.type.asPsiType(this@FirLightFieldForPropertySymbol)
}
}
private val _isDeprecated: Boolean by lazyPub {
propertySymbol.hasDeprecatedAnnotation(AnnotationUseSiteTarget.FIELD)
}
override fun isDeprecated(): Boolean = _isDeprecated
private val _identifier: PsiIdentifier by lazyPub {
FirLightIdentifier(this, propertySymbol)
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
override fun getType(): PsiType = _returnedType
override fun getName(): String = fieldName
private val _modifierList: PsiModifierList by lazyPub {
val modifiers = mutableSetOf<String>()
val suppressFinal = !propertySymbol.isVal
propertySymbol.computeModalityForMethod(
isTopLevel = isTopLevel,
suppressFinal = suppressFinal,
result = modifiers
)
if (forceStatic) {
modifiers.add(PsiModifier.STATIC)
}
val visibility =
if (takePropertyVisibility) propertySymbol.toPsiVisibilityForMember(isTopLevel = false) else PsiModifier.PRIVATE
modifiers.add(visibility)
if (!suppressFinal) {
modifiers.add(PsiModifier.FINAL)
}
if (propertySymbol.hasAnnotation("kotlin/jvm/Transient", null)) {
modifiers.add(PsiModifier.TRANSIENT)
}
if (propertySymbol.hasAnnotation("kotlin/jvm/Volatile", null)) {
modifiers.add(PsiModifier.VOLATILE)
}
val nullability = if (!(propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit)) {
analyzeWithSymbolAsContext(propertySymbol) {
getTypeNullability(propertySymbol.annotatedType.type)
}
} else NullabilityType.Unknown
val annotations = propertySymbol.computeAnnotations(
parent = this,
nullability = nullability,
annotationUseSiteTarget = AnnotationUseSiteTarget.FIELD,
)
FirLightClassModifierList(this, modifiers, annotations)
}
override fun getModifierList(): PsiModifierList = _modifierList
private val _initializer by lazyPub {
if (propertySymbol !is KtKotlinPropertySymbol) return@lazyPub null
if (!propertySymbol.isConst) return@lazyPub null
if (!propertySymbol.isVal) return@lazyPub null
(propertySymbol.initializer as? KtSimpleConstantValue<*>)?.createPsiLiteral(this)
}
override fun getInitializer(): PsiExpression? = _initializer
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightFieldForPropertySymbol &&
kotlinOrigin == other.kotlinOrigin &&
propertySymbol == other.propertySymbol)
override fun hashCode(): Int = kotlinOrigin.hashCode()
override fun isValid(): Boolean = super.isValid() && propertySymbol.isValid()
}
@@ -0,0 +1,204 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightMember
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.components.DefaultTypeClassIds
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithModality
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtTypeAndAnnotations
import org.jetbrains.kotlin.idea.frontend.api.types.*
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.SpecialNames
import java.util.*
internal fun <L : Any> L.invalidAccess(): Nothing =
error("Cls delegate shouldn't be accessed for fir light classes! Qualified name: ${javaClass.name}")
internal fun KtAnalysisSession.mapSuperType(
type: KtTypeAndAnnotations,
psiContext: PsiElement,
kotlinCollectionAsIs: Boolean = false
): PsiClassType? {
return mapSuperType(type.type, psiContext, kotlinCollectionAsIs)
}
internal fun KtAnalysisSession.mapSuperType(
type: KtType,
psiContext: PsiElement,
kotlinCollectionAsIs: Boolean = false
): PsiClassType? {
if (type !is KtNonErrorClassType) return null
val psiType = type.asPsiType(
psiContext,
if (kotlinCollectionAsIs) TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS else TypeMappingMode.SUPER_TYPE,
)
return psiType as? PsiClassType
}
internal enum class NullabilityType {
Nullable,
NotNull,
Unknown
}
//todo get rid of NullabilityType as it corresponds to KtTypeNullability
internal val KtType.nullabilityType: NullabilityType
get() = when (nullability) {
KtTypeNullability.NULLABLE -> NullabilityType.Nullable
KtTypeNullability.NON_NULLABLE -> NullabilityType.NotNull
KtTypeNullability.UNKNOWN -> NullabilityType.Unknown
}
internal fun KtSymbolWithModality.computeSimpleModality(): String? = when (modality) {
Modality.SEALED -> PsiModifier.ABSTRACT
Modality.FINAL -> PsiModifier.FINAL
Modality.ABSTRACT -> PsiModifier.ABSTRACT
Modality.OPEN -> null
}
internal fun KtSymbolWithModality.computeModalityForMethod(
isTopLevel: Boolean,
suppressFinal: Boolean,
result: MutableSet<String>
) {
require(this !is KtClassLikeSymbol)
computeSimpleModality()?.run {
if (this != PsiModifier.FINAL || !suppressFinal) {
result.add(this)
}
}
if (this is KtFunctionSymbol && isExternal) {
result.add(PsiModifier.NATIVE)
}
if (isTopLevel) {
result.add(PsiModifier.STATIC)
}
}
internal fun KtSymbolWithVisibility.toPsiVisibilityForMember(isTopLevel: Boolean): String =
visibility.toPsiVisibility(isTopLevel, forClass = false)
internal fun KtSymbolWithVisibility.toPsiVisibilityForClass(isTopLevel: Boolean): String =
visibility.toPsiVisibility(isTopLevel, forClass = true)
internal fun Visibility.toPsiVisibilityForMember(isTopLevel: Boolean): String =
toPsiVisibility(isTopLevel, forClass = false)
private fun Visibility.toPsiVisibility(isTopLevel: Boolean, forClass: Boolean): String = when (this) {
// Top-level private class has PACKAGE_LOCAL visibility in Java
// Nested private class has PRIVATE visibility
Visibilities.Private, Visibilities.PrivateToThis ->
if (forClass && isTopLevel) PsiModifier.PACKAGE_LOCAL else PsiModifier.PRIVATE
Visibilities.Protected -> PsiModifier.PROTECTED
else -> PsiModifier.PUBLIC
}
internal fun basicIsEquivalentTo(`this`: PsiElement?, that: PsiElement?): Boolean {
if (`this` == null || that == null) return false
if (`this` == that) return true
if (`this` !is KtLightElement<*, *>) return false
if (that !is KtLightElement<*, *>) return false
if (`this`.kotlinOrigin?.isEquivalentTo(that.kotlinOrigin) == true) return true
val thisMemberOrigin = (`this` as? KtLightMember<*>)?.lightMemberOrigin ?: return false
if (thisMemberOrigin.isEquivalentTo(that)) return true
val thatMemberOrigin = (that as? KtLightMember<*>)?.lightMemberOrigin ?: return false
return thisMemberOrigin.isEquivalentTo(thatMemberOrigin)
}
internal fun KtAnalysisSession.getTypeNullability(ktType: KtType): NullabilityType {
if (ktType.nullabilityType != NullabilityType.NotNull) return ktType.nullabilityType
if (ktType.isUnit) return NullabilityType.NotNull
if (ktType is KtTypeParameterType) {
// TODO Make supertype checking
// val subtypeOfNullableSuperType = context.firRef.withFir(phase) {
// it.session.typeCheckerContext.nullableAnyType().isSupertypeOf(it.session.typeCheckerContext, coneType)
// }
// if (!subtypeOfNullableSuperType) return NullabilityType.NotNull
return if (!ktType.isMarkedNullable) NullabilityType.Unknown else NullabilityType.NotNull
}
if (ktType !is KtClassType) return NullabilityType.NotNull
if (!ktType.isPrimitive) {
return ktType.nullabilityType
}
if (ktType !is KtNonErrorClassType) return NullabilityType.NotNull
if (ktType.typeArguments.any { it.type is KtClassErrorType }) return NullabilityType.NotNull
if (ktType.classId.shortClassName.asString() == SpecialNames.ANONYMOUS_STRING) return NullabilityType.NotNull
val canonicalSignature = ktType.mapTypeToJvmType().descriptor
if (canonicalSignature == "[L<error>;") return NullabilityType.NotNull
val isNotPrimitiveType = canonicalSignature.startsWith("L") || canonicalSignature.startsWith("[")
return if (isNotPrimitiveType) NullabilityType.NotNull else NullabilityType.Unknown
}
internal val KtType.isUnit get() = isClassTypeWithClassId(DefaultTypeClassIds.UNIT)
internal fun KtType.isClassTypeWithClassId(classId: ClassId): Boolean {
if (this !is KtNonErrorClassType) return false
return this.classId == classId
}
private fun escapeString(str: String): String = buildString {
str.forEach { char ->
val escaped = when (char) {
'\n' -> "\\n"
'\r' -> "\\r"
'\t' -> "\\t"
'\"' -> "\\\""
'\\' -> "\\\\"
else -> "$char"
}
append(escaped)
}
}
private fun KtSimpleConstantValue<*>.asStringForPsiLiteral(): String =
when (val value = this.value) {
is String -> "\"${escapeString(value)}\""
is Long -> "${value}L"
is Float -> "${value}f"
else -> value?.toString() ?: "null"
}
internal fun KtSimpleConstantValue<*>.createPsiLiteral(parent: PsiElement): PsiExpression? {
val asString = asStringForPsiLiteral()
val instance = PsiElementFactory.getInstance(parent.project)
return try {
instance.createExpressionFromText(asString, parent)
} catch (_: IncorrectOperationException) {
null
}
}
internal fun BitSet.copy(): BitSet = clone() as BitSet
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProvider
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.idea.frontend.api.tokens.hackyAllowRunningOnEdt
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
internal inline fun <E> allowLightClassesOnEdt(action: () -> E): E = hackyAllowRunningOnEdt(action)
@OptIn(InvalidWayOfUsingAnalysisSession::class)
internal inline fun <R> PsiElement.analyzeWithSymbolAsContext(
contextSymbol: KtSymbol,
action: KtAnalysisSession.() -> R
): R {
return project.analyzeWithSymbolAsContext(contextSymbol, action)
}
@OptIn(InvalidWayOfUsingAnalysisSession::class)
internal inline fun <R> Project.analyzeWithSymbolAsContext(
contextSymbol: KtSymbol,
action: KtAnalysisSession.() -> R
): R {
return KtAnalysisSessionProvider.getInstance(this).analyzeWithSymbolAsContext(contextSymbol, action)
}
@@ -0,0 +1,195 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightParameterListBuilder
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_FOR_GETTER
import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_FOR_SETTER
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertyAccessorSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertyGetterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySetterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.light.classes.symbol.parameters.FirLightSetterParameterForSymbol
import org.jetbrains.kotlin.load.java.JvmAbi.getterName
import org.jetbrains.kotlin.load.java.JvmAbi.setterName
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
internal class FirLightAccessorMethodForSymbol(
private val propertyAccessorSymbol: KtPropertyAccessorSymbol,
private val containingPropertySymbol: KtPropertySymbol,
lightMemberOrigin: LightMemberOrigin?,
containingClass: FirLightClassBase,
private val isTopLevel: Boolean,
) : FirLightMethod(
lightMemberOrigin,
containingClass,
if (propertyAccessorSymbol is KtPropertyGetterSymbol) METHOD_INDEX_FOR_GETTER else METHOD_INDEX_FOR_SETTER
) {
private val isGetter: Boolean get() = propertyAccessorSymbol is KtPropertyGetterSymbol
private fun String.abiName() =
if (isGetter) getterName(this) else setterName(this)
private val _name: String by lazyPub {
propertyAccessorSymbol.getJvmNameFromAnnotation() ?: run {
val defaultName = containingPropertySymbol.name.identifier.let {
if (containingClass.isAnnotationType) it else it.abiName()
}
containingPropertySymbol.computeJvmMethodName(defaultName, containingClass, accessorSite)
}
}
override fun getName(): String = _name
override fun hasTypeParameters(): Boolean = false
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
override fun isVarArgs(): Boolean = false
override val kotlinOrigin: KtDeclaration? =
(propertyAccessorSymbol.psi ?: containingPropertySymbol.psi) as? KtDeclaration
private val accessorSite
get() =
if (propertyAccessorSymbol is KtPropertyGetterSymbol) AnnotationUseSiteTarget.PROPERTY_GETTER
else AnnotationUseSiteTarget.PROPERTY_SETTER
//TODO Fix it when KtFirConstructorValueParameterSymbol be ready
private val isParameter: Boolean get() = containingPropertySymbol.psi.let { it == null || it is KtParameter }
private fun computeAnnotations(isPrivate: Boolean): List<PsiAnnotation> {
val nullabilityApplicable = isGetter &&
!isPrivate &&
!(isParameter && (containingClass.isAnnotationType || containingClass.isEnum))
val nullabilityType = if (nullabilityApplicable) {
analyzeWithSymbolAsContext(containingPropertySymbol) {
getTypeNullability(
containingPropertySymbol.annotatedType.type
)
}
} else NullabilityType.Unknown
val annotationsFromProperty = containingPropertySymbol.computeAnnotations(
parent = this,
nullability = nullabilityType,
annotationUseSiteTarget = accessorSite,
)
val annotationsFromAccessor = propertyAccessorSymbol.computeAnnotations(
parent = this,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
return annotationsFromProperty + annotationsFromAccessor
}
private fun computeModifiers(): Set<String> {
val isOverrideMethod = propertyAccessorSymbol.isOverride || containingPropertySymbol.isOverride
val isInterfaceMethod = containingClass.isInterface
val modifiers = mutableSetOf<String>()
containingPropertySymbol.computeModalityForMethod(
isTopLevel = isTopLevel,
suppressFinal = isOverrideMethod || isInterfaceMethod,
result = modifiers
)
val visibility = isOverrideMethod.ifTrue {
(containingClass as? FirLightClassForSymbol)
?.tryGetEffectiveVisibility(containingPropertySymbol)
?.toPsiVisibilityForMember(isTopLevel)
} ?: propertyAccessorSymbol.toPsiVisibilityForMember(isTopLevel)
modifiers.add(visibility)
if (containingPropertySymbol.hasJvmStaticAnnotation(accessorSite)) {
modifiers.add(PsiModifier.STATIC)
}
if (isInterfaceMethod) {
modifiers.add(PsiModifier.ABSTRACT)
}
return modifiers
}
private val _modifierList: PsiModifierList by lazyPub {
val modifiers = computeModifiers()
val annotations = computeAnnotations(modifiers.contains(PsiModifier.PRIVATE))
FirLightClassModifierList(this, modifiers, annotations)
}
override fun getModifierList(): PsiModifierList = _modifierList
override fun isConstructor(): Boolean = false
private val _isDeprecated: Boolean by lazyPub {
containingPropertySymbol.hasDeprecatedAnnotation(accessorSite)
}
override fun isDeprecated(): Boolean = _isDeprecated
private val _identifier: PsiIdentifier by lazyPub {
FirLightIdentifier(this, containingPropertySymbol)
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
private val _returnedType: PsiType? by lazyPub {
if (!isGetter) return@lazyPub PsiType.VOID
analyzeWithSymbolAsContext(containingPropertySymbol) {
containingPropertySymbol.annotatedType.type.asPsiType(this@FirLightAccessorMethodForSymbol)
}
}
override fun getReturnType(): PsiType? = _returnedType
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightAccessorMethodForSymbol &&
isGetter == other.isGetter &&
kotlinOrigin == other.kotlinOrigin &&
propertyAccessorSymbol == other.propertyAccessorSymbol)
override fun hashCode(): Int = kotlinOrigin.hashCode()
private val _parametersList by lazyPub {
val builder = LightParameterListBuilder(manager, language)
FirLightParameterForReceiver.tryGet(containingPropertySymbol, this)?.let {
builder.addParameter(it)
}
val propertyParameter = (propertyAccessorSymbol as? KtPropertySetterSymbol)?.parameter
if (propertyParameter != null) {
builder.addParameter(
FirLightSetterParameterForSymbol(
parameterSymbol = propertyParameter,
containingPropertySymbol = containingPropertySymbol,
containingMethod = this@FirLightAccessorMethodForSymbol
)
)
}
builder
}
override fun getParameterList(): PsiParameterList = _parametersList
override fun isValid(): Boolean = super.isValid() && propertyAccessorSymbol.isValid()
}
@@ -0,0 +1,66 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorSymbol
internal class FirLightConstructorForSymbol(
private val constructorSymbol: KtConstructorSymbol,
lightMemberOrigin: LightMemberOrigin?,
containingClass: FirLightClassBase,
methodIndex: Int,
) : FirLightMethodForSymbol(constructorSymbol, lightMemberOrigin, containingClass, methodIndex) {
private val _name: String? = containingClass.name
override fun getName(): String = _name ?: ""
override fun isConstructor(): Boolean = true
override fun hasTypeParameters(): Boolean = false
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
private val _annotations: List<PsiAnnotation> by lazyPub {
constructorSymbol.computeAnnotations(
parent = this,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
}
private val _isDeprecated: Boolean by lazyPub {
constructorSymbol.hasDeprecatedAnnotation()
}
override fun isDeprecated(): Boolean = _isDeprecated
private val _modifiers: Set<String> by lazyPub {
setOf(constructorSymbol.toPsiVisibilityForMember(isTopLevel = false))
}
private val _modifierList: PsiModifierList by lazyPub {
FirLightClassModifierList(this, _modifiers, _annotations)
}
override fun getModifierList(): PsiModifierList = _modifierList
override fun getReturnType(): PsiType? = null
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightConstructorForSymbol &&
kotlinOrigin == other.kotlinOrigin &&
constructorSymbol == other.constructorSymbol)
override fun hashCode(): Int = kotlinOrigin.hashCode()
override fun isValid(): Boolean = super.isValid() && constructorSymbol.isValid()
}
@@ -0,0 +1,104 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import com.intellij.psi.impl.PsiImplUtil
import com.intellij.psi.impl.PsiSuperMethodImplUtil
import com.intellij.psi.util.MethodSignature
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.KotlinLightReferenceListBuilder
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
internal abstract class FirLightMethod(
lightMemberOrigin: LightMemberOrigin?,
containingClass: KtLightClass,
private val methodIndex: Int
) : FirLightMemberImpl<PsiMethod>(lightMemberOrigin, containingClass), KtLightMethod {
override fun getBody(): PsiCodeBlock? = null
override fun getReturnTypeElement(): PsiTypeElement? = null
override fun setName(p0: String): PsiElement = cannotModify()
override fun isVarArgs() = PsiImplUtil.isVarArgs(this)
override fun getHierarchicalMethodSignature() = PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this)
override fun findSuperMethodSignaturesIncludingStatic(checkAccess: Boolean): List<MethodSignatureBackedByPsiMethod> =
PsiSuperMethodImplUtil.findSuperMethodSignaturesIncludingStatic(this, checkAccess)
override fun findDeepestSuperMethod() = PsiSuperMethodImplUtil.findDeepestSuperMethod(this)
override fun findDeepestSuperMethods(): Array<out PsiMethod> = PsiSuperMethodImplUtil.findDeepestSuperMethods(this)
override fun findSuperMethods(): Array<out PsiMethod> = PsiSuperMethodImplUtil.findSuperMethods(this)
override fun findSuperMethods(checkAccess: Boolean): Array<out PsiMethod> =
PsiSuperMethodImplUtil.findSuperMethods(this, checkAccess)
override fun findSuperMethods(parentClass: PsiClass?): Array<out PsiMethod> =
PsiSuperMethodImplUtil.findSuperMethods(this, parentClass)
override fun getSignature(substitutor: PsiSubstitutor): MethodSignature =
MethodSignatureBackedByPsiMethod.create(this, substitutor)
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
override fun accept(visitor: PsiElementVisitor) {
if (visitor is JavaElementVisitor) {
visitor.visitMethod(this)
} else {
visitor.visitElement(this)
}
}
override val isMangled: Boolean = false
abstract override fun getTypeParameters(): Array<PsiTypeParameter>
abstract override fun hasTypeParameters(): Boolean
abstract override fun getTypeParameterList(): PsiTypeParameterList?
override fun getThrowsList(): PsiReferenceList =
KotlinLightReferenceListBuilder(manager, language, PsiReferenceList.Role.THROWS_LIST) //TODO()
override fun getDefaultValue(): PsiAnnotationMemberValue? = null //TODO()
protected fun <T> T.computeJvmMethodName(
defaultName: String,
containingClass: FirLightClassBase,
annotationUseSiteTarget: AnnotationUseSiteTarget? = null
): String where T : KtAnnotatedSymbol, T : KtSymbolWithVisibility, T : KtCallableSymbol {
getJvmNameFromAnnotation(annotationUseSiteTarget)?.let { return it }
val effectiveVisibilityIfNotInternal = (visibility != Visibilities.Internal).ifTrue {
(containingClass as? FirLightClassForSymbol)?.tryGetEffectiveVisibility(this)
} ?: this.visibility
if (effectiveVisibilityIfNotInternal != Visibilities.Internal) return defaultName
//TODO
// val moduleName = module?.name ?: return defaultName
return defaultName
// if (hasPublishedApiAnnotation(annotationUseSiteTarget)) return defaultName
//
// return KotlinTypeMapper.InternalNameMapper.mangleInternalName(defaultName, moduleName)
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.PsiIdentifier
import com.intellij.psi.PsiParameterList
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.light.classes.symbol.parameters.FirLightParameterList
import org.jetbrains.kotlin.psi.KtDeclaration
import java.util.*
internal abstract class FirLightMethodForSymbol(
private val functionSymbol: KtFunctionLikeSymbol,
lightMemberOrigin: LightMemberOrigin?,
containingClass: FirLightClassBase,
methodIndex: Int,
argumentsSkipMask: BitSet? = null
) : FirLightMethod(
lightMemberOrigin,
containingClass,
methodIndex
) {
private var _isVarArgs: Boolean = functionSymbol.valueParameters.any { it.isVararg }
override fun isVarArgs(): Boolean = _isVarArgs
private val _parametersList by lazyPub {
FirLightParameterList(this, functionSymbol, argumentsSkipMask)
}
private val _identifier: PsiIdentifier by lazyPub {
FirLightIdentifier(this, functionSymbol)
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
override fun getParameterList(): PsiParameterList = _parametersList
override val kotlinOrigin: KtDeclaration? = functionSymbol.psi as? KtDeclaration
override fun isValid(): Boolean = super.isValid() && functionSymbol.isValid()
}
@@ -0,0 +1,145 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
import java.util.*
internal class FirLightSimpleMethodForSymbol(
private val functionSymbol: KtFunctionSymbol,
lightMemberOrigin: LightMemberOrigin?,
containingClass: FirLightClassBase,
methodIndex: Int,
private val isTopLevel: Boolean,
argumentsSkipMask: BitSet? = null,
private val suppressStatic: Boolean = false
) : FirLightMethodForSymbol(
functionSymbol = functionSymbol,
lightMemberOrigin = lightMemberOrigin,
containingClass = containingClass,
methodIndex = methodIndex,
argumentsSkipMask = argumentsSkipMask,
) {
private val _name: String by lazyPub {
functionSymbol.computeJvmMethodName(functionSymbol.name.asString(), containingClass)
}
override fun getName(): String = _name
private val _typeParameterList: PsiTypeParameterList? by lazyPub {
hasTypeParameters().ifTrue {
FirLightTypeParameterListForSymbol(
owner = this,
symbolWithTypeParameterList = functionSymbol,
innerShiftCount = 0
)
}
}
override fun hasTypeParameters(): Boolean =
functionSymbol.typeParameters.isNotEmpty()
override fun getTypeParameterList(): PsiTypeParameterList? = _typeParameterList
override fun getTypeParameters(): Array<PsiTypeParameter> =
_typeParameterList?.typeParameters ?: PsiTypeParameter.EMPTY_ARRAY
private fun computeAnnotations(isPrivate: Boolean): List<PsiAnnotation> {
val nullability = if (isVoidReturnType || isPrivate) {
NullabilityType.Unknown
} else {
analyzeWithSymbolAsContext(functionSymbol) {
getTypeNullability(
functionSymbol.annotatedType.type
)
}
}
return functionSymbol.computeAnnotations(
parent = this,
nullability = nullability,
annotationUseSiteTarget = null,
)
}
private fun computeModifiers(): Set<String> {
if (functionSymbol.hasInlineOnlyAnnotation()) return setOf(PsiModifier.FINAL, PsiModifier.PRIVATE)
val finalModifier = kotlinOrigin?.hasModifier(KtTokens.FINAL_KEYWORD) == true
val modifiers = mutableSetOf<String>()
functionSymbol.computeModalityForMethod(
isTopLevel = isTopLevel,
suppressFinal = !finalModifier && functionSymbol.isOverride,
result = modifiers
)
val visibility: String = functionSymbol.isOverride.ifTrue {
(containingClass as? FirLightClassForSymbol)
?.tryGetEffectiveVisibility(functionSymbol)
?.toPsiVisibilityForMember(isTopLevel)
} ?: functionSymbol.toPsiVisibilityForMember(isTopLevel = isTopLevel)
modifiers.add(visibility)
if (!suppressStatic && functionSymbol.hasJvmStaticAnnotation()) {
modifiers.add(PsiModifier.STATIC)
}
if (functionSymbol.hasAnnotation("kotlin/jvm/Strictfp", null)) {
modifiers.add(PsiModifier.STRICTFP)
}
if (functionSymbol.hasAnnotation("kotlin/jvm/Synchronized", null)) {
modifiers.add(PsiModifier.SYNCHRONIZED)
}
return modifiers
}
private val _isDeprecated: Boolean by lazyPub {
functionSymbol.hasDeprecatedAnnotation()
}
override fun isDeprecated(): Boolean = _isDeprecated
private val _modifierList: PsiModifierList by lazyPub {
val modifiers = computeModifiers()
val annotations = computeAnnotations(modifiers.contains(PsiModifier.PRIVATE))
FirLightClassModifierList(this, modifiers, annotations)
}
override fun getModifierList(): PsiModifierList = _modifierList
override fun isConstructor(): Boolean = false
private val isVoidReturnType: Boolean
get() = functionSymbol.annotatedType.type.run {
isUnit && nullabilityType != NullabilityType.Nullable
}
private val _returnedType: PsiType by lazyPub {
if (isVoidReturnType) return@lazyPub PsiType.VOID
analyzeWithSymbolAsContext(functionSymbol) {
functionSymbol.annotatedType.type.asPsiType(this@FirLightSimpleMethodForSymbol)
}
}
override fun getReturnType(): PsiType = _returnedType
override fun equals(other: Any?): Boolean =
this === other || (other is FirLightSimpleMethodForSymbol && functionSymbol == other.functionSymbol)
override fun hashCode(): Int = functionSymbol.hashCode()
override fun isValid(): Boolean = super.isValid() && functionSymbol.isValid()
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiModifierListOwner
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.psi.KtModifierListOwner
internal class FirLightClassModifierList<T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(
containingDeclaration: T,
private val modifiers: Set<String>,
private val annotations: List<PsiAnnotation>
) : FirLightModifierList<T>(containingDeclaration) {
override fun hasModifierProperty(name: String): Boolean = name in modifiers
override val givenAnnotations: List<KtLightAbstractAnnotation>?
get() = invalidAccess()
override fun getAnnotations(): Array<out PsiAnnotation> = annotations.toTypedArray()
override fun findAnnotation(qualifiedName: String) = annotations.firstOrNull { it.qualifiedName == qualifiedName }
override fun equals(other: Any?): Boolean = this === other
override fun hashCode(): Int = kotlinOrigin.hashCode()
}
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiModifierListOwner
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
import org.jetbrains.kotlin.psi.KtModifierList
import org.jetbrains.kotlin.psi.KtModifierListOwner
internal abstract class FirLightModifierList<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(
protected val owner: T
) : KtLightElementBase(owner), PsiModifierList, KtLightElement<KtModifierList, PsiModifierListOwner> {
override val clsDelegate: PsiModifierListOwner
get() = invalidAccess()
override val kotlinOrigin: KtModifierList?
get() = owner.kotlinOrigin?.modifierList
override fun getParent() = owner
override fun hasExplicitModifier(name: String) = hasModifierProperty(name)
override fun setModifierProperty(name: String, value: Boolean) = cannotModify()
override fun checkSetModifierProperty(name: String, value: Boolean) = throw IncorrectOperationException()
override fun addAnnotation(qualifiedName: String): PsiAnnotation = cannotModify()
override fun getApplicableAnnotations(): Array<out PsiAnnotation> = annotations
override fun getAnnotations(): Array<out PsiAnnotation> = emptyArray() //TODO()
override fun findAnnotation(qualifiedName: String): PsiAnnotation? = null //TODO()
override fun isEquivalentTo(another: PsiElement?) =
another is FirLightModifierList<*> && owner == another.owner
override fun isWritable() = false
override fun toString() = "Light modifier list of $owner"
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
}
@@ -0,0 +1,72 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.navigation.NavigationItem
import com.intellij.psi.*
import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.SearchScope
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.elements.*
import org.jetbrains.kotlin.psi.KtParameter
internal abstract class FirLightParameter(containingDeclaration: FirLightMethod) : PsiVariable, NavigationItem,
KtLightElement<KtParameter, PsiParameter>, KtLightParameter, KtLightElementBase(containingDeclaration) {
override val clsDelegate: PsiParameter
get() = invalidAccess()
override val givenAnnotations: List<KtLightAbstractAnnotation>
get() = invalidAccess()
override fun getTypeElement(): PsiTypeElement? = null
override fun getInitializer(): PsiExpression? = null
override fun hasInitializer(): Boolean = false
override fun computeConstantValue(): Any? = null
abstract override fun getNameIdentifier(): PsiIdentifier?
abstract override fun getName(): String
@Throws(IncorrectOperationException::class)
override fun normalizeDeclaration() {
}
override fun setName(p0: String): PsiElement = TODO() //cannotModify()
override val method: KtLightMethod = containingDeclaration
override fun getDeclarationScope(): KtLightMethod = method
override fun accept(visitor: PsiElementVisitor) {
if (visitor is JavaElementVisitor) {
visitor.visitParameter(this)
}
}
override fun toString(): String = "Fir Light Parameter $name"
override fun isEquivalentTo(another: PsiElement?): Boolean =
basicIsEquivalentTo(this, another as? PsiParameter)
override fun getNavigationElement(): PsiElement = kotlinOrigin ?: method.navigationElement
override fun getUseScope(): SearchScope = kotlinOrigin?.useScope ?: LocalSearchScope(this)
override fun isValid() = parent.isValid
abstract override fun getType(): PsiType
override fun getContainingFile(): PsiFile = method.containingFile
override fun getParent(): PsiElement = method.parameterList
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
abstract override fun isVarArgs(): Boolean
}
@@ -0,0 +1,62 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtValueParameterSymbol
import org.jetbrains.kotlin.psi.KtParameter
internal abstract class FirLightParameterBaseForSymbol(
private val parameterSymbol: KtValueParameterSymbol,
private val containingMethod: FirLightMethod
) : FirLightParameter(containingMethod) {
private val _name: String = parameterSymbol.name.asString()
override fun getName(): String = _name
override fun hasModifierProperty(name: String): Boolean =
modifierList.hasModifierProperty(name)
override val kotlinOrigin: KtParameter? = parameterSymbol.psi as? KtParameter
abstract override fun getModifierList(): PsiModifierList
private val _identifier: PsiIdentifier by lazyPub {
FirLightIdentifier(this, parameterSymbol)
}
protected val nullabilityType: NullabilityType
get() {
val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType || it.isEnum } &&
!containingMethod.hasModifierProperty(PsiModifier.PRIVATE)
return if (nullabilityApplicable) {
analyzeWithSymbolAsContext(parameterSymbol) {
getTypeNullability(
parameterSymbol.annotatedType.type
)
}
}
else NullabilityType.Unknown
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
private val _type by lazyPub {
val convertedType = analyzeWithSymbolAsContext(parameterSymbol) {
parameterSymbol.annotatedType.type.asPsiType(this@FirLightParameterBaseForSymbol)
}
if (convertedType is PsiArrayType && parameterSymbol.isVararg) {
PsiEllipsisType(convertedType.componentType, convertedType.annotationProvider)
} else convertedType
}
override fun getType(): PsiType = _type
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
}
@@ -0,0 +1,90 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiIdentifier
import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtTypeAndAnnotations
import org.jetbrains.kotlin.psi.KtParameter
internal class FirLightParameterForReceiver private constructor(
private val receiverTypeAndAnnotations: KtTypeAndAnnotations,
private val context: KtSymbol,
methodName: String,
method: FirLightMethod
) : FirLightParameter(method) {
companion object {
fun tryGet(
callableSymbol: KtCallableSymbol,
method: FirLightMethod
): FirLightParameterForReceiver? {
if (callableSymbol !is KtNamedSymbol) return null
if (!callableSymbol.isExtension) return null
val extensionTypeAndAnnotations = callableSymbol.receiverType ?: return null
return FirLightParameterForReceiver(
receiverTypeAndAnnotations = extensionTypeAndAnnotations,
context = callableSymbol,
methodName = callableSymbol.name.asString(),
method = method
)
}
}
private val _name: String by lazyPub {
AsmUtil.getLabeledThisName(methodName, AsmUtil.LABELED_THIS_PARAMETER, AsmUtil.RECEIVER_PARAMETER_NAME)
}
override fun getNameIdentifier(): PsiIdentifier? = null
override fun getName(): String = _name
override fun isVarArgs() = false
override fun hasModifierProperty(name: String): Boolean = false
override val kotlinOrigin: KtParameter? = null
private val _annotations: List<PsiAnnotation> by lazyPub {
receiverTypeAndAnnotations.annotations.map {
FirLightAnnotationForAnnotationCall(it, this)
}
}
override fun getModifierList(): PsiModifierList = _modifierList
private val _modifierList: PsiModifierList by lazyPub {
FirLightClassModifierList(this, emptySet(), _annotations)
}
private val _type: PsiType by lazyPub {
analyzeWithSymbolAsContext(context) {
receiverTypeAndAnnotations.type.asPsiType(this@FirLightParameterForReceiver)
}
}
override fun getType(): PsiType = _type
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightParameterForReceiver &&
receiverTypeAndAnnotations == other.receiverTypeAndAnnotations)
override fun hashCode(): Int = kotlinOrigin.hashCode()
override fun isValid(): Boolean = super.isValid() && context.isValid()
}
@@ -0,0 +1,53 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtValueParameterSymbol
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
internal class FirLightParameterForSymbol(
private val parameterSymbol: KtValueParameterSymbol,
containingMethod: FirLightMethod
) : FirLightParameterBaseForSymbol(parameterSymbol, containingMethod) {
private val isConstructorParameterSymbol = containingMethod.isConstructor
private val _annotations: List<PsiAnnotation> by lazyPub {
val annotationSite = isConstructorParameterSymbol.ifTrue {
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
}
val nullability = if (parameterSymbol.isVararg) NullabilityType.NotNull else super.nullabilityType
parameterSymbol.computeAnnotations(
parent = this,
nullability = nullability,
annotationUseSiteTarget = annotationSite,
includeAnnotationsWithoutSite = true
)
}
override fun getModifierList(): PsiModifierList = _modifierList
private val _modifierList: PsiModifierList by lazyPub {
FirLightClassModifierList(this, emptySet(), _annotations)
}
override fun isVarArgs() = parameterSymbol.isVararg
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightParameterForSymbol && parameterSymbol == other.parameterSymbol)
override fun hashCode(): Int = kotlinOrigin.hashCode()
override fun isValid(): Boolean = super.isValid() && parameterSymbol.isValid()
}
@@ -0,0 +1,68 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.parameters
import com.intellij.psi.PsiParameter
import com.intellij.psi.PsiParameterList
import com.intellij.psi.impl.light.LightParameterListBuilder
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.light.classes.symbol.FirLightMethod
import org.jetbrains.kotlin.light.classes.symbol.FirLightParameterForReceiver
import org.jetbrains.kotlin.light.classes.symbol.FirLightParameterForSymbol
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtParameterList
import java.util.*
internal class FirLightParameterList(
private val parent: FirLightMethod,
private val functionSymbol: KtFunctionLikeSymbol,
argumentsSkipMask: BitSet? = null
) : KtLightElement<KtParameterList, PsiParameterList>,
// With this, a parent chain is properly built: from FirLightParameter through FirLightParameterList to FirLightMethod
KtLightElementBase(parent),
// NB: we can't use delegation here, which will conflict getTextRange from KtLightElementBase
PsiParameterList {
override val kotlinOrigin: KtParameterList?
get() = (parent.kotlinOrigin as? KtFunction)?.valueParameterList
override val clsDelegate: PsiParameterList by lazyPub {
val builder = LightParameterListBuilder(manager, language)
FirLightParameterForReceiver.tryGet(functionSymbol, parent)?.let {
builder.addParameter(it)
}
functionSymbol.valueParameters.mapIndexed { index, parameter ->
val needToSkip = argumentsSkipMask?.get(index) == true
if (!needToSkip) {
builder.addParameter(
FirLightParameterForSymbol(
parameterSymbol = parameter,
containingMethod = parent
)
)
}
}
builder
}
override fun getParameters(): Array<PsiParameter> {
return clsDelegate.parameters
}
override fun getParameterIndex(p: PsiParameter): Int {
return clsDelegate.getParameterIndex(p)
}
override fun getParametersCount(): Int {
return clsDelegate.parametersCount
}
}
@@ -0,0 +1,54 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.parameters
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtValueParameterSymbol
import org.jetbrains.kotlin.light.classes.symbol.*
internal class FirLightSetterParameterForSymbol(
private val containingPropertySymbol: KtPropertySymbol,
private val parameterSymbol: KtValueParameterSymbol,
containingMethod: FirLightMethod
) : FirLightParameterBaseForSymbol(parameterSymbol, containingMethod) {
private val _annotations: List<PsiAnnotation> by lazyPub {
val annotationsFomSetter = parameterSymbol.computeAnnotations(
parent = this,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
val annotationsFromProperty = containingPropertySymbol.computeAnnotations(
parent = this,
nullability = nullabilityType,
annotationUseSiteTarget = AnnotationUseSiteTarget.SETTER_PARAMETER,
includeAnnotationsWithoutSite = false
)
annotationsFomSetter + annotationsFromProperty
}
override fun getModifierList(): PsiModifierList = _modifierList
private val _modifierList: PsiModifierList by lazyPub {
FirLightClassModifierList(this, emptySet(), _annotations)
}
override fun isVarArgs() = false
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightSetterParameterForSymbol && parameterSymbol == other.parameterSymbol)
override fun hashCode(): Int = kotlinOrigin.hashCode()
override fun isValid(): Boolean = super.isValid() && parameterSymbol.isValid()
}
@@ -0,0 +1,168 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.elements
import com.intellij.lang.Language
import com.intellij.openapi.util.Pair
import com.intellij.openapi.util.TextRange
import com.intellij.psi.*
import com.intellij.psi.impl.PsiClassImplUtil
import com.intellij.psi.impl.light.LightElement
import com.intellij.psi.javadoc.PsiDocComment
import com.intellij.psi.search.SearchScope
import org.jetbrains.kotlin.asJava.classes.KotlinSuperTypeListBuilder
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.frontend.api.isValid
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtNonErrorClassType
import org.jetbrains.kotlin.light.classes.symbol.*
import org.jetbrains.kotlin.light.classes.symbol.FirLightTypeParameterListForSymbol
import org.jetbrains.kotlin.light.classes.symbol.analyzeWithSymbolAsContext
import org.jetbrains.kotlin.light.classes.symbol.basicIsEquivalentTo
import org.jetbrains.kotlin.light.classes.symbol.invalidAccess
import org.jetbrains.kotlin.light.classes.symbol.mapSuperType
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.psiUtil.startOffset
internal class FirLightTypeParameter(
private val parent: FirLightTypeParameterListForSymbol,
private val index: Int,
private val typeParameterSymbol: KtTypeParameterSymbol
) : LightElement(parent.manager, KotlinLanguage.INSTANCE), PsiTypeParameter,
KtLightDeclaration<KtTypeParameter, PsiTypeParameter> {
override val clsDelegate: PsiTypeParameter get() = invalidAccess()
override val givenAnnotations: List<KtLightAbstractAnnotation>? get() = invalidAccess()
override val kotlinOrigin: KtTypeParameter? = typeParameterSymbol.psi as? KtTypeParameter
override fun copy(): PsiElement =
FirLightTypeParameter(parent, index, typeParameterSymbol)
override fun accept(visitor: PsiElementVisitor) {
if (visitor is JavaElementVisitor) {
visitor.visitTypeParameter(this)
} else {
super<LightElement>.accept(visitor)
}
}
private val _extendsList: PsiReferenceList by lazyPub {
val listBuilder = KotlinSuperTypeListBuilder(
kotlinOrigin = null,
manager = manager,
language = language,
role = PsiReferenceList.Role.EXTENDS_LIST
)
analyzeWithSymbolAsContext(typeParameterSymbol) {
typeParameterSymbol.upperBounds
.filterIsInstance<KtNonErrorClassType>()
.filter { it.classId != StandardClassIds.Any }
.mapNotNull {
mapSuperType(it, this@FirLightTypeParameter, kotlinCollectionAsIs = true)
}
.forEach { listBuilder.addReference(it) }
}
listBuilder
}
override fun getExtendsList(): PsiReferenceList = _extendsList
override fun getExtendsListTypes(): Array<PsiClassType> =
PsiClassImplUtil.getExtendsListTypes(this)
//PsiClass simple implementation
override fun getImplementsList(): PsiReferenceList? = null
override fun getImplementsListTypes(): Array<PsiClassType> = PsiClassType.EMPTY_ARRAY
override fun getSuperClass(): PsiClass? = null
override fun getInterfaces(): Array<PsiClass> = PsiClass.EMPTY_ARRAY
override fun getSupers(): Array<PsiClass> = PsiClass.EMPTY_ARRAY
override fun getSuperTypes(): Array<PsiClassType> = PsiClassType.EMPTY_ARRAY
override fun getConstructors(): Array<PsiMethod> = PsiMethod.EMPTY_ARRAY
override fun getInitializers(): Array<PsiClassInitializer> = PsiClassInitializer.EMPTY_ARRAY
override fun getAllFields(): Array<PsiField> = PsiField.EMPTY_ARRAY
override fun getAllMethods(): Array<PsiMethod> = PsiMethod.EMPTY_ARRAY
override fun getAllInnerClasses(): Array<PsiClass> = PsiClass.EMPTY_ARRAY
override fun findFieldByName(name: String?, checkBases: Boolean): PsiField? = null
override fun findMethodBySignature(patternMethod: PsiMethod?, checkBases: Boolean): PsiMethod? = null
override fun findMethodsBySignature(patternMethod: PsiMethod?, checkBases: Boolean): Array<PsiMethod> = PsiMethod.EMPTY_ARRAY
override fun findMethodsAndTheirSubstitutorsByName(name: String?, checkBases: Boolean)
: MutableList<Pair<PsiMethod, PsiSubstitutor>> = mutableListOf()
override fun getAllMethodsAndTheirSubstitutors()
: MutableList<Pair<PsiMethod, PsiSubstitutor>> = mutableListOf()
override fun findInnerClassByName(name: String?, checkBases: Boolean): PsiClass? = null
override fun getLBrace(): PsiElement? = null
override fun getRBrace(): PsiElement? = null
override fun getScope(): PsiElement = parent
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean = false
override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean = false
override fun getVisibleSignatures(): MutableCollection<HierarchicalMethodSignature> = mutableListOf()
override fun setName(name: String): PsiElement = cannotModify()
override fun getNameIdentifier(): PsiIdentifier? = null
override fun getModifierList(): PsiModifierList? = null
override fun hasModifierProperty(name: String): Boolean = false
override fun getOwner(): PsiTypeParameterListOwner? = parent.owner
override fun getParent(): PsiElement = parent
override fun getAnnotations(): Array<PsiAnnotation> = PsiAnnotation.EMPTY_ARRAY
override fun getContainingClass(): PsiClass? = null
override fun getDocComment(): PsiDocComment? = null
override fun isDeprecated(): Boolean = false
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
override fun hasTypeParameters(): Boolean = false
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getQualifiedName(): String? = null
override fun getMethods(): Array<PsiMethod> = PsiMethod.EMPTY_ARRAY
override fun findMethodsByName(name: String?, checkBases: Boolean): Array<PsiMethod> = PsiMethod.EMPTY_ARRAY
override fun getFields(): Array<PsiField> = PsiField.EMPTY_ARRAY
override fun getInnerClasses(): Array<PsiClass> = PsiClass.EMPTY_ARRAY
override fun isInterface(): Boolean = false
override fun isAnnotationType(): Boolean = false
override fun isEnum(): Boolean = false
override fun findAnnotation(qualifiedName: String): PsiAnnotation? = null
override fun addAnnotation(qualifiedName: String): PsiAnnotation = cannotModify()
//End of PsiClass simple implementation
override fun getText(): String = kotlinOrigin?.text ?: ""
override fun getName(): String? = typeParameterSymbol.name.asString()
override fun getIndex(): Int = index
override fun getApplicableAnnotations(): Array<PsiAnnotation> = PsiAnnotation.EMPTY_ARRAY //TODO
override fun toString(): String = "FirLightTypeParameter:$name"
override fun getNavigationElement(): PsiElement =
kotlinOrigin ?: parent.navigationElement
override fun getLanguage(): Language = KotlinLanguage.INSTANCE
override fun getUseScope(): SearchScope =
kotlinOrigin?.useScope ?: parent.useScope
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightTypeParameter && index == other.index && typeParameterSymbol == other.typeParameterSymbol)
override fun hashCode(): Int = typeParameterSymbol.hashCode() + index
override fun isEquivalentTo(another: PsiElement): Boolean =
basicIsEquivalentTo(this, another)
override fun getTextRange(): TextRange? = kotlinOrigin?.textRange
override fun getContainingFile(): PsiFile = parent.containingFile
override fun getTextOffset(): Int = kotlinOrigin?.startOffset ?: super.getTextOffset()
override fun getStartOffsetInParent(): Int = kotlinOrigin?.startOffsetInParent ?: super.getStartOffsetInParent()
override fun isValid(): Boolean = super.isValid() && typeParameterSymbol.isValid()
}