|
From: <mir...@us...> - 2007-04-25 10:14:06
|
Revision: 2361
http://svn.sourceforge.net/rubyeclipse/?rev=2361&view=rev
Author: mirkostocker
Date: 2007-04-25 03:14:02 -0700 (Wed, 25 Apr 2007)
Log Message:
-----------
add some infrastructure code (copied from JDT) to rename files and add a first attempt to rename the file if the renamed class has the same name. My plans are to implement a "rename file" refactoring that updates the 'require' statements. After that, we can start adding Rails specific extensions to refactorings, for example to rename view files if we rename a controller method.
Modified Paths:
--------------
trunk/org.rubypeople.rdt.refactoring/META-INF/MANIFEST.MF
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/action/RenameAction.java
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/Messages.java
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RubyRefactoring.java
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/messages.properties
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/rename/RenameRefactoring.java
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/renameclass/RenameClassRefactoring.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/IRubyStatusConstants.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/DynamicValidationStateChange.java
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RDTChange.java
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RenameResourceChange.java
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/Resources.java
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/WorkspaceTracker.java
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/renameclass/RenameClassFileNameChangeProvider.java
trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/editprovider/FileNameChangeProvider.java
Modified: trunk/org.rubypeople.rdt.refactoring/META-INF/MANIFEST.MF
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/META-INF/MANIFEST.MF 2007-04-21 00:29:10 UTC (rev 2360)
+++ trunk/org.rubypeople.rdt.refactoring/META-INF/MANIFEST.MF 2007-04-25 10:14:02 UTC (rev 2361)
@@ -62,7 +62,8 @@
org.eclipse.ui.editors,
org.rubypeople.rdt.core,
org.eclipse.compare,
- org.jruby
+ org.jruby,
+ org.eclipse.core.filesystem
Eclipse-LazyStart: true
Bundle-Vendor: %rubyRefactoring.providerName
Bundle-ClassPath: refactoring.jar
Modified: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/action/RenameAction.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/action/RenameAction.java 2007-04-21 00:29:10 UTC (rev 2360)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/action/RenameAction.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -32,8 +32,6 @@
public class RenameAction extends WorkbenchWindowActionDelegate {
- public static final Class[] renamableClasses = {};
-
@Override
public void run() {
run(RenameRefactoring.class, RenameRefactoring.NAME);
Added: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/DynamicValidationStateChange.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/DynamicValidationStateChange.java (rev 0)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/DynamicValidationStateChange.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -0,0 +1,116 @@
+package org.rubypeople.rdt.refactoring.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.SafeRunner;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.CompositeChange;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+
+public class DynamicValidationStateChange extends CompositeChange implements WorkspaceTracker.Listener {
+
+ private boolean fListenerRegistered= false;
+ private RefactoringStatus fValidationState= null;
+ private long fTimeStamp;
+
+ // 30 minutes
+ private static final long LIFE_TIME= 30 * 60 * 1000;
+
+ public DynamicValidationStateChange(Change change) {
+ super(change.getName());
+ add(change);
+ markAsSynthetic();
+ }
+
+ public DynamicValidationStateChange(String name) {
+ super(name);
+ markAsSynthetic();
+ }
+
+ public DynamicValidationStateChange(String name, Change[] changes) {
+ super(name, changes);
+ markAsSynthetic();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void initializeValidationData(IProgressMonitor pm) {
+ super.initializeValidationData(pm);
+ WorkspaceTracker.INSTANCE.addListener(this);
+ fListenerRegistered= true;
+ fTimeStamp= System.currentTimeMillis();
+ }
+
+ public void dispose() {
+ if (fListenerRegistered) {
+ WorkspaceTracker.INSTANCE.removeListener(this);
+ fListenerRegistered= false;
+ }
+ super.dispose();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException {
+ if (fValidationState == null) {
+ return super.isValid(pm);
+ }
+ return fValidationState;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Change perform(IProgressMonitor pm) throws CoreException {
+ final Change[] result= new Change[1];
+ IWorkspaceRunnable runnable= new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ result[0]= DynamicValidationStateChange.super.perform(monitor);
+ }
+ };
+ RubyCore.run(runnable, null, pm);
+ return result[0];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Change createUndoChange(Change[] childUndos) {
+ DynamicValidationStateChange result= new DynamicValidationStateChange(getName());
+ for (int i= 0; i < childUndos.length; i++) {
+ result.add(childUndos[i]);
+ }
+ return result;
+ }
+
+ public void workspaceChanged() {
+ long currentTime= System.currentTimeMillis();
+ if (currentTime - fTimeStamp < LIFE_TIME)
+ return;
+ fValidationState= RefactoringStatus.createFatalErrorStatus(Messages.DynamicValidationStateChange_workspace_changed);
+ // remove listener from workspace tracker
+ WorkspaceTracker.INSTANCE.removeListener(this);
+ fListenerRegistered= false;
+ // clear up the children to not hang onto too much memory
+ Change[] children= clear();
+ for (int i= 0; i < children.length; i++) {
+ final Change change= children[i];
+ SafeRunner.run(new ISafeRunnable() {
+ public void run() throws Exception {
+ change.dispose();
+ }
+ public void handleException(Throwable exception) {
+ RubyPlugin.log(exception);
+ }
+ });
+ }
+ }
+}
Modified: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/Messages.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/Messages.java 2007-04-21 00:29:10 UTC (rev 2360)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/Messages.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -1,5 +1,7 @@
package org.rubypeople.rdt.refactoring.core;
+import java.text.MessageFormat;
+
import org.eclipse.osgi.util.NLS;
public class Messages extends NLS {
@@ -10,11 +12,37 @@
public static String RefactoringConditionChecker_SyntaxErrorInCurrent;
public static String RefactoringConditionChecker_SyntaxErrorInProject;
+
+ public static String RenameResourceChange_name;
+
+ public static String RenameResourceChange_does_not_exist;
+
+ public static String RenameResourceChange_rename_resource;
+
+ public static String DynamicValidationStateChange_workspace_changed;
+
+ public static String Change_is_unsaved;
+
+ public static String Change_is_read_only;
+
+ public static String Change_same_read_only;
+
+ public static String Change_has_modifications;
+
+ public static String Change_does_not_exist;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
+ public static String format(String message, Object object) {
+ return MessageFormat.format(message, new Object[] { object});
+ }
+
+ public static String format(String message, Object[] objects) {
+ return MessageFormat.format(message, objects);
+ }
+
private Messages() {
}
}
Added: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RDTChange.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RDTChange.java (rev 0)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RDTChange.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -0,0 +1,254 @@
+package org.rubypeople.rdt.refactoring.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.filebuffers.ITextFileBufferManager;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension4;
+
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.rubypeople.rdt.core.IRubyElement;
+
+/**
+ * RDT specific change object, copied from the JDT
+ */
+public abstract class RDTChange extends Change {
+
+ private long fModificationStamp;
+ private boolean fReadOnly;
+
+ private static class ValidationState {
+ private IResource fResource;
+ private int fKind;
+ private boolean fDirty;
+ private boolean fReadOnly;
+ private long fModificationStamp;
+ private ITextFileBuffer fTextFileBuffer;
+ public static final int RESOURCE= 1;
+ public static final int DOCUMENT= 2;
+ public ValidationState(IResource resource) {
+ fResource= resource;
+ if (resource instanceof IFile) {
+ initializeFile((IFile)resource);
+ } else {
+ initializeResource(resource);
+ }
+ }
+ public void checkDirty(RefactoringStatus status, long stampToMatch, IProgressMonitor pm) throws CoreException {
+ if (fDirty) {
+ if (fKind == DOCUMENT && fTextFileBuffer != null && stampToMatch == fModificationStamp) {
+ fTextFileBuffer.commit(pm, false);
+ } else {
+ status.addFatalError(Messages.format(
+ Messages.Change_is_unsaved, fResource.getFullPath().toString()));
+ }
+ }
+ }
+ public void checkDirty(RefactoringStatus status) {
+ if (fDirty) {
+ status.addFatalError(Messages.format(
+ Messages.Change_is_unsaved, fResource.getFullPath().toString()));
+ }
+ }
+ public void checkReadOnly(RefactoringStatus status) {
+ if (fReadOnly) {
+ status.addFatalError(Messages.format(
+ Messages.Change_is_read_only, fResource.getFullPath().toString()));
+ }
+ }
+ public void checkSameReadOnly(RefactoringStatus status, boolean valueToMatch) {
+ if (fReadOnly != valueToMatch) {
+ status.addFatalError(Messages.format(
+ Messages.Change_same_read_only,
+ fResource.getFullPath().toString()));
+ }
+ }
+ public void checkModificationStamp(RefactoringStatus status, long stampToMatch) {
+ if (fKind == DOCUMENT) {
+ if (stampToMatch != IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP && fModificationStamp != stampToMatch) {
+ status.addFatalError(Messages.format(
+ Messages.Change_has_modifications, fResource.getFullPath().toString()));
+ }
+ } else {
+ if (stampToMatch != IResource.NULL_STAMP && fModificationStamp != stampToMatch) {
+ status.addFatalError(Messages.format(
+ Messages.Change_has_modifications, fResource.getFullPath().toString()));
+
+ }
+ }
+ }
+ private void initializeFile(IFile file) {
+ fTextFileBuffer= getBuffer(file);
+ if (fTextFileBuffer == null) {
+ initializeResource(file);
+ } else {
+ IDocument document= fTextFileBuffer.getDocument();
+ fDirty= fTextFileBuffer.isDirty();
+ fReadOnly= Resources.isReadOnly(file);
+ if (document instanceof IDocumentExtension4) {
+ fKind= DOCUMENT;
+ fModificationStamp= ((IDocumentExtension4)document).getModificationStamp();
+ } else {
+ fKind= RESOURCE;
+ fModificationStamp= file.getModificationStamp();
+ }
+ }
+
+ }
+ private void initializeResource(IResource resource) {
+ fKind= RESOURCE;
+ fDirty= false;
+ fReadOnly= Resources.isReadOnly(resource);
+ fModificationStamp= resource.getModificationStamp();
+ }
+ }
+
+ protected static final int NONE= 0;
+ protected static final int READ_ONLY= 1 << 0;
+ protected static final int DIRTY= 1 << 1;
+ private static final int SAVE= 1 << 2;
+ protected static final int SAVE_IF_DIRTY= SAVE | DIRTY;
+
+ protected RDTChange() {
+ fModificationStamp= IResource.NULL_STAMP;
+ fReadOnly= false;
+ }
+
+ public void initializeValidationData(IProgressMonitor pm) {
+ IResource resource= getResource(getModifiedElement());
+ if (resource != null) {
+ fModificationStamp= getModificationStamp(resource);
+ fReadOnly= Resources.isReadOnly(resource);
+ }
+ }
+
+ // protected final RefactoringStatus isValid(IProgressMonitor pm, boolean checkReadOnly, boolean checkDirty) throws CoreException {
+ protected final RefactoringStatus isValid(IProgressMonitor pm, int flags) throws CoreException {
+ pm.beginTask("", 2); //$NON-NLS-1$
+ try {
+ RefactoringStatus result= new RefactoringStatus();
+ Object modifiedElement= getModifiedElement();
+ checkExistence(result, modifiedElement);
+ if (result.hasFatalError())
+ return result;
+ if (flags == NONE)
+ return result;
+ IResource resource= getResource(modifiedElement);
+ if (resource != null) {
+ ValidationState state= new ValidationState(resource);
+ state.checkModificationStamp(result, fModificationStamp);
+ if (result.hasFatalError())
+ return result;
+ state.checkSameReadOnly(result, fReadOnly);
+ if (result.hasFatalError())
+ return result;
+ if ((flags & READ_ONLY) != 0) {
+ state.checkReadOnly(result);
+ if (result.hasFatalError())
+ return result;
+ }
+ if ((flags & DIRTY) != 0) {
+ if ((flags & SAVE) != 0) {
+ state.checkDirty(result, fModificationStamp, new SubProgressMonitor(pm, 1));
+ } else {
+ state.checkDirty(result);
+ }
+ }
+ }
+ return result;
+ } finally {
+ pm.done();
+ }
+ }
+
+ protected final RefactoringStatus isValid(int flags) throws CoreException {
+ return isValid(new NullProgressMonitor(), flags);
+ }
+
+ protected static void checkIfModifiable(RefactoringStatus status, Object element, int flags) {
+ checkIfModifiable(status, getResource(element), flags);
+ }
+
+ protected static void checkIfModifiable(RefactoringStatus result, IResource resource, int flags) {
+ checkExistence(result, resource);
+ if (result.hasFatalError())
+ return;
+ if (flags == NONE)
+ return;
+ ValidationState state= new ValidationState(resource);
+ if ((flags & READ_ONLY) != 0) {
+ state.checkReadOnly(result);
+ if (result.hasFatalError())
+ return;
+ }
+ if ((flags & DIRTY) != 0) {
+ state.checkDirty(result);
+ }
+ }
+
+ protected static void checkExistence(RefactoringStatus status, Object element) {
+ if (element == null) {
+ status.addFatalError(Messages.DynamicValidationStateChange_workspace_changed);
+
+ } else if (element instanceof IResource && !((IResource)element).exists()) {
+ status.addFatalError(Messages.format(
+ Messages.Change_does_not_exist, ((IResource)element).getFullPath().toString()));
+ } else if (element instanceof IRubyElement && !((IRubyElement)element).exists()) {
+ status.addFatalError(Messages.format(
+ Messages.Change_does_not_exist, ((IRubyElement)element).getElementName()));
+ }
+ }
+
+ private static IResource getResource(Object element) {
+ if (element instanceof IResource) {
+ return (IResource)element;
+ }
+ /*if (element instanceof ICompilationUnit) {
+ return ((ICompilationUnit)element).getPrimary().getResource();
+ }*/
+ if (element instanceof IRubyElement) {
+ return ((IRubyElement)element).getResource();
+ }
+ if (element instanceof IAdaptable) {
+ return (IResource)((IAdaptable)element).getAdapter(IResource.class);
+ }
+ return null;
+ }
+
+ public String toString() {
+ return getName();
+ }
+
+ public long getModificationStamp(IResource resource) {
+ if (!(resource instanceof IFile))
+ return resource.getModificationStamp();
+ IFile file= (IFile)resource;
+ ITextFileBuffer buffer= getBuffer(file);
+ if (buffer == null) {
+ return file.getModificationStamp();
+ } else {
+ IDocument document= buffer.getDocument();
+ if (document instanceof IDocumentExtension4) {
+ return ((IDocumentExtension4)document).getModificationStamp();
+ } else {
+ return file.getModificationStamp();
+ }
+ }
+ }
+
+ private static ITextFileBuffer getBuffer(IFile file) {
+ ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
+ return manager.getTextFileBuffer(file.getFullPath());
+ }
+}
Added: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RenameResourceChange.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RenameResourceChange.java (rev 0)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RenameResourceChange.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -0,0 +1,93 @@
+package org.rubypeople.rdt.refactoring.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.ChangeDescriptor;
+import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
+import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+
+public final class RenameResourceChange extends RDTChange {
+
+ public static IPath renamedResourcePath(IPath path, String newName) {
+ return path.removeLastSegments(1).append(newName);
+ }
+
+ private final String fComment;
+
+ private final RefactoringDescriptor fDescriptor;
+
+ private final String fNewName;
+
+ private final IPath fResourcePath;
+
+ private final long fStampToRestore;
+
+ private RenameResourceChange(RefactoringDescriptor descriptor, IPath resourcePath, String newName, String comment, long stampToRestore) {
+ fDescriptor= descriptor;
+ fResourcePath= resourcePath;
+ fNewName= newName;
+ fComment= comment;
+ fStampToRestore= stampToRestore;
+ }
+
+ public RenameResourceChange(RefactoringDescriptor descriptor, IResource resource, String newName, String comment) {
+ this(descriptor, resource.getFullPath(), newName, comment, IResource.NULL_STAMP);
+ }
+
+ public ChangeDescriptor getDescriptor() {
+ if (fDescriptor != null)
+ return new RefactoringChangeDescriptor(fDescriptor);
+ return null;
+ }
+
+ public Object getModifiedElement() {
+ return getResource();
+ }
+
+ public String getName() {
+ return Messages.format(Messages.RenameResourceChange_name, new String[] { fResourcePath.toString(), fNewName});
+ }
+
+ public String getNewName() {
+ return fNewName;
+ }
+
+ private IResource getResource() {
+ return ResourcesPlugin.getWorkspace().getRoot().findMember(fResourcePath);
+ }
+
+ public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException {
+ IResource resource= getResource();
+ if (resource == null || !resource.exists()) {
+ return RefactoringStatus.createFatalErrorStatus(Messages.format(Messages.RenameResourceChange_does_not_exist, fResourcePath.toString()));
+ } else {
+ return super.isValid(pm, DIRTY);
+ }
+ }
+
+ public Change perform(IProgressMonitor pm) throws CoreException {
+ try {
+ pm.beginTask(Messages.RenameResourceChange_rename_resource, 1);
+
+ IResource resource= getResource();
+ long currentStamp= resource.getModificationStamp();
+ IPath newPath= renamedResourcePath(fResourcePath, fNewName);
+ resource.move(newPath, IResource.SHALLOW, pm);
+ if (fStampToRestore != IResource.NULL_STAMP) {
+ IResource newResource= ResourcesPlugin.getWorkspace().getRoot().findMember(newPath);
+ newResource.revertModificationStamp(fStampToRestore);
+ }
+ String oldName= fResourcePath.lastSegment();
+ return new RenameResourceChange(null, newPath, oldName, fComment, currentStamp);
+ } finally {
+ pm.done();
+ }
+ }
+}
Added: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/Resources.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/Resources.java (rev 0)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/Resources.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -0,0 +1,228 @@
+package org.rubypeople.rdt.refactoring.core;
+
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.filesystem.EFS;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.ResourceAttributes;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.rubypeople.rdt.internal.ui.IRubyStatusConstants;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+import org.rubypeople.rdt.internal.ui.RubyUIStatus;
+
+public class Resources {
+
+ private Resources() {
+ }
+
+ /**
+ * Checks if the given resource is in sync with the underlying file system.
+ *
+ * @param resource the resource to be checked
+ * @return IStatus status describing the check's result. If <code>status.
+ * isOK()</code> returns <code>true</code> then the resource is in sync
+ */
+ public static IStatus checkInSync(IResource resource) {
+ return checkInSync(new IResource[] {resource});
+ }
+
+ /**
+ * Checks if the given resources are in sync with the underlying file
+ * system.
+ *
+ * @param resources the resources to be checked
+ * @return IStatus status describing the check's result. If <code>status.
+ * isOK() </code> returns <code>true</code> then the resources are in sync
+ */
+ public static IStatus checkInSync(IResource[] resources) {
+ IStatus result= null;
+ for (int i= 0; i < resources.length; i++) {
+ IResource resource= resources[i];
+ if (!resource.isSynchronized(IResource.DEPTH_INFINITE)) {
+ result= addOutOfSync(result, resource);
+ }
+ }
+ if (result != null)
+ return result;
+ return new Status(IStatus.OK, RubyPlugin.getPluginId(), IStatus.OK, "", null); //$NON-NLS-1$
+ }
+
+ /**
+ * Makes the given resource committable. Committable means that it is
+ * writeable and that its content hasn't changed by calling
+ * <code>validateEdit</code> for the given resource on <tt>IWorkspace</tt>.
+ *
+ * @param resource the resource to be checked
+ * @param context the context passed to <code>validateEdit</code>
+ * @return status describing the method's result. If <code>status.isOK()</code> returns <code>true</code> then the resources are committable.
+ *
+ * @see org.eclipse.core.resources.IWorkspace#validateEdit(org.eclipse.core.resources.IFile[], java.lang.Object)
+ */
+ public static IStatus makeCommittable(IResource resource, Object context) {
+ return makeCommittable(new IResource[] { resource }, context);
+ }
+
+ /**
+ * Makes the given resources committable. Committable means that all
+ * resources are writeable and that the content of the resources hasn't
+ * changed by calling <code>validateEdit</code> for a given file on
+ * <tt>IWorkspace</tt>.
+ *
+ * @param resources the resources to be checked
+ * @param context the context passed to <code>validateEdit</code>
+ * @return IStatus status describing the method's result. If <code>status.
+ * isOK()</code> returns <code>true</code> then the add resources are
+ * committable
+ *
+ * @see org.eclipse.core.resources.IWorkspace#validateEdit(org.eclipse.core.resources.IFile[], java.lang.Object)
+ */
+ public static IStatus makeCommittable(IResource[] resources, Object context) {
+ List readOnlyFiles= new ArrayList();
+ for (int i= 0; i < resources.length; i++) {
+ IResource resource= resources[i];
+ if (resource.getType() == IResource.FILE && isReadOnly(resource))
+ readOnlyFiles.add(resource);
+ }
+ if (readOnlyFiles.size() == 0)
+ return new Status(IStatus.OK, RubyPlugin.getPluginId(), IStatus.OK, "", null); //$NON-NLS-1$
+
+ Map oldTimeStamps= createModificationStampMap(readOnlyFiles);
+ IStatus status= ResourcesPlugin.getWorkspace().validateEdit(
+ (IFile[]) readOnlyFiles.toArray(new IFile[readOnlyFiles.size()]), context);
+ if (!status.isOK())
+ return status;
+
+ IStatus modified= null;
+ Map newTimeStamps= createModificationStampMap(readOnlyFiles);
+ for (Iterator iter= oldTimeStamps.keySet().iterator(); iter.hasNext();) {
+ IFile file= (IFile) iter.next();
+ if (!oldTimeStamps.get(file).equals(newTimeStamps.get(file)))
+ modified= addModified(modified, file);
+ }
+ if (modified != null)
+ return modified;
+ return new Status(IStatus.OK, RubyPlugin.getPluginId(), IStatus.OK, "", null); //$NON-NLS-1$
+ }
+
+ private static Map createModificationStampMap(List files){
+ Map map= new HashMap();
+ for (Iterator iter= files.iterator(); iter.hasNext(); ) {
+ IFile file= (IFile)iter.next();
+ map.put(file, new Long(file.getModificationStamp()));
+ }
+ return map;
+ }
+
+ private static IStatus addModified(IStatus status, IFile file) {
+ IStatus entry= RubyUIStatus.createError(
+ IRubyStatusConstants.VALIDATE_EDIT_CHANGED_CONTENT,
+ Messages.format("CorextMessages.Resources_fileModified", file.getFullPath().toString()),
+ null);
+ if (status == null) {
+ return entry;
+ } else if (status.isMultiStatus()) {
+ ((MultiStatus)status).add(entry);
+ return status;
+ } else {
+ MultiStatus result= new MultiStatus(RubyPlugin.getPluginId(),
+ IRubyStatusConstants.VALIDATE_EDIT_CHANGED_CONTENT,
+ "CorextMessages.Resources_modifiedResources", null);
+ result.add(status);
+ result.add(entry);
+ return result;
+ }
+ }
+
+ private static IStatus addOutOfSync(IStatus status, IResource resource) {
+ IStatus entry= new Status(
+ IStatus.ERROR,
+ ResourcesPlugin.PI_RESOURCES,
+ IResourceStatus.OUT_OF_SYNC_LOCAL,
+ Messages.format("CorextMessages.Resources_outOfSync", resource.getFullPath().toString()),
+ null);
+ if (status == null) {
+ return entry;
+ } else if (status.isMultiStatus()) {
+ ((MultiStatus)status).add(entry);
+ return status;
+ } else {
+ MultiStatus result= new MultiStatus(
+ ResourcesPlugin.PI_RESOURCES,
+ IResourceStatus.OUT_OF_SYNC_LOCAL,
+ "CorextMessages.Resources_outOfSyncResources", null);
+ result.add(status);
+ result.add(entry);
+ return result;
+ }
+ }
+
+ /**
+ * This method is used to generate a list of local locations to
+ * be used in DnD for file transfers.
+ *
+ * @param resources the array of resources to get the local
+ * locations for
+ * @return the local locations
+ */
+ public static String[] getLocationOSStrings(IResource[] resources) {
+ List result= new ArrayList(resources.length);
+ for (int i= 0; i < resources.length; i++) {
+ IPath location= resources[i].getLocation();
+ if (location != null)
+ result.add(location.toOSString());
+ }
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+ /**
+ * Returns the location of the given resource. For local
+ * resources this is the OS path in the local file system. For
+ * remote resource this is the URI.
+ *
+ * @param resource the resource
+ * @return the location string or <code>null</code> if the
+ * location URI of the resource is <code>null</code>
+ */
+ public static String getLocationString(IResource resource) {
+ URI uri= resource.getLocationURI();
+ if (uri == null)
+ return null;
+ return EFS.SCHEME_FILE.equalsIgnoreCase(uri.getScheme())
+ ? new File(uri).getAbsolutePath()
+ : uri.toString();
+ }
+
+ public static boolean isReadOnly(IResource resource) {
+ ResourceAttributes resourceAttributes = resource.getResourceAttributes();
+ if (resourceAttributes == null) // not supported on this platform for this resource
+ return false;
+ return resourceAttributes.isReadOnly();
+ }
+
+ static void setReadOnly(IResource resource, boolean readOnly) {
+ ResourceAttributes resourceAttributes = resource.getResourceAttributes();
+ if (resourceAttributes == null) // not supported on this platform for this resource
+ return;
+
+ resourceAttributes.setReadOnly(readOnly);
+ try {
+ resource.setResourceAttributes(resourceAttributes);
+ } catch (CoreException e) {
+ RubyPlugin.log(e);
+ }
+ }
+}
Modified: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RubyRefactoring.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RubyRefactoring.java 2007-04-21 00:29:10 UTC (rev 2360)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/RubyRefactoring.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -32,6 +32,7 @@
import java.util.Collection;
import java.util.Map;
+import org.eclipse.core.internal.resources.File;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -43,10 +44,12 @@
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PlatformUI;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.internal.ui.rubyeditor.RubyEditor;
import org.rubypeople.rdt.refactoring.documentprovider.DocumentProvider;
import org.rubypeople.rdt.refactoring.documentprovider.WorkspaceDocumentProvider;
import org.rubypeople.rdt.refactoring.editprovider.FileMultiEditProvider;
+import org.rubypeople.rdt.refactoring.editprovider.FileNameChangeProvider;
import org.rubypeople.rdt.refactoring.editprovider.IEditProvider;
import org.rubypeople.rdt.refactoring.editprovider.IMultiFileEditProvider;
import org.rubypeople.rdt.refactoring.preview.RubyTextFileChange;
@@ -69,6 +72,8 @@
private RubyEditor editor;
+ private FileNameChangeProvider fileNameChangeProvider;
+
public RubyRefactoring(String name) {
this.name = name;
initialStatus = new RefactoringStatus();
@@ -84,10 +89,14 @@
protected void setEditProvider(IEditProvider editProvider) {
this.editProvider = editProvider;
}
-
+
protected void setEditProvider(IMultiFileEditProvider multiFileEditProvider) {
this.multiFileEditProvider = multiFileEditProvider;
}
+
+ protected void setFileNameChangeProvider(FileNameChangeProvider fileNameChangeProvider) {
+ this.fileNameChangeProvider = fileNameChangeProvider;
+ }
@Override
public String getName() {
@@ -133,7 +142,35 @@
@Override
public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
+ Change change = createEditChanges();
+
+ Map<String, String> filesToRename = fileNameChangeProvider.getFilesToRename(getAllAffectedFiles(change));
+ if(filesToRename.isEmpty()) {
+ return change;
+ }
+
+ CompositeChange compositeChange = new CompositeChange(getName(), new Change[]{change});
+ compositeChange.markAsSynthetic();
+ for (Map.Entry<String, String> entry : filesToRename.entrySet()) {
+ RenameResourceChange renameResourceChange = new RenameResourceChange(null, RubyPlugin.getWorkspace().getRoot().findMember(entry.getKey()), entry.getValue(), "comment");
+ compositeChange.add(new DynamicValidationStateChange(renameResourceChange));
+ }
+ return compositeChange;
+ }
+
+ private Collection<File> getAllAffectedFiles(Change change) {
+ Collection<File> affectedFiles = new ArrayList<File>();
+ for (Object object : change.getAffectedObjects()) {
+ if (object instanceof File) {
+ affectedFiles.add((File) object);
+ }
+ }
+ return affectedFiles;
+ }
+
+ private Change createEditChanges() {
DocumentProvider docProvider = new WorkspaceDocumentProvider(getActiveFile());
+
if(multiFileEditProvider != null) {
return createMultiFileChange(docProvider);
}
@@ -184,4 +221,8 @@
public IMultiFileEditProvider getMultiFileEditProvider() {
return multiFileEditProvider;
}
+
+ public FileNameChangeProvider getFileNameChangeProvider() {
+ return fileNameChangeProvider != null ? fileNameChangeProvider : new FileNameChangeProvider();
+ }
}
Added: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/WorkspaceTracker.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/WorkspaceTracker.java (rev 0)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/WorkspaceTracker.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -0,0 +1,55 @@
+package org.rubypeople.rdt.refactoring.core;
+
+import org.eclipse.core.runtime.ListenerList;
+
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+
+public class WorkspaceTracker {
+
+ public final static WorkspaceTracker INSTANCE= new WorkspaceTracker();
+
+ public interface Listener {
+ public void workspaceChanged();
+ }
+
+ private ListenerList fListeners;
+ private ResourceListener fResourceListener;
+
+ private WorkspaceTracker() {
+ fListeners= new ListenerList();
+ }
+
+ private class ResourceListener implements IResourceChangeListener {
+ public void resourceChanged(IResourceChangeEvent event) {
+ workspaceChanged();
+ }
+ }
+
+ private void workspaceChanged() {
+ Object[] listeners= fListeners.getListeners();
+ for (int i= 0; i < listeners.length; i++) {
+ ((Listener)listeners[i]).workspaceChanged();
+ }
+ }
+
+ public void addListener(Listener l) {
+ fListeners.add(l);
+ if (fResourceListener == null) {
+ fResourceListener= new ResourceListener();
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(fResourceListener);
+ }
+ }
+
+ public void removeListener(Listener l) {
+ if (fListeners.size() == 0)
+ return;
+ fListeners.remove(l);
+ if (fListeners.size() == 0) {
+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(fResourceListener);
+ fResourceListener= null;
+ }
+ }
+}
Modified: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/messages.properties
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/messages.properties 2007-04-21 00:29:10 UTC (rev 2360)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/messages.properties 2007-04-25 10:14:02 UTC (rev 2361)
@@ -1,3 +1,12 @@
RefactoringConditionChecker_SyntaxErrorInProject=There is a syntax error somewhere in the project, the refactoring might not work on these files.
RefactoringConditionChecker_EmptyDocument=Nothing to do in empty document.
RefactoringConditionChecker_SyntaxErrorInCurrent=There is a syntax error in the current file, refactoring is not possible.
+RenameResourceChange_rename_resource=rename resource
+RenameResourceChange_name=Rename ''{0}'' to: ''{1}''
+RenameResourceChange_does_not_exist=''{0}'' does not exist
+Change_is_unsaved={0} is unsaved.
+Change_is_read_only={0} is read only.
+Change_has_modifications={0} has been modified since the refactoring got executed.
+Change_does_not_exist=''{0}'' does not exist anymore.
+Change_same_read_only= The read only state of {0} has changed.
+DynamicValidationStateChange_workspace_changed=The workspace has been modified since the refactoring change object has been created
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/rename/RenameRefactoring.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/rename/RenameRefactoring.java 2007-04-21 00:29:10 UTC (rev 2360)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/rename/RenameRefactoring.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -68,6 +68,7 @@
setName(delegateRenameRefactoring.getName());
setEditProvider(delegateRenameRefactoring.getMultiFileEditProvider());
setEditProvider(delegateRenameRefactoring.getEditProvider());
+ setFileNameChangeProvider(delegateRenameRefactoring.getFileNameChangeProvider());
for(IWizardPage aktPage : delegateRenameRefactoring.getPages()) {
pages.add(aktPage);
}
Added: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/renameclass/RenameClassFileNameChangeProvider.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/renameclass/RenameClassFileNameChangeProvider.java (rev 0)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/renameclass/RenameClassFileNameChangeProvider.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -0,0 +1,31 @@
+package org.rubypeople.rdt.refactoring.core.renameclass;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.internal.resources.File;
+import org.rubypeople.rdt.refactoring.editprovider.FileNameChangeProvider;
+
+public class RenameClassFileNameChangeProvider extends FileNameChangeProvider {
+
+ private final RenameClassConfig config;
+
+ public RenameClassFileNameChangeProvider(RenameClassConfig renameClassConfig) {
+ this.config = renameClassConfig;
+ }
+
+ @Override
+ public Map<String, String> getFilesToRename(Collection<File> objects) {
+ HashMap<String, String> filesToRename = new HashMap<String, String>();
+ for (File file : objects) {
+ String name = file.getName();
+ name = name.replaceAll("\\." + file.getFileExtension() + "$", "");
+ if(name.equals(config.getSelectedNode().getCPath().getName())) {
+ filesToRename.put(file.getFullPath().toString(), config.getNewName() + ".rb");
+ }
+ }
+ return filesToRename;
+ }
+
+}
Modified: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/renameclass/RenameClassRefactoring.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/renameclass/RenameClassRefactoring.java 2007-04-21 00:29:10 UTC (rev 2360)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/core/renameclass/RenameClassRefactoring.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -48,7 +48,7 @@
if(conditionChecker.shouldPerform()) {
RenameClassEditProvider editProvider = new RenameClassEditProvider(renameClassConfig);
setEditProvider(editProvider);
-
+ setFileNameChangeProvider(new RenameClassFileNameChangeProvider(renameClassConfig));
pages.add(new RenamePage(NAME, renameClassConfig.getSelectedNode().getCPath().getName(),
new NewNameListener(renameClassConfig, new ConstNameValidator(), new ArrayList<String>())));
Added: trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/editprovider/FileNameChangeProvider.java
===================================================================
--- trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/editprovider/FileNameChangeProvider.java (rev 0)
+++ trunk/org.rubypeople.rdt.refactoring/src/org/rubypeople/rdt/refactoring/editprovider/FileNameChangeProvider.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -0,0 +1,15 @@
+package org.rubypeople.rdt.refactoring.editprovider;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.internal.resources.File;
+
+public class FileNameChangeProvider {
+
+ public Map<String, String> getFilesToRename(Collection<File> objects) {
+ return new HashMap<String, String>();
+ }
+
+}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/IRubyStatusConstants.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/IRubyStatusConstants.java 2007-04-21 00:29:10 UTC (rev 2360)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/IRubyStatusConstants.java 2007-04-25 10:14:02 UTC (rev 2361)
@@ -22,5 +22,10 @@
// collide with resource and ruby model constants.
public static final int INTERNAL_ERROR= 10001;
-
+
+ /**
+ * Status constant indicating that an validateEdit call has changed the
+ * content of a file on disk.
+ */
+ public static final int VALIDATE_EDIT_CHANGED_CONTENT= 10003;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|