package com.dubture.symfony.core.refactoring; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.dltk.core.IType; import org.eclipse.dltk.core.ModelException; 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.TextChange; import org.eclipse.ltk.core.refactoring.TextFileChange; import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; import org.eclipse.ltk.core.refactoring.participants.RenameParticipant; import org.eclipse.php.internal.core.typeinference.PHPModelUtils; import org.eclipse.search.core.text.TextSearchEngine; import org.eclipse.search.core.text.TextSearchMatchAccess; import org.eclipse.search.core.text.TextSearchRequestor; import org.eclipse.search.core.text.TextSearchScope; import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.ReplaceEdit; import org.eclipse.text.edits.TextEditGroup; import com.dubture.symfony.core.log.Logger; import com.dubture.symfony.core.model.Bundle; import com.dubture.symfony.core.model.SymfonyModelAccess; import com.dubture.symfony.index.SymfonyIndexer; import com.dubture.symfony.index.handler.IServiceHandler; public class RenameServiceClass extends RenameParticipant { private IType type; public RenameServiceClass() { } @Override protected boolean initialize(Object element) { if (element instanceof IType) { type = (IType) element; return true; } return false; } @Override public String getName() { return "Rename Service Class"; } @Override public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) throws OperationCanceledException { return new RefactoringStatus(); } @Override public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { if (type.getScriptProject() == null) { return null; } try { final List<IResource> resources = new ArrayList<IResource>(); SymfonyIndexer.getInstance().findServicesByClassName(PHPModelUtils.getFullName(type), type.getScriptProject().getProject().getFullPath().toString(), new IServiceHandler() { @Override public void handle(String id, String phpClass, String path, String _public, String tags) { try { IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path)); if (file.exists()) { resources.add(file); } } catch (Exception e) { // ignore if not exists } } }); if (resources.isEmpty()) { return null; } resources.add(type.getScriptProject().getProject().getFolder("app/config")); // search by default List<Bundle> findBundles = SymfonyModelAccess.getDefault().findBundles(type.getScriptProject()); for (Bundle bundle : findBundles) { resources.add(ResourcesPlugin.getWorkspace().getRoot().getFolder(bundle.getPath().append("Resources").append("config"))); } TextSearchScope searchScope = TextSearchScope.newSearchScope(resources.toArray(new IResource[resources.size()]), Pattern.compile(".*"), true); Pattern search = TextSearchEngine.createPattern(PHPModelUtils.getFullName(type), false, false); final String newName = createNewName(); final HashMap<IFile, Change> changes= new HashMap<IFile, Change>(); TextSearchRequestor collector= new TextSearchRequestor() { public boolean acceptPatternMatch(TextSearchMatchAccess matchAccess) throws CoreException { IFile file= matchAccess.getFile(); if (matchAccess.getMatchOffset() == 0) { return true; } char fileContentChar = matchAccess.getFileContentChar(matchAccess.getMatchOffset()-1); if (!(Character.isWhitespace(fileContentChar) || fileContentChar == '\'' || fileContentChar == '"' || fileContentChar == ':' || fileContentChar == '>')) { return false; } int end = matchAccess.getMatchOffset()+matchAccess.getMatchLength(); if (end < matchAccess.getFileContentLength()) { fileContentChar = matchAccess.getFileContentChar(end); if (!(Character.isWhitespace(fileContentChar) || fileContentChar == '\'' || fileContentChar == '"' || fileContentChar == '<')) { return false; } } TextFileChange change= (TextFileChange) changes.get(file); if (change == null) { TextChange textChange= getTextChange(file); // an other participant already modified that file? if (textChange != null) { return false; // don't try to merge changes } change= new TextFileChange(file.getName(), file); change.setEdit(new MultiTextEdit()); changes.put(file, change); } ReplaceEdit edit= new ReplaceEdit(matchAccess.getMatchOffset(), matchAccess.getMatchLength(), newName); change.addEdit(edit); change.addTextEditGroup(new TextEditGroup("Update service reference", edit)); //$NON-NLS-1$ return true; } }; TextSearchEngine.create().search(searchScope, collector, search, null); if (changes.isEmpty()) { return null; } CompositeChange result= new CompositeChange("Rename service class"); result.addAll(changes.values().toArray(new Change[changes.size()])); return result; } catch (Exception e) { Logger.logException(e); } return null; } private String createNewName() throws ModelException { StringBuilder newName = new StringBuilder(); if (type.getParent() instanceof IType) { newName.append(type.getParent().getElementName()); newName.append("\\"); } newName.append(getArguments().getNewName()); return newName.toString(); } }