mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
redundant suppression available in the editor IDEA-151197
also, global inspection redundant suppressions made java independent (WEB-16634)
This commit is contained in:
@@ -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"
|
||||
|
||||
+1
-14
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ public class Test {
|
||||
}
|
||||
|
||||
void foo() {
|
||||
//noinspec<caret>tion unchecked
|
||||
//noinspection unc<caret>hecked
|
||||
foo(new ArrayList<String>());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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>());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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>()));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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>());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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>());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+2
-2
@@ -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>
|
||||
|
||||
+6
-73
@@ -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() {
|
||||
|
||||
+42
@@ -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());
|
||||
}
|
||||
}
|
||||
+40
-1
@@ -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);
|
||||
|
||||
|
||||
+109
-95
@@ -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"/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user