/******************************************************************************* * Copyright (c) 2014, 2015 Google, Inc 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: * Sergey Prigogin (Google) - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceProxyVisitor; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; import org.eclipse.ltk.core.refactoring.participants.ISharableParticipant; import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; import org.eclipse.ltk.core.refactoring.participants.RenameArguments; import org.eclipse.ltk.core.refactoring.participants.RenameParticipant; /** * Updates include statements and include guards in response to a file or a folder rename. */ public class HeaderFileRenameParticipant extends RenameParticipant implements ISharableParticipant { private Map<IResource, RenameArguments> renamedResources; private Change change; public HeaderFileRenameParticipant() { } @Override protected boolean initialize(Object element) { addElement(element, getArguments()); return renamedResources != null; } @Override public void addElement(Object element, RefactoringArguments arguments) { if (element instanceof IResource && arguments instanceof RenameArguments) { if (renamedResources == null) renamedResources = new HashMap<>(); renamedResources.put((IResource) element, (RenameArguments) arguments); } } @Override public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) throws OperationCanceledException { try { if (renamedResources == null) return RefactoringStatus.create(Status.OK_STATUS); // Maps the affected files to new, not yet existing, files. final Map<IFile, IFile> movedFiles = new HashMap<>(); final Map<IContainer, IContainer> renamedContainers = new HashMap<>(); for (Map.Entry<IResource, RenameArguments> entry : renamedResources.entrySet()) { IResource renamedResource = entry.getKey(); RenameArguments args = entry.getValue(); if (!args.getUpdateReferences()) continue; if (renamedResource.isLinked()) continue; String newName = args.getNewName(); if (renamedResource instanceof IContainer) { IContainer container = (IContainer) renamedResource; final IPath oldPath = container.getFullPath(); final IPath newPath = oldPath.removeLastSegments(1).append(newName); final IWorkspaceRoot workspaceRoot = container.getWorkspace().getRoot(); IContainer newContainer = container.getType() == IResource.FOLDER ? workspaceRoot.getFolder(newPath) : workspaceRoot.getProject(newName); renamedContainers.put(container, newContainer); container.accept(new IResourceProxyVisitor() { @Override public boolean visit(IResourceProxy proxy) throws CoreException { if (proxy.isLinked()) return false; if (proxy.getType() == IResource.FILE) { IFile file = (IFile) proxy.requestResource(); IPath path = replacePrefix(file.getFullPath(), oldPath.segmentCount(), newPath); movedFiles.put(file, workspaceRoot.getFile(path)); return false; } return true; } }, IResource.NONE); } else if (renamedResource instanceof IFile) { IFile file = (IFile) renamedResource; movedFiles.put(file, file.getParent().getFile(new Path(newName))); } } HeaderFileReferenceAdjuster includeAdjuster = new HeaderFileReferenceAdjuster(movedFiles, renamedContainers, getProcessor()); change = includeAdjuster.createChange(context, pm); } catch (CoreException e) { return RefactoringStatus.create(e.getStatus()); } finally { pm.done(); } return RefactoringStatus.create(Status.OK_STATUS); } @Override public Change createPreChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { change = RenameParticipantHelper.postprocessParticipantChange(change, this); pm.done(); return change; } @Override public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { pm.done(); return null; } @Override public String getName() { return RenameMessages.HeaderFileRenameParticipant_name; } /** * Replaces first few segments of the given path with the contents of another path. * * @param path the original path * @param prefixLength the number of segments of {@code path} to replace * @param newPrefix the replacement path * @return the modified path */ private static IPath replacePrefix(IPath path, int prefixLength, IPath newPrefix) { return newPrefix.append(path.removeFirstSegments(prefixLength)); } }