make SameParameterValueInspection be available in editor

This commit is contained in:
Dmitry Batkovich
2016-10-03 13:08:55 +03:00
parent 938ad4b75d
commit cb30ac46f5
5 changed files with 219 additions and 12 deletions
@@ -17,9 +17,13 @@ package com.intellij.codeInspection.sameParameterValue;
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.impl.UnusedSymbolUtil;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase;
import com.intellij.codeInspection.reference.*;
import com.intellij.psi.PsiReference;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -51,11 +55,7 @@ public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionT
if (value != null) {
if (!globalContext.shouldCheck(refParameter, this)) continue;
if (problems == null) problems = new ArrayList<>(1);
final String paramName = refParameter.getName();
problems.add(manager.createProblemDescriptor(refParameter.getElement(), InspectionsBundle.message(
"inspection.same.parameter.problem.descriptor", "<code>" + paramName + "</code>", "<code>" + value + "</code>"),
createFix(paramName, value),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false));
problems.add(registerProblem(manager, refParameter.getElement(), value));
}
}
}
@@ -63,7 +63,6 @@ public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionT
return problems == null ? null : problems.toArray(new CommonProblemDescriptor[problems.size()]);
}
@Override
protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext globalContext,
@NotNull final ProblemDescriptionsProcessor processor) {
@@ -118,7 +117,7 @@ public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionT
}
protected LocalQuickFix createFix(String paramName, String value) {
throw new UnsupportedOperationException();
return null;
}
@Override
@@ -127,4 +126,131 @@ public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionT
return fix.toString();
}
@Nullable
@Override
public LocalInspectionTool getSharedLocalInspectionTool() {
return new LocalSameParameterValueInspection(this);
}
private class LocalSameParameterValueInspection extends BaseJavaLocalInspectionTool {
private static final String NOT_CONST = "_NOT_CONST";
private final SameParameterValueInspectionBase myGlobal;
private LocalSameParameterValueInspection(SameParameterValueInspectionBase global) {
myGlobal = global;
}
@Override
@NotNull
public String getGroupDisplayName() {
return myGlobal.getGroupDisplayName();
}
@Override
@NotNull
public String getDisplayName() {
return myGlobal.getDisplayName();
}
@Override
@NotNull
public String getShortName() {
return myGlobal.getShortName();
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
boolean isOnTheFly,
@NotNull LocalInspectionToolSession session) {
return new JavaElementVisitor() {
private final UnusedDeclarationInspectionBase myDeadCodeTool;
{
InspectionProfile profile = InspectionProjectProfileManager.getInstance(holder.getProject()).getCurrentProfile();
UnusedDeclarationInspectionBase deadCodeTool = (UnusedDeclarationInspectionBase)profile.getUnwrappedTool(UnusedDeclarationInspectionBase.SHORT_NAME, holder.getFile());
myDeadCodeTool = deadCodeTool == null ? new UnusedDeclarationInspectionBase() : deadCodeTool;
}
@Override
public void visitMethod(PsiMethod method) {
if (method.isConstructor()) return;
PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length == 0) return;
if (myDeadCodeTool.isEntryPoint(method)) return;
if (!method.getHierarchicalMethodSignature().getSuperSignatures().isEmpty()) return;
PsiParameter lastParameter = parameters[parameters.length - 1];
final String[] paramValues;
final boolean hasVarArg = lastParameter.getType() instanceof PsiEllipsisType;
if (hasVarArg) {
if (parameters.length == 1) return;
paramValues = new String[parameters.length - 1];
} else {
paramValues = new String[parameters.length];
}
if (UnusedSymbolUtil.processUsages(holder.getProject(), method.getContainingFile(), method, new EmptyProgressIndicator(), null, info -> {
PsiElement element = info.getElement();
if (!(element instanceof PsiReferenceExpression)) {
return false;
}
PsiElement parent = element.getParent();
if (!(parent instanceof PsiMethodCallExpression)) {
return false;
}
PsiMethodCallExpression methodCall = (PsiMethodCallExpression) parent;
PsiExpression[] arguments = methodCall.getArgumentList().getExpressions();
if (arguments.length < paramValues.length) return false;
boolean needFurtherProcess = false;
for (int i = 0; i < paramValues.length; i++) {
Object value = paramValues[i];
final String currentArg = getArgValue(arguments[i]);
if (value == null) {
paramValues[i] = currentArg;
if (currentArg != NOT_CONST) {
needFurtherProcess = true;
}
} else if (value != NOT_CONST) {
if (!paramValues[i].equals(currentArg)) {
paramValues[i] = NOT_CONST;
} else {
needFurtherProcess = true;
}
}
}
return needFurtherProcess;
})) {
for (int i = 0, length = paramValues.length; i < length; i++) {
String value = paramValues[i];
if (value != null && value != NOT_CONST) {
holder.registerProblem(registerProblem(holder.getManager(), parameters[i], value));
}
}
}
}
};
}
private String getArgValue(PsiExpression arg) {
return arg instanceof PsiLiteralExpression ? arg.getText() : NOT_CONST;
}
}
private ProblemDescriptor registerProblem(@NotNull InspectionManager manager,
PsiParameter parameter,
String value) {
final String name = parameter.getName();
return manager.createProblemDescriptor(parameter,
InspectionsBundle.message("inspection.same.parameter.problem.descriptor",
"<code>" + name + "</code>",
"<code>" + value + "</code>"),
createFix(name, value),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false);
}
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>Test.java</file>
<line>4</line>
<module>testMethodWithSuper</module>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Actual method parameter is the same constant</problem_class>
<description>Actual value of parameter '&lt;code&gt;i&lt;/code&gt;' is always '&lt;code&gt;10&lt;/code&gt;'</description>
</problem>
</problems>
@@ -0,0 +1,20 @@
public class Test {
static class AAA {
public void mmm(int i) {
System.out.println(i + 10);
}
}
static class BBB extends AAA {
@Override
public void mmm(int i) {
System.out.println(i + 20);
}
}
public static void main(String[] args) {
new BBB().mmm(10);
new AAA().mmm(10);
}
}
@@ -0,0 +1,45 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection;
import com.intellij.JavaTestUtil;
import com.intellij.codeInspection.sameParameterValue.SameParameterValueInspection;
import com.intellij.testFramework.InspectionTestCase;
public class SameParameterValueLocalTest extends InspectionTestCase {
private final LocalInspectionTool myTool = new SameParameterValueInspection().getSharedLocalInspectionTool();
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath() + "/inspection";
}
private String getGlobalTestDir() {
return "sameParameterValue/" + getTestName(true);
}
public void testEntryPoint() {
doTest(getGlobalTestDir(), myTool);
}
public void testMethodWithSuper() {
doTest(getGlobalTestDir(), myTool);
}
public void testVarargs() {
doTest(getGlobalTestDir(), myTool);
}
}
@@ -16,19 +16,23 @@ public class SameParameterValueTest extends InspectionTestCase {
return "sameParameterValue/" + getTestName(true);
}
public void testEntryPoint() throws Exception {
public void testEntryPoint() {
doTest(getTestDir(), myTool, false, true);
}
public void testWithoutDeadCode() throws Exception {
public void testWithoutDeadCode() {
doTest(getTestDir(), myTool, false, false);
}
public void testVarargs() throws Exception {
public void testVarargs() {
doTest(getTestDir(), myTool, false, true);
}
public void testSimpleVararg() throws Exception {
public void testSimpleVararg() {
doTest(getTestDir(), myTool, false, true);
}
public void testMethodWithSuper() {
doTest(getTestDir(), myTool, false, true);
}
}