org.jetbrains.kotlin.fir.symbols.FirBasedSymbol.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.symbols
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirImplementationDetail
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.arguments
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.utils.exceptions.withFirSymbolIdEntry
import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
abstract class FirBasedSymbol : DeclarationSymbolMarker {
private var _fir: E? = null
@SymbolInternals
val fir: E
get() = _fir
?: errorWithAttachment("Fir is not initialized for ${this::class}") {
withFirSymbolIdEntry("symbol", this@FirBasedSymbol)
}
@FirImplementationDetail
fun bind(e: @UnsafeVariance E) {
_fir = e
}
val isBound: Boolean get() = _fir != null
val origin: FirDeclarationOrigin
get() = fir.origin
val source: KtSourceElement?
get() = fir.source
val moduleData: FirModuleData
get() = fir.moduleData
val annotations: List
get() = fir.annotations
val resolvedAnnotationsWithArguments: List
get() = fir.resolvedAnnotationsWithArguments(this)
val resolvedAnnotationsWithClassIds: List
get() = fir.resolvedAnnotationsWithClassIds(this)
val resolvedCompilerAnnotationsWithClassIds: List
get() = fir.resolvedCompilerRequiredAnnotations(this)
val resolvedAnnotationClassIds: List
get() = fir.resolvedAnnotationClassIds(this)
}
@SymbolInternals
fun FirAnnotationContainer.resolvedCompilerRequiredAnnotations(anchorElement: FirBasedSymbol<*>): List {
if (annotations.isEmpty()) return emptyList()
anchorElement.lazyResolveToPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
return annotations
}
@SymbolInternals
fun FirAnnotationContainer.resolvedAnnotationsWithArguments(anchorElement: FirBasedSymbol<*>): List {
if (isDefinitelyEmpty(anchorElement)) return emptyList()
annotations.resolveAnnotationsWithArguments(anchorElement)
// Note: this.annotations reference may be changed by the previous call!
return annotations
}
@SymbolInternals
fun List.resolveAnnotationsWithArguments(anchorElement: FirBasedSymbol<*>) {
/**
* This loop by index is required to avoid possible [ConcurrentModificationException],
* because the annotations might be in a process of resolve from some other threads
*/
var hasAnnotationCallWithArguments = false
for (i in indices) {
val currentAnnotation = get(i)
if (currentAnnotation is FirAnnotationCall && currentAnnotation.arguments.isNotEmpty()) {
hasAnnotationCallWithArguments = true
break
}
}
val phase = if (hasAnnotationCallWithArguments) {
FirResolvePhase.ANNOTATION_ARGUMENTS
} else {
FirResolvePhase.TYPES
}
anchorElement.lazyResolveToPhase(phase)
}
private fun FirAnnotationContainer.isDefinitelyEmpty(anchorElement: FirBasedSymbol<*>): Boolean {
if (annotations.isEmpty()) {
if (anchorElement !is FirBackingFieldSymbol) return true
if (anchorElement.propertySymbol.annotations.none { it.useSiteTarget == null }) return true
}
return false
}
@SymbolInternals
fun FirAnnotationContainer.resolvedAnnotationsWithClassIds(anchorElement: FirBasedSymbol<*>): List {
if (isDefinitelyEmpty(anchorElement)) return emptyList()
anchorElement.lazyResolveToPhase(FirResolvePhase.TYPES)
return annotations
}
@SymbolInternals
fun resolveAnnotationsWithClassIds(anchorElement: FirBasedSymbol<*>) {
anchorElement.lazyResolveToPhase(FirResolvePhase.TYPES)
}
@SymbolInternals
fun FirAnnotationContainer.resolvedAnnotationClassIds(anchorElement: FirBasedSymbol<*>): List {
return resolvedAnnotationsWithClassIds(anchorElement).mapNotNull {
(it.annotationTypeRef.coneType as? ConeClassLikeType)?.lookupTag?.classId
}
}
@RequiresOptIn
annotation class SymbolInternals