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
.sameParameterValue
;
18 import com
.intellij
.analysis
.AnalysisScope
;
19 import com
.intellij
.codeInsight
.daemon
.GroupNames
;
20 import com
.intellij
.codeInspection
.*;
21 import com
.intellij
.codeInspection
.reference
.*;
22 import com
.intellij
.openapi
.application
.ApplicationManager
;
23 import com
.intellij
.openapi
.diagnostic
.Logger
;
24 import com
.intellij
.openapi
.project
.Project
;
25 import com
.intellij
.openapi
.util
.Comparing
;
26 import com
.intellij
.psi
.*;
27 import com
.intellij
.psi
.search
.searches
.ReferencesSearch
;
28 import com
.intellij
.psi
.util
.PsiTreeUtil
;
29 import com
.intellij
.refactoring
.changeSignature
.ChangeSignatureProcessor
;
30 import com
.intellij
.refactoring
.changeSignature
.ParameterInfoImpl
;
31 import com
.intellij
.refactoring
.util
.CommonRefactoringUtil
;
32 import com
.intellij
.refactoring
.util
.InlineUtil
;
33 import com
.intellij
.util
.IncorrectOperationException
;
34 import org
.jetbrains
.annotations
.NotNull
;
35 import org
.jetbrains
.annotations
.Nullable
;
37 import java
.util
.ArrayList
;
38 import java
.util
.Collection
;
39 import java
.util
.List
;
44 public class SameParameterValueInspection
extends GlobalJavaInspectionTool
{
45 private static final Logger LOG
= Logger
.getInstance("#" + SameParameterValueInspection
.class.getName());
48 public CommonProblemDescriptor
[] checkElement(RefEntity refEntity
, AnalysisScope scope
, InspectionManager manager
, GlobalInspectionContext globalContext
,
49 ProblemDescriptionsProcessor processor
) {
50 ArrayList
<ProblemDescriptor
> problems
= null;
51 if (refEntity
instanceof RefMethod
) {
52 final RefMethod refMethod
= (RefMethod
)refEntity
;
54 if (refMethod
.hasSuperMethods()) return null;
56 if (refMethod
.isEntry()) return null;
58 RefParameter
[] parameters
= refMethod
.getParameters();
59 for (RefParameter refParameter
: parameters
) {
60 String value
= refParameter
.getActualValueIfSame();
62 if (problems
== null) problems
= new ArrayList
<ProblemDescriptor
>(1);
63 final String paramName
= refParameter
.getName();
64 problems
.add(manager
.createProblemDescriptor(refParameter
.getElement(), InspectionsBundle
.message(
65 "inspection.same.parameter.problem.descriptor", "<code>" + paramName
+ "</code>", "<code>" + value
+ "</code>"),
66 new InlineParameterValueFix(paramName
, value
),
67 ProblemHighlightType
.GENERIC_ERROR_OR_WARNING
));
72 return problems
== null ?
null : problems
.toArray(new CommonProblemDescriptor
[problems
.size()]);
76 protected boolean queryExternalUsagesRequests(final RefManager manager
, final GlobalJavaInspectionContext globalContext
,
77 final ProblemDescriptionsProcessor processor
) {
78 manager
.iterate(new RefJavaVisitor() {
79 @Override public void visitElement(RefEntity refEntity
) {
80 if (refEntity
instanceof RefElement
&& processor
.getDescriptions(refEntity
) != null) {
81 refEntity
.accept(new RefJavaVisitor() {
82 @Override public void visitMethod(final RefMethod refMethod
) {
83 globalContext
.enqueueMethodUsagesProcessor(refMethod
, new GlobalJavaInspectionContext
.UsagesProcessor() {
84 public boolean process(PsiReference psiReference
) {
85 processor
.ignoreElement(refMethod
);
99 public String
getDisplayName() {
100 return InspectionsBundle
.message("inspection.same.parameter.display.name");
104 public String
getGroupDisplayName() {
105 return GroupNames
.DECLARATION_REDUNDANCY
;
109 public String
getShortName() {
110 return "SameParameterValue";
114 public QuickFix
getQuickFix(final String hint
) {
115 if (hint
== null) return null;
116 final int spaceIdx
= hint
.indexOf(' ');
117 if (spaceIdx
== -1 || spaceIdx
>= hint
.length() - 1) return null; //invalid hint
118 final String paramName
= hint
.substring(0, spaceIdx
);
119 final String value
= hint
.substring(spaceIdx
+ 1);
120 return new InlineParameterValueFix(paramName
, value
);
124 public String
getHint(final QuickFix fix
) {
125 final InlineParameterValueFix valueFix
= (InlineParameterValueFix
)fix
;
126 return valueFix
.getParamName() + " " + valueFix
.getValue();
129 public static class InlineParameterValueFix
implements LocalQuickFix
{
130 private final String myValue
;
131 private final String myParameterName
;
133 public InlineParameterValueFix(final String parameterName
, final String value
) {
135 myParameterName
= parameterName
;
139 public String
getName() {
140 return InspectionsBundle
.message("inspection.same.parameter.fix.name", myParameterName
, myValue
);
144 public String
getFamilyName() {
148 public void applyFix(@NotNull final Project project
, @NotNull ProblemDescriptor descriptor
) {
149 final PsiElement element
= descriptor
.getPsiElement();
150 final PsiMethod method
= PsiTreeUtil
.getParentOfType(element
, PsiMethod
.class);
151 LOG
.assertTrue(method
!= null);
152 PsiParameter parameter
= PsiTreeUtil
.getParentOfType(element
, PsiParameter
.class, false);
153 if (parameter
== null) {
154 final PsiParameter
[] parameters
= method
.getParameterList().getParameters();
155 for (PsiParameter psiParameter
: parameters
) {
156 if (Comparing
.strEqual(psiParameter
.getName(), myParameterName
)) {
157 parameter
= psiParameter
;
162 if (parameter
== null) return;
163 if (!CommonRefactoringUtil
.checkReadOnlyStatus(project
, parameter
)) return;
165 final PsiExpression defToInline
;
167 defToInline
= JavaPsiFacade
.getInstance(project
).getElementFactory().createExpressionFromText(myValue
, parameter
);
169 catch (IncorrectOperationException e
) {
173 inlineSameParameterValue(method
, parameter
, defToInline
);
176 public static void inlineSameParameterValue(final PsiMethod method
, final PsiParameter parameter
, final PsiExpression defToInline
) {
177 final Collection
<PsiReference
> refsToInline
= ReferencesSearch
.search(parameter
).findAll();
179 final Runnable runnable
= new Runnable() {
182 PsiExpression
[] exprs
= new PsiExpression
[refsToInline
.size()];
184 for (PsiReference reference
: refsToInline
) {
185 if (reference
instanceof PsiJavaCodeReferenceElement
) {
186 exprs
[idx
++] = InlineUtil
.inlineVariable(parameter
, defToInline
, (PsiJavaCodeReferenceElement
)reference
);
190 for (final PsiExpression expr
: exprs
) {
191 if (expr
!= null) InlineUtil
.tryToInlineArrayCreationForVarargs(expr
);
194 removeParameter(method
, parameter
);
196 catch (IncorrectOperationException e
) {
202 ApplicationManager
.getApplication().runWriteAction(runnable
);
205 public static void removeParameter(final PsiMethod method
, final PsiParameter parameter
) {
206 final PsiParameter
[] parameters
= method
.getParameterList().getParameters();
207 final List
<ParameterInfoImpl
> psiParameters
= new ArrayList
<ParameterInfoImpl
>();
209 final String paramName
= parameter
.getName();
210 for (PsiParameter param
: parameters
) {
211 if (!Comparing
.strEqual(paramName
, param
.getName())) {
212 psiParameters
.add(new ParameterInfoImpl(paramIdx
, param
.getName(), param
.getType()));
217 new ChangeSignatureProcessor(method
.getProject(), method
, false, null, method
.getName(), method
.getReturnType(),
218 psiParameters
.toArray(new ParameterInfoImpl
[psiParameters
.size()])).run();
221 public String
getValue() {
225 public String
getParamName() {
226 return myParameterName
;