diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml
index a4b2104dd0dd..446a60139ca4 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -478,7 +478,7 @@
-
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java
index 1c060d80e94d..3db32d7e7936 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java
@@ -61,7 +61,11 @@ public abstract class GroovySuppressableInspectionTool extends LocalInspectionTo
}
public boolean isSuppressedFor(final PsiElement element) {
- return getElementToolSuppressedIn(element, getID()) != null;
+ return isElementToolSuppressedIn(element, getID());
+ }
+
+ public static boolean isElementToolSuppressedIn(final PsiElement place, final String toolId) {
+ return getElementToolSuppressedIn(place, toolId) != null;
}
@Nullable
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyUnusedDeclarationInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyUnusedDeclarationInspection.java
index 7e9b9549b300..518bc941a2f4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyUnusedDeclarationInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyUnusedDeclarationInspection.java
@@ -16,18 +16,23 @@
package org.jetbrains.plugins.groovy.codeInspection;
import com.intellij.analysis.AnalysisScope;
+import com.intellij.codeInspection.CustomSuppressableInspectionTool;
import com.intellij.codeInspection.GlobalInspectionContext;
import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.SuppressIntentionAction;
import com.intellij.codeInspection.ex.DescriptorProviderInspection;
import com.intellij.codeInspection.ex.JobDescriptor;
import com.intellij.codeInspection.ex.UnfairLocalInspectionTool;
+import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
-public class GroovyUnusedDeclarationInspection extends DescriptorProviderInspection implements UnfairLocalInspectionTool {
+public class GroovyUnusedDeclarationInspection extends DescriptorProviderInspection implements UnfairLocalInspectionTool,
+ CustomSuppressableInspectionTool {
public static final String SHORT_NAME = "GroovyUnusedDeclaration";
@Override
@@ -47,4 +52,14 @@ public class GroovyUnusedDeclarationInspection extends DescriptorProviderInspect
return JobDescriptor.EMPTY_ARRAY;
}
+ @Nullable
+ @Override
+ public SuppressIntentionAction[] getSuppressActions(@Nullable PsiElement element) {
+ return GroovySuppressableInspectionTool.getSuppressActions(SHORT_NAME);
+ }
+
+ @Override
+ public boolean isSuppressedFor(PsiElement element) {
+ return GroovySuppressableInspectionTool.isElementToolSuppressedIn(element, SHORT_NAME);
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java
index 471224f71585..91b12bf090b4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java
@@ -49,6 +49,7 @@ import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
+import org.jetbrains.plugins.groovy.codeInspection.GroovySuppressableInspectionTool;
import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection;
import org.jetbrains.plugins.groovy.editor.GroovyImportOptimizer;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
@@ -84,13 +85,15 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
}
public void doCollectInformation(@NotNull final ProgressIndicator progress) {
- final InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
- final boolean deadCodeEnabled = profile.isToolEnabled(HighlightDisplayKey.find(GroovyUnusedDeclarationInspection.SHORT_NAME), myFile);
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
VirtualFile virtualFile = myFile.getViewProvider().getVirtualFile();
if (!fileIndex.isInContent(virtualFile)) {
return;
}
+
+ final InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
+ final HighlightDisplayKey unusedDefKey = HighlightDisplayKey.find(GroovyUnusedDeclarationInspection.SHORT_NAME);
+ final boolean deadCodeEnabled = profile.isToolEnabled(unusedDefKey, myFile);
final UnusedDeclarationInspection deadCodeInspection = (UnusedDeclarationInspection)profile.getUnwrappedTool(UnusedDeclarationInspection.SHORT_NAME, myFile);
final GlobalUsageHelper usageHelper = new GlobalUsageHelper() {
public boolean isCurrentFileAlreadyChecked() {
@@ -122,13 +125,16 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
}
}
- if (deadCodeEnabled && element instanceof GrNamedElement && !PostHighlightingPass.isImplicitUsage((GrNamedElement)element, progress)) {
+ if (deadCodeEnabled &&
+ element instanceof GrNamedElement &&
+ !PostHighlightingPass.isImplicitUsage((GrNamedElement)element, progress) &&
+ !GroovySuppressableInspectionTool.isElementToolSuppressedIn(element, GroovyUnusedDeclarationInspection.SHORT_NAME)) {
PsiElement nameId = ((GrNamedElement)element).getNameIdentifierGroovy();
if (nameId.getNode().getElementType() == GroovyTokenTypes.mIDENT) {
String name = ((GrNamedElement)element).getName();
if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed((GrTypeDefinition)element, progress, usageHelper)) {
HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, "Class " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL);
- QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element));
+ QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element), unusedDefKey);
unusedDeclarations.add(highlightInfo);
}
else if (element instanceof GrMethod) {
@@ -136,14 +142,14 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
if (!PostHighlightingPass.isMethodReferenced(method, progress, usageHelper)) {
String message = (method.isConstructor() ? "Constructor" : "Method") + " " + name + " is unused";
HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, message, HighlightInfoType.UNUSED_SYMBOL);
- QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method));
+ QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method), unusedDefKey);
unusedDeclarations.add(highlightInfo);
}
}
else if (element instanceof GrField && isFieldUnused((GrField)element, progress, usageHelper)) {
HighlightInfo highlightInfo =
PostHighlightingPass.createUnusedSymbolInfo(nameId, "Property " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL);
- QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element));
+ QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element), unusedDefKey);
unusedDeclarations.add(highlightInfo);
}
else if (element instanceof GrParameter) {
@@ -168,18 +174,11 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
PsiElement scope = parameter.getDeclarationScope();
if (scope instanceof GrMethod) {
GrMethod method = (GrMethod)scope;
- if ((method.isConstructor() ||
- method.hasModifierProperty(PsiModifier.PRIVATE) ||
- method.hasModifierProperty(PsiModifier.STATIC) ||
- !method.hasModifierProperty(PsiModifier.ABSTRACT) &&
- !isOverriddenOrOverrides(method)) &&
- !method.hasModifierProperty(PsiModifier.NATIVE) &&
- !HighlightMethodUtil.isSerializationRelatedMethod(method, method.getContainingClass()) &&
- !PsiClassImplUtil.isMainOrPremainMethod(method)) {
+ if (methodMayHaveUnusedParameters(method)) {
+ PsiElement identifier = parameter.getNameIdentifierGroovy();
HighlightInfo highlightInfo = PostHighlightingPass
- .createUnusedSymbolInfo(parameter.getNameIdentifierGroovy(), "Parameter " + parameter.getName() + " is unused",
- HighlightInfoType.UNUSED_SYMBOL);
- QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedGrParameterFix(parameter));
+ .createUnusedSymbolInfo(identifier, "Parameter " + parameter.getName() + " is unused", HighlightInfoType.UNUSED_SYMBOL);
+ QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedGrParameterFix(parameter), unusedDefKey);
unusedDeclarations.add(highlightInfo);
}
}
@@ -206,6 +205,16 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
}
+ private static boolean methodMayHaveUnusedParameters(GrMethod method) {
+ return (method.isConstructor() ||
+ method.hasModifierProperty(PsiModifier.PRIVATE) ||
+ method.hasModifierProperty(PsiModifier.STATIC) ||
+ !method.hasModifierProperty(PsiModifier.ABSTRACT) && !isOverriddenOrOverrides(method)) &&
+ !method.hasModifierProperty(PsiModifier.NATIVE) &&
+ !HighlightMethodUtil.isSerializationRelatedMethod(method, method.getContainingClass()) &&
+ !PsiClassImplUtil.isMainOrPremainMethod(method);
+ }
+
private static boolean isFieldUnused(GrField field, ProgressIndicator progress, GlobalUsageHelper usageHelper) {
if (!PostHighlightingPass.isFieldUnused(field, progress, usageHelper)) return false;
final GrAccessorMethod[] getters = field.getGetters();
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy
index 8e06733c95d8..4a95a884d75f 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy
@@ -151,7 +151,7 @@ public class GroovyHighlightingTest extends LightGroovyTestCase {
public void testDefinitionUsedInClosure() { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); }
public void testDefinitionUsedInClosure2() { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); }
public void testDefinitionUsedInSwitchCase() { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); }
- public void testUnusedDefinitionForMethodMissing() {doTest(new GroovyUnusedDeclarationInspection())}
+ public void testUnusedDefinitionForMethodMissing() {doTest(new GroovyUnusedDeclarationInspection(), new UnusedDeclarationInspection())}
public void testDuplicateInnerClass() {doTest();}
public void testThisInStaticContext() {doTest();}
@@ -677,6 +677,21 @@ List> list2
doTest(new GroovyUnusedDeclarationInspection(), new UnusedDeclarationInspection())
}
+ public void testSuppressUnusedMethod() {
+ myFixture.configureByText('_.groovy', '''\
+class Foo {
+ @SuppressWarnings("GroovyUnusedDeclaration")
+ static def foo(int x) {
+ print 2
+ }
+
+ static def bar() {}
+}
+''')
+ myFixture.enableInspections(new UnusedDeclarationInspection(), new GroovyUnusedDeclarationInspection())
+ myFixture.testHighlighting(true, false, true)
+ }
+
public void testAliasInParameterType() {
myFixture.configureByText('a_.groovy', '''\
import java.awt.event.ActionListener