From cd4c1b08aed741ec97ccf9db366fbfcb28a4f73f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 9 Sep 2016 13:53:38 +0300 Subject: [PATCH] new inspection: deprecated member is used --- .../DeprecatedIsStillUsedInspection.java | 99 +++++++++++++++++++ .../deprecatedIsStillUsed/simple/expected.xml | 24 +++++ .../simple/src/Test.java | 44 +++++++++ .../DeprecatedIsStillUsedInspectionTest.java | 35 +++++++ .../DeprecatedIsStillUsed.html | 21 ++++ resources/src/META-INF/IdeaPlugin.xml | 3 + 6 files changed, 226 insertions(+) create mode 100644 java/java-analysis-impl/src/com/intellij/codeInspection/DeprecatedIsStillUsedInspection.java create mode 100644 java/java-tests/testData/inspection/deprecatedIsStillUsed/simple/expected.xml create mode 100644 java/java-tests/testData/inspection/deprecatedIsStillUsed/simple/src/Test.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInspection/DeprecatedIsStillUsedInspectionTest.java create mode 100644 resources-en/src/inspectionDescriptions/DeprecatedIsStillUsed.html diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/DeprecatedIsStillUsedInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/DeprecatedIsStillUsedInspection.java new file mode 100644 index 000000000000..e4509d252f11 --- /dev/null +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/DeprecatedIsStillUsedInspection.java @@ -0,0 +1,99 @@ +/* + * Copyright 2000-2016 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. + */ +package com.intellij.codeInspection; + +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.PsiSearchHelper; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; + +/** + * @author cdr + */ +public class DeprecatedIsStillUsedInspection extends LocalInspectionTool { + //@Override + //@NotNull + //public String getDisplayName() { + // return "Deprecated member is used"; + //} + // + //@Override + //@NotNull + //public String getShortName() { + // return "DeprecatedIsUsed"; + //} + // + + @NotNull + @Override + public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, + final boolean isOnTheFly, + @NotNull final LocalInspectionToolSession session) { + return new JavaElementVisitor() { + @Override + public void visitIdentifier(PsiIdentifier identifier) { + PsiElement parent = identifier.getParent(); + if (parent instanceof PsiMember && parent instanceof PsiNameIdentifierOwner && ((PsiNameIdentifierOwner)parent).getNameIdentifier() == identifier) { + checkMember((PsiMember)parent, identifier, holder); + } + super.visitIdentifier(identifier); + } + }; + } + + private void checkMember(@NotNull PsiMember member, @NotNull PsiIdentifier identifier, @NotNull ProblemsHolder holder) { + if (!(member instanceof PsiDocCommentOwner) || !isDeprecated((PsiDocCommentOwner)member)) { + return; + } + + PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(member.getProject()); + String name = member.getName(); + if (name != null && hasUsages(member, name, searchHelper, member.getResolveScope())) { + holder.registerProblem(identifier, "Deprecated member '" + name + "' is still used"); + } + } + + private static boolean isDeprecated(PsiDocCommentOwner element) { + return element.isDeprecated() || element.getContainingClass() != null && element.getContainingClass().isDeprecated(); + } + + + private static boolean hasUsages(@NotNull PsiElement element, + @NotNull String name, + @NotNull PsiSearchHelper psiSearchHelper, + @NotNull GlobalSearchScope searchScope) { + PsiSearchHelper.SearchCostResult cheapEnough = psiSearchHelper.isCheapEnoughToSearch(name, searchScope, null, null); + if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES || + cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) { + return false; + } + + return !ReferencesSearch.search(element, searchScope, false).forEach(reference -> { + PsiElement referenceElement = reference.getElement(); + return isInsideDeprecated(referenceElement); + }); + } + + private static boolean isInsideDeprecated(PsiElement element) { + PsiElement parent = element; + while ((parent = PsiTreeUtil.getParentOfType(parent, PsiDocCommentOwner.class, true)) != null) { + if (((PsiDocCommentOwner)parent).isDeprecated()) return true; + } + return false; + } +} diff --git a/java/java-tests/testData/inspection/deprecatedIsStillUsed/simple/expected.xml b/java/java-tests/testData/inspection/deprecatedIsStillUsed/simple/expected.xml new file mode 100644 index 000000000000..3954a5716a4d --- /dev/null +++ b/java/java-tests/testData/inspection/deprecatedIsStillUsed/simple/expected.xml @@ -0,0 +1,24 @@ + + + + Test.java + 5 + Deprecated member 'bbb' is still used + + + Test.java + 8 + Deprecated member 'bbb2' is still used + + + Test.java + 11 + Deprecated member 'bbb3' is still used + + + Test.java + 16 + Deprecated member 'Bbb4' is still used + + + diff --git a/java/java-tests/testData/inspection/deprecatedIsStillUsed/simple/src/Test.java b/java/java-tests/testData/inspection/deprecatedIsStillUsed/simple/src/Test.java new file mode 100644 index 000000000000..dfbc1da2247b --- /dev/null +++ b/java/java-tests/testData/inspection/deprecatedIsStillUsed/simple/src/Test.java @@ -0,0 +1,44 @@ +public class Test{ + /** + * @deprecated + */ + int bbb; + + @Deprecated + int bbb2; + + @Deprecated + int bbb3() { + return 0; + } + + @Deprecated + class Bbb4 { + + } + + int use(){ + return bbb + bbb2 + bbb3() + Bbb4.class.toString().hashCode(); + } + + + ////////////////////////////// + + @Deprecated + int ddd2; + + @Deprecated + int ddd3() { + return 0; + } + + @Deprecated + class Ddd4 { + + } + + @Deprecated + int useFromDeprecated(){ + return ddd2 + ddd3() + Ddd4.class.toString().hashCode(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DeprecatedIsStillUsedInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DeprecatedIsStillUsedInspectionTest.java new file mode 100644 index 000000000000..252729c6de1d --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DeprecatedIsStillUsedInspectionTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2016 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. + */ + +package com.intellij.codeInspection; + +import com.intellij.JavaTestUtil; +import com.intellij.testFramework.InspectionTestCase; + +public class DeprecatedIsStillUsedInspectionTest extends InspectionTestCase { + @Override + protected String getTestDataPath() { + return JavaTestUtil.getJavaTestDataPath() + "/inspection"; + } + + private void doTest() throws Exception { + doTest("deprecatedIsStillUsed/" + getTestName(true), new DeprecatedIsStillUsedInspection()); + } + + public void testSimple() throws Exception{ + doTest(); + } +} diff --git a/resources-en/src/inspectionDescriptions/DeprecatedIsStillUsed.html b/resources-en/src/inspectionDescriptions/DeprecatedIsStillUsed.html new file mode 100644 index 000000000000..40f01d0e8836 --- /dev/null +++ b/resources-en/src/inspectionDescriptions/DeprecatedIsStillUsed.html @@ -0,0 +1,21 @@ + + +Reports deprecated classes, methods and fields which are used in your code nonetheless. + +
+For example: + +
+class MyCode {
+  @Deprecated
+  // warning: "Deprecated member is still used"
+  void oldMethod() {}
+
+  void newMethod() {
+    oldMethod(); // forgotten usage
+  }
+}
+
+(The usages from within deprecated places are ignored). + + \ No newline at end of file diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 84713f65de70..e2d6a8c17c3e 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -667,6 +667,9 @@ +