// 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; /** *

* delegate object that contains the logic used by the processor. *

* */ 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; } }