Initial implementation of usage search for get/set methods in form of synthetic extension
This commit is contained in:
@@ -39,6 +39,17 @@ import java.util.*
|
||||
interface SyntheticExtensionPropertyDescriptor : PropertyDescriptor {
|
||||
val getMethod: FunctionDescriptor
|
||||
val setMethod: FunctionDescriptor?
|
||||
|
||||
companion object {
|
||||
fun findByGetterOrSetter(getterOrSetter: FunctionDescriptor, resolutionScope: JetScope): SyntheticExtensionPropertyDescriptor? {
|
||||
val owner = getterOrSetter.getContainingDeclaration()
|
||||
if (owner !is JavaClassDescriptor) return null
|
||||
|
||||
return resolutionScope.getSyntheticExtensionProperties(owner.getDefaultType())
|
||||
.filterIsInstance<SyntheticExtensionPropertyDescriptor>()
|
||||
.firstOrNull { getterOrSetter == it.getMethod || getterOrSetter == it.setMethod }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AdditionalScopesWithSyntheticExtensions(storageManager: StorageManager) : FileScopeProvider.AdditionalScopes() {
|
||||
|
||||
+6
-17
@@ -45,32 +45,21 @@ public object JavaResolveExtension : CacheExtension<(PsiElement) -> Pair<JavaDes
|
||||
KotlinCacheService.getInstance(project)[this](element).second
|
||||
}
|
||||
|
||||
fun PsiMethod.getJavaMethodDescriptor(): FunctionDescriptor {
|
||||
fun PsiMethod.getJavaMethodDescriptor(): FunctionDescriptor? {
|
||||
val method = getOriginalElement() as PsiMethod
|
||||
val resolver = JavaResolveExtension.getResolver(method.getProject(), method)
|
||||
val methodDescriptor = when {
|
||||
return when {
|
||||
method.isConstructor() -> resolver.resolveConstructor(JavaConstructorImpl(method))
|
||||
else -> resolver.resolveMethod(JavaMethodImpl(method))
|
||||
}
|
||||
assert(methodDescriptor != null) { "No descriptor found for " + method.getText() }
|
||||
|
||||
return methodDescriptor!!
|
||||
}
|
||||
|
||||
fun PsiClass.getJavaClassDescriptor(): ClassDescriptor {
|
||||
val resolver = JavaResolveExtension.getResolver(getProject(), this)
|
||||
val classDescriptor = resolver.resolveClass(JavaClassImpl(this))
|
||||
assert(classDescriptor != null) { "No descriptor found for " + getText() }
|
||||
|
||||
return classDescriptor!!
|
||||
fun PsiClass.getJavaClassDescriptor(): ClassDescriptor? {
|
||||
return JavaResolveExtension.getResolver(getProject(), this).resolveClass(JavaClassImpl(this))
|
||||
}
|
||||
|
||||
fun PsiField.getJavaFieldDescriptor(): PropertyDescriptor {
|
||||
val resolver = JavaResolveExtension.getResolver(getProject(), this)
|
||||
val fieldDescriptor = resolver.resolveField(JavaFieldImpl(this))
|
||||
assert(fieldDescriptor != null) { "No descriptor found for " + getText() }
|
||||
|
||||
return fieldDescriptor!!
|
||||
fun PsiField.getJavaFieldDescriptor(): PropertyDescriptor? {
|
||||
return JavaResolveExtension.getResolver(getProject(), this).resolveField(JavaFieldImpl(this))
|
||||
}
|
||||
|
||||
fun PsiMember.getJavaMemberDescriptor(): DeclarationDescriptor? {
|
||||
|
||||
@@ -502,7 +502,7 @@
|
||||
<directClassInheritorsSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDirectInheritorsSearcher"/>
|
||||
<definitionsScopedSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDefinitionsSearcher"/>
|
||||
<annotatedElementsSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinAnnotatedElementsSearcher"/>
|
||||
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinLightPropertyAccessorsReferenceSearcher"/>
|
||||
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinPropertyAccessorsReferenceSearcher"/>
|
||||
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinConstructorDelegationCallReferenceSearcher"/>
|
||||
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinOverridingMethodReferenceSearcher"/>
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ class UsePropertyAccessSyntaxIntention : JetSelfTargetingOffsetIndependentIntent
|
||||
}
|
||||
|
||||
private fun findSyntheticProperty(function: FunctionDescriptor, resolutionScope: JetScope): SyntheticExtensionPropertyDescriptor? {
|
||||
findSyntheticPropertyNoOverriddenCheck(function, resolutionScope)?.let { return it }
|
||||
SyntheticExtensionPropertyDescriptor.findByGetterOrSetter(function, resolutionScope)?.let { return it }
|
||||
|
||||
for (overridden in function.getOverriddenDescriptors()) {
|
||||
findSyntheticProperty(overridden, resolutionScope)?.let { return it }
|
||||
@@ -97,15 +97,6 @@ class UsePropertyAccessSyntaxIntention : JetSelfTargetingOffsetIndependentIntent
|
||||
return null
|
||||
}
|
||||
|
||||
private fun findSyntheticPropertyNoOverriddenCheck(function: FunctionDescriptor, resolutionScope: JetScope): SyntheticExtensionPropertyDescriptor? {
|
||||
val owner = function.getContainingDeclaration()
|
||||
if (owner !is JavaClassDescriptor) return null
|
||||
|
||||
return resolutionScope.getSyntheticExtensionProperties(owner.getDefaultType())
|
||||
.filterIsInstance<SyntheticExtensionPropertyDescriptor>()
|
||||
.firstOrNull { function == it.getMethod || function == it.setMethod }
|
||||
}
|
||||
|
||||
private fun replaceWithPropertyGet(callExpression: JetCallExpression, propertyName: Name) {
|
||||
val newExpression = JetPsiFactory(callExpression).createExpression(propertyName.render())
|
||||
callExpression.replace(newExpression)
|
||||
|
||||
@@ -388,7 +388,7 @@ public fun JetChangeInfo.getAffectedCallables(): Collection<UsageInfo> = methodD
|
||||
public fun ChangeInfo.toJetChangeInfo(originalChangeSignatureDescriptor: JetMethodDescriptor): JetChangeInfo {
|
||||
val method = getMethod() as PsiMethod
|
||||
|
||||
val functionDescriptor = method.getJavaMethodDescriptor()
|
||||
val functionDescriptor = method.getJavaMethodDescriptor()!!
|
||||
val parameterDescriptors = functionDescriptor.getValueParameters()
|
||||
|
||||
//noinspection ConstantConditions
|
||||
|
||||
+2
@@ -394,6 +394,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
if (!RefactoringPackage.isTrueJavaMethod(method)) return;
|
||||
|
||||
FunctionDescriptor methodDescriptor = ResolvePackage.getJavaMethodDescriptor((PsiMethod) method);
|
||||
assert methodDescriptor != null;
|
||||
|
||||
DeclarationDescriptor containingDescriptor = methodDescriptor.getContainingDeclaration();
|
||||
if (!(containingDescriptor instanceof JavaClassDescriptor)) return;
|
||||
@@ -958,6 +959,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
boolean startedFromJava = method instanceof PsiMethod;
|
||||
if (startedFromJava && originalJavaMethodDescriptor == null) {
|
||||
FunctionDescriptor methodDescriptor = ResolvePackage.getJavaMethodDescriptor((PsiMethod) method);
|
||||
assert methodDescriptor != null;
|
||||
originalJavaMethodDescriptor =
|
||||
new JetChangeSignatureData(methodDescriptor, method, Collections.singletonList(methodDescriptor));;
|
||||
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ public class KotlinMethodNode(
|
||||
val descriptor = when (myMethod) {
|
||||
is JetFunction -> myMethod.resolveToDescriptor() as FunctionDescriptor
|
||||
is JetClass -> (myMethod.resolveToDescriptor() as ClassDescriptor).getUnsubstitutedPrimaryConstructor() ?: return
|
||||
is PsiMethod -> myMethod.getJavaMethodDescriptor()
|
||||
is PsiMethod -> myMethod.getJavaMethodDescriptor() ?: return
|
||||
else -> throw AssertionError("Invalid declaration: ${myMethod.getElementTextWithContext()}")
|
||||
}
|
||||
val containerName = sequence<DeclarationDescriptor>(descriptor) { it.getContainingDeclaration() }
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ public class KotlinIntroduceParameterMethodUsageProcessor : IntroduceParameterMe
|
||||
|
||||
val changeInfo = createChangeInfo(data, element) ?: return true
|
||||
// Java method is already updated at this point
|
||||
val addedParameterType = data.getMethodToReplaceIn().getJavaMethodDescriptor().getValueParameters().last().getType()
|
||||
val addedParameterType = data.getMethodToReplaceIn().getJavaMethodDescriptor()!!.getValueParameters().last().getType()
|
||||
changeInfo.getNewParameters().last().currentTypeText = IdeDescriptorRenderers.SOURCE_CODE.renderType(addedParameterType)
|
||||
|
||||
val scope = element.getUseScope().let {
|
||||
|
||||
+25
-13
@@ -17,27 +17,27 @@
|
||||
package org.jetbrains.kotlin.idea.search.ideaExtensions
|
||||
|
||||
import com.intellij.openapi.application.QueryExecutorBase
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.UsageSearchContext
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.kotlin.idea.JetFileType
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.idea.JetFileType
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getJavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.psi.JetProperty
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticExtensionPropertyDescriptor
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticExtensionsScope
|
||||
|
||||
public class KotlinLightPropertyAccessorsReferenceSearcher() : QueryExecutorBase<PsiReference, MethodReferencesSearch.SearchParameters>(true) {
|
||||
public class KotlinPropertyAccessorsReferenceSearcher() : QueryExecutorBase<PsiReference, MethodReferencesSearch.SearchParameters>(true) {
|
||||
override fun processQuery(queryParameters: MethodReferencesSearch.SearchParameters, consumer: Processor<PsiReference>) {
|
||||
val method = queryParameters.getMethod()
|
||||
val unwrapped = method.namedUnwrappedElement
|
||||
val propertyName = propertyName(method) ?: return
|
||||
|
||||
if (unwrapped !is JetProperty) return
|
||||
|
||||
val propertyName = unwrapped.getName()
|
||||
if (propertyName == null) return
|
||||
|
||||
val onlyKotlinFiles = restrictToKotlinSources(queryParameters.getScope())
|
||||
val onlyKotlinFiles = restrictToKotlinSources(queryParameters.getEffectiveSearchScope())
|
||||
|
||||
queryParameters.getOptimizer()!!.searchWord(
|
||||
propertyName,
|
||||
@@ -47,10 +47,22 @@ public class KotlinLightPropertyAccessorsReferenceSearcher() : QueryExecutorBase
|
||||
method)
|
||||
}
|
||||
|
||||
private fun restrictToKotlinSources(originalScope: SearchScope): SearchScope {
|
||||
if (originalScope is GlobalSearchScope) {
|
||||
return GlobalSearchScope.getScopeRestrictedByFileTypes(originalScope as GlobalSearchScope, JetFileType.INSTANCE)
|
||||
private fun propertyName(method: PsiMethod): String? {
|
||||
val unwrapped = method.namedUnwrappedElement
|
||||
if (unwrapped is JetProperty) {
|
||||
return unwrapped.getName()
|
||||
}
|
||||
|
||||
val functionDescriptor = method.getJavaMethodDescriptor() ?: return null
|
||||
val syntheticExtensionsScope = SyntheticExtensionsScope(LockBasedStorageManager())
|
||||
val property = SyntheticExtensionPropertyDescriptor.findByGetterOrSetter(functionDescriptor, syntheticExtensionsScope) ?: return null
|
||||
return property.getName().asString()
|
||||
}
|
||||
|
||||
private fun restrictToKotlinSources(originalScope: SearchScope): SearchScope {
|
||||
return when (originalScope) {
|
||||
is GlobalSearchScope -> GlobalSearchScope.getScopeRestrictedByFileTypes(originalScope, JetFileType.INSTANCE)
|
||||
else -> originalScope
|
||||
}
|
||||
return originalScope
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// PSI_ELEMENT: com.intellij.psi.PsiMethod
|
||||
// OPTIONS: usages
|
||||
class JavaClass {
|
||||
public int <caret>getSomething() { return 1; }
|
||||
public void setSomething(int value) {}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo(javaClass: JavaClass) {
|
||||
print(javaClass.something)
|
||||
javaClass.something = 1
|
||||
javaClass.something++
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Value read (2: 21) print(javaClass.something)
|
||||
Value read (4: 15) javaClass.something++
|
||||
@@ -1250,6 +1250,12 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/JKMethodUsages.0.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SyntheticProperties.0.java")
|
||||
public void testSyntheticProperties() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/SyntheticProperties.0.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user