redundant suppression available in the editor IDEA-151197

also, global inspection redundant suppressions made java independent (WEB-16634)
This commit is contained in:
Anna.Kozlova
2018-09-21 19:37:01 +02:00
parent ec3d956aa1
commit 83a859546b
18 changed files with 231 additions and 199 deletions
@@ -155,9 +155,6 @@
<localInspection groupPath="Java" language="JAVA" shortName="DuplicateThrows" bundle="messages.InspectionsBundle" key="inspection.duplicate.throws.display.name"
groupKey="group.names.declaration.redundancy" enabledByDefault="true" level="WARNING" cleanupTool="true"
implementationClass="com.intellij.codeInspection.duplicateThrows.DuplicateThrowsInspection" />
<globalInspection shortName="RedundantSuppression" bundle="messages.InspectionsBundle" key="inspection.redundant.suppression.name"
groupKey="inspection.general.tools.group.name" enabledByDefault="false" level="WARNING"
implementationClass="com.intellij.codeInspection.RedundantSuppressInspection"/>
<globalInspection groupPath="Java" shortName="UnnecessaryModuleDependencyInspection" bundle="messages.InspectionsBundle"
key="unnecessary.module.dependency.display.name" groupKey="group.names.declaration.redundancy" enabledByDefault="true"
level="WARNING"
@@ -22,7 +22,6 @@ import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.SuppressionUtilCore;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
@@ -42,22 +41,14 @@ public class RemoveSuppressWarningAction implements LocalQuickFix {
@NotNull
private final String myID;
private final String myProblemLine;
public RemoveSuppressWarningAction(@NotNull String ID, final String problemLine) {
myID = ID;
myProblemLine = problemLine;
}
public RemoveSuppressWarningAction(@NotNull String id) {
final int idx = id.indexOf(";");
if (idx > -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()) {
@@ -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);
}
}
@@ -7,7 +7,7 @@ public class Test {
}
void foo() {
//noinspec<caret>tion unchecked
//noinspection unc<caret>hecked
foo(new ArrayList<String>());
}
}
@@ -7,7 +7,7 @@ public class Test {
}
void foo() {
//noinsp<caret>ection unchecked,blah-blah-toolid
//noinspection un<caret>checked,blah-blah-toolid
foo(new ArrayList<String>());
}
}
@@ -12,7 +12,7 @@ public class Test {
}
void foo() {
//noinspe<caret>ction unchecked
//noinspection unc<caret>hecked
foo(new ArrayList<String>()).addAll(foo1(new ArrayList<String>()));
}
}
@@ -8,7 +8,7 @@ public class Test {
}
void foo() {
//noinspe<caret>ction unchecked
//noinspection unche<caret>cked
List<ArrayList<String>> list = foo(new ArrayList<String>());
}
}
@@ -7,8 +7,8 @@ public class Test {
return null;
}
@SuppressWarnings("unchecked")
void fo<caret>o() {
@SuppressWarnings("unch<caret>ecked")
void foo() {
List<ArrayList<String>> list = foo(new ArrayList<String>());
}
}
@@ -1,8 +1,8 @@
// "Remove 'unchecked' suppression" "true"
import java.util.*;
@SuppressWarnings("unchecked")
public class Te<caret>st {
@SuppressWarnings("un<caret>checked")
public class Test {
@SafeVarargs
static <T> List<T> foo(T... t){
return null;
@@ -1,8 +1,8 @@
// "Remove 'unchecked' suppression" "true"
import java.util.*;
@SuppressWarnings({"unchecked", "bla-blah-toolid"})
public class Tes<caret>t {
@SuppressWarnings({"unch<caret>ecked", "bla-blah-toolid"})
public class Test {
@SafeVarargs
static <T> List<T> foo(T... t){
return null;
@@ -4,7 +4,6 @@
<problem>
<file>module-info.java</file>
<line>5</line>
<entry_point TYPE="java.module" FQNAME="com.moduleinfo.test" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant suppression</problem_class>
<description>Redundant suppression</description>
</problem>
@@ -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
@@ -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() {
@@ -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());
}
}
@@ -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<String, Set<PsiElement>> 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<PsiElement> inside,
List<PsiElement> outside,
Set<String> 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<String> 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);
@@ -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<String, QuickFix> 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<PsiElement, Collection<String>> 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<String> ids = new ArrayList<>();
StringUtil.tokenize(idsString, "[, ]").forEach(ids::add);
if (IGNORE_ALL && (ids.contains(SuppressionUtil.ALL) || ids.contains(SuppressionUtil.ALL.toLowerCase()))) return;
Collection<String> 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<String> 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<PsiElement, Collection<String>> suppressedScopes,
boolean ignoreAll,
RedundantSuppressionDetector suppressor) {
String idsString = suppressor.getSuppressionIds(element);
if (idsString != null && !idsString.isEmpty()) {
List<String> ids = new ArrayList<>();
StringUtil.tokenize(idsString, "[, ]").forEach(ids::add);
if (ignoreAll && (ids.contains(SuppressionUtil.ALL) || ids.contains(SuppressionUtil.ALL.toLowerCase()))) return;
Collection<String> 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<String, Set<PsiElement>> toolToSuppressScopes,
Set<String> 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<PsiElement, Collection<String>> scopes = new HashMap<>();
collectSuppressions(element, scopes, false, suppressor);
Collection<String> suppressIds = scopes.get(element);
if (suppressIds != null) {
for (String suppressId : suppressIds) {
if (!activeTools.contains(suppressId)) continue;
Set<PsiElement> 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<ProblemDescriptor> 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
@@ -893,6 +893,9 @@
<localInspection shortName="LongLine" bundle="messages.InspectionsBundle" key="long.line.display.name"
groupKey="inspection.general.tools.group.name" enabledByDefault="false"
level="WARNING" implementationClass="com.intellij.codeInspection.longLine.LongLineInspection"/>
<globalInspection shortName="RedundantSuppression" bundle="messages.InspectionsBundle" key="inspection.redundant.suppression.name"
groupKey="inspection.general.tools.group.name" enabledByDefault="false" level="WARNING"
implementationClass="com.intellij.codeInspection.RedundantSuppressInspection"/>
<annotator language="TEXT" implementationClass="com.intellij.codeInsight.highlighting.LargeFilesAnnotator"/>