devkit: don't hold psi in quick fixed and cleanup
authorSergey Ignatov <sergey.ignatov@jetbrains.com>
Thu, 5 Nov 2015 13:01:53 +0000 (16:01 +0300)
committerSergey Ignatov <sergey.ignatov@jetbrains.com>
Thu, 5 Nov 2015 13:06:29 +0000 (16:06 +0300)
plugins/devkit/src/actions/NewActionDialog.java
plugins/devkit/src/inspections/ComponentNotRegisteredInspection.java
plugins/devkit/src/inspections/quickfix/AbstractRegisterFix.java
plugins/devkit/src/inspections/quickfix/BaseFix.java
plugins/devkit/src/inspections/quickfix/CreateConstructorFix.java
plugins/devkit/src/inspections/quickfix/ImplementOrExtendFix.java
plugins/devkit/src/inspections/quickfix/RegisterActionFix.java
plugins/devkit/src/inspections/quickfix/RegisterComponentFix.java
plugins/devkit/src/util/PsiUtil.java

index 779929ceb8184565e000ee44793a3fe3c2b53159..d3a155f7dbdda7c1b215463357600473e2a02cc1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -24,7 +24,6 @@ import com.intellij.openapi.keymap.KeymapUtil;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
-import com.intellij.psi.JavaPsiFacade;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiNameHelper;
 import com.intellij.ui.ColoredListCellRenderer;
