mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJPL-19723 [inspections]: fix Redundant Suppression false positive for SSR inspection
GitOrigin-RevId: 068c01dc48efeb976e1fe9aba1933fbfd74450aa
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3b4a6dc223
commit
1ea9a32a5b
+53
-1
@@ -1,26 +1,43 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.structuralsearch.inspection;
|
||||
|
||||
import com.intellij.analysis.AnalysisScope;
|
||||
import com.intellij.codeHighlighting.HighlightDisplayLevel;
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.InspectionEngine;
|
||||
import com.intellij.codeInspection.RedundantSuppressInspection;
|
||||
import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper;
|
||||
import com.intellij.codeInspection.ex.InspectionProfileImpl;
|
||||
import com.intellij.codeInspection.ex.InspectionToolWrapper;
|
||||
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
|
||||
import com.intellij.codeInspection.ex.ToolsImpl;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.profile.codeInspection.InspectionProfileManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.structuralsearch.MatchOptions;
|
||||
import com.intellij.structuralsearch.inspection.SSBasedInspection;
|
||||
import com.intellij.structuralsearch.inspection.StructuralSearchProfileActionProvider;
|
||||
import com.intellij.structuralsearch.plugin.replace.ui.ReplaceConfiguration;
|
||||
import com.intellij.structuralsearch.plugin.ui.Configuration;
|
||||
import com.intellij.structuralsearch.plugin.ui.SearchConfiguration;
|
||||
import com.intellij.testFramework.InspectionTestUtil;
|
||||
import com.intellij.testFramework.InspectionsKt;
|
||||
import com.intellij.testFramework.PerformanceUnitTest;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.testFramework.fixtures.impl.GlobalInspectionContextForTests;
|
||||
import com.intellij.tools.ide.metrics.benchmark.Benchmark;
|
||||
import com.intellij.util.PairProcessor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class SSBasedInspectionTest extends SSBasedInspectionTestCase {
|
||||
|
||||
@@ -42,6 +59,41 @@ public class SSBasedInspectionTest extends SSBasedInspectionTestCase {
|
||||
inspectionTest(configuration, HighlightDisplayLevel.ERROR);
|
||||
quickFixTest("Suppress for statement");
|
||||
}
|
||||
|
||||
public void testRedundantSuppress() {
|
||||
final Configuration configuration = new ReplaceConfiguration();
|
||||
configuration.setName("println");
|
||||
configuration.setSuppressId("println");
|
||||
|
||||
final MatchOptions matchOptions = configuration.getMatchOptions();
|
||||
matchOptions.setFileType(JavaFileType.INSTANCE);
|
||||
matchOptions.fillSearchCriteria("System.out.println();");
|
||||
configuration.getReplaceOptions().setReplacement("System.out.print('\\n');");
|
||||
|
||||
Project project = myFixture.getProject();
|
||||
InspectionProfileImpl profile = InspectionProfileManager.getInstance(project).getCurrentProfile();
|
||||
StructuralSearchProfileActionProvider.createNewInspection(configuration, project, profile);
|
||||
@NotNull InspectionToolWrapper<?, ?> redundantSuppressInspection = new GlobalInspectionToolWrapper(new RedundantSuppressInspection());
|
||||
|
||||
VirtualFile sourceDir = myFixture.copyDirectoryToProject(new File("RedundantSuppress/", "src").getPath(), "");
|
||||
AnalysisScope scope = new AnalysisScope(myFixture.getPsiManager().findDirectory(sourceDir));
|
||||
|
||||
SSBasedInspection inspection = SSBasedInspection.getStructuralSearchInspection(profile);
|
||||
List<InspectionToolWrapper<?, ?>> wrappers = new ArrayList<>();
|
||||
wrappers.add(redundantSuppressInspection);
|
||||
wrappers.add(new LocalInspectionToolWrapper(inspection));
|
||||
wrappers.addAll(inspection.getChildren());
|
||||
|
||||
GlobalInspectionContextForTests globalContext = InspectionsKt.createGlobalContextForTool(scope, project, wrappers);
|
||||
InspectionTestUtil.runTool(redundantSuppressInspection, scope, globalContext);
|
||||
InspectionTestUtil.compareToolResults(globalContext, redundantSuppressInspection, false, getTestDataPath() + "/RedundantSuppress/");
|
||||
|
||||
myFixture.testHighlighting(true, false, false, "FixAll.java");
|
||||
final IntentionAction intention = myFixture.getAvailableIntention("Fix all 'println' problems in file");
|
||||
assertNotNull("Intention not found. Did you forget a <caret>?", intention);
|
||||
myFixture.checkPreviewAndLaunchAction(intention);
|
||||
myFixture.checkResultByFile("FixAll.after.java");
|
||||
}
|
||||
|
||||
public void testBrokenPattern() {
|
||||
// check broken pattern does not throw exceptions
|
||||
|
||||
@@ -376,8 +376,8 @@ public final class InspectionEngine {
|
||||
if (holder.hasResults()) {
|
||||
for (ProblemDescriptor descriptor : holder.getResults()) {
|
||||
PsiElement element = descriptor.getPsiElement();
|
||||
if (element == null || !ignoreSuppressedElements || !SuppressionUtil.inspectionResultSuppressed(element, tool)) {
|
||||
LocalInspectionToolWrapper wrapper = getRedirectedToolWrapper(toolWrapper, descriptor);
|
||||
LocalInspectionToolWrapper wrapper = getRedirectedToolWrapper(toolWrapper, descriptor);
|
||||
if (element == null || !ignoreSuppressedElements || !SuppressionUtil.inspectionResultSuppressed(element, wrapper.getTool())) {
|
||||
resultDescriptors.computeIfAbsent(wrapper, x -> new ArrayList<>()).add(descriptor);
|
||||
}
|
||||
}
|
||||
@@ -391,8 +391,7 @@ public final class InspectionEngine {
|
||||
return resultDescriptors;
|
||||
}
|
||||
|
||||
private static @Nullable LocalInspectionToolWrapper getRedirectedToolWrapper(LocalInspectionToolWrapper toolWrapper,
|
||||
ProblemDescriptor descriptor) {
|
||||
private static LocalInspectionToolWrapper getRedirectedToolWrapper(LocalInspectionToolWrapper toolWrapper, ProblemDescriptor descriptor) {
|
||||
if (descriptor instanceof ProblemDescriptorWithReporterName name && toolWrapper.getTool() instanceof DynamicGroupTool groupTool) {
|
||||
String reportingToolName = name.getReportingToolShortName();
|
||||
for (LocalInspectionToolWrapper child : groupTool.getChildren()) {
|
||||
@@ -416,8 +415,7 @@ public final class InspectionEngine {
|
||||
if (toolWrapper instanceof LocalInspectionToolWrapper local) {
|
||||
Map<LocalInspectionToolWrapper, List<ProblemDescriptor>> problemDescriptors =
|
||||
inspectEx(Collections.singletonList(local), psiFile, psiFile.getTextRange(), psiFile.getTextRange(),
|
||||
false,
|
||||
false, true, new EmptyProgressIndicator(), PairProcessor.alwaysTrue());
|
||||
false, false, true, new EmptyProgressIndicator(), PairProcessor.alwaysTrue());
|
||||
|
||||
for (List<ProblemDescriptor> group : problemDescriptors.values()) {
|
||||
result.addAll(group);
|
||||
|
||||
+14
-8
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.analysis.AnalysisScope;
|
||||
@@ -138,18 +138,24 @@ public abstract class RedundantSuppressInspectionBase extends GlobalSimpleInspec
|
||||
InspectionToolWrapper<?, ?> toolWrapper = entry.getKey();
|
||||
String toolId = entry.getValue();
|
||||
toolWrapper.initialize(globalContext);
|
||||
Collection<CommonProblemDescriptor> descriptors;
|
||||
List<ProblemDescriptor> descriptors;
|
||||
if (toolWrapper instanceof LocalInspectionToolWrapper local) {
|
||||
if (local.isUnfair()) {
|
||||
continue; // can't work with passes other than LocalInspectionPass
|
||||
}
|
||||
LocalInspectionTool tool = local.getTool();
|
||||
String id = toolWrapper.getMainToolId();
|
||||
List<LocalInspectionToolWrapper> wrappers;
|
||||
if (id != null) {
|
||||
LocalInspectionToolWrapper mainTool = (LocalInspectionToolWrapper)((InspectionProfileImpl)profile).getToolById(id, psiFile);
|
||||
wrappers = mainTool != null ? List.of(local, mainTool) : List.of(local);
|
||||
}
|
||||
else {
|
||||
wrappers = List.of(local);
|
||||
}
|
||||
List<ProblemDescriptor> found = Collections.synchronizedList(new ArrayList<>());
|
||||
// shouldn't use standard ProblemsHolder because it filters out suppressed elements by default
|
||||
InspectionEngine.inspectEx(Collections.singletonList(new LocalInspectionToolWrapper(tool)), psiFile, psiFile.getTextRange(),
|
||||
psiFile.getTextRange(), false,
|
||||
true, false, ProgressIndicatorProvider.getGlobalProgressIndicator(),
|
||||
(wrapper, descriptor) -> found.add(descriptor));
|
||||
InspectionEngine.inspectEx(wrappers, psiFile, psiFile.getTextRange(), psiFile.getTextRange(), false, true, false,
|
||||
ProgressIndicatorProvider.getGlobalProgressIndicator(), (__, descriptor) -> found.add(descriptor));
|
||||
descriptors = new ArrayList<>(found);
|
||||
}
|
||||
else if (toolWrapper instanceof GlobalInspectionToolWrapper global) {
|
||||
@@ -166,7 +172,7 @@ public abstract class RedundantSuppressInspectionBase extends GlobalSimpleInspec
|
||||
Collection<String> suppressedIds = e.getValue();
|
||||
PsiElement suppressedScope = e.getKey();
|
||||
if (!suppressedIds.contains(toolId)) continue;
|
||||
for (CommonProblemDescriptor descriptor : descriptors) {
|
||||
for (ProblemDescriptor descriptor : descriptors) {
|
||||
if (!(descriptor instanceof ProblemDescriptor problemDescriptor)) continue;
|
||||
PsiElement element = problemDescriptor.getPsiElement();
|
||||
if (element == null) continue;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class Y {
|
||||
|
||||
void x() {
|
||||
<caret>System.out.print('\n');
|
||||
System.out.print('\n');
|
||||
System.out.print('\n');
|
||||
|
||||
// noinspection println
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class Y {
|
||||
|
||||
void x() {
|
||||
<warning descr="println"><caret>System.out.println();</warning>
|
||||
<warning descr="println">System.out.println();</warning>
|
||||
<warning descr="println">System.out.println();</warning>
|
||||
|
||||
// noinspection println
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
</problems>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class X {
|
||||
|
||||
void x() {
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
|
||||
// noinspection println
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user