new inspection: deprecated member is used

This commit is contained in:
Alexey Kudravtsev
2016-09-09 13:53:38 +03:00
parent 884043aacc
commit cd4c1b08ae
6 changed files with 226 additions and 0 deletions
@@ -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;
}
}
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>Test.java</file>
<line>5</line>
<description>Deprecated member 'bbb' is still used</description>
</problem>
<problem>
<file>Test.java</file>
<line>8</line>
<description>Deprecated member 'bbb2' is still used</description>
</problem>
<problem>
<file>Test.java</file>
<line>11</line>
<description>Deprecated member 'bbb3' is still used</description>
</problem>
<problem>
<file>Test.java</file>
<line>16</line>
<description>Deprecated member 'Bbb4' is still used</description>
</problem>
</problems>
@@ -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();
}
}
@@ -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();
}
}
@@ -0,0 +1,21 @@
<html>
<body>
Reports deprecated classes, methods and fields which are used in your code nonetheless.
<!-- tooltip end -->
<br>
For example:
<pre>
<b><font color="#000080">class</font></b> MyCode {
@Deprecated
// warning: "Deprecated member is still used"
<b><font color="#000080">void</font></b> <span style="background-color: yellow;">oldMethod</span>() {}
<b><font color="#000080">void</font></b> newMethod() {
oldMethod(); // forgotten usage
}
}
</pre>
(The usages from within deprecated places are ignored).
</body>
</html>
+3
View File
@@ -667,6 +667,9 @@
<localInspection groupPath="Java" language="JAVA" suppressId="deprecation" shortName="Deprecation" displayName="Deprecated API usage" groupKey="group.names.code.maturity.issues" groupBundle="messages.InspectionsBundle"
enabledByDefault="true" level="WARNING"
implementationClass="com.intellij.codeInspection.deprecation.DeprecationInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="DeprecatedIsStillUsed" displayName="Deprecated member is still used"
groupKey="group.names.code.maturity.issues" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"
implementationClass="com.intellij.codeInspection.DeprecatedIsStillUsedInspection" />
<localInspection language="XML" shortName="DeprecatedClassUsageInspection" displayName="Deprecated API usage in XML" groupKey="group.names.xml" groupBundle="messages.InspectionsBundle"
enabledByDefault="true" level="WARNING" implementationClass="com.intellij.codeInspection.xml.DeprecatedClassUsageInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="EqualsAndHashcode" bundle="messages.InspectionsBundle" key="inspection.equals.hashcode.display.name"