add a dev kit inspection: try to write stateless EP;
authorSergey Ignatov <sergey.ignatov@jetbrains.com>
Tue, 3 Nov 2015 11:30:05 +0000 (14:30 +0300)
committerSergey Ignatov <sergey.ignatov@jetbrains.com>
Tue, 3 Nov 2015 11:50:27 +0000 (14:50 +0300)
on IDEA-CR-6432

plugins/devkit/resources/META-INF/plugin.xml
plugins/devkit/resources/inspectionDescriptions/StatefulEp.html
plugins/devkit/src/inspections/StatefulEpInspection.java

index 9108d97e3e4538dba534dda60364f74e34f8f0ba..e1918e6fc5fa77babe875c6e906f14b6d5dc70ba 100644 (file)
     <localInspection language="JAVA" shortName="UnsafeReturnStatementVisitor" displayName="Unsafe return statements visitor"
                      groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.internal.UnsafeReturnStatementVisitorInspection" />
-    <localInspection language="JAVA" shortName="StatefulEp" displayName="Stateful EP"
+    <localInspection language="JAVA" shortName="StatefulEp" displayName="Stateful Extension"
                      groupKey="inspections.group.name"
                      enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.StatefulEpInspection"/>
index e54b56826000e8ab0edffec4eb35d0f6b5dc63a9..254ac913fe47e3adcb61ba06d223d05ffffd89b7 100644 (file)
@@ -1,5 +1,6 @@
 <html>
 <body>
-Are you sure about holding heavy objects in Extension Point implementation?
+Potential memory leak detected. Please don't hold heavy objects in extensions if you're not a 100% sure.
+In the ideal world, extensions should be stateless.
 </body>
 </html>
\ No newline at end of file
index 46f2664227922be3d649139058d096bedbdd40ce..c4015d232d878a071f6a7ceac885d846a8b86712 100644 (file)
@@ -40,23 +40,15 @@ public class StatefulEpInspection extends DevKitInspectionBase {
     if (isQuickFix || shouldCheck(psiClass)) {
       List<ProblemDescriptor> result = ContainerUtil.newArrayList();
       for (final PsiField field : fields) {
-        Checker projectChecker = new Checker(Project.class) {
-          @Override
-          boolean predicate() {
-            return !field.hasModifierProperty(PsiModifier.FINAL);
+        for (Class c : new Class[]{PsiElement.class, PsiReference.class, Project.class}) {
+          if (c == Project.class && field.hasModifierProperty(PsiModifier.FINAL)) continue;
+          String message = c == PsiElement.class
+                           ? "Potential memory leak: don't hold PsiElement, use SmartPsiElementPointer instead" +
+                             (isQuickFix ? "; also see LocalQuickFixOnPsiElement" : "")
+                           : "Don't use " + c.getSimpleName() + " as a field in extension";
+          if (InheritanceUtil.isInheritor(field.getType(), c.getCanonicalName())) {
+            result.add(manager.createProblemDescriptor(field, message, true, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly));
           }
-        };
-        Checker psiChecker = new Checker(PsiElement.class) {
-          @NotNull
-          @Override
-          String getMessage() {
-            return "Potential memory leak: don't hold PsiElement, use SmartPsiElementPointer instead of" +
-                   (isQuickFix ? "; also see LocalQuickFixOnPsiElement" : "");
-          }
-        };
-        Checker refChecker = new Checker(PsiReference.class);
-        for (Checker checker : new Checker[]{projectChecker, psiChecker, refChecker}) {
-          checker.check(field, manager, isOnTheFly, result);
         }
       }
       return result.toArray(new ProblemDescriptor[result.size()]);
@@ -70,29 +62,4 @@ public class StatefulEpInspection extends DevKitInspectionBase {
     }
     return false;
   }
-
-  private static class Checker {
-    @NotNull Class myClass;
-
-    private Checker(@NotNull Class psiClass) {
-      myClass = psiClass;
-    }
-
-    private void check(@NotNull PsiField field, @NotNull InspectionManager manager, boolean isOnTheFly, @NotNull List<ProblemDescriptor> result) {
-      if (predicate() && InheritanceUtil.isInheritor(field.getType(), myClass.getCanonicalName())) {
-        String message = getMessage();
-        String actual = message.isEmpty() ? "Don't use " + myClass.getSimpleName() + " as a field in extension points" : message;
-        result.add(manager.createProblemDescriptor(field, actual, true, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly));
-      }
-    }
-
-    @NotNull
-    String getMessage() {
-      return "";
-    }
-
-    boolean predicate() {
-      return true;
-    }
-  }
 }
\ No newline at end of file