diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java index e93f2319908..edc3efee88e 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 QNX Software Systems and others. + * Copyright (c) 2000, 2014 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 @@ -8,6 +8,7 @@ * Contributors: * QNX Software Systems - Initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.core.model; @@ -21,6 +22,7 @@ import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.parser.FileContent; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.internal.core.model.IBufferFactory; +import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; @@ -419,6 +421,15 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource */ public IPath getLocation(); + /** + * Returns the corresponding file for this translation unit, or {@code null} if this translation + * unit does not have a corresponding file. + * + * @return the corresponding file, or {@code null} if none + * @since 5.9 + */ + IFile getFile(); + /** * Returns the scanner info associated with this translation unit. May return {@code null} * if no configuration is available. diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java index 43795868a96..3f1c586f390 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 QNX Software Systems and others. + * Copyright (c) 2000, 2014 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 @@ -354,8 +354,9 @@ public class TranslationUnit extends Openable implements ITranslationUnit { return location; } + @Override public IFile getFile() { - IResource res = getResource(); + IResource res = super.getResource(); if (res instanceof IFile) { return (IFile) res; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java index 2608f573256..6c179ddeece 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2013 IBM Corporation and others. + * Copyright (c) 2004, 2014 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 @@ -345,7 +345,8 @@ public abstract class ArrayUtil { } /** - * Adds all elements of an array to a collection. + * Adds all elements of an array to a collection. For an {@link ArrayList} this method is + * slightly more efficient than {@link java.util.Collections#addAll(Collection, T...)}. * @since 5.4 */ @SafeVarargs 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 67bcd7c907d..3569960ec4f 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 @@ -12,8 +12,10 @@ package org.eclipse.cdt.ui.tests.refactoring.rename; import junit.framework.Test; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; +import org.eclipse.jface.text.TextSelection; import org.eclipse.ltk.core.refactoring.participants.MoveRefactoring; import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring; import org.eclipse.ltk.internal.core.refactoring.resource.MoveResourcesProcessor; @@ -23,6 +25,10 @@ import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.ui.tests.refactoring.RefactoringTestBase; import org.eclipse.cdt.internal.ui.refactoring.CRefactoring; +import org.eclipse.cdt.internal.ui.refactoring.rename.CRefactoringArgument; +import org.eclipse.cdt.internal.ui.refactoring.rename.CRefactory; +import org.eclipse.cdt.internal.ui.refactoring.rename.CRenameProcessor; +import org.eclipse.cdt.internal.ui.refactoring.rename.CRenameRefactoring; /** * Tests for @@ -55,6 +61,27 @@ public class RenameMoveHeaderRefactoringTest extends RefactoringTestBase { throw new UnsupportedOperationException(); } + + protected CRenameRefactoring createRenameRefactoring(String newName) { + IFile file = getSelectedFile(); + TextSelection selection = getSelection(); + CRefactoringArgument arg = new CRefactoringArgument(file, selection.getOffset(), selection.getLength()); + CRenameProcessor processor = new CRenameProcessor(CRefactory.getInstance(), arg); + processor.setReplacementText(newName); + processor.setSelectedOptions(0xFFFF & ~CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH); + return new CRenameRefactoring(processor); + } + + protected void executeRenameRefactoring(String newName, boolean expectedSuccess) throws Exception { + CRenameRefactoring refactoring = createRenameRefactoring(newName); + refactoring.getProcessor().lockIndex(); + try { + executeRefactoring(refactoring, expectedSuccess); + } finally { + refactoring.getProcessor().unlockIndex(); + } + } + // test1.h //#ifndef TEST1_H_ //#define TEST1_H_ @@ -249,4 +276,44 @@ public class RenameMoveHeaderRefactoringTest extends RefactoringTestBase { executeRefactoring(refactoring, true); compareFiles(); } + + // OriginalClass.h + //#ifndef ORIGINALCLASS_H_ + //#define ORIGINALCLASS_H_ + // + //class OriginalClass {}; + // + //#endif // ORIGINALCLASS_H_ + //==================== + // RenamedClass.h + //#ifndef RENAMEDCLASS_H_ + //#define RENAMEDCLASS_H_ + // + //class RenamedClass {}; + // + //#endif // RENAMEDCLASS_H_ + + // OriginalClass.cpp + //#include "OriginalClass.h" + //==================== + // RenamedClass.cpp + //#include "RenamedClass.h" + + // OriginalClass_test.cpp + //#include "OriginalClass.h" + //==================== + // RenamedClass_test.cpp + //#include "RenamedClass.h" + + // SomeOtherFile.cpp + //#include "OriginalClass.h" + ///*$*/OriginalClass/*$$*/ a; + //==================== + // SomeOtherFile.cpp + //#include "RenamedClass.h" + //RenamedClass a; + public void testClassRename() throws Exception { + executeRenameRefactoring("RenamedClass", true); + compareFiles(); + } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTestBase.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTestBase.java index 455d40d7006..87308188c29 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTestBase.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTestBase.java @@ -47,7 +47,7 @@ public class RenameTestBase extends RefactoringTests { protected Change getRefactorChanges(IFile file, int offset, String newName) throws Exception { CRenameRefactoring refactoring = createRefactoring(file, offset, newName); - ((CRenameProcessor) refactoring.getProcessor()).lockIndex(); + refactoring.getProcessor().lockIndex(); try { RefactoringStatus rs = checkConditions(refactoring); if (!rs.hasError()) { @@ -62,7 +62,7 @@ public class RenameTestBase extends RefactoringTests { // is shown. return null; } finally { - ((CRenameProcessor) refactoring.getProcessor()).unlockIndex(); + refactoring.getProcessor().unlockIndex(); } } @@ -78,7 +78,7 @@ public class RenameTestBase extends RefactoringTests { protected String[] getRefactorMessages(IFile file, int offset, String newName) throws Exception { String[] result; CRenameRefactoring refactoring = createRefactoring(file, offset, newName); - ((CRenameProcessor) refactoring.getProcessor()).lockIndex(); + refactoring.getProcessor().lockIndex(); try { RefactoringStatus rs = checkConditions(refactoring); if (!rs.hasWarning()) { @@ -94,17 +94,17 @@ public class RenameTestBase extends RefactoringTests { } return result; } finally { - ((CRenameProcessor) refactoring.getProcessor()).unlockIndex(); + refactoring.getProcessor().unlockIndex(); } } protected RefactoringStatus checkConditions(IFile file, int offset, String newName) throws Exception { CRenameRefactoring refactoring = createRefactoring(file, offset, newName); - ((CRenameProcessor) refactoring.getProcessor()).lockIndex(); + refactoring.getProcessor().lockIndex(); try { return checkConditions(refactoring); } finally { - ((CRenameProcessor) refactoring.getProcessor()).unlockIndex(); + refactoring.getProcessor().unlockIndex(); } } @@ -118,12 +118,12 @@ public class RenameTestBase extends RefactoringTests { protected int getRefactorSeverity(IFile file, int offset, String newName) throws Exception { CRenameRefactoring refactoring = createRefactoring(file, offset, newName); - ((CRenameProcessor) refactoring.getProcessor()).lockIndex(); + refactoring.getProcessor().lockIndex(); try { RefactoringStatus rs = checkConditions(refactoring); return rs.getSeverity(); } finally { - ((CRenameProcessor) refactoring.getProcessor()).unlockIndex(); + refactoring.getProcessor().unlockIndex(); } } diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index 874483ca5e0..dcea8385cf1 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -4225,7 +4225,7 @@ class="org.eclipse.cdt.internal.ui.refactoring.dialogs.CreateFileChangePreview" id="org.eclipse.cdt.internal.ui.refactoring.createFileChangePreviewhangePreview"> - + fCreate; + private List fDelete; + + private List fMove; + private List fMoveArguments; + + private List fRename; + private List fRenameArguments; + + private List fCopy; + private List fCopyArguments; + + private int fIgnoreCount; + private List fDeltaDescriptions; + + public static abstract class DeltaDescription { + protected IResource fResource; + + public DeltaDescription(IResource resource) { + fResource= resource; + } + + public abstract void buildDelta(IResourceChangeDescriptionFactory builder); + + public abstract IPath getDestinationPath(); + } + + public static class DeleteDescription extends DeltaDescription { + public DeleteDescription(IResource resource) { + super(resource); + } + + @Override + public void buildDelta(IResourceChangeDescriptionFactory builder) { + builder.delete(fResource); + } + + @Override + public IPath getDestinationPath() { + return null; + } + } + + public static class ChangedDescription extends DeltaDescription { + public ChangedDescription(IFile resource) { + super(resource); + } + + @Override + public void buildDelta(IResourceChangeDescriptionFactory builder) { + builder.change((IFile)fResource); + } + + @Override + public IPath getDestinationPath() { + return null; + } + } + + public static class CreateDescription extends DeltaDescription { + public CreateDescription(IResource resource) { + super(resource); + } + + @Override + public void buildDelta(IResourceChangeDescriptionFactory builder) { + builder.create(fResource); + } + + @Override + public IPath getDestinationPath() { + return fResource.getFullPath(); + } + } + + public static class MoveDescription extends DeltaDescription { + private IPath fDestination; + + public MoveDescription(IResource resource, IPath destination) { + super(resource); + fDestination= destination; + } + + @Override + public void buildDelta(IResourceChangeDescriptionFactory builder) { + IResource existing= ResourcesPlugin.getWorkspace().getRoot().findMember(fDestination); + if (existing != null && !existing.equals(fResource)) { + builder.delete(existing); + } + builder.move(fResource, fDestination); + } + + @Override + public IPath getDestinationPath() { + return fDestination; + } + } + + public static class CopyDescription extends DeltaDescription { + private IPath fDestination; + + public CopyDescription(IResource resource, IPath destination) { + super(resource); + fDestination= destination; + } + + @Override + public void buildDelta(IResourceChangeDescriptionFactory builder) { + IResource existing= ResourcesPlugin.getWorkspace().getRoot().findMember(fDestination); + if (existing != null && !existing.equals(fResource)) { + builder.delete(existing); + } + builder.copy(fResource, fDestination); + } + + @Override + public IPath getDestinationPath() { + return fDestination; + } + } + + /** + * Adds the given file to the list of changed files. + * + * @param file the changed file + */ + public void addChanged(IFile file) { + if (fIgnoreCount == 0) { + internalAdd(new ChangedDescription(file)); + } + } + + /** + * Adds the given resource to the list of resources to be created. + * + * @param create the resource to be add to the list of resources to be created + */ + public void addCreate(IResource create) { + if (fCreate == null) + fCreate= new ArrayList<>(2); + fCreate.add(create); + if (fIgnoreCount == 0) { + internalAdd(new CreateDescription(create)); + } + } + + /** + * Adds the given resource to the list of resources to be deleted. + * + * @param delete the resource to be deleted + */ + public void addDelete(IResource delete) { + if (fDelete == null) + fDelete= new ArrayList<>(2); + fDelete.add(delete); + if (fIgnoreCount == 0) { + internalAdd(new DeleteDescription(delete)); + } + } + + /** + * Adds the given resource to the list of resources to be moved. + * + * @param move the resource to be moved + * @param arguments the move arguments + */ + public void addMove(IResource move, MoveArguments arguments) { + if (fMove == null) { + fMove= new ArrayList<>(2); + fMoveArguments= new ArrayList<>(2); + } + fMove.add(move); + fMoveArguments.add(arguments); + if (fIgnoreCount == 0) { + IPath destination= ((IResource)arguments.getDestination()).getFullPath().append(move.getName()); + internalAdd(new MoveDescription(move, destination)); + } + } + + /** + * Adds the given resource to the list of resources to be copied. + * + * @param copy the resource to be copied + * @param arguments the copy arguments + */ + public void addCopy(IResource copy, CopyArguments arguments) { + if (fCopy == null) { + fCopy= new ArrayList<>(2); + fCopyArguments= new ArrayList<>(2); + } + fCopy.add(copy); + fCopyArguments.add(arguments); + addCopyDelta(copy, arguments); + } + + /** + * Adds the given resource to the list of renamed resources. + * + * @param rename the resource to be renamed + * @param arguments the arguments of the rename + */ + public void addRename(IResource rename, RenameArguments arguments) { + Assert.isNotNull(rename); + Assert.isNotNull(arguments); + if (fRename == null) { + fRename= new ArrayList<>(2); + fRenameArguments= new ArrayList<>(2); + } + fRename.add(rename); + fRenameArguments.add(arguments); + if (fIgnoreCount == 0) { + IPath newPath= rename.getFullPath().removeLastSegments(1).append(arguments.getNewName()); + internalAdd(new MoveDescription(rename, newPath)); + } + } + + public RefactoringParticipant[] getParticipants(RefactoringStatus status, + RefactoringProcessor processor, String[] natures, SharableParticipants shared) { + List result= new ArrayList<>(5); + if (fDelete != null) { + DeleteArguments arguments= new DeleteArguments(); + for (Iterator iter= fDelete.iterator(); iter.hasNext();) { + DeleteParticipant[] deletes= ParticipantManager.loadDeleteParticipants(status, + processor, iter.next(), + arguments, natures, shared); + result.addAll(Arrays.asList(deletes)); + } + } + if (fCreate != null) { + CreateArguments arguments= new CreateArguments(); + for (Iterator iter= fCreate.iterator(); iter.hasNext();) { + CreateParticipant[] creates= ParticipantManager.loadCreateParticipants(status, + processor, iter.next(), + arguments, natures, shared); + result.addAll(Arrays.asList(creates)); + } + } + if (fMove != null) { + for (int i= 0; i < fMove.size(); i++) { + Object element= fMove.get(i); + MoveArguments arguments= fMoveArguments.get(i); + MoveParticipant[] moves= ParticipantManager.loadMoveParticipants(status, + processor, element, + arguments, natures, shared); + result.addAll(Arrays.asList(moves)); + + } + } + if (fCopy != null) { + for (int i= 0; i < fCopy.size(); i++) { + Object element= fCopy.get(i); + CopyArguments arguments= fCopyArguments.get(i); + CopyParticipant[] copies= ParticipantManager.loadCopyParticipants(status, + processor, element, + arguments, natures, shared); + result.addAll(Arrays.asList(copies)); + } + } + if (fRename != null) { + for (int i= 0; i < fRename.size(); i++) { + Object resource= fRename.get(i); + RenameArguments arguments= fRenameArguments.get(i); + RenameParticipant[] renames= ParticipantManager.loadRenameParticipants(status, + processor, resource, + arguments, natures, shared); + result.addAll(Arrays.asList(renames)); + } + } + return result.toArray(new RefactoringParticipant[result.size()]); + } + + public void ignoreForDelta() { + fIgnoreCount++; + } + + public void trackForDelta() { + fIgnoreCount--; + } + + public void addDelta(DeltaDescription description) { + if (fIgnoreCount > 0) + return; + internalAdd(description); + } + + public void addCopyDelta(IResource copy, CopyArguments arguments) { + if (fIgnoreCount == 0) { + IPath destination= ((IResource) arguments.getDestination()).getFullPath().append(copy.getName()); + internalAdd(new CopyDescription(copy, destination)); + } + } + + /** + * Checks if the resource will exist in the future based on + * the recorded resource modifications. + * + * @param resource the resource to check + * @return whether the resource will exist or not + */ + public boolean willExist(IResource resource) { + if (fDeltaDescriptions == null) + return false; + IPath fullPath= resource.getFullPath(); + for (Iterator iter= fDeltaDescriptions.iterator(); iter.hasNext();) { + DeltaDescription delta= iter.next(); + if (fullPath.equals(delta.getDestinationPath())) + return true; + } + return false; + } + + public void buildDelta(IResourceChangeDescriptionFactory builder) { + if (fDeltaDescriptions == null) + return; + for (Iterator iter= fDeltaDescriptions.iterator(); iter.hasNext();) { + iter.next().buildDelta(builder); + } + } + + public static void buildMoveDelta(IResourceChangeDescriptionFactory builder, IResource resource, RenameArguments args) { + IPath newPath= resource.getFullPath().removeLastSegments(1).append(args.getNewName()); + new MoveDescription(resource, newPath).buildDelta(builder); + } + + public static void buildMoveDelta(IResourceChangeDescriptionFactory builder, IResource resource, MoveArguments args) { + IPath destination= ((IResource)args.getDestination()).getFullPath().append(resource.getName()); + new MoveDescription(resource, destination).buildDelta(builder); + } + + public static void buildCopyDelta(IResourceChangeDescriptionFactory builder, IResource resource, CopyArguments args) { + IPath destination= ((IResource)args.getDestination()).getFullPath().append(resource.getName()); + new CopyDescription(resource, destination).buildDelta(builder); + } + + private void internalAdd(DeltaDescription description) { + if (fDeltaDescriptions == null) + fDeltaDescriptions= new ArrayList<>(); + fDeltaDescriptions.add(description); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SourceHeaderPartnerFinder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SourceHeaderPartnerFinder.java index 0b6f27d39eb..b4a6b6d835b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SourceHeaderPartnerFinder.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SourceHeaderPartnerFinder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2014 Wind River Systems, 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 @@ -9,6 +9,7 @@ * Anton Leherbauer (Wind River Systems) - initial API and implementation * Markus Schorn (Wind River Systems) * Marc-Andre Laperle - Extracted Util class from ToggleSourceHeaderAction + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.editor; @@ -355,4 +356,36 @@ public final class SourceHeaderPartnerFinder { } return partnerUnit; } + + /** + * Checks if the given path points to a partner source of the given header file. A source file + * is considered a partner if its name without extension is the same as the name of the header, + * or its name differs by one of the suffixes used for partner, e.g. test, files. + * + * @param partnerCandidate the file system path of the file to check + * @param header the file system path of the header file + * @param partnerFileSuffixes name suffixes allowed for partner files + * @return {@code true} if {@code partnerCandidate} is a partner of {@code header} + */ + public static boolean isPartnerFile(IPath partnerCandidate, IPath header, String[] partnerFileSuffixes) { + String headerName = header.removeFileExtension().lastSegment(); + String sourceName = partnerCandidate.removeFileExtension().lastSegment(); + if (headerName.equals(sourceName)) + return true; + if (sourceName.startsWith(headerName)) { + int pos = headerName.length(); + // Skip a delimiter before the suffix, e.g. an underscore or a dash. + while (pos < sourceName.length() && !Character.isLetterOrDigit(sourceName.charAt(pos))) { + pos++; + } + if (pos == sourceName.length()) + return true; + String suffix = sourceName.substring(pos); + for (String s : partnerFileSuffixes) { + if (suffix.equalsIgnoreCase(s)) + return true; + } + } + return false; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java index a9bc21bfc1c..95295723c41 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java @@ -60,6 +60,7 @@ import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.corext.util.CModelUtil; +import org.eclipse.cdt.internal.ui.refactoring.changes.CCompositeChange; import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper; /** diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IndexToASTNameHelper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IndexToASTNameHelper.java index f0b2bc36201..10b463c5d35 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IndexToASTNameHelper.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IndexToASTNameHelper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2011, 2014 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 @@ -34,7 +34,8 @@ public class IndexToASTNameHelper { return visitor.getMatches(); } - public static IASTName findMatchingASTName(IASTTranslationUnit tu, IName name, IIndex index) throws CoreException { + public static IASTName findMatchingASTName(IASTTranslationUnit tu, IName name, IIndex index) + throws CoreException { if (name instanceof IASTName) { return (IASTName) name; } else if (!(name instanceof IIndexName)) { @@ -65,85 +66,86 @@ public class IndexToASTNameHelper { private static boolean isQualifiedName(IASTName name) { return name instanceof ICPPASTQualifiedName; } -} -class IndexNameToAstNameMatcher extends ASTVisitor { - private IASTName result; - private IBinding bindingToFind; - private char[] charNameToFind; - private IIndex index; - private IASTFileLocation locationToFind; + private static class BindingToAstNameMatcher extends ASTVisitor { + private List results = new ArrayList<>(); + private IBinding bindingToFind; + private char[] toFindName; + private IIndex index; - public IndexNameToAstNameMatcher(IASTTranslationUnit tu, IIndexName indexName, IIndex index) throws CoreException { - super(true); - locationToFind = indexName.getFileLocation(); - bindingToFind = index.findBinding(indexName); - this.index = index; - charNameToFind = bindingToFind.getNameCharArray(); - shouldVisitImplicitNames = true; - shouldVisitImplicitNameAlternates = true; - } + public BindingToAstNameMatcher(IBinding binding, IIndex index) { + super(true); + bindingToFind = index.adaptBinding(binding); + this.index = index; + toFindName = binding.getNameCharArray(); + shouldVisitImplicitNames = true; + shouldVisitImplicitNameAlternates = true; + } - @Override - public int visit(IASTName candidate) { - if (!IndexToASTNameHelper.shouldConsiderName(candidate)) { + @Override + public int visit(IASTName candidate) { + if (!IndexToASTNameHelper.shouldConsiderName(candidate)) { + return PROCESS_CONTINUE; + } + if (isEquivalent(candidate)) { + results.add(candidate); + } return PROCESS_CONTINUE; } - if (isEquivalent(candidate)) { - result = candidate; - return PROCESS_ABORT; + + private boolean isEquivalent(IASTName candidate) { + return CharArrayUtils.equals(candidate.getSimpleID(), toFindName) && bindingToFind.equals(index.adaptBinding(candidate.resolveBinding())); + } + + public List getMatches() { + return results; } - return PROCESS_CONTINUE; } - private boolean isEquivalent(IASTName candidate) { - return matchesIndexName(candidate) && bindingToFind.equals(index.adaptBinding(candidate.resolveBinding())); - } + private static class IndexNameToAstNameMatcher extends ASTVisitor { + private IASTName result; + private IBinding bindingToFind; + private char[] charNameToFind; + private IIndex index; + private IASTFileLocation locationToFind; - private boolean matchesIndexName(IASTName candidate) { - IASTFileLocation candidateLocation = candidate.getFileLocation(); - return locationToFind.getNodeOffset() == candidateLocation.getNodeOffset() && - locationToFind.getNodeLength() == candidateLocation.getNodeLength() && - locationToFind.getFileName().equals(candidateLocation.getFileName()) && - CharArrayUtils.equals(candidate.getLookupKey(), charNameToFind); - } + public IndexNameToAstNameMatcher(IASTTranslationUnit tu, IIndexName indexName, IIndex index) + throws CoreException { + super(true); + locationToFind = indexName.getFileLocation(); + bindingToFind = index.findBinding(indexName); + this.index = index; + charNameToFind = bindingToFind.getNameCharArray(); + shouldVisitImplicitNames = true; + shouldVisitImplicitNameAlternates = true; + } - public IASTName getMatch() { - return result; - } -} - -class BindingToAstNameMatcher extends ASTVisitor { - private List results = new ArrayList<>(); - private IBinding bindingToFind; - private char[] toFindName; - private IIndex index; - - public BindingToAstNameMatcher(IBinding binding, IIndex index) { - super(true); - bindingToFind = index.adaptBinding(binding); - this.index = index; - toFindName = binding.getNameCharArray(); - shouldVisitImplicitNames = true; - shouldVisitImplicitNameAlternates = true; - } - - @Override - public int visit(IASTName candidate) { - if (!IndexToASTNameHelper.shouldConsiderName(candidate)) { + @Override + public int visit(IASTName candidate) { + if (!IndexToASTNameHelper.shouldConsiderName(candidate)) { + return PROCESS_CONTINUE; + } + if (isEquivalent(candidate)) { + result = candidate; + return PROCESS_ABORT; + } return PROCESS_CONTINUE; } - if (isEquivalent(candidate)) { - results.add(candidate); + + private boolean isEquivalent(IASTName candidate) { + return matchesIndexName(candidate) && bindingToFind.equals(index.adaptBinding(candidate.resolveBinding())); } - return PROCESS_CONTINUE; - } - private boolean isEquivalent(IASTName candidate) { - return CharArrayUtils.equals(candidate.getSimpleID(), toFindName) && bindingToFind.equals(index.adaptBinding(candidate.resolveBinding())); - } + private boolean matchesIndexName(IASTName candidate) { + IASTFileLocation candidateLocation = candidate.getFileLocation(); + return locationToFind.getNodeOffset() == candidateLocation.getNodeOffset() && + locationToFind.getNodeLength() == candidateLocation.getNodeLength() && + locationToFind.getFileName().equals(candidateLocation.getFileName()) && + CharArrayUtils.equals(candidate.getSimpleID(), charNameToFind); + } - public List getMatches() { - return results; + public IASTName getMatch() { + return result; + } } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.java index 1b483e2b563..df54cac45c0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2012 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2014 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 @@ -15,8 +15,6 @@ package org.eclipse.cdt.internal.ui.refactoring; import org.eclipse.osgi.util.NLS; final class Messages extends NLS { - public static String DeleteFileChange_0; - public static String DeleteFileChange_1; public static String Refactoring_name; public static String Refactoring_PM_LoadTU; public static String Refactoring_PM_CheckTU; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.properties index a27e2df95df..2a8c5f7ba24 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2008, 2012 Institute for Software, HSR Hochschule fuer Technik +# Copyright (c) 2008, 2014 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 @@ -10,8 +10,6 @@ # Institute for Software - initial API and implementation # Sergey Prigogin (Google) ############################################################################### -DeleteFileChange_0=Delete File -DeleteFileChange_1=File doesn't exist. Refactoring_name=Refactoring Refactoring_PM_LoadTU=Load Translation Unit Refactoring_PM_CheckTU=Check Translation Unit @@ -21,9 +19,6 @@ Refactoring_PM_MergeComments=Merge Comments Refactoring_CanceledByUser=Refactoring canceled by user. Refactoring_CompileErrorInTU=The translation unit contains one or several problems. This can be caused by a syntax error in the code or a parser flaw. The refactoring will possibly fail. AddDeclarationNodeToClassChange_AddDeclaration=Add Declaration to Class {0}. -CreateFileChange_CreateFile=Create file: {0} -CreateFileChange_UnknownLoc=Unknown location: {0} -CreateFileChange_FileExists=File already exists: {0} CRefactoring_FileNotFound=The file {0} is not on the build path of a C/C++ project. CRefactoring_checking_final_conditions=Checking preconditions... CRefactoringDescriptor_unknown_project=Project ''{0}'' does not exist or is not a C/C++ project. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/ModificationCollector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/ModificationCollector.java index b1da07702fd..328072de88c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/ModificationCollector.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/ModificationCollector.java @@ -25,6 +25,9 @@ import org.eclipse.ltk.core.refactoring.CompositeChange; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.cdt.internal.ui.refactoring.changes.CCompositeChange; +import org.eclipse.cdt.internal.ui.refactoring.changes.CreateFileChange; + /** * A ModificationCollector can be passed through a refactoring and manages the rewriters * and additional changes a refactoring can create. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/AbstractCElementRenameChange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/AbstractCElementRenameChange.java new file mode 100644 index 00000000000..6fe9a39f578 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/AbstractCElementRenameChange.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2000, 2014 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.changes; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.resource.ResourceChange; + +import org.eclipse.cdt.core.model.CoreModel; + +public abstract class AbstractCElementRenameChange extends ResourceChange { + private final String fNewName; + private final String fOldName; + private final IPath fResourcePath; + private final long fStampToRestore; + + protected AbstractCElementRenameChange(IPath resourcePath, String oldName, String newName) { + this(resourcePath, oldName, newName, IResource.NULL_STAMP); + } + + protected AbstractCElementRenameChange(IPath resourcePath, String oldName, String newName, long stampToRestore) { + Assert.isNotNull(newName, "new name"); //$NON-NLS-1$ + Assert.isNotNull(oldName, "old name"); //$NON-NLS-1$ + fResourcePath= resourcePath; + fOldName= oldName; + fNewName= newName; + fStampToRestore= stampToRestore; + } + + protected abstract IPath createNewPath(); + + protected abstract Change createUndoChange(long stampToRestore) throws CoreException; + + protected abstract void doRename(IProgressMonitor pm) throws CoreException; + + @Override + public Object getModifiedElement() { + return CoreModel.getDefault().create(getResource()); + } + + @Override + protected IResource getModifiedResource() { + return getResource(); + } + + public String getNewName() { + return fNewName; + } + + public String getOldName() { + return fOldName; + } + + protected final IResource getResource() { + return ResourcesPlugin.getWorkspace().getRoot().findMember(fResourcePath); + } + + protected IPath getResourcePath() { + return fResourcePath; + } + + @Override + public final Change perform(IProgressMonitor pm) throws CoreException { + try { + pm.beginTask(Messages.AbstractCElementRenameChange_renaming, 1); + IResource resource= getResource(); + IPath newPath= createNewPath(); + Change result= createUndoChange(resource.getModificationStamp()); + doRename(new SubProgressMonitor(pm, 1)); + if (fStampToRestore != IResource.NULL_STAMP) { + IResource newResource= ResourcesPlugin.getWorkspace().getRoot().findMember(newPath); + newResource.revertModificationStamp(fStampToRestore); + } + return result; + } finally { + pm.done(); + } + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CCompositeChange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/CCompositeChange.java similarity index 96% rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CCompositeChange.java rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/CCompositeChange.java index 27b668eb970..689ba2ea204 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CCompositeChange.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/CCompositeChange.java @@ -9,7 +9,7 @@ * Contributors: * Institute for Software (IFS)- initial API and implementation ******************************************************************************/ -package org.eclipse.cdt.internal.ui.refactoring; +package org.eclipse.cdt.internal.ui.refactoring.changes; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.ChangeDescriptor; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CreateFileChange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/CreateFileChange.java similarity index 80% rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CreateFileChange.java rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/CreateFileChange.java index 5b8f2990760..aa9d6b3a0ad 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CreateFileChange.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/CreateFileChange.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2014 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 @@ -10,7 +10,7 @@ * Institute for Software - initial API and implementation * Sergey Prigogin (Google) *******************************************************************************/ -package org.eclipse.cdt.internal.ui.refactoring; +package org.eclipse.cdt.internal.ui.refactoring.changes; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -30,7 +30,8 @@ import org.eclipse.ltk.core.refactoring.resource.ResourceChange; import org.eclipse.osgi.util.NLS; /** - * A Change for creating a new file with the given name, content and encoding at the specified path. + * A {@link Change} for creating a new file with the given name, content and encoding at + * the specified path. * * @author Emanuel Graf */ @@ -60,7 +61,7 @@ public class CreateFileChange extends ResourceChange { @Override public String getName() { if (name == null) { - return NLS.bind(Messages.CreateFileChange_CreateFile, path.toOSString()); + return NLS.bind(Messages.CreateFileChange_create_file, path.toOSString()); } return name; } @@ -70,19 +71,18 @@ public class CreateFileChange extends ResourceChange { } @Override - public RefactoringStatus isValid(IProgressMonitor pm) - throws CoreException, OperationCanceledException { + public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException, OperationCanceledException { RefactoringStatus result= new RefactoringStatus(); IFile file= ResourcesPlugin.getWorkspace().getRoot().getFile(path); URI location= file.getLocationURI(); if (location == null) { - result.addFatalError(NLS.bind(Messages.CreateFileChange_UnknownLoc, file.getFullPath().toString())); + result.addFatalError(NLS.bind(Messages.CreateFileChange_unknown_location, file.getFullPath().toString())); return result; } if (file.exists()) { - result.addFatalError(NLS.bind(Messages.CreateFileChange_FileExists, file.getFullPath().toString())); + result.addFatalError(NLS.bind(Messages.CreateFileChange_file_exists, file.getFullPath().toString())); return result; } return result; @@ -94,7 +94,7 @@ public class CreateFileChange extends ResourceChange { InputStream is = new ByteArrayInputStream(source.getBytes()); file.create(is, false, new SubProgressMonitor(pm, 1)); if (encoding != null) { - file.setCharset(encoding, new SubProgressMonitor(pm,1)); + file.setCharset(encoding, new SubProgressMonitor(pm, 1)); } return new DeleteFileChange(file.getFullPath()); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/DeleteFileChange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/DeleteFileChange.java similarity index 76% rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/DeleteFileChange.java rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/DeleteFileChange.java index fead3c69dcb..02e06245842 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/DeleteFileChange.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/DeleteFileChange.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2014 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,9 +7,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Institute for Software - initial API and implementation + * Institute for Software - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ -package org.eclipse.cdt.internal.ui.refactoring; +package org.eclipse.cdt.internal.ui.refactoring.changes; import java.io.BufferedReader; import java.io.IOException; @@ -24,15 +25,14 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.osgi.util.NLS; /** - * The counterpart to the CreateFileChange, a change to delete a file. + * The counterpart to the {@link CreateFileChange}, a change to delete a file. * * @author Emanuel Graf - * */ public class DeleteFileChange extends Change { - private final IPath path; private String source; @@ -45,25 +45,22 @@ public class DeleteFileChange extends Change { return path; } - @Override public String getName() { - return Messages.DeleteFileChange_0 + path.toOSString(); + return NLS.bind(Messages.DeleteFileChange_delete_file, path.toOSString()); } - @Override public void initializeValidationData(IProgressMonitor pm) { // Nothing to do } @Override - public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException, - OperationCanceledException { + public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException, OperationCanceledException { RefactoringStatus status = new RefactoringStatus(); IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path); - if(!file.exists()) { - status.addFatalError(Messages.DeleteFileChange_1 + path.toString()); + if (!file.exists()) { + status.addFatalError(NLS.bind(Messages.DeleteFileChange_file_does_not_exist, path.toString())); } return status; } @@ -72,7 +69,7 @@ public class DeleteFileChange extends Change { String encoding= null; try { encoding= file.getCharset(); - } catch (CoreException ex) { + } catch (CoreException e) { // fall through. Take default encoding. } StringBuffer sb= new StringBuffer(); @@ -80,10 +77,11 @@ public class DeleteFileChange extends Change { InputStream in= null; try { in= file.getContents(); - if (encoding != null) + if (encoding != null) { br= new BufferedReader(new InputStreamReader(in, encoding)); - else - br= new BufferedReader(new InputStreamReader(in)); + } else { + br= new BufferedReader(new InputStreamReader(in)); + } int read= 0; while ((read= br.read()) != -1) { sb.append((char) read); @@ -100,8 +98,7 @@ public class DeleteFileChange extends Change { IFile file= ResourcesPlugin.getWorkspace().getRoot().getFile(path); source = getSource(file); Change undo = new CreateFileChange(file.getFullPath(), source, file.getCharset()); - file.delete(true,true, pm); + file.delete(true, true, pm); return undo; } - } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/Messages.java new file mode 100644 index 00000000000..322256989fb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/Messages.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 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.ui.refactoring.changes; + +import org.eclipse.osgi.util.NLS; + +final class Messages extends NLS { + public static String AbstractCElementRenameChange_renaming; + public static String CreateFileChange_create_file; + public static String CreateFileChange_unknown_location; + public static String CreateFileChange_file_exists; + public static String DeleteFileChange_delete_file; + public static String DeleteFileChange_file_does_not_exist; + public static String RenameTranslationUnitChange_name; + + static { + NLS.initializeMessages(Messages.class.getName(), Messages.class); + } + + // Do not instantiate. + private Messages() { + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/Messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/Messages.properties new file mode 100644 index 00000000000..cfb5ca7a63a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/Messages.properties @@ -0,0 +1,17 @@ +############################################################################### +# Copyright (c) 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 +############################################################################### +AbstractCElementRenameChange_renaming=Renaming... +CreateFileChange_create_file=Create file: {0} +CreateFileChange_unknown_location=Unknown location: {0} +CreateFileChange_file_exists=File already exists: {0} +DeleteFileChange_delete_file=Delete file: {0} +DeleteFileChange_file_does_not_exist=File {0} does not exist. +RenameTranslationUnitChange_name=Rename file ''{0}'' to ''{1}'' diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/RenameTranslationUnitChange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/RenameTranslationUnitChange.java new file mode 100644 index 00000000000..a7502340ae9 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/RenameTranslationUnitChange.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2000, 2014 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.changes; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.osgi.util.NLS; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ITranslationUnit; + +import org.eclipse.cdt.internal.ui.viewsupport.BasicElementLabels; + +public final class RenameTranslationUnitChange extends AbstractCElementRenameChange { + + public RenameTranslationUnitChange(ITranslationUnit tu, String newName) { + this(tu.getResource().getFullPath(), tu.getElementName(), newName, IResource.NULL_STAMP); + Assert.isTrue(!tu.isReadOnly(), "Translation unit must not be read-only"); //$NON-NLS-1$ + } + + private RenameTranslationUnitChange(IPath resourcePath, String oldName, String newName, long stampToRestore) { + super(resourcePath, oldName, newName, stampToRestore); + + setValidationMethod(VALIDATE_NOT_READ_ONLY | SAVE_IF_DIRTY); + } + + @Override + protected IPath createNewPath() { + IPath path= getResourcePath(); + return path.removeLastSegments(1).append(getNewName()); + } + + @Override + protected Change createUndoChange(long stampToRestore) throws CModelException { + return new RenameTranslationUnitChange(createNewPath(), getNewName(), getOldName(), stampToRestore); + } + + @Override + protected void doRename(IProgressMonitor pm) throws CoreException { + ITranslationUnit tu= (ITranslationUnit) getModifiedElement(); + if (tu != null) + tu.rename(getNewName(), false, pm); + } + + @Override + public String getName() { + return NLS.bind(Messages.RenameTranslationUnitChange_name, + BasicElementLabels.getCElementName(getOldName()), + BasicElementLabels.getCElementName(getNewName())); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/UndoCTextFileChange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/UndoCTextFileChange.java similarity index 84% rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/UndoCTextFileChange.java rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/UndoCTextFileChange.java index c2a0f002272..ed06449b223 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/UndoCTextFileChange.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/changes/UndoCTextFileChange.java @@ -1,15 +1,15 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 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 - * http://www.eclipse.org/legal/epl-v10.html + * Copyright (c) 2006, 2014 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 + * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: - * IBM Corporation - Initial API and implementation - * Markus Schorn (Wind River Systems) + * Contributors: + * IBM Corporation - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ -package org.eclipse.cdt.internal.ui.refactoring; +package org.eclipse.cdt.internal.ui.refactoring.changes; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; @@ -32,6 +32,8 @@ import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.core.model.TranslationUnit; +import org.eclipse.cdt.internal.ui.refactoring.DocumentAdapter; + /** * UndoCTextFileChange that uses a working copy in order to generate CModel events. * @author janees diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/dialogs/CreateFileChangePreview.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/dialogs/CreateFileChangePreview.java index 88b27d17af2..f9612b3f498 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/dialogs/CreateFileChangePreview.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/dialogs/CreateFileChangePreview.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2014 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,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Institute for Software - initial API and implementation + * Institute for Software - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.dialogs; @@ -27,26 +27,19 @@ import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.text.CSourceViewerConfiguration; import org.eclipse.cdt.internal.ui.editor.CSourceViewer; -import org.eclipse.cdt.internal.ui.refactoring.CreateFileChange; +import org.eclipse.cdt.internal.ui.refactoring.changes.CreateFileChange; import org.eclipse.cdt.internal.ui.text.CTextTools; import org.eclipse.cdt.internal.ui.util.ViewerPane; /** * @author Emanuel Graf - * */ public class CreateFileChangePreview implements IChangePreviewViewer { - private static class CreateFileChangePane extends ViewerPane{ - - /** - * @param parent - * @param style - */ + private static class CreateFileChangePane extends ViewerPane { public CreateFileChangePane(Composite parent, int style) { super(parent, style); } - } private CreateFileChangePane control; @@ -57,11 +50,14 @@ public class CreateFileChangePreview implements IChangePreviewViewer { public void createControl(Composite parent) { control = new CreateFileChangePane(parent, SWT.BORDER | SWT.FLAT); Dialog.applyDialogFont(control); - srcViewer= new CSourceViewer(control, null, null, false, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION, CUIPlugin.getDefault().getPreferenceStore()); + srcViewer= new CSourceViewer(control, null, null, false, + SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION, + CUIPlugin.getDefault().getPreferenceStore()); textTools = CUIPlugin.getDefault().getTextTools(); IPreferenceStore store= CUIPlugin.getDefault().getCombinedPreferenceStore(); - CSourceViewerConfiguration sourceViewerConfiguration = new CSourceViewerConfiguration(textTools.getColorManager(), store, null, textTools.getDocumentPartitioning()); - srcViewer.configure(sourceViewerConfiguration); + CSourceViewerConfiguration configuration = + new CSourceViewerConfiguration(textTools.getColorManager(), store, null, textTools.getDocumentPartitioning()); + srcViewer.configure(configuration); srcViewer.setEditable(false); control.setContent(srcViewer.getControl()); } @@ -85,5 +81,4 @@ public class CreateFileChangePreview implements IChangePreviewViewer { } } } - } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ParameterNamesInputPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ParameterNamesInputPage.java index 0de86606430..9bdf0727817 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ParameterNamesInputPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ParameterNamesInputPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2012 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2014 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 @@ -28,6 +28,9 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; import org.eclipse.text.edits.InsertEdit; import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.TextEdit; @@ -36,18 +39,16 @@ import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.refactoring.CTextFileChange; import org.eclipse.cdt.internal.ui.preferences.formatter.TranslationUnitPreview; -import org.eclipse.cdt.internal.ui.refactoring.CCompositeChange; import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; +import org.eclipse.cdt.internal.ui.refactoring.changes.CCompositeChange; import org.eclipse.cdt.internal.ui.refactoring.dialogs.ValidatingLabeledTextField; /** * InputPage used by the ImplementMethod refactoring if its necessary to enter additional parameter names. * * @author Mirko Stocker - * */ public class ParameterNamesInputPage extends UserInputWizardPage { - private static final int PREVIEW_UPDATE_DELAY = 500; private MethodToImplementConfig config; private TranslationUnitPreview translationUnitPreview; @@ -62,7 +63,6 @@ public class ParameterNamesInputPage extends UserInputWizardPage { @Override public void createControl(Composite parent) { - Composite superComposite = new Composite(parent, SWT.NONE); superComposite.setLayout(new GridLayout()); @@ -74,13 +74,11 @@ public class ParameterNamesInputPage extends UserInputWizardPage { validatingLabeledTextField.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); for (final ParameterInfo actParameterInfo : config.getParaHandler().getParameterInfos()) { - String type = actParameterInfo.getTypeName(); String content = actParameterInfo.getParameterName(); boolean readOnly = !actParameterInfo.hasNewName(); validatingLabeledTextField.addElement(type, content, readOnly, new ValidatingLabeledTextField.Validator(){ - @Override public void hasErrors() { setPageComplete(false); @@ -100,7 +98,6 @@ public class ParameterNamesInputPage extends UserInputWizardPage { } createPreview(superComposite); - setControl(superComposite); } @@ -141,7 +138,6 @@ public class ParameterNamesInputPage extends UserInputWizardPage { if (insertEdit == null) { return Messages.ImplementMethodRefactoringPage_PreviewGenerationNotPossible; } - return insertEdit.getText().trim(); } catch (OperationCanceledException e) { return Messages.ImplementMethodRefactoringPage_PreviewCanceled; @@ -165,15 +161,22 @@ public class ParameterNamesInputPage extends UserInputWizardPage { setPreviewText(functionDefinitionSignature); return Status.OK_STATUS; } + private void setPreviewText(final String text) { - if (getShell() != null && getShell().getDisplay() != null) { - getShell().getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - if (translationUnitPreview.getControl() != null && !translationUnitPreview.getControl().isDisposed()) { - translationUnitPreview.setPreviewText(text); + Shell shell = getShell(); + if (shell != null) { + Display display = shell.getDisplay(); + if (display != null) { + display.asyncExec(new Runnable() { + @Override + public void run() { + Control control = translationUnitPreview.getControl(); + if (control != null && !control.isDisposed()) { + translationUnitPreview.setPreviewText(text); + } } - }}); + }); + } } } }; @@ -214,21 +217,20 @@ public class ParameterNamesInputPage extends UserInputWizardPage { } protected void joinPreviewJob() { - if (delayedPreviewUpdater == null) { + if (delayedPreviewUpdater == null) return; - } try { delayedPreviewUpdater.join(); - } catch (InterruptedException e1) { - CUIPlugin.log(e1); + } catch (InterruptedException e) { + CUIPlugin.log(e); } } private void updatePreview() { - if (translationUnitPreview == null) { + if (translationUnitPreview == null) return; - } + delayedPreviewUpdater.schedule(PREVIEW_UPDATE_DELAY); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/ASTManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/ASTManager.java index dc470cbca9d..52bca6b0e7b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/ASTManager.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/ASTManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2012 Wind River Systems, Inc. and others. + * Copyright (c) 2005, 2014 Wind River Systems, 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 @@ -132,9 +132,10 @@ public class ASTManager implements IDisposable { public final static int FALSE= 0; public final static int UNKNOWN= -1; + // TODO(sprigogin): Replace fSharedAST and fTranslationUnits with CRefactoringContext. private IASTTranslationUnit fSharedAST; private Map fTranslationUnits= new HashMap<>(); - private HashSet fProblemUnits= new HashSet<>(); + private Set fProblemUnits= new HashSet<>(); private CRefactoringArgument fArgument; private IBinding[] fValidBindings; private String fRenameTo; @@ -836,7 +837,7 @@ public class ASTManager implements IDisposable { return; pm.beginTask(RenameMessages.ASTManager_task_analyze, 2); - IASTTranslationUnit tu= getTranslationUnit(index, fArgument.getSourceFile(), true, status); + IASTTranslationUnit tu= getAST(index, fArgument.getSourceFile(), true, status); pm.worked(1); if (tu != null) { final IASTNodeSelector nodeSelector = tu.getNodeSelector(tu.getFilePath()); @@ -912,8 +913,20 @@ public class ASTManager implements IDisposable { return rawSignature.substring(offset, end); } - private IASTTranslationUnit getTranslationUnit(IIndex index, IFile sourceFile, boolean cacheit, - RefactoringStatus status) { + /** + * Returns an AST for the given file. + * + * @param index the index to use for the AST + * @param sourceFile the source file to obtain an AST for + * @param astStyle the style to pass to {@link ITranslationUnit#getAST(IIndex, int)} method. + * If a previously cached AST is returned, the style is not guaranteed to match + * the requested one. + * @param cacheIt if {@code true}, the AST will be cached for later reuse + * @return the requested AST or {@code null} + * @throws CoreException + */ + public synchronized IASTTranslationUnit getAST(IIndex index, IFile sourceFile, int astStyle, + boolean cacheIt) throws CoreException { IASTTranslationUnit ast= fTranslationUnits.get(sourceFile); if (ast == null) { ICElement celem= CoreModel.getDefault().create(sourceFile); @@ -925,20 +938,16 @@ public class ASTManager implements IDisposable { // Try to get a shared AST before creating our own. ast = ASTProvider.getASTProvider().acquireSharedAST(tu, index, ASTProvider.WAIT_ACTIVE_ONLY, null); - if (ast == null) { - try { - ast= tu.getAST(index, PARSE_MODE); - } catch (CoreException e) { - status.addError(e.getMessage()); - } - if (cacheit) { - fTranslationUnits.put(sourceFile, ast); - } - } else { + if (ast != null) { if (fSharedAST != null) { ASTProvider.getASTProvider().releaseSharedAST(fSharedAST); } fSharedAST = ast; + } else { + ast= tu.getAST(index, astStyle); + if (cacheIt) { + fTranslationUnits.put(sourceFile, ast); + } } } } @@ -946,7 +955,17 @@ public class ASTManager implements IDisposable { return ast; } - public void analyzeTextMatches(IIndex index, Collection matches, + private IASTTranslationUnit getAST(IIndex index, IFile sourceFile, boolean cacheIt, + RefactoringStatus status) { + try { + return getAST(index, sourceFile, PARSE_MODE, cacheIt); + } catch (CoreException e) { + status.addError(e.getMessage()); + return null; + } + } + + public void analyzeTextMatches(IIndex index, Collection matches, IProgressMonitor monitor, RefactoringStatus status) { CRefactoringMatchStore store= new CRefactoringMatchStore(); for (CRefactoringMatch match : matches) { @@ -986,7 +1005,7 @@ public class ASTManager implements IDisposable { } if (doParse) { - IASTTranslationUnit tu= getTranslationUnit(index, file, false, status); + IASTTranslationUnit tu= getAST(index, file, false, status); monitor.worked(1); analyzeTextMatchesOfTranslationUnit(tu, store, status); if (status.hasFatalError()) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameClassProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameClassProcessor.java index c0bec58f65e..894a237d788 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameClassProcessor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameClassProcessor.java @@ -1,57 +1,206 @@ /******************************************************************************* - * Copyright (c) 2005, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2005, 2014 Wind River Systems, 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: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) ******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; import java.util.ArrayList; -import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +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.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.CompositeChange; import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.participants.RenameArguments; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.index.IIndexFileLocation; +import org.eclipse.cdt.core.index.IIndexInclude; +import org.eclipse.cdt.core.index.IIndexName; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.PreferenceConstants; + +import org.eclipse.cdt.internal.ui.editor.SourceHeaderPartnerFinder; +import org.eclipse.cdt.internal.ui.refactoring.changes.CCompositeChange; +import org.eclipse.cdt.internal.ui.refactoring.changes.RenameTranslationUnitChange; +import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator; /** * Processor adding constructor and destructor to the bindings to be renamed. */ public class CRenameClassProcessor extends CRenameTypeProcessor { + private final List tuRenames = new ArrayList<>(); public CRenameClassProcessor(CRenameProcessor processor, String kind) { super(processor, kind); } - + + @Override + public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { + Change change = super.createChange(pm); + if (tuRenames.isEmpty()) + return change; + + CompositeChange compositeChange; + if (change instanceof CompositeChange) { + compositeChange = (CompositeChange) change; + } else { + compositeChange = new CCompositeChange(""); //$NON-NLS-1$ + compositeChange.markAsSynthetic(); + compositeChange.add(change); + } + for (Change tuRename : tuRenames) { + compositeChange.add(tuRename); + } + return compositeChange; + } + @Override protected IBinding[] getBindingsToBeRenamed(RefactoringStatus status) { + tuRenames.clear(); CRefactoringArgument argument= getArgument(); IBinding binding= argument.getBinding(); ArrayList bindings= new ArrayList<>(); if (binding != null) { + recordRename(binding); bindings.add(binding); } if (binding instanceof ICPPClassType) { ICPPClassType ctype= (ICPPClassType) binding; ICPPConstructor[] ctors= ctype.getConstructors(); if (ctors != null) { - bindings.addAll(Arrays.asList(ctors)); + ArrayUtil.addAll(bindings, ctors); } IScope scope= ctype.getCompositeScope(); if (scope != null) { IBinding[] dtors= scope.find("~" + argument.getName()); //$NON-NLS-1$ if (dtors != null) { - bindings.addAll(Arrays.asList(dtors)); + ArrayUtil.addAll(bindings, dtors); } } + + renameCompilationUnits(ctype); } return bindings.toArray(new IBinding[bindings.size()]); } + + private void renameCompilationUnits(ICPPBinding binding) { + IIndex index = getIndex(); + if (index == null) { + return; + } + try { + index.acquireReadLock(); + Set locations = new HashSet<>(); + IIndexName[] names = index.findNames(binding, IIndex.FIND_DEFINITIONS); + for (IIndexName name : names) { + locations.add(name.getFile().getLocation()); + } + if (locations.size() != 1) + return; + IIndexFileLocation location = locations.iterator().next(); + String fullPath = location.getFullPath(); + if (fullPath == null) + return; + IPath headerPath = new Path(fullPath); + String className = binding.getName(); + String headerName = NewSourceFileGenerator.generateHeaderFileNameFromClass(className); + if (!headerPath.lastSegment().equals(headerName)) + return; + IResource file = ResourcesPlugin.getWorkspace().getRoot().findMember(headerPath); + if (file == null || file.getType() != IResource.FILE) + return; + String newClassName = getReplacementText(); + String newHeaderName = NewSourceFileGenerator.generateHeaderFileNameFromClass(newClassName); + if (!newHeaderName.equals(headerName)) { + renameTranslationUnit((IFile) file, newHeaderName); + } + String sourceName = NewSourceFileGenerator.generateSourceFileNameFromClass(className); + String testName = NewSourceFileGenerator.generateTestFileNameFromClass(className); + String[] partnerFileSuffixes = getPartnerFileSuffixes(); + IIndexInclude[] includedBy = index.findIncludedBy(names[0].getFile()); + for (IIndexInclude include : includedBy) { + location = include.getIncludedByLocation(); + fullPath = location.getFullPath(); + if (fullPath == null) + continue; + IPath sourcePath = new Path(fullPath); + file = ResourcesPlugin.getWorkspace().getRoot().findMember(sourcePath); + if (file != null && file.getType() == IResource.FILE) { + if (sourcePath.lastSegment().equals(sourceName)) { + String newName = NewSourceFileGenerator.generateSourceFileNameFromClass(newClassName); + if (!newName.equals(sourceName)) { + renameTranslationUnit((IFile) file, newName); + } + } else if (sourcePath.lastSegment().equals(testName)) { + String newName = NewSourceFileGenerator.generateTestFileNameFromClass(newClassName); + file = ResourcesPlugin.getWorkspace().getRoot().findMember(sourcePath); + if (!newName.equals(testName)) { + renameTranslationUnit((IFile) file, newName); + } + } else if (SourceHeaderPartnerFinder.isPartnerFile(sourcePath, headerPath, partnerFileSuffixes)) { + String name = sourcePath.lastSegment(); + String baseName = headerPath.removeFileExtension().lastSegment(); + if (name.startsWith(baseName)) { + String newBaseName = new Path(headerName).removeFileExtension().lastSegment(); + String newName = newBaseName + name.substring(baseName.length()); + if (!newName.equals(name)) { + renameTranslationUnit((IFile) file, newName); + } + } + } + } + } + } catch (CoreException e) { + CUIPlugin.log(e); + return; + } catch (InterruptedException e) { + return; // Ignore. + } finally { + index.releaseReadLock(); + } + } + + protected void renameTranslationUnit(IFile file, String newName) { + ICElement elem = CoreModel.getDefault().create(file); + if (elem instanceof ITranslationUnit) { + tuRenames.add(new RenameTranslationUnitChange((ITranslationUnit) elem, newName)); + getRenameModifications().rename(file, new RenameArguments(newName, true)); + } + } + + private String[] getPartnerFileSuffixes() { + IFile file= getArgument().getSourceFile(); + IProject project = file == null ? null : file.getProject(); + String value = PreferenceConstants.getPreference( + PreferenceConstants.INCLUDES_PARTNER_FILE_SUFFIXES, project, ""); //$NON-NLS-1$ + return value.split(","); //$NON-NLS-1$ + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameMethodProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameMethodProcessor.java index e1f24fee771..9079f9d2f84 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameMethodProcessor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameMethodProcessor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2005, 2014 Wind River Systems, 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 @@ -102,6 +102,7 @@ public class CRenameMethodProcessor extends CRenameGlobalProcessor { IBinding binding= argument.getBinding(); ArrayList bindings= new ArrayList<>(); if (binding != null) { + recordRename(binding); bindings.add(binding); } if (binding instanceof ICPPMethod) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessor.java index 806ad2145a4..884a6983434 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2011 Wind River Systems, Inc. and others. + * Copyright (c) 2004, 2014 Wind River Systems, 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 @@ -11,10 +11,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -24,10 +20,7 @@ import org.eclipse.core.runtime.OperationCanceledException; 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.ParticipantManager; import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; -import org.eclipse.ltk.core.refactoring.participants.RenameArguments; -import org.eclipse.ltk.core.refactoring.participants.RenameParticipant; import org.eclipse.ltk.core.refactoring.participants.RenameProcessor; import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; import org.eclipse.osgi.util.NLS; @@ -37,7 +30,6 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.cdt.core.CCProjectNature; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CProjectNature; -import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.model.CoreModel; @@ -48,7 +40,10 @@ import org.eclipse.cdt.core.model.ICProject; * use and forwards further calls to the delegate. */ public class CRenameProcessor extends RenameProcessor { - public static final String IDENTIFIER= "org.eclips.cdt.refactoring.RenameProcessor"; //$NON-NLS-1$ + public static final String IDENTIFIER= "org.eclips.cdt.refactoring.RenameProcessor"; //$NON-NLS-1$ + + private static final String[] AFFECTED_PROJECT_NATURES = + { CCProjectNature.CC_NATURE_ID, CProjectNature.C_NATURE_ID }; private final CRefactoringArgument fArgument; private CRenameProcessorDelegate fDelegate; @@ -61,8 +56,6 @@ public class CRenameProcessor extends RenameProcessor { private IIndex fIndex; private int fIndexLockCount; private RefactoringStatus fInitialConditionsStatus; - - private Change fChange; public CRenameProcessor(CRefactory refactoringManager, CRefactoringArgument arg) { fManager= refactoringManager; @@ -186,38 +179,22 @@ public class CRenameProcessor extends RenameProcessor { @Override public RefactoringStatus checkFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException, OperationCanceledException { - return fDelegate.checkFinalConditions(pm, context); + return fDelegate.checkFinalConditions(pm, context); } @Override public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { - fChange = fDelegate.createChange(pm); - return fChange; - } - - /** - * @return the change if it has been created, or null otherwise. - */ - Change getChange() { - return fChange; + return fDelegate.createChange(pm); } @Override - public RefactoringParticipant[] loadParticipants(RefactoringStatus status, - SharableParticipants sharedParticipants) throws CoreException { - RenameArguments arguments= new RenameArguments(getReplacementText(), true); - final String[] natures= {CCProjectNature.CC_NATURE_ID, CProjectNature.C_NATURE_ID}; - List result= new ArrayList(); - IBinding binding= getArgument().getBinding(); - if (binding != null) { - result.addAll(Arrays.asList(ParticipantManager.loadRenameParticipants(status, - this, binding, arguments, natures, sharedParticipants))); - } - return result.toArray(new RefactoringParticipant[result.size()]); - } + public final RefactoringParticipant[] loadParticipants(RefactoringStatus status, + SharableParticipants shared) throws CoreException { + return fDelegate.getRenameModifications().loadParticipants(status, this, AFFECTED_PROJECT_NATURES, shared); + } /** - * Options for the input page in the refactoring wizard + * Options for the input page in the refactoring wizard. */ public int getAvailableOptions() { if (fDelegate == null) { @@ -227,7 +204,7 @@ public class CRenameProcessor extends RenameProcessor { } /** - * Options for the input page that trigger the preview + * Options for the input page that trigger the preview. */ public int getOptionsForcingPreview() { if (fDelegate == null) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessorDelegate.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessorDelegate.java index 05b583f4cc9..aef58c84802 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessorDelegate.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessorDelegate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2004, 2014 Wind River Systems, 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 @@ -24,6 +24,7 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -35,6 +36,8 @@ import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.TextEditChangeGroup; import org.eclipse.ltk.core.refactoring.TextFileChange; import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; +import org.eclipse.ltk.core.refactoring.participants.RenameArguments; +import org.eclipse.ltk.core.refactoring.participants.ResourceChangeChecker; import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker; import org.eclipse.osgi.util.NLS; import org.eclipse.text.edits.MultiTextEdit; @@ -53,6 +56,7 @@ import org.eclipse.cdt.ui.refactoring.CTextFileChange; public abstract class CRenameProcessorDelegate { private CRenameProcessor fTopProcessor; private ArrayList fMatches; + private final RenameModifications fRenameModifications = new RenameModifications(); protected String fProcessorBaseName; private int fAvailableOptions= CRefactory.OPTION_IN_CODE_REFERENCES | @@ -88,7 +92,7 @@ public abstract class CRenameProcessorDelegate { } final public int getSelectedOptions() { - return fTopProcessor.getSelectedOptions(); + return fTopProcessor.getSelectedOptions() & fAvailableOptions; } final public String getSelectedWorkingSet() { @@ -181,9 +185,7 @@ public abstract class CRenameProcessorDelegate { locations.add(name.getFile().getLocation()); } } - } catch (InterruptedException e) { - return files; - } catch (CoreException e) { + } catch (CoreException | InterruptedException e) { return files; } finally { index.releaseReadLock(); @@ -283,11 +285,17 @@ public abstract class CRenameProcessorDelegate { } result.addWarning(msg); } - IFile[] files= fileset.toArray(new IFile[fileset.size()]); if (context != null) { + ResourceChangeChecker checker = (ResourceChangeChecker) context.getChecker(ResourceChangeChecker.class); + IResourceChangeDescriptionFactory deltaFactory = checker.getDeltaFactory(); ValidateEditChecker editChecker= (ValidateEditChecker) context.getChecker(ValidateEditChecker.class); - editChecker.addFiles(files); + for (IFile changedFile : fileset) { + deltaFactory.change(changedFile); + editChecker.addFile(changedFile); + } + fRenameModifications.buildDelta(deltaFactory); + fRenameModifications.buildValidateEdits(editChecker); } monitor.done(); return result; @@ -373,15 +381,38 @@ public abstract class CRenameProcessorDelegate { return overallChange; } - /** + /** * Returns the array of bindings that must be renamed. */ protected IBinding[] getBindingsToBeRenamed(RefactoringStatus status) { - return new IBinding[] { getArgument().getBinding() }; + IBinding binding = getArgument().getBinding(); + recordRename(binding); + return new IBinding[] { binding }; } + /** + * Returns the modifications associated with the refactoring. + */ + public RenameModifications getRenameModifications() { + return fRenameModifications; + } + + protected void recordRename(IBinding binding) { + RenameArguments args = new RenameArguments(getReplacementText(), true); + RenameModifications renameModifications = getRenameModifications(); + renameModifications.rename(binding, args); + } + + protected void recordRename(IBinding[] bindings) { + RenameArguments args = new RenameArguments(getReplacementText(), true); + RenameModifications renameModifications = getRenameModifications(); + for (IBinding binding : bindings) { + renameModifications.rename(binding, args); + } + } + /** - * @return a save mode from {@link org.eclipse.cdt.internal.ui.refactoring.RefactoringSaveHelper} + * Returns a save mode from {@link org.eclipse.cdt.internal.ui.refactoring.RefactoringSaveHelper} */ public abstract int getSaveMode(); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoring.java index 9425d1fe1f6..9722dd62e91 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoring.java @@ -1,16 +1,20 @@ /******************************************************************************* - * Copyright (c) 2004, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2004, 2014 Wind River Systems, 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: - * Markus Schorn - initial API and implementation - * Sergey Prigogin (Google) + * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) ******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring; /** @@ -18,8 +22,27 @@ import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring; */ public class CRenameRefactoring extends ProcessorBasedRefactoring { public static final String ID = "org.eclipse.cdt.internal.ui.refactoring.rename.CRenameRefactoring"; //$NON-NLS-1$ + private Change fChange; public CRenameRefactoring(CRenameProcessor processor) { super(processor); } + + @Override + public CRenameProcessor getProcessor() { + return (CRenameProcessor) super.getProcessor(); + } + + @Override + public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { + fChange = super.createChange(pm); + return fChange; + } + + /** + * Returns the change if it has been created, or {@code null} otherwise. + */ + Change getChange() { + return fChange; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoringInputPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoringInputPage.java index d5ef17064ac..bd6d28edea6 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoringInputPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoringInputPage.java @@ -493,8 +493,8 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { } } } - + private CRenameProcessor getRenameProcessor() { - return (CRenameProcessor) ((CRenameRefactoring) getRefactoring()).getProcessor(); + return ((CRenameRefactoring) getRefactoring()).getProcessor(); } } 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 942e9187232..d15a526ad86 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 @@ -27,14 +27,16 @@ 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.MoveArguments; import org.eclipse.ltk.core.refactoring.participants.MoveParticipant; +import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; /** * Updates include statements and include guards in response to a file or a folder move. */ -public class HeaderFileMoveParticipant extends MoveParticipant { - private IResource movedResource; +public class HeaderFileMoveParticipant extends MoveParticipant implements ISharableParticipant { + private Map movedResources; private Change change; public HeaderFileMoveParticipant() { @@ -42,63 +44,80 @@ public class HeaderFileMoveParticipant extends MoveParticipant { @Override protected boolean initialize(Object element) { - if (element instanceof IResource) { - this.movedResource = (IResource) element; - return true; + addElement(element, getArguments()); + return movedResources != null; + } + + @Override + public void addElement(Object element, RefactoringArguments arguments) { + if (element instanceof IResource && arguments instanceof MoveArguments) { + if (movedResources == null) + movedResources = new HashMap<>(); + movedResources.put((IResource) element, (MoveArguments) arguments); } - return false; } @Override public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) throws OperationCanceledException { - MoveArguments args = getArguments(); - if (!args.getUpdateReferences()) - return null; - if (movedResource.isLinked()) - return null; - - Object destinationResource = args.getDestination(); - if (!(destinationResource instanceof IContainer)) - return null; - final IContainer destination = (IContainer) destinationResource; - final IPath destinationLocation = destination.getLocation(); - if (destinationLocation.equals(movedResource.getLocation().removeLastSegments(1))) - return null; - try { + if (movedResources == null) + return RefactoringStatus.create(Status.OK_STATUS); + // Maps the affected files to new, not yet existing, files. final Map movedFiles = new HashMap<>(); - if (movedResource instanceof IContainer) { - final int prefixLength = movedResource.getFullPath().segmentCount() - 1; - ((IContainer) movedResource).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(); - movedFiles.put(file, destination.getFile(file.getFullPath().removeFirstSegments(prefixLength))); - return false; + + for (Map.Entry entry : movedResources.entrySet()) { + IResource movedResource = entry.getKey(); + MoveArguments args = entry.getValue(); + if (!args.getUpdateReferences()) + continue; + if (movedResource.isLinked()) + continue; + + Object destinationResource = args.getDestination(); + if (!(destinationResource instanceof IContainer)) + continue; + final IContainer destination = (IContainer) destinationResource; + final IPath destinationLocation = destination.getLocation(); + if (destinationLocation.equals(movedResource.getLocation().removeLastSegments(1))) + continue; + + if (movedResource instanceof IContainer) { + final int prefixLength = movedResource.getFullPath().segmentCount() - 1; + ((IContainer) movedResource).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(); + movedFiles.put(file, destination.getFile(file.getFullPath().removeFirstSegments(prefixLength))); + return false; + } + return true; } - return true; - } - }, IResource.NONE); - } else if (movedResource instanceof IFile) { - IFile file = (IFile) movedResource; - movedFiles.put(file, destination.getFile(new Path(movedResource.getName()))); + }, IResource.NONE); + } else if (movedResource instanceof IFile) { + IFile file = (IFile) movedResource; + movedFiles.put(file, destination.getFile(new Path(movedResource.getName()))); + } } - - HeaderFileReferenceAdjuster includeAdjuster = new HeaderFileReferenceAdjuster(movedFiles); + + HeaderFileReferenceAdjuster includeAdjuster = + new HeaderFileReferenceAdjuster(movedFiles, 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; } 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 207e64b465c..f87ce5c3c74 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 @@ -10,9 +10,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; -import static org.eclipse.cdt.internal.ui.editor.ASTProvider.WAIT_ACTIVE_ONLY; -import static org.eclipse.cdt.internal.ui.editor.ASTProvider.getASTProvider; - import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; @@ -42,6 +39,7 @@ import org.eclipse.jface.text.IRegion; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.CompositeChange; import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; +import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor; import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker; import org.eclipse.text.edits.DeleteEdit; import org.eclipse.text.edits.InsertEdit; @@ -94,18 +92,21 @@ public class HeaderFileReferenceAdjuster { private final Map movedFiles; private final Map movedFilesByLocation; + private ASTManager astManager; private IIndex index; private int indexLockCount; /** * @param movedFiles keys are moved files, values are new, not yet existing, files + * @param processor the refactoring processor */ - public HeaderFileReferenceAdjuster(Map movedFiles) { + public HeaderFileReferenceAdjuster(Map movedFiles, 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.astManager = getASTManager(processor); } public Change createChange(CheckConditionsContext context, IProgressMonitor pm) @@ -116,6 +117,11 @@ public class HeaderFileReferenceAdjuster { IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); lockIndex(); + + ASTManager sharedASTManager = astManager; + if (astManager == null) + astManager = new ASTManager(null); + try { for (Entry entry : movedFiles.entrySet()) { IFile oldFile = entry.getKey(); @@ -156,7 +162,7 @@ public class HeaderFileReferenceAdjuster { for (IFile file : affectedFiles) { ITranslationUnit tu = (ITranslationUnit) coreModel.create(file); if (workingCopyManager.findSharedWorkingCopy(tu) != null) - continue; + continue; // Shared working copies have already been processed. addFileChange(tu, changes, checker, progress.newChild(1)); } @@ -165,6 +171,10 @@ public class HeaderFileReferenceAdjuster { change.markAsSynthetic(); } } finally { + if (astManager != sharedASTManager) { + astManager.dispose(); + astManager = null; + } unlockIndex(); pm.done(); } @@ -186,25 +196,11 @@ public class HeaderFileReferenceAdjuster { throws CoreException, OperationCanceledException { checkCanceled(pm); - IASTTranslationUnit sharedAst = null; - SubMonitor progress = SubMonitor.convert(pm, 2); try { - IASTTranslationUnit ast = - getASTProvider().acquireSharedAST(tu, index, WAIT_ACTIVE_ONLY, progress.newChild(1)); - if (ast == null) { - checkCanceled(pm); - ast= tu.getAST(index, PARSE_MODE); - if (ast == null) - return null; - } else { - sharedAst = ast; - } + IASTTranslationUnit ast = astManager.getAST(index, tu.getFile(), PARSE_MODE, false); return createEdit(ast, tu, progress.newChild(1)); } finally { - if (sharedAst != null) { - getASTProvider().releaseSharedAST(sharedAst); - } pm.done(); } } @@ -463,6 +459,13 @@ public class HeaderFileReferenceAdjuster { } } + private static ASTManager getASTManager(RefactoringProcessor processor) { + if (processor instanceof CRenameProcessor) { + return ((CRenameProcessor) processor).getAstManager(); + } + return null; + } + private static void checkCanceled(IProgressMonitor pm) throws OperationCanceledException { if (pm != null && pm.isCanceled()) throw new OperationCanceledException(); @@ -474,10 +477,10 @@ public class HeaderFileReferenceAdjuster { return false; IPreferencesService preferences = Platform.getPreferencesService(); IScopeContext[] scopes = PreferenceConstants.getPreferenceScopes(oldfile.getProject()); - int schema = preferences.getInt(CUIPlugin.PLUGIN_ID, + int scheme = preferences.getInt(CUIPlugin.PLUGIN_ID, PreferenceConstants.CODE_TEMPLATES_INCLUDE_GUARD_SCHEME, PreferenceConstants.CODE_TEMPLATES_INCLUDE_GUARD_SCHEME_FILE_NAME, scopes); - switch (schema) { + switch (scheme) { case PreferenceConstants.CODE_TEMPLATES_INCLUDE_GUARD_SCHEME_FILE_PATH: return true; 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 e4ab35e40ec..b8e2db6e4b1 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 @@ -28,14 +28,16 @@ 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 { - private IResource renamedResource; +public class HeaderFileRenameParticipant extends RenameParticipant implements ISharableParticipant { + private Map renamedResources; private Change change; public HeaderFileRenameParticipant() { @@ -43,60 +45,75 @@ public class HeaderFileRenameParticipant extends RenameParticipant { @Override protected boolean initialize(Object element) { - if (element instanceof IResource) { - this.renamedResource = (IResource) element; - return true; + 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); } - return false; } @Override public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) throws OperationCanceledException { - RenameArguments args = getArguments(); - if (!args.getUpdateReferences()) - return null; - if (renamedResource.isLinked()) - return null; - - String newName = args.getNewName(); - try { + if (renamedResources == null) + return RefactoringStatus.create(Status.OK_STATUS); + // Maps the affected files to new, not yet existing, files. final Map movedFiles = new HashMap<>(); - if (renamedResource instanceof IContainer) { - final IPath oldPath = renamedResource.getFullPath(); - final IPath newPath = oldPath.removeLastSegments(1).append(newName); - final IWorkspaceRoot workspaceRoot = renamedResource.getWorkspace().getRoot(); - ((IContainer) renamedResource).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; + + for (Map.Entry 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) { + final IPath oldPath = renamedResource.getFullPath(); + final IPath newPath = oldPath.removeLastSegments(1).append(newName); + final IWorkspaceRoot workspaceRoot = renamedResource.getWorkspace().getRoot(); + ((IContainer) renamedResource).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; } - return true; - } - }, IResource.NONE); - } else if (renamedResource instanceof IFile) { - IFile file = (IFile) renamedResource; - movedFiles.put(file, file.getParent().getFile(new Path(newName))); + }, 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); + HeaderFileReferenceAdjuster includeAdjuster = + new HeaderFileReferenceAdjuster(movedFiles, 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; } @@ -113,13 +130,12 @@ public class HeaderFileRenameParticipant extends RenameParticipant { } /** - * Replaces first few segments of the given path by the contents of another path. + * 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 - * @since 5.8 */ private static IPath replacePrefix(IPath path, int prefixLength, IPath newPrefix) { return newPrefix.append(path.removeFirstSegments(prefixLength)); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameModifications.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameModifications.java new file mode 100644 index 00000000000..de36c88c7ca --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameModifications.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2000, 2014 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.rename; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory; +import org.eclipse.core.runtime.Assert; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.participants.IParticipantDescriptorFilter; +import org.eclipse.ltk.core.refactoring.participants.ParticipantManager; +import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; +import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; +import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor; +import org.eclipse.ltk.core.refactoring.participants.RenameArguments; +import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; +import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker; + +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.model.ISourceRoot; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.parser.util.ArrayUtil; + +import org.eclipse.cdt.internal.corext.refactoring.participants.ResourceModifications; + +import org.eclipse.cdt.internal.ui.refactoring.reorg.RefactoringModifications; + +/** + * Stores objects renamed by the rename refactoring. + */ +public class RenameModifications extends RefactoringModifications { + private List fRename; + private List fRenameArguments; + private List fParticipantDescriptorFilter; + + public RenameModifications() { + fRename = new ArrayList<>(); + fRenameArguments = new ArrayList<>(); + fParticipantDescriptorFilter = new ArrayList<>(); + } + + public void rename(IBinding binding, RenameArguments args) { + add(binding, args, null); + } + + public void rename(IResource resource, RenameArguments args) { + add(resource, args, null); + } + + public void rename(ISourceRoot sourceFolder, RenameArguments arguments) { + add(sourceFolder, arguments, null); + if (sourceFolder.getResource() != null) { + getResourceModifications().addRename(sourceFolder.getResource(), arguments); + } + } + + public void rename(ITranslationUnit unit, RenameArguments args) { + add(unit, args, null); + if (unit.getResource() != null) { + getResourceModifications().addRename(unit.getResource(), new RenameArguments(args.getNewName(), args.getUpdateReferences())); + } + } + + @Override + public void buildDelta(IResourceChangeDescriptionFactory builder) { + for (int i = 0; i < fRename.size(); i++) { + Object element= fRename.get(i); + if (element instanceof IResource) { + ResourceModifications.buildMoveDelta(builder, (IResource) element, + (RenameArguments) fRenameArguments.get(i)); + } + } + getResourceModifications().buildDelta(builder); + } + + @Override + public void buildValidateEdits(ValidateEditChecker checker) { + for (Iterator iter = fRename.iterator(); iter.hasNext();) { + Object element = iter.next(); + if (element instanceof ITranslationUnit) { + ITranslationUnit unit = (ITranslationUnit) element; + IResource resource = unit.getResource(); + if (resource != null && resource.getType() == IResource.FILE) { + checker.addFile((IFile) resource); + } + } + } + } + + @Override + public RefactoringParticipant[] loadParticipants(RefactoringStatus status, RefactoringProcessor owner, + String[] natures, SharableParticipants shared) { + List result = new ArrayList<>(); + for (int i = 0; i < fRename.size(); i++) { + ArrayUtil.addAll(result, + ParticipantManager.loadRenameParticipants(status, + owner, fRename.get(i), + (RenameArguments) fRenameArguments.get(i), + fParticipantDescriptorFilter.get(i), + natures, shared)); + } + ArrayUtil.addAll(result, getResourceModifications().getParticipants(status, owner, natures, shared)); + return result.toArray(new RefactoringParticipant[result.size()]); + } + + private void add(Object element, RefactoringArguments args, IParticipantDescriptorFilter filter) { + Assert.isNotNull(element); + Assert.isNotNull(args); + fRename.add(element); + fRenameArguments.add(args); + fParticipantDescriptorFilter.add(filter); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameParticipantHelper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameParticipantHelper.java new file mode 100644 index 00000000000..92d54c46aa8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameParticipantHelper.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 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.ui.refactoring.rename; + +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.CompositeChange; +import org.eclipse.ltk.core.refactoring.TextChange; +import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; +import org.eclipse.text.edits.MultiTextEdit; +import org.eclipse.text.edits.TextEdit; + +/** + * Static methods used by rename and move participants. + */ +public class RenameParticipantHelper { + /** + * Consolidates the change produced by a refactoring participant with the one produced by + * the refactoring processor. If the two changes are be affecting the same files, the part of + * the refactoring participant's change that affects the files also modified by the refactoring + * processor is merged into the processor's change. The remaining part, if any, is returned from + * the method. + * + * @param change the change produced by a refactoring participant + * @param participant the refactoring participant + * @return the resulting change, or {@code null} + */ + public static Change postprocessParticipantChange(Change change, RefactoringParticipant participant) { + if (change == null) + return null; + CompositeChange compositeChange = change instanceof CompositeChange ? + (CompositeChange) change : null; + Change[] changes = compositeChange != null ? + compositeChange.getChildren() : new Change[] { change }; + for (Change ch : changes) { + if (ch instanceof TextChange) { + TextChange textChange = (TextChange) ch; + Object element = textChange.getModifiedElement(); + TextChange primaryChange = participant.getTextChange(element); + if (primaryChange != null) { + TextEdit edit = textChange.getEdit(); + addExplodedTextEdit(edit, primaryChange); + if (compositeChange != null) { + compositeChange.remove(ch); + } else { + change = null; + } + } + } + } + if (compositeChange != null && compositeChange.getChildren().length == 0) + change = null; + return change; + } + + private static void addExplodedTextEdit(TextEdit textEdit, TextChange primaryChange) { + if (textEdit instanceof MultiTextEdit) { + TextEdit[] children = ((MultiTextEdit) textEdit).removeChildren(); + for (TextEdit edit : children) { + addExplodedTextEdit(edit, primaryChange); + } + } else { + primaryChange.addEdit(textEdit); + } + } + + private RenameParticipantHelper() {} +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameSupport.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameSupport.java index df251517fbe..73da8c8309f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameSupport.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/RenameSupport.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2014 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 @@ -188,7 +188,7 @@ public class RenameSupport { wizard.setForcePreviewReview(mode != DialogMode.ALL_PAGES); } RefactoringStarter starter = new RefactoringStarter(); - CRenameProcessor processor = (CRenameProcessor) refactoring.getProcessor(); + CRenameProcessor processor = refactoring.getProcessor(); processor.lockIndex(); try { RefactoringStatus status = processor.checkInitialConditions(new NullProgressMonitor()); @@ -244,7 +244,7 @@ public class RenameSupport { return false; } - CRenameProcessor renameProcessor = getRenameProcessor(); + CRenameProcessor renameProcessor = fRefactoring.getProcessor(); renameProcessor.lockIndex(); try { fPreCheckStatus = renameProcessor.checkInitialConditions(new NullProgressMonitor()); @@ -261,7 +261,7 @@ public class RenameSupport { RefactoringExecutionHelper helper= new RefactoringExecutionHelper(fRefactoring, RefactoringCore.getConditionCheckingFailedSeverity(), renameProcessor.getSaveMode(), parent, context); - Change change = renameProcessor.getChange(); + Change change = fRefactoring.getChange(); Assert.isNotNull(change); helper.performChange(change, true); return true; @@ -280,10 +280,6 @@ public class RenameSupport { fRefactoring= new CRenameRefactoring(processor); } - private CRenameProcessor getRenameProcessor() { - return (CRenameProcessor) fRefactoring.getProcessor(); - } - /** * Creates a new rename support for the given {@link ICProject}. * diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/reorg/RefactoringModifications.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/reorg/RefactoringModifications.java new file mode 100644 index 00000000000..6c613139e57 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/reorg/RefactoringModifications.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2000, 2014 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.reorg; + +import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; +import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor; +import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; +import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker; + +import org.eclipse.cdt.internal.corext.refactoring.participants.ResourceModifications; + +public abstract class RefactoringModifications { + private ResourceModifications fResourceModifications; + + public RefactoringModifications() { + fResourceModifications= new ResourceModifications(); + } + + public ResourceModifications getResourceModifications() { + return fResourceModifications; + } + + public abstract RefactoringParticipant[] loadParticipants(RefactoringStatus status, + RefactoringProcessor owner, String[] natures, SharableParticipants shared); + + public abstract void buildDelta(IResourceChangeDescriptionFactory builder); + + /** + * Implementors add all resources that need a validate edit. + * + * @param checker the validate edit checker + */ + public void buildValidateEdits(ValidateEditChecker checker) { + // Default implementation does nothing. + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFileCreator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFileCreator.java index a6db3b126b5..a26d36cb550 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFileCreator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFileCreator.java @@ -24,7 +24,7 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.cdt.ui.CUIPlugin; -import org.eclipse.cdt.internal.ui.refactoring.CreateFileChange; +import org.eclipse.cdt.internal.ui.refactoring.changes.CreateFileChange; public class ToggleFileCreator { private static final String EMPTY_STRING = ""; //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java index 18f3399592a..8f83a24df08 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java @@ -2326,11 +2326,11 @@ public class PreferenceConstants { * the workspace setting should be taken. Note that passing {@code null} should be avoided. * @return Returns the node matching the given context. */ - private static IEclipsePreferences getPreferenceNode(String key, ICProject project) { + private static IEclipsePreferences getPreferenceNode(String key, IProject project) { IEclipsePreferences node = null; if (project != null) { - node = new ProjectScope(project.getProject()).getNode(CUIPlugin.PLUGIN_ID); + node = new ProjectScope(project).getNode(CUIPlugin.PLUGIN_ID); if (node.get(key, null) != null) { return node; } @@ -2348,6 +2348,19 @@ public class PreferenceConstants { return DefaultScope.INSTANCE.getNode(CUIPlugin.PLUGIN_ID); } + /** + * Returns the string value for the given key in the given context. + * + * @param key The preference key + * @param project The current context or {@code null} if no context is available and + * the workspace setting should be taken. Note that passing {@code null} should be avoided. + * @return Returns the current value for the string. + * @since 5.9 + */ + public static String getPreference(String key, IProject project) { + return getPreference(key, project, null); + } + /** * Returns the string value for the given key in the given context. * @@ -2358,7 +2371,21 @@ public class PreferenceConstants { * @since 5.0 */ public static String getPreference(String key, ICProject project) { - return getPreference(key, project, null); + return getPreference(key, project.getProject()); + } + + /** + * Returns the string value for the given key in the given context. + * + * @param key The preference key + * @param project The current context or {@code null} if no context is available and + * the workspace setting should be taken. Note that passing {@code null} should be avoided. + * @param defaultValue The default value if not specified in the preferences. + * @return Returns the current value of the preference. + * @since 5.9 + */ + public static String getPreference(String key, IProject project, String defaultValue) { + return getPreferenceNode(key, project).get(key, defaultValue); } /** @@ -2372,7 +2399,22 @@ public class PreferenceConstants { * @since 5.6 */ public static String getPreference(String key, ICProject project, String defaultValue) { - return getPreferenceNode(key, project).get(key, defaultValue); + return getPreference(key, project.getProject(), defaultValue); + } + + /** + * Returns the integer value for the given key in the given context. + * + * @param key The preference key + * @param project The current context or {@code null} if no context is available and + * the workspace setting should be taken. Note that passing {@code null} should + * be avoided. + * @param defaultValue The default value if not specified in the preferences. + * @return Returns the current value of the preference. + * @since 5.9 + */ + public static int getPreference(String key, IProject project, int defaultValue) { + return getPreferenceNode(key, project).getInt(key, defaultValue); } /** @@ -2387,7 +2429,21 @@ public class PreferenceConstants { * @since 5.1 */ public static int getPreference(String key, ICProject project, int defaultValue) { - return getPreferenceNode(key, project).getInt(key, defaultValue); + return getPreference(key, project.getProject(), defaultValue); + } + + /** + * Returns the boolean value for the given key in the given context. + * + * @param key The preference key + * @param project The current context or {@code null} if no context is available and + * the workspace setting should be taken. Note that passing {@code null} should be avoided. + * @param defaultValue The default value if not specified in the preferences. + * @return Returns the current value of the preference. + * @since 5.9 + */ + public static boolean getPreference(String key, IProject project, boolean defaultValue) { + return getPreferenceNode(key, project).getBoolean(key, defaultValue); } /** @@ -2401,7 +2457,7 @@ public class PreferenceConstants { * @since 5.1 */ public static boolean getPreference(String key, ICProject project, boolean defaultValue) { - return getPreferenceNode(key, project).getBoolean(key, defaultValue); + return getPreference(key, project.getProject(), defaultValue); } /** diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/CTextFileChange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/CTextFileChange.java index c8cf7e6e968..c938952ed36 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/CTextFileChange.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/CTextFileChange.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems and others. + * Copyright (c) 2006, 2014 Wind River 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 @@ -29,7 +29,7 @@ import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.internal.core.model.TranslationUnit; import org.eclipse.cdt.internal.ui.refactoring.DocumentAdapter; -import org.eclipse.cdt.internal.ui.refactoring.UndoCTextFileChange; +import org.eclipse.cdt.internal.ui.refactoring.changes.UndoCTextFileChange; /** * A TextFileChange that uses a working copy in order to generate CModel events. @@ -57,7 +57,7 @@ public class CTextFileChange extends TextFileChange { * @since 5.1 */ public CTextFileChange(String name, ITranslationUnit tu) { - super(name, getFile(tu)); + super(name, tu.getFile()); fTranslationUnit = tu; if (tu instanceof IWorkingCopy) fWorkingCopy = (IWorkingCopy) tu; @@ -102,8 +102,4 @@ public class CTextFileChange extends TextFileChange { protected Change createUndoChange(UndoEdit edit, ContentStamp stampToRestore) { return new UndoCTextFileChange(getName(), getFile(), edit, stampToRestore, getSaveMode()); } - - private static IFile getFile(ITranslationUnit tu) { - return (IFile) tu.getResource(); - } }