1 /******************************************************************************* 2 * Copyright (c) 2000, 2020 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.jdt.internal.ui.refactoring.actions; 15 16 import org.eclipse.core.runtime.CoreException; 17 18 import org.eclipse.jface.dialogs.MessageDialog; 19 import org.eclipse.jface.preference.IPreferenceStore; 20 import org.eclipse.jface.viewers.IStructuredSelection; 21 22 import org.eclipse.jface.text.IDocument; 23 import org.eclipse.jface.text.ITextSelection; 24 25 import org.eclipse.ui.IWorkbenchSite; 26 27 import org.eclipse.jdt.core.IField; 28 import org.eclipse.jdt.core.IJavaElement; 29 import org.eclipse.jdt.core.IPackageFragment; 30 import org.eclipse.jdt.core.IType; 31 import org.eclipse.jdt.core.ITypeRoot; 32 import org.eclipse.jdt.core.JavaModelException; 33 import org.eclipse.jdt.core.dom.AST; 34 import org.eclipse.jdt.core.dom.ASTNode; 35 import org.eclipse.jdt.core.dom.SimpleName; 36 37 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; 38 import org.eclipse.jdt.internal.corext.refactoring.RefactoringExecutionStarter; 39 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 40 41 import org.eclipse.jdt.ui.JavaUI; 42 import org.eclipse.jdt.ui.PreferenceConstants; 43 import org.eclipse.jdt.ui.actions.SelectionDispatchAction; 44 45 import org.eclipse.jdt.internal.ui.JavaPlugin; 46 import org.eclipse.jdt.internal.ui.actions.ActionUtil; 47 import org.eclipse.jdt.internal.ui.actions.SelectionConverter; 48 import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; 49 import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; 50 import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; 51 import org.eclipse.jdt.internal.ui.javaeditor.JavaTextSelection; 52 import org.eclipse.jdt.internal.ui.refactoring.RefactoringMessages; 53 import org.eclipse.jdt.internal.ui.refactoring.reorg.RenameLinkedMode; 54 import org.eclipse.jdt.internal.ui.text.correction.CorrectionCommandHandler; 55 import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedNamesAssistProposal; 56 import org.eclipse.jdt.internal.ui.util.ExceptionHandler; 57 58 public class RenameJavaElementAction extends SelectionDispatchAction { 59 60 private JavaEditor fEditor; 61 RenameJavaElementAction(IWorkbenchSite site)62 public RenameJavaElementAction(IWorkbenchSite site) { 63 super(site); 64 } 65 RenameJavaElementAction(JavaEditor editor)66 public RenameJavaElementAction(JavaEditor editor) { 67 this(editor.getEditorSite()); 68 fEditor= editor; 69 setEnabled(SelectionConverter.canOperateOn(fEditor)); 70 } 71 72 //---- Structured selection ------------------------------------------------ 73 74 @Override selectionChanged(IStructuredSelection selection)75 public void selectionChanged(IStructuredSelection selection) { 76 try { 77 if (selection.size() == 1) { 78 setEnabled(canEnable(selection)); 79 return; 80 } 81 } catch (JavaModelException e) { 82 // http://bugs.eclipse.org/bugs/show_bug.cgi?id=19253 83 if (JavaModelUtil.isExceptionToBeLogged(e)) 84 JavaPlugin.log(e); 85 } catch (CoreException e) { 86 JavaPlugin.log(e); 87 } 88 setEnabled(false); 89 } 90 canEnable(IStructuredSelection selection)91 private static boolean canEnable(IStructuredSelection selection) throws CoreException { 92 IJavaElement element= getJavaElement(selection); 93 if (element == null) 94 return false; 95 return RefactoringAvailabilityTester.isRenameElementAvailable(element); 96 } 97 getJavaElement(IStructuredSelection selection)98 private static IJavaElement getJavaElement(IStructuredSelection selection) { 99 if (selection.size() != 1) 100 return null; 101 Object first= selection.getFirstElement(); 102 if (! (first instanceof IJavaElement)) 103 return null; 104 return (IJavaElement)first; 105 } 106 107 @Override run(IStructuredSelection selection)108 public void run(IStructuredSelection selection) { 109 IJavaElement element= getJavaElement(selection); 110 if (element == null) 111 return; 112 if (!ActionUtil.isEditable(getShell(), element)) 113 return; 114 try { 115 run(element, false); 116 } catch (CoreException e){ 117 ExceptionHandler.handle(e, RefactoringMessages.RenameJavaElementAction_name, RefactoringMessages.RenameJavaElementAction_exception); 118 } 119 } 120 121 //---- text selection ------------------------------------------------------------ 122 123 @Override selectionChanged(ITextSelection selection)124 public void selectionChanged(ITextSelection selection) { 125 if (selection instanceof JavaTextSelection) { 126 try { 127 JavaTextSelection javaTextSelection= (JavaTextSelection)selection; 128 IJavaElement[] elements= javaTextSelection.resolveElementAtOffset(); 129 if (isVarTypeSelection(javaTextSelection)) { 130 setEnabled(false); 131 } 132 else { 133 if (elements.length == 1) { 134 setEnabled(RefactoringAvailabilityTester.isRenameElementAvailable(elements[0])); 135 } else { 136 ASTNode node= javaTextSelection.resolveCoveringNode(); 137 setEnabled(node instanceof SimpleName); 138 } 139 } 140 } catch (CoreException e) { 141 setEnabled(false); 142 } 143 } else { 144 setEnabled(true); 145 } 146 } 147 148 @Override run(ITextSelection selection)149 public void run(ITextSelection selection) { 150 if (!ActionUtil.isEditable(fEditor)) 151 return; 152 if (canRunInEditor() && !isVarTypeSelection(selection)) 153 doRun(); 154 else 155 MessageDialog.openInformation(getShell(), RefactoringMessages.RenameAction_rename, RefactoringMessages.RenameAction_unavailable); 156 } 157 doRun()158 public void doRun() { 159 RenameLinkedMode activeLinkedMode= RenameLinkedMode.getActiveLinkedMode(); 160 if (activeLinkedMode != null) { 161 if (activeLinkedMode.isCaretInLinkedPosition()) { 162 activeLinkedMode.startFullDialog(); 163 return; 164 } else { 165 activeLinkedMode.cancel(); 166 } 167 } 168 169 try { 170 IJavaElement element= getJavaElementFromEditor(); 171 IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); 172 boolean lightweight= store.getBoolean(PreferenceConstants.REFACTOR_LIGHTWEIGHT); 173 if (element != null && RefactoringAvailabilityTester.isRenameElementAvailable(element)) { 174 run(element, lightweight); 175 return; 176 } else if (lightweight) { 177 // fall back to local rename: 178 CorrectionCommandHandler handler= new CorrectionCommandHandler(fEditor, LinkedNamesAssistProposal.ASSIST_ID, true); 179 if (handler.doExecute()) { 180 fEditor.setStatusLineErrorMessage(RefactoringMessages.RenameJavaElementAction_started_rename_in_file); 181 return; 182 } 183 } 184 } catch (CoreException e) { 185 ExceptionHandler.handle(e, RefactoringMessages.RenameJavaElementAction_name, RefactoringMessages.RenameJavaElementAction_exception); 186 } 187 MessageDialog.openInformation(getShell(), RefactoringMessages.RenameJavaElementAction_name, RefactoringMessages.RenameJavaElementAction_not_available); 188 } 189 canRunInEditor()190 public boolean canRunInEditor() { 191 if (RenameLinkedMode.getActiveLinkedMode() != null) 192 return true; 193 194 try { 195 IJavaElement element= getJavaElementFromEditor(); 196 if (element == null) 197 return true; 198 199 return RefactoringAvailabilityTester.isRenameElementAvailable(element); 200 } catch (JavaModelException e) { 201 if (JavaModelUtil.isExceptionToBeLogged(e)) 202 JavaPlugin.log(e); 203 } catch (CoreException e) { 204 JavaPlugin.log(e); 205 } 206 return false; 207 } 208 getJavaElementFromEditor()209 private IJavaElement getJavaElementFromEditor() throws JavaModelException { 210 IJavaElement[] elements= SelectionConverter.codeResolve(fEditor); 211 if (elements == null || elements.length != 1) 212 return null; 213 if (elements[0].getElementType() == IJavaElement.LOCAL_VARIABLE) { 214 IJavaElement element= elements[0]; 215 IJavaElement parent= element.getParent(); 216 if(parent != null && parent.getElementType() == IJavaElement.FIELD) { 217 IField parentField= (IField) parent; 218 IJavaElement topParent= parent.getParent(); 219 if(topParent != null && topParent.getElementType() == IJavaElement.TYPE) { 220 if (((IType)topParent).isRecord()) { 221 return parentField; 222 } 223 } 224 } 225 } 226 return elements[0]; 227 } 228 229 //---- helper methods ------------------------------------------------------------------- 230 run(IJavaElement element, boolean lightweight)231 private void run(IJavaElement element, boolean lightweight) throws CoreException { 232 // Work around for http://dev.eclipse.org/bugs/show_bug.cgi?id=19104 233 if (! ActionUtil.isEditable(fEditor, getShell(), element)) 234 return; 235 //XXX workaround bug 31998 236 if (ActionUtil.mustDisableJavaModelAction(getShell(), element)) 237 return; 238 239 if (lightweight && fEditor instanceof CompilationUnitEditor && ! (element instanceof IPackageFragment)) { 240 new RenameLinkedMode(element, (CompilationUnitEditor) fEditor).start(); 241 } else { 242 RefactoringExecutionStarter.startRenameRefactoring(element, getShell()); 243 } 244 } 245 isVarTypeSelection(ITextSelection textSelection)246 private boolean isVarTypeSelection(ITextSelection textSelection) { 247 if (textSelection instanceof JavaTextSelection) { 248 ASTNode node= ((JavaTextSelection) textSelection).resolveCoveringNode(); 249 if (node instanceof SimpleName && node.getAST().apiLevel() >= AST.JLS10 && ((SimpleName) node).isVar()) { 250 return true; 251 } 252 } else if (textSelection != null) { 253 ITypeRoot typeRoot= EditorUtility.getEditorInputJavaElement(fEditor, true); 254 if (typeRoot != null) { 255 IDocument document= JavaUI.getDocumentProvider().getDocument(fEditor.getEditorInput()); 256 if (document != null) { 257 JavaTextSelection javaTextSelection= new JavaTextSelection(typeRoot, document, textSelection.getOffset(), textSelection.getLength()); 258 return isVarTypeSelection(javaTextSelection); 259 } 260 } 261 } 262 return false; 263 } 264 } 265