From 89863bd2a390e0638a39e11b028d259b698ff459 Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Wed, 1 Apr 2020 18:52:22 +0300 Subject: [PATCH] Uast: unifying resolve to two methods `resolveToDeclaration` and `resolveToPsiMethod` --- .../kotlin/declarations/KotlinUAnnotation.kt | 4 +- .../declarations/KotlinUImportStatement.kt | 5 +- .../KotlinUCallableReferenceExpression.kt | 3 +- .../KotlinUQualifiedReferenceExpression.kt | 4 +- .../KotlinUSafeQualifiedExpression.kt | 3 +- .../KotlinUSimpleReferenceExpression.kt | 70 ++----------- .../internal/kotlinInternalUastUtils.kt | 98 +++++++++++++++---- .../kotlin/internal/kotlinUastMultiresolve.kt | 5 +- .../testData/Anonymous.resolved.txt | 8 +- .../testData/Constructors.resolved.txt | 2 +- .../uast-kotlin/testData/Imports.resolved.txt | 32 +++--- .../uast-kotlin/testData/Resolve.resolved.txt | 22 ++--- .../testData/TypeReferences.resolved.txt | 2 +- 13 files changed, 135 insertions(+), 123 deletions(-) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt index 6bf95447287..3ede78c513d 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt @@ -63,7 +63,9 @@ abstract class KotlinUAnnotationBase( protected abstract fun computeClassDescriptor(): ClassDescriptor? - override fun resolve(): PsiClass? = computeClassDescriptor()?.toSource()?.getMaybeLightElement() as? PsiClass + override fun resolve(): PsiClass? = computeClassDescriptor()?.let { + sourcePsi.calleeExpression?.let { ktExpression -> resolveToDeclaration(ktExpression, it) } + } as? PsiClass override fun findAttributeValue(name: String?): UExpression? = findDeclaredAttributeValue(name) ?: findAttributeDefaultValue(name ?: "value") diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUImportStatement.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUImportStatement.kt index a6c8b8ec3ca..d39cfe230d9 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUImportStatement.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUImportStatement.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtImportDirective import org.jetbrains.kotlin.psi.KtReferenceExpression import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector -import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.uast.UElement import org.jetbrains.uast.UImportStatement import org.jetbrains.uast.USimpleNameReferenceExpression @@ -63,9 +62,7 @@ class KotlinUImportStatement( override fun resolve(): PsiElement? { val reference = psi.getQualifiedElementSelector() as? KtReferenceExpression ?: return null - val bindingContext = reference.analyze() - val referenceTarget = bindingContext[BindingContext.REFERENCE_TARGET, reference] ?: return null - return referenceTarget.toSource()?.getMaybeLightElement() + return resolveToDeclaration(reference) } } } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCallableReferenceExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCallableReferenceExpression.kt index 4182a6b569a..aa65d6dffad 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCallableReferenceExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCallableReferenceExpression.kt @@ -16,6 +16,7 @@ package org.jetbrains.uast.kotlin +import com.intellij.psi.PsiElement import com.intellij.psi.PsiNamedElement import com.intellij.psi.ResolveResult import org.jetbrains.kotlin.psi.KtCallableReferenceExpression @@ -45,7 +46,7 @@ class KotlinUCallableReferenceExpression( override val resolvedName: String? get() = (resolve() as? PsiNamedElement)?.name - override fun resolve() = sourcePsi.callableReference.resolveCallToDeclaration() + override fun resolve(): PsiElement? = resolveToDeclaration(sourcePsi.callableReference) override fun multiResolve(): Iterable = getResolveResultVariants(sourcePsi.callableReference) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUQualifiedReferenceExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUQualifiedReferenceExpression.kt index 0f58c5c8bde..aeb0128d44b 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUQualifiedReferenceExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUQualifiedReferenceExpression.kt @@ -16,8 +16,10 @@ package org.jetbrains.uast.kotlin +import com.intellij.psi.PsiElement import com.intellij.psi.PsiNamedElement import org.jetbrains.kotlin.psi.KtDotQualifiedExpression +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.uast.UCallExpression import org.jetbrains.uast.UElement import org.jetbrains.uast.UQualifiedReferenceExpression @@ -33,7 +35,7 @@ class KotlinUQualifiedReferenceExpression( override val selector by lz { KotlinConverter.convertOrEmpty(sourcePsi.selectorExpression, this) } override val accessType = UastQualifiedExpressionAccessType.SIMPLE - override fun resolve() = sourcePsi.selectorExpression?.resolveCallToDeclaration() + override fun resolve(): PsiElement? = sourcePsi.selectorExpression?.let { resolveToDeclaration(it) } override val resolvedName: String? get() = (resolve() as? PsiNamedElement)?.name diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSafeQualifiedExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSafeQualifiedExpression.kt index bf827e782c2..6650654db64 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSafeQualifiedExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSafeQualifiedExpression.kt @@ -16,6 +16,7 @@ package org.jetbrains.uast.kotlin +import com.intellij.psi.PsiElement import com.intellij.psi.PsiNamedElement import com.intellij.psi.ResolveResult import org.jetbrains.kotlin.psi.KtSafeQualifiedExpression @@ -36,6 +37,6 @@ class KotlinUSafeQualifiedExpression( override val resolvedName: String? get() = (resolve() as? PsiNamedElement)?.name - override fun resolve() = sourcePsi.selectorExpression?.resolveCallToDeclaration() + override fun resolve(): PsiElement? = sourcePsi.selectorExpression?.let { resolveToDeclaration(it) } override fun multiResolve(): Iterable = getResolveResultVariants(sourcePsi.selectorExpression) } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt index fd43faad630..69d10d7b100 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt @@ -16,22 +16,20 @@ package org.jetbrains.uast.kotlin -import com.intellij.psi.* -import org.jetbrains.kotlin.descriptors.* +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiNamedElement +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS -import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl -import org.jetbrains.kotlin.resolve.source.getPsi -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor -import org.jetbrains.kotlin.utils.addToStdlib.constant import org.jetbrains.uast.* import org.jetbrains.uast.internal.acceptList import org.jetbrains.uast.internal.log @@ -43,31 +41,7 @@ open class KotlinUSimpleReferenceExpression( override val sourcePsi: KtSimpleNameExpression, givenParent: UElement? ) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression, KotlinUElementWithType, KotlinEvaluatableUElement { - private val resolvedDeclaration: PsiElement? by lz { - sourcePsi.resolveCallToDeclaration()?.let { return@lz it } - - var declarationDescriptor = sourcePsi.analyze()[BindingContext.REFERENCE_TARGET, sourcePsi] ?: return@lz null - if (declarationDescriptor is ImportedFromObjectCallableDescriptor<*>) { - declarationDescriptor = declarationDescriptor.callableFromObject - } - if (declarationDescriptor is SyntheticJavaPropertyDescriptor) { - declarationDescriptor = when (sourcePsi.readWriteAccess()) { - ReferenceAccess.WRITE, ReferenceAccess.READ_WRITE -> - declarationDescriptor.setMethod ?: declarationDescriptor.getMethod - ReferenceAccess.READ -> declarationDescriptor.getMethod - } - } - - if (declarationDescriptor is PackageViewDescriptor) { - return@lz JavaPsiFacade.getInstance(sourcePsi.project).findPackage(declarationDescriptor.fqName.asString()) - } - - resolveToPsiClass(this, declarationDescriptor, sourcePsi)?.let { return@lz it } - if (declarationDescriptor is DeclarationDescriptorWithSource) { - declarationDescriptor.source.getPsi()?.let { it.getMaybeLightElement() ?: it }?.let { return@lz it } - } - return@lz resolveDeserialized(sourcePsi, declarationDescriptor, sourcePsi.readWriteAccess()) - } + private val resolvedDeclaration: PsiElement? by lz { resolveToDeclaration(sourcePsi) } override val identifier get() = sourcePsi.getReferencedName() @@ -190,31 +164,6 @@ open class KotlinUSimpleReferenceExpression( override fun resolve(): PsiMethod? = resolveToPsiMethod(sourcePsi, accessorDescriptor) } - private fun KtExpression.readWriteAccess(): ReferenceAccess { - var expression = getQualifiedExpressionForSelectorOrThis() - loop@ while (true) { - val parent = expression.parent - when (parent) { - is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression - else -> break@loop - } - } - - val assignment = expression.getAssignmentByLHS() - if (assignment != null) { - return when (assignment.operationToken) { - KtTokens.EQ -> ReferenceAccess.WRITE - else -> ReferenceAccess.READ_WRITE - } - } - - return if ((expression.parent as? KtUnaryExpression)?.operationToken - in constant { setOf(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS) } - ) - ReferenceAccess.READ_WRITE - else - ReferenceAccess.READ - } } class KotlinClassViaConstructorUSimpleReferenceExpression( @@ -228,8 +177,7 @@ class KotlinClassViaConstructorUSimpleReferenceExpression( private val resolved by lazy { when (val resultingDescriptor = sourcePsi.getResolvedCall(sourcePsi.analyze())?.descriptorForResolveViaConstructor()) { is ConstructorDescriptor -> { - resultingDescriptor.constructedClass.toSource()?.getMaybeLightElement() - ?: (resultingDescriptor as? DeserializedCallableMemberDescriptor)?.let { resolveContainingDeserializedClass(sourcePsi, it) } + sourcePsi.calleeExpression?.let { resolveToDeclaration(it, resultingDescriptor) } } is SamConstructorDescriptor -> (resultingDescriptor.returnType?.getFunctionalInterfaceType(this, sourcePsi) as? PsiClassType)?.resolve() diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt index e6f7e6e6df0..0660841746b 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor @@ -48,10 +49,13 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMemberSignature import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject +import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS +import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch @@ -60,14 +64,17 @@ import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor +import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.type.MapPsiToAsmDesc import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.isInterface +import org.jetbrains.kotlin.utils.addToStdlib.constant import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.uast.* @@ -132,7 +139,7 @@ internal fun resolveToPsiMethod( internal fun getContainingLightClass(original: KtDeclaration): KtLightClass? = (original.containingClassOrObject?.toLightClass() ?: original.containingKtFile.findFacadeClass()) -internal fun resolveContainingDeserializedClass(context: KtElement, memberDescriptor: DeserializedCallableMemberDescriptor): PsiClass? { +private fun resolveContainingDeserializedClass(context: KtElement, memberDescriptor: DeserializedCallableMemberDescriptor): PsiClass? { val containingDeclaration = memberDescriptor.containingDeclaration return when (containingDeclaration) { is LazyJavaPackageFragment -> { @@ -142,24 +149,24 @@ internal fun resolveContainingDeserializedClass(context: KtElement, memberDescri JavaPsiFacade.getInstance(context.project).findClass(containingClassQualifiedName, context.resolveScope) ?: return null } is DeserializedClassDescriptor -> { - val declaredPsiType = containingDeclaration.defaultType.toPsiType(null, context, false) + val declaredPsiType = containingDeclaration.defaultType.toPsiType(null as PsiModifierListOwner?, context, false) (declaredPsiType as? PsiClassType)?.resolve() ?: return null } else -> return null } } -internal fun resolveToPsiClass(uElement: UElement, declarationDescriptor: DeclarationDescriptor, context: KtElement): PsiClass? = +private fun resolveToPsiClass(uElement: () -> UElement?, declarationDescriptor: DeclarationDescriptor, context: KtElement): PsiClass? = when (declarationDescriptor) { is ConstructorDescriptor -> declarationDescriptor.returnType is ClassDescriptor -> declarationDescriptor.defaultType is TypeParameterDescriptor -> declarationDescriptor.defaultType is TypeAliasDescriptor -> declarationDescriptor.expandedType else -> null - }?.toPsiType(uElement, context, true).let { PsiTypesUtil.getPsiClass(it) } + }?.toPsiType(uElement.invoke(), context, true).let { PsiTypesUtil.getPsiClass(it) } -internal fun resolveDeserialized( +private fun resolveDeserialized( context: KtElement, descriptor: DeclarationDescriptor, accessHint: ReferenceAccess? = null @@ -236,7 +243,7 @@ private fun PsiMethod.matchesDesc(desc: String) = desc == buildString { private fun getMethodSignatureFromDescriptor(context: KtElement, descriptor: CallableDescriptor): JvmMemberSignature? { fun PsiType.raw() = (this as? PsiClassType)?.rawType() ?: PsiPrimitiveType.getUnboxedType(this) ?: this - fun KotlinType.toPsiType() = toPsiType(null, context, false).raw() + fun KotlinType.toPsiType() = toPsiType(null as PsiModifierListOwner?, context, false).raw() val originalDescriptor = descriptor.original val receiverType = originalDescriptor.extensionReceiverParameter?.type?.toPsiType() @@ -251,8 +258,8 @@ private fun getMethodSignatureFromDescriptor(context: KtElement, descriptor: Cal internal fun lz(initializer: () -> T) = lazy(LazyThreadSafetyMode.SYNCHRONIZED, initializer) -internal fun KotlinType.toPsiType(source: UElement, element: KtElement, boxed: Boolean): PsiType = - toPsiType(source.getParentOfType(false)?.javaPsi as? PsiModifierListOwner, element, boxed) +internal fun KotlinType.toPsiType(source: UElement?, element: KtElement, boxed: Boolean): PsiType = + toPsiType(source?.getParentOfType(false)?.javaPsi as? PsiModifierListOwner, element, boxed) internal fun KotlinType.toPsiType(lightDeclaration: PsiModifierListOwner?, context: KtElement, boxed: Boolean): PsiType { if (this.isError) return UastErrorType @@ -351,7 +358,7 @@ internal fun KtClassOrObject.toPsiType(): PsiType { return PsiTypesUtil.getClassType(lightClass) } -internal fun PsiElement.getMaybeLightElement(): PsiElement? { +private fun PsiElement.getMaybeLightElement(): PsiElement? { return when (this) { is KtDeclaration -> { val lightElement = toLightElements().firstOrNull() @@ -374,15 +381,6 @@ internal fun PsiElement.getMaybeLightElement(): PsiElement? { } } -internal fun KtElement.resolveCallToDeclaration(resultingDescriptor: DeclarationDescriptor? = null): PsiElement? { - val descriptor = resultingDescriptor ?: run { - val resolvedCall = getResolvedCall(analyze()) ?: return null - resolvedCall.resultingDescriptor - } - - return descriptor.toSource()?.getMaybeLightElement() -} - internal fun KtExpression.unwrapBlockOrParenthesis(): KtExpression { val innerExpression = KtPsiUtil.safeDeparenthesize(this) if (innerExpression is KtBlockExpression) { @@ -473,4 +471,68 @@ internal enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) { READ(true, false), WRITE(false, true), READ_WRITE(true, true) } +internal fun resolveToDeclaration(sourcePsi: KtExpression): PsiElement? = + when (sourcePsi) { + is KtSimpleNameExpression -> + sourcePsi.analyze()[BindingContext.REFERENCE_TARGET, sourcePsi] + ?.let { resolveToDeclaration(sourcePsi, it) } + else -> + sourcePsi.getResolvedCall(sourcePsi.analyze())?.resultingDescriptor + ?.let { descriptor -> resolveToDeclaration(sourcePsi, descriptor) } + } + + +internal fun resolveToDeclaration(sourcePsi: KtExpression, declarationDescriptor: DeclarationDescriptor): PsiElement? { + declarationDescriptor.toSource()?.getMaybeLightElement()?.let { return it } + + var declarationDescriptor = declarationDescriptor + if (declarationDescriptor is ImportedFromObjectCallableDescriptor<*>) { + declarationDescriptor = declarationDescriptor.callableFromObject + } + if (declarationDescriptor is SyntheticJavaPropertyDescriptor) { + declarationDescriptor = when (sourcePsi.readWriteAccess()) { + ReferenceAccess.WRITE, ReferenceAccess.READ_WRITE -> + declarationDescriptor.setMethod ?: declarationDescriptor.getMethod + ReferenceAccess.READ -> declarationDescriptor.getMethod + } + } + + if (declarationDescriptor is PackageViewDescriptor) { + return JavaPsiFacade.getInstance(sourcePsi.project).findPackage(declarationDescriptor.fqName.asString()) + } + + resolveToPsiClass({ sourcePsi.toUElement() }, declarationDescriptor, sourcePsi)?.let { return it } + if (declarationDescriptor is DeclarationDescriptorWithSource) { + declarationDescriptor.source.getPsi()?.let { it.getMaybeLightElement() ?: it }?.let { return it } + } + return resolveDeserialized(sourcePsi, declarationDescriptor, sourcePsi.readWriteAccess()) +} + +internal fun KtExpression.readWriteAccess(): ReferenceAccess { + var expression = getQualifiedExpressionForSelectorOrThis() + loop@ while (true) { + val parent = expression.parent + when (parent) { + is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression + else -> break@loop + } + } + + val assignment = expression.getAssignmentByLHS() + if (assignment != null) { + return when (assignment.operationToken) { + KtTokens.EQ -> ReferenceAccess.WRITE + else -> ReferenceAccess.READ_WRITE + } + } + + return if ((expression.parent as? KtUnaryExpression)?.operationToken + in constant { setOf(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS) } + ) + ReferenceAccess.READ_WRITE + else + ReferenceAccess.READ +} + + diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinUastMultiresolve.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinUastMultiresolve.kt index e0be1a5525b..12813c76076 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinUastMultiresolve.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinUastMultiresolve.kt @@ -18,8 +18,7 @@ import org.jetbrains.uast.UElement import org.jetbrains.uast.UMultiResolvable import org.jetbrains.uast.UResolvable import org.jetbrains.uast.kotlin.KotlinUastResolveProviderService -import org.jetbrains.uast.kotlin.getMaybeLightElement -import org.jetbrains.uast.kotlin.toSource +import org.jetbrains.uast.kotlin.resolveToDeclaration internal fun getReferenceVariants(ktElement: KtElement, nameHint: String): Sequence = @@ -31,7 +30,7 @@ internal fun UElement.getResolveResultVariants(ktExpression: KtExpression?): Ite val referenceVariants = getReferenceVariants(ktExpression, ktExpression.name ?: ktExpression.text) fun asCandidateInfo(descriptor: DeclarationDescriptor): CandidateInfo? = - descriptor.toSource()?.getMaybeLightElement()?.let { CandidateInfo(it, PsiSubstitutor.EMPTY) } + resolveToDeclaration(ktExpression, descriptor)?.let { CandidateInfo(it, PsiSubstitutor.EMPTY) } return referenceVariants.mapNotNull(::asCandidateInfo).asIterable() } diff --git a/plugins/uast-kotlin/testData/Anonymous.resolved.txt b/plugins/uast-kotlin/testData/Anonymous.resolved.txt index 6a1175b4118..01e2ea21450 100644 --- a/plugins/uast-kotlin/testData/Anonymous.resolved.txt +++ b/plugins/uast-kotlin/testData/Anonymous.resolved.txt @@ -1,10 +1,10 @@ -UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null +UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> PsiClass:Closeable: Closeable +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiPackage:java.io: io UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> PsiPackage:java: java UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = io) -> PsiPackage:java.io: io UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = Closeable) -> PsiClass:Closeable: Closeable -UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null +UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> PsiClass:InputStream: InputStream +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiPackage:java.io: io UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> PsiPackage:java: java UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = io) -> PsiPackage:java.io: io UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = InputStream) -> PsiClass:InputStream: InputStream diff --git a/plugins/uast-kotlin/testData/Constructors.resolved.txt b/plugins/uast-kotlin/testData/Constructors.resolved.txt index 09c3994262d..57103eda78b 100644 --- a/plugins/uast-kotlin/testData/Constructors.resolved.txt +++ b/plugins/uast-kotlin/testData/Constructors.resolved.txt @@ -50,6 +50,6 @@ UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call' UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = s) -> Light Parameter: s UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String ULocalVariable (name = local) -> USimpleNameReferenceExpression (identifier = s) -> Light Parameter: s - UBlockExpression -> UQualifiedReferenceExpression -> null: null + UBlockExpression -> UQualifiedReferenceExpression -> PsiMethod:toString: toString UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = local) -> LightVariableBuilder:local: local UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to PsiMethod:toString) -> USimpleNameReferenceExpression (identifier = toString) -> PsiMethod:toString: toString diff --git a/plugins/uast-kotlin/testData/Imports.resolved.txt b/plugins/uast-kotlin/testData/Imports.resolved.txt index fbbc2802f2d..c286609a63a 100644 --- a/plugins/uast-kotlin/testData/Imports.resolved.txt +++ b/plugins/uast-kotlin/testData/Imports.resolved.txt @@ -1,39 +1,39 @@ -UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null +UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> PsiMethod:currentThread: currentThread +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiClass:Thread: Thread +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiPackage:java.lang: lang UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> PsiPackage:java: java UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = lang) -> PsiPackage:java.lang: lang UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = Thread) -> PsiClass:Thread: Thread UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = currentThread) -> PsiMethod:currentThread: currentThread -UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null +UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> PsiField:NORM_PRIORITY: NORM_PRIORITY +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiClass:Thread: Thread +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiPackage:java.lang: lang UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> PsiPackage:java: java UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = lang) -> PsiPackage:java.lang: lang UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = Thread) -> PsiClass:Thread: Thread UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = NORM_PRIORITY) -> PsiField:NORM_PRIORITY: NORM_PRIORITY -UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null +UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> PsiClass:UncaughtExceptionHandler: UncaughtExceptionHandler +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiClass:Thread: Thread +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiPackage:java.lang: lang UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> PsiPackage:java: java UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = lang) -> PsiPackage:java.lang: lang UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = Thread) -> PsiClass:Thread: Thread UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = UncaughtExceptionHandler) -> PsiClass:UncaughtExceptionHandler: UncaughtExceptionHandler UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiClass:Thread: Thread +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiPackage:java.lang: lang UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> PsiPackage:java: java UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = lang) -> PsiPackage:java.lang: lang UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = Thread) -> PsiClass:Thread: Thread UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = sleep) -> null: null -UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null +UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> PsiMethod:emptyList: emptyList +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiPackage:kotlin.collections: collections UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = kotlin) -> PsiPackage:kotlin: kotlin UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = collections) -> PsiPackage:kotlin.collections: collections UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = emptyList) -> PsiMethod:emptyList: emptyList -UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null -UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null +UImportStatement (isOnDemand = false) -> UQualifiedReferenceExpression -> PsiField:SIZE_BYTES: SIZE_BYTES +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiClass:IntCompanionObject: IntCompanionObject +UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiClass:Integer: Integer UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = kotlin) -> PsiPackage:kotlin: kotlin UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = Int) -> PsiClass:Integer: Integer UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = Companion) -> PsiClass:IntCompanionObject: IntCompanionObject diff --git a/plugins/uast-kotlin/testData/Resolve.resolved.txt b/plugins/uast-kotlin/testData/Resolve.resolved.txt index 973b035d285..f069f386baf 100644 --- a/plugins/uast-kotlin/testData/Resolve.resolved.txt +++ b/plugins/uast-kotlin/testData/Resolve.resolved.txt @@ -14,7 +14,7 @@ UBlockExpression -> UQualifiedReferenceExpression -> KtLightMethodImpl:foo: foo } }: A UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to KtLightMethodImpl:inlineFoo) -> USimpleNameReferenceExpression (identifier = inlineFoo) -> KtLightMethodImpl:inlineFoo: inlineFoo - UBlockExpression -> UQualifiedReferenceExpression -> null: null + UBlockExpression -> UQualifiedReferenceExpression -> PsiMethod:forEach: forEach UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:listOf) -> USimpleNameReferenceExpression (identifier = listOf) -> PsiMethod:listOf: listOf UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))(resolves to KtLightMethodImpl:A) -> USimpleNameReferenceExpression (identifier = A) -> KtLightClassImpl:open class A { fun foo() {} @@ -25,32 +25,32 @@ UBlockExpression -> UQualifiedReferenceExpression -> KtLightMethodImpl:foo: foo UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:forEach) -> USimpleNameReferenceExpression (identifier = forEach) -> PsiMethod:forEach: forEach UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:println) -> USimpleNameReferenceExpression (identifier = println) -> PsiMethod:println: println UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:println) -> USimpleNameReferenceExpression (identifier = it) -> null: null - UBlockExpression -> UQualifiedReferenceExpression -> null: null + UBlockExpression -> UQualifiedReferenceExpression -> PsiMethod:joinToString: joinToString UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:listOf) -> USimpleNameReferenceExpression (identifier = listOf) -> PsiMethod:listOf: listOf UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to PsiMethod:joinToString) -> USimpleNameReferenceExpression (identifier = joinToString) -> PsiMethod:joinToString: joinToString - UBlockExpression -> UQualifiedReferenceExpression -> null: null + UBlockExpression -> UQualifiedReferenceExpression -> PsiMethod:size: size UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:listOf) -> USimpleNameReferenceExpression (identifier = listOf) -> PsiMethod:listOf: listOf UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = size) -> PsiMethod:size: size - UBlockExpression -> UQualifiedReferenceExpression -> null: null + UBlockExpression -> UQualifiedReferenceExpression -> PsiMethod:getIndices: getIndices UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:listOf) -> USimpleNameReferenceExpression (identifier = listOf) -> PsiMethod:listOf: listOf UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = indices) -> PsiMethod:getIndices: getIndices UTypeReferenceExpression (name = java.util.Date) -> USimpleNameReferenceExpression (identifier = java) -> PsiPackage:java: java UTypeReferenceExpression (name = java.util.Date) -> USimpleNameReferenceExpression (identifier = util) -> PsiPackage:java.util: util UTypeReferenceExpression (name = java.util.Date) -> USimpleNameReferenceExpression (identifier = Date) -> PsiClass:Date: Date ULocalVariable (name = date) -> UQualifiedReferenceExpression -> PsiMethod:Date: Date - UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null + UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiPackage:java.util: util UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = java) -> PsiPackage:java: java UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = util) -> PsiPackage:java.util: util UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))(resolves to PsiMethod:Date) -> USimpleNameReferenceExpression (identifier = Date) -> PsiMethod:Date: Date - UBinaryExpression (operator = =) -> UQualifiedReferenceExpression -> null: null + UBinaryExpression (operator = =) -> UQualifiedReferenceExpression -> PsiMethod:setTime: setTime UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = date) -> LightVariableBuilder:date: date UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = time) -> PsiMethod:setTime: setTime UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = =) -> null: null - UBlockExpression -> UQualifiedReferenceExpression -> null: null + UBlockExpression -> UQualifiedReferenceExpression -> PsiMethod:last: last UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:listOf) -> USimpleNameReferenceExpression (identifier = listOf) -> PsiMethod:listOf: listOf UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to PsiMethod:last) -> USimpleNameReferenceExpression (identifier = last) -> PsiMethod:last: last - UBlockExpression -> UQualifiedReferenceExpression -> null: null - UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null + UBlockExpression -> UQualifiedReferenceExpression -> PsiMethod:setValue: setValue + UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> PsiMethod:first: first UQualifiedReferenceExpression -> UQualifiedReferenceExpression -> null: null UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:mutableMapOf) -> USimpleNameReferenceExpression (identifier = mutableMapOf) -> PsiMethod:mutableMapOf: mutableMapOf UBinaryExpression (operator = ) -> USimpleNameReferenceExpression (identifier = to) -> PsiMethod:to: to @@ -58,7 +58,7 @@ UBlockExpression -> UQualifiedReferenceExpression -> KtLightMethodImpl:foo: foo UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to PsiMethod:first) -> USimpleNameReferenceExpression (identifier = first) -> PsiMethod:first: first UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:setValue) -> USimpleNameReferenceExpression (identifier = setValue) -> PsiMethod:setValue: setValue UBinaryExpression (operator = ..) -> USimpleNameReferenceExpression (identifier = ..) -> null: null - UBlockExpression -> UQualifiedReferenceExpression -> null: null + UBlockExpression -> UQualifiedReferenceExpression -> PsiMethod:longRangeContains: longRangeContains UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = intRange) -> LightVariableBuilder:intRange: intRange UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:longRangeContains) -> USimpleNameReferenceExpression (identifier = contains) -> PsiMethod:longRangeContains: longRangeContains UBinaryExpressionWithType -> USimpleNameReferenceExpression (identifier = as) -> null: null @@ -82,7 +82,7 @@ UTypeReferenceExpression (name = A) -> USimpleNameReferenceExpression (identifie } }: A UTypeReferenceExpression (name = T) -> USimpleNameReferenceExpression (identifier = T) -> KotlinLightTypeParameter:T: T - UBlockExpression -> UQualifiedReferenceExpression -> null: null + UBlockExpression -> UQualifiedReferenceExpression -> PsiMethod:isEmpty: isEmpty UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = listT) -> Light Parameter: listT UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to PsiMethod:isEmpty) -> USimpleNameReferenceExpression (identifier = isEmpty) -> PsiMethod:isEmpty: isEmpty UForEachExpression -> USimpleNameReferenceExpression (identifier = listT) -> Light Parameter: listT diff --git a/plugins/uast-kotlin/testData/TypeReferences.resolved.txt b/plugins/uast-kotlin/testData/TypeReferences.resolved.txt index 3d9fbed8a3e..9ba7cd5928d 100644 --- a/plugins/uast-kotlin/testData/TypeReferences.resolved.txt +++ b/plugins/uast-kotlin/testData/TypeReferences.resolved.txt @@ -19,7 +19,7 @@ UTypeReferenceExpression (name = T) -> USimpleNameReferenceExpression (identifie UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:listOf) -> USimpleNameReferenceExpression (identifier = at) -> LightVariableBuilder:at: at UTypeReferenceExpression (name = java.util.List) -> USimpleNameReferenceExpression (identifier = List) -> PsiClass:List: List UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String - ULocalVariable (name = tsl) -> UQualifiedReferenceExpression -> null: null + ULocalVariable (name = tsl) -> UQualifiedReferenceExpression -> PsiMethod:map: map UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = tl) -> LightVariableBuilder:tl: tl UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))(resolves to PsiMethod:map) -> USimpleNameReferenceExpression (identifier = map) -> PsiMethod:map: map UReturnExpression -> UQualifiedReferenceExpression -> null: null