1 19 package org.netbeans.modules.java.editor.rename; 20 21 import com.sun.source.util.TreePath; 22 import java.awt.event.ActionEvent ; 23 import java.io.IOException ; 24 import java.util.EnumSet ; 25 import java.util.HashSet ; 26 import java.util.Set ; 27 import javax.lang.model.element.Element; 28 import javax.lang.model.element.ElementKind; 29 import javax.lang.model.element.ElementKind; 30 import javax.lang.model.element.ExecutableElement; 31 import javax.lang.model.util.ElementFilter; 32 import javax.swing.Action ; 33 import javax.swing.text.BadLocationException ; 34 import javax.swing.text.Document ; 35 import javax.swing.text.JTextComponent ; 36 import org.netbeans.api.java.source.CancellableTask; 37 import org.netbeans.api.java.source.CompilationController; 38 import org.netbeans.api.java.source.CompilationInfo; 39 import org.netbeans.api.java.source.JavaSource; 40 import org.netbeans.api.java.source.JavaSource.Phase; 41 import org.netbeans.editor.BaseAction; 42 import org.netbeans.editor.Utilities; 43 import org.netbeans.modules.editor.highlights.spi.Highlight; 44 import org.netbeans.modules.java.editor.semantic.ColoringAttributes; 45 import org.netbeans.modules.java.editor.semantic.FindLocalUsagesQuery; 46 import org.netbeans.modules.refactoring.api.ui.RefactoringActionsFactory; 47 import org.openide.DialogDisplayer; 48 import org.openide.ErrorManager; 49 import org.openide.NotifyDescriptor; 50 import org.openide.cookies.EditorCookie; 51 import org.openide.cookies.EditorCookie; 52 import org.openide.loaders.DataObject; 53 import org.openide.nodes.Node; 54 import org.openide.util.Lookup; 55 import org.openide.util.RequestProcessor; 56 import org.openide.util.lookup.AbstractLookup; 57 import org.openide.util.lookup.InstanceContent; 58 59 63 public class InstantRenameAction extends BaseAction { 64 65 66 public InstantRenameAction() { 67 super("in-place-refactoring", ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET 68 | SAVE_POSITION); 69 } 70 71 public void actionPerformed(ActionEvent evt, final JTextComponent target) { 72 try { 73 final int caret = target.getCaretPosition(); 74 String ident = Utilities.getIdentifier(Utilities.getDocument(target), caret); 75 76 if (ident == null) { 77 Utilities.setStatusBoldText(target, "Cannot perform instant rename here."); 78 return; 79 } 80 81 DataObject od = (DataObject) target.getDocument().getProperty(Document.StreamDescriptionProperty); 82 JavaSource js = JavaSource.forFileObject(od.getPrimaryFile()); 83 final boolean[] wasResolved = new boolean[1]; 84 final Set <Highlight>[] changePoints = new Set [1]; 85 86 js.runUserActionTask(new CancellableTask<CompilationController>() { 87 public void cancel() { 88 } 89 public void run(CompilationController controller) throws Exception { 90 if (controller.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) 91 return; 92 93 changePoints[0] = computeChangePoints(controller, caret, wasResolved); 94 } 95 }, true); 96 97 if (wasResolved[0]) { 98 if (changePoints[0] != null) { 99 doInstantRename(changePoints[0], target, caret, ident); 100 } else { 101 doFullRename(od.getCookie(EditorCookie.class), od.getNodeDelegate()); 102 } 103 } else { 104 Utilities.setStatusBoldText(target, "Cannot perform instant rename here."); 105 } 106 } catch (BadLocationException e) { 107 ErrorManager.getDefault().notify(e); 108 } catch (IOException ioe) { 109 ErrorManager.getDefault().notify(ioe); 110 } 111 } 112 113 @Override 114 protected Class getShortDescriptionBundleClass() { 115 return InstantRenameAction.class; 116 } 117 118 private void doInstantRename(Set <Highlight> changePoints, JTextComponent target, int caret, String ident) throws BadLocationException { 119 InstantRenamePerformer.performInstantRename(target, changePoints, caret); 120 } 121 122 private void doFullRename(EditorCookie ec, Node n) { 123 124 InstanceContent ic = new InstanceContent(); 125 ic.add(ec); 126 ic.add(n); 127 Lookup actionContext = new AbstractLookup(ic); 128 129 Action a = RefactoringActionsFactory.renameAction().createContextAwareInstance(actionContext); 130 a.actionPerformed(RefactoringActionsFactory.DEFAULT_EVENT); 131 } 132 133 static Set <Highlight> computeChangePoints(CompilationInfo info, final int caret, final boolean[] wasResolved) throws IOException { 134 TreePath path = info.getTreeUtilities().pathFor(caret); 135 Element el = info.getTrees().getElement(path); 136 137 if (el == null) { 138 wasResolved[0] = false; 139 return null; 140 } 141 142 final Highlight name = org.netbeans.modules.java.editor.semantic.Utilities.createHighlight(info.getCompilationUnit(), info.getTrees().getSourcePositions(), info.getDocument(), path, EnumSet.of(ColoringAttributes.MARK_OCCURRENCES), null); 144 145 info.getDocument().render(new Runnable () { 146 public void run() { 147 wasResolved[0] = name.getStart() <= caret && caret <= name.getEnd(); 148 } 149 }); 150 151 if (!wasResolved[0]) 152 return null; 153 154 if (el.getKind() == ElementKind.CONSTRUCTOR) { 155 el = el.getEnclosingElement(); 157 } 158 159 if (allowInstantRename(el)) { 160 Set <Highlight> points = new HashSet <Highlight>(new FindLocalUsagesQuery().findUsages(el, info, info.getDocument())); 161 162 if (el.getKind().isClass()) { 163 for (ExecutableElement c : ElementFilter.constructorsIn(el.getEnclosedElements())) { 165 TreePath t = info.getTrees().getPath(c); 166 167 if (t != null) { 168 Highlight h = org.netbeans.modules.java.editor.semantic.Utilities.createHighlight(info.getCompilationUnit(), info.getTrees().getSourcePositions(), info.getDocument(), t, EnumSet.of(ColoringAttributes.MARK_OCCURRENCES), null); 169 170 if (h != null) { 171 points.add(h); 172 } 173 } 174 } 175 } 176 177 return points; 178 } 179 180 return null; 181 } 182 183 private static boolean allowInstantRename(Element e) { 184 if (org.netbeans.modules.java.editor.semantic.Utilities.isPrivateElement(e)) { 185 return true; 186 } 187 188 if (e.getKind() == ElementKind.CLASS) { Element enclosing = e.getEnclosingElement(); 191 192 return LOCAL_CLASS_PARENTS.contains(enclosing.getKind()); 193 } 194 195 return false; 196 } 197 198 private static final Set <ElementKind> LOCAL_CLASS_PARENTS = EnumSet.of(ElementKind.CONSTRUCTOR, ElementKind.INSTANCE_INIT, ElementKind.METHOD, ElementKind.STATIC_INIT); 199 200 } 201 | Popular Tags |