allow plugins to suppress "interface never implemented" and "abstract class has no concrete subclass" inspections for classes which are implemented by proxies at runtime (e.g. for classes extending DomElement in DevKit)

This commit is contained in:
nik
2014-08-25 12:20:54 +04:00
parent 6f1dc649bf
commit 20b41d2793
7 changed files with 71 additions and 2 deletions
@@ -0,0 +1,29 @@
/*
* Copyright 2000-2014 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.inheritance;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.PsiClass;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class ImplementedAtRuntimeCondition {
public static final ExtensionPointName<ImplementedAtRuntimeCondition> EP_NAME = ExtensionPointName.create("com.intellij.codeInsight.implementedAtRuntime");
public abstract boolean isImplementedAtRuntime(@NotNull PsiClass psiClass);
}
@@ -15,6 +15,7 @@
*/
package com.siyeh.ig.psiutils;
import com.intellij.codeInspection.inheritance.ImplementedAtRuntimeCondition;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiClass;
@@ -80,6 +81,11 @@ public class InheritanceUtil {
public static boolean hasImplementation(@NotNull PsiClass aClass) {
final SearchScope scope = GlobalSearchScope.projectScope(aClass.getProject());
if (aClass.isInterface() && FunctionalExpressionSearch.search(aClass, scope).findFirst() != null) return true;
for (ImplementedAtRuntimeCondition condition : ImplementedAtRuntimeCondition.EP_NAME.getExtensions()) {
if (condition.isImplementedAtRuntime(aClass)) {
return true;
}
}
final Query<PsiClass> search = ClassInheritorsSearch.search(aClass, scope, true, true);
return !search.forEach(new Processor<PsiClass>() {
@Override
@@ -152,6 +152,7 @@
implementationClass="org.jetbrains.idea.devkit.navigation.DescriptionTypeRelatedItemLineMarkerProvider"/>
<codeInsight.lineMarkerProvider language="JAVA"
implementationClass="org.jetbrains.idea.devkit.navigation.ExtensionPointDeclarationRelatedItemLineMarkerProvider"/>
<codeInsight.implementedAtRuntime implementation="org.jetbrains.idea.devkit.inspections.DevKitImplementedAtRuntimeCondition"/>
</extensions>
<project-components>
@@ -0,0 +1,30 @@
/*
* Copyright 2000-2014 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 org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInspection.inheritance.ImplementedAtRuntimeCondition;
import com.intellij.psi.PsiClass;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public class DevKitImplementedAtRuntimeCondition extends ImplementedAtRuntimeCondition {
@Override
public boolean isImplementedAtRuntime(@NotNull PsiClass psiClass) {
return DevKitImplicitUsageProvider.isDomElementClass(psiClass);
}
}
@@ -50,7 +50,7 @@ public class DevKitImplicitUsageProvider implements ImplicitUsageProvider {
return false;
}
private static boolean isDomElementClass(PsiClass psiClass) {
static boolean isDomElementClass(PsiClass psiClass) {
if (psiClass.isEnum() ||
psiClass.isAnnotationType() ||
psiClass.hasModifierProperty(PsiModifier.PRIVATE)) {
@@ -20,6 +20,7 @@ import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.testFramework.TestDataPath;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import com.siyeh.ig.inheritance.AbstractClassNeverImplementedInspection;
@TestDataPath("$CONTENT_ROOT/testData/inspections/implicitUsage")
public class DevKitImplicitUsageProviderTest extends LightCodeInsightFixtureTestCase {
@@ -37,7 +38,7 @@ public class DevKitImplicitUsageProviderTest extends LightCodeInsightFixtureTest
myFixture.addClass("package com.intellij.util.xml; public interface DomElementVisitor {}");
myFixture.addClass("package com.intellij.util.xml; public interface GenericAttributeValue<T> extends DomElement {}");
myFixture.enableInspections(new UnusedSymbolLocalInspection(), new UnusedDeclarationInspection());
myFixture.enableInspections(new UnusedSymbolLocalInspection(), new UnusedDeclarationInspection(), new AbstractClassNeverImplementedInspection());
}
public void testImplicitUsagesDomElement() {
+2
View File
@@ -46,6 +46,8 @@
<extensionPoints>
<extensionPoint name="codeInsight.changeVariableTypeQuickFixProvider"
interface="com.intellij.codeInsight.quickfix.ChangeVariableTypeQuickFixProvider"/>
<extensionPoint name="codeInsight.implementedAtRuntime"
interface="com.intellij.codeInspection.inheritance.ImplementedAtRuntimeCondition"/>
<extensionPoint name="conversion.rule"
interface="com.intellij.refactoring.typeMigration.rules.TypeConversionRule"/>