1 // Copyright (c) 2005 by Leif Frenzel. All rights reserved.
2 // See http://leiffrenzel.de
3 // modified for phpeclipse.de project by axelcl
4 package net.sourceforge.phpdt.ltk.core;
6 import java.io.ByteArrayOutputStream;
7 import java.io.InputStream;
8 import java.util.ArrayList;
9 import java.util.Iterator;
10 import java.util.List;
12 import net.sourceforge.phpdt.core.ISourceRange;
13 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
14 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
15 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
16 import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
17 import net.sourceforge.phpdt.internal.core.SourceMethod;
18 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
20 import org.eclipse.core.resources.IContainer;
21 import org.eclipse.core.resources.IFile;
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.core.runtime.CoreException;
24 import org.eclipse.core.runtime.IProgressMonitor;
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.core.runtime.Status;
27 import org.eclipse.ltk.core.refactoring.Change;
28 import org.eclipse.ltk.core.refactoring.CompositeChange;
29 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
30 import org.eclipse.ltk.core.refactoring.TextFileChange;
31 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
32 import org.eclipse.ltk.core.refactoring.participants.IConditionChecker;
33 import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker;
34 import org.eclipse.text.edits.MultiTextEdit;
35 import org.eclipse.text.edits.ReplaceEdit;
39 * delegate object that contains the logic used by the processor.
43 public class RenameLocalVariableDelegate extends RenameIdentifierDelegate {
45 public RenameLocalVariableDelegate(final RenameIdentifierInfo info) {
49 RefactoringStatus checkInitialConditions() {
50 RefactoringStatus result = new RefactoringStatus();
51 IFile sourceFile = info.getSourceFile();
52 if (sourceFile == null || !sourceFile.exists()) {
53 result.addFatalError(CoreTexts.renamePropertyDelegate_noSourceFile);
54 } else if (info.getSourceFile().isReadOnly()) {
55 result.addFatalError(CoreTexts.renamePropertyDelegate_roFile);
56 } else if (isEmpty(info.getOldName())) {
57 // || !isPropertyKey( info.getSourceFile(), info.getOldName() ) ) {
58 result.addFatalError(CoreTexts.renamePropertyDelegate_noPHPKey);
63 RefactoringStatus checkFinalConditions(final IProgressMonitor pm, final CheckConditionsContext ctxt) {
64 RefactoringStatus result = new RefactoringStatus();
65 pm.beginTask(CoreTexts.renamePropertyDelegate_checking, 100);
66 // do something long-running here: traverse the entire project (or even
67 // workspace) to look for all *.p files with the same bundle
69 IFile file = info.getSourceFile();
70 IProject project = file.getProject();
72 SourceMethod method = info.getMethod();
73 ISourceRange range = method.getSourceRange();
74 if (project.isNatureEnabled(PHPeclipsePlugin.PHP_NATURE_ID)) {
75 determineMethodOffsets(file, range.getOffset(), range.getLength(), result);
77 } catch (CoreException e) {
78 String msg = "Project: " + project.getLocation().toOSString() + " CoreException " + e.getMessage();
80 } catch (Exception e) {
81 String msg = "Project: " + project.getLocation().toOSString() + " Exception " + e.getMessage();
88 IFile[] files = new IFile[phpFiles.size()];
89 phpFiles.keySet().toArray(files);
90 IConditionChecker checker = ctxt.getChecker(ValidateEditChecker.class);
91 ValidateEditChecker editChecker = (ValidateEditChecker) checker;
92 editChecker.addFiles(files);
98 protected void createChange(final IProgressMonitor pm, final CompositeChange rootChange) {
100 pm.beginTask(CoreTexts.renamePropertyDelegate_collectingChanges, 100);
101 // all files in the same bundle
102 rootChange.addAll(createChangesForContainer(pm));
108 // finds the offsets of the identifier to rename
109 // usually, this would be the job of a proper parser;
110 // using a primitive brute-force approach here
111 private void determineMethodOffsets(final IFile file, int offset, int length, final RefactoringStatus status) {
112 ArrayList matches = new ArrayList();
114 String content = readFileContent(file, status);
115 String methodString = content.substring(offset, offset + length);
116 Scanner scanner = new Scanner(true, false);
117 scanner.setSource(methodString.toCharArray());
118 scanner.setPHPMode(true);
119 char[] word = info.getOldName().toCharArray();
121 int fToken = ITerminalSymbols.TokenNameEOF;
123 fToken = scanner.getNextToken();
124 while (fToken != ITerminalSymbols.TokenNameEOF) {
125 if (fToken == ITerminalSymbols.TokenNameVariable) {
126 if (scanner.equalsCurrentTokenSource(word)) {
127 matches.add(Integer.valueOf(scanner.getCurrentTokenStartPosition() + offset));
130 fToken = scanner.getNextToken();
133 } catch (InvalidInputException e) {
134 String msg = "File: " + file.getLocation().toOSString() + " InvalidInputException " + e.getMessage();
135 status.addError(msg);
136 } catch (SyntaxError e) {
137 String msg = "File: " + file.getLocation().toOSString() + " SyntaxError " + e.getMessage();
138 status.addError(msg);
141 } catch (Exception e) {
142 String msg = "File: " + file.getLocation().toOSString() + " Exception " + e.getMessage();
143 status.addError(msg);
145 if (matches.size() > 0) {
146 phpFiles.put(file, matches);
150 private String readFileContent(final IFile file, final RefactoringStatus refStatus) {
151 String result = null;
153 InputStream is = file.getContents();
154 byte[] buf = new byte[1024];
155 ByteArrayOutputStream bos = new ByteArrayOutputStream();
156 int len = is.read(buf);
158 bos.write(buf, 0, len);
162 result = new String(bos.toByteArray());
163 } catch (Exception ex) {
164 String msg = ex.toString();
165 refStatus.addFatalError(msg);
166 String pluginId = PHPeclipsePlugin.getPluginId();
167 IStatus status = new Status(IStatus.ERROR, pluginId, 0, msg, ex);
168 PHPeclipsePlugin.getDefault().getLog().log(status);