Added a new refactoring action: net.sourceforge.phpdt.ltk.ui.actions.RenameLocalVariable
authoraxelcl <axelcl>
Sun, 15 Jan 2006 21:54:16 +0000 (21:54 +0000)
committeraxelcl <axelcl>
Sun, 15 Jan 2006 21:54:16 +0000 (21:54 +0000)
This refactoring replaces any $-variable inside a function or method declaration
The action can detect the scope of a PHP function or class method.
Currently this refactoring doesn't replace variables inside double quoted strings.
This refactoring doesn't look for global variables inside the function or method.
This refactoring doesn't look correctly for "self::" and "$this" tokens inside the function or method.
This refactoring doesn't look for a preceding PHPDoc comment and therefore cannot replace any local variables inside the PHPdoc comment.

16 files changed:
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/CoreTexts.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenameIdentifierDelegate.java [moved from net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenamePropertyDelegate.java with 96% similarity]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenameIdentifierInfo.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenameIdentifierRefactoring.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenameLocalVariableDelegate.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenamePHPProcessor.java [moved from net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenamePropertyProcessor.java with 83% similarity]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenamePropertyInfo.java [deleted file]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenamePropertyRefactoring.java [deleted file]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/UITexts.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/actions/RenameLocalVariable.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/actions/RenamePHPIdentifier.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/uitexts.properties
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameIdentifierPage.java [copied from net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/wizards/RenamePropertyInputPage.java with 93% similarity]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameIdentifierWizard.java [copied from net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/wizards/RenamePropertyWizard.java with 60% similarity]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameLocalVariablePage.java [moved from net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/wizards/RenamePropertyInputPage.java with 72% similarity]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/wizards/RenameLocalVariableWizard.java [moved from net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/wizards/RenamePropertyWizard.java with 60% similarity]

index 731454c..bad78a2 100644 (file)
@@ -11,7 +11,6 @@ import org.eclipse.osgi.util.NLS;
  * bundle.
  * </p>
  *