@@ -78,7 +77,7 @@ public class NewActionDialog extends DialogWrapper implements ActionData {
   private Project myProject;
   private ButtonGroup myAnchorButtonGroup;
 
-  public  NewActionDialog(PsiClass actionClass) {
+  public NewActionDialog(@NotNull PsiClass actionClass) {
     this(actionClass.getProject());
 
     myActionNameEdit.setText(actionClass.getQualifiedName());
@@ -89,18 +88,18 @@ public class NewActionDialog extends DialogWrapper implements ActionData {
     }
   }
 
-  protected NewActionDialog(final Project project) {
+  protected NewActionDialog(Project project) {
     super(project, false);
     myProject = project;
     init();
     setTitle(DevKitBundle.message("new.action.dialog.title"));
     final ActionManager actionManager = ActionManager.getInstance();
-    final String[] actionIds = actionManager.getActionIds("");
+    String[] actionIds = actionManager.getActionIds("");
     Arrays.sort(actionIds);
-    final List<ActionGroup> actionGroups = new ArrayList<ActionGroup>();
+    List<ActionGroup> actionGroups = new ArrayList<ActionGroup>();
     for(String actionId: actionIds) {
       if (actionManager.isGroup(actionId)) {
-        final AnAction anAction = actionManager.getAction(actionId);
+        AnAction anAction = actionManager.getAction(actionId);
         if (anAction instanceof DefaultActionGroup) {
           actionGroups.add((ActionGroup) anAction);
         }
@@ -115,7 +114,7 @@ public class NewActionDialog extends DialogWrapper implements ActionData {
           myActionList.setListData(ArrayUtil.EMPTY_OBJECT_ARRAY);
         }
         else {
-          final AnAction[] actions = group.getChildren(null);
+          AnAction[] actions = group.getChildren(null);
           // filter out actions that don't have IDs - they can't be used for anchoring in plugin.xml
           List<AnAction> realActions = new ArrayList<AnAction>();
           for(AnAction action: actions) {
@@ -128,7 +127,7 @@ public class NewActionDialog extends DialogWrapper implements ActionData {
       }
     });
     new ListSpeedSearch(myGroupList, new Function<Object, String>() {
-      public String fun(final Object o) {
+      public String fun(Object o) {
         return ActionManager.getInstance().getId((AnAction) o);
       }
     });
@@ -140,7 +139,7 @@ public class NewActionDialog extends DialogWrapper implements ActionData {
       }
     });
 
-    final MyDocumentListener listener = new MyDocumentListener();
+    MyDocumentListener listener = new MyDocumentListener();
     myActionIdEdit.getDocument().addDocumentListener(listener);
     myActionNameEdit.getDocument().addDocumentListener(listener);
     myActionTextEdit.getDocument().addDocumentListener(listener);
@@ -158,8 +157,8 @@ public class NewActionDialog extends DialogWrapper implements ActionData {
     myFirstKeystrokeEdit.getDocument().addDocumentListener(listener);
     myClearFirstKeystroke.setText(null);
 
-    final Icon icon = AllIcons.Actions.Cancel;
-    final Dimension size = new Dimension(icon.getIconWidth(), icon.getIconHeight());
+    Icon icon = AllIcons.Actions.Cancel;
+    Dimension size = new Dimension(icon.getIconWidth(), icon.getIconHeight());
     myClearFirstKeystroke.setIcon(icon);
     myClearFirstKeystroke.setPreferredSize(size);
     myClearFirstKeystroke.setMaximumSize(size);
@@ -266,7 +265,7 @@ public class NewActionDialog extends DialogWrapper implements ActionData {
     protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
       AnAction group = (AnAction) value;
       append(ActionManager.getInstance().getId(group), SimpleTextAttributes.REGULAR_ATTRIBUTES);
-      final String text = group.getTemplatePresentation().getText();
+      String text = group.getTemplatePresentation().getText();
       if (text != null) {
         append(" (" + text + ")", SimpleTextAttributes.REGULAR_ATTRIBUTES);
       }
index efa00629281fc3b691eeae0f119655fbe9a3e1d0..63a6de641a0493f0caf5c5d5b56026141c9aee5f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -40,9 +40,6 @@ import javax.swing.*;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 
-/**
- * @author swr
- */
 public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
   public boolean CHECK_ACTIONS = true;
   public boolean IGNORE_NON_PUBLIC = true;
@@ -65,7 +62,7 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
 
   @Nullable
   public JComponent createOptionsPanel() {
-    final JPanel jPanel = new JPanel();
+    JPanel jPanel = new JPanel();
     jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.Y_AXIS));
 
     final JCheckBox ignoreNonPublic = new JCheckBox(
@@ -82,7 +79,7 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
             CHECK_ACTIONS);
     checkJavaActions.addChangeListener(new ChangeListener() {
       public void stateChanged(ChangeEvent e) {
-        final boolean selected = checkJavaActions.isSelected();
+        boolean selected = checkJavaActions.isSelected();
         CHECK_ACTIONS = selected;
         ignoreNonPublic.setEnabled(selected);
       }
@@ -95,8 +92,8 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
 
   @Nullable
   public ProblemDescriptor[] checkClass(@NotNull PsiClass checkedClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
-    final PsiFile psiFile = checkedClass.getContainingFile();
-    final PsiIdentifier classIdentifier = checkedClass.getNameIdentifier();
+    PsiFile psiFile = checkedClass.getContainingFile();
+    PsiIdentifier classIdentifier = checkedClass.getNameIdentifier();
     if (checkedClass.getQualifiedName() != null &&
         classIdentifier != null &&
         psiFile != null &&
@@ -108,11 +105,11 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
         return null;
       }
 
-      final PsiManager psiManager = checkedClass.getManager();
-      final GlobalSearchScope scope = checkedClass.getResolveScope();
+      PsiManager psiManager = checkedClass.getManager();
+      GlobalSearchScope scope = checkedClass.getResolveScope();
 
       if (CHECK_ACTIONS) {
-        final PsiClass actionClass = JavaPsiFacade.getInstance(psiManager.getProject()).findClass(AnAction.class.getName(), scope);
+        PsiClass actionClass = JavaPsiFacade.getInstance(psiManager.getProject()).findClass(AnAction.class.getName(), scope);
         if (actionClass == null) {
           // stop if action class cannot be found (non-devkit module/project)
           return null;
@@ -122,8 +119,8 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
             return null;
           }
           if (!isActionRegistered(checkedClass) && canFix(checkedClass)) {
-            final LocalQuickFix fix = new RegisterActionFix(checkedClass);
-            final ProblemDescriptor problem = manager.createProblemDescriptor(
+            LocalQuickFix fix = new RegisterActionFix(org.jetbrains.idea.devkit.util.PsiUtil.createPointer(checkedClass));
+            ProblemDescriptor problem = manager.createProblemDescriptor(
                     classIdentifier,
                     DevKitBundle.message("inspections.component.not.registered.message",
                                          DevKitBundle.message("new.menu.action.text")),
@@ -136,17 +133,17 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
         }
       }
 
-      final ComponentType[] types = ComponentType.values();
+      ComponentType[] types = ComponentType.values();
       for (ComponentType type : types) {
-        final PsiClass compClass = JavaPsiFacade.getInstance(psiManager.getProject()).findClass(type.myClassName, scope);
+        PsiClass compClass = JavaPsiFacade.getInstance(psiManager.getProject()).findClass(type.myClassName, scope);
         if (compClass == null) {
           // stop if component classes cannot be found (non-devkit module/project)
           return null;
         }
         if (checkedClass.isInheritor(compClass, true)) {
           if (getRegistrationTypes(checkedClass, false) == null && canFix(checkedClass)) {
-            final LocalQuickFix fix = new RegisterComponentFix(type, checkedClass);
-            final ProblemDescriptor problem = manager.createProblemDescriptor(classIdentifier,
+            LocalQuickFix fix = new RegisterComponentFix(type, org.jetbrains.idea.devkit.util.PsiUtil.createPointer(checkedClass));
+            ProblemDescriptor problem = manager.createProblemDescriptor(classIdentifier,
                                                                               DevKitBundle.message("inspections.component.not.registered.message",
                                                                                                    DevKitBundle.message(type.myPropertyKey)),
                                                                               fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
@@ -162,10 +159,10 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
   }
 
   private static boolean canFix(PsiClass psiClass) {
-    final Project project = psiClass.getProject();
-    final PsiFile psiFile = psiClass.getContainingFile();
+    Project project = psiClass.getProject();
+    PsiFile psiFile = psiClass.getContainingFile();
     LOG.assertTrue(psiFile != null);
-    final Module module = ModuleUtilCore.findModuleForFile(psiFile.getVirtualFile(), project);
+    Module module = ModuleUtilCore.findModuleForFile(psiFile.getVirtualFile(), project);
     return PluginModuleType.isPluginModuleOrDependency(module);
   }
 }
index 0fe0e82ae95bdd9edc02532185ea11c3a85da60d..294332acec5dca64deabd783363a7c2b532cdc96 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -26,6 +26,7 @@ import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiFile;
+import com.intellij.psi.SmartPsiElementPointer;
 import com.intellij.psi.xml.XmlFile;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NonNls;
@@ -38,11 +39,11 @@ import org.jetbrains.idea.devkit.util.DescriptorUtil;
 import java.util.List;
 
 abstract class AbstractRegisterFix implements LocalQuickFix, DescriptorUtil.Patcher {
-  protected final PsiClass myClass;
-  private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.devkit.inspections.quickfix.AbstractRegisterFix");
+  protected final SmartPsiElementPointer<PsiClass> myPointer;
+  protected static final Logger LOG = Logger.getInstance(AbstractRegisterFix.class);
 
-  public AbstractRegisterFix(PsiClass klass) {
-    myClass = klass;
+  public AbstractRegisterFix(@NotNull SmartPsiElementPointer<PsiClass> klass) {
+    myPointer = klass;
   }
 
   @NotNull
@@ -60,7 +61,7 @@ abstract class AbstractRegisterFix implements LocalQuickFix, DescriptorUtil.Patc
   // copy of com.intellij.ide.actions.CreateElementActionBase.filterMessage()
   protected static String filterMessage(String message) {
     if (message == null) return null;
-    @NonNls final String ioExceptionPrefix = "java.io.IOException:";
+    @NonNls String ioExceptionPrefix = "java.io.IOException:";
     if (message.startsWith(ioExceptionPrefix)) {
       message = message.substring(ioExceptionPrefix.length());
     }
@@ -69,7 +70,12 @@ abstract class AbstractRegisterFix implements LocalQuickFix, DescriptorUtil.Patc
 
   public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) {
     if (!FileModificationService.getInstance().preparePsiElementForWrite(descriptor.getPsiElement())) return;
-    final PsiFile psiFile = myClass.getContainingFile();
+    PsiFile psiFile = myPointer.getContainingFile();
+    final PsiClass element = myPointer.getElement();
+    if (element == null) {
+      LOG.info("Element is null for PsiPointer: " + myPointer);
+      return;
+    }
     LOG.assertTrue(psiFile != null);
     final Module module = ModuleUtil.findModuleForFile(psiFile.getVirtualFile(), project);
     assert module != null;
@@ -78,26 +84,26 @@ abstract class AbstractRegisterFix implements LocalQuickFix, DescriptorUtil.Patc
       public void run() {
         try {
           if (PluginModuleType.isOfType(module)) {
-            final XmlFile pluginXml = PluginModuleType.getPluginXml(module);
+            XmlFile pluginXml = PluginModuleType.getPluginXml(module);
             if (pluginXml != null) {
-              DescriptorUtil.patchPluginXml(AbstractRegisterFix.this, myClass, pluginXml);
+              DescriptorUtil.patchPluginXml(AbstractRegisterFix.this, element, pluginXml);
             }
           }
           else {
             List<Module> modules = PluginModuleType.getCandidateModules(module);
             if (modules.size() > 1) {
-              final ChooseModulesDialog dialog = new ChooseModulesDialog(project, modules, getName());
+              ChooseModulesDialog dialog = new ChooseModulesDialog(project, modules, getName());
               if (!dialog.showAndGet()) {
                 return;
               }
               modules = dialog.getSelectedModules();
             }
-            final XmlFile[] pluginXmls = new XmlFile[modules.size()];
+            XmlFile[] pluginXmls = new XmlFile[modules.size()];
             for (int i = 0; i < pluginXmls.length; i++) {
               pluginXmls[i] = PluginModuleType.getPluginXml(modules.get(i));
             }
 
-            DescriptorUtil.patchPluginXml(AbstractRegisterFix.this, myClass, pluginXmls);
+            DescriptorUtil.patchPluginXml(AbstractRegisterFix.this, element, pluginXmls);
           }
           CommandProcessor.getInstance().markCurrentCommandAsGlobal(project);
         }
index 6dd775740ca57e548361fbeeb691d3516f4d9ad5..fdc1b4d9b5b5cf2563660c2dec7f49add89a074f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -24,43 +24,42 @@ import com.intellij.openapi.vfs.ReadonlyStatusHandler;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiElement;
+import com.intellij.psi.SmartPsiElementPointer;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.idea.devkit.DevKitBundle;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.devkit.DevKitBundle;
 
-/**
- * @author swr
- */
 abstract class BaseFix implements LocalQuickFix {
-  protected final PsiElement myElement;
+  protected final SmartPsiElementPointer<? extends PsiElement> myPointer;
   protected final boolean myOnTheFly;
 
-  protected BaseFix(PsiElement element, boolean onTheFly) {
-    myElement = element;
+  protected BaseFix(@NotNull SmartPsiElementPointer<? extends PsiElement> pointer, boolean onTheFly) {
+    myPointer = pointer;
     myOnTheFly = onTheFly;
   }
 
   public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
     // can happen during batch-inspection if resolution has already been applied
     // to plugin.xml or java class
-    if (!myElement.isValid()) return;
+    PsiElement element = myPointer.getElement();
+    if (element == null || !element.isValid()) return;
 
-    final boolean external = descriptor.getPsiElement().getContainingFile() != myElement.getContainingFile();
+    boolean external = descriptor.getPsiElement().getContainingFile() != element.getContainingFile();
     if (external) {
-      final PsiClass clazz = PsiTreeUtil.getParentOfType(myElement, PsiClass.class, false);
-      final ReadonlyStatusHandler readonlyStatusHandler = ReadonlyStatusHandler.getInstance(project);
-      final VirtualFile[] files = new VirtualFile[]{myElement.getContainingFile().getVirtualFile()};
-      final ReadonlyStatusHandler.OperationStatus status = readonlyStatusHandler.ensureFilesWritable(files);
+      PsiClass clazz = PsiTreeUtil.getParentOfType(element, PsiClass.class, false);
+      ReadonlyStatusHandler readonlyStatusHandler = ReadonlyStatusHandler.getInstance(project);
+      VirtualFile[] files = new VirtualFile[]{element.getContainingFile().getVirtualFile()};
+      ReadonlyStatusHandler.OperationStatus status = readonlyStatusHandler.ensureFilesWritable(files);
 
       if (status.hasReadonlyFiles()) {
-        final String className = clazz != null ? clazz.getQualifiedName() : myElement.getContainingFile().getName();
+        String className = clazz != null ? clazz.getQualifiedName() : element.getContainingFile().getName();
 
         Messages.showMessageDialog(project,
-                DevKitBundle.message("inspections.registration.problems.quickfix.read-only",
-                        className),
-                getName(),
-                Messages.getErrorIcon());
+                                   DevKitBundle.message("inspections.registration.problems.quickfix.read-only",
+                                                        className),
+                                   getName(),
+                                   Messages.getErrorIcon());
         return;
       }
     }
index cce73cd8d504ff11d03598e7dc56ebe8fb81fcac..d0d53902c30f67ebc53d14383fa8192eea086fa6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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,22 +17,17 @@ package org.jetbrains.idea.devkit.inspections.quickfix;
 
 import com.intellij.codeInspection.ProblemDescriptor;
 import com.intellij.openapi.project.Project;
-import com.intellij.psi.JavaPsiFacade;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiModifier;
+import com.intellij.psi.*;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.idea.devkit.DevKitBundle;
 
-/**
- * @author swr
- */
-public class CreateConstructorFix extends BaseFix {
+import static org.jetbrains.idea.devkit.util.PsiUtil.createPointer;
 
-  public CreateConstructorFix(PsiClass checkedClass, boolean onTheFly) {
-    super(checkedClass, onTheFly);
+public class CreateConstructorFix extends BaseFix {
+  public CreateConstructorFix(@NotNull PsiClass aClass, boolean isOnTheFly) {
+    super(createPointer(aClass), isOnTheFly);
   }
 
   @NotNull
@@ -46,12 +41,14 @@ public class CreateConstructorFix extends BaseFix {
   }
 
   protected void doFix(Project project, ProblemDescriptor descriptor, boolean external) throws IncorrectOperationException {
-    final PsiClass clazz = (PsiClass)myElement;
+    PsiElement element = myPointer.getElement();
+    if (!(element instanceof PsiClass)) return;
+    PsiClass clazz = (PsiClass)element;
 
     PsiMethod ctor = JavaPsiFacade.getInstance(clazz.getProject()).getElementFactory().createConstructor();
     PsiUtil.setModifierProperty(ctor, PsiModifier.PUBLIC, true);
 
-    final PsiMethod[] constructors = clazz.getConstructors();
+    PsiMethod[] constructors = clazz.getConstructors();
     if (constructors.length > 0) {
       ctor = (PsiMethod)clazz.addBefore(ctor, constructors[0]);
     } else {
index 31693193819e68ce1e6d9ec1d205bc9f7b3ebeb9..1acf58c513206f62e7f98f77a05d5ff428990b2f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -25,32 +25,35 @@ import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.idea.devkit.DevKitBundle;
 
-/**
- * @author swr
- */
-public class ImplementOrExtendFix extends BaseFix {
+import static org.jetbrains.idea.devkit.util.PsiUtil.createPointer;
 
-  private final PsiClass myCompClass;
+public class ImplementOrExtendFix extends BaseFix {
+  private final SmartPsiElementPointer<PsiClass> myCompClassPointer;
 
-  private ImplementOrExtendFix(PsiClass compClass, PsiClass checkedClass, boolean onTheFly) {
-    super(checkedClass, onTheFly);
-    myCompClass = compClass;
+  private ImplementOrExtendFix(@NotNull PsiClass compClass,
+                               @NotNull PsiClass checkedClass,
+                               boolean onTheFly) {
+    super(createPointer(checkedClass), onTheFly);
+    myCompClassPointer = createPointer(compClass);
   }
 
+  @NotNull
   public static LocalQuickFix[] createFix(PsiClass compClass, PsiClass checkedClass, boolean onTheFly) {
     ImplementOrExtendFix fix = null;
 
     if (compClass.isInterface() && compClass.getImplementsList() != null) {
       fix = new ImplementOrExtendFix(compClass, checkedClass, onTheFly);
-    } else if (!compClass.isInterface()) {
-      final PsiReferenceList extendsList = checkedClass.getExtendsList();
+    }
+    else if (!compClass.isInterface()) {
+      PsiReferenceList extendsList = checkedClass.getExtendsList();
       if (extendsList != null) {
         if (extendsList.getReferenceElements().length == 0) {
           fix = new ImplementOrExtendFix(compClass, checkedClass, onTheFly);
-        } else if (extendsList.getReferenceElements().length == 1) {
+        }
+        else if (extendsList.getReferenceElements().length == 1) {
           // check for explicit "extends Object" case
-          final PsiClassType javaLangObject = PsiType.getJavaLangObject(checkedClass.getManager(),
-                  checkedClass.getResolveScope());
+          PsiClassType javaLangObject = PsiType.getJavaLangObject(checkedClass.getManager(),
+                                                                        checkedClass.getResolveScope());
           if (extendsList.getReferencedTypes()[0].equals(javaLangObject)) {
             fix = new ImplementOrExtendFix(compClass, checkedClass, onTheFly);
           }
@@ -62,10 +65,12 @@ public class ImplementOrExtendFix extends BaseFix {
 
   @NotNull
   public String getName() {
-    return (myCompClass.isInterface()
+    PsiClass clazz = myCompClassPointer.getElement();
+    if (clazz == null) return "Invalid";
+    return (clazz.isInterface()
             ? StringUtil.capitalize(DevKitBundle.message("keyword.implement"))
             : StringUtil.capitalize(DevKitBundle.message("keyword.extend")))
-            + " '" + myCompClass.getQualifiedName() + "'";
+           + " '" + clazz.getQualifiedName() + "'";
   }
 
   @NotNull
@@ -74,16 +79,21 @@ public class ImplementOrExtendFix extends BaseFix {
   }
 
   protected void doFix(Project project, ProblemDescriptor descriptor, boolean external) throws IncorrectOperationException {
-    final PsiClass clazz = (PsiClass)myElement;
-    final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(clazz.getProject()).getElementFactory();
-    final PsiClassType compType = elementFactory.createType(myCompClass);
+    PsiElement element = myPointer.getElement();
+    PsiClass compClass = myCompClassPointer.getElement();
+    if (!(element instanceof PsiClass)) return;
+    if (compClass == null) return;
+    PsiClass clazz = (PsiClass)element;
+    PsiElementFactory elementFactory = JavaPsiFacade.getInstance(clazz.getProject()).getElementFactory();
+    PsiClassType compType = elementFactory.createType(compClass);
 
-    final PsiReferenceList list;
-    if (myCompClass.isInterface()) {
+    PsiReferenceList list;
+    if (compClass.isInterface()) {
       list = clazz.getImplementsList();
       assert list != null;
-    } else {
-      final PsiReferenceList extendsList = clazz.getExtendsList();
+    }
+    else {
+      PsiReferenceList extendsList = clazz.getExtendsList();
       assert extendsList != null;
       if (extendsList.getReferencedTypes().length > 0) {
         extendsList.getReferenceElements()[0].delete();
@@ -91,7 +101,7 @@ public class ImplementOrExtendFix extends BaseFix {
       list = extendsList;
     }
 
-    final PsiElement e = list.add(elementFactory.createReferenceElementByType(compType));
+    PsiElement e = list.add(elementFactory.createReferenceElementByType(compType));
     if (myOnTheFly && external && e instanceof Navigatable) ((Navigatable)e).navigate(true);
   }
 }
index 5a56054492f93cf489f42e6ca8f143e561608053..8abdb2bce51d674b2b613b6eb7c439338021e262 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -19,6 +19,7 @@ import com.intellij.codeInspection.ProblemDescriptor;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.PsiClass;
+import com.intellij.psi.SmartPsiElementPointer;
 import com.intellij.psi.xml.XmlFile;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
@@ -31,8 +32,8 @@ import org.jetbrains.idea.devkit.util.ActionType;
 public class RegisterActionFix extends AbstractRegisterFix {
   private NewActionDialog myDialog;
 
-  public RegisterActionFix(PsiClass klass) {
-    super(klass);
+  public RegisterActionFix(@NotNull SmartPsiElementPointer<PsiClass> pointer) {
+    super(pointer);
   }
 
   protected String getType() {
@@ -46,7 +47,12 @@ public class RegisterActionFix extends AbstractRegisterFix {
     }
 
     try {
-      myDialog = new NewActionDialog(myClass);
+      PsiClass element = myPointer.getElement();
+      if (element == null) {
+        LOG.info("Element is null for PsiPointer: " + myPointer);
+        return;
+      }
+      myDialog = new NewActionDialog(element);
       if (myDialog.showAndGet()) {
         super.applyFix(project, descriptor);
       }
index 0c3d0fd645e27535c2b66dda42ae497563d51f35..2f6c5a5b782f3a6aaca17f0c728bdd6fe83149b9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
 package org.jetbrains.idea.devkit.inspections.quickfix;
 
 import com.intellij.psi.PsiClass;
+import com.intellij.psi.SmartPsiElementPointer;
 import com.intellij.psi.xml.XmlFile;
 import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.idea.devkit.DevKitBundle;
 import org.jetbrains.idea.devkit.util.ComponentType;
 
 public class RegisterComponentFix extends AbstractRegisterFix {
   private final ComponentType myType;
 
-  public RegisterComponentFix(ComponentType type, PsiClass klass) {
-    super(klass);
+  public RegisterComponentFix(ComponentType type, @NotNull SmartPsiElementPointer<PsiClass> pointer) {
+    super(pointer);
     myType = type;
   }
 
index ffa1a5b430992342f7b4cc1f57cc972963ba39d1..99c6e86f5c34bf8187f34d989aa1f63c26a6c5c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -39,12 +39,12 @@ public class PsiUtil {
   private PsiUtil() { }
 
   public static boolean isInstantiable(@NotNull PsiClass cls) {
-    final PsiModifierList modList = cls.getModifierList();
+    PsiModifierList modList = cls.getModifierList();
     if (modList == null || cls.isInterface() || modList.hasModifierProperty(PsiModifier.ABSTRACT) || !isPublicOrStaticInnerClass(cls)) {
       return false;
     }
 
-    final PsiMethod[] constructors = cls.getConstructors();
+    PsiMethod[] constructors = cls.getConstructors();
     if (constructors.length == 0) return true;
 
     for (PsiMethod constructor : constructors) {
@@ -57,7 +57,7 @@ public class PsiUtil {
   }
 
   public static boolean isPublicOrStaticInnerClass(@NotNull PsiClass cls) {
-    final PsiModifierList modifiers = cls.getModifierList();
+    PsiModifierList modifiers = cls.getModifierList();
     if (modifiers == null) return false;
 
     return modifiers.hasModifierProperty(PsiModifier.PUBLIC) &&
@@ -66,9 +66,9 @@ public class PsiUtil {
 
   @Nullable
   public static String getReturnedLiteral(PsiMethod method, PsiClass cls) {
-    final PsiExpression value = getReturnedExpression(method);
+    PsiExpression value = getReturnedExpression(method);
     if (value instanceof PsiLiteralExpression) {
-      final Object str = ((PsiLiteralExpression)value).getValue();
+      Object str = ((PsiLiteralExpression)value).getValue();
       return str == null ? null : str.toString();
     }
     else if (value instanceof PsiMethodCallExpression) {
@@ -95,11 +95,11 @@ public class PsiUtil {
     if (body != null) {
       PsiStatement[] statements = body.getStatements();
       if (statements.length == 1 && statements[0] instanceof PsiReturnStatement) {
-        final PsiExpression value = ((PsiReturnStatement)statements[0]).getReturnValue();
+        PsiExpression value = ((PsiReturnStatement)statements[0]).getReturnValue();
         if (value instanceof PsiReferenceExpression) {
-          final PsiElement element = ((PsiReferenceExpression)value).resolve();
+          PsiElement element = ((PsiReferenceExpression)value).resolve();
           if (element instanceof PsiField) {
-            final PsiField field = (PsiField)element;
+            PsiField field = (PsiField)element;
             if (field.hasModifierProperty(PsiModifier.FINAL)) {
               return field.getInitializer();
             }
@@ -183,4 +183,9 @@ public class PsiUtil {
 
     return true;
   }
+
+  @NotNull
+  public static <E extends PsiElement> SmartPsiElementPointer<E> createPointer(@NotNull E e) {
+    return SmartPointerManager.getInstance(e.getProject()).createSmartPsiElementPointer(e);
+  }
 }