diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml
index 73eb0991a417..d49306eb8602 100644
--- a/plugins/devkit/resources/META-INF/plugin.xml
+++ b/plugins/devkit/resources/META-INF/plugin.xml
@@ -91,7 +91,7 @@
implementationClass="org.jetbrains.idea.devkit.inspections.ExtensionPointBeanClassInspection"/>
-
+
diff --git a/plugins/devkit/src/inspections/DevKitEntryPoints.java b/plugins/devkit/src/inspections/DevKitEntryPoints.java
deleted file mode 100644
index bb06e7171462..000000000000
--- a/plugins/devkit/src/inspections/DevKitEntryPoints.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2000-2013 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.codeInsight.daemon.ImplicitUsageProvider;
-import com.intellij.psi.*;
-
-/**
- * User: anna
- */
-public class DevKitEntryPoints implements ImplicitUsageProvider {
-
- @Override
- public boolean isImplicitUsage(PsiElement element) {
- if (element instanceof PsiClass) {
- final PsiClass psiClass = (PsiClass)element;
- if (psiClass.isEnum() ||
- psiClass.isAnnotationType() ||
- psiClass.hasModifierProperty(PsiModifier.PRIVATE)) {
- return false;
- }
-
- final PsiClass domClass =
- JavaPsiFacade.getInstance(element.getProject()).findClass("com.intellij.util.xml.DomElement", element.getResolveScope());
- if (domClass != null && psiClass.isInheritor(domClass, true)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean isImplicitRead(PsiElement element) {
- return false;
- }
-
- @Override
- public boolean isImplicitWrite(PsiElement element) {
- return false;
- }
-}
diff --git a/plugins/devkit/src/inspections/DevKitImplicitUsageProvider.java b/plugins/devkit/src/inspections/DevKitImplicitUsageProvider.java
new file mode 100644
index 000000000000..fa87c70ad337
--- /dev/null
+++ b/plugins/devkit/src/inspections/DevKitImplicitUsageProvider.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2000-2013 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.codeInsight.daemon.ImplicitUsageProvider;
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author anna
+ */
+public class DevKitImplicitUsageProvider implements ImplicitUsageProvider {
+
+ @Override
+ public boolean isImplicitUsage(PsiElement element) {
+ if (element instanceof PsiClass) {
+ final PsiClass psiClass = (PsiClass)element;
+ return isDomElementClass(psiClass);
+ }
+
+ if (element instanceof PsiMethod) {
+ PsiMethod psiMethod = (PsiMethod)element;
+ return isDomElementMethod(psiMethod);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean isImplicitRead(PsiElement element) {
+ return false;
+ }
+
+ @Override
+ public boolean isImplicitWrite(PsiElement element) {
+ return false;
+ }
+
+ private static boolean isDomElementClass(PsiClass psiClass) {
+ if (psiClass.isEnum() ||
+ psiClass.isAnnotationType() ||
+ psiClass.hasModifierProperty(PsiModifier.PRIVATE)) {
+ return false;
+ }
+
+ return isDomElementInheritor(psiClass);
+ }
+
+ private static boolean isDomElementMethod(PsiMethod psiMethod) {
+ if (!psiMethod.hasModifierProperty(PsiModifier.PUBLIC) ||
+ psiMethod.hasModifierProperty(PsiModifier.STATIC) ||
+ psiMethod.isConstructor() ||
+ psiMethod.getParameterList().getParametersCount() > 1) {
+ return false;
+ }
+
+ final PsiClass containingClass = psiMethod.getContainingClass();
+ if (containingClass == null) {
+ return false;
+ }
+
+ if (!isDomElementClass(containingClass)) {
+ return isDomElementVisitorMethod(psiMethod, containingClass);
+ }
+
+ final PsiType returnType = psiMethod.getReturnType();
+ if (!(returnType instanceof PsiClassType)) {
+ return false;
+ }
+
+ PsiClassType returnClassType = (PsiClassType)returnType;
+
+ // Dom getDom(), GenericAttributeValue getAttr(), ...
+ final PsiClass returnResolved = returnClassType.resolve();
+ if (isDomElementInheritor(returnResolved)) {
+ return true;
+ }
+
+ // List getDoms()
+ if (returnClassType.getParameterCount() == 1 &&
+ InheritanceUtil.isInheritor(returnResolved, CommonClassNames.JAVA_UTIL_LIST)) {
+ final PsiType listType = returnClassType.getParameters()[0];
+ return isDomElementInheritor(listType);
+ }
+
+ return false;
+ }
+
+ private static boolean isDomElementVisitorMethod(PsiMethod method,
+ PsiClass containingClass) {
+ if (method.getReturnType() != PsiType.VOID ||
+ !method.getName().startsWith("visit") ||
+ method.getParameterList().getParametersCount() != 1 ||
+ !InheritanceUtil.isInheritor(containingClass, "com.intellij.util.xml.DomElementVisitor")) {
+ return false;
+ }
+
+ final PsiType psiType = method.getParameterList().getParameters()[0].getType();
+ return isDomElementInheritor(psiType);
+ }
+
+ private static boolean isDomElementInheritor(@Nullable PsiType psiType) {
+ return InheritanceUtil.isInheritor(psiType, "com.intellij.util.xml.DomElement");
+ }
+
+ private static boolean isDomElementInheritor(@Nullable PsiClass psiClass) {
+ return InheritanceUtil.isInheritor(psiClass, "com.intellij.util.xml.DomElement");
+ }
+}
\ No newline at end of file
diff --git a/plugins/devkit/testData/codeInsight/ImplicitUsagesDomElement.java b/plugins/devkit/testData/codeInsight/ImplicitUsagesDomElement.java
new file mode 100644
index 000000000000..2bbdc6b95671
--- /dev/null
+++ b/plugins/devkit/testData/codeInsight/ImplicitUsagesDomElement.java
@@ -0,0 +1,32 @@
+import java.util.List;
+import com.intellij.util.xml.DomElement;
+import com.intellij.util.xml.GenericAttributeValue;
+
+public abstract class ImplicitUsagesDomElement implements DomElement {
+
+ public abstract GenericAttributeValue getStringAttribute();
+ public abstract ImplicitUsagesDomElement getDomElement();
+
+ public abstract List getDoms();
+
+ public abstract ImplicitUsagesDomElement addDom();
+ public abstract ImplicitUsagesDomElement addDomIndexed(int index);
+
+
+ // invalid ===========
+
+ private GenericAttributeValue getStringAttributePrivate() { return null; };
+ public static GenericAttributeValue getStringAttributeStatic() { return null; };
+
+ public String getNonDomString() { return null; };
+ public int getNonDomPrimitiveType() { return 0; }
+
+ private int normalPrivateMethod() { return 0; }
+
+ public List getNonDomList() { return null; }
+
+
+ public abstract ImplicitUsagesDomElement addDomMoreThanOneParam(int i, int j);
+ public String addNonDom() { return null; }
+
+}
\ No newline at end of file
diff --git a/plugins/devkit/testData/codeInsight/ImplicitUsagesDomElementVisitor.java b/plugins/devkit/testData/codeInsight/ImplicitUsagesDomElementVisitor.java
new file mode 100644
index 000000000000..938a9e8632d5
--- /dev/null
+++ b/plugins/devkit/testData/codeInsight/ImplicitUsagesDomElementVisitor.java
@@ -0,0 +1,30 @@
+import com.intellij.util.xml.DomElement;
+import com.intellij.util.xml.DomElementVisitor;
+
+public class ImplicitUsagesDomElementVisitor implements DomElementVisitor {
+
+ public static void main(String[] args) {} // suppress class unused
+
+ interface MyDom extends DomElement {}
+
+ public void visitMyDom(MyDom myDom) { myDom = null; }
+ public void visit(MyDom myDom) { myDom = null; }
+
+ // invalid ===========
+ public String nonVoidReturnTypeMethod(MyDom myDom) { myDom = null; return null; }
+ public void doesNotStartWithVisit(MyDom myDom) { myDom = null; }
+ public void nonDomParameter(int i) { i = 0; }
+ private void visitMyDomMoreThanOneParam(MyDom myDom, int index) { myDom = null; index = 0; }
+ private void visitMyDomPrivate(MyDom myDom) { myDom = null; }
+ public static void visitMyDomStatic(MyDom myDom) { myDom = null; }
+
+
+ public static class NonDomElementVisitorClass {
+
+ public static void main(String[] args) {} // suppress class unused
+
+ public void visitMyDom(MyDom myDom) { myDom = null; }
+
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy b/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy
index 25c19d643ee4..07df3077a4a7 100644
--- a/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy
+++ b/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -17,6 +17,8 @@ package org.jetbrains.idea.devkit.codeInsight
import com.intellij.codeInsight.TargetElementUtilBase
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.codeInspection.LocalInspectionTool
+import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection
+import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.PluginPathManager
import com.intellij.psi.ElementDescriptionUtil
@@ -196,6 +198,24 @@ public class PluginXmlFunctionalTest extends JavaCodeInsightFixtureTestCase {
myFixture.testHighlighting(true, true, true);
}
+ public void testImplicitUsagesDomElement() {
+ myFixture.addClass("package com.intellij.util.xml; public interface DomElement {}")
+ myFixture.addClass("package com.intellij.util.xml; public interface GenericAttributeValue extends DomElement {}")
+
+ myFixture.enableInspections(new UnusedSymbolLocalInspection(), new UnusedDeclarationInspection())
+ myFixture.configureByFile("ImplicitUsagesDomElement.java")
+ myFixture.testHighlighting()
+ }
+
+ public void testImplicitUsagesDomElementVisitor() {
+ myFixture.addClass("package com.intellij.util.xml; public interface DomElement {}")
+ myFixture.addClass("package com.intellij.util.xml; public interface DomElementVisitor {}")
+
+ myFixture.enableInspections(new UnusedSymbolLocalInspection(), new UnusedDeclarationInspection())
+ myFixture.configureByFile("ImplicitUsagesDomElementVisitor.java")
+ myFixture.testHighlighting()
+ }
+
static Collection> getInspectionClasses() {
return Arrays.asList(
//RegistrationProblemsInspection.class,