/*******************************************************************************
* Copyright (c) 2007 Business Objects Software Limited and others.
* All rights reserved.
* This file is 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:
* Business Objects Software Limited - initial API and implementation
*******************************************************************************/
/*
* RenameAction.java
* Creation date: Feb 23 2007.
* By: Greg McClement
*/
package org.openquark.cal.eclipse.ui.actions;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.SortedSet;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IStorage;
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.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.PerformChangeOperation;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.TextEditorAction;
import org.openquark.cal.compiler.CompilerMessageLogger;
import org.openquark.cal.compiler.FieldName;
import org.openquark.cal.compiler.IdentifierInfo;
import org.openquark.cal.compiler.IdentifierOccurrence;
import org.openquark.cal.compiler.LanguageInfo;
import org.openquark.cal.compiler.MessageLogger;
import org.openquark.cal.compiler.ModuleContainer;
import org.openquark.cal.compiler.ModuleName;
import org.openquark.cal.compiler.ModuleSourceDefinition;
import org.openquark.cal.compiler.Name;
import org.openquark.cal.compiler.QualifiedName;
import org.openquark.cal.compiler.Refactorer;
import org.openquark.cal.compiler.SearchManager;
import org.openquark.cal.compiler.SourceIdentifier;
import org.openquark.cal.compiler.SourcePosition;
import org.openquark.cal.compiler.IdentifierInfo.TopLevel;
import org.openquark.cal.compiler.IdentifierOccurrence.Binding;
import org.openquark.cal.eclipse.core.CALModelManager;
import org.openquark.cal.eclipse.ui.CALEclipseUIPlugin;
import org.openquark.cal.eclipse.ui.CALUIMessages;
import org.openquark.cal.eclipse.ui.caleditor.CALEditor;
import org.openquark.cal.eclipse.ui.caleditor.CALHyperlinkDetector;
import org.openquark.cal.eclipse.ui.caleditor.PartiallySynchronizedDocument;
import org.openquark.cal.eclipse.ui.util.CoreUtility;
import org.openquark.cal.eclipse.ui.util.CreateFolderChange;
import org.openquark.cal.eclipse.ui.util.MoveResourceChange;
import org.openquark.cal.eclipse.ui.util.RenameResourceChange;
import org.openquark.util.Pair;
/**
* Provides access the the Rename refactorer throught the Eclipse UI.
*
* @author Greg McClement
*/
public class RenameAction extends TextEditorAction{
private final SearchManager searchManager;
private final static String errorTitle = ActionMessages.RenameAction_windowTitle;
public RenameAction(ResourceBundle bundle, String prefix, ITextEditor editor) {
super(bundle, prefix, editor);
CALModelManager modelManager = CALModelManager.getCALModelManager();
searchManager = modelManager.getSearchManager();
}
@Override
public void run() {
// update has been called by the framework
if (!isEnabled()){
return;
}
if (!CoreUtility.builderEnabledCheck(errorTitle)){
return;
}
final CALEditor textEditor = (CALEditor) getTextEditor();
final ITextSelection selection = ActionUtilities.getSelection(textEditor);
final IDocument document = ActionUtilities.getDocument(textEditor);
if (document != null) {
final int offset = selection.getOffset();
try {
final PartiallySynchronizedDocument psd = (PartiallySynchronizedDocument) document;
CALModelManager cmm = CALModelManager.getCALModelManager();
final IStorage storage = textEditor.getStorage();
ModuleName moduleName;
try{
moduleName = cmm.getModuleName(storage);
}
catch(IllegalArgumentException ex){
// CAL File is not in the correct spot in the hierarchy so there
// is no type information available.
CoreUtility.showMessage(errorTitle, ActionMessages.error_calFileNotInCorrectLocation_message, IStatus.ERROR);
return;
}
final Pair<SourcePosition, SourcePosition> posAndPosToTheLeft = CALHyperlinkDetector.getCurrentPositionAndPositionToTheLeft(psd, offset, moduleName);
if (posAndPosToTheLeft == null){
CoreUtility.showErrorOnStatusLine(textEditor, ActionMessages.OpenAction_error_noSourceCodeMetrics);
return;
}
CoreUtility.initializeCALBuilder(null, 100, 100);
ModuleSourceDefinition msd = cmm.getModuleSourceDefinition(moduleName);
if (msd == null){
CoreUtility.showErrorOnStatusLine(textEditor, ActionMessages.error_messageBadSelection_noTypeInformation_CAL);
return;
}
if (!cmm.getProgramModelManager().hasModuleInProgram(moduleName)){
CoreUtility.showErrorOnStatusLine(textEditor, ActionMessages.OpenAction_error_noSourceCodeMetrics);
return;
}
CompilerMessageLogger messageLogger = new MessageLogger();
IdentifierOccurrence<?> occurrence = searchManager.findSymbolAt(moduleName, posAndPosToTheLeft.fst(), posAndPosToTheLeft.snd(), messageLogger);
// we only activate renaming if the occurrence is not an operator...
if (occurrence != null && !(occurrence instanceof IdentifierOccurrence.Reference.Operator<?>)) {
final IdentifierInfo identifierInfo = occurrence.getIdentifierInfo();
if (identifierInfo instanceof IdentifierInfo.DataConsFieldName) {
final IdentifierInfo.DataConsFieldName oldName = (IdentifierInfo.DataConsFieldName)identifierInfo;
performDataConsFieldNameRename(textEditor.getSite().getShell(), cmm, messageLogger, oldName, oldName.getFieldName().getCalSourceForm());
CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger);
} else if (identifierInfo instanceof IdentifierInfo.TypeVariable) {
final IdentifierInfo.TypeVariable oldName = (IdentifierInfo.TypeVariable)identifierInfo;
performTypeVarRename(textEditor.getSite().getShell(), cmm, messageLogger, moduleName, oldName, oldName.getTypeVarName());
CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger);
} else if (identifierInfo instanceof IdentifierInfo.Local) {
final IdentifierInfo.Local oldLocalName = (IdentifierInfo.Local)identifierInfo;
if (occurrence instanceof Binding.PunnedTextualDataConsFieldName<?>) {
final List<Binding<IdentifierInfo.TopLevel.DataCons>> dataConsBindings = ((Binding.PunnedTextualDataConsFieldName<?>)occurrence).getDataConsNameBindings();
final List<IdentifierInfo.TopLevel.DataCons> dataConsInfos = new ArrayList<IdentifierInfo.TopLevel.DataCons>();
for (final Binding<IdentifierInfo.TopLevel.DataCons> dataConsBinding : dataConsBindings) {
dataConsInfos.add(dataConsBinding.getIdentifierInfo());
}
final IdentifierInfo.DataConsFieldName oldName = new IdentifierInfo.DataConsFieldName(FieldName.make(oldLocalName.getVarName()), dataConsInfos);
final MessageDialog dialog = new MessageDialog(
textEditor.getSite().getShell(),
ActionMessages.RenameAction_punnedDataConsField_title,
null,
ActionMessages.RenameAction_punnedDataConsField_message,
MessageDialog.QUESTION,
new String[] {
ActionMessages.RenameAction_punnedDataConsField_renameDataConsField,
ActionMessages.RenameAction_punnedDataConsField_renameLocalVar,
IDialogConstants.CANCEL_LABEL },
0); // data cons field name is the default
final int userChoice = dialog.open();
switch (userChoice) {
case 0:
performDataConsFieldNameRename(textEditor.getSite().getShell(), cmm, messageLogger, oldName, oldName.getFieldName().getCalSourceForm());
break;
case 1:
performLocalNameRename(textEditor.getSite().getShell(), cmm, messageLogger, moduleName, oldLocalName, oldLocalName.getVarName());
break;
case 2:
// the user cancelled the operation, so do nothing
break;
}
} else {
performLocalNameRename(textEditor.getSite().getShell(), cmm, messageLogger, moduleName, oldLocalName, oldLocalName.getVarName());
}
CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger);
} else if (identifierInfo instanceof IdentifierInfo.TopLevel) {
final IdentifierInfo.TopLevel topLevelIdentifierInfo = (IdentifierInfo.TopLevel)identifierInfo;
final QualifiedName oldName = topLevelIdentifierInfo.getResolvedName();
final SourceIdentifier.Category category = getCategoryFromTopLevelIdentifierInfo(topLevelIdentifierInfo);
performRename(textEditor.getSite().getShell(), cmm, messageLogger, oldName, oldName.getUnqualifiedName(), category);
CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger);
} else if (identifierInfo instanceof IdentifierInfo.Module) {
final ModuleName oldName = ((IdentifierInfo.Module)identifierInfo).getResolvedName();
final SourceIdentifier.Category category = SourceIdentifier.Category.MODULE_NAME;
performRename(textEditor.getSite().getShell(), cmm, messageLogger, oldName, oldName.toSourceText(), category);
CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger);
}
}
else{
CoreUtility.showMessage(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_noSymbolSelectedError, IStatus.WARNING);
}
} catch (BadLocationException e) {
// will only happen on concurrent modification
CALEclipseUIPlugin.log(new Status(IStatus.ERROR, CALEclipseUIPlugin.PLUGIN_ID, IStatus.OK, "", e)); //$NON-NLS-1$
return;
}
}
}
/**
* @param identifierInfo the top level identifier's info
* @return the corresponding category.
*/
// todo-jowong when all renaming functionality moves to the new framework, this will no longer be necessary
private static SourceIdentifier.Category getCategoryFromTopLevelIdentifierInfo(final IdentifierInfo.TopLevel identifierInfo) {
if (identifierInfo instanceof TopLevel.FunctionOrClassMethod) {
return SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD;
} else if (identifierInfo instanceof TopLevel.TypeCons) {
return SourceIdentifier.Category.TYPE_CONSTRUCTOR;
} else if (identifierInfo instanceof TopLevel.DataCons) {
return SourceIdentifier.Category.DATA_CONSTRUCTOR;
} else if (identifierInfo instanceof TopLevel.TypeClass) {
return SourceIdentifier.Category.TYPE_CLASS;
} else {
throw new IllegalArgumentException("Unknown identifierInfo: " + identifierInfo);
}
}
/**
* Performs a local variable renaming.
* @param shell the shell
* @param cmm the CAL model manager
* @param messageLogger the message logger
* @param moduleName the current module name
* @param oldName the original name to be renamed
* @param initValue the initial value for the dialog
*/
static void performLocalNameRename(Shell shell, CALModelManager cmm, CompilerMessageLogger messageLogger, ModuleName moduleName, IdentifierInfo.Local oldName, String initValue) {
CoreUtility.SaveAllDirtyEditors sade = new CoreUtility.SaveAllDirtyEditors(shell);
// Only rename if the module is compiled
if (cmm.getModuleTypeInfo(moduleName) == null){
CoreUtility.showMessage(errorTitle, ActionMessages.OpenAction_error_noSourceCodeMetrics, IStatus.ERROR);
return;
}
sade.open();
// only rename if all the dirty editors were saved.
if (sade.getReturnCode() == Window.OK){
// Ask the user what the new name for the symbol is going to be.
RenameDialog rd = new RenameDialog(shell, initValue) {
@Override
String getDialogTitle() {
return ActionMessages.RenameAction_renameLocalVariable_title;
}
@Override
boolean isValidNewName(final String identifier) {
return LanguageInfo.isValidFunctionName(identifier);
}
};
rd.open();
if (rd.getReturnCode() == Window.OK){
// Run the refactorer
ModuleContainer moduleContainer = CALModelManager.getCALModelManager().getModuleContainer(CALEditor.getSourceManagerFactory(false, shell, null));
Refactorer refactorer = new Refactorer.RenameLocalName(moduleContainer, moduleName, oldName, rd.getNewName());
refactorer.calculateModifications(messageLogger);
if (CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger)){
return;
}
refactorer.apply(messageLogger);
if (CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger)){
return;
}
}
}
}
/**
* Performs a type variable renaming.
* @param shell the shell
* @param cmm the CAL model manager
* @param messageLogger the message logger
* @param moduleName the current module name
* @param oldName the original name to be renamed
* @param initValue the initial value for the dialog
*/
static void performTypeVarRename(Shell shell, CALModelManager cmm, CompilerMessageLogger messageLogger, ModuleName moduleName, IdentifierInfo.TypeVariable oldName, String initValue) {
CoreUtility.SaveAllDirtyEditors sade = new CoreUtility.SaveAllDirtyEditors(shell);
// Only rename if the module is compiled
if (cmm.getModuleTypeInfo(moduleName) == null){
CoreUtility.showMessage(errorTitle, ActionMessages.OpenAction_error_noSourceCodeMetrics, IStatus.ERROR);
return;
}
sade.open();
// only rename if all the dirty editors were saved.
if (sade.getReturnCode() == Window.OK){
// Ask the user what the new name for the symbol is going to be.
RenameDialog rd = new RenameDialog(shell, initValue) {
@Override
String getDialogTitle() {
return ActionMessages.RenameAction_renameTypeVariable_title;
}
@Override
boolean isValidNewName(final String identifier) {
return LanguageInfo.isValidTypeVariableName(identifier);
}
};
rd.open();
if (rd.getReturnCode() == Window.OK){
// Run the refactorer
ModuleContainer moduleContainer = CALModelManager.getCALModelManager().getModuleContainer(CALEditor.getSourceManagerFactory(false, shell, null));
Refactorer refactorer = new Refactorer.RenameTypeVariable(moduleContainer, moduleName, oldName, rd.getNewName());
refactorer.calculateModifications(messageLogger);
if (CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger)){
return;
}
refactorer.apply(messageLogger);
if (CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger)){
return;
}
}
}
}
/**
* Performs a data cons field name renaming.
* @param shell the shell
* @param cmm the CAL model manager
* @param messageLogger the message logger
* @param oldName the original name to be renamed
* @param initValue the initial value for the dialog
*/
static void performDataConsFieldNameRename(final Shell shell, CALModelManager cmm, CompilerMessageLogger messageLogger, IdentifierInfo.DataConsFieldName oldName, String initValue) {
CoreUtility.SaveAllDirtyEditors sade = new CoreUtility.SaveAllDirtyEditors(shell);
// Only rename if the module is compiled
if (cmm.getModuleTypeInfo(oldName.getFirstAssociatedDataConstructor().getResolvedName().getModuleName()) == null){
CoreUtility.showMessage(errorTitle, ActionMessages.OpenAction_error_noSourceCodeMetrics, IStatus.ERROR);
return;
}
sade.open();
// only rename if all the dirty editors were saved.
if (sade.getReturnCode() == Window.OK){
// Ask the user what the new name for the symbol is going to be.
RenameDialog rd = new RenameDialog(shell, initValue) {
@Override
String getDialogTitle() {
return ActionMessages.RenameAction_renameDataConsFieldName_title;
}
@Override
boolean isValidNewName(final String identifier) {
return LanguageInfo.isValidFieldName(identifier);
}
};
rd.open();
if (rd.getReturnCode() == Window.OK){
// Run the refactorer
final Refactorer.RenameDataConsFieldName.UserChoiceConfirmer confirmer =
new Refactorer.RenameDataConsFieldName.UserChoiceConfirmer() {
public boolean shouldRenameMultipleDataConsField(FieldName oldName, SortedSet<QualifiedName> dataConsSet) {
final StringBuilder dataConsList = new StringBuilder();
for (final QualifiedName dataConsName : dataConsSet) {
dataConsList.append(dataConsName).append("\n");
}
final String message = MessageFormat.format(ActionMessages.RenameAction_fieldNameAssociatedWithMultipleDataCons, oldName, dataConsList.toString());
MessageDialog dialog = new MessageDialog(
shell,
ActionMessages.RenameAction_renameDataConsFieldName_title,
null,
message,
MessageDialog.QUESTION,
new String[] { IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL },
0); // yes is the default
return dialog.open() == 0;
}
public void notifyCollisionOfNewName(FieldName newName) {
CoreUtility.showMessage(errorTitle, MessageFormat.format(ActionMessages.RenameAction_fieldNameAlreadyDefinedInDataCons, newName), IStatus.ERROR);
}
};
ModuleContainer moduleContainer = CALModelManager.getCALModelManager().getModuleContainer(CALEditor.getSourceManagerFactory(false, shell, null));
Refactorer refactorer = new Refactorer.RenameDataConsFieldName(moduleContainer, oldName, FieldName.make(rd.getNewName()), confirmer);
refactorer.calculateModifications(messageLogger);
if (CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger)){
return;
}
refactorer.apply(messageLogger);
if (CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger)){
return;
}
}
}
}
static void performRename(Shell shell, CALModelManager cmm, CompilerMessageLogger messageLogger, Name oldName, String initValue, final SourceIdentifier.Category category) {
CoreUtility.SaveAllDirtyEditors sade = new CoreUtility.SaveAllDirtyEditors(shell);
// Only rename if the module is compiled
if (cmm.getModuleTypeInfo(oldName.getModuleName()) == null){
CoreUtility.showMessage(errorTitle, ActionMessages.OpenAction_error_noSourceCodeMetrics, IStatus.ERROR);
return;
}
sade.open();
// only rename if all the dirty editors were saved.
if (sade.getReturnCode() == Window.OK){
if (
category != null &&
// rename does not support these types of symbols
category != SourceIdentifier.Category.LOCAL_VARIABLE &&
category != SourceIdentifier.Category.LOCAL_VARIABLE_DEFINITION
){
// Ask the user what the new name for the symbol is going to be.
RenameDialog rd = new RenameDialog(shell, initValue) {
@Override
String getDialogTitle() {
if (category == SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD) {
return ActionMessages.RenameAction_renameFunctionOrClassMethod_title;
} else if (category == SourceIdentifier.Category.DATA_CONSTRUCTOR) {
return ActionMessages.RenameAction_renameDataCons_title;
} else if (category == SourceIdentifier.Category.TYPE_CONSTRUCTOR) {
return ActionMessages.RenameAction_renameTypeCons_title;
} else if (category == SourceIdentifier.Category.TYPE_CLASS) {
return ActionMessages.RenameAction_renameTypeClass_title;
} else if (category == SourceIdentifier.Category.MODULE_NAME) {
return ActionMessages.RenameAction_renameModule_title;
} else {
return super.getDialogTitle();
}
}
@Override
boolean isValidNewName(String identifier) {
if (category == SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD) {
return LanguageInfo.isValidFunctionName(identifier);
} else if (category == SourceIdentifier.Category.DATA_CONSTRUCTOR) {
return LanguageInfo.isValidDataConstructorName(identifier);
} else if (category == SourceIdentifier.Category.TYPE_CONSTRUCTOR) {
return LanguageInfo.isValidTypeConstructorName(identifier);
} else if (category == SourceIdentifier.Category.TYPE_CLASS) {
return LanguageInfo.isValidTypeClassName(identifier);
} else if (category == SourceIdentifier.Category.MODULE_NAME) {
return LanguageInfo.isValidModuleName(identifier);
} else {
return false;
}
}
};
rd.open();
if (rd.getReturnCode() == Window.OK){
// Run the refactorer
ModuleContainer moduleContainer = CALModelManager.getCALModelManager().getModuleContainer(CALEditor.getSourceManagerFactory(false, shell, null));
QualifiedName oldQN;
QualifiedName newQN;
if (oldName instanceof QualifiedName){
oldQN = (QualifiedName) oldName;
newQN = QualifiedName.make(oldQN.getModuleName(), rd.getNewName());
}
else if (oldName instanceof ModuleName){
ModuleName oldModuleName = (ModuleName) oldName;
try{
ModuleName newModuleName = ModuleName.make(rd.getNewName());
oldQN = QualifiedName.make(oldModuleName, Refactorer.Rename.UNQUALIFIED_NAME_FOR_MODULE_RENAMING);
newQN = QualifiedName.make(newModuleName, Refactorer.Rename.UNQUALIFIED_NAME_FOR_MODULE_RENAMING);
}
catch(IllegalArgumentException ex){
CoreUtility.showMessage(errorTitle, CALUIMessages.CALNewModuleWizard_error_invalidModuleName, IStatus.ERROR);
return;
}
}
else{
throw new IllegalArgumentException();
}
Refactorer refactorer = new Refactorer.Rename(moduleContainer, cmm.getTypeChecker(), oldQN, newQN, category);
refactorer.calculateModifications(messageLogger);
if (CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger)){
return;
}
refactorer.apply(messageLogger);
if (CoreUtility.showErrors(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_failed, messageLogger)){
return;
}
if (oldName instanceof ModuleName){
ModuleName oldModuleName = oldQN.getModuleName();
ModuleName newModuleName = newQN.getModuleName();
if (!oldModuleName.equals(newModuleName)){
IStorage definitionStorage = cmm.getInputSourceFile(oldModuleName);
if (definitionStorage instanceof IFile){
IFile definitionFile = (IFile) definitionStorage;
final String newName = newModuleName.getLastComponent() + ".cal";
Change renameChange = null;
// if the file name would change then create
// a Change object for the rename
if (!newModuleName.getLastComponent().equals(oldModuleName.getLastComponent())){
RenameResourceChange changeFileName = new RenameResourceChange(null, definitionFile, newName, null);
changeFileName.initializeValidationData(new NullProgressMonitor());
renameChange = changeFileName;
}
CompositeChange moveChanges = new CompositeChange("");
// If the hierarchical part of the name changed
// then we have to move the file
// to a new location
if (
(newModuleName.getNComponents() != oldModuleName.getNComponents()) ||
(
newModuleName.getNComponents() > 1 &&
(!newModuleName.getImmediatePrefix().equals(oldModuleName.getImmediatePrefix()))
)){
IPath sourcePath = definitionFile.getLocation();
IPath rootPath = sourcePath.removeLastSegments(oldModuleName.getNComponents());
IPath destPath = rootPath;
String[] components = newModuleName.getComponents();
for (int i = 0; i < components.length - 1; i++) {
destPath = destPath.append(components[i]);
}
IFolder lastComponent = null;
{
IFolder rootFolder = (IFolder) ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(rootPath);
lastComponent = rootFolder;
final String[] newModuleNameComponents = newModuleName.getComponents();
final int justBeforeLastComponent = newModuleNameComponents.length - 1;
for(int i = 0; i < justBeforeLastComponent; ++i){
final String componentName = newModuleNameComponents[i];
lastComponent = lastComponent.getFolder(componentName);
if (!lastComponent.exists()){
moveChanges.add(new CreateFolderChange(lastComponent));
}
}
}
// have to move the file after the name is changed
IFolder sourceFolder = (IFolder) ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(sourcePath.removeLastSegments(1));
final IFile sourceFile = sourceFolder.getFile(newModuleName.getLastComponent() + ".cal");
MoveResourceChange changeLocation = new MoveResourceChange(sourceFile, lastComponent);
changeLocation.initializeValidationData(new NullProgressMonitor());
moveChanges.add(changeLocation);
}
{
// The rename has to run first so that the move in perform2 is
// accessing an existing file.
try {
if (renameChange != null){
PerformChangeOperation perform1= new PerformChangeOperation(renameChange);
ResourcesPlugin.getWorkspace().run(perform1, new NullProgressMonitor());
}
if (moveChanges != null){
PerformChangeOperation perform2= new PerformChangeOperation(moveChanges);
ResourcesPlugin.getWorkspace().run(perform2, new NullProgressMonitor());
}
} catch (CoreException e) {
CALEclipseUIPlugin.log(new Status(IStatus.ERROR, CALEclipseUIPlugin.PLUGIN_ID, IStatus.OK, "", e)); //$NON-NLS-1$ }
}
// perform.getUndoChange();
}
}
else{
assert false;
}
}
}
}
}
else{
CoreUtility.showMessage(ActionMessages.RenameAction_windowTitle, ActionMessages.RenameAction_noSymbolSelectedError, IStatus.WARNING);
}
}
}
/**
* A dialog for asking the user for the new name of the symbol.
*/
private static abstract class RenameDialog extends Dialog{
private Text newNameText;
private final String originalName;
private String newName;
protected RenameDialog(Shell parentShell, String originalName) {
super(parentShell);
this.newName = originalName;
this.originalName = originalName;
}
public String getNewName(){
return newName;
}
@Override
protected void okPressed(){
newName = newNameText.getText();
super.okPressed();
}
@Override
protected Button createButton(Composite parent, int id, String label, boolean defaultButton) {
Button button = super.createButton(parent, id, label, defaultButton);
if (id == IDialogConstants.OK_ID){
button.setEnabled(false);
}
return button;
}
@Override
public Control createDialogArea(Composite parent){
Composite composite = (Composite) super.createDialogArea(parent);
getShell().setText(getDialogTitle());
GridLayout layout = new GridLayout();
layout.verticalSpacing = 20;
layout.numColumns = 2;
composite.setLayout(layout);
Label label = new Label(composite, SWT.CENTER);
label.setText(ActionMessages.RenameAction_newNameTextLabel);
{
newNameText = new Text(composite, SWT.LEFT | SWT.BORDER);
newNameText.setText(newName);
newNameText.selectAll();
newNameText.addModifyListener(
new ModifyListener(){
private boolean identifierIsOkay(String identifier){
if (identifier.length() == 0){
return false;
}
if (!isValidNewName(identifier)){
return false;
}
if (identifier.equals(originalName)){
return false;
}
return true;
}
public void modifyText(ModifyEvent arg0) {
getButton(IDialogConstants.OK_ID).setEnabled(identifierIsOkay(newNameText.getText()));
}
}
);
GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
gridData.grabExcessHorizontalSpace = true;
gridData.widthHint = 250;
newNameText.setLayoutData(gridData);
}
getInitialSize();
return composite;
}
/**
* @return the title for the dialog.
*/
String getDialogTitle() {
return ActionMessages.RenameAction_windowTitle;
}
/**
* @param identifier an identifier to check.
* @return whether the name is valid as the new name in a renaming.
*/
abstract boolean isValidNewName(String identifier);
}
}