From f99e6e67652088d42453556259ab0a3b8dd30d9f Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Fri, 1 Nov 2013 18:33:59 +0400 Subject: [PATCH] Fix usage type detection for static members of Java classes and members of nested classes --- .../plugin/findUsages/JetUsageTypeProvider.kt | 74 ++++++++++--------- .../JKClassAllUsages.results.txt | 8 +- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.kt b/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.kt index 23d4b5b19ca..397d7bf269f 100644 --- a/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.kt +++ b/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.kt @@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.lexer.JetTokens import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache import org.jetbrains.jet.plugin.JetBundle +import org.jetbrains.jet.lang.resolve.java.descriptor.JavaNamespaceDescriptor public object JetUsageTypeProvider : UsageTypeProviderEx { public override fun getUsageType(element: PsiElement?): UsageType? { @@ -38,73 +39,78 @@ public object JetUsageTypeProvider : UsageTypeProviderEx { } public override fun getUsageType(element: PsiElement?, targets: Array): UsageType? { - if (element == null) return null + val simpleName = element?.getParentByType(javaClass()) + if (simpleName == null) return null fun getCommonUsageType(): UsageType? { return when { - element.getParentByType(javaClass()) != null -> + simpleName.getParentByType(javaClass()) != null -> UsageType.CLASS_IMPORT - element.getParentByTypeAndBranch(javaClass()) { getCallableReference() } != null -> + simpleName.getParentByTypeAndBranch(javaClass()) { getCallableReference() } != null -> JetUsageTypes.CALLABLE_REFERENCE else -> null } } fun getClassUsageType(): UsageType? { - val property = element.getParentByType(javaClass()) + val property = simpleName.getParentByType(javaClass()) if (property != null) { when { - property.getTypeRef().isAncestor(element) -> + property.getTypeRef().isAncestor(simpleName) -> return if (property.isLocal()) UsageType.CLASS_LOCAL_VAR_DECLARATION else JetUsageTypes.NON_LOCAL_PROPERTY_TYPE - property.getReceiverTypeRef().isAncestor(element) -> + property.getReceiverTypeRef().isAncestor(simpleName) -> return JetUsageTypes.EXTENSION_RECEIVER_TYPE } } - val function = element.getParentByType(javaClass()) + val function = simpleName.getParentByType(javaClass()) if (function != null) { when { - function.getReturnTypeRef().isAncestor(element) -> + function.getReturnTypeRef().isAncestor(simpleName) -> return JetUsageTypes.FUNCTION_RETURN_TYPE - function.getReceiverTypeRef().isAncestor(element) -> + function.getReceiverTypeRef().isAncestor(simpleName) -> return JetUsageTypes.EXTENSION_RECEIVER_TYPE } } return when { - element.getParentByTypeAndBranch(javaClass()) { getExtendsBound() } != null - || element.getParentByTypeAndBranch(javaClass()) { getBoundTypeReference() } != null -> + simpleName.getParentByTypeAndBranch(javaClass()) { getExtendsBound() } != null + || simpleName.getParentByTypeAndBranch(javaClass()) { getBoundTypeReference() } != null -> JetUsageTypes.TYPE_CONSTRAINT - element is JetDelegationSpecifier - || element.getParentByTypeAndBranch(javaClass()) { getTypeReference() } != null -> + simpleName is JetDelegationSpecifier + || simpleName.getParentByTypeAndBranch(javaClass()) { getTypeReference() } != null -> JetUsageTypes.SUPER_TYPE - element.getParentByTypeAndBranch(javaClass()) { getTypeReference() } != null -> + simpleName.getParentByTypeAndBranch(javaClass()) { getTypeReference() } != null -> JetUsageTypes.TYPE_DEFINITION - element.getParentByType(javaClass()) != null -> + simpleName.getParentByType(javaClass()) != null -> UsageType.TYPE_PARAMETER - element.getParentByTypeAndBranch(javaClass()) { getTypeReference() } != null -> + simpleName.getParentByTypeAndBranch(javaClass()) { getTypeReference() } != null -> JetUsageTypes.VALUE_PARAMETER_TYPE - element.getParentByTypeAndBranch(javaClass()) { getTypeRef() } != null -> + simpleName.getParentByTypeAndBranch(javaClass()) { getTypeRef() } != null -> JetUsageTypes.IS - with(element.getParentByTypeAndBranch(javaClass()) { getRight() }) { + with(simpleName.getParentByTypeAndBranch(javaClass()) { getRight() }) { val opType = this?.getOperationReference()?.getReferencedNameElementType() opType == JetTokens.AS_KEYWORD || opType == JetTokens.AS_SAFE } -> UsageType.CLASS_CAST_TO - with(element.getParentByTypeAndBranch(javaClass()) { getReceiverExpression() }) { - this?.getReceiverExpression() is JetSimpleNameExpression + with(simpleName.getParentByType(javaClass())) { + if (this == null) false + else if (getReceiverExpression() == simpleName) true + else + getSelectorExpression() == simpleName + && getParentByTypeAndBranch(javaClass(), true) { getReceiverExpression() } != null } -> JetUsageTypes.CLASS_OBJECT_ACCESS - element.getParentByTypeAndBranch(javaClass()) { getSuperTypeQualifier() } != null -> + simpleName.getParentByTypeAndBranch(javaClass()) { getSuperTypeQualifier() } != null -> JetUsageTypes.SUPER_TYPE_QUALIFIER else -> null @@ -112,30 +118,30 @@ public object JetUsageTypeProvider : UsageTypeProviderEx { } fun getVariableUsageType(): UsageType? { - if (element.getParentByTypeAndBranch(javaClass()) { getDelegateExpression() } != null) { + if (simpleName.getParentByTypeAndBranch(javaClass()) { getDelegateExpression() } != null) { return JetUsageTypes.DELEGATE } - val dotQualifiedExpression = element.getParentByType(javaClass()) + val dotQualifiedExpression = simpleName.getParentByType(javaClass()) if (dotQualifiedExpression != null) { val parent = dotQualifiedExpression.getParent() when { - dotQualifiedExpression.getReceiverExpression().isAncestor(element) -> + dotQualifiedExpression.getReceiverExpression().isAncestor(simpleName) -> return JetUsageTypes.RECEIVER - parent is JetDotQualifiedExpression && parent.getReceiverExpression().isAncestor(element) -> + parent is JetDotQualifiedExpression && parent.getReceiverExpression().isAncestor(simpleName) -> return JetUsageTypes.RECEIVER } } return when { - element.getParentByTypeAndPredicate( + simpleName.getParentByTypeAndPredicate( javaClass(), false, { JetPsiUtil.isAssignment(it) } - )?.getLeft().isAncestor(element) -> + )?.getLeft().isAncestor(simpleName) -> UsageType.WRITE - element.getParentByType(javaClass()) != null -> + simpleName.getParentByType(javaClass()) != null -> UsageType.READ else -> null @@ -144,14 +150,14 @@ public object JetUsageTypeProvider : UsageTypeProviderEx { fun getFunctionUsageType(descriptor: FunctionDescriptor): UsageType? { return when { - element.getParentByTypeAndBranch(javaClass()) { getTypeReference() } != null -> + simpleName.getParentByTypeAndBranch(javaClass()) { getTypeReference() } != null -> JetUsageTypes.SUPER_TYPE descriptor is ConstructorDescriptor - && element.getParentByTypeAndBranch(javaClass()) { getTypeReference() } != null -> + && simpleName.getParentByTypeAndBranch(javaClass()) { getTypeReference() } != null -> UsageType.ANNOTATION - with(element.getParentByTypeAndBranch(javaClass()) { getCalleeExpression() }) { + with(simpleName.getParentByTypeAndBranch(javaClass()) { getCalleeExpression() }) { this?.getCalleeExpression() is JetSimpleNameExpression } -> if (descriptor is ConstructorDescriptor) UsageType.CLASS_NEW_OPERATOR else JetUsageTypes.FUNCTION_CALL @@ -163,17 +169,17 @@ public object JetUsageTypeProvider : UsageTypeProviderEx { val usageType = getCommonUsageType() if (usageType != null) return usageType - val reference = element.getParentByType(javaClass()) + val reference = simpleName.getParentByType(javaClass()) if (reference == null) return null - val file = element.getContainingFile() + val file = simpleName.getContainingFile() if (file == null) return null val bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache(file as JetFile).getBindingContext() val descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, reference) return when (descriptor) { - is ClassifierDescriptor -> getClassUsageType() + is ClassifierDescriptor, is JavaNamespaceDescriptor -> getClassUsageType() is VariableDescriptor -> getVariableUsageType() is FunctionDescriptor -> getFunctionUsageType(descriptor) else -> null diff --git a/idea/testData/findUsages/java/findJavaClassUsages/JKClassAllUsages.results.txt b/idea/testData/findUsages/java/findJavaClassUsages/JKClassAllUsages.results.txt index 25cf03bec30..c6809cccfa8 100644 --- a/idea/testData/findUsages/java/findJavaClassUsages/JKClassAllUsages.results.txt +++ b/idea/testData/findUsages/java/findJavaClassUsages/JKClassAllUsages.results.txt @@ -2,6 +2,10 @@ Class/object property type (2: 15) var next: A? = A() Function return types (15: 20) fun getNext(): A? { Function return types (36: 16) fun Any.toA(): A? { Local variable declaration (11: 17) val aa: A = a +Nested class/object (1: 31) public class X(bar: String? = A.BAR): A() { +Nested class/object (3: 26) val myBar: String? = A.BAR +Nested class/object (6: 9) A.BAR = "" +Nested class/object (7: 9) A.foos() New instance creation (2: 20) var next: A? = A() New instance creation (32: 18) fun X.bar(a: A = A()) { Parameter type (10: 16) fun foo(a: A) { @@ -11,8 +15,4 @@ Supertype (1: 39) public class X(bar: String? = A.BAR): A() { Supertype (23: 19) class object: A() { Supertype (28: 11) object O: A() { Target type of 'is' operation (37: 24) return if (this is A) this as A else null -Unclassified usage (1: 31) public class X(bar: String? = A.BAR): A() { -Unclassified usage (3: 26) val myBar: String? = A.BAR -Unclassified usage (6: 9) A.BAR = "" -Unclassified usage (7: 9) A.foos() Usage in cast target type (37: 35) return if (this is A) this as A else null