/******************************************************************************* * Copyright (c) 2006, 2015 Zend Technologies and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Zend Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.php.refactoring.core.rename; import java.text.MessageFormat; import java.util.*; import java.util.Map.Entry; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.IScriptProject; import org.eclipse.dltk.core.IType; import org.eclipse.dltk.core.ModelException; import org.eclipse.dltk.core.search.*; 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.ParticipantManager; import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; import org.eclipse.ltk.core.refactoring.participants.RenameArguments; import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; import org.eclipse.ltk.internal.core.refactoring.resource.ResourceProcessors; import org.eclipse.php.core.ast.nodes.*; import org.eclipse.php.core.compiler.PHPFlags; import org.eclipse.php.internal.core.PHPLanguageToolkit; import org.eclipse.php.internal.core.ast.locator.PHPElementConciliator; import org.eclipse.php.refactoring.core.PhpRefactoringCoreMessages; import org.eclipse.php.refactoring.core.rename.logic.RenameTrait; import org.eclipse.php.refactoring.core.utils.RefactoringUtility; /** * Description: * * @author Roy, 2007 */ public class RenameTraitProcessor extends AbstractRenameProcessor<IFile> implements ITextUpdating { public static final String RENAME_IS_PROCESSING = PhpRefactoringCoreMessages .getString("RenameClassNameProcessor.0"); //$NON-NLS-1$ public static final String CREATING_MODIFICATIONS_LABEL = PhpRefactoringCoreMessages .getString("RenameClassNameProcessor.1"); //$NON-NLS-1$ private static final String CLASS_IS_USED = PhpRefactoringCoreMessages .getString("RenameClassNameProcessor.2"); //$NON-NLS-1$ private static final String ID_RENAME_CLASS = "php.refactoring.ui.rename.className"; //$NON-NLS-1$ protected static final String ATTRIBUTE_TEXTUAL_MATCHES = "textual"; //$NON-NLS-1$ public static final String RENAME_CLASS_PROCESSOR_NAME = PhpRefactoringCoreMessages .getString("RenameTraitNameProcessor.3"); //$NON-NLS-1$ /** * The original identifier node we want to rename */ private final ASTNode identifier; /** * holds whether or not we want to change also the inlined text */ private boolean isUpdateTextualMatches; private IType[] types; public RenameTraitProcessor(IFile operatedFile, ASTNode locateNode) { super(operatedFile); //$NON-NLS-1$ this.identifier = locateNode; IModelElement[] elements = null; try { elements = identifier.getProgramRoot().getSourceModule() .codeSelect(getOffset(), 0); } catch (ModelException e) { elements = new IModelElement[0]; } types = getTypes(elements); } private IType[] getTypes(IModelElement[] elements) { if (elements == null) { return new IType[0]; } List<IType> types = new ArrayList<IType>(); for (int i = 0; i < elements.length; i++) { try { if ((elements[i] instanceof IType) || PHPFlags.isTrait(((IType) elements[i]).getFlags())) { types.add((IType) elements[i]); } } catch (ModelException e) { } } return types.toArray(new IType[types.size()]); } /** * Derive the change */ public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { CompositeChange rootChange = new CompositeChange( PhpRefactoringCoreMessages .getString("RenameClassNameProcessor.4")); //$NON-NLS-1$ rootChange.markAsSynthetic(); try { pm.beginTask(RenameTraitProcessor.RENAME_IS_PROCESSING, participantFiles.size()); pm.setTaskName(RenameTraitProcessor.CREATING_MODIFICATIONS_LABEL); if (pm.isCanceled()) throw new OperationCanceledException(); // get target parameters final String newElementName = getNewElementName(); // go over the files and check for global variable usage for (Entry<IFile, Program> entry : participantFiles.entrySet()) { final IFile file = entry.getKey(); final Program program = entry.getValue(); final RenameTrait rename = new RenameTrait(file, identifier, getCurrentElementName(), newElementName, getUpdateTextualMatches(), types); // aggregate the changes identifiers program.accept(rename); if (pm.isCanceled()) throw new OperationCanceledException(); pm.worked(1); if (rename.hasChanges()) { TextFileChange change = acquireChange(file, program); rename.updateChange(change); rootChange.add(change); } } return rootChange; } finally { pm.done(); } } public Object[] getElements() { return new Object[] { identifier }; } public String getIdentifier() { return ID_RENAME_CLASS; } public String getProcessorName() { return RENAME_CLASS_PROCESSOR_NAME; } public Object getNewElement() { return getNewElementName(); } private int getOffset() { if (identifier instanceof Identifier) { return ((Identifier) identifier).getStart(); } if (identifier instanceof ClassDeclaration) { return ((ClassDeclaration) identifier).getName().getStart(); } if (identifier instanceof InterfaceDeclaration) { return ((InterfaceDeclaration) identifier).getName().getStart(); } return identifier.getStart(); } public String getCurrentElementName() { if (identifier instanceof Identifier) { return ((Identifier) identifier).getName(); } if (identifier instanceof ClassDeclaration) { return ((ClassDeclaration) identifier).getName().getName(); } if (identifier instanceof InterfaceDeclaration) { return ((InterfaceDeclaration) identifier).getName().getName(); } return identifier.toString(); } @Override protected void collectReferences(Program program, IProgressMonitor pm) { final HashSet<IResource> list = new HashSet<IResource>(); IScriptProject project = this.identifier.getProgramRoot() .getSourceModule().getScriptProject(); IDLTKSearchScope scope = SearchEngine.createSearchScope(project, getSearchFlags(false)); SearchPattern pattern = null; int matchMode = SearchPattern.R_EXACT_MATCH | SearchPattern.R_ERASURE_MATCH; SearchEngine engine = new SearchEngine(); pattern = SearchPattern.createPattern(getCurrentElementName(), IDLTKSearchConstants.TYPE, IDLTKSearchConstants.ALL_OCCURRENCES, matchMode, PHPLanguageToolkit.getDefault()); try { engine.search(pattern, new SearchParticipant[] { SearchEngine .getDefaultSearchParticipant() }, scope, new SearchRequestor() { @Override public void acceptSearchMatch(SearchMatch match) throws CoreException { IModelElement element = (IModelElement) match .getElement(); list.add(element.getResource()); } }, new NullProgressMonitor()); } catch (CoreException e) { } for (Iterator<IResource> it = list.iterator(); it.hasNext();) { IResource file = it.next(); if (file instanceof IFile) { try { participantFiles.put((IFile) file, RefactoringUtility.getProgramForFile((IFile) file)); } catch (Exception e) { } } } } public boolean canEnableTextUpdating() { return true; } public String getCurrentElementQualifier() { return getCurrentElementName(); } public boolean getUpdateTextualMatches() { return isUpdateTextualMatches; } public void setUpdateTextualMatches(boolean update) { isUpdateTextualMatches = update; } public RefactoringStatus getRefactoringStatus(IFile key, Program program) { if (PHPElementConciliator.classNameAlreadyExists(program, getNewElementName())) { final String message = MessageFormat.format( RenameTraitProcessor.CLASS_IS_USED, new Object[] { key.getName() }); return RefactoringStatus.createWarningStatus(message); } return null; } @Override public RefactoringParticipant[] loadParticipants(RefactoringStatus status, SharableParticipants sharedParticipants) throws CoreException { String[] affectedNatures = ResourceProcessors .computeAffectedNatures(resource); RenameArguments fRenameArguments = new RenameArguments( getNewElementName(), false); LinkedList<RefactoringParticipant> participants = new LinkedList<RefactoringParticipant>( Arrays.asList(ParticipantManager.loadRenameParticipants(status, this, identifier, fRenameArguments, null, affectedNatures, sharedParticipants))); for (IType type : types) { participants.addAll(Arrays.asList(ParticipantManager .loadRenameParticipants(status, this, type, fRenameArguments, null, affectedNatures, sharedParticipants))); } return participants.toArray(new RefactoringParticipant[participants .size()]); } }