diff --git a/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml b/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml
index 540b98060310..21e9f308c395 100644
--- a/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml
+++ b/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml
@@ -155,9 +155,6 @@
-
-1) {
myID = id.substring(0, idx);
- myProblemLine = id.substring(idx);
}
else {
myID = id;
- myProblemLine = null;
}
}
@@ -72,7 +63,7 @@ public class RemoveSuppressWarningAction implements LocalQuickFix {
PsiElement element = descriptor.getPsiElement();
try {
if (element != null) {
- final PsiJavaDocumentedElement commentOwner = PsiTreeUtil.getParentOfType(element, PsiJavaDocumentedElement.class);
+ final PsiJavaDocumentedElement commentOwner = PsiTreeUtil.getParentOfType(element, PsiJavaDocumentedElement.class, false);
if (commentOwner != null) {
final PsiElement psiElement = JavaSuppressionUtil.getElementMemberSuppressedIn(commentOwner, myID);
if (psiElement instanceof PsiAnnotation) {
@@ -113,10 +104,6 @@ public class RemoveSuppressWarningAction implements LocalQuickFix {
}
private void removeFromComment(final PsiComment comment, final boolean checkLine) throws IncorrectOperationException {
- if (checkLine) {
- final PsiStatement statement = PsiTreeUtil.getNextSiblingOfType(comment, PsiStatement.class);
- if (statement != null && !Comparing.strEqual(statement.getText(), myProblemLine)) return;
- }
String newText = removeFromElementText(comment);
if (newText != null) {
if (newText.isEmpty()) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
index 3cf304bb107a..b03e2a67ff90 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
@@ -3,13 +3,15 @@
package com.intellij.codeInspection;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
+import com.intellij.codeInsight.daemon.impl.RemoveSuppressWarningAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiDocCommentOwner;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public class SuppressManagerImpl extends SuppressManager {
+public class SuppressManagerImpl extends SuppressManager implements RedundantSuppressionDetector {
private static final Logger LOG = Logger.getInstance(SuppressManager.class);
@Override
@@ -53,4 +55,20 @@ public class SuppressManagerImpl extends SuppressManager {
public boolean alreadyHas14Suppressions(@NotNull final PsiDocCommentOwner commentOwner) {
return JavaSuppressionUtil.alreadyHas14Suppressions(commentOwner);
}
+
+ @Override
+ public String getSuppressionIds(@NotNull PsiElement element) {
+ return JavaSuppressionUtil.getSuppressedInspectionIdsIn(element);
+ }
+
+ @Override
+ public boolean isSuppressionFor(@NotNull PsiElement elementWithSuppression, @NotNull PsiElement place, @NotNull String toolId) {
+ PsiElement suppressionScope = JavaSuppressionUtil.getElementToolSuppressedIn(place, toolId);
+ return suppressionScope != null && PsiTreeUtil.isAncestor(elementWithSuppression, suppressionScope, false);
+ }
+
+ @Override
+ public LocalQuickFix createRemoveRedundantSuppressionFix(@NotNull String toolId) {
+ return new RemoveSuppressWarningAction(toolId);
+ }
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before1.java
index 825706ca2b75..601fcbd95354 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before1.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before1.java
@@ -7,7 +7,7 @@ public class Test {
}
void foo() {
- //noinspection unchecked
+ //noinspection unchecked
foo(new ArrayList());
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before2.java
index d8436646d0dc..ea4f460f44ac 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before2.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before2.java
@@ -7,7 +7,7 @@ public class Test {
}
void foo() {
- //noinspection unchecked,blah-blah-toolid
+ //noinspection unchecked,blah-blah-toolid
foo(new ArrayList());
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before3.java
index 61a94caa32b5..c6ef8991cc9e 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before3.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before3.java
@@ -12,7 +12,7 @@ public class Test {
}
void foo() {
- //noinspection unchecked
+ //noinspection unchecked
foo(new ArrayList()).addAll(foo1(new ArrayList()));
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before4.java
index f408873bf4dd..d3b9aeef5b4d 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before4.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before4.java
@@ -8,7 +8,7 @@ public class Test {
}
void foo() {
- //noinspection unchecked
+ //noinspection unchecked
List> list = foo(new ArrayList());
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before5.java
index b294d2d5a2df..a787de0a33d2 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before5.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before5.java
@@ -7,8 +7,8 @@ public class Test {
return null;
}
- @SuppressWarnings("unchecked")
- void foo() {
+ @SuppressWarnings("unchecked")
+ void foo() {
List> list = foo(new ArrayList());
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before6.java
index 60f4268bf047..92c9bdea1298 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before6.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before6.java
@@ -1,8 +1,8 @@
// "Remove 'unchecked' suppression" "true"
import java.util.*;
-@SuppressWarnings("unchecked")
-public class Test {
+@SuppressWarnings("unchecked")
+public class Test {
@SafeVarargs
static List foo(T... t){
return null;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before9.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before9.java
index e34ee0e8c198..0af466c7a84e 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before9.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantUncheckedVarargs/before9.java
@@ -1,8 +1,8 @@
// "Remove 'unchecked' suppression" "true"
import java.util.*;
-@SuppressWarnings({"unchecked", "bla-blah-toolid"})
-public class Test {
+@SuppressWarnings({"unchecked", "bla-blah-toolid"})
+public class Test {
@SafeVarargs
static List foo(T... t){
return null;
diff --git a/java/java-tests/testData/inspection/redundantSuppress/moduleInfo/expected.xml b/java/java-tests/testData/inspection/redundantSuppress/moduleInfo/expected.xml
index 9bc83e9c78ed..42e08b9f9adf 100644
--- a/java/java-tests/testData/inspection/redundantSuppress/moduleInfo/expected.xml
+++ b/java/java-tests/testData/inspection/redundantSuppress/moduleInfo/expected.xml
@@ -4,7 +4,6 @@
module-info.java
5
-
Redundant suppression
Redundant suppression
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java
index 4e3b3a1d46bd..19a899a3eec4 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java
@@ -16,84 +16,17 @@
package com.intellij.java.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.InspectionToolWrapper;
-import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.codeInspection.PossibleHeapPollutionVarargsInspection;
+import com.intellij.codeInspection.RedundantSuppressInspection;
import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection;
-import com.intellij.psi.*;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
public class RemoveRedundantUncheckedSuppressionTest extends LightQuickFixParameterizedTestCase {
- @NotNull
+
@Override
- protected LocalInspectionTool[] configureLocalInspectionTools() {
- final PossibleHeapPollutionVarargsInspection varargsInspection = new PossibleHeapPollutionVarargsInspection();
- final UncheckedWarningLocalInspection warningLocalInspection = new UncheckedWarningLocalInspection();
- final RedundantSuppressInspection inspection = new RedundantSuppressInspection(){
- @NotNull
- @Override
- protected InspectionToolWrapper[] getInspectionTools(PsiElement psiElement, @NotNull InspectionManager manager) {
- return new InspectionToolWrapper[]{
- new LocalInspectionToolWrapper(varargsInspection),
- new LocalInspectionToolWrapper(warningLocalInspection)
- };
- }
- };
-
- return new LocalInspectionTool[] {
- new LocalInspectionTool() {
- @Nls
- @NotNull
- @Override
- public String getGroupDisplayName() {
- return inspection.getGroupDisplayName();
- }
-
- @Nls
- @NotNull
- @Override
- public String getDisplayName() {
- return inspection.getDisplayName();
- }
-
- @NotNull
- @Override
- public String getShortName() {
- return inspection.getShortName();
- }
-
- @NotNull
- @Override
- public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder,
- boolean isOnTheFly,
- @NotNull LocalInspectionToolSession session) {
- return new JavaElementVisitor() {
- @Override
- public void visitClass(PsiClass aClass) {
- checkMember(aClass, inspection, holder);
- }
-
- @Override
- public void visitMethod(PsiMethod method) {
- checkMember(method, inspection, holder);
- }
- };
- }
-
- private void checkMember(PsiMember member, RedundantSuppressInspection inspection, ProblemsHolder holder) {
- final ProblemDescriptor[] problemDescriptors = inspection.checkElement(member, InspectionManager.getInstance(getProject()));
- if (problemDescriptors != null) {
- for (ProblemDescriptor problemDescriptor : problemDescriptors) {
- holder.registerProblem(problemDescriptor);
- }
- }
- }
- },
- varargsInspection,
- warningLocalInspection
- };
+ protected void setUp() throws Exception {
+ super.setUp();
+ enableInspectionTools(new RedundantSuppressInspection(), new PossibleHeapPollutionVarargsInspection(), new UncheckedWarningLocalInspection());
}
@Override
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/RedundantSuppressTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/RedundantSuppressTest.java
index f95a66380153..ce6871db7105 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInspection/RedundantSuppressTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/RedundantSuppressTest.java
@@ -63,7 +63,7 @@ public class RedundantSuppressTest extends InspectionTestCase {
}
public void testModuleInfo() {
- doTest();
+ doTest("redundantSuppress/" + getTestName(true), myWrapper,"java 1.5",false);
}
public void testDefaultFile() {
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/RedundantSuppressionDetector.java b/platform/analysis-api/src/com/intellij/codeInspection/RedundantSuppressionDetector.java
new file mode 100644
index 000000000000..3d9b22ec200a
--- /dev/null
+++ b/platform/analysis-api/src/com/intellij/codeInspection/RedundantSuppressionDetector.java
@@ -0,0 +1,42 @@
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.codeInspection;
+
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+
+public interface RedundantSuppressionDetector {
+
+ /**
+ * @return comma separated list of suppress ids configured in this {@code element}
+ */
+ @Nullable
+ String getSuppressionIds(@NotNull PsiElement element);
+
+ /**
+ * @return quickfix to remove {@code toolId} suppression from list of suppressions
+ */
+ @Nullable
+ LocalQuickFix createRemoveRedundantSuppressionFix(@NotNull String toolId);
+
+ /**
+ * @param elementWithSuppression e.g. comment or @SuppressWarning annotation
+ * @param place element with currently suppressed warning
+ * @return true if {@code place} is suppressed by {@code elementWithSuppression}
+ */
+ boolean isSuppressionFor(@NotNull PsiElement elementWithSuppression, @NotNull PsiElement place, @NotNull String toolId);
+
+ /**
+ * @return range with {@code toolId} to highlight in the editor
+ */
+ default TextRange getHighlightingRange(PsiElement elementWithSuppression, String toolId) {
+ String suppressionElementText = elementWithSuppression.getText();
+ int idx = suppressionElementText.indexOf(toolId);
+ return idx > 0
+ ? new TextRange(idx, idx + toolId.length())
+ : new TextRange(0, suppressionElementText.length());
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
index 926c90a678ae..33dc5223a529 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
@@ -58,6 +58,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
+import java.util.stream.Collectors;
/**
* @author max
@@ -74,6 +75,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
private final String myShortcutText;
private final SeverityRegistrar mySeverityRegistrar;
private final InspectionProfileWrapper myProfileWrapper;
+ private final Map> mySuppressedElements = new HashMap<>();
public LocalInspectionsPass(@NotNull PsiFile file,
@Nullable Document document,
@@ -224,6 +226,40 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
myInfos = new ArrayList<>();
addHighlightsFromResults(myInfos);
+
+ if (isOnTheFly) highlightRedundantSuppressions(toolWrappers, iManager, inside, outside, elementDialectIds);
+ }
+
+ private void highlightRedundantSuppressions(@NotNull List extends LocalInspectionToolWrapper> toolWrappers,
+ @NotNull InspectionManager iManager,
+ List inside,
+ List outside,
+ Set elementDialectIds) {
+ HighlightDisplayKey key = HighlightDisplayKey.find(RedundantSuppressInspection.SHORT_NAME);
+ final InspectionProfileImpl inspectionProfile = myProfileWrapper.getInspectionProfile();
+ if (key != null && inspectionProfile.isToolEnabled(key, getFile())) {
+ InspectionToolWrapper toolWrapper = inspectionProfile.getToolById(RedundantSuppressInspection.SHORT_NAME, getFile());
+ InspectionSuppressor suppressor = LanguageInspectionSuppressors.INSTANCE.forLanguage(getFile().getLanguage());
+ if (suppressor instanceof RedundantSuppressionDetector) {
+ Set activeTools = toolWrappers.stream().map(tool -> tool.getID()).collect(Collectors.toSet());
+ LocalInspectionTool
+ localTool = ((RedundantSuppressInspection)toolWrapper.getTool()).createLocalTool((RedundantSuppressionDetector)suppressor, mySuppressedElements, activeTools);
+ ProblemsHolder holder = new ProblemsHolder(iManager, getFile(), true);
+ PsiElementVisitor visitor = localTool.buildVisitor(holder, true);
+ InspectionEngine.acceptElements(inside, visitor, elementDialectIds, null);
+ InspectionEngine.acceptElements(outside, visitor, elementDialectIds, null);
+
+ HighlightSeverity severity = myProfileWrapper.getErrorLevel(key, getFile()).getSeverity();
+ for (ProblemDescriptor descriptor : holder.getResults()) {
+ ProgressManager.checkCanceled();
+ PsiElement element = descriptor.getPsiElement();
+ if (element != null) {
+ Document thisDocument = documentManager.getDocument(getFile());
+ createHighlightsForDescriptor(myInfos, emptyActionRegistered, ilManager, getFile(), thisDocument, new LocalInspectionToolWrapper(localTool), severity, descriptor, element);
+ }
+ }
+ }
+ }
}
@NotNull
@@ -473,7 +509,10 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
@NotNull ProblemDescriptor descriptor,
@NotNull PsiElement element) {
LocalInspectionTool tool = toolWrapper.getTool();
- if (myIgnoreSuppressed && SuppressionUtil.inspectionResultSuppressed(element, tool)) return;
+ if (myIgnoreSuppressed && SuppressionUtil.inspectionResultSuppressed(element, tool)) {
+ mySuppressedElements.computeIfAbsent(toolWrapper.getID(), shortName -> new HashSet<>()).add(element);
+ return;
+ }
HighlightInfoType level = ProblemDescriptorUtil.highlightTypeFromDescriptor(descriptor, severity, mySeverityRegistrar);
@NonNls String message = ProblemDescriptorUtil.renderDescriptionMessage(descriptor, element);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java b/platform/lang-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
similarity index 63%
rename from java/java-analysis-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
rename to platform/lang-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
index 4a760ed6adc6..6b72734c178f 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
@@ -1,37 +1,24 @@
-/*
- * Copyright 2000-2014 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.
- */
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection;
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInsight.daemon.impl.RemoveSuppressWarningAction;
import com.intellij.codeInspection.ex.*;
import com.intellij.codeInspection.reference.*;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
+import com.intellij.lang.Language;
+import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.BidirectionalMap;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import org.jdom.Element;
+import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,6 +28,7 @@ import java.util.*;
public class RedundantSuppressInspection extends GlobalInspectionTool {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.RedundantSuppressInspection");
+ public static final String SHORT_NAME = "RedundantSuppression";
public boolean IGNORE_ALL;
private BidirectionalMap myQuickFixes;
@@ -60,7 +48,7 @@ public class RedundantSuppressInspection extends GlobalInspectionTool {
@NotNull
@NonNls
public String getShortName() {
- return "RedundantSuppression";
+ return SHORT_NAME;
}
@Override
@@ -80,25 +68,19 @@ public class RedundantSuppressInspection extends GlobalInspectionTool {
@NotNull final InspectionManager manager,
@NotNull final GlobalInspectionContext globalContext,
@NotNull final ProblemDescriptionsProcessor problemDescriptionsProcessor) {
- globalContext.getRefManager().iterate(new RefJavaVisitor() {
+ globalContext.getRefManager().iterate(new RefVisitor() {
@Override
- public void visitJavaModule(@NotNull RefJavaModule javaModule) {
- visitElement(javaModule);
- }
-
- @Override public void visitClass(@NotNull RefClass refClass) {
- visitElement(refClass);
- }
-
- private void visitElement(@NotNull RefElement refElement) {
+ public void visitFile(@NotNull RefFile refElement) {
if (!globalContext.shouldCheck(refElement, RedundantSuppressInspection.this)) return;
- final PsiElement element = refElement.getElement();
- if (element == null) return;
- final CommonProblemDescriptor[] descriptors = checkElement(element, manager);
+ final PsiFile file = refElement.getPsiElement();
+ if (file == null) return;
+ InspectionSuppressor extension = LanguageInspectionSuppressors.INSTANCE.forLanguage(file.getLanguage());
+ if (!(extension instanceof RedundantSuppressionDetector)) return;
+ final CommonProblemDescriptor[] descriptors = checkElement(file, (RedundantSuppressionDetector)extension, manager);
for (CommonProblemDescriptor descriptor : descriptors) {
if (descriptor instanceof ProblemDescriptor) {
final PsiElement psiElement = ((ProblemDescriptor)descriptor).getPsiElement();
- final PsiMember member = PsiTreeUtil.getParentOfType(psiElement, PsiMember.class);
+ final PsiElement member = globalContext.getRefManager().getContainerElement(psiElement);
final RefElement reference = globalContext.getRefManager().getReference(member);
if (reference != null) {
problemDescriptionsProcessor.addProblemElement(reference, descriptor);
@@ -112,48 +94,15 @@ public class RedundantSuppressInspection extends GlobalInspectionTool {
}
@NotNull
- public ProblemDescriptor[] checkElement(@NotNull final PsiElement psiElement, @NotNull final InspectionManager manager) {
+ public ProblemDescriptor[] checkElement(@NotNull final PsiFile psiElement,
+ RedundantSuppressionDetector extension,
+ @NotNull final InspectionManager manager) {
final Map> suppressedScopes = new THashMap<>();
- psiElement.accept(new JavaRecursiveElementWalkingVisitor() {
- @Override public void visitModifierList(PsiModifierList list) {
- super.visitModifierList(list);
- final PsiElement parent = list.getParent();
- if (parent instanceof PsiModifierListOwner && !(parent instanceof PsiClass)) {
- checkElement(parent);
- }
- }
-
- @Override public void visitComment(PsiComment comment) {
- checkElement(comment);
- }
-
- @Override public void visitClass(PsiClass aClass) {
- if (aClass == psiElement) {
- super.visitClass(aClass);
- checkElement(aClass);
- }
- }
-
-
- private void checkElement(final PsiElement owner) {
- String idsString = JavaSuppressionUtil.getSuppressedInspectionIdsIn(owner);
- if (idsString != null && !idsString.isEmpty()) {
- List ids = new ArrayList<>();
- StringUtil.tokenize(idsString, "[, ]").forEach(ids::add);
- if (IGNORE_ALL && (ids.contains(SuppressionUtil.ALL) || ids.contains(SuppressionUtil.ALL.toLowerCase()))) return;
- Collection suppressed = suppressedScopes.get(owner);
- if (suppressed == null) {
- suppressed = ids;
- }
- else {
- for (String id : ids) {
- if (!suppressed.contains(id)) {
- suppressed.add(id);
- }
- }
- }
- suppressedScopes.put(owner, suppressed);
- }
+ psiElement.accept(new PsiRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitElement(PsiElement element) {
+ super.visitElement(element);
+ collectSuppressions(element, suppressedScopes, IGNORE_ALL, extension);
}
});
@@ -236,8 +185,8 @@ public class RedundantSuppressInspection extends GlobalInspectionTool {
if (!(descriptor instanceof ProblemDescriptor)) continue;
PsiElement element = ((ProblemDescriptor)descriptor).getPsiElement();
if (element == null) continue;
- PsiElement annotation = JavaSuppressionUtil.getElementToolSuppressedIn(element, toolId);
- if (annotation != null && PsiTreeUtil.isAncestor(suppressedScope, annotation, false) || annotation == null && !PsiTreeUtil.isAncestor(suppressedScope, element, false)) {
+ PsiLanguageInjectionHost host = InjectedLanguageManager.getInstance(element.getProject()).getInjectionHost(element);
+ if (extension.isSuppressionFor(suppressedScope, ObjectUtils.notNull(host, element), toolId)) {
suppressedIds.remove(toolId);
break;
}
@@ -247,37 +196,24 @@ public class RedundantSuppressInspection extends GlobalInspectionTool {
for (PsiElement suppressedScope : suppressedScopes.keySet()) {
Collection suppressedIds = suppressedScopes.get(suppressedScope);
for (String toolId : suppressedIds) {
- PsiJavaDocumentedElement documentedElement;
- String problemLine = null;
- if (suppressedScope instanceof PsiJavaDocumentedElement) {
- documentedElement = (PsiJavaDocumentedElement)suppressedScope;
- }
- else {
- documentedElement = PsiTreeUtil.getParentOfType(suppressedScope, PsiJavaDocumentedElement.class);
- final PsiStatement statement = PsiTreeUtil.getNextSiblingOfType(suppressedScope, PsiStatement.class);
- problemLine = statement != null ? statement.getText() : null;
- }
+ PsiNamedElement documentedElement = globalContext.getRefManager().getContainerElement(suppressedScope);
if (documentedElement != null && documentedElement.isValid()) {
- String description = InspectionsBundle.message("inspection.redundant.suppression.description");
if (myQuickFixes == null) myQuickFixes = new BidirectionalMap<>();
- final String key = toolId + (problemLine != null ? ";" + problemLine : "");
+ String key = toolId + ";" + suppressedScope.getLanguage().getID();
QuickFix fix = myQuickFixes.get(key);
if (fix == null) {
- fix = new RemoveSuppressWarningAction(toolId, problemLine);
+ fix = createQuickFix(key);
myQuickFixes.put(key, fix);
}
PsiElement identifier;
- if (suppressedScope instanceof PsiNameIdentifierOwner && suppressedScope instanceof PsiJavaDocumentedElement) {
- identifier = ((PsiNameIdentifierOwner)suppressedScope).getNameIdentifier();
+ if (suppressedScope instanceof PsiNameIdentifierOwner && suppressedScope == documentedElement) {
+ identifier = ObjectUtils.notNull(((PsiNameIdentifierOwner)suppressedScope).getNameIdentifier(), suppressedScope);
}
else {
identifier = suppressedScope;
}
- if (identifier == null) {
- identifier = documentedElement;
- }
result.add(
- manager.createProblemDescriptor(identifier, description, (LocalQuickFix)fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
+ manager.createProblemDescriptor(identifier, InspectionsBundle.message("inspection.redundant.suppression.description"), (LocalQuickFix)fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
false));
}
}
@@ -290,6 +226,84 @@ public class RedundantSuppressInspection extends GlobalInspectionTool {
return result.toArray(ProblemDescriptor.EMPTY_ARRAY);
}
+ private static void collectSuppressions(@NotNull PsiElement element,
+ Map> suppressedScopes,
+ boolean ignoreAll,
+ RedundantSuppressionDetector suppressor) {
+ String idsString = suppressor.getSuppressionIds(element);
+ if (idsString != null && !idsString.isEmpty()) {
+ List ids = new ArrayList<>();
+ StringUtil.tokenize(idsString, "[, ]").forEach(ids::add);
+ if (ignoreAll && (ids.contains(SuppressionUtil.ALL) || ids.contains(SuppressionUtil.ALL.toLowerCase()))) return;
+ Collection suppressed = suppressedScopes.get(element);
+ if (suppressed == null) {
+ suppressed = ids;
+ }
+ else {
+ for (String id : ids) {
+ if (!suppressed.contains(id)) {
+ suppressed.add(id);
+ }
+ }
+ }
+ suppressedScopes.put(element, suppressed);
+ }
+ }
+
+ public LocalInspectionTool createLocalTool(RedundantSuppressionDetector suppressor,
+ Map> toolToSuppressScopes,
+ Set activeTools) {
+ return new LocalInspectionTool() {
+ @NotNull
+ @Override
+ public String getShortName() {
+ return SHORT_NAME;
+ }
+
+ @Nls
+ @NotNull
+ @Override
+ public String getDisplayName() {
+ return RedundantSuppressInspection.this.getDisplayName();
+ }
+
+ @NotNull
+ @Override
+ public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
+ return new PsiElementVisitor() {
+
+ @Override
+ public void visitElement(PsiElement element) {
+ super.visitElement(element);
+ HashMap> scopes = new HashMap<>();
+ collectSuppressions(element, scopes, false, suppressor);
+ Collection suppressIds = scopes.get(element);
+ if (suppressIds != null) {
+ for (String suppressId : suppressIds) {
+ if (!activeTools.contains(suppressId)) continue;
+ Set suppressedPlaces = toolToSuppressScopes.get(suppressId);
+ if (suppressedPlaces == null || suppressedPlaces.stream().noneMatch(place -> suppressor.isSuppressionFor(element, place, suppressId))) {
+ holder.registerProblem(element, suppressor.getHighlightingRange(element, suppressId),
+ InspectionsBundle.message("inspection.redundant.suppression.description"),
+ suppressor.createRemoveRedundantSuppressionFix(suppressId));
+ }
+ }
+ }
+ }
+ };
+ }
+ };
+ }
+
+ private static QuickFix createQuickFix(String key) {
+ String[] toolAndLang = key.split(";");
+ Language language = Language.findLanguageByID(toolAndLang[1]);
+ if (language == null) return null;
+ InspectionSuppressor suppressor = LanguageInspectionSuppressors.INSTANCE.forLanguage(language);
+ return suppressor instanceof RedundantSuppressionDetector
+ ? ((RedundantSuppressionDetector)suppressor).createRemoveRedundantSuppressionFix(toolAndLang[0]) : null;
+ }
+
@NotNull
protected InspectionToolWrapper[] getInspectionTools(PsiElement psiElement, @NotNull InspectionManager manager) {
// todo for what we create modifiable model here?
@@ -303,7 +317,7 @@ public class RedundantSuppressInspection extends GlobalInspectionTool {
@Override
@Nullable
public QuickFix getQuickFix(final String hint) {
- return myQuickFixes != null ? myQuickFixes.get(hint) : new RemoveSuppressWarningAction(hint);
+ return myQuickFixes != null ? myQuickFixes.get(hint) : createQuickFix(hint);
}
@Override
diff --git a/java/java-impl/src/inspectionDescriptions/RedundantSuppression.html b/platform/platform-resources-en/src/inspectionDescriptions/RedundantSuppression.html
similarity index 100%
rename from java/java-impl/src/inspectionDescriptions/RedundantSuppression.html
rename to platform/platform-resources-en/src/inspectionDescriptions/RedundantSuppression.html
diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml
index 90401ca7b9e7..07735b0d4e24 100644
--- a/platform/platform-resources/src/META-INF/LangExtensions.xml
+++ b/platform/platform-resources/src/META-INF/LangExtensions.xml
@@ -893,6 +893,9 @@
+