diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java index 181577c942f3..e4f8aa291a91 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java @@ -175,10 +175,8 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool { if (!refElement.isSuspicious()) return; PsiFile file = refElement.getContainingFile(); - if (file == null) return; - boolean isSuppressed = refElement.isSuppressed(getShortName(), ALTERNATIVE_ID); - if (isSuppressed || !((GlobalInspectionContextBase)globalContext).isToCheckFile(file, UnusedDeclarationInspectionBase.this) && !scope.contains(file)) { + if (!((GlobalInspectionContextBase)globalContext).isToCheckFile(file, UnusedDeclarationInspectionBase.this) && !scope.contains(file)) { getEntryPointsManager(globalContext).addEntryPoint(refElement, false); } } diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java index 8cf91c161ba4..0b18b61541eb 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java @@ -65,6 +65,7 @@ import java.util.function.Supplier; import java.util.stream.Collectors; public class UnusedDeclarationPresentation extends DefaultInspectionToolPresentation { + private static final String[] SUPPRESSIONS = {UnusedDeclarationInspectionBase.SHORT_NAME, UnusedDeclarationInspectionBase.ALTERNATIVE_ID}; private final Map myFixedElements = ConcurrentCollectionFactory.createConcurrentIdentityMap(); private final Set myExcludedElements = ConcurrentCollectionFactory.createConcurrentIdentitySet(); @@ -430,14 +431,14 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta } private @Nullable RefJavaElement refineElement(RefEntity refEntity) { - if (!(refEntity instanceof RefJavaElement refElement)) return null; //dead code doesn't work with refModule | refPackage + if (!(refEntity instanceof RefJavaElement refElement)) return null; // dead code doesn't work with refModule | refPackage RefFilter filter = getFilter(); if (!filter.accepts(refElement)) return null; RefJavaElement refinedElement = (RefJavaElement)getRefManager().getRefinedElement(refEntity); if (refinedElement != refEntity && filter.accepts(refinedElement)) return null; // prevent duplicate reporting if (!refinedElement.isValid()) return null; if (!compareVisibilities(refinedElement, getTool().getSharedLocalInspectionTool())) return null; - if (isSuppressed(refinedElement)) return null; + if (isSuppressed(refinedElement) || refinedElement.isSuppressed(SUPPRESSIONS)) return null; if (!ApplicationManager.getApplication().isHeadlessEnvironment() & getContext().getUIOptions().FILTER_RESOLVED_ITEMS && (myFixedElements.containsKey(refinedElement) || isExcluded(refinedElement))) { return null; diff --git a/java/java-tests/testData/inspection/deadCode/suppress1/expected.xml b/java/java-tests/testData/inspection/deadCode/suppress1/expected.xml index 79e1a0fd0a57..b31f99c02e3d 100644 --- a/java/java-tests/testData/inspection/deadCode/suppress1/expected.xml +++ b/java/java-tests/testData/inspection/deadCode/suppress1/expected.xml @@ -1,4 +1,12 @@ - + + + B.java + 2 + 2 + 1 + B + All constructor usages belong to the calls chain that has no members reachable from entry points. + diff --git a/java/java-tests/testData/inspection/deadCode/suppress2/expected.xml b/java/java-tests/testData/inspection/deadCode/suppress2/expected.xml index 79e1a0fd0a57..210257490d21 100644 --- a/java/java-tests/testData/inspection/deadCode/suppress2/expected.xml +++ b/java/java-tests/testData/inspection/deadCode/suppress2/expected.xml @@ -1,4 +1,11 @@ - + + + B.java + 1 + 6 + 1 + Class has one instantiation, but it is not reachable from entry points. + diff --git a/java/java-tests/testData/inspection/deadCode/suppressOverriddenMethod/expected.xml b/java/java-tests/testData/inspection/deadCode/suppressOverriddenMethod/expected.xml index d704d58ed391..ce6c57d5a0d3 100644 --- a/java/java-tests/testData/inspection/deadCode/suppressOverriddenMethod/expected.xml +++ b/java/java-tests/testData/inspection/deadCode/suppressOverriddenMethod/expected.xml @@ -1,4 +1,18 @@ + + A.java + 1 + 22 + 1 + &nbsp;Abstract&nbsp;class has an implementation but <ul><li>it is never instantiated OR</li><li>no instantiations are reachable from entry points.</li></ul> + + + B.java + 1 + 13 + 1 + Class has one instantiation, but it is not reachable from entry points. + diff --git a/java/java-tests/testData/inspection/deadCode/suppressionIsNotAnEntryPoint/expected.xml b/java/java-tests/testData/inspection/deadCode/suppressionIsNotAnEntryPoint/expected.xml new file mode 100644 index 000000000000..a86c673ba87d --- /dev/null +++ b/java/java-tests/testData/inspection/deadCode/suppressionIsNotAnEntryPoint/expected.xml @@ -0,0 +1,10 @@ + + + + MyInterafaceImpl.java + 2 + 13 + 16 + Class is not instantiated. + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/deadCode/suppressionIsNotAnEntryPoint/src/MyInterafaceImpl.java b/java/java-tests/testData/inspection/deadCode/suppressionIsNotAnEntryPoint/src/MyInterafaceImpl.java new file mode 100644 index 000000000000..e994f355389f --- /dev/null +++ b/java/java-tests/testData/inspection/deadCode/suppressionIsNotAnEntryPoint/src/MyInterafaceImpl.java @@ -0,0 +1,5 @@ + +public class MyInterafaceImpl implements MyInterface { + @Override + public void myMethod() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/deadCode/suppressionIsNotAnEntryPoint/src/MyInterface.java b/java/java-tests/testData/inspection/deadCode/suppressionIsNotAnEntryPoint/src/MyInterface.java new file mode 100644 index 000000000000..11eea590706b --- /dev/null +++ b/java/java-tests/testData/inspection/deadCode/suppressionIsNotAnEntryPoint/src/MyInterface.java @@ -0,0 +1,5 @@ + +public interface MyInterface { + @SuppressWarnings("unused") + void myMethod(); +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java index c6028fd0e11a..24879f241aaf 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java @@ -79,6 +79,10 @@ public class UnusedDeclarationInspectionTest extends AbstractUnusedDeclarationTe doTest5(); } + public void testSuppressionIsNotAnEntryPoint() { + doTest(); + } + public void testSuppressByNoinspectionTag() { doTest(); } diff --git a/platform/analysis-api/api-dump-unreviewed.txt b/platform/analysis-api/api-dump-unreviewed.txt index e5c5938c7e54..f9c8baec020a 100644 --- a/platform/analysis-api/api-dump-unreviewed.txt +++ b/platform/analysis-api/api-dump-unreviewed.txt @@ -2101,6 +2101,7 @@ com.intellij.codeInspection.reference.RefElement - a:isPermanentEntry():Z - a:isReachable():Z - a:isReferenced():Z +- isSuppressed(java.lang.String[]):Z com.intellij.codeInspection.reference.RefEntity - com.intellij.openapi.util.UserDataHolder - sf:EMPTY_ELEMENTS_ARRAY:com.intellij.codeInspection.reference.RefEntity[] diff --git a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefElement.java b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefElement.java index ba59119d1aad..d9062d55d176 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefElement.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefElement.java @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInspection.reference; import com.intellij.psi.PsiElement; @@ -106,4 +106,14 @@ public interface RefElement extends RefEntity { @NotNull RefElement getContainingEntry(); + + /** + * Checks if the specified warnings are suppressed for this element or any of its surrounding elements. + * + * @param toolIds the tool ids to check, for example "unchecked" or "deprecation" + * @return true, when any one of the specified ids is suppressed or when "ALL" is suppressed, false otherwise. + */ + default boolean isSuppressed(String @NotNull ... warningIds) { + return false; + } } diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefElementImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefElementImpl.java index 55ee628653a8..ecc943112749 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefElementImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefElementImpl.java @@ -1,4 +1,4 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInspection.reference; import com.intellij.codeInspection.SuppressionUtil; @@ -277,6 +277,7 @@ public abstract class RefElementImpl extends RefEntityImpl implements RefElement mySuppressions = text.split("[, ]"); } + @Override public boolean isSuppressed(String @NotNull ... toolIds) { if (mySuppressions != null) { for (@NonNls String suppression : mySuppressions) {