Extension method syntax inspection

This commit is contained in:
Roman Shevchenko
2012-11-10 21:36:44 +01:00
parent 1eef8f0897
commit 3656acccf1
8 changed files with 131 additions and 28 deletions
@@ -0,0 +1,67 @@
/*
* Copyright 2000-2012 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.deprecation;
import com.intellij.codeInspection.*;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiModifierListImpl;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
// todo[r.sh] drop this after transition period finished
public class DeprecatedDefenderSyntaxInspection extends BaseJavaLocalInspectionTool {
private final LocalQuickFix myQuickFix = new MyQuickFix();
@Nullable
@Override
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod method, @NotNull InspectionManager manager, boolean isOnTheFly) {
final PsiJavaToken marker = PsiModifierListImpl.findExtensionMethodMarker(method);
return marker == null ? null : new ProblemDescriptor[]{
manager.createProblemDescriptor(marker, getDisplayName(), myQuickFix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly)
};
}
private static class MyQuickFix implements LocalQuickFix {
@NotNull
@Override
public String getName() {
return InspectionsBundle.message("deprecated.defender.syntax.fix");
}
@NotNull
@Override
public String getFamilyName() {
return "";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement marker = descriptor.getPsiElement();
if (marker != null && PsiUtil.isJavaToken(marker, JavaTokenType.DEFAULT_KEYWORD)) {
final PsiElement parent = marker.getParent();
if (parent instanceof PsiMethod) {
marker.delete();
final PsiMethod method = (PsiMethod)parent;
if (!method.hasModifierProperty(PsiModifier.DEFAULT)) {
PsiUtil.setModifierProperty(method, PsiModifier.DEFAULT, true);
}
}
}
}
}
}
@@ -180,7 +180,7 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
}
@Nullable
private static PsiJavaToken findExtensionMethodMarker(@Nullable PsiMethod method) {
public static PsiJavaToken findExtensionMethodMarker(@Nullable PsiMethod method) {
// todo[r.sh] drop this after transition period finished
if (method == null) return null;
final PsiCodeBlock body = method.getBody();
@@ -0,0 +1,8 @@
interface I {
void m1() <warning descr="Deprecated extension method syntax">default</warning> { }
default void m2() <warning descr="Deprecated extension method syntax">default</warning> { }
@SuppressWarnings("extensionSyntax")
void m3() default { }
}
@@ -17,11 +17,11 @@ package com.intellij.codeInsight.daemon;
import com.intellij.ExtensionPoints;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.compiler.JavacQuirksInspection;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.codeInspection.defUse.DefUseInspection;
import com.intellij.codeInspection.deprecation.DeprecatedDefenderSyntaxInspection;
import com.intellij.codeInspection.redundantCast.RedundantCastInspection;
import com.intellij.codeInspection.reference.EntryPoint;
import com.intellij.codeInspection.reference.RefElement;
@@ -45,13 +45,13 @@ import java.util.List;
public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/advHighlighting7";
private void doTest(boolean checkWarnings, boolean checkInfos, InspectionProfileEntry... tools) throws Exception {
for (InspectionProfileEntry tool : tools) { enableInspectionTool(tool); }
private void doTest(boolean checkWarnings, boolean checkInfos, Class<?>... classes) {
enableInspectionTools(classes);
doTest(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, checkInfos);
}
private void doTest(boolean checkWarnings, boolean checkWeakWarnings, boolean checkInfos, InspectionProfileEntry... tools) throws Exception {
for (InspectionProfileEntry tool : tools) { enableInspectionTool(tool); }
private void doTest(boolean checkWarnings, boolean checkWeakWarnings, boolean checkInfos, Class<?>... classes) {
enableInspectionTools(classes);
doTest(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, checkWeakWarnings, checkInfos);
}
@@ -93,16 +93,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
public void testDiamondNeg12() throws Exception { doTest(false, false); }
public void testDiamondNeg13() throws Exception { doTest(false, false); }
public void testDiamondNeg14() throws Exception { doTest(false, false); }
public void testDiamondMisc() throws Exception {
final LanguageLevel oldLevel = getLanguageLevel();
try {
setLanguageLevel(LanguageLevel.JDK_1_7);
doTest(false, false);
}
finally {
setLanguageLevel(oldLevel);
}
}
public void testDiamondMisc() throws Exception { setLanguageLevel(LanguageLevel.JDK_1_7); doTest(false, false); }
public void testHighlightInaccessibleFromClassModifierList() throws Exception { doTest(false, false); }
public void testInnerInTypeArguments() throws Exception { doTest(false, false); }
@@ -138,28 +129,25 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
}
}
public void testJavacQuirks() throws Exception {
setLanguageLevel(LanguageLevel.JDK_1_6);
doTest(true, false);
}
public void testJavacQuirks() throws Exception { setLanguageLevel(LanguageLevel.JDK_1_6); doTest(true, false); }
public void testNumericLiterals() throws Exception { doTest(false, false); }
public void testMultiCatch() throws Exception { doTest(false, false); }
public void testTryWithResources() throws Exception { doTest(false, false); }
public void testTryWithResourcesWarn() throws Exception { doTest(true, false, new DefUseInspection()); }
public void testTryWithResourcesWarn() throws Exception { doTest(true, false, DefUseInspection.class); }
public void testSafeVarargsApplicability() throws Exception { doTest(true, false); }
public void testUncheckedGenericsArrayCreation() throws Exception { doTest(true, false); }
public void testGenericsArrayCreation() throws Exception { doTest(false, false); }
public void testPreciseRethrow() throws Exception { doTest(false, false); }
public void testImprovedCatchAnalysis() throws Exception { doTest(true, false); }
public void testPolymorphicTypeCast() throws Exception { doTest(true, false); }
public void testErasureClashConfusion() throws Exception { doTest(true, false, new UnusedDeclarationInspection()); }
public void testUnused() throws Exception { doTest(true, false, new UnusedDeclarationInspection()); }
public void testErasureClashConfusion() throws Exception { doTest(true, false, UnusedDeclarationInspection.class); }
public void testUnused() throws Exception { doTest(true, false, UnusedDeclarationInspection.class); }
public void testSuperBound() throws Exception { doTest(false, false); }
public void testExtendsBound() throws Exception { doTest(false, false); }
public void testIDEA84533() throws Exception { doTest(false, false); }
public void testClassLiteral() throws Exception { doTest(false, false); }
public void testExtensionMethods() throws Exception { doTest(false, false); }
public void testExtensionMethodSyntax() throws Exception { doTest(true, false, DeprecatedDefenderSyntaxInspection.class); }
public void testMethodReferences() throws Exception { doTest(false, true, false); }
public void testUsedMethodsByMethodReferences() throws Exception { doTest(true, true, false); }
public void testLambdaExpressions() throws Exception { doTest(false, true, false); }
@@ -652,4 +652,7 @@ inspection.javadoc.problem.pointing.to.itself=Javadoc pointing to itself
inspection.redirect.template=<html><body>Injected element has problem: {0} (in <a href=\"#navigation/{1}:{2}\">{3}</a>). </body></html>
nothing.found=Nothing found
special.annotations.list.annotation.pattern=Add Annotations Pattern
special.annotations.list.annotation.pattern=Add Annotations Pattern
deprecated.defender.syntax.description=Deprecated extension method syntax
deprecated.defender.syntax.fix=Convert extension method syntax
@@ -22,9 +22,7 @@ import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInspection.GlobalInspectionTool;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.*;
import com.intellij.ide.highlighter.ProjectFileType;
import com.intellij.ide.startup.StartupManagerEx;
@@ -44,6 +42,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.editor.impl.EditorFactoryImpl;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
import com.intellij.openapi.fileTypes.FileType;
@@ -437,6 +436,35 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
}
}
// todo: use Class<? extends InspectionProfileEntry> once on Java 7
protected void enableInspectionTools(@NotNull Class<?>... classes) {
final InspectionProfileEntry[] tools = new InspectionProfileEntry[classes.length];
final List<InspectionEP> eps = ContainerUtil.newArrayList();
ContainerUtil.addAll(eps, Extensions.getExtensions(LocalInspectionEP.LOCAL_INSPECTION));
ContainerUtil.addAll(eps, Extensions.getExtensions(InspectionEP.GLOBAL_INSPECTION));
ContainerUtil.addAll(eps, (InspectionEP[])Extensions.getExtensions("com.intellij.specialTool"));
next:
for (int i = 0; i < classes.length; i++) {
for (InspectionEP ep : eps) {
if (classes[i].getName().equals(ep.implementationClass)) {
tools[i] = ep.instantiateTool();
continue next;
}
}
throw new IllegalArgumentException("Unable to find extension point for " + classes[i].getName());
}
enableInspectionTools(tools);
}
protected void enableInspectionTools(@NotNull InspectionProfileEntry... tools) {
for (InspectionProfileEntry tool : tools) {
enableInspectionTool(tool);
}
}
protected void enableInspectionTool(@NotNull InspectionProfileEntry tool) {
if (tool instanceof InspectionTool) {
enableInspectionTool(myAvailableInspectionTools, (InspectionTool)tool);
@@ -0,0 +1,6 @@
<html xmlns="http://www.w3.org/1999/html">
<body>
Detects deprecated extension method syntax: <pre>void m() default { }</pre>
Allows to convert it to the correct form: <pre>default void m() { }</pre>
</body>
</html>
+3
View File
@@ -456,6 +456,9 @@
<localInspection language="JAVA" suppressId="deprecation" shortName="Deprecation" displayName="Deprecated API usage" groupName=""
enabledByDefault="true" level="WARNING"
implementationClass="com.intellij.codeInspection.deprecation.DeprecationInspection"/>
<localInspection language="JAVA" shortName="extensionSyntax" bundle="messages.InspectionsBundle" key="deprecated.defender.syntax.description"
groupName="" enabledByDefault="true" level="WARNING"
implementationClass="com.intellij.codeInspection.deprecation.DeprecatedDefenderSyntaxInspection"/>
<localInspection language="XML" shortName="DeprecatedClassUsageInspection" displayName="Deprecated API usage in XML" groupName="XML"
enabledByDefault="true" level="WARNING" implementationClass="com.intellij.util.xml.DeprecatedClassUsageInspection"/>
<localInspection language="JAVA" shortName="EqualsAndHashcode" bundle="messages.InspectionsBundle" key="inspection.equals.hashcode.display.name"