diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/CProjectHelper.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/CProjectHelper.java index 1885fbaccd0..27068a1a379 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/CProjectHelper.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/CProjectHelper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2010 IBM Corporation and others. + * Copyright (c) 2005, 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 @@ -10,12 +10,16 @@ * Andrew Ferguson (Symbian) * Markus Schorn (Wind River Systems) * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.core.testplugin; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; import java.util.zip.ZipFile; import org.eclipse.cdt.core.CCProjectNature; @@ -30,6 +34,7 @@ import org.eclipse.cdt.core.model.IBinaryContainer; import org.eclipse.cdt.core.model.ICContainer; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IPathEntry; import org.eclipse.cdt.core.model.ISourceRoot; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference; @@ -38,6 +43,7 @@ import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager; import org.eclipse.cdt.core.settings.model.TestCfgDataProvider; import org.eclipse.cdt.core.settings.model.util.CDataUtil; +import org.eclipse.cdt.internal.core.model.InternalCoreModelUtil; import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -115,7 +121,7 @@ public class CProjectHelper { } /** - * Add the default binary parser if no binary parser configured. + * Adds the default binary parser if no binary parser configured. * * @param project * @throws CoreException @@ -293,6 +299,45 @@ public class CProjectHelper { folder.delete(true, null); } + /** + * Adds a source root to a C/C++ project. + * + * @param cproject the project to add the source root to + * @param rootName the relative path of the source root + */ + public static void addSourceRoot(ICProject cproject, String rootName) throws CoreException { + IProject project = cproject.getProject(); + IFolder rootFolder = project.getFolder(rootName); + if (!rootFolder.exists()) { + rootFolder.create(false, true, null); + } + IPath rootPath = rootFolder.getFullPath(); + + if (!CCorePlugin.getDefault().isNewStyleProject(project)) { + InternalCoreModelUtil.addSourceEntry(project, rootFolder, false, null); + } else { + IPathEntry[] entries = cproject.getRawPathEntries(); + ArrayList newEntries= new ArrayList<>(entries.length + 1); + + for (IPathEntry entry : entries) { + if (entry.getEntryKind() == IPathEntry.CDT_SOURCE) { + if (rootPath.equals(entry.getPath())) { + return; // The source root exists already. + } + } + newEntries.add(entry); + } + + IPathEntry newEntry= CoreModel.newSourceEntry(rootPath); + + Set modified= new HashSet<>(); + InternalCoreModelUtil.addExclusionPatterns(newEntry, newEntries, modified); + newEntries.add(CoreModel.newSourceEntry(rootPath)); + + cproject.setRawPathEntries(newEntries.toArray(new IPathEntry[newEntries.size()]), null); + } + } + /** * Attempts to find an archive with the given name in the workspace */ @@ -353,8 +398,7 @@ public class CProjectHelper { } /** - * Attempts to find a TranslationUnit with the given name in the workspace - * @throws InterruptedException + * Attempts to find a TranslationUnit with the given name in the workspace. */ public static ITranslationUnit findTranslationUnit(ICProject testProject, String name) throws CModelException, InterruptedException { for (int j = 0; j < 20; j++) { @@ -376,7 +420,7 @@ public class CProjectHelper { } /** - * Attempts to find an element with the given name in the workspace + * Attempts to find an element with the given name in the workspace. */ public static ICElement findElement(ICProject testProject, String name) throws CModelException { ICElement[] sourceRoots = testProject.getChildren(); @@ -414,7 +458,6 @@ public class CProjectHelper { } } - public static void importSourcesFromPlugin(ICProject project, Bundle bundle, String sources) throws CoreException { try { String baseDir= FileLocator.toFileURL(FileLocator.find(bundle, new Path(sources), null)).getFile(); @@ -422,21 +465,18 @@ public class CProjectHelper { new File(baseDir), FileSystemStructureProvider.INSTANCE, OVERWRITE_QUERY); importOp.setCreateContainerStructure(false); importOp.run(new NullProgressMonitor()); - } - catch (Exception e) { + } catch (Exception e) { throw new CoreException(new Status(IStatus.ERROR, CTestPlugin.PLUGIN_ID, 0, "Import Interrupted", e)); } } /** - * @return the location of a newly created directory in temporary area. - * Note that cleanup should be done with {@link ResourceHelper#cleanUp()}. - * @throws IOException - * @throws CoreException + * Returns the location of a newly created directory in a temporary area. + * Note that cleanup should be done with {@link ResourceHelper#cleanUp()}. */ public static File freshDir() throws IOException, CoreException { IPath folderPath = ResourceHelper.createTemporaryFolder(); - File folder = new File(folderPath.toOSString()); + File folder = folderPath.toFile(); Assert.assertTrue(folder.exists()); Assert.assertTrue(folder.isDirectory()); Assert.assertTrue(folder.canWrite()); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/InternalCoreModelUtil.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/InternalCoreModelUtil.java new file mode 100644 index 00000000000..3a335ed2da3 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/InternalCoreModelUtil.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2010, 2014 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.core.model; + +import static org.eclipse.cdt.core.model.CoreModelUtil.isExcludedPath; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.IPathEntry; +import org.eclipse.cdt.core.model.ISourceEntry; +import org.eclipse.cdt.core.settings.model.CSourceEntry; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.core.settings.model.ICSourceEntry; +import org.eclipse.cdt.core.settings.model.WriteAccessException; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; + +/** + * Non-API methods for manipulating C/C++ projects. + */ +public class InternalCoreModelUtil { + public static void addSourceEntry(IProject project, IFolder folder, boolean removeProject, + IProgressMonitor monitor) throws CoreException { + ICSourceEntry newEntry = new CSourceEntry(folder, null, 0); + ICProjectDescription des = CCorePlugin.getDefault().getProjectDescription(project, true); + addEntryToAllCfgs(des, newEntry, removeProject); + CCorePlugin.getDefault().setProjectDescription(project, des, false, monitor); + } + + private static void addEntryToAllCfgs(ICProjectDescription des, ICSourceEntry entry, + boolean removeProject) throws WriteAccessException, CoreException { + ICConfigurationDescription cfgs[] = des.getConfigurations(); + for (ICConfigurationDescription cfg : cfgs) { + ICSourceEntry[] entries = cfg.getSourceEntries(); + entries = addEntry(entries, entry, removeProject); + cfg.setSourceEntries(entries); + } + } + + private static ICSourceEntry[] addEntry(ICSourceEntry[] entries, ICSourceEntry sourceEntry, + boolean removeProject) { + Set set = new HashSet<>(); + for (ICSourceEntry entry : entries) { + if (removeProject && new Path(entry.getValue()).segmentCount() == 1) + continue; + set.add(entry); + } + set.add(sourceEntry); + return set.toArray(new ICSourceEntry[set.size()]); + } + + public static void addExclusionPatterns(IPathEntry newEntry, List existing, + Set modifiedEntries) { + IPath entryPath= newEntry.getPath(); + for (int i= 0; i < existing.size(); i++) { + IPathEntry curr= existing.get(i); + IPath currPath= curr.getPath(); + if (curr.getEntryKind() == IPathEntry.CDT_SOURCE && currPath.isPrefixOf(entryPath)) { + IPath[] exclusionFilters= ((ISourceEntry) curr).getExclusionPatterns(); + if (!isExcludedPath(entryPath, exclusionFilters)) { + IPath pathToExclude= entryPath.removeFirstSegments(currPath.segmentCount()).addTrailingSeparator(); + IPath[] newExclusionFilters= new IPath[exclusionFilters.length + 1]; + System.arraycopy(exclusionFilters, 0, newExclusionFilters, 0, exclusionFilters.length); + newExclusionFilters[exclusionFilters.length]= pathToExclude; + + IPathEntry updated= CoreModel.newSourceEntry(currPath, newExclusionFilters); + existing.set(i, updated); + modifiedEntries.add(updated); + } + } + } + } +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameMoveHeaderRefactoringTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameMoveHeaderRefactoringTest.java index ec213ccf8d1..d652102f8dc 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameMoveHeaderRefactoringTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameMoveHeaderRefactoringTest.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 @@ -21,6 +21,8 @@ import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring; import org.eclipse.ltk.internal.core.refactoring.resource.MoveResourcesProcessor; import org.eclipse.ltk.internal.core.refactoring.resource.RenameResourceProcessor; +import org.eclipse.cdt.core.model.ISourceRoot; +import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.ui.tests.refactoring.RefactoringTestBase; @@ -61,7 +63,6 @@ public class RenameMoveHeaderRefactoringTest extends RefactoringTestBase { throw new UnsupportedOperationException(); } - protected CRenameRefactoring createRenameRefactoring(String newName) { IFile file = getSelectedFile(); TextSelection selection = getSelection(); @@ -189,7 +190,7 @@ public class RenameMoveHeaderRefactoringTest extends RefactoringTestBase { // //#include "dir3/header1.h" - // header2.cpp + // source2.cpp //#include "dir1/header1.h" //#include "dir2/header3.h" // @@ -212,6 +213,61 @@ public class RenameMoveHeaderRefactoringTest extends RefactoringTestBase { compareFiles(); } + // src1/header1.h + //#ifndef HEADER1_H_ + //#define HEADER1_H_ + // + //#include "src1/header2.h" + // + //#endif // HEADER1_H_ + //==================== + // src2/header1.h + //#ifndef HEADER1_H_ + //#define HEADER1_H_ + // + //#include "src2/header2.h" + // + //#endif // HEADER1_H_ + + // src1/header2.h + //#if !defined(HEADER2_H_) + //#define HEADER2_H_ + // + //class A {}; + // + //#endif /* HEADER2_H_ */ + //==================== + // src2/header2.h + //#if !defined(HEADER2_H_) + //#define HEADER2_H_ + // + //class A {}; + // + //#endif /* HEADER2_H_ */ + + // src1/source1.cpp + //#include + // + //#include "src1/header1.h" + //==================== + // src2/source1.cpp + //#include + // + //#include "src2/header1.h" + public void testSourceRootRename() throws Exception { + CProjectHelper.addSourceRoot(getCProject(), "src1"); + IFolder resource = getProject().getFolder("src1"); + RenameResourceProcessor processor = new RenameResourceProcessor(resource); + processor.setNewResourceName("src2"); + RenameRefactoring refactoring = new RenameRefactoring(processor); + executeRefactoring(refactoring, true); + ISourceRoot[] sourceRoots = getCProject().getAllSourceRoots(); + assertEquals(2, sourceRoots.length); + assertEquals(getProject().getName(), sourceRoots[0].getElementName()); + assertEquals("src2", sourceRoots[1].getElementName()); + compareFiles(); + } + // dir1/header1.h //#ifndef DIR1_HEADER1_H_ //#define DIR1_HEADER1_H_ @@ -254,7 +310,7 @@ public class RenameMoveHeaderRefactoringTest extends RefactoringTestBase { // //#include "dir3/dir1/header1.h" - // header2.cpp + // source2.cpp //#include "dir1/header1.h" //#include "dir2/header3.h" // 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 9d9cbbb5b48..e3a12fa7d80 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 @@ -10,11 +10,13 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; +import java.util.Collections; 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.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceProxyVisitor; @@ -83,9 +85,10 @@ public class HeaderFileMoveParticipant extends MoveParticipant implements IShara if (destinationLocation.equals(movedResource.getLocation().removeLastSegments(1))) continue; - if (movedResource instanceof IContainer) { - final int prefixLength = movedResource.getFullPath().segmentCount() - 1; - ((IContainer) movedResource).accept(new IResourceProxyVisitor() { + if (movedResource instanceof IFolder) { + IFolder folder = (IFolder) movedResource; + final int prefixLength = folder.getFullPath().segmentCount() - 1; + folder.accept(new IResourceProxyVisitor() { @Override public boolean visit(IResourceProxy proxy) throws CoreException { if (proxy.isLinked()) @@ -103,9 +106,9 @@ public class HeaderFileMoveParticipant extends MoveParticipant implements IShara movedFiles.put(file, destination.getFile(new Path(movedResource.getName()))); } } - - HeaderFileReferenceAdjuster includeAdjuster = - new HeaderFileReferenceAdjuster(movedFiles, null, getProcessor()); + + HeaderFileReferenceAdjuster includeAdjuster = new HeaderFileReferenceAdjuster(movedFiles, + Collections.emptyMap(), 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 d5f4cef240e..6aa398d8323 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 @@ -63,11 +63,13 @@ import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexInclude; import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.index.IndexLocationFactory; +import org.eclipse.cdt.core.model.CModelException; 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.core.settings.model.ICSourceEntry; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.IWorkingCopyManager; import org.eclipse.cdt.ui.PreferenceConstants; @@ -77,6 +79,7 @@ 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; import org.eclipse.cdt.internal.core.dom.rewrite.util.ASTNodes; +import org.eclipse.cdt.internal.core.model.SourceRoot; import org.eclipse.cdt.internal.core.util.TextUtil; import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo; import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; @@ -104,9 +107,10 @@ public class HeaderFileReferenceAdjuster { private int indexLockCount; /** - * @param movedFiles keys are moved files, values are new, not yet existing, files + * @param movedFiles keys are files being moved or renamed, 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}. + * not yet existing folders and projects. * @param processor the refactoring processor */ public HeaderFileReferenceAdjuster(Map movedFiles, @@ -114,7 +118,8 @@ public class HeaderFileReferenceAdjuster { this.movedFiles = movedFiles; this.movedFilesByLocation = new HashMap<>(); for (Entry entry : movedFiles.entrySet()) { - this.movedFilesByLocation.put(entry.getKey().getLocation().toOSString(), entry.getValue().getLocation()); + this.movedFilesByLocation.put(entry.getKey().getLocation().toOSString(), + entry.getValue().getLocation()); } this.renamedContainers = renamedContainers; this.astManager = getASTManager(processor); @@ -458,11 +463,30 @@ public class HeaderFileReferenceAdjuster { 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; + IProject newProject = newFile.getProject(); + if (newProject.exists()) { + // Move within the same or to a different existing project. + cProject = CoreModel.getDefault().create(newProject); + if (cProject == null) + break; + } + ISourceRoot[] roots; + try { + roots = cProject.getAllSourceRoots(); + } catch (CModelException e) { + break; + } + IContainer base = null; + for (ISourceRoot root : roots) { + root = getModifiedSourceRoot(cProject, root); + if (root.isOnSourceEntry(newFile)) { + base = root.getResource(); + break; + } + } + + if (base == null) + break; IPath path = PathUtil.makeRelativePath(newFile.getFullPath(), base.getFullPath()); if (path == null) break; @@ -477,6 +501,33 @@ public class HeaderFileReferenceAdjuster { return null; } + protected ISourceRoot getModifiedSourceRoot(ICProject cProject, ISourceRoot root) { + IContainer container = root.getResource(); + ICSourceEntry sourceEntry = ((SourceRoot) root).getSourceEntry(); + for (Entry entry : renamedContainers.entrySet()) { + IPath oldFolderPath = entry.getKey().getFullPath(); + IPath newFolderPath = entry.getValue().getFullPath(); + sourceEntry = RenameCSourceFolderChange.renameSourceEntry(sourceEntry, oldFolderPath, newFolderPath); + } + IContainer newContainer = getModifiedContainer(container); + return new SourceRoot(cProject, newContainer, sourceEntry); + } + + private IContainer getModifiedContainer(IContainer container) { + IPath relativePath = Path.EMPTY; + for (IContainer ancestor = container; ancestor.getType() != IResource.ROOT; ancestor = ancestor.getParent()) { + IContainer newContainer = renamedContainers.get(ancestor); + if (newContainer != null) { + if (relativePath.isEmpty()) { + return newContainer; + } + return newContainer.getFolder(relativePath); + } + relativePath = new Path(ancestor.getName()).append(relativePath); + } + return container; + } + private void flushEditBuffer(int offset, StringBuilder text, Deque deletes, MultiTextEdit edit) { consumeDeletesUpTo(offset, deletes, edit); if (text.length() != 0) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameCSourceFolderChange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameCSourceFolderChange.java index 4c5fecd975d..59a14f3898c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameCSourceFolderChange.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameCSourceFolderChange.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2009, 2015 Institute for Software, HSR Hochschule fuer Technik * Rapperswil, University of applied sciences and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -7,7 +7,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Institute for Software (IFS)- initial API and implementation + * Institute for Software (IFS)- initial API and implementation + * Sergey Prigogin (Google) ******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; @@ -39,27 +40,28 @@ import org.eclipse.cdt.ui.CUIPlugin; * @author Emanuel Graf IFS */ public class RenameCSourceFolderChange extends Change { - private IPath oldName; - private IPath newName; - private IProject project; - private IFolder folder; + private final IPath oldFolderPath; + private final IPath newFolderPath; + private final IProject project; + private final IFolder oldFolder; - public RenameCSourceFolderChange(IPath oldFolderPath, IPath newFolderPath, IProject project, IFolder oldFolder) { + public RenameCSourceFolderChange(IFolder oldFolder, IPath newFolderPath) { super(); - this.oldName = oldFolderPath; - this.newName = newFolderPath; - this.project = project; - folder = oldFolder; + this.oldFolder = oldFolder; + this.newFolderPath = newFolderPath; + this.oldFolderPath = oldFolder.getFullPath(); + this.project = oldFolder.getProject(); } @Override public Object getModifiedElement() { - return folder; + return oldFolder; } @Override public String getName() { - return NLS.bind(RenameMessages.RenameCSourceFolderChange_Name0, oldName.lastSegment(), newName.lastSegment()); + return NLS.bind(RenameMessages.RenameCSourceFolderChange_Name0, + oldFolderPath.lastSegment(), newFolderPath.lastSegment()); } @Override @@ -68,51 +70,56 @@ public class RenameCSourceFolderChange extends Change { @Override public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException, OperationCanceledException { - if (folder.exists()) { + if (oldFolder.exists()) { return RefactoringStatus.create(Status.OK_STATUS); } else { return RefactoringStatus.create(new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, - NLS.bind(RenameMessages.RenameCSourceFolderChange_ErrorMsg, folder.getName()))); + NLS.bind(RenameMessages.RenameCSourceFolderChange_ErrorMsg, oldFolder.getName()))); } } @Override public Change perform(IProgressMonitor pm) throws CoreException { changeEntryInAllCfgs(CCorePlugin.getDefault().getProjectDescription(project, true)); - IFolder folder2 = project.getFolder(newName.lastSegment()); - return new RenameCSourceFolderChange(newName, oldName, project, folder2); + IFolder newFolder = project.getFolder(newFolderPath.removeFirstSegments(1)); + return new RenameCSourceFolderChange(newFolder, oldFolderPath); } private void changeEntryInAllCfgs(ICProjectDescription des) throws WriteAccessException, CoreException { ICConfigurationDescription cfgs[] = des.getConfigurations(); for (ICConfigurationDescription cfg : cfgs) { ICSourceEntry[] entries = cfg.getSourceEntries(); - entries = renameEntry(entries); + entries = renameSourceEntries(entries); cfg.setSourceEntries(entries); } CCorePlugin.getDefault().setProjectDescription(project, des, false, new NullProgressMonitor()); } - private ICSourceEntry[] renameEntry(ICSourceEntry[] entries) { + private ICSourceEntry[] renameSourceEntries(ICSourceEntry[] sourceEntries) { Set set = new HashSet<>(); - for (ICSourceEntry entry : entries) { - String entryPath = entry.getName(); - if (entryPath.equals(oldName.toString())) { - set.add(new CSourceEntry(newName, entry.getExclusionPatterns(), entry.getFlags())); - } else { - IPath oldSegments = oldName.removeFirstSegments(oldName.segmentCount() - 1); - Set exclusionPatterns = new HashSet<>(); - for (IPath pattern : entry.getExclusionPatterns()) { - if (pattern.equals(oldSegments)) { - exclusionPatterns.add(newName.removeFirstSegments(newName.segmentCount() - 1)); - } else { - exclusionPatterns.add(pattern); - } - } - - set.add(new CSourceEntry(entry.getValue(), exclusionPatterns.toArray(new IPath[exclusionPatterns.size()]), entry.getFlags())); - } + for (ICSourceEntry entry : sourceEntries) { + set.add(renameSourceEntry(entry, oldFolderPath, newFolderPath)); } return set.toArray(new ICSourceEntry[set.size()]); } + + static ICSourceEntry renameSourceEntry(ICSourceEntry sourceEntry, IPath oldFolderPath, IPath newFolderPath) { + String entryPath = sourceEntry.getName(); + if (entryPath.equals(oldFolderPath.toString())) { + return new CSourceEntry(newFolderPath, sourceEntry.getExclusionPatterns(), sourceEntry.getFlags()); + } else { + IPath oldSegments = oldFolderPath.removeFirstSegments(oldFolderPath.segmentCount() - 1); + Set exclusionPatterns = new HashSet<>(); + for (IPath pattern : sourceEntry.getExclusionPatterns()) { + if (pattern.equals(oldSegments)) { + exclusionPatterns.add(newFolderPath.removeFirstSegments(newFolderPath.segmentCount() - 1)); + } else { + exclusionPatterns.add(pattern); + } + } + + return new CSourceEntry(sourceEntry.getValue(), + exclusionPatterns.toArray(new IPath[exclusionPatterns.size()]), sourceEntry.getFlags()); + } + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/SourceFolderRenameParticipant.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/SourceFolderRenameParticipant.java index d935a66d3ce..cb413056fb6 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/SourceFolderRenameParticipant.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/SourceFolderRenameParticipant.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2014 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2009, 2015 Institute for Software, HSR Hochschule fuer Technik * Rapperswil, University of applied sciences and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -41,10 +41,9 @@ public class SourceFolderRenameParticipant extends RenameParticipant { @Override public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { - IPath oldFolderPath = oldFolder.getFullPath(); String newName = getArguments().getNewName(); - IPath newFolderPath = oldFolderPath.removeLastSegments(1).append(newName); - return new RenameCSourceFolderChange(oldFolderPath, newFolderPath, oldFolder.getProject(), oldFolder); + IPath newFolderPath = oldFolder.getFullPath().removeLastSegments(1).append(newName); + return new RenameCSourceFolderChange(oldFolder, newFolderPath); } @Override diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/folderwizard/NewSourceFolderWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/folderwizard/NewSourceFolderWizardPage.java index da6ed5a6afb..245c0bd15b5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/folderwizard/NewSourceFolderWizardPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/folderwizard/NewSourceFolderWizardPage.java @@ -12,7 +12,6 @@ package org.eclipse.cdt.internal.ui.wizards.folderwizard; import java.util.ArrayList; import java.util.HashSet; -import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFolder; @@ -50,21 +49,15 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CProjectNature; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; -import org.eclipse.cdt.core.model.CoreModelUtil; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICModelStatus; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.IPathEntry; -import org.eclipse.cdt.core.model.ISourceEntry; import org.eclipse.cdt.core.model.ISourceRoot; -import org.eclipse.cdt.core.settings.model.CSourceEntry; -import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; -import org.eclipse.cdt.core.settings.model.ICProjectDescription; -import org.eclipse.cdt.core.settings.model.ICSourceEntry; -import org.eclipse.cdt.core.settings.model.WriteAccessException; import org.eclipse.cdt.ui.CElementLabelProvider; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.internal.core.model.InternalCoreModelUtil; import org.eclipse.cdt.internal.core.model.PathEntryManager; import org.eclipse.cdt.internal.ui.ICHelpContextIds; @@ -357,10 +350,10 @@ public class NewSourceFolderWizardPage extends NewElementWizardPage { Set modified= new HashSet<>(); if (fExcludeInOthersFields.isSelected()) { - addExclusionPatterns(newEntry, newEntries, modified); + InternalCoreModelUtil.addExclusionPatterns(newEntry, newEntries, modified); newEntries.add(CoreModel.newSourceEntry(path)); } else { - if (projectEntryIndex != -1) { + if (projectEntryIndex >= 0) { fIsProjectAsSourceFolder= true; newEntries.set(projectEntryIndex, newEntry); } else { @@ -390,27 +383,6 @@ public class NewSourceFolderWizardPage extends NewElementWizardPage { } } - private static void addExclusionPatterns(IPathEntry newEntry, List existing, Set modifiedEntries) { - IPath entryPath= newEntry.getPath(); - for (int i= 0; i < existing.size(); i++) { - IPathEntry curr= existing.get(i); - IPath currPath= curr.getPath(); - if (curr.getEntryKind() == IPathEntry.CDT_SOURCE && currPath.isPrefixOf(entryPath)) { - IPath[] exclusionFilters= ((ISourceEntry) curr).getExclusionPatterns(); - if (!CoreModelUtil.isExcludedPath(entryPath, exclusionFilters)) { - IPath pathToExclude= entryPath.removeFirstSegments(currPath.segmentCount()).addTrailingSeparator(); - IPath[] newExclusionFilters= new IPath[exclusionFilters.length + 1]; - System.arraycopy(exclusionFilters, 0, newExclusionFilters, 0, exclusionFilters.length); - newExclusionFilters[exclusionFilters.length]= pathToExclude; - - IPathEntry updated= CoreModel.newSourceEntry(currPath, newExclusionFilters); - existing.set(i, updated); - modifiedEntries.add(updated); - } - } - } - } - // ---- creation ---------------- public ISourceRoot getNewSourceRoot() { @@ -429,7 +401,8 @@ public class NewSourceFolderWizardPage extends NewElementWizardPage { try { String relPath= fRootDialogField.getText(); - IFolder folder= fCurrCProject.getProject().getFolder(relPath); + IProject project = fCurrCProject.getProject(); + IFolder folder= project.getFolder(relPath); if (!folder.exists()) { CoreUtility.createFolder(folder, true, true, new SubProgressMonitor(monitor, 1)); } @@ -437,11 +410,9 @@ public class NewSourceFolderWizardPage extends NewElementWizardPage { throw new InterruptedException(); } - if (CCorePlugin.getDefault().isNewStyleProject(fCurrCProject.getProject())) { - ICSourceEntry newEntry = new CSourceEntry(folder, null, 0); - ICProjectDescription des = CCorePlugin.getDefault().getProjectDescription(fCurrCProject.getProject(), true); - addEntryToAllCfgs(des, newEntry, fIsProjectAsSourceFolder); - CCorePlugin.getDefault().setProjectDescription(fCurrCProject.getProject(), des, false, new SubProgressMonitor(monitor, 2)); + if (CCorePlugin.getDefault().isNewStyleProject(project)) { + InternalCoreModelUtil.addSourceEntry(project, folder, fIsProjectAsSourceFolder, + new SubProgressMonitor(monitor, 2)); } else { fCurrCProject.setRawPathEntries(fNewEntries, new SubProgressMonitor(monitor, 2)); } @@ -451,28 +422,7 @@ public class NewSourceFolderWizardPage extends NewElementWizardPage { monitor.done(); } } - - private void addEntryToAllCfgs(ICProjectDescription des, ICSourceEntry entry, boolean removeProj) - throws WriteAccessException, CoreException{ - ICConfigurationDescription cfgs[] = des.getConfigurations(); - for (ICConfigurationDescription cfg : cfgs) { - ICSourceEntry[] entries = cfg.getSourceEntries(); - entries = addEntry(entries, entry, removeProj); - cfg.setSourceEntries(entries); - } - } - - private ICSourceEntry[] addEntry(ICSourceEntry[] entries, ICSourceEntry sourceEntry, boolean removeProj) { - Set set = new HashSet<>(); - for (ICSourceEntry entry : entries) { - if (removeProj && new Path(entry.getValue()).segmentCount() == 1) - continue; - set.add(entry); - } - set.add(sourceEntry); - return set.toArray(new ICSourceEntry[set.size()]); - } - + // ------------- choose dialogs private IFolder chooseFolder(String title, String message, IPath initialPath) {