From 9488ed0ba8720513f281e554f8a91323b379d93d Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Thu, 13 Jan 2011 20:38:31 +0000 Subject: [PATCH] Added proper interaction between Generate Getters and Setters refactoring and team provider. --- .../ui/refactoring/CRefactoring2.java | 32 +++- .../cdt/internal/ui/refactoring/Messages.java | 1 + .../ui/refactoring/Messages.properties | 1 + .../GenerateGettersAndSettersRefactoring.java | 30 +++- .../internal/ui/refactoring/utils/Checks.java | 151 ++++++++++++++++++ .../ui/refactoring/utils/Messages.java | 15 +- .../ui/refactoring/utils/messages.properties | 1 + .../ui/refactoring/actions/CRenameAction.java | 7 +- .../actions/RefactoringAction.java | 8 +- 9 files changed, 224 insertions(+), 22 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Checks.java diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring2.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring2.java index 4d33409cd33..cb2d941aaa2 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring2.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring2.java @@ -17,8 +17,10 @@ import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.Region; import org.eclipse.jface.viewers.ISelection; @@ -27,6 +29,9 @@ import org.eclipse.ltk.core.refactoring.Refactoring; import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor; import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; +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.cdt.core.dom.ast.ASTVisitor; @@ -162,9 +167,27 @@ public abstract class CRefactoring2 extends Refactoring { @Override public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { - return new RefactoringStatus(); + if (pm == null) + pm = new NullProgressMonitor(); + pm.beginTask(Messages.CRefactoring_checking_final_conditions, 6); + + CheckConditionsContext context = createCheckConditionsContext(); + RefactoringStatus result = checkFinalConditions(new SubProgressMonitor(pm, 5), context); + if (result.hasFatalError()) { + pm.done(); + return result; + } + if (pm.isCanceled()) + throw new OperationCanceledException(); + + result.merge(context.check(new SubProgressMonitor(pm, 1))); + pm.done(); + return result; } + protected abstract RefactoringStatus checkFinalConditions(IProgressMonitor subProgressMonitor, + CheckConditionsContext checkContext) throws CoreException, OperationCanceledException; + @Override public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { @@ -247,4 +270,11 @@ public abstract class CRefactoring2 extends Refactoring { }); return names; } + + private CheckConditionsContext createCheckConditionsContext() throws CoreException { + CheckConditionsContext result= new CheckConditionsContext(); + result.add(new ValidateEditChecker(getValidationContext())); + result.add(new ResourceChangeChecker()); + 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 881ec182586..13d0d67d2a4 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 @@ -30,6 +30,7 @@ public final class Messages extends NLS { public static String CreateFileChange_UnknownLoc; public static String CreateFileChange_FileExists; public static String CRefactoring_FileNotFound; + public static String CRefactoring_checking_final_conditions; public static String Refactoring_SelectionNotValid; public static String Refactoring_CantLoadTU; public static String Refactoring_Ambiguity; 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 ba6dbe706c6..6ae45bc3622 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 @@ -25,6 +25,7 @@ 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... Refactoring_SelectionNotValid=Selection is not valid. Refactoring_CantLoadTU=Can not load translation unit. Refactoring_Ambiguity=Translation unit is ambiguous. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java index b5918e39ec0..af2c97bab8d 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java @@ -15,6 +15,7 @@ package org.eclipse.cdt.internal.ui.refactoring.gettersandsetters; import java.util.ArrayList; import java.util.List; +import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; @@ -22,6 +23,7 @@ import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.ASTVisitor; @@ -50,6 +52,7 @@ import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; import org.eclipse.cdt.internal.ui.refactoring.RefactoringASTCache; import org.eclipse.cdt.internal.ui.refactoring.implementmethod.InsertLocation2; import org.eclipse.cdt.internal.ui.refactoring.implementmethod.MethodDefinitionInsertLocationFinder2; +import org.eclipse.cdt.internal.ui.refactoring.utils.Checks; import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper; import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum; @@ -114,17 +117,32 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring2 { } @Override - public RefactoringStatus checkFinalConditions(IProgressMonitor pm) - throws CoreException, OperationCanceledException { - RefactoringStatus finalStatus = null; - finalStatus = super.checkFinalConditions(pm); + public RefactoringStatus checkFinalConditions(IProgressMonitor pm, + CheckConditionsContext checkContext) throws CoreException, OperationCanceledException { + RefactoringStatus result = new RefactoringStatus(); if (!context.isImplementationInHeader()) { definitionInsertLocation = findInsertLocation(); if (definitionInsertLocation == null || tu.equals(definitionInsertLocation.getTranslationUnit())) { - finalStatus.addInfo(Messages.GenerateGettersAndSettersRefactoring_NoImplFile); + result.addInfo(Messages.GenerateGettersAndSettersRefactoring_NoImplFile); } } - return finalStatus; + Checks.addModifiedFilesToChecker(getAllFilesToModify(), checkContext); + return result; + } + + private IFile[] getAllFilesToModify() { + List files = new ArrayList(2); + IFile file = (IFile) tu.getResource(); + if (file != null) { + files.add(file); + } + if (definitionInsertLocation != null) { + file = definitionInsertLocation.getFile(); + if (file != null) { + files.add(file); + } + } + return files.toArray(new IFile[files.size()]); } private void initRefactoring(IProgressMonitor pm) throws OperationCanceledException, CoreException { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Checks.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Checks.java new file mode 100644 index 00000000000..49a98e82c15 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Checks.java @@ -0,0 +1,151 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 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.utils; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourceAttributes; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; +import org.eclipse.ltk.core.refactoring.participants.ResourceChangeChecker; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ITranslationUnit; + +import org.eclipse.cdt.internal.corext.util.CModelUtil; +import org.eclipse.cdt.internal.corext.util.Resources; + +/** + * This class defines a set of reusable static checks methods. + */ +public class Checks { + + /* + * no instances + */ + private Checks(){ + } + + public static boolean startsWithUpperCase(String s) { + if (s == null) { + return false; + } else if ("".equals(s)) { //$NON-NLS-1$ + return false; + } else { + // Workaround for JDK bug (see 26529) + return s.charAt(0) == Character.toUpperCase(s.charAt(0)); + } + } + + public static boolean startsWithLowerCase(String s){ + if (s == null) { + return false; + } else if ("".equals(s)) { //$NON-NLS-1$ + return false; + } else { + // Workaround for JDK bug (see 26529) + return s.charAt(0) == Character.toLowerCase(s.charAt(0)); + } + } + + public static boolean resourceExists(IPath resourcePath){ + return ResourcesPlugin.getWorkspace().getRoot().findMember(resourcePath) != null; + } + + public static boolean isReadOnly(Object element) throws CModelException { + if (element instanceof IResource) + return isReadOnly((IResource) element); + + if (element instanceof ICElement) { + return isReadOnly(((ICElement) element).getResource()); + } + + Assert.isTrue(false, "Not expected to get here"); //$NON-NLS-1$ + return false; + } + + public static boolean isReadOnly(IResource res) throws CModelException { + ResourceAttributes attributes= res.getResourceAttributes(); + if (attributes != null && attributes.isReadOnly()) + return true; + + if (! (res instanceof IContainer)) + return false; + + IContainer container= (IContainer)res; + IResource[] children; + try { + children = container.members(); + for (int i= 0; i < children.length; i++) { + if (isReadOnly(children[i])) + return true; + } + } catch (CModelException e){ + throw e; + } catch (CoreException e) { + throw new CModelException(e); + } + return false; + } + + //-------- validateEdit checks ---- + + public static RefactoringStatus validateModifiesFiles(IFile[] filesToModify, Object context) { + RefactoringStatus result= new RefactoringStatus(); + IStatus status= Resources.checkInSync(filesToModify); + if (!status.isOK()) + result.merge(RefactoringStatus.create(status)); + status= Resources.makeCommittable(filesToModify, context); + if (!status.isOK()) { + result.merge(RefactoringStatus.create(status)); + if (!result.hasFatalError()) { + result.addFatalError(Messages.Checks_validateEdit); + } + } + return result; + } + + public static void addModifiedFilesToChecker(IFile[] filesToModify, CheckConditionsContext context) { + ResourceChangeChecker checker= (ResourceChangeChecker) context.getChecker(ResourceChangeChecker.class); + IResourceChangeDescriptionFactory deltaFactory= checker.getDeltaFactory(); + + for (int i= 0; i < filesToModify.length; i++) { + deltaFactory.change(filesToModify[i]); + } + } + + public static RefactoringStatus validateEdit(ITranslationUnit tu, Object context) { + IResource resource= CModelUtil.toOriginal(tu).getResource(); + RefactoringStatus result= new RefactoringStatus(); + if (resource == null) + return result; + IStatus status= Resources.checkInSync(resource); + if (!status.isOK()) + result.merge(RefactoringStatus.create(status)); + status= Resources.makeCommittable(resource, context); + if (!status.isOK()) { + result.merge(RefactoringStatus.create(status)); + if (!result.hasFatalError()) { + result.addFatalError(Messages.Checks_validateEdit); + } + } + return result; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.java index 14187b3f0b7..b3118c73264 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2011 Institute for Software, HSR Hochschule fuer Technik * Rapperswil, University of applied sciences and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -7,7 +7,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Institute for Software - initial API and implementation + * Institute for Software - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.utils; @@ -15,13 +16,8 @@ package org.eclipse.cdt.internal.ui.refactoring.utils; import org.eclipse.osgi.util.NLS; public final class Messages extends NLS { - private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.refactoring.utils.messages";//$NON-NLS-1$ - private Messages() { - // Do not instantiate - } - public static String IdentifierHelper_isKeyword; public static String IdentifierHelper_isValid; public static String IdentifierHelper_leadingDigit; @@ -31,6 +27,11 @@ public final class Messages extends NLS { public static String VisibilityEnum_public; public static String VisibilityEnum_protected; public static String VisibilityEnum_private; + public static String Checks_validateEdit; + + private Messages() { + // Do not instantiate + } static { NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/messages.properties index 3abcaae5acf..e57e90e9c57 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/messages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/messages.properties @@ -19,3 +19,4 @@ IdentifierHelper_unidentifiedMistake=''{0}'' contains an unidentified mistake. VisibilityEnum_public=public VisibilityEnum_protected=protected VisibilityEnum_private=private +Checks_validateEdit=Team provider refused file modification. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/CRenameAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/CRenameAction.java index 7ccca4a37c0..a32edc6cb3e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/CRenameAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/CRenameAction.java @@ -24,7 +24,6 @@ import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.internal.ui.actions.ActionUtil; -import org.eclipse.cdt.internal.ui.editor.CEditor; import org.eclipse.cdt.internal.ui.refactoring.rename.CRefactory; import org.eclipse.cdt.internal.ui.refactoring.rename.RenameLinkedMode; @@ -42,19 +41,19 @@ public class CRenameAction extends RefactoringAction { @Override public void run(IShellProvider shellProvider, ICElement elem) { - if (!ActionUtil.isEditable((CEditor) fEditor, shellProvider.getShell(), elem)) + if (!ActionUtil.isEditable(fEditor, shellProvider.getShell(), elem)) return; CRefactory.getInstance().rename(shellProvider.getShell(), elem); } @Override public void run(IShellProvider shellProvider, IWorkingCopy workingCopy, ITextSelection selection) { - if (!ActionUtil.isEditable((CEditor) fEditor)) + if (!ActionUtil.isEditable(fEditor)) return; IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); boolean lightweight= store.getBoolean(PreferenceConstants.REFACTOR_LIGHTWEIGHT); if (lightweight) { - new RenameLinkedMode((CEditor) fEditor).start(); + new RenameLinkedMode(fEditor).start(); } else { CRefactory.getInstance().rename(shellProvider.getShell(), workingCopy, selection); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/RefactoringAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/RefactoringAction.java index ce519bfbbb3..be59b665ea1 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/RefactoringAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/RefactoringAction.java @@ -17,12 +17,12 @@ import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.window.IShellProvider; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchSite; -import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.internal.ui.editor.CEditor; import org.eclipse.cdt.internal.ui.refactoring.utils.EclipseObjects; /** @@ -31,7 +31,7 @@ import org.eclipse.cdt.internal.ui.refactoring.utils.EclipseObjects; * @noextend This class is not intended to be subclassed by clients. */ public abstract class RefactoringAction extends Action { - protected ITextEditor fEditor; + protected CEditor fEditor; private IWorkbenchSite fSite; private ICElement fElement; private boolean saveRequired; @@ -53,8 +53,8 @@ public abstract class RefactoringAction extends Action { public void setEditor(IEditorPart editor) { fEditor= null; fSite= null; - if (editor instanceof ITextEditor) { - fEditor= (ITextEditor) editor; + if (editor instanceof CEditor) { + fEditor= (CEditor) editor; } setEnabled(fEditor != null); }