- * @author Leif Frenzel
  */
 public class CoreTexts extends NLS {
 
@@ -33,5 +32,4 @@ public class CoreTexts extends NLS {
        public static String renamePropertyDelegate_collectingChanges;
 
        public static String renamePropertyDelegate_checking;
-       // public static String renamePropertyDelegate_propNotFound;
 }
\ No newline at end of file
@@ -42,18 +42,17 @@ import org.eclipse.text.edits.ReplaceEdit;
  * delegate object that contains the logic used by the processor.
  * </p>
  *
- * @author Leif Frenzel
  */
-class RenamePropertyDelegate {
+public class RenameIdentifierDelegate {
 
        // private static final String EXT_PROPERTIES = "properties"; //$NON-NLS-1$
 
-       private final RenamePropertyInfo info;
+       protected final RenameIdentifierInfo info;
 
        // PHP file with the identifier to rename -> offset of the key
-       private final Map phpFiles;
+       protected final Map phpFiles;
 
-       RenamePropertyDelegate(final RenamePropertyInfo info) {
+       public RenameIdentifierDelegate(final RenameIdentifierInfo info) {
                this.info = info;
                phpFiles = new HashMap();
        }
@@ -134,7 +133,7 @@ class RenamePropertyDelegate {
                return result;
        }
 
-       void createChange(final IProgressMonitor pm, final CompositeChange rootChange) {
+       protected void createChange(final IProgressMonitor pm, final CompositeChange rootChange) {
                try {
                        pm.beginTask(CoreTexts.renamePropertyDelegate_collectingChanges, 100);
                        // all files in the same bundle
@@ -165,7 +164,7 @@ class RenamePropertyDelegate {
        // return result;
        // }
 
-       private Change[] createChangesForContainer(final IProgressMonitor pm) {
+       protected Change[] createChangesForContainer(final IProgressMonitor pm) {
                List result = new ArrayList();
                Iterator it = phpFiles.keySet().iterator();
                int numberOfFiles = phpFiles.size();
@@ -195,7 +194,7 @@ class RenamePropertyDelegate {
                return (Change[]) result.toArray(new Change[result.size()]);
        }
 
-       private boolean isEmpty(final String candidate) {
+       protected boolean isEmpty(final String candidate) {
                return candidate == null || candidate.trim().length() == 0;
        }
 
@@ -258,7 +257,7 @@ class RenamePropertyDelegate {
                }
        }
 
-       private List getKeyOffsets(final IFile file) {
+       protected List getKeyOffsets(final IFile file) {
                return (List) phpFiles.get(file);
        }
 
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenameIdentifierInfo.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenameIdentifierInfo.java
new file mode 100644 (file)
index 0000000..60a9457
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+// modified for phpeclipse.de project by axelcl
+package net.sourceforge.phpdt.ltk.core;
+
+import net.sourceforge.phpdt.internal.core.SourceMethod;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * <p>
+ * an info object that holds the information that is passed from the user to the
+ * refactoring.
+ * </p>
+ *
+ */
+public class RenameIdentifierInfo {
+
+       // the offset of the property to be renamed in the file
+       private int offset;
+
+       // the new name for the property
+       private String newName;
+
+       // the old name of the property (as selected by the user)
+       private String oldName;
+
+       // the file that contains the property to be renamed
+       private IFile sourceFile;
+
+       // whether the refactoring should also change the identifier
+       // in corresponding PHP files in the same project
+       private boolean updateProject;
+
+       // whether the refactoring should also update PHP files in other
+       // projects than the current one
+       private boolean allProjects;
+
+       private SourceMethod method;
+
+       public int getOffset() {
+               return offset;
+       }
+
+       public void setOffset(final int offset) {
+               this.offset = offset;
+       }
+
+       public String getNewName() {
+               return newName;
+       }
+
+       public void setNewName(final String newName) {
+               this.newName = newName;
+       }
+
+       public String getOldName() {
+               return oldName;
+       }
+
+       public void setOldName(final String oldName) {
+               this.oldName = oldName;
+       }
+
+       public IFile getSourceFile() {
+               return sourceFile;
+       }
+
+       public void setSourceFile(final IFile sourceFile) {
+               this.sourceFile = sourceFile;
+       }
+
+       public boolean isAllProjects() {
+               return allProjects;
+       }
+
+       public void setAllProjects(final boolean allProjects) {
+               this.allProjects = allProjects;
+       }
+
+       public boolean isUpdateProject() {
+               return updateProject;
+       }
+
+       public void setUpdateProject(final boolean updateBundle) {
+               this.updateProject = updateBundle;
+       }
+
+       public SourceMethod getMethod() {
+               return method;
+       }
+
+       public void setMethod(SourceMethod method) {
+               this.method = method;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenameIdentifierRefactoring.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenameIdentifierRefactoring.java
new file mode 100644 (file)
index 0000000..54c2bad
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+// modified for phpeclipse.de project by axelcl
+package net.sourceforge.phpdt.ltk.core;
+
+import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring;
+import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
+
+/**
+ * <p>
+ * Refactoring for renaming identifiers in PHP files.
+ * </p>
+ *
+ * <p>
+ * All the actual work is done in the processor, so we just have to keep a
+ * reference to one here.
+ * <p>
+ *
+ */
+public class RenameIdentifierRefactoring extends ProcessorBasedRefactoring {
+
+       private final RefactoringProcessor processor;
+
+       public RenameIdentifierRefactoring(final RefactoringProcessor processor) {
+               super(processor);
+               this.processor = processor;
+       }
+
+       public RefactoringProcessor getProcessor() {
+               return processor;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenameLocalVariableDelegate.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenameLocalVariableDelegate.java
new file mode 100644 (file)
index 0000000..11f3fd5
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+// modified for phpeclipse.de project by axelcl
+package net.sourceforge.phpdt.ltk.core;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.ISourceRange;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.core.SourceMethod;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.CompositeChange;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.ltk.core.refactoring.TextFileChange;
+import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
+import org.eclipse.ltk.core.refactoring.participants.IConditionChecker;
+import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+
+/**
+ * <p>
+ * delegate object that contains the logic used by the processor.
+ * </p>
+ *
+ */
+public class RenameLocalVariableDelegate extends RenameIdentifierDelegate {
+
+       public RenameLocalVariableDelegate(final RenameIdentifierInfo info) {
+               super(info);
+       }
+
+       RefactoringStatus checkInitialConditions() {
+               RefactoringStatus result = new RefactoringStatus();
+               IFile sourceFile = info.getSourceFile();
+               if (sourceFile == null || !sourceFile.exists()) {
+                       result.addFatalError(CoreTexts.renamePropertyDelegate_noSourceFile);
+               } else if (info.getSourceFile().isReadOnly()) {
+                       result.addFatalError(CoreTexts.renamePropertyDelegate_roFile);
+               } else if (isEmpty(info.getOldName())) {
+                       // || !isPropertyKey( info.getSourceFile(), info.getOldName() ) ) {
+                       result.addFatalError(CoreTexts.renamePropertyDelegate_noPHPKey);
+               }
+               return result;
+       }
+
+       RefactoringStatus checkFinalConditions(final IProgressMonitor pm, final CheckConditionsContext ctxt) {
+               RefactoringStatus result = new RefactoringStatus();
+               pm.beginTask(CoreTexts.renamePropertyDelegate_checking, 100);
+               // do something long-running here: traverse the entire project (or even
+               // workspace) to look for all *.p files with the same bundle
+               // base name
+               IFile file = info.getSourceFile();
+               IProject project = file.getProject();
+               try {
+                       SourceMethod method = info.getMethod();
+                       ISourceRange range = method.getSourceRange();
+                       if (project.isNatureEnabled(PHPeclipsePlugin.PHP_NATURE_ID)) {
+                               determineMethodOffsets(file, range.getOffset(), range.getLength(), result);
+                       }
+               } catch (CoreException e) {
+                       String msg = "Project: " + project.getLocation().toOSString() + " CoreException " + e.getMessage();
+                       result.addError(msg);
+               } catch (Exception e) {
+                       String msg = "Project: " + project.getLocation().toOSString() + " Exception " + e.getMessage();
+                       result.addError(msg);
+               }
+
+               pm.worked(50);
+
+               if (ctxt != null) {
+                       IFile[] files = new IFile[phpFiles.size()];
+                       phpFiles.keySet().toArray(files);
+                       IConditionChecker checker = ctxt.getChecker(ValidateEditChecker.class);
+                       ValidateEditChecker editChecker = (ValidateEditChecker) checker;
+                       editChecker.addFiles(files);
+               }
+               pm.done();
+               return result;
+       }
+
+       protected void createChange(final IProgressMonitor pm, final CompositeChange rootChange) {
+               try {
+                       pm.beginTask(CoreTexts.renamePropertyDelegate_collectingChanges, 100);
+                       // all files in the same bundle
+                       rootChange.addAll(createChangesForContainer(pm));
+               } finally {
+                       pm.done();
+               }
+       }
+
+       // finds the offsets of the identifier to rename
+       // usually, this would be the job of a proper parser;
+       // using a primitive brute-force approach here
+       private void determineMethodOffsets(final IFile file, int offset, int length, final RefactoringStatus status) {
+               ArrayList matches = new ArrayList();
+               try {
+                       String content = readFileContent(file, status);
+                       String methodString = content.substring(offset, offset + length);
+                       Scanner scanner = new Scanner(true, false);
+                       scanner.setSource(methodString.toCharArray());
+                       scanner.setPHPMode(true);
+                       char[] word = info.getOldName().toCharArray();
+
+                       int fToken = ITerminalSymbols.TokenNameEOF;
+                       try {
+                               fToken = scanner.getNextToken();
+                               while (fToken != ITerminalSymbols.TokenNameEOF) {
+                                       if (fToken == ITerminalSymbols.TokenNameVariable) {
+                                               if (scanner.equalsCurrentTokenSource(word)) {
+                                                       matches.add(Integer.valueOf(scanner.getCurrentTokenStartPosition() + offset));
+                                               }
+                                       }
+                                       fToken = scanner.getNextToken();
+                               }
+
+                       } catch (InvalidInputException e) {
+                               String msg = "File: " + file.getLocation().toOSString() + " InvalidInputException " + e.getMessage();
+                               status.addError(msg);
+                       } catch (SyntaxError e) {
+                               String msg = "File: " + file.getLocation().toOSString() + " SyntaxError " + e.getMessage();
+                               status.addError(msg);
+                       }
+
+               } catch (Exception e) {
+                       String msg = "File: " + file.getLocation().toOSString() + " Exception " + e.getMessage();
+                       status.addError(msg);
+               }
+               if (matches.size() > 0) {
+                       phpFiles.put(file, matches);
+               }
+       }
+
+       private String readFileContent(final IFile file, final RefactoringStatus refStatus) {
+               String result = null;
+               try {
+                       InputStream is = file.getContents();
+                       byte[] buf = new byte[1024];
+                       ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                       int len = is.read(buf);
+                       while (len > 0) {
+                               bos.write(buf, 0, len);
+                               len = is.read(buf);
+                       }
+                       is.close();
+                       result = new String(bos.toByteArray());
+               } catch (Exception ex) {
+                       String msg = ex.toString();
+                       refStatus.addFatalError(msg);
+                       String pluginId = PHPeclipsePlugin.getPluginId();
+                       IStatus status = new Status(IStatus.ERROR, pluginId, 0, msg, ex);
+                       PHPeclipsePlugin.getDefault().getLog().log(status);
+               }
+               return result;
+       }
+
+}
@@ -12,22 +12,18 @@ import org.eclipse.ltk.core.refactoring.participants.*;
   * of the refactoring. In order to do that, the refactoring entry point
   * methods must be implemented.</p>
   *
-  * @author Leif Frenzel
   */
-public class RenamePropertyProcessor extends RefactoringProcessor {
+public class RenamePHPProcessor extends RefactoringProcessor {
 
-  private final RenamePropertyInfo info;
-  private final RenamePropertyDelegate delegate;
+  private final RenameIdentifierInfo info;
+  private final RenameIdentifierDelegate delegate;
 
-  public RenamePropertyProcessor( final RenamePropertyInfo info ) {
+  public RenamePHPProcessor( final RenameIdentifierInfo info, final RenameIdentifierDelegate delegate ) {
     this.info = info;
-    delegate = new RenamePropertyDelegate( info );
+    this.delegate = delegate;
   }
 
 
-  // interface methods of RefactoringProcessor
-  ////////////////////////////////////////////
-
   public Object[] getElements() {
     // usually, this would be some element object in the object model on which
     // we work (e.g. a Java element if we were in the Java Model); in this case
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenamePropertyInfo.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenamePropertyInfo.java
deleted file mode 100644 (file)
index 32a2c8c..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
-// See http://leiffrenzel.de
-// modified for phpeclipse.de project by axelcl
-package net.sourceforge.phpdt.ltk.core;
-
-import org.eclipse.core.resources.IFile;
-
-
-/** <p>an info object that holds the information that is passed from
-  * the user to the refactoring.</p>
-  *
-  * @author Leif Frenzel
-  */
-public class RenamePropertyInfo {
-
-  // the offset of the property to be renamed in the file
-  private int offset;
-  // the new name for the property
-  private String newName;
-  // the old name of the property (as selected by the user)
-  private String oldName;
-  // the file that contains the property to be renamed
-  private IFile sourceFile;
-  // whether the refactoring should also change the identifier
-  // in corresponding PHP files in the same project
-  private boolean updateProject;
-  // whether the refactoring should also update PHP files in other
-  // projects than the current one
-  private boolean allProjects;
-
-
-  // interface methods of IRenamePropertyInfo
-  ///////////////////////////////////////////
-
-  public int getOffset() {
-    return offset;
-  }
-
-  public void setOffset( final int offset ) {
-    this.offset = offset;
-  }
-
-  public String getNewName() {
-    return newName;
-  }
-
-  public void setNewName( final String newName ) {
-    this.newName = newName;
-  }
-
-  public String getOldName() {
-    return oldName;
-  }
-
-  public void setOldName( final String oldName ) {
-    this.oldName = oldName;
-  }
-
-  public IFile getSourceFile() {
-    return sourceFile;
-  }
-
-  public void setSourceFile( final IFile sourceFile ) {
-    this.sourceFile = sourceFile;
-  }
-
-  public boolean isAllProjects() {
-    return allProjects;
-  }
-
-  public void setAllProjects( final boolean allProjects ) {
-    this.allProjects = allProjects;
-  }
-
-  public boolean isUpdateProject() {
-    return updateProject;
-  }
-
-  public void setUpdateProject( final boolean updateBundle ) {
-    this.updateProject = updateBundle;
-  }
-}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenamePropertyRefactoring.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/core/RenamePropertyRefactoring.java
deleted file mode 100644 (file)
index e05e3a6..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
-// See http://leiffrenzel.de
-// modified for phpeclipse.de project by axelcl
-package net.sourceforge.phpdt.ltk.core;
-
-import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring;
-import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
-
-/** <p>Refactoring for renaming properties in Java Properties files.</p>
-  *
-  * <p>All the actual work is done in the processor, so we just have to
-  * keep a reference to one here.<p>
-  *
-  * @author Leif Frenzel
-  */
-public class RenamePropertyRefactoring extends ProcessorBasedRefactoring {
-
-  private final RefactoringProcessor processor;
-
-  public RenamePropertyRefactoring( final RefactoringProcessor processor ) {
-    super( processor );
-    this.processor = processor;
-  }
-
-
-  // interface methods of ProcessorBasedRefactoring
-  /////////////////////////////////////////////////
-
-  public RefactoringProcessor getProcessor() {
-    return processor;
-  }
-}
index c357bf3..a70f518 100644 (file)
@@ -10,7 +10,6 @@ import org.eclipse.osgi.util.NLS;
  * provides internationalized String messages for the UI.
  * </p>
  *
- * @author Leif Frenzel
  */
 public class UITexts {
 
@@ -30,4 +29,8 @@ public class UITexts {
        public static String renamePropertyInputPage_cbUpdateBundle;
 
        public static String renamePropertyInputPage_cbAllProjects;
+
+       public static String renameLocalVariable_refuseDlg_title;
+
+       public static String renameLocalVariable_refuseDlg_message;
 }
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/actions/RenameLocalVariable.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ltk/ui/actions/RenameLocalVariable.java
new file mode 100644 (file)
index 0000000..9bc7415
--- /dev/null
@@ -0,0 +1,197 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+// modified for phpeclipse.de project by axelcl
+package net.sourceforge.phpdt.ltk.ui.actions;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.core.SourceMethod;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierRefactoring;
+import net.sourceforge.phpdt.ltk.core.RenameLocalVariableDelegate;
+import net.sourceforge.phpdt.ltk.core.RenamePHPProcessor;
+import net.sourceforge.phpdt.ltk.ui.UITexts;
+import net.sourceforge.phpdt.ltk.ui.wizards.RenameLocalVariableWizard;
+import net.sourceforge.phpdt.ui.IWorkingCopyManager;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+public class RenameLocalVariable implements IEditorActionDelegate {
+
+       private ISelection selection;
+
+       private IEditorPart targetEditor;
+
+       private boolean onPHPFile;
+
+       private RenameIdentifierInfo info = new RenameIdentifierInfo();
+
+       // interface methods of IEditorActionDelegate
+       // ///////////////////////////////////////////
+
+       public void setActiveEditor(final IAction action, final IEditorPart targetEditor) {
+               this.targetEditor = targetEditor;
+               onPHPFile = false;
+               IFile file = getFile();
+
+               if (file != null && PHPFileUtil.isPHPFile(file)) {
+                       onPHPFile = true;
+               }
+       }
+
+       public void run(final IAction action) {
+               if (!onPHPFile) {
+                       refuse();
+               } else {
+                       if (selection != null && selection instanceof ITextSelection) {
+                               String word = null;
+                               Point point = null;
+                               if (targetEditor != null && (targetEditor instanceof PHPEditor)) {
+                                       PHPEditor editor = (PHPEditor) targetEditor;
+                                       if (editor != null) {
+                                               ITextSelection textSelection = (ITextSelection) editor.getSelectionProvider().getSelection();
+                                               IDocument doc = editor.getDocumentProvider().getDocument(editor.getEditorInput());
+                                               int pos = textSelection.getOffset();
+                                               point = PHPWordExtractor.findWord(doc, pos);
+                                               if (point != null) {
+                                                       try {
+                                                               word = doc.get(point.x, point.y);
+                                                               IWorkingCopyManager manager = PHPeclipsePlugin.getDefault().getWorkingCopyManager();
+                                                               ICompilationUnit unit = manager.getWorkingCopy(editor.getEditorInput());
+                                                               SourceMethod method = (SourceMethod) findEnclosingElement(point.x, unit, IJavaElement.METHOD);
+                                                               if (word == null || word.charAt(0) != '$' || method == null || !(method instanceof SourceMethod)) {
+                                                                       refuseLocalVariable();
+                                                               }
+                                                               applySelection((ITextSelection) selection, word, point, method);
+
+                                                       } catch (BadLocationException e) {
+                                                       }
+                                               }
+                                       }
+                               }
+                               if (saveAll()) {
+                                       openWizard();
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Returns the enclosing element of a particular element type,
+        * <code>null</code> if no enclosing element of that type exists.
+        */
+       public IJavaElement findEnclosingElement(int start, ICompilationUnit cu, int elementType) {
+               if (cu == null)
+                       return null;
+
+               try {
+                       IJavaElement element = cu.getElementAt(start);
+                       if (element == null) {
+                               element = cu;
+                       }
+
+                       return element.getAncestor(elementType);
+
+               } catch (JavaModelException e) {
+                       return null;
+               }
+       }
+
+       public void selectionChanged(final IAction action, final ISelection selection) {
+               this.selection = selection;
+       }
+
+       // helping methods
+       // ////////////////
+
+       private void applySelection(final ITextSelection textSelection, String word, Point point, SourceMethod method) {
+               if (word != null) {
+                       info.setOldName(word);
+                       info.setNewName(word);
+                       info.setOffset(point.x);
+               } else {
+                       info.setOldName(textSelection.getText());
+                       info.setNewName(textSelection.getText());
+                       info.setOffset(textSelection.getOffset());
+               }
+               info.setMethod(method);
+               info.setSourceFile(getFile());
+       }
+
+       private void refuseLocalVariable() {
+               String title = UITexts.renameLocalVariable_refuseDlg_title;
+               String message = UITexts.renameLocalVariable_refuseDlg_message;
+               MessageDialog.openInformation(getShell(), title, message);
+       }
+       private void refuse() {
+               String title = UITexts.renameProperty_refuseDlg_title;
+               String message = UITexts.renameProperty_refuseDlg_message;
+               MessageDialog.openInformation(getShell(), title, message);
+       }
+
+       private static boolean saveAll() {
+               IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+               return IDE.saveAllEditors(new IResource[] { workspaceRoot }, false);
+       }
+
+       private void openWizard() {
+               RenameLocalVariableDelegate delegate = new RenameLocalVariableDelegate(info);
+               RefactoringProcessor processor = new RenamePHPProcessor(info, delegate);
+               RenameIdentifierRefactoring ref = new RenameIdentifierRefactoring(processor);
+               RenameLocalVariableWizard wizard = new RenameLocalVariableWizard(ref, info);
+               RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard);
+               try {
+                       String titleForFailedChecks = ""; //$NON-NLS-1$
+                       op.run(getShell(), titleForFailedChecks);
+               } catch (final InterruptedException irex) {
+                       // operation was cancelled
+               }
+       }
+
+       private Shell getShell() {
+               Shell result = null;
+               if (targetEditor != null) {
+                       result = targetEditor.getSite().getShell();
+               } else {
+                       result = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+               }
+               return result;
+       }
+
+       private final IFile getFile() {
+               IFile result = null;
+               if (targetEditor instanceof ITextEditor) {
+                       ITextEditor editor = (ITextEditor) targetEditor;
+                       IEditorInput input = editor.getEditorInput();
+                       if (input instanceof IFileEditorInput) {
+                               result = ((IFileEditorInput) input).getFile();
+                       }
+               }
+               return result;
+       }
+}
index 4c58891..c73d1f4 100644 (file)
@@ -4,11 +4,12 @@
 package net.sourceforge.phpdt.ltk.ui.actions;
 
 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
-import net.sourceforge.phpdt.ltk.core.RenamePropertyInfo;
-import net.sourceforge.phpdt.ltk.core.RenamePropertyProcessor;
-import net.sourceforge.phpdt.ltk.core.RenamePropertyRefactoring;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierDelegate;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
+import net.sourceforge.phpdt.ltk.core.RenamePHPProcessor;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierRefactoring;
 import net.sourceforge.phpdt.ltk.ui.UITexts;
-import net.sourceforge.phpdt.ltk.ui.wizards.RenamePropertyWizard;
+import net.sourceforge.phpdt.ltk.ui.wizards.RenameIdentifierWizard;
 import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
 import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor;
 
@@ -43,35 +44,32 @@ import org.eclipse.ui.texteditor.ITextEditor;
  * This action is declared in the <code>plugin.xml</code>.
  * </p>
  *
- * @author Leif Frenzel
  */
 public class RenamePHPIdentifier implements IEditorActionDelegate {
 
-//     private static final String EXT_PROPERTIES = "properties"; //$NON-NLS-1$
-
        private ISelection selection;
 
        private IEditorPart targetEditor;
 
-       private boolean onPropertiesFile;
+       private boolean onPHPFile;
 
-       private RenamePropertyInfo info = new RenamePropertyInfo();
+       private RenameIdentifierInfo info = new RenameIdentifierInfo();
 
        // interface methods of IEditorActionDelegate
        // ///////////////////////////////////////////
 
        public void setActiveEditor(final IAction action, final IEditorPart targetEditor) {
                this.targetEditor = targetEditor;
-               onPropertiesFile = false;
+               onPHPFile = false;
                IFile file = getFile();
 
                if (file != null && PHPFileUtil.isPHPFile(file)) {
-                       onPropertiesFile = true;
+                       onPHPFile = true;
                }
        }
 
        public void run(final IAction action) {
-               if (!onPropertiesFile) {
+               if (!onPHPFile) {
                        refuse();
                } else {
                        if (selection != null && selection instanceof ITextSelection) {
@@ -132,9 +130,10 @@ public class RenamePHPIdentifier implements IEditorActionDelegate {
        }
 
        private void openWizard() {
-               RefactoringProcessor processor = new RenamePropertyProcessor(info);
-               RenamePropertyRefactoring ref = new RenamePropertyRefactoring(processor);
-               RenamePropertyWizard wizard = new RenamePropertyWizard(ref, info);
+               RenameIdentifierDelegate delegate = new RenameIdentifierDelegate( info );
+               RefactoringProcessor processor = new RenamePHPProcessor(info, delegate);
+               RenameIdentifierRefactoring ref = new RenameIdentifierRefactoring(processor);
+               RenameIdentifierWizard wizard = new RenameIdentifierWizard(ref, info);
                RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard);
                try {
                        String titleForFailedChecks = ""; //$NON-NLS-1$
index 60084d0..197714f 100644 (file)
@@ -2,4 +2,7 @@ renameProperty_refuseDlg_title=Rename PHP identifier
 renameProperty_refuseDlg_message=This refactoring is only available on PHP files.
 renamePropertyInputPage_lblNewName=New name\:
 renamePropertyInputPage_cbUpdateBundle=Update all PHP files in the same project
-renamePropertyInputPage_cbAllProjects=Update all PHP projects in the workspace (forces preview)
\ No newline at end of file
+renamePropertyInputPage_cbAllProjects=Update all PHP projects in the workspace (forces preview)
+
+renameLocalVariable_refuseDlg_title=Rename Local PHP variable
+renameLocalVariable_refuseDlg_message=The selected identifier is no local PHP variable.
\ No newline at end of file
@@ -2,7 +2,7 @@
 // See http://leiffrenzel.de
 package net.sourceforge.phpdt.ltk.ui.wizards;
 
-import net.sourceforge.phpdt.ltk.core.RenamePropertyInfo;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
 import net.sourceforge.phpdt.ltk.ui.UITexts;
 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
@@ -30,15 +30,14 @@ import org.eclipse.swt.widgets.Text;
   * whether the operation is supposed to span the entire workspace or only
   * the current project.</p>
   *
-  * @author Leif Frenzel
   */
-public class RenamePropertyInputPage extends UserInputWizardPage {
+public class RenameIdentifierPage extends UserInputWizardPage {
 
-  private static final String DS_KEY = RenamePropertyInputPage.class.getName();
+  private static final String DS_KEY = RenameIdentifierPage.class.getName();
   private static final String DS_UPDATE_BUNDLE = "UPDATE_BUNDLE"; //$NON-NLS-1$
   private static final String DS_ALL_PROJECTS  = "ALL_PROJECTS"; //$NON-NLS-1$
 
-  private final RenamePropertyInfo info;
+  private final RenameIdentifierInfo info;
 
   private IDialogSettings dialogSettings;
   private Text txtNewName;
@@ -46,8 +45,8 @@ public class RenamePropertyInputPage extends UserInputWizardPage {
   private Button cbAllProjects;
 
 
-  public RenamePropertyInputPage( final RenamePropertyInfo info ) {
-    super( RenamePropertyInputPage.class.getName() );
+  public RenameIdentifierPage( final RenameIdentifierInfo info ) {
+    super( RenameIdentifierPage.class.getName() );
     this.info = info;
     initDialogSettings();
   }
@@ -2,29 +2,28 @@
 // See http://leiffrenzel.de
 package net.sourceforge.phpdt.ltk.ui.wizards;
 
-import net.sourceforge.phpdt.ltk.core.RenamePropertyInfo;
-import net.sourceforge.phpdt.ltk.core.RenamePropertyRefactoring;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierRefactoring;
 
 import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
 
 
 
-/** <p>The wizard that is shown to the user for entering the necessary 
+/** <p>The wizard that is shown to the user for entering the necessary
   * information for property renaming.</p>
-  * 
-  * <p>The wizard class is primarily needed for deciding which pages are 
-  * shown to the user. The actual user interface creation goes on the 
+  *
+  * <p>The wizard class is primarily needed for deciding which pages are
+  * shown to the user. The actual user interface creation goes on the
   * pages.</p>
-  * 
-  * @author Leif Frenzel
+  *
   */
-public class RenamePropertyWizard extends RefactoringWizard {
+public class RenameIdentifierWizard extends RefactoringWizard {
 
-  private final RenamePropertyInfo info;
+  private final RenameIdentifierInfo info;
 
 
-  public RenamePropertyWizard( final RenamePropertyRefactoring refactoring,
-                               final RenamePropertyInfo info ) {
+  public RenameIdentifierWizard( final RenameIdentifierRefactoring refactoring,
+                               final RenameIdentifierInfo info ) {
     super( refactoring, DIALOG_BASED_USER_INTERFACE );
     this.info = info;
   }
@@ -35,6 +34,6 @@ public class RenamePropertyWizard extends RefactoringWizard {
 
   protected void addUserInputPages() {
     setDefaultPageTitle( getRefactoring().getName() );
-    addPage( new RenamePropertyInputPage( info ) );
+    addPage( new RenameLocalVariablePage( info ) );
   }
 }
@@ -2,7 +2,7 @@
 // See http://leiffrenzel.de
 package net.sourceforge.phpdt.ltk.ui.wizards;
 
-import net.sourceforge.phpdt.ltk.core.RenamePropertyInfo;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
 import net.sourceforge.phpdt.ltk.ui.UITexts;
 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
@@ -30,24 +30,21 @@ import org.eclipse.swt.widgets.Text;
   * whether the operation is supposed to span the entire workspace or only
   * the current project.</p>
   *
-  * @author Leif Frenzel
   */
-public class RenamePropertyInputPage extends UserInputWizardPage {
+public class RenameLocalVariablePage extends UserInputWizardPage {
 
-  private static final String DS_KEY = RenamePropertyInputPage.class.getName();
+  private static final String DS_KEY = RenameLocalVariablePage.class.getName();
   private static final String DS_UPDATE_BUNDLE = "UPDATE_BUNDLE"; //$NON-NLS-1$
   private static final String DS_ALL_PROJECTS  = "ALL_PROJECTS"; //$NON-NLS-1$
 
-  private final RenamePropertyInfo info;
+  private final RenameIdentifierInfo info;
 
   private IDialogSettings dialogSettings;
   private Text txtNewName;
-  private Button cbUpdateBundle;
-  private Button cbAllProjects;
 
 
-  public RenamePropertyInputPage( final RenamePropertyInfo info ) {
-    super( RenamePropertyInputPage.class.getName() );
+  public RenameLocalVariablePage( final RenameIdentifierInfo info ) {
+    super( RenameLocalVariablePage.class.getName() );
     this.info = info;
     initDialogSettings();
   }
@@ -103,30 +100,11 @@ public class RenamePropertyInputPage extends UserInputWizardPage {
 
   private void createCbUpdateBundle( final Composite composite ) {
     String texts = UITexts.renamePropertyInputPage_cbUpdateBundle;
-    cbUpdateBundle = createCheckbox( composite, texts );
-    cbUpdateBundle.addSelectionListener( new SelectionAdapter() {
-      public void widgetSelected( final SelectionEvent event ) {
-        boolean selected = cbUpdateBundle.getSelection();
-        dialogSettings.put( DS_UPDATE_BUNDLE, selected );
-        info.setUpdateProject( selected );
-      }
-    } );
     initUpdateBundleOption();
   }
 
   private void createCbAllProjects( final Composite composite ) {
     String text = UITexts.renamePropertyInputPage_cbAllProjects;
-    cbAllProjects = createCheckbox( composite, text );
-    cbAllProjects.addSelectionListener( new SelectionAdapter() {
-      public void widgetSelected( final SelectionEvent event ) {
-        boolean selected = cbAllProjects.getSelection();
-        dialogSettings.put( DS_ALL_PROJECTS, selected );
-        info.setAllProjects( selected );
-        // for demonstration purposes, we enforce the preview for refactorings
-        // that span the entire workspace
-        getRefactoringWizard().setForcePreviewReview( selected );
-      }
-    } );
     initAllProjectsOption();
   }
 
@@ -163,14 +141,14 @@ public class RenamePropertyInputPage extends UserInputWizardPage {
   }
 
   private void initUpdateBundleOption() {
-    boolean updateRefs = dialogSettings.getBoolean( DS_UPDATE_BUNDLE );
-    cbUpdateBundle.setSelection( updateRefs );
-    info.setUpdateProject( updateRefs );
+//    boolean updateRefs = dialogSettings.getBoolean( DS_UPDATE_BUNDLE );
+//    cbUpdateBundle.setSelection( updateRefs );
+//    info.setUpdateProject( updateRefs );
   }
 
   private void initAllProjectsOption() {
-    boolean allProjects = dialogSettings.getBoolean( DS_ALL_PROJECTS );
-    cbAllProjects.setSelection( allProjects );
-    info.setAllProjects( allProjects );
+//    boolean allProjects = dialogSettings.getBoolean( DS_ALL_PROJECTS );
+//    cbAllProjects.setSelection( allProjects );
+//    info.setAllProjects( allProjects );
   }
 }
@@ -2,29 +2,28 @@
 // See http://leiffrenzel.de
 package net.sourceforge.phpdt.ltk.ui.wizards;
 
-import net.sourceforge.phpdt.ltk.core.RenamePropertyInfo;
-import net.sourceforge.phpdt.ltk.core.RenamePropertyRefactoring;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierInfo;
+import net.sourceforge.phpdt.ltk.core.RenameIdentifierRefactoring;
 
 import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
 
 
 
-/** <p>The wizard that is shown to the user for entering the necessary 
+/** <p>The wizard that is shown to the user for entering the necessary
   * information for property renaming.</p>
-  * 
-  * <p>The wizard class is primarily needed for deciding which pages are 
-  * shown to the user. The actual user interface creation goes on the 
+  *
+  * <p>The wizard class is primarily needed for deciding which pages are
+  * shown to the user. The actual user interface creation goes on the
   * pages.</p>
-  * 
-  * @author Leif Frenzel
+  *
   */
-public class RenamePropertyWizard extends RefactoringWizard {
+public class RenameLocalVariableWizard extends RefactoringWizard {
 
-  private final RenamePropertyInfo info;
+  private final RenameIdentifierInfo info;
 
 
-  public RenamePropertyWizard( final RenamePropertyRefactoring refactoring,
-                               final RenamePropertyInfo info ) {
+  public RenameLocalVariableWizard( final RenameIdentifierRefactoring refactoring,
+                               final RenameIdentifierInfo info ) {
     super( refactoring, DIALOG_BASED_USER_INTERFACE );
     this.info = info;
   }
@@ -35,6 +34,6 @@ public class RenamePropertyWizard extends RefactoringWizard {
 
   protected void addUserInputPages() {
     setDefaultPageTitle( getRefactoring().getName() );
-    addPage( new RenamePropertyInputPage( info ) );
+    addPage( new RenameLocalVariablePage( info ) );
   }
 }