Add first prototype of BindingContext implementation by FIR

Add ImportMemberIntention intention as a test.
In this commit all failed test were disabled, necessary fixes will be
added in the following commits
This commit is contained in:
Stanislav Erokhin
2021-05-07 14:40:52 +02:00
committed by teamcityserver
parent 6919f3dbb5
commit 7ac599520e
48 changed files with 1850 additions and 6 deletions
+2 -1
View File
@@ -850,7 +850,8 @@ tasks {
":idea:idea-frontend-api:test",
":idea:idea-frontend-fir:test",
":idea:idea-frontend-fir:idea-fir-low-level-api:test",
":plugins:uast-kotlin-fir:test"
":plugins:uast-kotlin-fir:test",
":idea:idea-fir-fe10-binding:test"
)
}
@@ -50,7 +50,7 @@ inline val FirCall.resolvedArgumentMapping: Map<FirExpression, FirValueParameter
else -> null
}
inline val FirCall.argumentMapping: Map<FirExpression, FirValueParameter>?
inline val FirCall.argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>?
get() = when (val argumentList = argumentList) {
is FirResolvedArgumentList -> argumentList.mapping
is FirPartiallyResolvedArgumentList -> argumentList.mapping
+1
View File
@@ -49,6 +49,7 @@ dependencies {
testCompile(projectTests(":idea:idea-fir-performance-tests"))
testCompile(projectTests(":idea:idea-frontend-fir"))
testCompile(projectTests(":idea:idea-frontend-fir:idea-fir-low-level-api"))
testCompile(projectTests(":idea:idea-fir-fe10-binding"))
testCompile(projectTests(":j2k"))
testCompile(projectTests(":nj2k"))
if (Ide.IJ()) {
@@ -109,10 +109,7 @@ import org.jetbrains.kotlin.idea.highlighter.*
import org.jetbrains.kotlin.idea.imports.AbstractJsOptimizeImportsTest
import org.jetbrains.kotlin.idea.imports.AbstractJvmOptimizeImportsTest
import org.jetbrains.kotlin.idea.index.AbstractKotlinTypeAliasByExpansionShortNameIndexTest
import org.jetbrains.kotlin.idea.inspections.AbstractHLInspectionTest
import org.jetbrains.kotlin.idea.inspections.AbstractHLLocalInspectionTest
import org.jetbrains.kotlin.idea.inspections.AbstractLocalInspectionTest
import org.jetbrains.kotlin.idea.inspections.AbstractMultiFileLocalInspectionTest
import org.jetbrains.kotlin.idea.inspections.*
import org.jetbrains.kotlin.idea.intentions.*
import org.jetbrains.kotlin.idea.intentions.declarations.AbstractJoinLinesTest
import org.jetbrains.kotlin.idea.internal.AbstractBytecodeToolWindowTest
@@ -1246,6 +1243,13 @@ fun main(args: Array<String>) {
}
}
testGroup("idea/idea-fir-fe10-binding/tests", "idea") {
testClass<AbstractFe10BindingIntentionTest> {
val pattern = "^([\\w\\-_]+)\\.(kt|kts)$"
model("testData/intentions/conventionNameCalls/replaceContains", pattern = pattern)
}
}
testGroup("idea/scripting-support/test", "idea/scripting-support/testData") {
testClass<AbstractScratchRunActionTest> {
model(
@@ -0,0 +1,33 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
implementation(project(":idea:idea-frontend-fir"))
testImplementation(projectTests(":idea:idea-fir"))
testImplementation(projectTests(":idea:idea-frontend-independent"))
testImplementation(intellijDep())
testImplementation(intellijCoreDep())
testImplementation(toolsJar())
}
sourceSets {
"main" { projectDefault() }
"test" { projectDefault() }
}
testsJar()
projectTest {
dependsOn(":dist")
workingDir = rootDir
val useFirIdeaPlugin = kotlinBuildProperties.useFirIdeaPlugin
doFirst {
if (!useFirIdeaPlugin) {
error("Test task in the module should be executed with -Pidea.fir.plugin=true")
}
}
}
@@ -0,0 +1,742 @@
/*
* 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.idea.fir.fe10
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AbstractReceiverParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.*
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.KtPureElement
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
/**
* List of known problems/not-implemented:
* - getOrigin return itself all the time. Formally it should return "unsubstituted" version of itself, but it isn't clear,
* if we really needed that nor how to implemented it. Btw, it is relevant only to member functions/properties (unlikely, but may be to
* inner classes) and not for "resulting descriptor". I.e. only class/interface type parameters could be substituted in FIR,
* there is no "resulting descriptor" and type arguments are passed together with the target function.
* - equals on descriptors and type constructors. It isn't clear what type of equality we should implement,
* will figure that later o real cases.
* See the functions below
*/
internal fun FE10BindingContext.containerDeclarationImplementationPostponed(): Nothing =
implementationPostponed("It isn't clear what we really need and how to implement it")
internal fun FE10BindingContext.typeAliasImplementationPlanned(): Nothing =
implementationPlanned("It is easy to implement, but it isn't first priority")
interface KtSymbolBasedNamed : Named {
val ktSymbol: KtNamedSymbol
override fun getName(): Name = ktSymbol.name
}
private fun Visibility.toDescriptorVisibility(): DescriptorVisibility =
when (this) {
Visibilities.Public -> DescriptorVisibilities.PUBLIC
Visibilities.Private -> DescriptorVisibilities.PRIVATE
Visibilities.PrivateToThis -> DescriptorVisibilities.PRIVATE_TO_THIS
Visibilities.Protected -> DescriptorVisibilities.PROTECTED
Visibilities.Internal -> DescriptorVisibilities.INTERNAL
Visibilities.Local -> DescriptorVisibilities.LOCAL
else -> error("Unknown visibility: $this")
}
private fun KtClassKind.toDescriptorKlassKind(): ClassKind =
when (this) {
KtClassKind.CLASS -> ClassKind.CLASS
KtClassKind.ENUM_CLASS -> ClassKind.ENUM_CLASS
KtClassKind.ENUM_ENTRY -> ClassKind.ENUM_ENTRY
KtClassKind.ANNOTATION_CLASS -> ClassKind.ANNOTATION_CLASS
KtClassKind.OBJECT, KtClassKind.COMPANION_OBJECT, KtClassKind.ANONYMOUS_OBJECT -> ClassKind.OBJECT
KtClassKind.INTERFACE -> ClassKind.INTERFACE
}
private fun KtConstantValue.toConstantValue(): ConstantValue<*> =
when (this) {
KtUnsupportedConstantValue -> ErrorValue.create("Error value for KtUnsupportedConstantValue")
is KtSimpleConstantValue<*> -> when (constantValueKind) {
ConstantValueKind.Null -> NullValue()
ConstantValueKind.Boolean -> BooleanValue(value as Boolean)
ConstantValueKind.Char -> CharValue(value as Char)
ConstantValueKind.Byte -> ByteValue(value as Byte)
ConstantValueKind.Short -> ShortValue(value as Short)
ConstantValueKind.Int -> IntValue(value as Int)
ConstantValueKind.Long -> LongValue(value as Long)
ConstantValueKind.String -> StringValue(value as String)
ConstantValueKind.Float -> FloatValue(value as Float)
ConstantValueKind.Double -> DoubleValue(value as Double)
ConstantValueKind.UnsignedByte -> UByteValue(value as Byte)
ConstantValueKind.UnsignedShort -> UShortValue(value as Short)
ConstantValueKind.UnsignedInt -> UIntValue(value as Int)
ConstantValueKind.UnsignedLong -> ULongValue(value as Long)
else -> error("Unexpected constant KtSimpleConstantValue: $value (class: ${value?.javaClass}")
}
}
abstract class KtSymbolBasedDeclarationDescriptor(val context: FE10BindingContext) : DeclarationDescriptorWithSource {
abstract val ktSymbol: KtSymbol
override val annotations: Annotations
get() {
val ktAnnotations = (ktSymbol as? KtAnnotatedSymbol)?.annotations ?: return Annotations.EMPTY
return Annotations.create(ktAnnotations.map { KtSymbolBasedAnnotationDescriptor(it, context) })
}
override fun getSource(): SourceElement = ktSymbol.psi.safeAs<KtPureElement>().toSourceElement()
override fun getContainingDeclaration(): DeclarationDescriptor {
if (ktSymbol !is KtSymbolWithKind) error("ContainingDeclaration should be overriden")
val containerSymbol = context.withAnalysisSession {
(ktSymbol as KtSymbolWithKind).getContainingSymbol()
}
if (containerSymbol != null)
return containerSymbol.toDeclarationDescriptor(context)
// i.e. declaration is top-level
return KtSymbolBasedPackageFragmentDescriptor(getPackageFqNameIfTopLevel(), context)
}
protected abstract fun getPackageFqNameIfTopLevel(): FqName
private fun KtSymbol.toSignature(): IdSignature = context.ktAnalysisSessionFacade.toSignature(this)
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is KtSymbolBasedDeclarationDescriptor) return false
ktSymbol.psi?.let {
return other.ktSymbol.psi == it
}
return ktSymbol.toSignature() == other.ktSymbol.toSignature()
}
override fun hashCode(): Int {
ktSymbol.psi?.let { return it.hashCode() }
return ktSymbol.toSignature().hashCode()
}
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>?, data: D): R = noImplementation()
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>?): Unit = noImplementation()
// stub for automatic Substitutable<T> implementation for all relevant subclasses
fun substitute(substitutor: TypeSubstitutor): Nothing = noImplementation()
protected fun noImplementation(): Nothing = context.noImplementation("ktSymbol = $ktSymbol")
protected fun implementationPostponed(): Nothing = context.implementationPostponed("ktSymbol = $ktSymbol")
protected fun implementationPlanned(): Nothing = context.implementationPlanned("ktSymbol = $ktSymbol")
}
class KtSymbolBasedAnnotationDescriptor(
private val ktAnnotationCall: KtAnnotationCall,
val context: FE10BindingContext
) : AnnotationDescriptor {
override val type: KotlinType
get() = context.implementationPlanned("ktAnnotationCall = $ktAnnotationCall")
override val fqName: FqName?
get() = ktAnnotationCall.classId?.asSingleFqName()
override val allValueArguments: Map<Name, ConstantValue<*>> =
ktAnnotationCall.arguments.associate { Name.identifier(it.name) to it.expression.toConstantValue() }
override val source: SourceElement
get() = ktAnnotationCall.psi.toSourceElement()
}
class KtSymbolBasedClassDescriptor(override val ktSymbol: KtNamedClassOrObjectSymbol, context: FE10BindingContext) :
KtSymbolBasedDeclarationDescriptor(context), KtSymbolBasedNamed, ClassDescriptor {
override fun isInner(): Boolean = ktSymbol.isInner
override fun isCompanionObject(): Boolean = ktSymbol.classKind == KtClassKind.COMPANION_OBJECT
override fun isData(): Boolean = ktSymbol.isData
override fun isInline(): Boolean = ktSymbol.isInline // seems like th`is `flag should be removed in favor of isValue
override fun isValue(): Boolean = ktSymbol.isInline
override fun isFun(): Boolean = ktSymbol.isFun
override fun isExpect(): Boolean = implementationPostponed()
override fun isActual(): Boolean = implementationPostponed()
override fun isExternal(): Boolean = ktSymbol.isExternal
override fun getVisibility(): DescriptorVisibility = ktSymbol.visibility.toDescriptorVisibility()
override fun getModality(): Modality = ktSymbol.modality
override fun getKind(): ClassKind = ktSymbol.classKind.toDescriptorKlassKind()
override fun getCompanionObjectDescriptor(): ClassDescriptor? = ktSymbol.companionObject?.let {
KtSymbolBasedClassDescriptor(it, context)
}
override fun getTypeConstructor(): TypeConstructor = KtSymbolBasedClassTypeConstructor(this)
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> = getTypeParameters(ktSymbol)
override fun getDefaultType(): SimpleType {
val arguments = TypeUtils.getDefaultTypeProjections(typeConstructor.parameters)
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.EMPTY, typeConstructor, arguments, false,
MemberScopeForKtSymbolBasedDescriptors { "ktSymbol = $ktSymbol" }
)
}
override fun getThisAsReceiverParameter(): ReceiverParameterDescriptor =
ReceiverParameterDescriptorImpl(this, ImplicitClassReceiver(this), Annotations.EMPTY)
override fun getOriginal(): ClassDescriptor = this
override fun getUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor? = context.withAnalysisSession {
ktSymbol.getDeclaredMemberScope().getConstructors().firstOrNull { it.isPrimary }
?.let { KtSymbolBasedConstructorDescriptor(it, this@KtSymbolBasedClassDescriptor) }
}
@OptIn(ExperimentalStdlibApi::class)
override fun getConstructors(): Collection<ClassConstructorDescriptor> = context.withAnalysisSession {
ktSymbol.getDeclaredMemberScope().getConstructors().map {
KtSymbolBasedConstructorDescriptor(it, this@KtSymbolBasedClassDescriptor)
}.toList()
}
override fun getPackageFqNameIfTopLevel(): FqName = (ktSymbol.classIdIfNonLocal ?: error("should be top-level")).packageFqName
override fun getSealedSubclasses(): Collection<ClassDescriptor> = implementationPostponed()
override fun getMemberScope(typeArguments: MutableList<out TypeProjection>): MemberScope = noImplementation()
override fun getMemberScope(typeSubstitution: TypeSubstitution): MemberScope = noImplementation()
override fun getUnsubstitutedMemberScope(): MemberScope = noImplementation()
override fun getUnsubstitutedInnerClassesScope(): MemberScope = noImplementation()
override fun getStaticScope(): MemberScope = noImplementation()
override fun isDefinitelyNotSamInterface(): Boolean = noImplementation()
override fun getDefaultFunctionTypeForSamInterface(): SimpleType = noImplementation()
}
class KtSymbolBasedTypeParameterDescriptor(
override val ktSymbol: KtTypeParameterSymbol, context: FE10BindingContext
) : KtSymbolBasedDeclarationDescriptor(context), KtSymbolBasedNamed, TypeParameterDescriptor {
override fun isReified(): Boolean = ktSymbol.isReified
override fun getVariance(): Variance = ktSymbol.variance
override fun getTypeConstructor(): TypeConstructor = KtSymbolBasedTypeParameterTypeConstructor(this)
override fun getDefaultType(): SimpleType =
KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.EMPTY, typeConstructor, emptyList(), false,
MemberScopeForKtSymbolBasedDescriptors { "ktSymbol = $ktSymbol" }
)
override fun getUpperBounds(): List<KotlinType> = ktSymbol.upperBounds.map { it.toKotlinType(context) }
override fun getOriginal(): TypeParameterDescriptor = this
override fun getContainingDeclaration(): DeclarationDescriptor = context.containerDeclarationImplementationPostponed()
override fun getPackageFqNameIfTopLevel(): FqName = error("Should be called")
// there is no such thing in FIR, and it seems like it isn't really needed for IDE and could be bypassed on client site
override fun getIndex(): Int = implementationPostponed()
override fun isCapturedFromOuterDeclaration(): Boolean = noImplementation()
override fun getStorageManager(): StorageManager = noImplementation()
}
abstract class KtSymbolBasedFunctionLikeDescriptor(context: FE10BindingContext) :
KtSymbolBasedDeclarationDescriptor(context), FunctionDescriptor {
abstract override val ktSymbol: KtFunctionLikeSymbol
override fun getReturnType(): KotlinType = ktSymbol.annotatedType.toKotlinType(context)
override fun getValueParameters(): List<ValueParameterDescriptor> = ktSymbol.valueParameters.mapIndexed { index, it ->
KtSymbolBasedValueParameterDescriptor(it, context,this, index)
}
override fun hasStableParameterNames(): Boolean = implementationPostponed()
override fun hasSynthesizedParameterNames(): Boolean = implementationPostponed()
override fun getKind(): CallableMemberDescriptor.Kind = implementationPostponed()
override fun <V : Any?> getUserData(key: CallableDescriptor.UserDataKey<V>?): V? = null
override fun getOriginal(): FunctionDescriptor = this
override fun isHiddenForResolutionEverywhereBesideSupercalls(): Boolean = implementationPostponed()
override fun getInitialSignatureDescriptor(): FunctionDescriptor? = noImplementation()
override fun isHiddenToOvercomeSignatureClash(): Boolean = noImplementation()
override fun setOverriddenDescriptors(overriddenDescriptors: MutableCollection<out CallableMemberDescriptor>) = noImplementation()
override fun newCopyBuilder(): FunctionDescriptor.CopyBuilder<out FunctionDescriptor> = noImplementation()
override fun copy(
newOwner: DeclarationDescriptor?,
modality: Modality?,
visibility: DescriptorVisibility?,
kind: CallableMemberDescriptor.Kind?,
copyOverrides: Boolean
): FunctionDescriptor = noImplementation()
}
class KtSymbolBasedFunctionDescriptor(override val ktSymbol: KtFunctionSymbol, context: FE10BindingContext) :
KtSymbolBasedFunctionLikeDescriptor(context),
SimpleFunctionDescriptor,
KtSymbolBasedNamed {
override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? = getExtensionReceiverParameter(ktSymbol)
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = getDispatchReceiverParameter(ktSymbol)
override fun getPackageFqNameIfTopLevel(): FqName = (ktSymbol.callableIdIfNonLocal ?: error("should be top-level")).packageName
override fun isSuspend(): Boolean = ktSymbol.isSuspend
override fun isOperator(): Boolean = ktSymbol.isOperator
override fun isExternal(): Boolean = ktSymbol.isExternal
override fun isInline(): Boolean = ktSymbol.isInline
override fun isInfix(): Boolean = implementationPostponed()
override fun isTailrec(): Boolean = implementationPostponed()
override fun isExpect(): Boolean = context.incorrectImplementation { false }
override fun isActual(): Boolean = context.incorrectImplementation { false }
override fun getVisibility(): DescriptorVisibility = ktSymbol.visibility.toDescriptorVisibility()
override fun getModality(): Modality = ktSymbol.modality
override fun getTypeParameters(): List<TypeParameterDescriptor> = getTypeParameters(ktSymbol)
override fun getOverriddenDescriptors(): Collection<FunctionDescriptor> {
val overriddenKtSymbols = context.withAnalysisSession {
ktSymbol.getAllOverriddenSymbols()
}
return overriddenKtSymbols.map { KtSymbolBasedFunctionDescriptor(it as KtFunctionSymbol, context) }
}
override fun copy(
newOwner: DeclarationDescriptor?,
modality: Modality?,
visibility: DescriptorVisibility?,
kind: CallableMemberDescriptor.Kind?,
copyOverrides: Boolean
): SimpleFunctionDescriptor = context.noImplementation()
override fun getOriginal(): SimpleFunctionDescriptor = context.incorrectImplementation { this }
override fun newCopyBuilder(): FunctionDescriptor.CopyBuilder<out SimpleFunctionDescriptor> =
context.noImplementation()
}
class KtSymbolBasedConstructorDescriptor(
override val ktSymbol: KtConstructorSymbol,
private val ktSBClassDescriptor: KtSymbolBasedClassDescriptor
) : KtSymbolBasedFunctionLikeDescriptor(ktSBClassDescriptor.context),
ClassConstructorDescriptor {
override fun getName(): Name = Name.special("<init>")
override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? = null
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = getDispatchReceiverParameter(ktSymbol)
override fun getConstructedClass(): ClassDescriptor = ktSBClassDescriptor
override fun getContainingDeclaration(): ClassDescriptor = ktSBClassDescriptor
override fun getPackageFqNameIfTopLevel(): FqName = error("should not be called")
override fun isPrimary(): Boolean = ktSymbol.isPrimary
override fun getReturnType(): KotlinType = ktSBClassDescriptor.defaultType
override fun isSuspend(): Boolean = false
override fun isOperator(): Boolean = false
override fun isExternal(): Boolean = false
override fun isInline(): Boolean = false
override fun isInfix(): Boolean = false
override fun isTailrec(): Boolean = false
override fun isExpect(): Boolean = implementationPostponed()
override fun isActual(): Boolean = implementationPostponed()
override fun getVisibility(): DescriptorVisibility = ktSymbol.visibility.toDescriptorVisibility()
override fun getModality(): Modality = Modality.FINAL
override fun getTypeParameters(): List<TypeParameterDescriptor> = getTypeParameters(ktSymbol)
override fun getOriginal(): ClassConstructorDescriptor = this
override fun getOverriddenDescriptors(): Collection<FunctionDescriptor> = emptyList()
override fun copy(
newOwner: DeclarationDescriptor,
modality: Modality,
visibility: DescriptorVisibility,
kind: CallableMemberDescriptor.Kind,
copyOverrides: Boolean
): ClassConstructorDescriptor = noImplementation()
}
class KtSymbolBasedAnonymousFunctionDescriptor(
override val ktSymbol: KtAnonymousFunctionSymbol,
context: FE10BindingContext
) : KtSymbolBasedFunctionLikeDescriptor(context), SimpleFunctionDescriptor {
override fun getName(): Name = SpecialNames.ANONYMOUS_FUNCTION
override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? = getExtensionReceiverParameter(ktSymbol)
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null
override fun getPackageFqNameIfTopLevel(): FqName = error("Impossible to be a top-level declaration")
override fun isOperator(): Boolean = false
override fun isExternal(): Boolean = false
override fun isInline(): Boolean = false
override fun isInfix(): Boolean = false
override fun isTailrec(): Boolean = false
override fun isExpect(): Boolean = false
override fun isActual(): Boolean = false
override fun getVisibility(): DescriptorVisibility = DescriptorVisibilities.LOCAL
override fun getModality(): Modality = Modality.FINAL
override fun getTypeParameters(): List<TypeParameterDescriptor> = emptyList()
// it doesn't seems like isSuspend are used in FIR for anonymous functions, but it used in FIR2IR so if we really need that
// we could implement that later
override fun isSuspend(): Boolean = implementationPostponed()
override fun getOverriddenDescriptors(): Collection<FunctionDescriptor> = emptyList()
override fun copy(
newOwner: DeclarationDescriptor?,
modality: Modality?,
visibility: DescriptorVisibility?,
kind: CallableMemberDescriptor.Kind?,
copyOverrides: Boolean
): SimpleFunctionDescriptor = noImplementation()
override fun getOriginal(): SimpleFunctionDescriptor = this
override fun newCopyBuilder(): FunctionDescriptor.CopyBuilder<out SimpleFunctionDescriptor> = noImplementation()
}
private fun KtSymbolBasedDeclarationDescriptor.getDispatchReceiverParameter(ktSymbol: KtPossibleMemberSymbol): ReceiverParameterDescriptor? {
val ktDispatchTypeAndAnnotations = ktSymbol.dispatchType ?: return null
return KtSymbolStubDispatchReceiverParameterDescriptor(ktDispatchTypeAndAnnotations, context)
}
private fun <T> T.getExtensionReceiverParameter(
ktSymbol: KtPossibleExtensionSymbol
): ReceiverParameterDescriptor? where T : KtSymbolBasedDeclarationDescriptor, T : CallableDescriptor {
val receiverTypeAndAnnotation = ktSymbol.receiverType ?: return null
val receiverValue = ExtensionReceiver(this, receiverTypeAndAnnotation.type.toKotlinType(context), null)
return ReceiverParameterDescriptorImpl(this, receiverValue, receiverTypeAndAnnotation.getDescriptorsAnnotations(context))
}
private fun KtSymbolBasedDeclarationDescriptor.getTypeParameters(ktSymbol: KtSymbolWithTypeParameters) =
ktSymbol.typeParameters.map { KtSymbolBasedTypeParameterDescriptor(it, context) }
private class KtSymbolBasedReceiverValue(val ktType: KtType, val context: FE10BindingContext) : ReceiverValue {
override fun getType(): KotlinType = ktType.toKotlinType(context)
override fun replaceType(newType: KotlinType): ReceiverValue = context.noImplementation("Should be called from IDE")
override fun getOriginal(): ReceiverValue = this
}
// Don't think that annotation is important here, because containingDeclaration used way more then annotation and they are not supported here
private class KtSymbolStubDispatchReceiverParameterDescriptor(
val receiverType: KtType,
val context: FE10BindingContext
) : AbstractReceiverParameterDescriptor(Annotations.EMPTY) {
override fun getContainingDeclaration(): DeclarationDescriptor = context.containerDeclarationImplementationPostponed()
override fun getValue(): ReceiverValue = KtSymbolBasedReceiverValue(receiverType, context)
override fun copy(newOwner: DeclarationDescriptor): ReceiverParameterDescriptor =
context.noImplementation("Copy should be called from IDE code")
}
class KtSymbolBasedValueParameterDescriptor(
override val ktSymbol: KtValueParameterSymbol,
context: FE10BindingContext,
val containingDeclaration: KtSymbolBasedFunctionLikeDescriptor,
index: Int = -1,
) : KtSymbolBasedDeclarationDescriptor(context), KtSymbolBasedNamed, ValueParameterDescriptor {
override val index: Int
init {
if (index != -1) {
this.index = index
} else {
val containerSymbol = containingDeclaration.ktSymbol
this.index = containerSymbol.valueParameters.indexOfFirst {
it === ktSymbol
}
check(this.index != -1) {
"Parameter not found in container symbol = $containerSymbol"
}
}
}
override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? = null
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null
override fun getTypeParameters(): List<TypeParameterDescriptor> = emptyList()
override fun getReturnType(): KotlinType = ktSymbol.annotatedType.toKotlinType(context)
override fun getValueParameters(): List<ValueParameterDescriptor> = emptyList()
override fun hasStableParameterNames(): Boolean = false
override fun hasSynthesizedParameterNames(): Boolean = false
override fun <V : Any?> getUserData(key: CallableDescriptor.UserDataKey<V>?): V? = null
override fun getVisibility(): DescriptorVisibility = DescriptorVisibilities.LOCAL
override fun getType(): KotlinType = ktSymbol.annotatedType.toKotlinType(context)
override fun getContainingDeclaration(): CallableDescriptor = containingDeclaration
override fun getPackageFqNameIfTopLevel(): FqName = error("Couldn't be top-level")
override fun declaresDefaultValue(): Boolean = ktSymbol.hasDefaultValue
override val varargElementType: KotlinType?
get() {
if (!ktSymbol.isVararg) return null
return context.builtIns.getArrayElementType(type)
}
override fun getOriginal(): ValueParameterDescriptor = context.incorrectImplementation { this }
override fun copy(newOwner: CallableDescriptor, newName: Name, newIndex: Int): ValueParameterDescriptor =
context.noImplementation()
override fun getOverriddenDescriptors(): Collection<ValueParameterDescriptor> {
return containingDeclaration.overriddenDescriptors.map { valueParameters[index] }
}
override val isCrossinline: Boolean
get() = implementationPostponed()
override val isNoinline: Boolean
get() = implementationPostponed()
override fun isVar(): Boolean = false
override fun getCompileTimeInitializer(): ConstantValue<*>? = null
override fun isConst(): Boolean = false
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is KtSymbolBasedValueParameterDescriptor) return false
return index == other.index && containingDeclaration == other.containingDeclaration
}
override fun hashCode(): Int = containingDeclaration.hashCode() * 37 + index
}
class KtSymbolBasedPropertyDescriptor(
override val ktSymbol: KtPropertySymbol,
context: FE10BindingContext
) : KtSymbolBasedDeclarationDescriptor(context), KtSymbolBasedNamed, PropertyDescriptor {
override fun getPackageFqNameIfTopLevel(): FqName = (ktSymbol.callableIdIfNonLocal ?: error("should be top-level")).packageName
override fun getOriginal(): PropertyDescriptor = context.incorrectImplementation { this }
override fun getVisibility(): DescriptorVisibility = ktSymbol.visibility.toDescriptorVisibility()
override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? = getExtensionReceiverParameter(ktSymbol)
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = getDispatchReceiverParameter(ktSymbol)
override fun getTypeParameters(): List<TypeParameterDescriptor> = emptyList()
override fun getReturnType(): KotlinType = ktSymbol.annotatedType.toKotlinType(context)
override fun getValueParameters(): List<ValueParameterDescriptor> = emptyList()
override fun hasStableParameterNames(): Boolean = false
override fun hasSynthesizedParameterNames(): Boolean = false
override fun getOverriddenDescriptors(): Collection<PropertyDescriptor> = implementationPostponed()
override fun <V : Any?> getUserData(key: CallableDescriptor.UserDataKey<V>?): V? = null
override fun getType(): KotlinType = ktSymbol.annotatedType.toKotlinType(context)
override fun isVar(): Boolean = !ktSymbol.isVal
override fun getCompileTimeInitializer(): ConstantValue<*>? = ktSymbol.initializer?.toConstantValue()
override fun isConst(): Boolean = ktSymbol.initializer != null
override fun isLateInit(): Boolean = implementationPostponed()
override fun getModality(): Modality = implementationPlanned()
override fun isExpect(): Boolean = implementationPostponed()
override fun isActual(): Boolean = implementationPostponed()
override fun isExternal(): Boolean = implementationPlanned()
override fun setOverriddenDescriptors(overriddenDescriptors: MutableCollection<out CallableMemberDescriptor>) =
noImplementation()
override fun getKind(): CallableMemberDescriptor.Kind = implementationPlanned()
override fun copy(
newOwner: DeclarationDescriptor?,
modality: Modality?,
visibility: DescriptorVisibility?,
kind: CallableMemberDescriptor.Kind?,
copyOverrides: Boolean
): CallableMemberDescriptor = noImplementation()
override fun newCopyBuilder(): CallableMemberDescriptor.CopyBuilder<out PropertyDescriptor> = noImplementation()
override fun isSetterProjectedOut(): Boolean = implementationPostponed()
override fun getAccessors(): List<PropertyAccessorDescriptor> = listOfNotNull(getter, setter)
override fun getBackingField(): FieldDescriptor? = implementationPostponed()
override fun getDelegateField(): FieldDescriptor? = implementationPostponed()
override val isDelegated: Boolean
get() = implementationPostponed()
override val getter: PropertyGetterDescriptor?
get() = ktSymbol.getter?.let { KtSymbolBasedPropertyGetterDescriptor(it, this) }
override val setter: PropertySetterDescriptor?
get() = ktSymbol.setter?.let { KtSymbolBasedPropertySetterDescriptor(it, this) }
}
abstract class KtSymbolBasedVariableAccessorDescriptor(
val propertyDescriptor: KtSymbolBasedPropertyDescriptor
) : KtSymbolBasedDeclarationDescriptor(propertyDescriptor.context), VariableAccessorDescriptor {
override abstract val ktSymbol: KtPropertyAccessorSymbol
override fun getPackageFqNameIfTopLevel(): FqName = error("should be called")
override fun getContainingDeclaration(): DeclarationDescriptor = propertyDescriptor
override val correspondingVariable: VariableDescriptorWithAccessors
get() = propertyDescriptor
override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? = propertyDescriptor.extensionReceiverParameter
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = propertyDescriptor.dispatchReceiverParameter
override fun getTypeParameters(): List<TypeParameterDescriptor> = emptyList()
override fun getValueParameters(): List<ValueParameterDescriptor> = emptyList()
override fun hasStableParameterNames(): Boolean = false
override fun hasSynthesizedParameterNames(): Boolean = false
override fun <V : Any?> getUserData(key: CallableDescriptor.UserDataKey<V>?): V? = null
override fun setOverriddenDescriptors(overriddenDescriptors: MutableCollection<out CallableMemberDescriptor>) =
noImplementation()
override fun getKind(): CallableMemberDescriptor.Kind = propertyDescriptor.kind
override fun getVisibility(): DescriptorVisibility = propertyDescriptor.visibility
override fun getInitialSignatureDescriptor(): FunctionDescriptor? =
noImplementation()
override fun isHiddenToOvercomeSignatureClash(): Boolean = false
override fun isOperator(): Boolean = false
override fun isInfix(): Boolean = false
override fun isInline(): Boolean = ktSymbol.isInline
override fun isTailrec(): Boolean = false
override fun isHiddenForResolutionEverywhereBesideSupercalls(): Boolean =
implementationPostponed()
override fun isSuspend(): Boolean = false
override fun newCopyBuilder(): FunctionDescriptor.CopyBuilder<out FunctionDescriptor> =
noImplementation()
override fun getModality(): Modality = implementationPlanned()
override fun isExpect(): Boolean = implementationPostponed()
override fun isActual(): Boolean = implementationPostponed()
override fun isExternal(): Boolean = implementationPostponed()
}
class KtSymbolBasedPropertyGetterDescriptor(
override val ktSymbol: KtPropertyGetterSymbol,
propertyDescriptor: KtSymbolBasedPropertyDescriptor
) : KtSymbolBasedVariableAccessorDescriptor(propertyDescriptor), PropertyGetterDescriptor {
override fun getReturnType(): KotlinType = propertyDescriptor.returnType
override fun getName(): Name = Name.special("<get-${propertyDescriptor.name}>")
override fun isDefault(): Boolean = ktSymbol.isDefault
override fun getCorrespondingProperty(): PropertyDescriptor = propertyDescriptor
override fun copy(
newOwner: DeclarationDescriptor?,
modality: Modality?,
visibility: DescriptorVisibility?,
kind: CallableMemberDescriptor.Kind?,
copyOverrides: Boolean
): PropertyAccessorDescriptor = noImplementation()
override fun getOriginal(): PropertyGetterDescriptor = context.incorrectImplementation { this }
override fun getOverriddenDescriptors(): Collection<PropertyGetterDescriptor> = implementationPostponed()
}
class KtSymbolBasedPropertySetterDescriptor(
override val ktSymbol: KtPropertySetterSymbol,
propertyDescriptor: KtSymbolBasedPropertyDescriptor
) : KtSymbolBasedVariableAccessorDescriptor(propertyDescriptor), PropertySetterDescriptor {
override fun getReturnType(): KotlinType = propertyDescriptor.returnType
override fun getName(): Name = Name.special("<set-${propertyDescriptor.name}>")
override fun isDefault(): Boolean = ktSymbol.isDefault
override fun getCorrespondingProperty(): PropertyDescriptor = propertyDescriptor
override fun copy(
newOwner: DeclarationDescriptor?,
modality: Modality?,
visibility: DescriptorVisibility?,
kind: CallableMemberDescriptor.Kind?,
copyOverrides: Boolean
): PropertyAccessorDescriptor = noImplementation()
override fun getOriginal(): PropertySetterDescriptor = context.incorrectImplementation { this }
override fun getOverriddenDescriptors(): Collection<PropertySetterDescriptor> = implementationPostponed()
}
class KtSymbolBasedPackageFragmentDescriptor(
override val fqName: FqName,
val context: FE10BindingContext
) : PackageFragmentDescriptor {
override fun getName(): Name = fqName.shortName()
override fun getOriginal(): DeclarationDescriptorWithSource = this
override fun getSource(): SourceElement = SourceElement.NO_SOURCE
override val annotations: Annotations
get() = Annotations.EMPTY
override fun getContainingDeclaration(): ModuleDescriptor = context.moduleDescriptor
override fun getMemberScope(): MemberScope = context.noImplementation()
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>?, data: D): R =
context.noImplementation("IDE shouldn't use visitor on descriptors")
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>?) =
context.noImplementation("IDE shouldn't use visitor on descriptors")
}
@@ -0,0 +1,181 @@
/*
* 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.idea.fir.fe10
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
import org.jetbrains.kotlin.idea.fir.fe10.*
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getResolveState
import org.jetbrains.kotlin.idea.frontend.api.*
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.EntityWasGarbageCollectedException
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.KtAnalysisSessionFe10BindingHolder
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.tokens.assertIsValidAndAccessible
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.trackers.createProjectWideOutOfBlockModificationTracker
import java.lang.ref.WeakReference
interface FE10BindingContext {
val builtIns: KotlinBuiltIns
val ktAnalysisSessionFacade: KtAnalysisSessionFe10BindingHolder
val moduleDescriptor: ModuleDescriptor
/**
* Legend:
* - where was decided, that KtSymbolBased descriptor is not support method, noImplementation() method is called.
* - where the implementation planned, but not yet here: implementationPlanned()
* - if there is no simple implementation and it isn't clear if it really needed -- implementationPostponed()
* - if there were no investigation -- autogenerated TODO("not implemented") called
* - if we could implement it right now, but not entirely correct -- wrap it into incorrect implementation
*/
fun noImplementation(additionalInfo: String = ""): Nothing
fun implementationPostponed(additionalInfo: String = ""): Nothing
fun implementationPlanned(additionalInfo: String = ""): Nothing
fun <R> incorrectImplementation(block: () -> R) = block()
}
fun KtSymbol.toDeclarationDescriptor(context: FE10BindingContext): DeclarationDescriptor =
when (this) {
is KtNamedClassOrObjectSymbol -> KtSymbolBasedClassDescriptor(this, context)
is KtFunctionLikeSymbol -> toDeclarationDescriptor(context)
is KtValueParameterSymbol -> {
val containingSymbol = context.withAnalysisSession { this@toDeclarationDescriptor.getContainingSymbol() }
check(containingSymbol is KtFunctionLikeSymbol) {
"Unexpected containing symbol = $containingSymbol"
}
KtSymbolBasedValueParameterDescriptor(this, context, containingSymbol.toDeclarationDescriptor(context))
}
else -> context.implementationPlanned()
}
fun KtFunctionLikeSymbol.toDeclarationDescriptor(context: FE10BindingContext): KtSymbolBasedFunctionLikeDescriptor =
when (this) {
is KtFunctionSymbol -> KtSymbolBasedFunctionDescriptor(this, context)
is KtAnonymousFunctionSymbol -> KtSymbolBasedAnonymousFunctionDescriptor(this, context)
is KtConstructorSymbol -> {
val ktConstructorSymbol = this
val ktClassOrObject = context.withAnalysisSession { ktConstructorSymbol.getContainingSymbol() as KtNamedClassOrObjectSymbol }
KtSymbolBasedConstructorDescriptor(ktConstructorSymbol, KtSymbolBasedClassDescriptor(ktClassOrObject, context))
}
else -> error("Unexpected kind of KtFunctionLikeSymbol: ${this.javaClass}")
}
inline fun <R> FE10BindingContext.withAnalysisSession(f: KtAnalysisSession.() -> R): R = f(ktAnalysisSessionFacade.analysisSession)
class FE10BindingContextImpl(
val project: Project,
val ktElement: KtElement
) : FE10BindingContext {
private val token: ValidityToken = ValidityTokenForKtSymbolBasedWrappers(project)
private val moduleInfo = ktElement.getModuleInfo()
@OptIn(InvalidWayOfUsingAnalysisSession::class)
override val ktAnalysisSessionFacade = KtAnalysisSessionFe10BindingHolder.create(ktElement.getResolveState(), token)
override val moduleDescriptor: ModuleDescriptor = KtSymbolBasedModuleDescriptorImpl(this, moduleInfo)
override val builtIns: KotlinBuiltIns
get() = incorrectImplementation { DefaultBuiltIns.Instance }
override fun noImplementation(additionalInfo: String): Nothing =
error("This method should not be called for wrappers. $additionalInfo")
override fun implementationPostponed(additionalInfo: String): Nothing =
TODO("InvestigateLater and implement if needed. $additionalInfo")
override fun implementationPlanned(additionalInfo: String): Nothing =
TODO("SE_to_implement. $additionalInfo")
}
private class ValidityTokenForKtSymbolBasedWrappers(val project: Project) : ValidityToken() {
private val modificationTracker = project.createProjectWideOutOfBlockModificationTracker()
private val onCreatedTimeStamp = modificationTracker.modificationCount
override fun isValid(): Boolean {
return true
}
override fun getInvalidationReason(): String {
if (onCreatedTimeStamp != modificationTracker.modificationCount) return "PSI has changed since creation"
error("Getting invalidation reason for valid validity token")
}
override fun isAccessible(): Boolean = true
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
override fun getInaccessibilityReason(): String = error("Getting inaccessibility reason for validity token when it is accessible")
}
// This class supposed to be used for non-declaration resolved fir elements, because of that we don't case about FIR phases.
// TODO: review FIR access -- by common IDEA FIR design access FIR should be under read lock
internal class FirWeakReference<out T : FirElement>(firElement: T, private val token: ValidityToken) {
private val firWeakRef = WeakReference(firElement)
inline fun <R> withFir(action: (T) -> R): R {
return action(getFir())
}
fun getFir(): T {
token.assertIsValidAndAccessible()
return firWeakRef.get() ?: throw EntityWasGarbageCollectedException("FirElement")
}
}
private class KtSymbolBasedModuleDescriptorImpl(
val context: FE10BindingContext,
val moduleInfo: IdeaModuleInfo
) : ModuleDescriptor {
override val builtIns: KotlinBuiltIns
get() = context.builtIns
override val stableName: Name?
get() = context.noImplementation()
override val platform: TargetPlatform?
get() = moduleInfo.platform
override fun shouldSeeInternalsOf(targetModule: ModuleDescriptor): Boolean = context.noImplementation()
override fun getPackage(fqName: FqName): PackageViewDescriptor = context.noImplementation()
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> = context.noImplementation()
override val allDependencyModules: List<ModuleDescriptor>
get() = context.implementationPostponed()
override val expectedByModules: List<ModuleDescriptor>
get() = context.implementationPostponed()
override val allExpectedByModules: Set<ModuleDescriptor>
get() = context.implementationPostponed()
override fun <T> getCapability(capability: ModuleCapability<T>): T? = null
override val isValid: Boolean
get() = context.ktAnalysisSessionFacade.analysisSession.token.isValid()
override fun assertValid() {
assert(context.ktAnalysisSessionFacade.analysisSession.token.isValid())
}
override fun getName(): Name = moduleInfo.name
override fun getOriginal(): DeclarationDescriptor = this
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>?) = context.noImplementation()
override val annotations: Annotations
get() = context.incorrectImplementation { Annotations.EMPTY }
}
@@ -0,0 +1,133 @@
/*
* 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.idea.fir.fe10
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.idea.frontend.api.KtStarProjectionTypeArgument
import org.jetbrains.kotlin.idea.frontend.api.KtTypeArgument
import org.jetbrains.kotlin.idea.frontend.api.KtTypeArgumentWithVariance
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtAnonymousObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeAliasSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtTypeAndAnnotations
import org.jetbrains.kotlin.idea.frontend.api.types.*
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
abstract class KtSymbolBasedAbstractTypeConstructor<T> internal constructor(
val ktSBDescriptor: T
) : TypeConstructor where T : KtSymbolBasedDeclarationDescriptor, T : ClassifierDescriptor {
override fun getDeclarationDescriptor(): ClassifierDescriptor = ktSBDescriptor
// TODO: captured types
override fun isDenotable(): Boolean = true
// for Intention|inspection it shouldn't be important what to use.
override fun getBuiltIns(): KotlinBuiltIns = DefaultBuiltIns.Instance
// I don't think that we need to implement this method
override fun isFinal(): Boolean = ktSBDescriptor.context.implementationPostponed("ktSBDescriptor = $ktSBDescriptor")
@TypeRefinement
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor =
ktSBDescriptor.context.noImplementation("ktSBDescriptor = $ktSBDescriptor")
}
class KtSymbolBasedClassTypeConstructor(ktSBDescriptor: KtSymbolBasedClassDescriptor) :
KtSymbolBasedAbstractTypeConstructor<KtSymbolBasedClassDescriptor>(ktSBDescriptor) {
override fun getParameters(): List<TypeParameterDescriptor> =
ktSBDescriptor.ktSymbol.typeParameters.map { KtSymbolBasedTypeParameterDescriptor(it, ktSBDescriptor.context) }
override fun getSupertypes(): Collection<KotlinType> =
ktSBDescriptor.ktSymbol.superTypes.map { it.toKotlinType(ktSBDescriptor.context) }
}
class KtSymbolBasedTypeParameterTypeConstructor(ktSBDescriptor: KtSymbolBasedTypeParameterDescriptor) :
KtSymbolBasedAbstractTypeConstructor<KtSymbolBasedTypeParameterDescriptor>(ktSBDescriptor) {
override fun getParameters(): List<TypeParameterDescriptor> = emptyList()
override fun getSupertypes(): Collection<KotlinType> =
ktSBDescriptor.ktSymbol.upperBounds.map { it.toKotlinType(ktSBDescriptor.context) }
}
// This class is not suppose to be used as "is instance of" because scopes could be wrapped into other scopes
// so generally it isn't a good idea
internal class MemberScopeForKtSymbolBasedDescriptors(lazyDebugInfo: () -> String) : MemberScope {
private val additionalInfo by lazy(lazyDebugInfo)
private fun noImplementation(): Nothing =
error("Scope for descriptors based on KtSymbols should not be used, additional info: $additionalInfo")
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> = noImplementation()
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> = noImplementation()
override fun getFunctionNames(): Set<Name> = noImplementation()
override fun getVariableNames(): Set<Name> = noImplementation()
override fun getClassifierNames(): Set<Name> = noImplementation()
override fun printScopeStructure(p: Printer): Unit = noImplementation()
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor = noImplementation()
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> = noImplementation()
}
fun KtTypeAndAnnotations.getDescriptorsAnnotations(context: FE10BindingContext): Annotations =
Annotations.create(annotations.map { KtSymbolBasedAnnotationDescriptor(it, context) })
fun KtTypeAndAnnotations.toKotlinType(context: FE10BindingContext): UnwrappedType =
type.toKotlinType(context, getDescriptorsAnnotations(context))
fun KtTypeArgument.toTypeProjection(context: FE10BindingContext): TypeProjection =
when (this) {
KtStarProjectionTypeArgument -> StarProjectionForAbsentTypeParameter(context.builtIns)
is KtTypeArgumentWithVariance -> TypeProjectionImpl(variance, type.toKotlinType(context))
}
fun KtType.toKotlinType(context: FE10BindingContext, annotations: Annotations = Annotations.EMPTY): UnwrappedType {
if (this is KtNonDenotableType) return toKotlinType(context, annotations)
val typeConstructor = when (this) {
is KtTypeParameterType -> KtSymbolBasedTypeParameterDescriptor(this.symbol, context).typeConstructor
is KtClassType -> when (val classLikeSymbol = classSymbol) {
is KtTypeAliasSymbol -> context.typeAliasImplementationPlanned()
is KtNamedClassOrObjectSymbol -> KtSymbolBasedClassDescriptor(classLikeSymbol, context).typeConstructor
is KtAnonymousObjectSymbol -> context.implementationPostponed()
}
is KtErrorType -> ErrorUtils.createErrorTypeConstructorWithCustomDebugName(error)
else -> error("Unexpected subclass: ${this.javaClass}")
}
val ktTypeArguments = this.safeAs<KtClassType>()?.typeArguments ?: emptyList()
val markedAsNullable = this.safeAs<KtTypeWithNullability>()?.nullability == KtTypeNullability.NULLABLE
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
annotations, typeConstructor, ktTypeArguments.map { it.toTypeProjection(context) }, markedAsNullable,
MemberScopeForKtSymbolBasedDescriptors { this.asStringForDebugging() }
)
}
fun KtNonDenotableType.toKotlinType(context: FE10BindingContext, annotations: Annotations = Annotations.EMPTY): UnwrappedType =
when (this) {
is KtFlexibleType -> KotlinTypeFactory.flexibleType(
lowerBound.toKotlinType(context, annotations) as SimpleType,
upperBound.toKotlinType(context, annotations) as SimpleType
)
// most likely it isn't correct and intersectTypes(List<UnwrappedType>) should be used,
// but I don't think that we will have the real problem with that implementation
is KtIntersectionType -> IntersectionTypeConstructor(conjuncts.map { it.toKotlinType(context) }).createType()
}
@@ -0,0 +1,107 @@
/*
* 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.idea.fir.fe10
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.analyzer.ResolverForProject
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
import org.jetbrains.kotlin.caches.resolve.PlatformAnalysisSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.idea.FrontendInternals
import org.jetbrains.kotlin.idea.fir.fe10.binding.KtSymbolBasedBindingContext
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.diagnostics.BindingContextSuppressCache
import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class KtSymbolBasedResolutionFacade(
override val project: Project,
val context: FE10BindingContext
) : ResolutionFacade {
override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext = KtSymbolBasedBindingContext(context)
override fun analyze(elements: Collection<KtElement>, bodyResolveMode: BodyResolveMode): BindingContext =
KtSymbolBasedBindingContext(context)
override fun analyzeWithAllCompilerChecks(elements: Collection<KtElement>, callback: DiagnosticSink.DiagnosticsCallback?): AnalysisResult {
return AnalysisResult.success(KtSymbolBasedBindingContext(context), context.moduleDescriptor)
}
override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor {
val ktSymbol = context.withAnalysisSession {
declaration.getSymbol()
}
return ktSymbol.toDeclarationDescriptor(context)
}
override val moduleDescriptor: ModuleDescriptor
get() = context.moduleDescriptor
@FrontendInternals
override fun <T : Any> getFrontendService(serviceClass: Class<T>): T {
TODO("Not yet implemented")
}
@FrontendInternals
override fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T {
TODO("Not yet implemented")
}
@FrontendInternals
override fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
TODO("Not yet implemented")
}
override fun <T : Any> getIdeService(serviceClass: Class<T>): T {
TODO("Not yet implemented")
}
@FrontendInternals
override fun <T : Any> tryGetFrontendService(element: PsiElement, serviceClass: Class<T>): T? {
TODO("Not yet implemented")
}
override fun getResolverForProject(): ResolverForProject<out ModuleInfo> {
TODO("Not yet implemented")
}
}
class KtSymbolBasedKotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
override fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade =
KtSymbolBasedResolutionFacade(project, FE10BindingContextImpl(project, elements.first()))
// todo: platform are ignored
override fun getResolutionFacade(elements: List<KtElement>, platform: TargetPlatform): ResolutionFacade =
KtSymbolBasedResolutionFacade(project, FE10BindingContextImpl(project, elements.first()))
override fun getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade? =
file.safeAs<KtFile>()?.let { KtSymbolBasedResolutionFacade(project, FE10BindingContextImpl(project, it)) }
override fun getSuppressionCache(): KotlinSuppressCache {
return BindingContextSuppressCache(BindingContext.EMPTY)
}
override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? =
TODO("Not yet implemented")
override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, settings: PlatformAnalysisSettings): ResolutionFacade? {
TODO("Not yet implemented")
}
}
@@ -0,0 +1,234 @@
/*
* 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.idea.fir.fe10.binding
import com.intellij.lang.ASTNode
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.realPsi
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
import org.jetbrains.kotlin.idea.fir.fe10.*
import org.jetbrains.kotlin.idea.fir.fe10.FirWeakReference
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.*
private fun FirExpression?.toExpressionReceiverValue(context: FE10BindingContext): ReceiverValue? {
if (this == null) return null
if (this is FirThisReceiverExpression) {
val ktClassSymbol =
context.ktAnalysisSessionFacade.buildClassLikeSymbol(calleeReference.boundSymbol?.fir as FirClassLikeDeclaration<*>)
return ImplicitClassReceiver(ktClassSymbol.toDeclarationDescriptor(context) as ClassDescriptor)
}
val expression = realPsi.safeAs<KtExpression>() ?: context.implementationPostponed()
return ExpressionReceiver.create(
expression,
context.ktAnalysisSessionFacade.buildKtType(typeRef).toKotlinType(context),
context.incorrectImplementation { BindingContext.EMPTY }
)
}
internal class FirSimpleWrapperCall(
val ktCall: KtCallExpression,
val firCall: FirWeakReference<FirFunctionCall>,
val context: FE10BindingContext
) : Call {
override fun getCallOperationNode(): ASTNode = ktCall.node
override fun getExplicitReceiver(): Receiver? = firCall.withFir { it.explicitReceiver.toExpressionReceiverValue(context) }
override fun getDispatchReceiver(): ReceiverValue? = null
override fun getCalleeExpression(): KtExpression? = ktCall.calleeExpression
override fun getValueArgumentList(): KtValueArgumentList? = ktCall.valueArgumentList
override fun getValueArguments(): List<ValueArgument> = ktCall.valueArguments
override fun getFunctionLiteralArguments(): List<LambdaArgument> = ktCall.lambdaArguments
override fun getTypeArguments(): List<KtTypeProjection> = ktCall.typeArguments
override fun getTypeArgumentList(): KtTypeArgumentList? = ktCall.typeArgumentList
override fun getCallElement(): KtElement = ktCall
override fun getCallType(): Call.CallType = Call.CallType.DEFAULT
}
internal class FirWrapperResolvedCall(val firSimpleWrapperCall: FirSimpleWrapperCall) : ResolvedCall<CallableDescriptor> {
private val firCall get() = firSimpleWrapperCall.firCall
private val context get() = firSimpleWrapperCall.context
private val ktFunctionSymbol = firCall.withFir {
context.ktAnalysisSessionFacade.buildSymbol((it.calleeReference as FirResolvedNamedReference).resolvedSymbol.fir) as KtFunctionLikeSymbol
}
private val _typeArguments: Map<TypeParameterDescriptor, KotlinType> by lazy(LazyThreadSafetyMode.PUBLICATION) {
if (firCall.getFir().typeArguments.isEmpty()) return@lazy emptyMap()
val typeArguments = linkedMapOf<TypeParameterDescriptor, KotlinType>()
for ((index, parameter) in candidateDescriptor.typeParameters.withIndex()) {
val firTypeProjectionWithVariance = firCall.getFir().typeArguments[index] as FirTypeProjectionWithVariance
val kotlinType = context.ktAnalysisSessionFacade.buildKtType(firTypeProjectionWithVariance.typeRef).toKotlinType(context)
typeArguments[parameter] = kotlinType
}
typeArguments
}
private val arguments: Map<ValueParameterDescriptor, ResolvedValueArgument> by lazy(LazyThreadSafetyMode.PUBLICATION) {
val firArguments = firCall.withFir { it.argumentMapping } ?: context.implementationPostponed()
val firParameterToResolvedValueArgument = hashMapOf<FirValueParameter, ResolvedValueArgument>()
val allArguments = firSimpleWrapperCall.valueArguments + firSimpleWrapperCall.functionLiteralArguments
var argumentIndex = 0
for ((firExpression, firValueParameter) in firArguments.entries) {
if (firExpression is FirVarargArgumentsExpression) {
val varargArguments = mutableListOf<ValueArgument>()
for (subExpression in firExpression.arguments) {
val currentArgument = allArguments[argumentIndex]; argumentIndex++
check(currentArgument.getArgumentExpression() === subExpression.realPsi) {
"Different psi: ${currentArgument.getArgumentExpression()} !== ${subExpression.realPsi}"
}
varargArguments.add(currentArgument)
}
firParameterToResolvedValueArgument[firValueParameter] = VarargValueArgument(varargArguments)
} else {
val currentArgument = allArguments[argumentIndex]; argumentIndex++
check(currentArgument.getArgumentExpression() === firExpression.realPsi) {
"Different psi: ${currentArgument.getArgumentExpression()} !== ${firExpression.realPsi}"
}
firParameterToResolvedValueArgument[firValueParameter] = ExpressionValueArgument(currentArgument)
}
}
val arguments = linkedMapOf<ValueParameterDescriptor, ResolvedValueArgument>()
for ((parameterIndex, parameter) in ktFunctionSymbol.valueParameters.withIndex()) {
val resolvedValueArgument = context.ktAnalysisSessionFacade.withFir(parameter) { it: FirValueParameter ->
firParameterToResolvedValueArgument[it]
} ?: DefaultValueArgument.DEFAULT
arguments[candidateDescriptor.valueParameters[parameterIndex]] = resolvedValueArgument
}
arguments
}
override fun getStatus(): ResolutionStatus =
if (firCall.getFir().calleeReference is FirResolvedNamedReference) ResolutionStatus.SUCCESS else ResolutionStatus.OTHER_ERROR
override fun getCall(): Call = firSimpleWrapperCall
override fun getCandidateDescriptor(): CallableDescriptor {
return ktFunctionSymbol.toDeclarationDescriptor(context)
}
override fun getResultingDescriptor(): CallableDescriptor = context.incorrectImplementation { candidateDescriptor }
override fun getExtensionReceiver(): ReceiverValue? {
if (firCall.getFir().extensionReceiver === FirNoReceiverExpression) return null
return firCall.getFir().extensionReceiver.toExpressionReceiverValue(context)
}
override fun getDispatchReceiver(): ReceiverValue? {
if (firCall.getFir().dispatchReceiver === FirNoReceiverExpression) return null
return firCall.getFir().dispatchReceiver.toExpressionReceiverValue(context)
}
override fun getExplicitReceiverKind(): ExplicitReceiverKind {
if (firCall.getFir().explicitReceiver === null) return ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
if (firCall.getFir().explicitReceiver === firCall.getFir().extensionReceiver) return ExplicitReceiverKind.EXTENSION_RECEIVER
return ExplicitReceiverKind.DISPATCH_RECEIVER
}
override fun getValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> = arguments
override fun getValueArgumentsByIndex(): List<ResolvedValueArgument> = valueArguments.values.toList()
override fun getArgumentMapping(valueArgument: ValueArgument): ArgumentMapping {
val firArguments = firCall.withFir { it.argumentMapping } ?: context.implementationPostponed()
val argumentExpression = valueArgument.getArgumentExpression() ?: context.implementationPostponed()
var targetFirParameter: FirValueParameter? = null
outer@ for ((firExpression, firValueParameter) in firArguments.entries) {
if (firExpression is FirVarargArgumentsExpression) {
for (subExpression in firExpression.arguments)
if (subExpression.realPsi === argumentExpression) {
targetFirParameter = firValueParameter
break@outer
}
} else if (firExpression.realPsi === argumentExpression) {
targetFirParameter = firValueParameter
break@outer
}
}
if (targetFirParameter == null) return ArgumentUnmapped
val parameterIndex = ktFunctionSymbol.valueParameters.indexOfFirst {
context.ktAnalysisSessionFacade.withFir(it) { it: FirValueParameter -> it === targetFirParameter }
}
if (parameterIndex == -1) error("Fir parameter not found :(")
val parameterDescriptor = candidateDescriptor.valueParameters[parameterIndex]
return ArgumentMatchImpl(parameterDescriptor)
}
override fun getTypeArguments(): Map<TypeParameterDescriptor, KotlinType> = _typeArguments
override fun getDataFlowInfoForArguments(): DataFlowInfoForArguments = context.noImplementation()
override fun getSmartCastDispatchReceiverType(): KotlinType? = context.noImplementation()
}
class CallAndResolverCallWrappers(bindingContext: KtSymbolBasedBindingContext) {
private val context = bindingContext.context
init {
bindingContext.registerGetterByKey(BindingContext.CALL, this::getCall)
bindingContext.registerGetterByKey(BindingContext.RESOLVED_CALL, this::getResolvedCall)
bindingContext.registerGetterByKey(BindingContext.REFERENCE_TARGET, this::getReferenceTarget)
}
private fun getCall(element: KtElement): Call {
val ktCall = element.parent.safeAs<KtCallExpression>() ?: context.implementationPostponed()
val firCall = when (val fir = element.getOrBuildFir(context.ktAnalysisSessionFacade.firResolveState)) {
is FirFunctionCall -> fir
is FirSafeCallExpression -> fir.regularQualifiedAccess as? FirFunctionCall
else -> null
}
if (firCall != null) return FirSimpleWrapperCall(ktCall, FirWeakReference(firCall, context.ktAnalysisSessionFacade.analysisSession.token), context)
// Call for property
context.implementationPostponed()
}
private fun getResolvedCall(call: Call): ResolvedCall<*> {
check(call is FirSimpleWrapperCall) {
"Incorrect Call type: $call"
}
return FirWrapperResolvedCall(call)
}
private fun getReferenceTarget(key: KtReferenceExpression): DeclarationDescriptor? {
val ktSymbol = context.withAnalysisSession { key.mainReference.resolveToSymbols().singleOrNull() } ?: return null
return ktSymbol.toDeclarationDescriptor(context)
}
}
@@ -0,0 +1,64 @@
/*
* 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.idea.fir.fe10.binding
import com.google.common.collect.ImmutableMap
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.kotlin.idea.fir.fe10.FE10BindingContext
import org.jetbrains.kotlin.idea.fir.fe10.toKotlinType
import org.jetbrains.kotlin.idea.fir.fe10.withAnalysisSession
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice
import org.jetbrains.kotlin.util.slicedMap.WritableSlice
class KtSymbolBasedBindingContext(val context: FE10BindingContext) : BindingContext {
private val LOG = Logger.getInstance(KtSymbolBasedBindingContext::class.java)
private val getterBySlice: MutableMap<ReadOnlySlice<*, *>, (Nothing) -> Any?> = hashMapOf()
init {
CallAndResolverCallWrappers(this)
ToDescriptorBindingContextValueProviders(this)
}
fun <K, V> registerGetterByKey(slice: ReadOnlySlice<K, V>, getter: (K) -> V?) {
check(!getterBySlice.containsKey(slice)) {
"Key $slice already registered: ${getterBySlice[slice]}"
}
getterBySlice[slice] = getter
}
override fun getDiagnostics(): Diagnostics = context.incorrectImplementation { Diagnostics.EMPTY }
override fun <K : Any?, V : Any?> get(slice: ReadOnlySlice<K, V>, key: K): V? {
val getter = getterBySlice[slice]
if (getter == null) {
LOG.info("Key not registered: $slice")
return null
}
@Suppress("UNCHECKED_CAST")
return (getter as (K) -> V?)(key)
}
override fun getType(expression: KtExpression): KotlinType? =
context.withAnalysisSession {
expression.getKtType().toKotlinType(context)
}
override fun <K : Any?, V : Any?> getKeys(slice: WritableSlice<K, V>?): Collection<K> =
context.noImplementation()
override fun <K : Any?, V : Any?> getSliceContents(slice: ReadOnlySlice<K, V>): ImmutableMap<K, V> =
context.noImplementation()
override fun addOwnDataTo(trace: BindingTrace, commitDiagnostics: Boolean) =
context.noImplementation()
}
@@ -0,0 +1,79 @@
/*
* 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.idea.fir.fe10.binding
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.fir.fe10.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal class ToDescriptorBindingContextValueProviders(bindingContext: KtSymbolBasedBindingContext) {
private val context = bindingContext.context
private val declarationToDescriptorGetters = mutableListOf<(PsiElement) -> DeclarationDescriptor?>()
private inline fun <reified K : PsiElement, V : DeclarationDescriptor> KtSymbolBasedBindingContext.registerDeclarationToDescriptorByKey(
slice: ReadOnlySlice<K, V>,
crossinline getter: (K) -> V?
) {
declarationToDescriptorGetters.add {
if (it is K) getter(it) else null
}
registerGetterByKey(slice, { getter(it) })
}
init {
bindingContext.registerDeclarationToDescriptorByKey(BindingContext.CLASS, this::getClass)
bindingContext.registerDeclarationToDescriptorByKey(BindingContext.TYPE_PARAMETER, this::getTypeParameter)
bindingContext.registerDeclarationToDescriptorByKey(BindingContext.FUNCTION, this::getFunction)
bindingContext.registerDeclarationToDescriptorByKey(BindingContext.CONSTRUCTOR, this::getConstructor)
bindingContext.registerGetterByKey(BindingContext.DECLARATION_TO_DESCRIPTOR, this::getDeclarationToDescriptor)
}
private inline fun <reified T : Any> PsiElement.getKtSymbolOfTypeOrNull(): T? =
this@ToDescriptorBindingContextValueProviders.context.withAnalysisSession {
this@getKtSymbolOfTypeOrNull.safeAs<KtDeclaration>()?.getSymbol().safeAs<T>()
}
private fun getClass(key: PsiElement): ClassDescriptor? {
val ktClassSymbol = key.getKtSymbolOfTypeOrNull<KtNamedClassOrObjectSymbol>() ?: return null
return KtSymbolBasedClassDescriptor(ktClassSymbol, context)
}
private fun getTypeParameter(key: KtTypeParameter): TypeParameterDescriptor {
val ktTypeParameterSymbol = context.withAnalysisSession { key.getTypeParameterSymbol() }
return KtSymbolBasedTypeParameterDescriptor(ktTypeParameterSymbol, context)
}
private fun getFunction(key: PsiElement): SimpleFunctionDescriptor? {
val ktFunctionLikeSymbol = key.getKtSymbolOfTypeOrNull<KtFunctionLikeSymbol>() ?: return null
return ktFunctionLikeSymbol.toDeclarationDescriptor(context).safeAs()
}
private fun getConstructor(key: PsiElement): ConstructorDescriptor? {
val ktConstructorSymbol = key.getKtSymbolOfTypeOrNull<KtConstructorSymbol>() ?: return null
val containerClass = context.withAnalysisSession { ktConstructorSymbol.getContainingSymbol() }
check(containerClass is KtNamedClassOrObjectSymbol) {
"Unexpected contained for Constructor symbol: $containerClass, ktConstructorSymbol = $ktConstructorSymbol"
}
return KtSymbolBasedConstructorDescriptor(ktConstructorSymbol, KtSymbolBasedClassDescriptor(containerClass, context))
}
private fun getDeclarationToDescriptor(key: PsiElement): DeclarationDescriptor? {
for (getter in declarationToDescriptorGetters) {
getter(key)?.let { return it }
}
return null
}
}
@@ -0,0 +1,26 @@
/*
* 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.idea.inspections
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.idea.intentions.AbstractIntentionTest
import org.jetbrains.kotlin.test.utils.IgnoreTests
import java.io.File
abstract class AbstractFe10BindingIntentionTest : AbstractIntentionTest() {
override fun isFirPlugin() = true
// left empty because error reporting in FIR and old FE is different
override fun checkForErrorsBefore(fileText: String) {}
override fun checkForErrorsAfter(fileText: String) {}
override fun doTestFor(mainFile: File, pathToFiles: Map<String, PsiFile>, intentionAction: IntentionAction, fileText: String) {
IgnoreTests.runTestIfNotDisabledByFileDirective(mainFile.toPath(), IgnoreTests.DIRECTIVES.IGNORE_FE10_BINDING_BY_FIR, "after") {
super.doTestFor(mainFile, pathToFiles, intentionAction, fileText)
}
}
}
@@ -0,0 +1,136 @@
/*
* 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.idea.inspections;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/testData/intentions/conventionNameCalls/replaceContains")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class Fe10BindingIntentionTestGenerated extends AbstractFe10BindingIntentionTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInReplaceContains() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/intentions/conventionNameCalls/replaceContains"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), null, true);
}
@TestMetadata("containsFromJava.kt")
public void testContainsFromJava() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/containsFromJava.kt");
}
@TestMetadata("containsInExpression.kt")
public void testContainsInExpression() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/containsInExpression.kt");
}
@TestMetadata("extensionFunction.kt")
public void testExtensionFunction() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/extensionFunction.kt");
}
@TestMetadata("functionLiteralArgument.kt")
public void testFunctionLiteralArgument() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/functionLiteralArgument.kt");
}
@TestMetadata("functionLiteralArgumentAfterSemicolon.kt")
public void testFunctionLiteralArgumentAfterSemicolon() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/functionLiteralArgumentAfterSemicolon.kt");
}
@TestMetadata("functionLiteralArgumentAtStartOfBlock.kt")
public void testFunctionLiteralArgumentAtStartOfBlock() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/functionLiteralArgumentAtStartOfBlock.kt");
}
@TestMetadata("functionLiteralArgumentInExpression.kt")
public void testFunctionLiteralArgumentInExpression() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/functionLiteralArgumentInExpression.kt");
}
@TestMetadata("invalidArgument.kt")
public void testInvalidArgument() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/invalidArgument.kt");
}
@TestMetadata("missingArgument.kt")
public void testMissingArgument() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/missingArgument.kt");
}
@TestMetadata("missingDefaultArgument.kt")
public void testMissingDefaultArgument() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/missingDefaultArgument.kt");
}
@TestMetadata("multipleArguments.kt")
public void testMultipleArguments() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/multipleArguments.kt");
}
@TestMetadata("notContains.kt")
public void testNotContains() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/notContains.kt");
}
@TestMetadata("qualifier.kt")
public void testQualifier() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/qualifier.kt");
}
@TestMetadata("simpleArgument.kt")
public void testSimpleArgument() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/simpleArgument.kt");
}
@TestMetadata("simpleStringLiteral.kt")
public void testSimpleStringLiteral() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/simpleStringLiteral.kt");
}
@TestMetadata("super.kt")
public void testSuper() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/super.kt");
}
@TestMetadata("twoArgsContainsFromJava.kt")
public void testTwoArgsContainsFromJava() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/twoArgsContainsFromJava.kt");
}
@TestMetadata("typeArguments.kt")
public void testTypeArguments() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/typeArguments.kt");
}
@TestMetadata("unacceptableVararg1.kt")
public void testUnacceptableVararg1() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/unacceptableVararg1.kt");
}
@TestMetadata("unacceptableVararg2.kt")
public void testUnacceptableVararg2() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/unacceptableVararg2.kt");
}
@TestMetadata("withoutOperatorModifier.kt")
public void testWithoutOperatorModifier() throws Exception {
runTest("idea/testData/intentions/conventionNameCalls/replaceContains/withoutOperatorModifier.kt");
}
}
+2
View File
@@ -9,6 +9,7 @@ dependencies {
compile(project(":idea:formatter"))
compile(intellijDep())
compile(intellijCoreDep())
implementation(project(":idea:idea-fir-fe10-binding"))
// <temp>
compile(project(":idea:idea-core"))
@@ -26,6 +27,7 @@ dependencies {
testCompileOnly(intellijDep())
testRuntime(intellijDep())
testImplementation(project(":idea:idea-fir-fe10-binding"))
compile(intellijPluginDep("java"))
}
@@ -0,0 +1,54 @@
/*
* 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.idea.frontend.api.fir.utils
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.buildSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.ir.util.IdSignature
class KtAnalysisSessionFe10BindingHolder private constructor(
internal val firAnalysisSession: KtFirAnalysisSession
) {
val analysisSession: KtAnalysisSession get() = firAnalysisSession
val firResolveState: FirModuleResolveState get() = firAnalysisSession.firResolveState
fun buildClassLikeSymbol(fir: FirClassLikeDeclaration<*>): KtClassLikeSymbol =
firAnalysisSession.firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(fir)
fun buildKtType(coneType: FirTypeRef): KtType =
firAnalysisSession.firSymbolBuilder.typeBuilder.buildKtType(coneType)
fun buildSymbol(firElement: FirElement): KtSymbol? = firElement.buildSymbol(firAnalysisSession.firSymbolBuilder)
@Suppress("UNCHECKED_CAST", "NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
inline fun <T : FirDeclaration, R> withFir(ktSymbol: KtSymbol, crossinline action: (T) -> R) =
(ktSymbol as KtFirSymbol<T>).firRef.withFir(action = action)
fun toSignature(ktSymbol: KtSymbol): IdSignature = (ktSymbol as KtFirSymbol<*>).firRef.withFir { it.createSignature() }
companion object {
@InvalidWayOfUsingAnalysisSession
fun create(firResolveState: FirModuleResolveState, token: ValidityToken): KtAnalysisSessionFe10BindingHolder {
val firAnalysisSession = KtFirAnalysisSession.createAnalysisSessionByResolveState(firResolveState, token)
return KtAnalysisSessionFe10BindingHolder(firAnalysisSession)
}
}
}
@@ -181,6 +181,8 @@ object IgnoreTests {
const val FIX_ME = "// FIX_ME: "
const val FIR_IDENTICAL = "// FIR_IDENTICAL"
const val IGNORE_FE10_BINDING_BY_FIR = "// IGNORE_FE10_BINDING_BY_FIR"
}
enum class DirectivePosition {
@@ -0,0 +1,14 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<projectService serviceInterface="org.jetbrains.kotlin.caches.resolve.KotlinCacheService"
serviceImplementation="org.jetbrains.kotlin.idea.fir.fe10.KtSymbolBasedKotlinCacheServiceImpl"/>
<!-- Supported Intentions -->
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.conventionNameCalls.ReplaceContainsIntention</className>
<category>Kotlin</category>
</intentionAction>
</extensions>
</idea-plugin>
+1
View File
@@ -39,6 +39,7 @@ The Kotlin FIR plugin provides language support in IntelliJ IDEA and Android Stu
<xi:include href="caches.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="firInspections.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="firIntentions.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="fe10Binding.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="extensions/ide-frontend-independent.xml" xpointer="xpointer(/idea-plugin/*)"/>
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun foo() {
val c = Container()
c.cont<caret>ains(1)
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun foo() {
val c = Container()
1 in c
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun <T> doSomething(a: T) {}
fun test() {
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun <T> doSomething(a: T) {}
fun test() {
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test()
operator fun Test.contains(a: Int) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test()
operator fun Test.contains(a: Int) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(fn: () -> Boolean) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(fn: () -> Boolean) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(fn: () -> Boolean) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(fn: () -> Boolean) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(fn: () -> Boolean) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(fn: () -> Boolean) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun <T> doSomething(a: T) {}
fun test() {
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun <T> doSomething(a: T) {}
fun test() {
@@ -1,6 +1,7 @@
// IS_APPLICABLE: false
// ERROR: Cannot find a parameter with this name: c
// ERROR: 'operator' modifier is inapplicable on this function: must have a single value parameter
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(a: Int=1, b: Int=2): Boolean = true
@@ -1,6 +1,7 @@
// IS_APPLICABLE: false
// ERROR: No value passed for parameter 'b'
// ERROR: 'operator' modifier is inapplicable on this function: must have a single value parameter
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(a: Int, b: Int): Boolean = true
@@ -1,5 +1,7 @@
// IS_APPLICABLE: false
// ERROR: 'operator' modifier is inapplicable on this function: must have a single value parameter
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(a: Int=1, b: Int=2) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(a: Int) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(a: Int) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
class C {
companion object {
operator fun contains(s: String) = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
class C {
companion object {
operator fun contains(s: String) = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(a: Int) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(a: Int) : Boolean = true
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
@Suppress("INAPPLICABLE_OPERATOR_MODIFIER")
public operator fun CharSequence.contains(other: CharSequence, ignoreCase: Boolean = false): Boolean = false
fun test() {
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
@Suppress("INAPPLICABLE_OPERATOR_MODIFIER")
public operator fun CharSequence.contains(other: CharSequence, ignoreCase: Boolean = false): Boolean = false
fun test() {
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun <T> contains(a: T): Boolean = false
@@ -1,3 +1,4 @@
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun <T> contains(a: T): Boolean = false
@@ -1,5 +1,6 @@
// IS_APPLICABLE: false
// ERROR: 'operator' modifier is inapplicable on this function: must have a single value parameter
// IGNORE_FE10_BINDING_BY_FIR
fun test() {
class Test{
operator fun contains(vararg b: Int, c: Int = 0): Boolean = true
+1
View File
@@ -344,6 +344,7 @@ include ":compiler:test-infrastructure",
include ":idea:idea-frontend-fir:idea-fir-low-level-api"
include ":idea:idea-frontend-fir:idea-frontend-fir-generator"
include ":idea:idea-fir-performance-tests"
include ":idea:idea-fir-fe10-binding"
include ":plugins:parcelize:parcelize-compiler",
":plugins:parcelize:parcelize-ide",