[Analysis API] Move SyntheticPropertyAccessorReferenceDescriptorImpl
Also move some utilities from IDE to kotlin repo
This commit is contained in:
committed by
Ilya Kirillov
parent
71a30b0c5e
commit
a7c37286a3
@@ -15,6 +15,7 @@ dependencies {
|
|||||||
implementation(project(":compiler:backend.jvm"))
|
implementation(project(":compiler:backend.jvm"))
|
||||||
implementation(project(":compiler:backend-common"))
|
implementation(project(":compiler:backend-common"))
|
||||||
implementation(project(":compiler:backend.common.jvm"))
|
implementation(project(":compiler:backend.common.jvm"))
|
||||||
|
implementation(project(":compiler:light-classes"))
|
||||||
|
|
||||||
testApiJUnit5()
|
testApiJUnit5()
|
||||||
testImplementation(project(":analysis:analysis-api-providers"))
|
testImplementation(project(":analysis:analysis-api-providers"))
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.analysis.api.descriptors.references
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
|
import com.intellij.util.SmartList
|
||||||
|
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
|
||||||
|
import org.jetbrains.kotlin.asJava.canHaveSyntheticGetter
|
||||||
|
import org.jetbrains.kotlin.asJava.canHaveSyntheticSetter
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.references.SyntheticPropertyAccessorReference
|
||||||
|
import org.jetbrains.kotlin.idea.references.readWriteAccess
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtImportAlias
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
|
||||||
|
import org.jetbrains.kotlin.resolve.references.ReferenceAccess
|
||||||
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
|
class Fe10SyntheticPropertyAccessorReference(
|
||||||
|
expression: KtNameReferenceExpression,
|
||||||
|
getter: Boolean
|
||||||
|
) : SyntheticPropertyAccessorReference(expression, getter), KtFe10Reference {
|
||||||
|
|
||||||
|
override fun canBeReferenceTo(candidateTarget: PsiElement): Boolean {
|
||||||
|
if (candidateTarget !is PsiMethod || !isAccessorName(candidateTarget.name)) return false
|
||||||
|
if (getter && !candidateTarget.canHaveSyntheticGetter || !getter && !candidateTarget.canHaveSyntheticSetter) return false
|
||||||
|
if (!getter && expression.readWriteAccess(true) == ReferenceAccess.READ) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||||
|
val descriptors = expression.getReferenceTargets(context)
|
||||||
|
if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList()
|
||||||
|
|
||||||
|
val result = SmartList<FunctionDescriptor>()
|
||||||
|
for (descriptor in descriptors) {
|
||||||
|
if (descriptor is SyntheticJavaPropertyDescriptor) {
|
||||||
|
if (getter) {
|
||||||
|
result.add(descriptor.getMethod)
|
||||||
|
} else {
|
||||||
|
result.addIfNotNull(descriptor.setMethod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
|
||||||
|
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val resolvesByNames: Collection<Name>
|
||||||
|
get() = listOf(element.getReferencedNameAsName())
|
||||||
|
}
|
||||||
+30
@@ -5,9 +5,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.analysis.api.descriptors.references.base
|
package org.jetbrains.kotlin.analysis.api.descriptors.references.base
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiReference
|
||||||
import org.jetbrains.kotlin.analysis.api.descriptors.references.*
|
import org.jetbrains.kotlin.analysis.api.descriptors.references.*
|
||||||
import org.jetbrains.kotlin.idea.references.KotlinPsiReferenceRegistrar
|
import org.jetbrains.kotlin.idea.references.KotlinPsiReferenceRegistrar
|
||||||
import org.jetbrains.kotlin.idea.references.KotlinReferenceProviderContributor
|
import org.jetbrains.kotlin.idea.references.KotlinReferenceProviderContributor
|
||||||
|
import org.jetbrains.kotlin.idea.references.readWriteAccess
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtPackageDirective
|
||||||
|
import org.jetbrains.kotlin.psi.KtUserType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||||
|
import org.jetbrains.kotlin.resolve.references.ReferenceAccess
|
||||||
|
|
||||||
class KtFe10KotlinReferenceProviderContributor : KotlinReferenceProviderContributor {
|
class KtFe10KotlinReferenceProviderContributor : KotlinReferenceProviderContributor {
|
||||||
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) {
|
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) {
|
||||||
@@ -21,6 +30,27 @@ class KtFe10KotlinReferenceProviderContributor : KotlinReferenceProviderContribu
|
|||||||
registerProvider(factory = ::KtFe10ConstructorDelegationReference)
|
registerProvider(factory = ::KtFe10ConstructorDelegationReference)
|
||||||
registerProvider(factory = ::KtFe10CollectionLiteralReference)
|
registerProvider(factory = ::KtFe10CollectionLiteralReference)
|
||||||
registerProvider(factory = ::Fe10KDocReference)
|
registerProvider(factory = ::Fe10KDocReference)
|
||||||
|
|
||||||
|
registerMultiProvider<KtNameReferenceExpression> { nameReferenceExpression ->
|
||||||
|
if (nameReferenceExpression.getReferencedNameElementType() != KtTokens.IDENTIFIER) {
|
||||||
|
return@registerMultiProvider PsiReference.EMPTY_ARRAY
|
||||||
|
}
|
||||||
|
if (nameReferenceExpression.parents.any { it is KtImportDirective || it is KtPackageDirective || it is KtUserType }) {
|
||||||
|
return@registerMultiProvider PsiReference.EMPTY_ARRAY
|
||||||
|
}
|
||||||
|
|
||||||
|
when (nameReferenceExpression.readWriteAccess(useResolveForReadWrite = false)) {
|
||||||
|
ReferenceAccess.READ ->
|
||||||
|
arrayOf(Fe10SyntheticPropertyAccessorReference(nameReferenceExpression, getter = true))
|
||||||
|
ReferenceAccess.WRITE ->
|
||||||
|
arrayOf(Fe10SyntheticPropertyAccessorReference(nameReferenceExpression, getter = false))
|
||||||
|
ReferenceAccess.READ_WRITE ->
|
||||||
|
arrayOf(
|
||||||
|
Fe10SyntheticPropertyAccessorReference(nameReferenceExpression, getter = true),
|
||||||
|
Fe10SyntheticPropertyAccessorReference(nameReferenceExpression, getter = false)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-2
@@ -25,8 +25,6 @@ abstract class SyntheticPropertyAccessorReference(
|
|||||||
|
|
||||||
override fun canRename() = true
|
override fun canRename() = true
|
||||||
|
|
||||||
abstract override fun handleElementRename(newElementName: String): PsiElement?
|
|
||||||
|
|
||||||
override val resolvesByNames: Collection<Name>
|
override val resolvesByNames: Collection<Name>
|
||||||
get() = listOf(element.getReferencedNameAsName())
|
get() = listOf(element.getReferencedNameAsName())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.asJava
|
package org.jetbrains.kotlin.asJava
|
||||||
|
|
||||||
|
import com.intellij.lang.jvm.JvmModifier
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
|
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
|
||||||
@@ -18,6 +19,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
|||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.java.propertyNameByGetMethodName
|
import org.jetbrains.kotlin.load.java.propertyNameByGetMethodName
|
||||||
import org.jetbrains.kotlin.load.java.propertyNameBySetMethodName
|
import org.jetbrains.kotlin.load.java.propertyNameBySetMethodName
|
||||||
|
import org.jetbrains.kotlin.load.java.propertyNamesBySetMethodName
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -286,3 +288,52 @@ fun computeExpression(expression: PsiElement): Any? {
|
|||||||
if (constant.isError) return null
|
if (constant.isError) return null
|
||||||
return evalConstantValue(constant.toConstantValue(TypeUtils.NO_EXPECTED_TYPE))
|
return evalConstantValue(constant.toConstantValue(TypeUtils.NO_EXPECTED_TYPE))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val PsiMethod.canBeGetter: Boolean
|
||||||
|
get() = JvmAbi.isGetterName(name) && parameters.isEmpty() && returnTypeElement?.textMatches("void") != true
|
||||||
|
|
||||||
|
private val PsiMethod.canBeSetter: Boolean
|
||||||
|
get() = JvmAbi.isSetterName(name) && parameters.size == 1 && returnTypeElement?.textMatches("void") != false
|
||||||
|
|
||||||
|
private val PsiMethod.probablyCanHaveSyntheticAccessors: Boolean
|
||||||
|
get() = canHaveOverride && !hasTypeParameters() && !isFinalProperty
|
||||||
|
|
||||||
|
private val PsiMethod.getterName: Name? get() = propertyNameByGetMethodName(Name.identifier(name))
|
||||||
|
private val PsiMethod.setterNames: Collection<Name>? get() = propertyNamesBySetMethodName(Name.identifier(name)).takeIf { it.isNotEmpty() }
|
||||||
|
|
||||||
|
private val PsiMethod.isFinalProperty: Boolean
|
||||||
|
get() {
|
||||||
|
val property = unwrapped as? KtProperty ?: return false
|
||||||
|
if (property.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return false
|
||||||
|
val containingClassOrObject = property.containingClassOrObject ?: return true
|
||||||
|
return containingClassOrObject is KtObjectDeclaration
|
||||||
|
}
|
||||||
|
|
||||||
|
private val PsiMethod.isTopLevelDeclaration: Boolean get() = unwrapped?.isTopLevelKtOrJavaMember() == true
|
||||||
|
|
||||||
|
val PsiMethod.syntheticAccessors: Collection<Name>
|
||||||
|
get() {
|
||||||
|
if (!probablyCanHaveSyntheticAccessors) return emptyList()
|
||||||
|
|
||||||
|
return when {
|
||||||
|
canBeGetter -> listOfNotNull(getterName)
|
||||||
|
canBeSetter -> setterNames.orEmpty()
|
||||||
|
else -> emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val PsiMethod.canHaveSyntheticAccessors: Boolean get() = probablyCanHaveSyntheticAccessors && (canBeGetter || canBeSetter)
|
||||||
|
|
||||||
|
val PsiMethod.canHaveSyntheticGetter: Boolean get() = probablyCanHaveSyntheticAccessors && canBeGetter
|
||||||
|
|
||||||
|
val PsiMethod.canHaveSyntheticSetter: Boolean get() = probablyCanHaveSyntheticAccessors && canBeSetter
|
||||||
|
|
||||||
|
val PsiMethod.syntheticGetter: Name? get() = if (canHaveSyntheticGetter) getterName else null
|
||||||
|
|
||||||
|
val PsiMethod.syntheticSetters: Collection<Name>? get() = if (canHaveSyntheticSetter) setterNames else null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attention: only language constructs are checked. For example: static member, constructor, top-level property
|
||||||
|
* @return `false` if constraints are found. Otherwise, `true`
|
||||||
|
*/
|
||||||
|
val PsiMethod.canHaveOverride: Boolean get() = !hasModifier(JvmModifier.STATIC) && !isConstructor && !isTopLevelDeclaration
|
||||||
|
|||||||
Reference in New Issue
Block a user