IDEADEV-42139: new toggle button in the usage view "sort members alphabetically"
[fedora-idea.git] / java / java-impl / src / com / intellij / usages / impl / rules / JavaUsageTypeProvider.java
bloba18d810624102a3dfe5bed12cf7c70759a355ec0
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.usages.impl.rules;
18 import com.intellij.psi.*;
19 import com.intellij.psi.util.PsiTreeUtil;
20 import com.intellij.psi.util.PsiUtil;
21 import com.intellij.util.containers.HashSet;
22 import org.jetbrains.annotations.NotNull;
23 import org.jetbrains.annotations.Nullable;
25 import java.util.Arrays;
27 /**
28 * @author yole
30 public class JavaUsageTypeProvider implements UsageTypeProvider {
31 public UsageType getUsageType(final PsiElement element) {
32 UsageType classUsageType = getClassUsageType(element);
33 if (classUsageType != null) return classUsageType;
35 UsageType methodUsageType = getMethodUsageType(element);
36 if (methodUsageType != null) return methodUsageType;
38 if (element instanceof PsiLiteralExpression) {return UsageType.LITERAL_USAGE; }
40 return null;
43 @Nullable
44 private static UsageType getMethodUsageType(PsiElement element) {
45 if (element instanceof PsiReferenceExpression) {
46 final PsiMethod containerMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
47 if (containerMethod != null) {
48 final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
49 final PsiExpression qualifier = referenceExpression.getQualifierExpression();
50 final PsiElement p = referenceExpression.getParent();
51 if (p instanceof PsiMethodCallExpression) {
52 final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)p;
53 final PsiMethod calledMethod = callExpression.resolveMethod();
54 if (qualifier != null && !(qualifier instanceof PsiThisExpression) && calledMethod != null) {
55 if (haveCommonSuperMethod(containerMethod, calledMethod)) {
56 boolean parametersDelegated = parametersDelegated(containerMethod, callExpression);
58 if (qualifier instanceof PsiSuperExpression) {
59 return parametersDelegated ? UsageType.DELEGATE_TO_SUPER : UsageType.DELEGATE_TO_SUPER_PARAMETERS_CHANGED;
61 else {
62 return parametersDelegated ? UsageType.DELEGATE_TO_ANOTHER_INSTANCE : UsageType.DELEGATE_TO_ANOTHER_INSTANCE_PARAMETERS_CHANGED;
66 else if (calledMethod == containerMethod) {
67 return UsageType.RECURSION;
73 return null;
76 private static boolean parametersDelegated(final PsiMethod method, final PsiMethodCallExpression call) {
77 final PsiParameter[] parameters = method.getParameterList().getParameters();
78 final PsiExpression[] arguments = call.getArgumentList().getExpressions();
79 if (parameters.length != arguments.length) return false;
81 for (int i = 0; i < parameters.length; i++) {
82 PsiParameter parameter = parameters[i];
83 PsiExpression argument = arguments[i];
85 if (!(argument instanceof PsiReferenceExpression)) return false;
86 if (!((PsiReferenceExpression)argument).isReferenceTo(parameter)) return false;
89 for (PsiParameter parameter : parameters) {
90 if (PsiUtil.isAssigned(parameter)) return false;
93 return true;
96 private static boolean haveCommonSuperMethod(@NotNull PsiMethod m1, @NotNull PsiMethod m2) {
97 HashSet<PsiMethod> s1 = new HashSet<PsiMethod>(Arrays.asList(m1.findDeepestSuperMethods()));
98 s1.add(m1);
100 HashSet<PsiMethod> s2 = new HashSet<PsiMethod>(Arrays.asList(m2.findDeepestSuperMethods()));
101 s2.add(m2);
103 s1.retainAll(s2);
104 return !s1.isEmpty();
107 @Nullable
108 private static UsageType getClassUsageType(PsiElement element) {
110 if (element.getParent() instanceof PsiAnnotation &&
111 element == ((PsiAnnotation)element.getParent()).getNameReferenceElement()) return UsageType.ANNOTATION;
113 if (PsiTreeUtil.getParentOfType(element, PsiImportStatement.class, false) != null) return UsageType.CLASS_IMPORT;
114 PsiReferenceList referenceList = PsiTreeUtil.getParentOfType(element, PsiReferenceList.class);
115 if (referenceList != null) {
116 if (referenceList.getParent() instanceof PsiClass) return UsageType.CLASS_EXTENDS_IMPLEMENTS_LIST;
117 if (referenceList.getParent() instanceof PsiMethod) return UsageType.CLASS_METHOD_THROWS_LIST;
120 PsiTypeCastExpression castExpression = PsiTreeUtil.getParentOfType(element, PsiTypeCastExpression.class);
121 if (castExpression != null) {
122 if (PsiTreeUtil.isAncestor(castExpression.getCastType(), element, true)) return UsageType.CLASS_CAST_TO;
125 PsiInstanceOfExpression instanceOfExpression = PsiTreeUtil.getParentOfType(element, PsiInstanceOfExpression.class);
126 if (instanceOfExpression != null) {
127 if (PsiTreeUtil.isAncestor(instanceOfExpression.getCheckType(), element, true)) return UsageType.CLASS_INSTANCE_OF;
130 if (PsiTreeUtil.getParentOfType(element, PsiClassObjectAccessExpression.class) != null) return UsageType.CLASS_CLASS_OBJECT_ACCESS;
132 if (element instanceof PsiReferenceExpression) {
133 PsiReferenceExpression expression = (PsiReferenceExpression)element;
134 if (expression.resolve() instanceof PsiClass) {
135 return UsageType.CLASS_STATIC_MEMBER_ACCESS;
139 final PsiParameter psiParameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class);
140 if (psiParameter != null) {
141 final PsiElement scope = psiParameter.getDeclarationScope();
142 if (scope instanceof PsiMethod) return UsageType.CLASS_METHOD_PARAMETER_DECLARATION;
143 if (scope instanceof PsiCatchSection) return UsageType.CLASS_CATCH_CLAUSE_PARAMETER_DECLARATION;
144 if (scope instanceof PsiForeachStatement) return UsageType.CLASS_LOCAL_VAR_DECLARATION;
145 return null;
148 PsiField psiField = PsiTreeUtil.getParentOfType(element, PsiField.class);
149 if (psiField != null) {
150 if (PsiTreeUtil.isAncestor(psiField.getTypeElement(), element, true)) return UsageType.CLASS_FIELD_DECLARATION;
153 PsiLocalVariable psiLocalVar = PsiTreeUtil.getParentOfType(element, PsiLocalVariable.class);
154 if (psiLocalVar != null) {
155 if (PsiTreeUtil.isAncestor(psiLocalVar.getTypeElement(), element, true)) return UsageType.CLASS_LOCAL_VAR_DECLARATION;
158 PsiMethod psiMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
159 if (psiMethod != null) {
160 final PsiTypeElement retType = psiMethod.getReturnTypeElement();
161 if (retType != null && PsiTreeUtil.isAncestor(retType, element, true)) return UsageType.CLASS_METHOD_RETURN_TYPE;
164 final PsiNewExpression psiNewExpression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class);
165 if (psiNewExpression != null) {
166 final PsiJavaCodeReferenceElement classReference = psiNewExpression.getClassReference();
167 if (classReference != null && PsiTreeUtil.isAncestor(classReference, element, false)) return UsageType.CLASS_NEW_OPERATOR;
170 return null;