Inspections - pass onTheFly into ProblemDescriptors & use it to create LAZY refs...
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInspection / miscGenerics / RedundantArrayForVarargsCallInspection.java
blob18496c684a7e699939863402e7c5e10d031357d6
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.codeInspection.miscGenerics;
18 import com.intellij.codeInsight.CodeInsightUtilBase;
19 import com.intellij.codeInsight.daemon.GroupNames;
20 import com.intellij.codeInspection.*;
21 import com.intellij.openapi.diagnostic.Logger;
22 import com.intellij.openapi.project.Project;
23 import com.intellij.psi.*;
24 import com.intellij.psi.util.PsiUtil;
25 import com.intellij.refactoring.util.InlineUtil;
26 import com.intellij.util.IncorrectOperationException;
27 import org.jetbrains.annotations.NonNls;
28 import org.jetbrains.annotations.NotNull;
29 import org.jetbrains.annotations.Nullable;
31 import java.util.ArrayList;
32 import java.util.List;
34 /**
35 * @author ven
37 public class RedundantArrayForVarargsCallInspection extends GenericsInspectionToolBase {
38 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.miscGenerics.RedundantArrayForVarargsCallInspection");
39 private final LocalQuickFix myQuickFixAction = new MyQuickFix();
41 private static class MyQuickFix implements LocalQuickFix {
42 public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
43 PsiNewExpression arrayCreation = (PsiNewExpression) descriptor.getPsiElement();
44 if (arrayCreation == null || !arrayCreation.isValid()) return;
45 if (!CodeInsightUtilBase.prepareFileForWrite(arrayCreation.getContainingFile())) return;
46 InlineUtil.inlineArrayCreationForVarargs(arrayCreation);
49 @NotNull
50 public String getFamilyName() {
51 return getName();
54 @NotNull
55 public String getName() {
56 return InspectionsBundle.message("inspection.redundant.array.creation.quickfix");
60 public ProblemDescriptor[] getDescriptions(PsiElement place, final InspectionManager manager, final boolean isOnTheFly) {
61 if (!PsiUtil.isLanguageLevel5OrHigher(place)) return null;
62 final List<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>();
63 place.accept(new JavaRecursiveElementWalkingVisitor() {
64 @Override public void visitCallExpression(PsiCallExpression expression) {
65 super.visitCallExpression(expression);
66 checkCall(expression);
69 @Override public void visitEnumConstant(PsiEnumConstant enumConstant) {
70 super.visitEnumConstant(enumConstant);
71 checkCall(enumConstant);
74 @Override public void visitClass(PsiClass aClass) {
75 //do not go inside to prevent multiple signals of the same problem
78 private void checkCall(PsiCall expression) {
79 final JavaResolveResult resolveResult = expression.resolveMethodGenerics();
80 PsiElement element = resolveResult.getElement();
81 final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
82 if (element instanceof PsiMethod && ((PsiMethod)element).isVarArgs()) {
83 PsiMethod method = (PsiMethod)element;
84 PsiParameter[] parameters = method.getParameterList().getParameters();
85 PsiExpressionList argumentList = expression.getArgumentList();
86 if (argumentList != null) {
87 PsiExpression[] args = argumentList.getExpressions();
88 if (parameters.length == args.length) {
89 PsiExpression lastArg = args[args.length - 1];
90 PsiParameter lastParameter = parameters[args.length - 1];
91 PsiType lastParamType = lastParameter.getType();
92 LOG.assertTrue(lastParamType instanceof PsiEllipsisType);
93 if (lastArg instanceof PsiNewExpression &&
94 substitutor.substitute(((PsiEllipsisType) lastParamType).toArrayType()).equals(lastArg.getType())) {
95 PsiExpression[] initializers = getInitializers((PsiNewExpression)lastArg);
96 if (initializers != null) {
97 if (isSafeToFlatten(expression, method, initializers)) {
98 final ProblemDescriptor descriptor = manager.createProblemDescriptor(lastArg,
99 InspectionsBundle.message("inspection.redundant.array.creation.for.varargs.call.descriptor"),
100 myQuickFixAction,
101 ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
102 isOnTheFly);
104 problems.add(descriptor);
113 private boolean isSafeToFlatten(PsiCall callExpression, PsiMethod oldRefMethod, PsiExpression[] arrayElements) {
114 if (arrayElements.length == 1) {
115 PsiType type = arrayElements[0].getType();
116 // change foo(new Object[]{array}) to foo(array) is not safe
117 if (PsiType.NULL.equals(type) || type instanceof PsiArrayType) return false;
119 PsiCall copy = (PsiCall)callExpression.copy();
120 PsiExpressionList copyArgumentList = copy.getArgumentList();
121 LOG.assertTrue(copyArgumentList != null);
122 PsiExpression[] args = copyArgumentList.getExpressions();
123 try {
124 args[args.length - 1].delete();
125 if (arrayElements.length > 0) {
126 copyArgumentList.addRange(arrayElements[0], arrayElements[arrayElements.length - 1]);
128 final JavaResolveResult resolveResult = copy.resolveMethodGenerics();
129 return resolveResult.isValidResult() && resolveResult.getElement() == oldRefMethod;
131 catch (IncorrectOperationException e) {
132 return false;
136 if (problems.isEmpty()) return null;
137 return problems.toArray(new ProblemDescriptor[problems.size()]);
140 @Nullable
141 private static PsiExpression[] getInitializers(final PsiNewExpression newExpression) {
142 PsiArrayInitializerExpression initializer = newExpression.getArrayInitializer();
143 if (initializer != null) {
144 return initializer.getInitializers();
146 PsiExpression[] dims = newExpression.getArrayDimensions();
147 if (dims.length > 0) {
148 PsiExpression firstDimension = dims[0];
149 Object value =
150 JavaPsiFacade.getInstance(newExpression.getProject()).getConstantEvaluationHelper().computeConstantExpression(firstDimension);
151 if (value instanceof Integer && ((Integer)value).intValue() == 0) return PsiExpression.EMPTY_ARRAY;
154 return null;
157 @NotNull
158 public String getGroupDisplayName() {
159 return GroupNames.VERBOSE_GROUP_NAME;
162 @NotNull
163 public String getDisplayName() {
164 return InspectionsBundle.message("inspection.redundant.array.creation.display.name");
167 @NotNull
168 @NonNls
169 public String getShortName() {
170 return "RedundantArrayCreation";