[ULC] Move UltraLightSupport to service provided bridge

This commit is contained in:
Igor Yakovlev
2020-05-21 17:08:26 +03:00
parent 7cb2631991
commit 55bb8f24e3
5 changed files with 172 additions and 52 deletions
@@ -27,10 +27,26 @@ import org.jetbrains.kotlin.asJava.builder.LightClassDataHolderImpl
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClassForFacade import org.jetbrains.kotlin.asJava.classes.KtUltraLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClassForScript import org.jetbrains.kotlin.asJava.classes.KtUltraLightClassForScript
import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.components.JavaDeprecationSettings
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.KotlinType
/** /**
* This class solves the problem of interdependency between analyzing Kotlin code and generating JetLightClasses * This class solves the problem of interdependency between analyzing Kotlin code and generating JetLightClasses
@@ -46,16 +62,85 @@ import org.jetbrains.kotlin.resolve.BindingContext
*/ */
class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) : LightClassGenerationSupport() { class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) : LightClassGenerationSupport() {
private val ultraLightSupport = object : KtUltraLightSupport {
private val languageVersionSettings: LanguageVersionSettings
get() = getContext().languageVersionSettings ?: LanguageVersionSettingsImpl.DEFAULT
override val isReleasedCoroutine
get() = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
override val moduleDescriptor get() = traceHolder.module
override val moduleName: String get() = JvmCodegenUtil.getModuleName(moduleDescriptor)
override val deprecationResolver: DeprecationResolver
get() = DeprecationResolver(
LockBasedStorageManager.NO_LOCKS,
languageVersionSettings,
CoroutineCompatibilitySupport.ENABLED,
JavaDeprecationSettings
)
override val typeMapper: KotlinTypeMapper by lazyPub {
KotlinTypeMapper(
BindingContext.EMPTY,
ClassBuilderMode.LIGHT_CLASSES,
moduleName,
languageVersionSettings,
jvmTarget = JvmTarget.JVM_1_8,
typePreprocessor = KotlinType::cleanFromAnonymousTypes,
namePreprocessor = ::tryGetPredefinedName
)
}
}
override fun createUltraLightClassForFacade( override fun createUltraLightClassForFacade(
manager: PsiManager, manager: PsiManager,
facadeClassFqName: FqName, facadeClassFqName: FqName,
lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>, lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>,
files: Collection<KtFile> files: Collection<KtFile>
): KtUltraLightClassForFacade? = null ): KtUltraLightClassForFacade? {
override fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass? = null if (files.any { it.isScript() }) return null
override fun createUltraLightClassForScript(script: KtScript): KtUltraLightClassForScript? = null val filesToSupports: List<Pair<KtFile, KtUltraLightSupport>> = files.map {
it to UltraLightSupportViaService(it)
}
return KtUltraLightClassForFacade(
manager,
facadeClassFqName,
lightClassDataCache,
files,
filesToSupports
)
}
override fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass? {
if (element.shouldNotBeVisibleAsLightClass()) {
return null
}
return UltraLightSupportViaService(element).let { support ->
when {
element is KtObjectDeclaration && element.isObjectLiteral() ->
KtUltraLightClassForAnonymousDeclaration(element, support)
element.safeIsLocal() ->
KtUltraLightClassForLocalDeclaration(element, support)
(element.hasModifier(KtTokens.INLINE_KEYWORD)) ->
KtUltraLightInlineClass(element, support)
else -> KtUltraLightClass(element, support)
}
}
}
override fun createUltraLightClassForScript(script: KtScript): KtUltraLightClassForScript? =
KtUltraLightClassForScript(script, support = UltraLightSupportViaService(script))
override fun getUltraLightClassSupport(element: KtElement): KtUltraLightSupport = ultraLightSupport
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass { override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
//force resolve companion for light class generation //force resolve companion for light class generation
@@ -51,6 +51,8 @@ abstract class LightClassGenerationSupport {
abstract fun createUltraLightClassForScript(script: KtScript): KtUltraLightClassForScript? abstract fun createUltraLightClassForScript(script: KtScript): KtUltraLightClassForScript?
abstract fun getUltraLightClassSupport(element: KtElement): KtUltraLightSupport
abstract fun createUltraLightClassForFacade( abstract fun createUltraLightClassForFacade(
manager: PsiManager, manager: PsiManager,
facadeClassFqName: FqName, facadeClassFqName: FqName,
@@ -6,22 +6,23 @@
package org.jetbrains.kotlin.asJava.classes package org.jetbrains.kotlin.asJava.classes
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtAnnotated import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import java.util.concurrent.ConcurrentMap
interface KtUltraLightSupport { interface KtUltraLightSupport {
val moduleName: String val moduleName: String
fun findAnnotation(owner: KtAnnotated, fqName: FqName): Pair<KtAnnotationEntry, AnnotationDescriptor>?
val deprecationResolver: DeprecationResolver val deprecationResolver: DeprecationResolver
val typeMapper: KotlinTypeMapper val typeMapper: KotlinTypeMapper
val moduleDescriptor: ModuleDescriptor val moduleDescriptor: ModuleDescriptor
val isReleasedCoroutine: Boolean val isReleasedCoroutine: Boolean
fun hasAlias(file: KtFile, shortName: Name?): Boolean = false
companion object { companion object {
// This property may be removed once IntelliJ versions earlier than 2018.3 become unsupported // This property may be removed once IntelliJ versions earlier than 2018.3 become unsupported
@@ -31,3 +32,24 @@ interface KtUltraLightSupport {
var forceUsingOldLightClasses = false var forceUsingOldLightClasses = false
} }
} }
class UltraLightSupportViaService(private val ktElement: KtElement) : KtUltraLightSupport {
private val serviceProvidedSupport: KtUltraLightSupport
get() = LightClassGenerationSupport.getInstance(ktElement.project).getUltraLightClassSupport(ktElement)
override val moduleName: String
get() = serviceProvidedSupport.moduleName
override val deprecationResolver: DeprecationResolver
get() = serviceProvidedSupport.deprecationResolver
override val typeMapper: KotlinTypeMapper
get() = serviceProvidedSupport.typeMapper
override val moduleDescriptor: ModuleDescriptor
get() = serviceProvidedSupport.moduleDescriptor
override val isReleasedCoroutine: Boolean
get() = serviceProvidedSupport.isReleasedCoroutine
}
@@ -16,9 +16,13 @@ import com.intellij.psi.impl.compiled.ClsTypeElementImpl
import com.intellij.psi.impl.compiled.SignatureParsing import com.intellij.psi.impl.compiled.SignatureParsing
import com.intellij.psi.impl.compiled.StubBuildingVisitor import com.intellij.psi.impl.compiled.StubBuildingVisitor
import com.intellij.psi.impl.light.* import com.intellij.psi.impl.light.*
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker
import com.intellij.psi.util.TypeConversionUtil import com.intellij.psi.util.TypeConversionUtil
import com.intellij.util.BitUtil.isSet import com.intellij.util.BitUtil.isSet
import com.intellij.util.IncorrectOperationException import com.intellij.util.IncorrectOperationException
import com.intellij.util.containers.ConcurrentFactoryMap
import com.intellij.util.containers.ContainerUtil import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.UltraLightClassModifierExtension import org.jetbrains.kotlin.asJava.UltraLightClassModifierExtension
@@ -36,11 +40,14 @@ import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
@@ -50,12 +57,14 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.replace import org.jetbrains.kotlin.types.replace
import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
import java.text.StringCharacterIterator import java.text.StringCharacterIterator
import java.util.concurrent.ConcurrentMap
private interface TypeParametersSupport<D, T> { private interface TypeParametersSupport<D, T> {
fun parameters(declaration: D): List<T> fun parameters(declaration: D): List<T>
@@ -72,7 +81,7 @@ private val supportForDescriptor = object : TypeParametersSupport<CallableMember
override fun hasNonTrivialBounds( override fun hasNonTrivialBounds(
declaration: CallableMemberDescriptor, declaration: CallableMemberDescriptor,
typeParameter: TypeParameterDescriptor typeParameter: TypeParameterDescriptor,
) = typeParameter.upperBounds.any { !KotlinBuiltIns.isDefaultBound(it) } ) = typeParameter.upperBounds.any { !KotlinBuiltIns.isDefaultBound(it) }
override fun asDescriptor(typeParameter: TypeParameterDescriptor) = typeParameter override fun asDescriptor(typeParameter: TypeParameterDescriptor) = typeParameter
@@ -86,7 +95,7 @@ private val supportForSourceDeclaration = object : TypeParametersSupport<KtTypeP
override fun hasNonTrivialBounds( override fun hasNonTrivialBounds(
declaration: KtTypeParameterListOwner, declaration: KtTypeParameterListOwner,
typeParameter: KtTypeParameter typeParameter: KtTypeParameter,
) = typeParameter.extendsBound != null || declaration.typeConstraints.isNotEmpty() ) = typeParameter.extendsBound != null || declaration.typeConstraints.isNotEmpty()
override fun asDescriptor(typeParameter: KtTypeParameter) = typeParameter.resolve() as? TypeParameterDescriptor override fun asDescriptor(typeParameter: KtTypeParameter) = typeParameter.resolve() as? TypeParameterDescriptor
@@ -95,21 +104,21 @@ private val supportForSourceDeclaration = object : TypeParametersSupport<KtTypeP
internal fun buildTypeParameterListForDescriptor( internal fun buildTypeParameterListForDescriptor(
declaration: CallableMemberDescriptor, declaration: CallableMemberDescriptor,
owner: PsiTypeParameterListOwner, owner: PsiTypeParameterListOwner,
support: KtUltraLightSupport support: KtUltraLightSupport,
): PsiTypeParameterList = buildTypeParameterList(declaration, owner, support, supportForDescriptor) ): PsiTypeParameterList = buildTypeParameterList(declaration, owner, support, supportForDescriptor)
internal fun buildTypeParameterListForSourceDeclaration( internal fun buildTypeParameterListForSourceDeclaration(
declaration: KtTypeParameterListOwner, declaration: KtTypeParameterListOwner,
owner: PsiTypeParameterListOwner, owner: PsiTypeParameterListOwner,
support: KtUltraLightSupport support: KtUltraLightSupport,
): PsiTypeParameterList = buildTypeParameterList(declaration, owner, support, supportForSourceDeclaration) ): PsiTypeParameterList = buildTypeParameterList(declaration, owner, support, supportForSourceDeclaration)
private fun <D, T> buildTypeParameterList( private fun <D, T> buildTypeParameterList(
declaration: D, declaration: D,
owner: PsiTypeParameterListOwner, owner: PsiTypeParameterListOwner,
support: KtUltraLightSupport, support: KtUltraLightSupport,
typeParametersSupport: TypeParametersSupport<D, T> typeParametersSupport: TypeParametersSupport<D, T>,
): PsiTypeParameterList { ): PsiTypeParameterList {
val tpList = KotlinLightTypeParameterListBuilder(owner) val tpList = KotlinLightTypeParameterListBuilder(owner)
@@ -152,19 +161,20 @@ internal fun KtDeclaration.getKotlinType(): KotlinType? {
internal fun KtDeclaration.resolve() = LightClassGenerationSupport.getInstance(project).resolveToDescriptor(this) internal fun KtDeclaration.resolve() = LightClassGenerationSupport.getInstance(project).resolveToDescriptor(this)
internal fun KtElement.analyze() = LightClassGenerationSupport.getInstance(project).analyze(this) internal fun KtElement.analyze() = LightClassGenerationSupport.getInstance(project).analyze(this)
internal fun KtAnnotationEntry.analyzeAnnotation() = LightClassGenerationSupport.getInstance(project).analyzeAnnotation(this)
// copy-pasted from kotlinInternalUastUtils.kt and post-processed // copy-pasted from kotlinInternalUastUtils.kt and post-processed
internal fun KotlinType.asPsiType( internal fun KotlinType.asPsiType(
support: KtUltraLightSupport, support: KtUltraLightSupport,
mode: TypeMappingMode, mode: TypeMappingMode,
psiContext: PsiElement psiContext: PsiElement,
): PsiType = support.mapType(psiContext) { typeMapper, signatureWriter -> ): PsiType = support.mapType(psiContext) { typeMapper, signatureWriter ->
typeMapper.mapType(this, signatureWriter, mode) typeMapper.mapType(this, signatureWriter, mode)
} }
internal fun KtUltraLightSupport.mapType( internal fun KtUltraLightSupport.mapType(
psiContext: PsiElement, psiContext: PsiElement,
mapTypeToSignatureWriter: (KotlinTypeMapper, JvmSignatureWriter) -> Unit mapTypeToSignatureWriter: (KotlinTypeMapper, JvmSignatureWriter) -> Unit,
): PsiType { ): PsiType {
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS) val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
mapTypeToSignatureWriter(typeMapper, signatureWriter) mapTypeToSignatureWriter(typeMapper, signatureWriter)
@@ -174,7 +184,7 @@ internal fun KtUltraLightSupport.mapType(
fun createTypeFromCanonicalText( fun createTypeFromCanonicalText(
canonicalSignature: String, canonicalSignature: String,
psiContext: PsiElement psiContext: PsiElement,
): PsiType { ): PsiType {
val signature = StringCharacterIterator(canonicalSignature) val signature = StringCharacterIterator(canonicalSignature)
@@ -231,7 +241,7 @@ fun KotlinType.cleanFromAnonymousTypes(): KotlinType? {
fun KtUltraLightClass.createGeneratedMethodFromDescriptor( fun KtUltraLightClass.createGeneratedMethodFromDescriptor(
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
declarationForOrigin: KtDeclaration? = null declarationForOrigin: KtDeclaration? = null,
): KtLightMethod { ): KtLightMethod {
val kotlinOrigin = val kotlinOrigin =
@@ -245,7 +255,7 @@ fun KtUltraLightClass.createGeneratedMethodFromDescriptor(
} }
private fun KtUltraLightClass.lightMethod( private fun KtUltraLightClass.lightMethod(
descriptor: FunctionDescriptor descriptor: FunctionDescriptor,
): LightMethodBuilder { ): LightMethodBuilder {
val name = if (descriptor is ConstructorDescriptor) name else support.typeMapper.mapFunctionName(descriptor, OwnerKind.IMPLEMENTATION) val name = if (descriptor is ConstructorDescriptor) name else support.typeMapper.mapFunctionName(descriptor, OwnerKind.IMPLEMENTATION)
@@ -264,7 +274,7 @@ private fun KtUltraLightClass.lightMethod(
LightParameterListBuilder(manager, language), LightParameterListBuilder(manager, language),
object : LightModifierList(manager, language) { object : LightModifierList(manager, language) {
override fun hasModifierProperty(name: String) = ModifierFlags.hasModifierProperty(name, accessFlags) override fun hasModifierProperty(name: String) = ModifierFlags.hasModifierProperty(name, accessFlags)
} },
) )
} }
@@ -425,7 +435,7 @@ private fun ConstantValue<*>.asStringForPsiLiteral(parent: PsiElement): String =
val arrayPart = "[]".repeat(value.arrayNestedness) val arrayPart = "[]".repeat(value.arrayNestedness)
val fqName = value.classId.asSingleFqName() val fqName = value.classId.asSingleFqName()
val canonicalText = psiType( val canonicalText = psiType(
fqName.asString(), parent, boxPrimitiveType = value.arrayNestedness > 0 fqName.asString(), parent, boxPrimitiveType = value.arrayNestedness > 0,
).let(TypeConversionUtil::erasure).getCanonicalText(false) ).let(TypeConversionUtil::erasure).getCanonicalText(false)
"$canonicalText$arrayPart.class" "$canonicalText$arrayPart.class"
@@ -479,3 +489,32 @@ inline fun KtFile.safeIsScript() = runReadAction { this.isScript() }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
inline fun KtFile.safeScript() = runReadAction { this.script } inline fun KtFile.safeScript() = runReadAction { this.script }
internal fun KtUltraLightSupport.findAnnotation(owner: KtAnnotated, fqName: FqName): Pair<KtAnnotationEntry, AnnotationDescriptor>? {
val candidates = owner.annotationEntries.filter {
it.shortName == fqName.shortName() || hasAlias(owner.containingKtFile, it.shortName)
}
for (entry in candidates) {
val descriptor = entry.analyzeAnnotation()
if (descriptor?.fqName == fqName) {
return Pair(entry, descriptor)
}
}
if (owner is KtPropertyAccessor) {
// We might have from the beginning just resolve the descriptor of the accessor
// But we trying to avoid analysis in case property doesn't have any relevant annotations at all
// (in case of `findAnnotation` returns null)
if (findAnnotation(owner.property, fqName) == null) return null
val accessorDescriptor = owner.resolve() ?: return null
// Just reuse the logic of use-site targeted annotation from the compiler
val annotationDescriptor = accessorDescriptor.annotations.findAnnotation(fqName) ?: return null
val entry = annotationDescriptor.source.getPsi() as? KtAnnotationEntry ?: return null
return entry to annotationDescriptor
}
return null
}
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import java.util.concurrent.ConcurrentMap import java.util.concurrent.ConcurrentMap
@@ -62,40 +61,10 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
JvmCodegenUtil.getModuleName(moduleDescriptor) JvmCodegenUtil.getModuleName(moduleDescriptor)
} }
override fun findAnnotation(owner: KtAnnotated, fqName: FqName): Pair<KtAnnotationEntry, AnnotationDescriptor>? {
val candidates = owner.annotationEntries.filter {
it.shortName == fqName.shortName() || owner.containingKtFile.hasAlias(it.shortName)
}
for (entry in candidates) {
val descriptor = analyzeAnnotation(entry)
if (descriptor?.fqName == fqName) {
return Pair(entry, descriptor)
}
}
if (owner is KtPropertyAccessor) {
// We might have from the beginning just resolve the descriptor of the accessor
// But we trying to avoid analysis in case property doesn't have any relevant annotations at all
// (in case of `findAnnotation` returns null)
if (findAnnotation(owner.property, fqName) == null) return null
val accessorDescriptor = owner.resolveToDescriptorIfAny() ?: return null
// Just reuse the logic of use-site targeted annotation from the compiler
val annotationDescriptor = accessorDescriptor.annotations.findAnnotation(fqName) ?: return null
val entry = annotationDescriptor.source.getPsi() as? KtAnnotationEntry ?: return null
return entry to annotationDescriptor
}
return null
}
@OptIn(FrontendInternals::class) @OptIn(FrontendInternals::class)
override val deprecationResolver: DeprecationResolver override val deprecationResolver: DeprecationResolver
get() = resolutionFacade.getFrontendService(DeprecationResolver::class.java) get() = resolutionFacade.getFrontendService(DeprecationResolver::class.java)
override val typeMapper: KotlinTypeMapper by lazyPub { override val typeMapper: KotlinTypeMapper by lazyPub {
KotlinTypeMapper( KotlinTypeMapper(
BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
@@ -153,6 +122,9 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
override fun createUltraLightClassForScript(script: KtScript): KtUltraLightClassForScript? = override fun createUltraLightClassForScript(script: KtScript): KtUltraLightClassForScript? =
KtUltraLightClassForScript(script, support = KtUltraLightSupportImpl(script)) KtUltraLightClassForScript(script, support = KtUltraLightSupportImpl(script))
override fun getUltraLightClassSupport(element: KtElement): KtUltraLightSupport =
KtUltraLightSupportImpl(element)
private fun KtFile.hasAlias(shortName: Name?): Boolean { private fun KtFile.hasAlias(shortName: Name?): Boolean {
if (shortName == null) return false if (shortName == null) return false
return allAliases(this)[shortName.asString()] == true return allAliases(this)[shortName.asString()] == true