diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICContainer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICContainer.java index 3e9cce723fd..e47f565c30c 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICContainer.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICContainer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 QNX Software Systems and others. + * Copyright (c) 2000, 2015 QNX Software Systems 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 @@ -7,11 +7,14 @@ * * Contributors: * QNX Software Systems - Initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.core.model; +import org.eclipse.core.resources.IContainer; + /** - * A C Folder Resource. + * A C folder resource. * * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. @@ -22,12 +25,12 @@ public interface ICContainer extends ICElement, IParent, IOpenable { * It does not transitively answer non-C resources contained in folders; * these would have to be explicitly iterated over. *

- * Non-C resources includes files, folders, projects not accounted for. + * Non-C resources includes files, folders, projects not accounted for. *

* * @return an array of non-C resources directly contained in this project * @exception CModelException if this element does not exist or if an - * exception occurs while accessing its corresponding resource + * exception occurs while accessing its corresponding resource */ Object[] getNonCResources() throws CModelException; @@ -41,11 +44,9 @@ public interface ICContainer extends ICElement, IParent, IOpenable { ITranslationUnit[] getTranslationUnits() throws CModelException; /** - * Returns the translation unit with the specified name - * in this container (for example, "foobar.c"). - * The name has to be a valid translation unit name. - * This is a handle-only operation. The celement - * may or may not exist. + * Returns the translation unit with the specified name in this container + * (for example, {@code "foobar.c"}). The name has to be a valid translation unit name. + * This is a handle-only operation. The celement may or may not exist. * * @param name the given name * @return the translation unit with the specified name in this container @@ -54,46 +55,43 @@ public interface ICContainer extends ICElement, IParent, IOpenable { /** * Returns the all the binaries of this container. - * - * @throws CModelException */ IBinary[] getBinaries() throws CModelException; /** - * Return the binary for this name, it must be a - * valid binary + * Returns the binary for this name, it must be a valid binary. * This is a handle-only operation. The container may or may not exist. */ IBinary getBinary(String name); /** - * Returns all the archive of this container - * - * @throws CModelException + * Returns all the archives of this container. */ IArchive[] getArchives() throws CModelException; /** - * This is a handle-only operation. The container - * may or may not exist. + * This is a handle-only operation. The container may or may not exist. */ IArchive getArchive(String name); /** - * Return al the child containers of this container. - * - * @throws CModelException + * Returns all the child containers of this container. */ ICContainer[] getCContainers() throws CModelException; /** - * Returns the container with the given name. - * An empty string indicates the default package. - * This is a handle-only operation. The celement - * may or may not exist. + * Returns the container with the given name. An empty string indicates the default package. + * This is a handle-only operation. The celement may or may not exist. * - * @param name the given container + * @param name the name of a nested container * @return the container with the given name */ ICContainer getCContainer(String name); + + /** + * Returns the corresponding IContainer. + * @since 5.9 + */ + @Override + IContainer getResource(); } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CContainer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CContainer.java index ce08de1f29c..2f93d3f5dd4 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CContainer.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CContainer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 QNX Software Systems and others. + * Copyright (c) 2000, 2015 QNX Software Systems 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 @@ -282,4 +282,9 @@ public class CContainer extends Openable implements ICContainer { protected char getHandleMementoDelimiter() { return CElement.CEM_SOURCEFOLDER; } + + @Override + public IContainer getResource() { + return (IContainer) super.getResource(); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java index 0e0cbcbf9cd..d310172480e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2001, 2011 IBM Corporation and others. + * Copyright (c) 2001, 2015 IBM Corporation 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 @@ -677,11 +677,8 @@ public class StubUtility { return null; IPath path = file.getFullPath(); ISourceRoot root = cproject.findSourceRoot(file); - if (root != null) { - path = PathUtil.makeRelativePath(path, root.getPath()); - } else { - path = PathUtil.makeRelativePath(path, cproject.getPath()); - } + IPath basePath = root == null ? cproject.getPath() : root.getPath(); + path = PathUtil.makeRelativePath(path, basePath); return generateIncludeGuardSymbolFromFilePath(path.toString()); default: @@ -697,7 +694,7 @@ public class StubUtility { } } - private static String generateIncludeGuardSymbolFromFilePath(String filename) { + public static String generateIncludeGuardSymbolFromFilePath(String filename) { // Convert to upper case and replace invalid characters with underscores, // e.g. convert some/directory/foo-bar.h to SOME_DIRECTORY_FOO_BAR_H_ StringBuilder buf = new StringBuilder(filename.length() + 1); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileMoveParticipant.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileMoveParticipant.java index d15a526ad86..9d9cbbb5b48 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileMoveParticipant.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileMoveParticipant.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Google, Inc and others. + * 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 @@ -105,7 +105,7 @@ public class HeaderFileMoveParticipant extends MoveParticipant implements IShara } HeaderFileReferenceAdjuster includeAdjuster = - new HeaderFileReferenceAdjuster(movedFiles, getProcessor()); + new HeaderFileReferenceAdjuster(movedFiles, null, getProcessor()); change = includeAdjuster.createChange(context, pm); } catch (CoreException e) { return RefactoringStatus.create(e.getStatus()); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileReferenceAdjuster.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileReferenceAdjuster.java index eea99a70aba..739b8303645 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileReferenceAdjuster.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileReferenceAdjuster.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Google, Inc and others. + * 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 @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; +import java.io.File; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; @@ -22,6 +23,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -31,6 +33,7 @@ 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.Platform; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.preferences.IPreferencesService; @@ -62,12 +65,14 @@ import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.index.IndexLocationFactory; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ISourceRoot; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.IWorkingCopyManager; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.ui.refactoring.CTextFileChange; +import org.eclipse.cdt.utils.PathUtil; import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.ASTCommenter; import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap; @@ -93,20 +98,25 @@ public class HeaderFileReferenceAdjuster { private final Map movedFiles; private final Map movedFilesByLocation; + private final Map renamedContainers; private ASTManager astManager; private IIndex index; private int indexLockCount; /** * @param movedFiles keys are moved files, values are new, not yet existing, files + * @param renamedContainers keys are folders and projects being renamed, values are new, + * not yet existing folders and projects. May be {@code null}. * @param processor the refactoring processor */ - public HeaderFileReferenceAdjuster(Map movedFiles, RefactoringProcessor processor) { + public HeaderFileReferenceAdjuster(Map movedFiles, + Map renamedContainers, RefactoringProcessor processor) { this.movedFiles = movedFiles; this.movedFilesByLocation = new HashMap<>(); for (Entry entry : movedFiles.entrySet()) { this.movedFilesByLocation.put(entry.getKey().getLocation().toOSString(), entry.getValue().getLocation()); } + this.renamedContainers = renamedContainers; this.astManager = getASTManager(processor); } @@ -237,6 +247,10 @@ public class HeaderFileReferenceAdjuster { location = include.getPath(); if (location.isEmpty()) continue; // Unresolved include. + if (File.separatorChar == '\\') { + // Normalize path separators on Windows. + location = new Path(location).toString(); + } } else { String name = new String(include.getName().getSimpleID()); IncludeInfo includeInfo = new IncludeInfo(name, include.isSystemInclude()); @@ -429,12 +443,8 @@ public class HeaderFileReferenceAdjuster { return null; if (!oldGuard.equals(StubUtility.generateIncludeGuardSymbol(resource, tu.getCProject()))) return null; - IProject newProject = newFile.getProject(); - ICProject newCProject = CoreModel.getDefault().create(newProject); - if (newCProject == null) - return null; - String guard = StubUtility.generateIncludeGuardSymbol(newFile, newCProject); - if (guard.equals(oldGuard)) + String guard = generateNewIncludeGuardSymbol(resource, newFile, tu.getCProject()); + if (guard == null || guard.equals(oldGuard)) return null; MultiTextEdit rootEdit = new MultiTextEdit(); for (IRegion region : includeGuardPositions) { @@ -443,6 +453,28 @@ public class HeaderFileReferenceAdjuster { return rootEdit; } + private String generateNewIncludeGuardSymbol(IResource resource, IFile newFile, ICProject cProject) { + switch (getIncludeGuardScheme(cProject.getProject())) { + case PreferenceConstants.CODE_TEMPLATES_INCLUDE_GUARD_SCHEME_FILE_PATH: + ISourceRoot root = cProject.findSourceRoot(resource); + IContainer base = root == null ? cProject.getProject() : root.getResource(); + IContainer renamedBase = renamedContainers.get(base); + if (renamedBase != null) + base = renamedBase; + IPath path = PathUtil.makeRelativePath(newFile.getFullPath(), base.getFullPath()); + if (path == null) + break; + return StubUtility.generateIncludeGuardSymbolFromFilePath(path.toString()); + + case PreferenceConstants.CODE_TEMPLATES_INCLUDE_GUARD_SCHEME_FILE_NAME: + return StubUtility.generateIncludeGuardSymbolFromFilePath(newFile.getName()); + + default: + break; + } + return null; + } + private void flushEditBuffer(int offset, StringBuilder text, Deque deletes, MultiTextEdit edit) { consumeDeletesUpTo(offset, deletes, edit); if (text.length() != 0) { @@ -512,12 +544,7 @@ public class HeaderFileReferenceAdjuster { String filename = oldfile.getLocation().lastSegment(); if (!CoreModel.isValidHeaderUnitName(project, filename)) return false; - IPreferencesService preferences = Platform.getPreferencesService(); - IScopeContext[] scopes = PreferenceConstants.getPreferenceScopes(project); - int scheme = preferences.getInt(CUIPlugin.PLUGIN_ID, - PreferenceConstants.CODE_TEMPLATES_INCLUDE_GUARD_SCHEME, - PreferenceConstants.CODE_TEMPLATES_INCLUDE_GUARD_SCHEME_FILE_NAME, scopes); - switch (scheme) { + switch (getIncludeGuardScheme(project)) { case PreferenceConstants.CODE_TEMPLATES_INCLUDE_GUARD_SCHEME_FILE_PATH: return true; @@ -528,4 +555,13 @@ public class HeaderFileReferenceAdjuster { return false; } } + + private static int getIncludeGuardScheme(IProject project) { + IPreferencesService preferences = Platform.getPreferencesService(); + IScopeContext[] scopes = PreferenceConstants.getPreferenceScopes(project); + int scheme = preferences.getInt(CUIPlugin.PLUGIN_ID, + PreferenceConstants.CODE_TEMPLATES_INCLUDE_GUARD_SCHEME, + PreferenceConstants.CODE_TEMPLATES_INCLUDE_GUARD_SCHEME_FILE_NAME, scopes); + return scheme; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileRenameParticipant.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileRenameParticipant.java index b8e2db6e4b1..5ed9794205a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileRenameParticipant.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/HeaderFileRenameParticipant.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Google, Inc and others. + * 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 @@ -67,6 +67,7 @@ public class HeaderFileRenameParticipant extends RenameParticipant implements IS // Maps the affected files to new, not yet existing, files. final Map movedFiles = new HashMap<>(); + final Map renamedContainers = new HashMap<>(); for (Map.Entry entry : renamedResources.entrySet()) { IResource renamedResource = entry.getKey(); @@ -78,10 +79,14 @@ public class HeaderFileRenameParticipant extends RenameParticipant implements IS String newName = args.getNewName(); if (renamedResource instanceof IContainer) { - final IPath oldPath = renamedResource.getFullPath(); + IContainer container = (IContainer) renamedResource; + final IPath oldPath = container.getFullPath(); final IPath newPath = oldPath.removeLastSegments(1).append(newName); - final IWorkspaceRoot workspaceRoot = renamedResource.getWorkspace().getRoot(); - ((IContainer) renamedResource).accept(new IResourceProxyVisitor() { + 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()) @@ -101,7 +106,7 @@ public class HeaderFileRenameParticipant extends RenameParticipant implements IS } } HeaderFileReferenceAdjuster includeAdjuster = - new HeaderFileReferenceAdjuster(movedFiles, getProcessor()); + new HeaderFileReferenceAdjuster(movedFiles, renamedContainers, getProcessor()); change = includeAdjuster.createChange(context, pm); } catch (CoreException e) { return RefactoringStatus.create(e.getStatus());