update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInspection / reference / RefJavaUtilImpl.java
blobd5579d6269e0eba0bd59bd9d36ef8d5c12bcafee
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.
18 * User: anna
19 * Date: 21-Dec-2007
21 package com.intellij.codeInspection.reference;
23 import com.intellij.codeInspection.InspectionsBundle;
24 import com.intellij.psi.*;
25 import com.intellij.psi.search.GlobalSearchScope;
26 import com.intellij.psi.util.MethodSignatureUtil;
27 import com.intellij.psi.util.PsiTreeUtil;
28 import com.intellij.psi.util.PsiUtil;
29 import com.intellij.util.VisibilityUtil;
30 import org.jetbrains.annotations.Nullable;
32 public class RefJavaUtilImpl extends RefJavaUtil{
34 public void addReferences(final PsiModifierListOwner psiFrom, final RefJavaElement ref, @Nullable PsiElement findIn) {
35 final RefJavaElementImpl refFrom = (RefJavaElementImpl)ref;
36 if (findIn != null) {
37 findIn.accept(
38 new JavaRecursiveElementWalkingVisitor() {
39 @Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
42 @Override public void visitReferenceExpression(PsiReferenceExpression expression) {
43 visitElement(expression);
45 PsiElement psiResolved = expression.resolve();
47 if (psiResolved instanceof PsiModifierListOwner) {
48 if (isDeprecated(psiResolved)) refFrom.setUsesDeprecatedApi(true);
51 RefElement refResolved = refFrom.getRefManager().getReference(psiResolved);
52 refFrom.addReference(
53 refResolved, psiResolved, psiFrom, PsiUtil.isAccessedForWriting(expression),
54 PsiUtil.isAccessedForReading(expression), expression
57 if (refResolved instanceof RefMethod) {
58 updateRefMethod(psiResolved, refResolved, expression, psiFrom, refFrom);
63 @Override public void visitEnumConstant(PsiEnumConstant enumConstant) {
64 super.visitEnumConstant(enumConstant);
65 processNewLikeConstruct(enumConstant.resolveConstructor(), enumConstant.getArgumentList());
68 @Override public void visitNewExpression(PsiNewExpression newExpr) {
69 super.visitNewExpression(newExpr);
70 PsiMethod psiConstructor = newExpr.resolveConstructor();
71 final PsiExpressionList argumentList = newExpr.getArgumentList();
73 RefMethod refConstructor = processNewLikeConstruct(psiConstructor, argumentList);
75 if (refConstructor == null) { // No explicit constructor referenced. Should use default one.
76 PsiType newType = newExpr.getType();
77 if (newType instanceof PsiClassType) {
78 processClassReference(PsiUtil.resolveClassInType(newType), refFrom, psiFrom);
83 @Nullable
84 private RefMethod processNewLikeConstruct(final PsiMethod psiConstructor, final PsiExpressionList argumentList) {
85 if (psiConstructor != null) {
86 if (isDeprecated(psiConstructor)) refFrom.setUsesDeprecatedApi(true);
89 RefMethodImpl refConstructor = (RefMethodImpl)refFrom.getRefManager().getReference(
90 psiConstructor
92 refFrom.addReference(refConstructor, psiConstructor, psiFrom, false, true, null);
94 if (argumentList != null) {
95 PsiExpression[] psiParams = argumentList.getExpressions();
96 for (PsiExpression param : psiParams) {
97 param.accept(this);
100 if (refConstructor != null) {
101 refConstructor.updateParameterValues(psiParams);
104 return refConstructor;
107 @Override public void visitAnonymousClass(PsiAnonymousClass psiClass) {
108 RefClassImpl refClass = (RefClassImpl)refFrom.getRefManager().getReference(psiClass);
109 refFrom.addReference(refClass, psiClass, psiFrom, false, true, null);
112 @Override public void visitReturnStatement(PsiReturnStatement statement) {
113 super.visitReturnStatement(statement);
115 if (refFrom instanceof RefMethodImpl) {
116 RefMethodImpl refMethod = (RefMethodImpl)refFrom;
117 refMethod.updateReturnValueTemplate(statement.getReturnValue());
121 @Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
122 super.visitClassObjectAccessExpression(expression);
123 final PsiTypeElement operand = expression.getOperand();
124 final PsiType type = operand.getType();
125 if (type instanceof PsiClassType) {
126 processClassReference(((PsiClassType)type).resolve(), refFrom, psiFrom);
130 private void processClassReference(final PsiClass psiClass, final RefJavaElementImpl refFrom, final PsiModifierListOwner psiFrom) {
131 if (psiClass != null) {
132 RefClassImpl refClass = (RefClassImpl)refFrom.getRefManager().getReference(psiClass);
134 if (refClass != null) {
135 RefMethodImpl refDefaultConstructor = (RefMethodImpl)refClass.getDefaultConstructor();
137 if (refDefaultConstructor != null && !(refDefaultConstructor instanceof RefImplicitConstructor)) {
138 refDefaultConstructor.addInReference(refFrom);
139 refFrom.addOutReference(refDefaultConstructor);
141 else {
142 refFrom.addReference(refClass, psiClass, psiFrom, false, true, null);
152 private void updateRefMethod(PsiElement psiResolved,
153 RefElement refResolved,
154 PsiElement refExpression,
155 final PsiElement psiFrom,
156 final RefElement refFrom) {
157 PsiMethod psiMethod = (PsiMethod)psiResolved;
158 RefMethodImpl refMethod = (RefMethodImpl)refResolved;
160 PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(
161 refExpression,
162 PsiMethodCallExpression.class
164 if (call != null) {
165 PsiType returnType = psiMethod.getReturnType();
166 if (!psiMethod.isConstructor() && returnType != PsiType.VOID) {
167 if (!(call.getParent() instanceof PsiExpressionStatement)) {
168 refMethod.setReturnValueUsed(true);
171 addTypeReference(psiFrom, returnType, refFrom.getRefManager());
174 PsiExpressionList argumentList = call.getArgumentList();
175 if (argumentList.getExpressions().length > 0) {
176 refMethod.updateParameterValues(argumentList.getExpressions());
179 final PsiExpression psiExpression = call.getMethodExpression().getQualifierExpression();
180 if (psiExpression != null) {
181 final PsiType usedType = psiExpression.getType();
182 if (usedType != null) {
183 final String fqName = psiMethod.getContainingClass().getQualifiedName();
184 if (fqName != null) {
185 final PsiClassType methodOwnerType = JavaPsiFacade.getInstance(call.getProject()).getElementFactory()
186 .createTypeByFQClassName(fqName, GlobalSearchScope.allScope(psiMethod.getProject()));
187 if (!usedType.equals(methodOwnerType)) {
188 refMethod.setCalledOnSubClass(true);
199 public RefClass getTopLevelClass(RefElement refElement) {
200 RefEntity refParent = refElement.getOwner();
202 while (refParent != null && refParent instanceof RefElement && !(refParent instanceof RefFile)) {
203 refElement = (RefElementImpl)refParent;
204 refParent = refParent.getOwner();
207 return (RefClass)refElement;
210 public boolean isInheritor(RefClass subClass, RefClass superClass) {
211 if (subClass == superClass) return true;
213 for (RefClass baseClass : subClass.getBaseClasses()) {
214 if (isInheritor(baseClass, superClass)) return true;
217 return false;
220 @Nullable
221 public String getPackageName(RefEntity refEntity) {
222 if (refEntity instanceof RefProject) {
223 return null;
225 RefPackage refPackage = getPackage(refEntity);
227 return refPackage == null ? InspectionsBundle.message("inspection.reference.default.package") : refPackage.getQualifiedName();
230 public String getAccessModifier(PsiModifierListOwner psiElement) {
231 if (psiElement instanceof PsiParameter) return PsiModifier.PACKAGE_LOCAL;
233 PsiModifierList list = psiElement.getModifierList();
234 String result = PsiModifier.PACKAGE_LOCAL;
236 if (list != null) {
237 if (list.hasModifierProperty(PsiModifier.PRIVATE)) {
238 result = PsiModifier.PRIVATE;
240 else if (list.hasModifierProperty(PsiModifier.PROTECTED)) {
241 result = PsiModifier.PROTECTED;
243 else if (list.hasModifierProperty(PsiModifier.PUBLIC)) {
244 result = PsiModifier.PUBLIC;
246 else if (psiElement.getParent() instanceof PsiClass) {
247 PsiClass ownerClass = (PsiClass)psiElement.getParent();
248 if (ownerClass.isInterface()) {
249 result = PsiModifier.PUBLIC;
254 return result;
257 @Nullable public RefClass getOwnerClass(RefManager refManager, PsiElement psiElement) {
258 while (psiElement != null && !(psiElement instanceof PsiClass)) {
259 psiElement = psiElement.getParent();
262 return psiElement != null ? (RefClass)refManager.getReference(psiElement) : null;
265 @Nullable public RefClass getOwnerClass(RefElement refElement) {
266 RefEntity parent = refElement.getOwner();
268 while (!(parent instanceof RefClass) && parent instanceof RefElement) {
269 parent = parent.getOwner();
272 if (parent instanceof RefClass) return (RefClass)parent;
274 return null;
279 public boolean isMethodOnlyCallsSuper(PsiMethod method) {
280 boolean hasStatements = false;
281 PsiCodeBlock body = method.getBody();
282 if (body != null) {
283 PsiStatement[] statements = body.getStatements();
284 for (PsiStatement statement : statements) {
285 boolean isCallToSameSuper = false;
286 if (statement instanceof PsiExpressionStatement) {
287 isCallToSameSuper = isCallToSuperMethod(((PsiExpressionStatement)statement).getExpression(), method);
289 else if (statement instanceof PsiReturnStatement) {
290 PsiExpression expression = ((PsiReturnStatement)statement).getReturnValue();
291 isCallToSameSuper = expression == null || isCallToSuperMethod(expression, method);
294 hasStatements = true;
295 if (isCallToSameSuper) continue;
297 return false;
301 if (hasStatements) {
302 final PsiMethod[] superMethods = method.findSuperMethods();
303 for (PsiMethod superMethod : superMethods) {
304 if (VisibilityUtil.compare(VisibilityUtil.getVisibilityModifier(superMethod.getModifierList()),
305 VisibilityUtil.getVisibilityModifier(method.getModifierList())) > 0) return false;
308 return hasStatements;
311 public boolean isCallToSuperMethod(PsiExpression expression, PsiMethod method) {
312 if (expression instanceof PsiMethodCallExpression) {
313 PsiMethodCallExpression methodCall = (PsiMethodCallExpression)expression;
314 if (methodCall.getMethodExpression().getQualifierExpression() instanceof PsiSuperExpression) {
315 PsiMethod superMethod = (PsiMethod)methodCall.getMethodExpression().resolve();
316 if (superMethod == null || !MethodSignatureUtil.areSignaturesEqual(method, superMethod)) return false;
317 PsiExpression[] args = methodCall.getArgumentList().getExpressions();
318 PsiParameter[] parms = method.getParameterList().getParameters();
320 for (int i = 0; i < args.length; i++) {
321 PsiExpression arg = args[i];
322 if (!(arg instanceof PsiReferenceExpression)) return false;
323 if (!parms[i].equals(((PsiReferenceExpression)arg).resolve())) return false;
326 return true;
330 return false;
333 public int compareAccess(String a1, String a2) {
334 int i1 = getAccessNumber(a1);
335 int i2 = getAccessNumber(a2);
337 if (i1 == i2) return 0;
338 if (i1 < i2) return -1;
339 return 1;
342 @SuppressWarnings("StringEquality")
343 private static int getAccessNumber(String a) {
344 if (a == PsiModifier.PRIVATE) {
345 return 0;
347 else if (a == PsiModifier.PACKAGE_LOCAL) {
348 return 1;
350 else if (a == PsiModifier.PROTECTED) {
351 return 2;
353 else if (a == PsiModifier.PUBLIC) return 3;
355 return -1;
358 public void setAccessModifier(RefJavaElement refElement, String newAccess) {
359 ((RefJavaElementImpl)refElement).setAccessModifier(newAccess);
362 public void setIsStatic(RefJavaElement refElement, boolean isStatic) {
363 ((RefJavaElementImpl)refElement).setIsStatic(isStatic);
366 public void setIsFinal(RefJavaElement refElement, boolean isFinal) {
367 ((RefJavaElementImpl)refElement).setIsFinal(isFinal);
370 public void addTypeReference(PsiElement psiElement, PsiType psiType, RefManager refManager) {
371 RefClass ownerClass = getOwnerClass(refManager, psiElement);
373 if (ownerClass != null) {
374 psiType = psiType.getDeepComponentType();
376 if (psiType instanceof PsiClassType) {
377 PsiClass psiClass = PsiUtil.resolveClassInType(psiType);
378 if (psiClass != null && refManager.belongsToScope(psiClass)) {
379 RefClassImpl refClass = (RefClassImpl)refManager.getReference(psiClass);
380 if (refClass != null) {
381 refClass.addTypeReference(ownerClass);