1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 09:25:31 +02:00

Bug 318510 - Lightweight rename refactoring.

This commit is contained in:
Sergey Prigogin 2010-09-12 05:22:07 +00:00
parent b55cf8fa2e
commit f940989086
49 changed files with 3619 additions and 287 deletions

View file

@ -51,6 +51,7 @@ import org.eclipse.cdt.internal.ui.text.correction.CCorrectionProcessor;
import org.eclipse.cdt.internal.ui.text.correction.CorrectionContext;
import org.eclipse.cdt.internal.ui.text.correction.ProblemLocation;
import org.eclipse.cdt.internal.ui.text.correction.proposals.LinkedNamesAssistProposal;
import org.eclipse.cdt.internal.ui.text.correction.proposals.RenameRefactoringProposal;
import org.eclipse.cdt.internal.ui.text.correction.proposals.TUCorrectionProposal;
public class AssistQuickFixTest extends BaseUITestCase {
@ -263,9 +264,10 @@ public class AssistQuickFixTest extends BaseUITestCase {
CorrectionContext context= getCorrectionContext(fMatch.getOffset(), 0);
List<ICCompletionProposal> proposals= collectAssists(context, null);
assertNumberOfProposals(proposals, 1);
assertNumberOfProposals(proposals, 2);
assertCorrectLabels(proposals);
assertTrue(proposals.get(0) instanceof LinkedNamesAssistProposal);
assertTrue(proposals.get(1) instanceof RenameRefactoringProposal);
}
public void testLocalRenameMacro() throws Exception {
@ -279,9 +281,10 @@ public class AssistQuickFixTest extends BaseUITestCase {
CorrectionContext context= getCorrectionContext(fMatch.getOffset(), 0);
List<ICCompletionProposal> proposals= collectAssists(context, null);
assertNumberOfProposals(proposals, 1);
assertNumberOfProposals(proposals, 2);
assertCorrectLabels(proposals);
assertTrue(proposals.get(0) instanceof LinkedNamesAssistProposal);
assertTrue(proposals.get(1) instanceof RenameRefactoringProposal);
}
public void testLocalRenameLanguageKeyword() throws Exception {

View file

@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.corext.util;
@ -17,6 +18,8 @@ import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultLineTracker;
import org.eclipse.jface.text.ILineTracker;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.osgi.util.TextProcessor;
import org.eclipse.cdt.core.formatter.IndentManipulation;
import org.eclipse.cdt.core.model.ICProject;
@ -27,8 +30,23 @@ import org.eclipse.cdt.core.model.ICProject;
*/
public class Strings {
private Strings(){}
private Strings() {}
/**
* Tells whether we have to use the {@link TextProcessor}
* <p>
* This is used for performance optimization.
* </p>
* @since 3.4
*/
public static final boolean USE_TEXT_PROCESSOR;
static {
String testString= "args : String[]"; //$NON-NLS-1$
USE_TEXT_PROCESSOR= testString != TextProcessor.process(testString);
}
private static final String C_ELEMENT_DELIMITERS= TextProcessor.getDefaultDelimiters() + "<>(),?{} "; //$NON-NLS-1$
public static boolean startsWithIgnoreCase(String text, String prefix) {
int textLength= text.length();
int prefixLength= prefix.length();
@ -82,7 +100,7 @@ public class Strings {
/**
* Returns <code>true</code> if the given string only consists of
* white spaces according to Java. If the string is empty, <code>true
* white spaces according to C. If the string is empty, <code>true
* </code> is returned.
*
* @return <code>true</code> if the string only consists of white
@ -450,4 +468,93 @@ public class Strings {
public static String removeMnemonicIndicator(String string) {
return LegacyActionTools.removeMnemonics(string);
}
/**
* Adds special marks so that that the given string is readable in a BiDi environment.
*
* @param string the string
* @return the processed styled string
* @since 5.3
*/
public static String markLTR(String string) {
if (!USE_TEXT_PROCESSOR)
return string;
return TextProcessor.process(string);
}
/**
* Adds special marks so that that the given string is readable in a BiDi environment.
*
* @param string the string
* @param delimiters the delimiters
* @return the processed styled string
* @since 5.3
*/
public static String markLTR(String string, String delimiters) {
if (!USE_TEXT_PROCESSOR)
return string;
return TextProcessor.process(string, delimiters);
}
/**
* Adds special marks so that that the given C element label is readable in a BiDi
* environment.
*
* @param string the string
* @return the processed styled string
* @since 5.3
*/
public static String markCElementLabelLTR(String string) {
if (!USE_TEXT_PROCESSOR)
return string;
return TextProcessor.process(string, C_ELEMENT_DELIMITERS);
}
/**
* Adds special marks so that that the given styled C element label is readable in a BiDi
* environment.
*
* @param styledString the styled string
* @return the processed styled string
* @since 5.3
*/
public static StyledString markCElementLabelLTR(StyledString styledString) {
if (!USE_TEXT_PROCESSOR)
return styledString;
String inputString= styledString.getString();
String string= TextProcessor.process(inputString, C_ELEMENT_DELIMITERS);
if (string != inputString)
insertMarks(styledString, inputString, string);
return styledString;
}
/**
* Inserts the marks into the given styled string.
*
* @param styledString the styled string
* @param originalString the original string
* @param processedString the processed string
* @since 5.3
*/
private static void insertMarks(StyledString styledString, String originalString, String processedString) {
int originalLength= originalString.length();
int processedStringLength= processedString.length();
char orig= originalLength > 0 ? originalString.charAt(0) : '\0';
for (int o= 0, p= 0; p < processedStringLength; p++) {
char processed= processedString.charAt(p);
if (o < originalLength) {
if (orig == processed) {
o++;
if (o < originalLength)
orig= originalString.charAt(o);
continue;
}
}
styledString.insert(processed, p);
}
}
}

View file

@ -141,14 +141,12 @@ public class CPluginImages {
// build console
public static final String IMG_VIEW_BUILD = NAME_PREFIX + "buildconsole.gif"; //$NON-NLS-1$
public static final String IMG_VIEW_MENU = NAME_PREFIX + "view_menu.gif"; //$NON-NLS-1$
public static final String IMG_SAVE_CONSOLE = NAME_PREFIX + "save_console.gif"; //$NON-NLS-1$
// unknown type
public static final String IMG_OBJS_UNKNOWN = NAME_PREFIX + "unknown_obj.gif"; //$NON-NLS-1$
public static final ImageDescriptor DESC_BUILD_CONSOLE = createManaged(T_VIEW, IMG_VIEW_BUILD);
public static final ImageDescriptor IMG_VIEW_MENU_DESC = createManaged(T_VIEW, IMG_VIEW_MENU);
public static final ImageDescriptor IMG_SAVE_CONSOLE_DESC = createManaged(T_VIEW, IMG_SAVE_CONSOLE);
public static final ImageDescriptor DESC_OBJS_VARIABLE= createManaged(T_OBJ, IMG_OBJS_VARIABLE);
@ -364,6 +362,8 @@ public class CPluginImages {
public static final ImageDescriptor DESC_DLCL_CONFIGURE_ANNOTATIONS= createUnManaged(T_DLCL, "configure_annotations.gif"); //$NON-NLS-1$
public static final ImageDescriptor DESC_ELCL_CONFIGURE_ANNOTATIONS= createUnManaged(T_ELCL, "configure_annotations.gif"); //$NON-NLS-1$
public static final ImageDescriptor DESC_DLCL_VIEW_MENU= createUnManaged(T_DLCL, "view_menu.gif"); //$NON-NLS-1$
public static final ImageDescriptor DESC_ELCL_VIEW_MENU= createUnManaged(T_ELCL, "view_menu.gif"); //$NON-NLS-1$
public static final String IMG_OBJS_QUICK_ASSIST= NAME_PREFIX + "quickassist_obj.gif"; //$NON-NLS-1$
public static final ImageDescriptor DESC_OBJS_QUICK_ASSIST = createManaged(T_OBJ, IMG_OBJS_QUICK_ASSIST);

View file

@ -43,6 +43,9 @@ public class ActionMessages extends NLS {
public static String MemberFilterActionGroup_hide_inactive_description;
public static String ActionUtil_notOnBuildPath_title;
public static String ActionUtil_notOnBuildPath_message;
public static String ActionUtil_warning_derived_dontShowAgain;
public static String ActionUtil_warning_derived_message;
public static String ActionUtil_warning_derived_title;
public static String SelectAllAction_label;
public static String SelectAllAction_tooltip;
public static String ToggleLinkingAction_label;

View file

@ -46,6 +46,9 @@ MemberFilterActionGroup_hide_inactive_description=Toggles the visibility of inac
ActionUtil_notOnBuildPath_title=Operation Cannot be Performed
ActionUtil_notOnBuildPath_message=The resource is not on the build path of a Java project.
ActionUtil_warning_derived_title=Derived File Encountered
ActionUtil_warning_derived_message=The file ''{0}'' is derived. Do you really want to edit it?
ActionUtil_warning_derived_dontShowAgain=In the future, never warn if editing a derived file.
SelectAllAction_label= Select A&ll
SelectAllAction_tooltip= Select All

View file

@ -7,13 +7,25 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.actions;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.internal.corext.util.Messages;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.viewsupport.BasicElementLabels;
/*
* http://dev.eclipse.org/bugs/show_bug.cgi?id=19104
@ -37,11 +49,12 @@ public class ActionUtil {
// return true;
}
public static boolean isProcessable(Shell shell, CEditor editor) {
public static boolean isProcessable(CEditor editor) {
if (editor == null)
return true;
Shell shell = editor.getSite().getShell();
ICElement input= SelectionConverter.getInput(editor);
// if a Java editor doesn't have an input of type Java element
// if a C/C++ editor doesn't have an input of type C element
// then it is for sure not on the build path
if (input == null) {
MessageDialog.openInformation(shell,
@ -56,7 +69,7 @@ public class ActionUtil {
if (!(element instanceof ICElement))
return true;
if (isOnBuildPath((ICElement)element))
if (isOnBuildPath((ICElement) element))
return true;
MessageDialog.openInformation(shell,
ActionMessages.ActionUtil_notOnBuildPath_title,
@ -73,5 +86,66 @@ public class ActionUtil {
// return false;
return true;
}
/**
* Check whether <code>editor</code> and <code>element</code> are
* processable and editable. If the editor edits the element, the validation
* is only performed once. If necessary, ask the user whether the file(s)
* should be edited.
*
* @param editor an editor, or <code>null</code> iff the action was not
* executed from an editor
* @param shell a shell to serve as parent for a dialog
* @param element the element to check, cannot be <code>null</code>
* @return <code>true</code> if the element can be edited,
* <code>false</code> otherwise
*/
public static boolean isEditable(CEditor editor, Shell shell, ICElement element) {
if (editor != null) {
ICElement input= SelectionConverter.getInput(editor);
if (input != null && input.equals(element.getAncestor(ICElement.C_UNIT)))
return isEditable(editor);
else
return isEditable(editor) && isEditable(shell, element);
}
return isEditable(shell, element);
}
public static boolean isEditable(CEditor editor) {
if (!isProcessable(editor))
return false;
return editor.validateEditorInputState();
}
public static boolean isEditable(Shell shell, ICElement element) {
if (!isProcessable(shell, element))
return false;
ICElement cu= element.getAncestor(ICElement.C_UNIT);
if (cu != null) {
IResource resource= cu.getResource();
if (resource != null && resource.isDerived()) {
// see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#validateEditorInputState()
final String warnKey= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WARN_IF_INPUT_DERIVED;
IPreferenceStore store= EditorsUI.getPreferenceStore();
if (!store.getBoolean(warnKey))
return true;
MessageDialogWithToggle toggleDialog= MessageDialogWithToggle.openYesNoQuestion(
shell,
ActionMessages.ActionUtil_warning_derived_title,
Messages.format(ActionMessages.ActionUtil_warning_derived_message, BasicElementLabels.getPathLabel(resource.getFullPath(), false)),
ActionMessages.ActionUtil_warning_derived_dontShowAgain,
false,
null,
null);
EditorsUI.getPreferenceStore().setValue(warnKey, !toggleDialog.getToggleState());
return toggleDialog.getReturnCode() == IDialogConstants.YES_ID;
}
}
return true;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2008 IBM Corporation and others.
* Copyright (c) 2000, 2010 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
@ -25,16 +25,17 @@ import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.operation.IThreadListener;
/**
* An <code>IRunnableWithProgress</code> that adapts and <code>IWorkspaceRunnable</code>
* so that is can be executed inside <code>IRunnableContext</code>. <code>OperationCanceledException</code>
* thrown by the adapted runnable are caught and re-thrown as a <code>InterruptedException</code>.
*/
public class WorkbenchRunnableAdapter implements IRunnableWithProgress {
public class WorkbenchRunnableAdapter implements IRunnableWithProgress, IThreadListener {
private IWorkspaceRunnable fWorkspaceRunnable;
private ISchedulingRule fRule;
private boolean fTransfer;
/**
* Runs a workspace runnable with the workspace lock.
@ -51,10 +52,30 @@ public class WorkbenchRunnableAdapter implements IRunnableWithProgress {
fRule= rule;
}
/**
* Runs a workspace runnable with the given lock or <code>null</code> to run with no lock at
* all.
*
* @param runnable the runnable
* @param rule the scheduling rule, or <code>null</code>
* @param transfer <code>true</code> iff the rule is to be transfered to the modal context
* thread
*/
public WorkbenchRunnableAdapter(IWorkspaceRunnable runnable, ISchedulingRule rule, boolean transfer) {
fWorkspaceRunnable= runnable;
fRule= rule;
fTransfer= transfer;
}
public ISchedulingRule getSchedulingRule() {
return fRule;
}
public void threadChange(Thread thread) {
if (fTransfer)
Job.getJobManager().transferRule(fRule, thread);
}
/*
* @see IRunnableWithProgress#run(IProgressMonitor)
*/

View file

@ -150,7 +150,6 @@ import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
import org.eclipse.ui.texteditor.ContentAssistAction;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IEditorStatusLine;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.IUpdate;
@ -1223,6 +1222,20 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
*/
private EditorSelectionChangedListener fEditorSelectionChangedListener;
/**
* Time when last error message got set.
*
* @since 5.3
*/
private long fErrorMessageTime;
/**
* Timeout for the error message.
*
* @since 5.3
*/
private static final long ERROR_MESSAGE_TIMEOUT= 1000;
/** The outline page */
protected CContentOutlinePage fOutlinePage;
@ -2847,26 +2860,27 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC
/**
* Sets the given message as error message to this editor's status line.
*
* @param msg message to be set
* @param message message to be set
*/
@Override
protected void setStatusLineErrorMessage(String msg) {
IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
if (statusLine != null)
statusLine.setMessage(true, msg, null);
public void setStatusLineErrorMessage(String message) {
long now= System.currentTimeMillis();
if (message != null || now - fErrorMessageTime > ERROR_MESSAGE_TIMEOUT) {
super.setStatusLineErrorMessage(message);
fErrorMessageTime= message != null ? now : 0;
}
}
/**
* Sets the given message as message to this editor's status line.
*
* @param msg message to be set
* @param message message to be set
* @since 3.0
*/
@Override
protected void setStatusLineMessage(String msg) {
IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
if (statusLine != null)
statusLine.setMessage(false, msg, null);
protected void setStatusLineMessage(String message) {
if (System.currentTimeMillis() - fErrorMessageTime > ERROR_MESSAGE_TIMEOUT)
super.setStatusLineMessage(message);
}
/**

View file

@ -9,14 +9,17 @@
* IBM Corporation - initial API and implementation
* QNX Software System
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.util.ArrayList;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
@ -45,16 +48,20 @@ import org.eclipse.cdt.internal.ui.util.SWTUtil;
/**
* The page for general C/C++ preferences.
*/
public class CPluginPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
public class CPluginPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
public static final String C_BASE_PREF_PAGE_ID= "org.eclipse.cdt.ui.preferences.CPluginPreferencePage"; //$NON-NLS-1$
private static final String USE_STRUCTURAL_PARSE_MODE_LABEL= PreferencesMessages.CPluginPreferencePage_structuralParseMode_label;
private static final int GROUP_VINDENT = 5;
private static final int GROUP_HINDENT = 20;
private ArrayList<Button> fCheckBoxes;
private Button b1, b2, b3;
public CPluginPreferencePage() {
super(GRID);
super();
setPreferenceStore(CUIPlugin.getDefault().getPreferenceStore());
setDescription(PreferencesMessages.CPluginPreferencePage_description);
fCheckBoxes= new ArrayList<Button>();
}
@Override
@ -63,46 +70,33 @@ public class CPluginPreferencePage extends FieldEditorPreferencePage implements
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), ICHelpContextIds.C_PREF_PAGE);
}
/**
* @see FieldEditorPreferencePage#createControl(Composite)
*/
@Override
protected void createFieldEditors() {
Composite parent= getFieldEditorParent();
protected Control createContents(Composite parent) {
initializeDialogUnits(parent);
Label caption= new Label(parent, SWT.NULL);
caption.setText(PreferencesMessages.CPluginPreferencePage_caption);
GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= 1;
caption.setLayoutData(gd);
Composite container= new Composite(parent, SWT.NONE);
GridLayout layout= new GridLayout();
layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth= 0;
layout.verticalSpacing= convertVerticalDLUsToPixels(10);
layout.horizontalSpacing= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
container.setLayout(layout);
addFiller(parent);
Group outlineViewGroup = addGroup(container, PreferencesMessages.CPluginPreferencePage_outline_view);
addCheckBox(outlineViewGroup, PreferencesMessages.CPluginPreferencePage_structuralParseMode_label,
PreferenceConstants.PREF_USE_STRUCTURAL_PARSE_MODE);
BooleanFieldEditor useStructuralParseMode= new BooleanFieldEditor(PreferenceConstants.PREF_USE_STRUCTURAL_PARSE_MODE, USE_STRUCTURAL_PARSE_MODE_LABEL, parent);
addField(useStructuralParseMode);
addNote(outlineViewGroup, PreferencesMessages.CPluginPreferencePage_performanceHint);
String noteTitle= PreferencesMessages.CPluginPreferencePage_note;
String noteMessage= PreferencesMessages.CPluginPreferencePage_performanceHint;
Composite noteControl= createNoteComposite(JFaceResources.getDialogFont(), parent, noteTitle, noteMessage);
gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= 1;
noteControl.setLayoutData(gd);
// Build either default cfg or all.
Group gr = new Group(parent, SWT.NONE);
gr.setText(PreferencesMessages.CPluginPreferencePage_0);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.verticalIndent = GROUP_VINDENT;
gr.setLayoutData(gd);
gr.setLayout(new GridLayout());
// Build either default configuration or all.
Group gr = addGroup(container, PreferencesMessages.CPluginPreferencePage_build_scope);
Label l1 = new Label(gr, SWT.NONE);
l1.setText(PreferencesMessages.CPluginPreferencePage_1);
gd = new GridData(GridData.FILL_HORIZONTAL);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.verticalIndent = GROUP_VINDENT;
l1.setLayoutData(gd);
boolean b = ACBuilder.needAllConfigBuild();
boolean needAllConfigBuild = ACBuilder.needAllConfigBuild();
b1 = new Button(gr, SWT.RADIO);
b1.setText(PreferencesMessages.CPluginPreferencePage_2);
@ -110,49 +104,36 @@ public class CPluginPreferencePage extends FieldEditorPreferencePage implements
gd.verticalIndent = GROUP_VINDENT;
gd.horizontalIndent = GROUP_HINDENT;
b1.setLayoutData(gd);
b1.setSelection(!b);
b1.setSelection(!needAllConfigBuild);
b2 = new Button(gr, SWT.RADIO);
b2.setText(PreferencesMessages.CPluginPreferencePage_3);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalIndent = GROUP_HINDENT;
b2.setLayoutData(gd);
b2.setSelection(b);
b2.setSelection(needAllConfigBuild);
noteControl= createNoteComposite(
JFaceResources.getDialogFont(),
gr,
PreferencesMessages.CPluginPreferencePage_note,
PreferencesMessages.CPluginPreferencePage_4);
gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.verticalIndent = GROUP_VINDENT;
noteControl.setLayoutData(gd);
addNote(gr, PreferencesMessages.CPluginPreferencePage_4);
// Building project dependencies
Group gr2 = new Group(parent, SWT.NONE);
gr2.setText(PreferencesMessages.CPluginPreferencePage_5);
GridData gd2 = new GridData(GridData.FILL_HORIZONTAL);
gd2.verticalIndent = GROUP_VINDENT;
gr2.setLayoutData(gd2);
gr2.setLayout(new GridLayout());
boolean b2 = ACBuilder.buildConfigResourceChanges();
// Building project dependencies.
Group gr2 = addGroup(container, PreferencesMessages.CPluginPreferencePage_building_configurations);
b3 = new Button(gr2, SWT.CHECK);
b3.setText(PreferencesMessages.CPluginPreferencePage_7);
gd2 = new GridData(GridData.FILL_HORIZONTAL);
GridData gd2 = new GridData(GridData.FILL_HORIZONTAL);
gd2.verticalIndent = GROUP_VINDENT;
b3.setLayoutData(gd2);
b3.setSelection(b2);
b3.setSelection(ACBuilder.buildConfigResourceChanges());
GridLayout layout = new GridLayout();
layout.numColumns= 2;
Group dontAskGroup= new Group(parent, SWT.NONE);
dontAskGroup.setLayout(layout);
dontAskGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
dontAskGroup.setText(PreferencesMessages.CPluginPreferencePage_cdtDialogs_group);
// Refactoring.
Group refactoringGroup = addGroup(container, PreferencesMessages.CPluginPreferencePage_refactoring_title);
addCheckBox(refactoringGroup,
PreferencesMessages.CPluginPreferencePage_refactoring_auto_save,
PreferenceConstants.REFACTOR_SAVE_ALL_EDITORS);
addCheckBox(refactoringGroup,
PreferencesMessages.CPluginPreferencePage_refactoring_lightweight,
PreferenceConstants.REFACTOR_LIGHTWEIGHT);
Group dontAskGroup= addGroup(container, PreferencesMessages.CPluginPreferencePage_cdtDialogs_group, 2);
Label label= new Label(dontAskGroup, SWT.WRAP);
label.setText(PreferencesMessages.CPluginPreferencePage_clearDoNotShowAgainSettings_label);
GridData data= new GridData(GridData.FILL, GridData.CENTER, true, false);
@ -171,23 +152,56 @@ public class CPluginPreferencePage extends FieldEditorPreferencePage implements
}
});
SWTUtil.setButtonDimensionHint(clearButton);
Dialog.applyDialogFont(parent);
Dialog.applyDialogFont(container);
return container;
}
private void addNote(Group parent, String noteMessage) {
Composite noteControl= createNoteComposite(JFaceResources.getDialogFont(), parent,
PreferencesMessages.CPluginPreferencePage_note, noteMessage);
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.verticalIndent = GROUP_VINDENT;
noteControl.setLayoutData(gd);
}
@Override
protected Composite createNoteComposite(Font font, Composite composite,
String title, String message) {
Composite messageComposite = super.createNoteComposite(font, composite,
title, message);
protected Composite createNoteComposite(Font font, Composite composite, String title, String message) {
Composite messageComposite = super.createNoteComposite(font, composite, title, message);
Control[] children = messageComposite.getChildren();
if (children.length == 2 && (children[1] instanceof Label)) {
// this is temporary fix for problem that 3 line note does not displayed properly within the group
Label messageLabel = (Label) children[1];
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint=400;
gd.widthHint=500;
messageLabel.setLayoutData(gd);
}
return messageComposite;
}
private Group addGroup(Composite parent, String label) {
return addGroup(parent, label, 1);
}
private Group addGroup(Composite parent, String label, int numColumns) {
Group group = new Group(parent, SWT.NONE);
group.setText(label);
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
group.setLayout(new GridLayout(numColumns, false));
return group;
}
private Button addCheckBox(Composite parent, String label, String key) {
Button button= new Button(parent, SWT.CHECK);
button.setText(label);
button.setData(key);
button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
button.setSelection(getPreferenceStore().getBoolean(key));
fCheckBoxes.add(button);
return button;
}
protected void addFiller(Composite composite) {
PixelConverter pixelConverter= new PixelConverter(composite);
Label filler= new Label(composite, SWT.LEFT );
@ -235,6 +249,12 @@ public class CPluginPreferencePage extends FieldEditorPreferencePage implements
public boolean performOk() {
if (!super.performOk())
return false;
IPreferenceStore store= getPreferenceStore();
for (int i= 0; i < fCheckBoxes.size(); i++) {
Button button= fCheckBoxes.get(i);
String key= (String) button.getData();
store.setValue(key, button.getSelection());
}
// tell the Core Plugin about this preference
CCorePlugin.getDefault().setStructuralParseMode(useStructuralParseMode());
ACBuilder.setAllConfigBuild(b2.getSelection());
@ -245,6 +265,12 @@ public class CPluginPreferencePage extends FieldEditorPreferencePage implements
@Override
protected void performDefaults() {
super.performDefaults();
IPreferenceStore store= getPreferenceStore();
for (int i= 0; i < fCheckBoxes.size(); i++) {
Button button= fCheckBoxes.get(i);
String key= (String) button.getData();
button.setSelection(store.getDefaultBoolean(key));
}
ACBuilder.setAllConfigBuild(false);
ACBuilder.setBuildConfigResourceChanges(false);
b1.setSelection(true);

View file

@ -304,20 +304,24 @@ public final class PreferencesMessages extends NLS {
public static String FileLanguagesPropertyPage_missingLanguage;
public static String FileLanguagesPropertyPage_mappingTableTitle;
public static String CPluginPreferencePage_0;
public static String CPluginPreferencePage_outline_view;
public static String CPluginPreferencePage_build_scope;
public static String CPluginPreferencePage_1;
public static String CPluginPreferencePage_2;
public static String CPluginPreferencePage_3;
public static String CPluginPreferencePage_4;
public static String CPluginPreferencePage_5;
public static String CPluginPreferencePage_building_configurations;
public static String CPluginPreferencePage_7;
public static String CPluginPreferencePage_caption;
public static String CPluginPreferencePage_description;
public static String CPluginPreferencePage_cdtDialogs_group;
public static String CPluginPreferencePage_clear_button;
public static String CPluginPreferencePage_clearDoNotShowAgainSettings_label;
public static String CPluginPreferencePage_structuralParseMode_label;
public static String CPluginPreferencePage_note;
public static String CPluginPreferencePage_performanceHint;
public static String CPluginPreferencePage_refactoring_title;
public static String CPluginPreferencePage_refactoring_auto_save;
public static String CPluginPreferencePage_refactoring_lightweight;
public static String PropertyAndPreferencePage_useworkspacesettings_change;
public static String PropertyAndPreferencePage_showprojectspecificsettings_label;

View file

@ -344,22 +344,24 @@ FileLanguagesPropertyPage_mappingTableTitle = Language mappings for this file
ProposalFilterPreferencesUtil_defaultFilterName=<Default Filter>
# C/C++ Preferences
CPluginPreferencePage_0=Build scope
CPluginPreferencePage_outline_view=Outline view
CPluginPreferencePage_build_scope=Build scope
CPluginPreferencePage_1=Commands 'Build project', 'Build All', 'Build Working Set':
CPluginPreferencePage_2=Build a&ctive configuration in each project
CPluginPreferencePage_3=Build a&ll configurations in each project
CPluginPreferencePage_4=This feature is applicable only to projects that support separate configurations.
CPluginPreferencePage_5=Building project configurations
CPluginPreferencePage_building_configurations=Building project configurations
CPluginPreferencePage_7=Build configurations only when there are Eclipse resource changes within the project and its references
CPluginPreferencePage_caption= General settings for C/C++ Development:
CPluginPreferencePage_cdtDialogs_group=CDT Dialogs
CPluginPreferencePage_description=General settings for C/C++ Development:
CPluginPreferencePage_cdtDialogs_group=C/C++ dialogs
CPluginPreferencePage_clear_button=Clear
CPluginPreferencePage_clearDoNotShowAgainSettings_label=Clear all 'do not show again' settings and show all hidden dialogs again
CPluginPreferencePage_structuralParseMode_label= &Follow unindexed header files when producing the outline view
CPluginPreferencePage_note= Note:
CPluginPreferencePage_performanceHint= Enabling this preference may have negative impact on performance.
CPluginPreferencePage_structuralParseMode_label=&Follow unindexed header files when producing the outline view
CPluginPreferencePage_note=Note:
CPluginPreferencePage_performanceHint=Enabling this preference may have negative impact on performance.
CPluginPreferencePage_refactoring_title=Refactoring C/C++ code
CPluginPreferencePage_refactoring_auto_save=&Save all modified resources automatically prior to refactoring
CPluginPreferencePage_refactoring_lightweight=Rename in editor &without dialog
PropertyAndPreferencePage_useworkspacesettings_change=Configure Workspace Settings...
PropertyAndPreferencePage_showprojectspecificsettings_label=Configure Project Specific Settings...

View file

@ -31,15 +31,14 @@ import org.eclipse.cdt.ui.CUIPlugin;
/**
* @author Emanuel Graf IFS
*
*/
public abstract class CRefactoringDescription extends RefactoringDescriptor {
public static final String FILE_NAME = "fileName"; //$NON-NLS-1$
public static final String SELECTION = "selection"; //$NON-NLS-1$
protected Map<String, String> arguments;
public CRefactoringDescription(String id, String project, String description, String comment, int flags, Map<String, String> arguments) {
public CRefactoringDescription(String id, String project, String description, String comment, int flags,
Map<String, String> arguments) {
super(id, project, description, comment, flags);
this.arguments = arguments;
}
@ -51,11 +50,11 @@ public abstract class CRefactoringDescription extends RefactoringDescriptor {
protected ISelection getSelection() throws CoreException {
ISelection selection;
String selectStrings[] = arguments.get(SELECTION).split(","); //$NON-NLS-1$
if(selectStrings.length >= 2) {
if (selectStrings.length >= 2) {
int offset = Integer.parseInt(selectStrings[0]);
int length = Integer.parseInt(selectStrings[1]);
selection = new TextSelection(offset,length);
}else {
} else {
throw new CoreException(new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, "Illegal Selection")); //$NON-NLS-1$
}
return selection;
@ -65,7 +64,7 @@ public abstract class CRefactoringDescription extends RefactoringDescriptor {
ICProject proj;
IProject iProject = ResourcesPlugin.getWorkspace().getRoot().getProject(getProject());
proj = CoreModel.getDefault().create(iProject);
if(proj == null) {
if (proj == null) {
throw new CoreException(new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, "Unknown Project")); //$NON-NLS-1$
}
return proj;
@ -80,5 +79,4 @@ public abstract class CRefactoringDescription extends RefactoringDescriptor {
}
return file;
}
}

View file

@ -0,0 +1,172 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 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;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
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.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ProgressMonitorWrapper;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.osgi.util.NLS;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.actions.WorkbenchRunnableAdapter;
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
/**
* Copy of org.eclipse.ltk.internal.ui.refactoring.ChangeExceptionHandler
*/
public class ChangeExceptionHandler {
public static class NotCancelableProgressMonitor extends ProgressMonitorWrapper {
public NotCancelableProgressMonitor(IProgressMonitor monitor) {
super(monitor);
}
@Override
public void setCanceled(boolean b) {
// ignore set cancel
}
@Override
public boolean isCanceled() {
return false;
}
}
private Shell fParent;
private String fName;
private static class RefactorErrorDialog extends ErrorDialog {
public RefactorErrorDialog(Shell parentShell, String dialogTitle, String dialogMessage, IStatus status, int displayMask) {
super(parentShell, dialogTitle, dialogMessage, status, displayMask);
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
Button ok= getButton(IDialogConstants.OK_ID);
ok.setText(Messages.ChangeExceptionHandler_undo_button);
Button abort= createButton(parent, IDialogConstants.CANCEL_ID, Messages.ChangeExceptionHandler_abort_button, true);
abort.moveBelow(ok);
abort.setFocus();
}
@Override
protected Control createMessageArea(Composite parent) {
Control result= super.createMessageArea(parent);
new Label(parent, SWT.NONE); // filler
Label label= new Label(parent, SWT.NONE);
label.setText(Messages.ChangeExceptionHandler_message);
label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
applyDialogFont(result);
return result;
}
}
public ChangeExceptionHandler(Shell parent, Refactoring refactoring) {
fParent= parent;
fName= refactoring.getName();
}
public void handle(Change change, RuntimeException exception) {
CUIPlugin.log(exception);
IStatus status= null;
if (exception.getMessage() == null) {
status= new Status(IStatus.ERROR, CUIPlugin.getPluginId(), IStatus.ERROR,
Messages.ChangeExceptionHandler_status_without_detail, exception);
} else {
status= new Status(IStatus.ERROR, CUIPlugin.getPluginId(), IStatus.ERROR,
exception.getMessage(), exception);
}
handle(change, status);
}
public void handle(Change change, CoreException exception) {
CUIPlugin.log(exception);
handle(change, exception.getStatus());
}
private void handle(Change change, IStatus status) {
if (change instanceof CompositeChange) {
Change undo= ((CompositeChange)change).getUndoUntilException();
if (undo != null) {
CUIPlugin.log(status);
final ErrorDialog dialog= new RefactorErrorDialog(fParent,
Messages.ChangeExceptionHandler_dialog_title,
NLS.bind(Messages.ChangeExceptionHandler_dialog_message, fName),
status, IStatus.OK | IStatus.INFO | IStatus.WARNING | IStatus.ERROR);
int result= dialog.open();
if (result == IDialogConstants.OK_ID) {
performUndo(undo);
}
return;
}
}
ErrorDialog dialog= new ErrorDialog(fParent,
Messages.ChangeExceptionHandler_dialog_title,
NLS.bind(Messages.ChangeExceptionHandler_dialog_message, fName),
status, IStatus.OK | IStatus.INFO | IStatus.WARNING | IStatus.ERROR);
dialog.open();
}
private void performUndo(final Change undo) {
IWorkspaceRunnable runnable= new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
monitor.beginTask("", 11); //$NON-NLS-1$
try {
undo.initializeValidationData(new NotCancelableProgressMonitor(new SubProgressMonitor(monitor, 1)));
if (undo.isValid(new SubProgressMonitor(monitor,1)).hasFatalError()) {
monitor.done();
return;
}
undo.perform(new SubProgressMonitor(monitor, 9));
} finally {
undo.dispose();
}
}
};
WorkbenchRunnableAdapter adapter= new WorkbenchRunnableAdapter(runnable,
ResourcesPlugin.getWorkspace().getRoot());
ProgressMonitorDialog dialog= new ProgressMonitorDialog(fParent);
try {
dialog.run(false, false, adapter);
} catch (InvocationTargetException e) {
ExceptionHandler.handle(e, fParent,
Messages.ChangeExceptionHandler_undo_dialog_title,
NLS.bind(Messages.ChangeExceptionHandler_undo_dialog_message, fName));
} catch (InterruptedException e) {
// can't happen
}
}
}

View file

@ -0,0 +1,25 @@
/*******************************************************************************
* Copyright (c) 2000, 2008 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
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
public interface IScheduledRefactoring {
/**
* The scheduling rule used to perform the
* refactoring.
*
* @return {@link ISchedulingRule} not null
*/
public ISchedulingRule getSchedulingRule();
}

View file

@ -35,6 +35,20 @@ public final class Messages extends NLS {
public static String Refactoring_Ambiguity;
public static String NodeContainer_Name;
public static String NO_FILE;
public static String RefactoringSaveHelper_unexpected_exception;
public static String RefactoringSaveHelper_saving;
public static String RefactoringSaveHelper_always_save;
public static String RefactoringSaveHelper_save_all_resources;
public static String RefactoringSaveHelper_must_save;
public static String ChangeExceptionHandler_abort_button;
public static String ChangeExceptionHandler_dialog_message;
public static String ChangeExceptionHandler_dialog_title;
public static String ChangeExceptionHandler_message;
public static String ChangeExceptionHandler_status_without_detail;
public static String ChangeExceptionHandler_undo_button;
public static String ChangeExceptionHandler_undo_dialog_message;
public static String ChangeExceptionHandler_undo_dialog_title;
public static String RefactoringExecutionHelper_cannot_execute;
static {
NLS.initializeMessages(Messages.class.getName(), Messages.class);

View file

@ -29,3 +29,17 @@ Refactoring_CantLoadTU=Can not load translation unit.
Refactoring_Ambiguity=Translation unit is ambiguous.
NO_FILE=File not found.
NodeContainer_Name=name:
RefactoringSaveHelper_unexpected_exception=An unexpected exception occurred. See the error log for more details.
RefactoringSaveHelper_saving=Saving Resources
RefactoringSaveHelper_always_save=&Always save all modified resources automatically prior to refactoring
RefactoringSaveHelper_save_all_resources=Save Modified Resources
RefactoringSaveHelper_must_save=Some modified resources must be saved before this operation.
ChangeExceptionHandler_undo_button=Undo
ChangeExceptionHandler_abort_button=Abort
ChangeExceptionHandler_message=\n Click 'Undo' to undo all successfully executed changes of the current refactoring.\n Click 'Abort' to abort the current refactoring.
ChangeExceptionHandler_dialog_title=Refactoring
ChangeExceptionHandler_status_without_detail=Exception does not provide a detail message
ChangeExceptionHandler_undo_dialog_title=Undo Refactoring
ChangeExceptionHandler_undo_dialog_message=An unexpected exception occurred while undoing the refactoring ''{0}''
ChangeExceptionHandler_dialog_message=An exception has been caught while processing the refactoring ''{0}''.
RefactoringExecutionHelper_cannot_execute=The operation cannot be performed due to the following problem:\n\n{0}

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 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;
import org.eclipse.cdt.core.model.ICElement;
/**
* Helper class to detect whether a certain refactoring can be enabled on
* a selection.
* <p>
* This class has been introduced to decouple actions from the refactoring code,
* in order not to eagerly load refactoring classes during action
* initialization.
* </p>
*
* @since 5.3
*/
public final class RefactoringAvailabilityTester {
public static boolean isRenameElementAvailable(ICElement element) {
return true;
}
}

View file

@ -0,0 +1,225 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 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;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.PerformChangeOperation;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringCore;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.ui.refactoring.RefactoringUI;
import org.eclipse.osgi.util.NLS;
import org.eclipse.cdt.internal.ui.actions.WorkbenchRunnableAdapter;
/**
* A helper class to execute a refactoring. The class takes care of pushing the
* undo change onto the undo stack and folding editor edits into one editor
* undo object.
*/
public class RefactoringExecutionHelper {
private final Refactoring fRefactoring;
private final Shell fParent;
private final IRunnableContext fExecContext;
private final int fStopSeverity;
private final int fSaveMode;
private class Operation implements IWorkspaceRunnable {
public Change fChange;
public PerformChangeOperation fPerformChangeOperation;
private final boolean fForked;
private final boolean fForkChangeExecution;
public Operation(boolean forked, boolean forkChangeExecution) {
fForked= forked;
fForkChangeExecution= forkChangeExecution;
}
public void run(IProgressMonitor pm) throws CoreException {
try {
pm.beginTask("", fForked && !fForkChangeExecution ? 7 : 11); //$NON-NLS-1$
pm.subTask(""); //$NON-NLS-1$
final RefactoringStatus status= fRefactoring.checkAllConditions(new SubProgressMonitor(pm, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
if (status.getSeverity() >= fStopSeverity) {
final boolean[] canceled= { false };
if (fForked) {
fParent.getDisplay().syncExec(new Runnable() {
public void run() {
canceled[0]= showStatusDialog(status);
}
});
} else {
canceled[0]= showStatusDialog(status);
}
if (canceled[0]) {
throw new OperationCanceledException();
}
}
fChange= fRefactoring.createChange(new SubProgressMonitor(pm, 2, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
fChange.initializeValidationData(new SubProgressMonitor(pm, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
fPerformChangeOperation= new PerformChangeOperation(fChange);//RefactoringUI.createUIAwareChangeOperation(fChange);
fPerformChangeOperation.setUndoManager(RefactoringCore.getUndoManager(), fRefactoring.getName());
if (fRefactoring instanceof IScheduledRefactoring)
fPerformChangeOperation.setSchedulingRule(((IScheduledRefactoring) fRefactoring).getSchedulingRule());
if (!fForked || fForkChangeExecution)
fPerformChangeOperation.run(new SubProgressMonitor(pm, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
} finally {
pm.done();
}
}
/**
* @param status the status to show
* @return <code>true</code> iff the operation should be cancelled
*/
private boolean showStatusDialog(RefactoringStatus status) {
Dialog dialog= RefactoringUI.createRefactoringStatusDialog(status, fParent, fRefactoring.getName(), false);
return dialog.open() == IDialogConstants.CANCEL_ID;
}
}
/**
* Creates a new refactoring execution helper.
*
* @param refactoring the refactoring
* @param stopSeverity a refactoring status constant from {@link RefactoringStatus}
* @param saveMode a save mode from {@link RefactoringSaveHelper}
* @param parent the parent shell
* @param context the runnable context
*/
public RefactoringExecutionHelper(Refactoring refactoring, int stopSeverity, int saveMode, Shell parent,
IRunnableContext context) {
super();
Assert.isNotNull(refactoring);
Assert.isNotNull(parent);
Assert.isNotNull(context);
fRefactoring= refactoring;
fStopSeverity= stopSeverity;
fParent= parent;
fExecContext= context;
fSaveMode= saveMode;
}
/**
* Must be called in the UI thread.
* @param fork if set, the operation will be forked
* @param cancelable if set, the operation will be cancelable
* @throws InterruptedException thrown when the operation is canceled
* @throws InvocationTargetException thrown when the operation failed to execute
*/
public void perform(boolean fork, boolean cancelable) throws InterruptedException, InvocationTargetException {
perform(fork, false, cancelable);
}
/**
* Must be called in the UI thread.<br>
* <strong>Use {@link #perform(boolean, boolean)} unless you know exactly what you are doing!</strong>
*
* @param fork if set, the operation will be forked
* @param forkChangeExecution if the change should not be executed in the UI thread: This may not work in any case
* @param cancelable if set, the operation will be cancelable
* @throws InterruptedException thrown when the operation is canceled
* @throws InvocationTargetException thrown when the operation failed to execute
*/
public void perform(boolean fork, boolean forkChangeExecution, boolean cancelable) throws InterruptedException, InvocationTargetException {
Assert.isTrue(Display.getCurrent() != null);
final IJobManager manager= Job.getJobManager();
final ISchedulingRule rule;
if (fRefactoring instanceof IScheduledRefactoring) {
rule= ((IScheduledRefactoring) fRefactoring).getSchedulingRule();
} else {
rule= ResourcesPlugin.getWorkspace().getRoot();
}
try {
try {
Runnable r= new Runnable() {
public void run() {
manager.beginRule(rule, null);
}
};
BusyIndicator.showWhile(fParent.getDisplay(), r);
} catch (OperationCanceledException e) {
throw new InterruptedException(e.getMessage());
}
RefactoringSaveHelper saveHelper= new RefactoringSaveHelper(fSaveMode);
if (!saveHelper.saveEditors(fParent))
throw new InterruptedException();
final Operation op= new Operation(fork, forkChangeExecution);
fRefactoring.setValidationContext(fParent);
try {
fExecContext.run(fork, cancelable, new WorkbenchRunnableAdapter(op, rule, true));
if (fork && !forkChangeExecution && op.fPerformChangeOperation != null)
fExecContext.run(false, false, new WorkbenchRunnableAdapter(op.fPerformChangeOperation, rule, true));
if (op.fPerformChangeOperation != null) {
RefactoringStatus validationStatus= op.fPerformChangeOperation.getValidationStatus();
if (validationStatus != null && validationStatus.hasFatalError()) {
MessageDialog.openError(fParent, fRefactoring.getName(),
NLS.bind(Messages.RefactoringExecutionHelper_cannot_execute,
validationStatus.getMessageMatchingSeverity(RefactoringStatus.FATAL)));
throw new InterruptedException();
}
}
} catch (InvocationTargetException e) {
PerformChangeOperation pco= op.fPerformChangeOperation;
if (pco != null && pco.changeExecutionFailed()) {
ChangeExceptionHandler handler= new ChangeExceptionHandler(fParent, fRefactoring);
Throwable inner= e.getTargetException();
if (inner instanceof RuntimeException) {
handler.handle(pco.getChange(), (RuntimeException)inner);
} else if (inner instanceof CoreException) {
handler.handle(pco.getChange(), (CoreException)inner);
} else {
throw e;
}
} else {
throw e;
}
} catch (OperationCanceledException e) {
throw new InterruptedException(e.getMessage());
} finally {
saveHelper.triggerIncrementalBuild();
}
} finally {
manager.endRule(rule);
fRefactoring.setValidationContext(null);
}
}
}

View file

@ -0,0 +1,223 @@
/*******************************************************************************
* Copyright (c) 2000, 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
*
* Contributors:
* IBM Corporation - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.GlobalBuildAction;
import org.eclipse.ui.dialogs.ListDialog;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.util.EditorUtility;
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
/**
* Helper to save dirty editors prior to starting a refactoring.
*
* @see PreferenceConstants#REFACTOR_SAVE_ALL_EDITORS
* @since 5.3
*
* @noextend This class is not intended to be subclassed by clients.
*/
public class RefactoringSaveHelper {
private boolean fFilesSaved;
private final int fSaveMode;
/**
* Save mode to save all dirty editors (always ask).
*/
public static final int SAVE_ALL_ALWAYS_ASK= 1;
/**
* Save mode to save all dirty editors.
*/
public static final int SAVE_ALL= 2;
/**
* Save mode to not save any editors.
*/
public static final int SAVE_NOTHING= 3;
/**
* Save mode to save all editors that are known to cause trouble for C refactorings, e.g.
* editors on compilation units that are not in working copy mode.
*/
public static final int SAVE_REFACTORING= 4;
/**
* Creates a refactoring save helper with the given save mode.
*
* @param saveMode one of the SAVE_* constants
*/
public RefactoringSaveHelper(int saveMode) {
Assert.isLegal(saveMode == SAVE_ALL_ALWAYS_ASK
|| saveMode == SAVE_ALL
|| saveMode == SAVE_NOTHING
|| saveMode == SAVE_REFACTORING);
fSaveMode= saveMode;
}
/**
* Saves all editors. Depending on the {@link PreferenceConstants#REFACTOR_SAVE_ALL_EDITORS}
* preference, the user is asked to save affected dirty editors.
*
* @param shell the parent shell for the confirmation dialog
* @return <code>true</code> if save was successful and refactoring can proceed;
* false if the refactoring must be canceled
*/
public boolean saveEditors(Shell shell) {
final IEditorPart[] dirtyEditors;
switch (fSaveMode) {
case SAVE_ALL_ALWAYS_ASK:
case SAVE_ALL:
dirtyEditors= EditorUtility.getDirtyEditors(true);
break;
case SAVE_REFACTORING:
dirtyEditors= EditorUtility.getDirtyEditorsToSave(false); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=175495
break;
case SAVE_NOTHING:
return true;
default:
throw new IllegalStateException(Integer.toString(fSaveMode));
}
if (dirtyEditors.length == 0)
return true;
if (!askSaveAllDirtyEditors(shell, dirtyEditors))
return false;
// Save isn't cancelable.
if (fSaveMode == SAVE_ALL_ALWAYS_ASK || fSaveMode == SAVE_ALL
|| RefactoringSavePreferences.getSaveAllEditors()) {
if (!CUIPlugin.getActiveWorkbenchWindow().getWorkbench().saveAllEditors(false))
return false;
} else {
IRunnableWithProgress runnable= new IRunnableWithProgress() {
public void run(IProgressMonitor pm) throws InterruptedException {
int count= dirtyEditors.length;
pm.beginTask("", count); //$NON-NLS-1$
for (int i= 0; i < count; i++) {
IEditorPart editor= dirtyEditors[i];
editor.doSave(new SubProgressMonitor(pm, 1));
if (pm.isCanceled())
throw new InterruptedException();
}
pm.done();
}
};
try {
PlatformUI.getWorkbench().getProgressService().runInUI(CUIPlugin.getActiveWorkbenchWindow(), runnable, null);
} catch (InterruptedException e) {
return false;
} catch (InvocationTargetException e) {
ExceptionHandler.handle(e, shell,
Messages.RefactoringSaveHelper_saving, Messages.RefactoringSaveHelper_unexpected_exception);
return false;
}
}
fFilesSaved= true;
return true;
}
/**
* Triggers an incremental build if this save helper did save files before.
*/
public void triggerIncrementalBuild() {
if (fFilesSaved && ResourcesPlugin.getWorkspace().getDescription().isAutoBuilding()) {
new GlobalBuildAction(CUIPlugin.getActiveWorkbenchWindow(), IncrementalProjectBuilder.INCREMENTAL_BUILD).run();
}
}
/**
* Returns whether this save helper did actually save any files.
*
* @return <code>true</code> iff files have been saved
*/
public boolean didSaveFiles() {
return fFilesSaved;
}
private boolean askSaveAllDirtyEditors(Shell shell, IEditorPart[] dirtyEditors) {
final boolean canSaveAutomatically= fSaveMode != SAVE_ALL_ALWAYS_ASK;
if (canSaveAutomatically && RefactoringSavePreferences.getSaveAllEditors()) //must save everything
return true;
ListDialog dialog= new ListDialog(shell) {
{
setShellStyle(getShellStyle() | SWT.APPLICATION_MODAL);
}
@Override
protected Control createDialogArea(Composite parent) {
Composite result= (Composite) super.createDialogArea(parent);
if (canSaveAutomatically) {
final Button check= new Button(result, SWT.CHECK);
check.setText(Messages.RefactoringSaveHelper_always_save);
check.setSelection(RefactoringSavePreferences.getSaveAllEditors());
check.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
RefactoringSavePreferences.setSaveAllEditors(check.getSelection());
}
});
applyDialogFont(result);
}
return result;
}
};
dialog.setTitle(Messages.RefactoringSaveHelper_save_all_resources);
dialog.setLabelProvider(createDialogLabelProvider());
dialog.setMessage(Messages.RefactoringSaveHelper_must_save);
dialog.setContentProvider(new ArrayContentProvider());
dialog.setInput(Arrays.asList(dirtyEditors));
return dialog.open() == Window.OK;
}
private ILabelProvider createDialogLabelProvider() {
return new LabelProvider() {
@Override
public Image getImage(Object element) {
return ((IEditorPart) element).getTitleImage();
}
@Override
public String getText(Object element) {
return ((IEditorPart) element).getTitle();
}
};
}
}

View file

@ -0,0 +1,31 @@
/*******************************************************************************
* Copyright (c) 2000, 2008 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;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
public class RefactoringSavePreferences {
public static final String PREF_SAVE_ALL_EDITORS= PreferenceConstants.REFACTOR_SAVE_ALL_EDITORS;
public static boolean getSaveAllEditors() {
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
return store.getBoolean(PREF_SAVE_ALL_EDITORS);
}
public static void setSaveAllEditors(boolean save) {
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
store.setValue(PREF_SAVE_ALL_EDITORS, save);
}
}

View file

@ -0,0 +1,55 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 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;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
/**
* A helper class to activate the UI of a refactoring
*/
public class RefactoringStarter {
private RefactoringStatus fStatus;
public boolean activate(RefactoringWizard wizard, Shell parent, String dialogTitle, int saveMode) {
RefactoringSaveHelper saveHelper= new RefactoringSaveHelper(saveMode);
if (!canActivate(saveHelper, parent))
return false;
try {
RefactoringWizardOpenOperation op= new RefactoringWizardOpenOperation(wizard);
int result= op.run(parent, dialogTitle);
fStatus= op.getInitialConditionCheckingStatus();
if (result == IDialogConstants.CANCEL_ID || result == RefactoringWizardOpenOperation.INITIAL_CONDITION_CHECKING_FAILED) {
saveHelper.triggerIncrementalBuild();
return false;
} else {
return true;
}
} catch (InterruptedException e) {
return false; // User action got canceled
}
}
public RefactoringStatus getInitialConditionCheckingStatus() {
return fStatus;
}
private boolean canActivate(RefactoringSaveHelper saveHelper, Shell shell) {
return saveHelper.saveEditors(shell);
}
}

View file

@ -8,6 +8,7 @@
* Contributors:
* Markus Schorn - initial API and implementation
* IBM Corporation
* Sergey Prigogin (Google)
******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.rename;
@ -25,8 +26,10 @@ import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
import org.eclipse.osgi.util.NLS;
@ -96,6 +99,7 @@ import org.eclipse.cdt.core.index.IIndex;
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.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
@ -105,7 +109,10 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitMethod;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethod;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.index.IIndexScope;
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.corext.util.CModelUtil;
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
/**
* Used per refactoring to cache the IASTTranslationUnits. Collects methods operating
@ -897,17 +904,39 @@ public class ASTManager {
if (ast == null) {
ICElement celem= CoreModel.getDefault().create(sourceFile);
if (celem instanceof ITranslationUnit) {
ITranslationUnit tu= (ITranslationUnit) celem;
int options= ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT |
ITranslationUnit.AST_SKIP_INDEXED_HEADERS;
try {
ast= tu.getAST(index, options);
} catch (CoreException e) {
status.addError(e.getMessage());
}
if (cacheit) {
fTranslationUnits.put(sourceFile, ast);
}
ITranslationUnit tu= CModelUtil.toWorkingCopy((ITranslationUnit) celem);
// if (tu instanceof IWorkingCopy) {
// synchronized (tu) {
// try {
// ast = ((IWorkingCopy) tu).reconcile(true, false, null);
// } catch (CModelException e) {
// CUIPlugin.log(e);
// }
// }
// }
// Try to get a shared AST before creating our own.
final IASTTranslationUnit[] ast_holder = new IASTTranslationUnit[1];
ASTProvider.getASTProvider().runOnAST(tu, ASTProvider.WAIT_IF_OPEN, null, new ASTRunnable() {
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
// Leaking of AST outside of runOnAST method is a dangerous, but it does not cause
// harm here since the index remains locked for the life time of the AST.
ast_holder[0] = ast;
return Status.OK_STATUS;
}
});
ast = ast_holder[0];
if (ast == null) {
int options= ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT |
ITranslationUnit.AST_SKIP_INDEXED_HEADERS;
try {
ast= tu.getAST(index, options);
} catch (CoreException e) {
status.addError(e.getMessage());
}
if (cacheit) {
fTranslationUnits.put(sourceFile, ast);
}
}
}
}
return ast;
@ -1096,6 +1125,7 @@ public class ASTManager {
private void findConflictingBindingsWithNewName(IASTTranslationUnit tu,
CRefactoringMatchStore store, final Set<IPath> paths,
final RefactoringStatus status) {
ASTNameVisitor nv = new ASTSpecificNameVisitor(fRenameTo) {
@Override
protected int visitName(IASTName name, boolean isDestructor) {
@ -1117,10 +1147,9 @@ public class ASTManager {
path= new Path(floc.getFileName());
IBinding binding= name.resolveBinding();
if (binding instanceof IProblemBinding) {
handleProblemBinding(name.getTranslationUnit(),
(IProblemBinding) binding, status);
handleProblemBinding(name.getTranslationUnit(), (IProblemBinding) binding, status);
} else if (binding != null) {
fConflictingBinding.add(binding);
fConflictingBinding.add(binding);
}
}
}
@ -1147,9 +1176,7 @@ public class ASTManager {
return name.getImageLocation();
}
private void analyzeAstTextMatchPair(CRefactoringMatch match, IASTName name,
RefactoringStatus status) {
private void analyzeAstTextMatchPair(CRefactoringMatch match, IASTName name, RefactoringStatus status) {
IBinding binding= name.resolveBinding();
int cmp= FALSE;
Integer cmpObj= fKnownBindings.get(binding);
@ -1417,7 +1444,7 @@ public class ASTManager {
String message2 = NLS.bind(RenameMessages.CRenameLocalProcessor_error_message2, conflict.getName());
String message3 = NLS.bind(RenameMessages.CRenameLocalProcessor_error_message3, what);
String space = " \n"; //$NON-NLS-1$
String formatted = message + space + message1 + space + message2 + space + message3;
String formatted = message + space + message1 + space + message2 + space + message3;
RefactoringStatusEntry[] entries= status.getEntries();
for (RefactoringStatusEntry entry : entries) {
if (formatted.equals(entry.getMessage())) {

View file

@ -1,12 +1,13 @@
/*******************************************************************************
* Copyright (c) 2004, 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2004, 2010 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;
@ -18,10 +19,10 @@ import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.ide.IDE;
@ -30,6 +31,7 @@ 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.refactoring.RefactoringStarter;
/**
* Serves to launch the various refactorings.
@ -80,40 +82,58 @@ public class CRefactory {
}
CRefactoringArgument iarg= new CRefactoringArgument(arg);
final CRenameProcessor processor = new CRenameProcessor(this, iarg);
try {
processor.lockIndex();
try {
CRenameRefactoring r= new CRenameRefactoring(processor);
RefactoringWizardOpenOperation op=
new RefactoringWizardOpenOperation(new CRenameRefactoringWizard(r));
op.run(shell, RenameMessages.CRefactory_title_rename);
} finally {
processor.unlockIndex();
}
} catch (CoreException e) {
CUIPlugin.log(e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
CRenameRefactoring refactoring= new CRenameRefactoring(processor);
openDialog(shell, refactoring, false);
}
public void rename(Shell shell, IWorkingCopy wc, ITextSelection s) {
IResource res= wc.getResource();
if (res instanceof IFile == false) {
public void rename(Shell shell, IWorkingCopy workingCopy, ITextSelection selection) {
IResource res= workingCopy.getResource();
if (!(res instanceof IFile)) {
return;
}
if (!IDE.saveAllEditors(new IResource[] { ResourcesPlugin.getWorkspace().getRoot() }, false)) {
return;
}
CRefactoringArgument iarg= new CRefactoringArgument((IFile) res, s.getOffset(), s.getLength());
CRefactoringArgument iarg=
new CRefactoringArgument((IFile) res, selection.getOffset(), selection.getLength());
final CRenameProcessor processor = new CRenameProcessor(this, iarg);
try {
CRenameRefactoring refactoring= new CRenameRefactoring(processor);
openDialog(shell, refactoring, false);
}
/**
* Opens the refactoring dialog.
*
* <p>
* This method has to be called from within the UI thread.
* </p>
*
* @param shell a shell used as a parent for the refactoring, preview, or error dialog
* @param showPreviewOnly if <code>true</code>, the dialog skips all user input pages and
* directly shows the preview or error page. Otherwise, shows all pages.
* @return <code>true</code> if the refactoring has been executed successfully,
* or <code>false</code> if it has been canceled.
*/
static boolean openDialog(Shell shell, CRenameRefactoring refactoring, boolean showPreviewOnly) {
try {
CRenameRefactoringWizard wizard;
if (!showPreviewOnly) {
wizard = new CRenameRefactoringWizard(refactoring);
} else {
wizard = new CRenameRefactoringWizard(refactoring) {
@Override
protected void addUserInputPages() {
// nothing to add
}
};
wizard.setForcePreviewReview(showPreviewOnly);
}
RefactoringStarter starter = new RefactoringStarter();
CRenameProcessor processor = (CRenameProcessor) refactoring.getProcessor();
processor.lockIndex();
try {
CRenameRefactoring r= new CRenameRefactoring(processor);
RefactoringWizardOpenOperation op=
new RefactoringWizardOpenOperation(new CRenameRefactoringWizard(r));
op.run(shell, RenameMessages.CRefactory_title_rename);
processor.checkInitialConditions(new NullProgressMonitor());
return starter.activate(wizard, shell, RenameMessages.CRefactory_title_rename, processor.getSaveMode());
} finally {
processor.unlockIndex();
}
@ -122,6 +142,7 @@ public class CRefactory {
} catch (CoreException e) {
CUIPlugin.log(e);
}
return false;
}
public TextSearchWrapper getTextSearch() {

View file

@ -1,15 +1,18 @@
/*******************************************************************************
* Copyright (c) 2005, 2008 Wind River Systems, Inc. and others.
* Copyright (c) 2005, 2010 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 org.eclipse.cdt.internal.ui.refactoring.RefactoringSaveHelper;
/**
* Rename processor that sets up the input page for renaming a global entity.
@ -24,4 +27,9 @@ public class CRenameGlobalProcessor extends CRenameProcessorDelegate {
CRefactory.OPTION_IN_COMMENT |
CRefactory.OPTION_IN_MACRO_DEFINITION);
}
@Override
public int getSaveMode() {
return RefactoringSaveHelper.SAVE_REFACTORING;
}
}

View file

@ -1,15 +1,18 @@
/*******************************************************************************
* Copyright (c) 2004,2008 Wind River Systems, Inc. and others.
* Copyright (c) 2004, 2010 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 org.eclipse.cdt.internal.ui.refactoring.RefactoringSaveHelper;
/**
* Rename processor setting up input page for renaming include directives.
*/
@ -29,4 +32,10 @@ public class CRenameIncludeProcessor extends CRenameProcessorDelegate {
protected int getAcceptedLocations(int selectedOptions) {
return selectedOptions | CRefactory.OPTION_IN_INCLUDE_DIRECTIVE;
}
@Override
public int getSaveMode() {
// TODO(sprigogin): Should it be SAVE_REFACTORING?
return RefactoringSaveHelper.SAVE_ALL;
}
}

View file

@ -6,7 +6,8 @@
* 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;
@ -23,6 +24,8 @@ import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringSaveHelper;
/**
* Rename processor, setting up input page for a local rename.
@ -80,4 +83,9 @@ public class CRenameLocalProcessor extends CRenameProcessorDelegate {
}
}
}
@Override
public int getSaveMode() {
return RefactoringSaveHelper.SAVE_NOTHING;
}
}

View file

@ -30,6 +30,8 @@ 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;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.cdt.core.CCProjectNature;
import org.eclipse.cdt.core.CCorePlugin;
@ -47,15 +49,16 @@ import org.eclipse.cdt.core.model.ICProject;
public class CRenameProcessor extends RenameProcessor {
public static final String IDENTIFIER= "org.eclips.cdt.refactoring.RenameProcessor"; //$NON-NLS-1$
private CRefactoringArgument fArgument;
private final CRefactoringArgument fArgument;
private CRenameProcessorDelegate fDelegate;
private String fReplacementText;
private String fWorkingSet;
private int fScope;
private int fSelectedOptions;
private CRefactory fManager;
private ASTManager fAstManager;
private final CRefactory fManager;
private final ASTManager fAstManager;
private IIndex fIndex;
private RefactoringStatus fInitialConditionsStatus;
public CRenameProcessor(CRefactory refactoringManager, CRefactoringArgument arg) {
fManager= refactoringManager;
@ -70,7 +73,7 @@ public class CRenameProcessor extends RenameProcessor {
// overrider
@Override
public Object[] getElements() {
return new Object[] {fArgument.getBinding()};
return new Object[] { fArgument.getBinding() };
}
// overrider
@ -101,15 +104,18 @@ public class CRenameProcessor extends RenameProcessor {
@Override
public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
throws CoreException, OperationCanceledException {
if (fInitialConditionsStatus != null) {
return fInitialConditionsStatus; // Already checked.
}
String identifier= null;
RefactoringStatus status= new RefactoringStatus();
fInitialConditionsStatus= new RefactoringStatus();
if (fArgument != null) {
fAstManager.analyzeArgument(fIndex, pm, status);
fAstManager.analyzeArgument(fIndex, pm, fInitialConditionsStatus);
identifier= fArgument.getName();
}
if (identifier == null || identifier.length() < 1) {
status.addFatalError(RenameMessages.CRenameTopProcessor_error_invalidTextSelection);
return status;
if (identifier == null || identifier.length() == 0) {
fInitialConditionsStatus.addFatalError(RenameMessages.CRenameTopProcessor_error_invalidTextSelection);
return fInitialConditionsStatus;
}
IFile file= fArgument.getSourceFile();
IPath path= null;
@ -122,12 +128,12 @@ public class CRenameProcessor extends RenameProcessor {
fDelegate= createDelegate();
if (fDelegate == null) {
status.addFatalError(RenameMessages.CRenameTopProcessor_error_invalidName);
return status;
fInitialConditionsStatus.addFatalError(RenameMessages.CRenameTopProcessor_error_invalidName);
return fInitialConditionsStatus;
}
RefactoringStatus s1= fDelegate.checkInitialConditions(new NullProgressMonitor());
status.merge(s1);
return status;
RefactoringStatus status= fDelegate.checkInitialConditions(new NullProgressMonitor());
fInitialConditionsStatus.merge(status);
return fInitialConditionsStatus;
}
private CRenameProcessorDelegate createDelegate() {
@ -252,9 +258,14 @@ public class CRenameProcessor extends RenameProcessor {
return fWorkingSet;
}
/**
* Sets the name of the working set. If the name of the working set is invalid,
* it's set to an empty string.
*/
public void setWorkingSet(String workingSet) {
fWorkingSet = workingSet;
fWorkingSet = checkWorkingSet(workingSet);
}
public String getReplacementText() {
return fReplacementText;
}
@ -289,4 +300,21 @@ public class CRenameProcessor extends RenameProcessor {
public IIndex getIndex() {
return fIndex;
}
/**
* @return a save mode from {@link org.eclipse.cdt.internal.ui.refactoring.RefactoringSaveHelper}
*/
public int getSaveMode() {
return fDelegate.getSaveMode();
}
private String checkWorkingSet(String workingSet) {
if (workingSet != null && workingSet.length() > 0) {
IWorkingSetManager wsManager= PlatformUI.getWorkbench().getWorkingSetManager();
if (wsManager.getWorkingSet(workingSet) != null) {
return workingSet;
}
}
return ""; //$NON-NLS-1$
}
}

View file

@ -376,4 +376,9 @@ public abstract class CRenameProcessorDelegate {
protected IBinding[] getBindingsToBeRenamed(RefactoringStatus status) {
return new IBinding[] {getArgument().getBinding()};
}
/**
* @return a save mode from {@link org.eclipse.cdt.internal.ui.refactoring.RefactoringSaveHelper}
*/
public abstract int getSaveMode();
}

View file

@ -1,32 +1,25 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 Wind River Systems, Inc. and others.
* Copyright (c) 2004, 2010 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 org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring;
import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
/**
* Refactoring implementation using a refactoring processor.
*/
public class CRenameRefactoring extends ProcessorBasedRefactoring {
private CRenameProcessor fProcessor;
public static final String ID = "org.eclipse.cdt.internal.ui.refactoring.rename.CRenameRefactoring"; //$NON-NLS-1$
public CRenameRefactoring(CRenameProcessor processor) {
super(processor);
fProcessor= processor;
}
@Override
public RefactoringProcessor getProcessor() {
return fProcessor;
}
}

View file

@ -13,7 +13,6 @@
package org.eclipse.cdt.internal.ui.refactoring.rename;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.window.Window;
import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
import org.eclipse.osgi.util.NLS;
@ -35,30 +34,15 @@ import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.IWorkingSetSelectionDialog;
import org.eclipse.cdt.core.CConventions;
import org.eclipse.cdt.ui.CUIPlugin;
/**
* Input page added to the standard refactoring wizard.
*/
public class CRenameRefactoringInputPage extends UserInputWizardPage {
public static final String PAGE_NAME = "RenameRefactoringPage"; //$NON-NLS-1$
public static final String PAGE_NAME = "RenameRefactoringPage"; //$NON-NLS-1$
private static final String KEY_IGNORE_VIRTUAL = "ignoreVirtual"; //$NON-NLS-1$
private static final String KEY_REFERENCES_INV = "references_inv"; //$NON-NLS-1$
private static final String KEY_COMMENT = "comment"; //$NON-NLS-1$
private static final String KEY_STRING = "string"; //$NON-NLS-1$
private static final String KEY_INACTIVE = "inactive"; //$NON-NLS-1$
private static final String KEY_SCOPE = "scope"; //$NON-NLS-1$
private static final String KEY_WORKING_SET_NAME = "workingset"; //$NON-NLS-1$
private static final String KEY_INCLUDE = "include"; //$NON-NLS-1$
private static final String KEY_MACRO_DEFINITION = "macroDefinition"; //$NON-NLS-1$
private static final String KEY_PREPROCESSOR = "preprocessor"; //$NON-NLS-1$
private static final String KEY_EXHAUSTIVE_FILE_SEARCH = "exhausiveFileSearch"; //$NON-NLS-1$
private IDialogSettings fDialogSettings;
private String fSearchString;
final CRenameRefactoringPreferences fPreferences;
private String fSearchString;
private int fOptions;
private int fForcePreviewOptions= 0;
private int fEnableScopeOptions;
@ -82,12 +66,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
public CRenameRefactoringInputPage() {
super(PAGE_NAME);
String key= "CRenameRefactoringInputPage"; //$NON-NLS-1$
IDialogSettings ds= CUIPlugin.getDefault().getDialogSettings();
fDialogSettings= ds.getSection(key);
if (fDialogSettings == null) {
fDialogSettings= ds.addNewSection(key);
}
fPreferences = new CRenameRefactoringPreferences();
}
private boolean hasOption(int options) {
@ -335,7 +314,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
if (fWorkspace != null) {
int choice;
try {
choice= fDialogSettings.getInt(KEY_SCOPE);
choice= fPreferences.getInt(CRenameRefactoringPreferences.KEY_SCOPE);
} catch (Exception e) {
choice= TextSearchWrapper.SCOPE_RELATED_PROJECTS;
}
@ -357,26 +336,26 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
}
processor.setScope(choice);
String workingSet= checkWorkingSet(fDialogSettings.get(KEY_WORKING_SET_NAME));
fWorkingSetSpec.setText(workingSet);
processor.setWorkingSet(workingSet);
String workingSet= fPreferences.get(CRenameRefactoringPreferences.KEY_WORKING_SET_NAME);
processor.setWorkingSet(workingSet); // CRenameProcessor validates the working set name.
fWorkingSetSpec.setText(processor.getWorkingSet());
}
if (fDoVirtual != null) {
boolean val= !fDialogSettings.getBoolean(KEY_IGNORE_VIRTUAL);
boolean val= !fPreferences.getBoolean(CRenameRefactoringPreferences.KEY_IGNORE_VIRTUAL);
fDoVirtual.setSelection(val);
}
if (fReferences != null) {
boolean val= !fDialogSettings.getBoolean(KEY_REFERENCES_INV);
boolean val= !fPreferences.getBoolean(CRenameRefactoringPreferences.KEY_REFERENCES_INV);
fReferences.setSelection(val);
}
initOption(fInComment, KEY_COMMENT);
initOption(fInString, KEY_STRING);
initOption(fInInclude, KEY_INCLUDE);
initOption(fInMacro, KEY_MACRO_DEFINITION);
initOption(fInPreprocessor, KEY_PREPROCESSOR);
initOption(fInInactiveCode, KEY_INACTIVE);
initOption(fExhausiveFileSearch, KEY_EXHAUSTIVE_FILE_SEARCH);
initOption(fInComment, CRenameRefactoringPreferences.KEY_COMMENT);
initOption(fInString, CRenameRefactoringPreferences.KEY_STRING);
initOption(fInInclude, CRenameRefactoringPreferences.KEY_INCLUDE);
initOption(fInMacro, CRenameRefactoringPreferences.KEY_MACRO_DEFINITION);
initOption(fInPreprocessor, CRenameRefactoringPreferences.KEY_PREPROCESSOR);
initOption(fInInactiveCode, CRenameRefactoringPreferences.KEY_INACTIVE);
initOption(fExhausiveFileSearch, CRenameRefactoringPreferences.KEY_EXHAUSTIVE_FILE_SEARCH);
}
private int computeSelectedOptions() {
@ -386,8 +365,8 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
options |= computeOption(fInComment, CRefactory.OPTION_IN_COMMENT);
options |= computeOption(fInString, CRefactory.OPTION_IN_STRING_LITERAL);
options |= computeOption(fInInclude, CRefactory.OPTION_IN_INCLUDE_DIRECTIVE);
options |= computeOption(fInPreprocessor, CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE);
options |= computeOption(fInMacro, CRefactory.OPTION_IN_MACRO_DEFINITION);
options |= computeOption(fInPreprocessor, CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE);
options |= computeOption(fInInactiveCode, CRefactory.OPTION_IN_INACTIVE_CODE);
options |= computeOption(fExhausiveFileSearch, CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH);
return options;
@ -403,21 +382,11 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
private void initOption(Button button, String key) {
boolean val= false;
if (button != null) {
val= fDialogSettings.getBoolean(key);
val= fPreferences.getBoolean(key);
button.setSelection(val);
}
}
private String checkWorkingSet(String ws) {
if (ws != null && ws.length() > 0) {
IWorkingSetManager wsManager= PlatformUI.getWorkbench().getWorkingSetManager();
if (wsManager.getWorkingSet(ws)!=null) {
return ws;
}
}
return ""; //$NON-NLS-1$
}
private void storePreferences() {
if (fWorkspace != null) {
int choice= TextSearchWrapper.SCOPE_RELATED_PROJECTS;
@ -428,47 +397,47 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
} else if (fWorkingSet.getSelection()) {
choice= TextSearchWrapper.SCOPE_WORKING_SET;
}
fDialogSettings.put(KEY_SCOPE, choice);
fDialogSettings.put(KEY_WORKING_SET_NAME, fWorkingSetSpec.getText());
fPreferences.put(CRenameRefactoringPreferences.KEY_SCOPE, choice);
fPreferences.put(CRenameRefactoringPreferences.KEY_WORKING_SET_NAME, fWorkingSetSpec.getText());
}
if (fDoVirtual != null) {
fDialogSettings.put(KEY_IGNORE_VIRTUAL, !fDoVirtual.getSelection());
fPreferences.put(CRenameRefactoringPreferences.KEY_IGNORE_VIRTUAL, !fDoVirtual.getSelection());
}
if (fReferences != null) {
fDialogSettings.put(KEY_REFERENCES_INV, !fReferences.getSelection());
fPreferences.put(CRenameRefactoringPreferences.KEY_REFERENCES_INV, !fReferences.getSelection());
}
if (fInComment != null) {
fDialogSettings.put(KEY_COMMENT, fInComment.getSelection());
fPreferences.put(CRenameRefactoringPreferences.KEY_COMMENT, fInComment.getSelection());
}
if (fInString != null) {
fDialogSettings.put(KEY_STRING, fInString.getSelection());
fPreferences.put(CRenameRefactoringPreferences.KEY_STRING, fInString.getSelection());
}
if (fInInclude != null) {
fDialogSettings.put(KEY_INCLUDE, fInInclude.getSelection());
fPreferences.put(CRenameRefactoringPreferences.KEY_INCLUDE, fInInclude.getSelection());
}
if (fInPreprocessor != null) {
fDialogSettings.put(KEY_PREPROCESSOR, fInPreprocessor.getSelection());
fPreferences.put(CRenameRefactoringPreferences.KEY_PREPROCESSOR, fInPreprocessor.getSelection());
}
if (fInMacro != null) {
fDialogSettings.put(KEY_MACRO_DEFINITION, fInMacro.getSelection());
fPreferences.put(CRenameRefactoringPreferences.KEY_MACRO_DEFINITION, fInMacro.getSelection());
}
if (fInInactiveCode != null) {
fDialogSettings.put(KEY_INACTIVE, fInInactiveCode.getSelection());
fPreferences.put(CRenameRefactoringPreferences.KEY_INACTIVE, fInInactiveCode.getSelection());
}
if (fExhausiveFileSearch != null) {
fDialogSettings.put(KEY_EXHAUSTIVE_FILE_SEARCH, fExhausiveFileSearch.getSelection());
fPreferences.put(CRenameRefactoringPreferences.KEY_EXHAUSTIVE_FILE_SEARCH, fExhausiveFileSearch.getSelection());
}
}
protected void onSelectWorkingSet() {
CRenameProcessor processor= getRenameProcessor();
String wsName= checkWorkingSet(fWorkingSetSpec.getText());
String wsName= fWorkingSetSpec.getText();
IWorkingSetManager wsManager= PlatformUI.getWorkbench().getWorkingSetManager();
IWorkingSetSelectionDialog dlg=
wsManager.createWorkingSetSelectionDialog(getShell(), false);
IWorkingSet currentWorkingSet= wsManager.getWorkingSet(wsName);
if (currentWorkingSet != null) {
dlg.setSelection(new IWorkingSet[] {currentWorkingSet});
dlg.setSelection(new IWorkingSet[] { currentWorkingSet });
}
IWorkingSet ws= null;
if (dlg.open() == Window.OK) {
@ -486,8 +455,8 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
}
}
fWorkingSetSpec.setText(wsName);
processor.setWorkingSet(wsName);
processor.setWorkingSet(wsName); // CRenameProcessor validates the working set name.
fWorkingSetSpec.setText(processor.getWorkingSet());
updateEnablement();
}

View file

@ -0,0 +1,90 @@
/*******************************************************************************
* Copyright (c) 2010 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.jface.dialogs.IDialogSettings;
import org.eclipse.cdt.ui.CUIPlugin;
public class CRenameRefactoringPreferences {
private static final String DIALOG_SETTINGS_KEY = "CRenameRefactoringInputPage"; //$NON-NLS-1$
public static final String KEY_IGNORE_VIRTUAL = "ignoreVirtual"; //$NON-NLS-1$
public static final String KEY_REFERENCES_INV = "references_inv"; //$NON-NLS-1$
public static final String KEY_COMMENT = "comment"; //$NON-NLS-1$
public static final String KEY_STRING = "string"; //$NON-NLS-1$
public static final String KEY_INACTIVE = "inactive"; //$NON-NLS-1$
public static final String KEY_SCOPE = "scope"; //$NON-NLS-1$
public static final String KEY_WORKING_SET_NAME = "workingset"; //$NON-NLS-1$
public static final String KEY_INCLUDE = "include"; //$NON-NLS-1$
public static final String KEY_MACRO_DEFINITION = "macroDefinition"; //$NON-NLS-1$
public static final String KEY_PREPROCESSOR = "preprocessor"; //$NON-NLS-1$
public static final String KEY_EXHAUSTIVE_FILE_SEARCH = "exhausiveFileSearch"; //$NON-NLS-1$
private IDialogSettings fDialogSettings;
public CRenameRefactoringPreferences() {
super();
IDialogSettings ds= CUIPlugin.getDefault().getDialogSettings();
fDialogSettings= ds.getSection(DIALOG_SETTINGS_KEY);
if (fDialogSettings == null) {
fDialogSettings= ds.addNewSection(DIALOG_SETTINGS_KEY);
}
}
public String get(String key) {
return fDialogSettings.get(key);
}
public boolean getBoolean(String key) {
return fDialogSettings.getBoolean(key);
}
public int getInt(String key) {
return fDialogSettings.getInt(key);
}
public void put(String key, int value) {
fDialogSettings.put(key, value);
}
public void put(String key, String value) {
fDialogSettings.put(key, value);
}
public void put(String key, boolean value) {
fDialogSettings.put(key, value);
}
public int getOptions() {
int options= 0;
if (!getBoolean(KEY_IGNORE_VIRTUAL))
options |= CRefactory.OPTION_DO_VIRTUAL;
if (!getBoolean(KEY_REFERENCES_INV))
options |= CRefactory.OPTION_IN_CODE;
if (getBoolean(KEY_COMMENT))
options |= CRefactory.OPTION_IN_COMMENT;
if (getBoolean(KEY_STRING))
options |= CRefactory.OPTION_IN_STRING_LITERAL;
if (getBoolean(KEY_INCLUDE))
options |= CRefactory.OPTION_IN_INCLUDE_DIRECTIVE;
if (getBoolean(KEY_MACRO_DEFINITION))
options |= CRefactory.OPTION_IN_MACRO_DEFINITION;
if (getBoolean(KEY_PREPROCESSOR))
options |= CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE;
if (getBoolean(KEY_INACTIVE))
options |= CRefactory.OPTION_IN_INACTIVE_CODE;
if (getBoolean(KEY_EXHAUSTIVE_FILE_SEARCH))
options |= CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH;
return options;
}
}

View file

@ -0,0 +1,856 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 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 org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
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.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tracker;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener2;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.bindings.keys.IKeyLookup;
import org.eclipse.jface.bindings.keys.KeyLookupFactory;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.util.Geometry;
import org.eclipse.jface.util.Util;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.IViewportListener;
import org.eclipse.jface.text.IWidgetTokenKeeper;
import org.eclipse.jface.text.IWidgetTokenKeeperExtension;
import org.eclipse.jface.text.IWidgetTokenOwner;
import org.eclipse.jface.text.IWidgetTokenOwnerExtension;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.keys.IBindingService;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.CPluginImages;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.editor.ICEditorActionDefinitionIds;
import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage;
public class RenameInformationPopup implements IWidgetTokenKeeper, IWidgetTokenKeeperExtension {
private class PopupVisibilityManager implements IPartListener2, ControlListener, MouseListener, KeyListener, ITextListener, IViewportListener {
public void start() {
fEditor.getSite().getWorkbenchWindow().getPartService().addPartListener(this);
final ISourceViewer viewer= fEditor.getViewer();
final StyledText textWidget= viewer.getTextWidget();
textWidget.addControlListener(this);
textWidget.addMouseListener(this);
textWidget.addKeyListener(this);
fEditor.getSite().getShell().addControlListener(this);
viewer.addTextListener(this);
viewer.addViewportListener(this);
fPopup.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
fEditor.getSite().getWorkbenchWindow().getPartService().removePartListener(PopupVisibilityManager.this);
if (!textWidget.isDisposed()) {
textWidget.removeControlListener(PopupVisibilityManager.this);
textWidget.removeMouseListener(PopupVisibilityManager.this);
textWidget.removeKeyListener(PopupVisibilityManager.this);
}
fEditor.getSite().getShell().removeControlListener(PopupVisibilityManager.this);
viewer.removeTextListener(PopupVisibilityManager.this);
viewer.removeViewportListener(PopupVisibilityManager.this);
if (fMenuImage != null) {
fMenuImage.dispose();
fMenuImage= null;
}
if (fMenuManager != null) {
fMenuManager.dispose();
fMenuManager= null;
}
fRenameLinkedMode.cancel();
}
});
}
public void partActivated(IWorkbenchPartReference partRef) {
IWorkbenchPart fPart= fEditor.getEditorSite().getPart();
if (partRef.getPart(false) == fPart) {
updateVisibility();
}
}
public void partBroughtToTop(IWorkbenchPartReference partRef) {
}
public void partClosed(IWorkbenchPartReference partRef) {
}
public void partDeactivated(IWorkbenchPartReference partRef) {
IWorkbenchPart fPart= fEditor.getEditorSite().getPart();
if (fPopup != null && !fPopup.isDisposed() && partRef.getPart(false) == fPart) {
fPopup.setVisible(false);
}
}
public void partHidden(IWorkbenchPartReference partRef) {
}
public void partInputChanged(IWorkbenchPartReference partRef) {
}
public void partOpened(IWorkbenchPartReference partRef) {
}
public void partVisible(IWorkbenchPartReference partRef) {
}
public void controlMoved(ControlEvent e) {
updatePopupLocation(true);
updateVisibility(); //only for hiding outside editor area
}
public void controlResized(ControlEvent e) {
updatePopupLocation(true);
updateVisibility(); //only for hiding outside editor area
}
public void mouseDoubleClick(MouseEvent e) {
}
public void mouseDown(MouseEvent e) {
}
public void mouseUp(MouseEvent e) {
updatePopupLocation(false);
updateVisibility();
}
public void keyPressed(KeyEvent e) {
updatePopupLocation(false);
updateVisibility();
}
public void keyReleased(KeyEvent e) {
}
public void textChanged(TextEvent event) {
if (!event.getViewerRedrawState())
return;
updatePopupLocation(false);
updateVisibility(); //only for hiding outside editor area
}
public void viewportChanged(int verticalOffset) {
updatePopupLocation(true);
updateVisibility(); //only for hiding outside editor area
}
}
/**
* Cached platform flag for dealing with platform-specific issue:
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=219326 : Shell with custom region and SWT.NO_TRIM still has border
*/
private static boolean MAC = Util.isMac();
private static final int WIDGET_PRIORITY= 1000;
private static final String DIALOG_SETTINGS_SECTION= "RenameInformationPopup"; //$NON-NLS-1$
private static final String SNAP_POSITION_KEY= "snap_position"; //$NON-NLS-1$
private static final int SNAP_POSITION_UNDER_RIGHT_FIELD= 0;
private static final int SNAP_POSITION_OVER_RIGHT_FIELD= 1;
private static final int SNAP_POSITION_UNDER_LEFT_FIELD= 2;
private static final int SNAP_POSITION_OVER_LEFT_FIELD= 3;
private static final int SNAP_POSITION_LOWER_RIGHT= 4;
private static final int POPUP_VISIBILITY_DELAY= 300;
/**
* Offset of info hover arrow from the left or right side.
*/
private static final int HAO= 10;
/**
* Width of info hover arrow.
*/
private static final int HAW= 8;
/**
* Height of info hover arrow.
*/
private static final int HAH= 10;
/**
* Gap between linked position and popup.
*/
private static final int GAP= 2;
private final CEditor fEditor;
private final RenameLinkedMode fRenameLinkedMode;
private int fSnapPosition;
private boolean fSnapPositionChanged;
private Shell fPopup;
private GridLayout fPopupLayout;
private Region fRegion;
private Image fMenuImage;
private MenuManager fMenuManager;
private ToolBar fToolBar;
private String fOpenDialogBinding= ""; //$NON-NLS-1$
private boolean fIsMenuUp= false;
private boolean fDelayJobFinished= false;
public RenameInformationPopup(CEditor editor, RenameLinkedMode renameLinkedMode) {
fEditor= editor;
fRenameLinkedMode= renameLinkedMode;
restoreSnapPosition();
}
private void restoreSnapPosition() {
IDialogSettings settings= getDialogSettings();
try {
fSnapPosition= settings.getInt(SNAP_POSITION_KEY);
} catch (NumberFormatException e) {
// default:
fSnapPosition= SNAP_POSITION_UNDER_LEFT_FIELD;
}
fSnapPositionChanged= true;
}
private IDialogSettings getDialogSettings() {
return CUIPlugin.getDefault().getDialogSettingsSection(DIALOG_SETTINGS_SECTION);
}
public void open() {
// Must cache here, since editor context is not available in menu from popup shell:
fOpenDialogBinding= getOpenDialogBinding();
Shell workbenchShell= fEditor.getSite().getShell();
final Display display= workbenchShell.getDisplay();
fPopup= new Shell(workbenchShell, SWT.ON_TOP | SWT.NO_TRIM | SWT.TOOL);
fPopupLayout= new GridLayout(2, false);
fPopupLayout.marginWidth= 1;
fPopupLayout.marginHeight= 1;
fPopupLayout.marginLeft= 4;
fPopupLayout.horizontalSpacing= 0;
fPopup.setLayout(fPopupLayout);
createContent(fPopup);
updatePopupLocation(true);
new PopupVisibilityManager().start();
// Leave linked mode when popup loses focus
// (except when focus goes back to workbench window or menu is open):
fPopup.addShellListener(new ShellAdapter() {
@Override
public void shellDeactivated(ShellEvent e) {
if (fIsMenuUp)
return;
final Shell editorShell= fEditor.getSite().getShell();
display.asyncExec(new Runnable() {
// post to UI thread since editor shell only gets activated after popup has lost focus
public void run() {
Shell activeShell= display.getActiveShell();
if (activeShell != editorShell) {
fRenameLinkedMode.cancel();
}
}
});
}
});
if (!MAC) { // carbon and cocoa draw their own border...
fPopup.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent pe) {
pe.gc.drawPolygon(getPolygon(true));
}
});
}
// fPopup.moveBelow(null); // make sure hovers are on top of the info popup
// XXX workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=170774
// fPopup.moveBelow(workbenchShell.getShells()[0]);
UIJob delayJob= new UIJob(display, RenameMessages.RenameInformationPopup_delayJobName) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
fDelayJobFinished= true;
if (fPopup != null && !fPopup.isDisposed()) {
updateVisibility();
}
return Status.OK_STATUS;
}
};
delayJob.setSystem(true);
delayJob.setPriority(Job.INTERACTIVE);
delayJob.schedule(POPUP_VISIBILITY_DELAY);
}
public void close() {
if (fPopup != null) {
if (!fPopup.isDisposed()) {
fPopup.close();
}
fPopup= null;
}
releaseWidgetToken();
if (fRegion != null) {
if (!fRegion.isDisposed()) {
fRegion.dispose();
}
}
}
public Shell getShell() {
return fPopup;
}
private void updatePopupLocation(boolean force) {
if (!force && fSnapPosition == SNAP_POSITION_LOWER_RIGHT)
return;
packPopup();
Point loc= computePopupLocation(fSnapPosition);
if (loc != null && !loc.equals(fPopup.getLocation())) {
fPopup.setLocation(loc);
// XXX workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=170774
// fPopup.moveBelow(fEditor.getSite().getShell().getShells()[0]);
}
}
private void updateVisibility() {
if (fPopup != null && !fPopup.isDisposed() && fDelayJobFinished) {
boolean visible= false;
//TODO: Check for visibility of linked position, not whether popup is outside of editor?
if (fRenameLinkedMode.isCaretInLinkedPosition()) {
StyledText textWidget= fEditor.getViewer().getTextWidget();
Rectangle eArea= Geometry.toDisplay(textWidget, textWidget.getClientArea());
Rectangle pBounds= fPopup.getBounds();
pBounds.x -= GAP;
pBounds.y -= GAP;
pBounds.width += 2 * GAP;
pBounds.height += 2 * GAP;
if (eArea.intersects(pBounds)) {
visible= true;
}
}
if (visible && !fPopup.isVisible()) {
ISourceViewer viewer= fEditor.getViewer();
if (viewer instanceof IWidgetTokenOwnerExtension) {
IWidgetTokenOwnerExtension widgetTokenOwnerExtension= (IWidgetTokenOwnerExtension) viewer;
widgetTokenOwnerExtension.requestWidgetToken(this, WIDGET_PRIORITY);
}
} else if (!visible && fPopup.isVisible()) {
releaseWidgetToken();
}
fPopup.setVisible(visible);
}
}
private void releaseWidgetToken() {
ISourceViewer viewer= fEditor.getViewer();
if (viewer instanceof IWidgetTokenOwner) {
IWidgetTokenOwner widgetTokenOwner= (IWidgetTokenOwner) viewer;
widgetTokenOwner.releaseWidgetToken(this);
}
}
/**
* @param snapPosition one of the SNAP_POSITION_* constants
* @return the location in display coordinates or <code>null</code> iff not visible
*/
private Point computePopupLocation(int snapPosition) {
if (fPopup == null || fPopup.isDisposed())
return null;
switch (snapPosition) {
case SNAP_POSITION_LOWER_RIGHT:
{
StyledText eWidget= fEditor.getViewer().getTextWidget();
Rectangle eBounds= eWidget.getClientArea();
Point eLowerRight= eWidget.toDisplay(eBounds.x + eBounds.width, eBounds.y + eBounds.height);
Point pSize= getExtent();
return new Point(eLowerRight.x - pSize.x - 5, eLowerRight.y - pSize.y - 5);
}
case SNAP_POSITION_UNDER_RIGHT_FIELD:
case SNAP_POSITION_OVER_RIGHT_FIELD:
{
LinkedPosition position= fRenameLinkedMode.getCurrentLinkedPosition();
if (position == null)
return null;
ISourceViewer viewer= fEditor.getViewer();
ITextViewerExtension5 viewer5= (ITextViewerExtension5) viewer;
int widgetOffset= viewer5.modelOffset2WidgetOffset(position.offset + position.length);
StyledText textWidget= viewer.getTextWidget();
Point pos= textWidget.getLocationAtOffset(widgetOffset);
Point pSize= getExtent();
if (snapPosition == SNAP_POSITION_OVER_RIGHT_FIELD) {
pos.y-= pSize.y + GAP;
} else {
pos.y+= textWidget.getLineHeight(widgetOffset) + GAP;
}
pos.x+= GAP;
Point dPos= textWidget.toDisplay(pos);
Rectangle displayBounds= textWidget.getDisplay().getClientArea();
Rectangle dPopupRect= Geometry.createRectangle(dPos, pSize);
Geometry.moveInside(dPopupRect, displayBounds);
return new Point(dPopupRect.x, dPopupRect.y);
}
case SNAP_POSITION_UNDER_LEFT_FIELD:
case SNAP_POSITION_OVER_LEFT_FIELD:
default: // same as SNAP_POSITION_UNDER_LEFT_FIELD
{
LinkedPosition position= fRenameLinkedMode.getCurrentLinkedPosition();
if (position == null)
return null;
ISourceViewer viewer= fEditor.getViewer();
ITextViewerExtension5 viewer5= (ITextViewerExtension5) viewer;
int widgetOffset= viewer5.modelOffset2WidgetOffset(position.offset/* + position.length*/);
StyledText textWidget= viewer.getTextWidget();
Point pos= textWidget.getLocationAtOffset(widgetOffset);
Point pSize= getExtent();
pSize.y+= HAH + 1;
pos.x-= HAO;
if (snapPosition == SNAP_POSITION_OVER_LEFT_FIELD) {
pos.y-= pSize.y;
} else {
pos.y+= textWidget.getLineHeight(widgetOffset);
}
Point dPos= textWidget.toDisplay(pos);
Rectangle displayBounds= textWidget.getDisplay().getClientArea();
Rectangle dPopupRect= Geometry.createRectangle(dPos, pSize);
Geometry.moveInside(dPopupRect, displayBounds);
return new Point(dPopupRect.x, dPopupRect.y);
}
}
}
private void addMoveSupport(final Shell popupShell, final Control movedControl) {
movedControl.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(final MouseEvent downEvent) {
if (downEvent.button != 1) {
return;
}
final Point POPUP_SOURCE= popupShell.getLocation();
final StyledText textWidget= fEditor.getViewer().getTextWidget();
Point pSize= getExtent();
int originalSnapPosition= fSnapPosition;
/*
* Feature in Tracker: it is not possible to directly control the feedback,
* see https://bugs.eclipse.org/bugs/show_bug.cgi?id=121300
* and https://bugs.eclipse.org/bugs/show_bug.cgi?id=121298#c1 .
*
* Workaround is to have an offscreen rectangle for tracking mouse movement
* and a manually updated rectangle for the actual drop target.
*/
final Tracker tracker= new Tracker(textWidget, SWT.NONE);
final Point[] LOCATIONS= {
textWidget.toControl(computePopupLocation(SNAP_POSITION_UNDER_RIGHT_FIELD)),
textWidget.toControl(computePopupLocation(SNAP_POSITION_OVER_RIGHT_FIELD)),
textWidget.toControl(computePopupLocation(SNAP_POSITION_UNDER_LEFT_FIELD)),
textWidget.toControl(computePopupLocation(SNAP_POSITION_OVER_LEFT_FIELD)),
textWidget.toControl(computePopupLocation(SNAP_POSITION_LOWER_RIGHT))
};
final Rectangle[] DROP_TARGETS= {
Geometry.createRectangle(LOCATIONS[0], pSize),
Geometry.createRectangle(LOCATIONS[1], pSize),
new Rectangle(LOCATIONS[2].x, LOCATIONS[2].y + HAH, pSize.x, pSize.y),
Geometry.createRectangle(LOCATIONS[3], pSize),
Geometry.createRectangle(LOCATIONS[4], pSize)
};
final Rectangle MOUSE_MOVE_SOURCE= new Rectangle(1000000, 0, 0, 0);
tracker.setRectangles(new Rectangle[] { MOUSE_MOVE_SOURCE, DROP_TARGETS[fSnapPosition] });
tracker.setStippled(true);
ControlListener moveListener= new ControlAdapter() {
/*
* @see org.eclipse.swt.events.ControlAdapter#controlMoved(org.eclipse.swt.events.ControlEvent)
*/
@Override
public void controlMoved(ControlEvent moveEvent) {
Rectangle[] currentRects= tracker.getRectangles();
final Rectangle mouseMoveCurrent= currentRects[0];
Point popupLoc= new Point(
POPUP_SOURCE.x + mouseMoveCurrent.x - MOUSE_MOVE_SOURCE.x,
POPUP_SOURCE.y + mouseMoveCurrent.y - MOUSE_MOVE_SOURCE.y);
popupShell.setLocation(popupLoc);
Point ePopupLoc= textWidget.toControl(popupLoc);
int minDist= Integer.MAX_VALUE;
for (int snapPos= 0; snapPos < DROP_TARGETS.length; snapPos++) {
int dist= Geometry.distanceSquared(ePopupLoc, LOCATIONS[snapPos]);
if (dist < minDist) {
minDist= dist;
fSnapPosition= snapPos;
fSnapPositionChanged= true;
currentRects[1]= DROP_TARGETS[snapPos];
}
}
tracker.setRectangles(currentRects);
}
};
tracker.addControlListener(moveListener);
boolean committed= tracker.open();
tracker.close();
tracker.dispose();
if (committed) {
getDialogSettings().put(SNAP_POSITION_KEY, fSnapPosition);
} else {
fSnapPosition= originalSnapPosition;
fSnapPositionChanged= true;
}
updatePopupLocation(true);
activateEditor();
}
});
}
private void packPopup() {
if (!fSnapPositionChanged) {
return;
}
fSnapPositionChanged= false;
boolean isUnderLeft= fSnapPosition == SNAP_POSITION_UNDER_LEFT_FIELD;
boolean isOverLeft= fSnapPosition == SNAP_POSITION_OVER_LEFT_FIELD;
fPopupLayout.marginTop= isUnderLeft ? HAH : 0;
fPopupLayout.marginBottom= isOverLeft ? HAH + 1 : 0;
fPopup.pack();
Region oldRegion= fRegion;
if (isUnderLeft || isOverLeft) {
fRegion= new Region();
fRegion.add(getPolygon(false));
fPopup.setRegion(fRegion);
Rectangle bounds= fRegion.getBounds();
fPopup.setSize(bounds.width, bounds.height + 1);
} else {
fRegion= null;
fPopup.setRegion(null);
}
if (oldRegion != null) {
oldRegion.dispose();
}
}
private Point getExtent() {
Point e = fPopup.getSize();
switch (fSnapPosition) {
case SNAP_POSITION_UNDER_LEFT_FIELD:
e.y -= HAH;
break;
case SNAP_POSITION_OVER_LEFT_FIELD:
e.y -= HAH + 1;
break;
}
return e;
}
private int[] getPolygon(boolean border) {
Point e = getExtent();
int b = border ? 1 : 0;
boolean isRTL= (fPopup.getStyle() & SWT.RIGHT_TO_LEFT) != 0;
int ha1= isRTL ? e.x - HAO : HAO + HAW;
int ha2= isRTL ? e.x - HAO - HAW / 2 : HAO + HAW / 2;
int ha3= isRTL ? e.x - HAO - HAW : HAO;
int[] poly;
switch (fSnapPosition) {
case SNAP_POSITION_OVER_LEFT_FIELD:
poly= new int[] {
0, 0,
e.x - b, 0,
e.x - b, e.y - b,
ha1, e.y - b,
ha2, e.y + HAH - b,
ha3, e.y - b,
0, e.y - b,
0, 0 };
break;
case SNAP_POSITION_UNDER_LEFT_FIELD:
poly= new int[] {
0, HAH,
ha3 + b, HAH,
ha2, b,
ha1 - b, HAH,
e.x - b, HAH,
e.x - b, e.y + HAH - b,
0, e.y + HAH - b,
0, HAH };
break;
default:
poly= new int[] {
0, 0,
e.x - b, 0,
e.x - b, e.y - b,
0, e.y - b,
0, 0 };
break;
}
return poly;
}
private void createContent(Composite parent) {
Display display= parent.getDisplay();
Color foreground= display.getSystemColor(SWT.COLOR_INFO_FOREGROUND);
Color background= display.getSystemColor(SWT.COLOR_INFO_BACKGROUND);
addMoveSupport(fPopup, parent);
StyledText hint= new StyledText(fPopup, SWT.READ_ONLY | SWT.SINGLE);
String enterKeyName= getEnterBinding();
String hintTemplate= RenameMessages.RenameInformationPopup_EnterNewName;
hint.setText(NLS.bind(hintTemplate, enterKeyName));
hint.setForeground(foreground);
hint.setStyleRange(new StyleRange(hintTemplate.indexOf("{0}"), enterKeyName.length(), null, null, SWT.BOLD)); //$NON-NLS-1$
hint.setEnabled(false); // text must not be selectable
addMoveSupport(fPopup, hint);
addViewMenu(parent);
recursiveSetBackgroundColor(parent, background);
}
private ToolBar addViewMenu(final Composite parent) {
fToolBar= new ToolBar(parent, SWT.FLAT);
final ToolItem menuButton = new ToolItem(fToolBar, SWT.PUSH, 0);
fMenuImage= CPluginImages.DESC_ELCL_VIEW_MENU.createImage();
menuButton.setImage(fMenuImage);
menuButton.setToolTipText(RenameMessages.RenameInformationPopup_menu);
fToolBar.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
showMenu(fToolBar);
}
});
menuButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
showMenu(fToolBar);
}
});
fToolBar.pack();
return fToolBar;
}
private void showMenu(ToolBar toolBar) {
Menu menu= getMenuManager().createContextMenu(toolBar);
menu.setLocation(toolBar.toDisplay(0, toolBar.getSize().y));
fIsMenuUp= true;
menu.setVisible(true);
}
private MenuManager getMenuManager() {
if (fMenuManager != null) {
return fMenuManager;
}
fMenuManager= new MenuManager();
fMenuManager.setRemoveAllWhenShown(true);
fMenuManager.addMenuListener(new IMenuListener2() {
public void menuAboutToHide(IMenuManager manager) {
fIsMenuUp= false;
}
public void menuAboutToShow(IMenuManager manager) {
boolean canRefactor= !fRenameLinkedMode.isOriginalName();
IAction refactorAction= new Action(RenameMessages.RenameInformationPopup_RenameInWorkspace) {
@Override
public void run() {
activateEditor();
fRenameLinkedMode.doRename(false);
}
};
refactorAction.setAccelerator(SWT.CR);
refactorAction.setEnabled(canRefactor);
manager.add(refactorAction);
IAction previewAction= new Action(RenameMessages.RenameInformationPopup_Preview) {
@Override
public void run() {
activateEditor();
fRenameLinkedMode.doRename(true);
}
};
previewAction.setAccelerator(SWT.CTRL | SWT.CR);
previewAction.setEnabled(canRefactor);
manager.add(previewAction);
IAction openDialogAction= new Action(RenameMessages.RenameInformationPopup_OpenDialog + '\t' + fOpenDialogBinding) {
@Override
public void run() {
activateEditor();
fRenameLinkedMode.startFullDialog();
}
};
manager.add(openDialogAction);
manager.add(new Separator());
MenuManager subMenuManager= new MenuManager(RenameMessages.RenameInformationPopup_SnapTo);
addMoveMenuItem(subMenuManager, SNAP_POSITION_UNDER_LEFT_FIELD, RenameMessages.RenameInformationPopup_snap_under_left);
addMoveMenuItem(subMenuManager, SNAP_POSITION_UNDER_RIGHT_FIELD, RenameMessages.RenameInformationPopup_snap_under_right);
addMoveMenuItem(subMenuManager, SNAP_POSITION_OVER_LEFT_FIELD, RenameMessages.RenameInformationPopup_snap_over_left);
addMoveMenuItem(subMenuManager, SNAP_POSITION_OVER_RIGHT_FIELD, RenameMessages.RenameInformationPopup_snap_over_right);
addMoveMenuItem(subMenuManager, SNAP_POSITION_LOWER_RIGHT, RenameMessages.RenameInformationPopup_snap_bottom_right);
manager.add(subMenuManager);
IAction prefsAction= new Action(RenameMessages.RenameInformationPopup_preferences) {
@Override
public void run() {
fRenameLinkedMode.cancel();
String linkedModePrefPageID= "org.eclipse.ui.editors.preferencePages.LinkedModePreferencePage"; //$NON-NLS-1$
String refactoringPrefPageID= CPluginPreferencePage.C_BASE_PREF_PAGE_ID;
PreferencesUtil.createPreferenceDialogOn(fEditor.getSite().getShell(), refactoringPrefPageID, new String[] { linkedModePrefPageID, refactoringPrefPageID }, null).open();
}
};
manager.add(prefsAction);
}
});
return fMenuManager;
}
private void addMoveMenuItem(IMenuManager manager, final int snapPosition, String text) {
IAction action= new Action(text, IAction.AS_RADIO_BUTTON) {
@Override
public void run() {
fSnapPosition= snapPosition;
fSnapPositionChanged= true;
getDialogSettings().put(SNAP_POSITION_KEY, fSnapPosition);
updatePopupLocation(true);
activateEditor();
}
};
action.setChecked(fSnapPosition == snapPosition);
manager.add(action);
}
private static String getEnterBinding() {
return KeyStroke.getInstance(KeyLookupFactory.getDefault().formalKeyLookup(IKeyLookup.CR_NAME)).format();
}
/**
* WARNING: only works in workbench window context!
* @return the keybinding for Refactor &gt; Rename
*/
private static String getOpenDialogBinding() {
IBindingService bindingService= (IBindingService)PlatformUI.getWorkbench().getAdapter(IBindingService.class);
if (bindingService == null)
return ""; //$NON-NLS-1$
String binding= bindingService.getBestActiveBindingFormattedFor(ICEditorActionDefinitionIds.RENAME_ELEMENT);
return binding == null ? "" : binding; //$NON-NLS-1$
}
private static void recursiveSetBackgroundColor(Control control, Color color) {
control.setBackground(color);
if (control instanceof Composite) {
Control[] children= ((Composite) control).getChildren();
for (int i= 0; i < children.length; i++) {
recursiveSetBackgroundColor(children[i], color);
}
}
}
public boolean ownsFocusShell() {
if (fIsMenuUp)
return true;
if (fPopup == null || fPopup.isDisposed())
return false;
Shell activeShell= fPopup.getDisplay().getActiveShell();
if (fPopup == activeShell)
return true;
return false;
}
private void activateEditor() {
fEditor.getSite().getShell().setActive();
}
public boolean requestWidgetToken(IWidgetTokenOwner owner) {
return false;
}
public boolean requestWidgetToken(IWidgetTokenOwner owner, int priority) {
return false;
}
public boolean setFocus(IWidgetTokenOwner owner) {
if (fToolBar != null && !fToolBar.isDisposed())
showMenu(fToolBar);
return true;
}
}

View file

@ -0,0 +1,517 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 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.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.core.commands.operations.IOperationHistory;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.commands.operations.OperationHistoryFactory;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IEditingSupport;
import org.eclipse.jface.text.IEditingSupportRegistry;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewerExtension6;
import org.eclipse.jface.text.IUndoManager;
import org.eclipse.jface.text.IUndoManagerExtension;
import org.eclipse.jface.text.link.ILinkedModeListener;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedModeUI;
import org.eclipse.jface.text.link.LinkedModeUI.ExitFlags;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
import org.eclipse.cdt.core.CConventions;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.IWorkingCopyManager;
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.editor.EditorHighlightingSynchronizer;
import org.eclipse.cdt.internal.ui.search.LinkedNamesFinder;
import org.eclipse.cdt.internal.ui.text.correction.proposals.LinkedNamesAssistProposal.DeleteBlockingExitPolicy;
public class RenameLinkedMode {
private class FocusEditingSupport implements IEditingSupport {
public boolean ownsFocusShell() {
if (fInfoPopup == null)
return false;
if (fInfoPopup.ownsFocusShell()) {
return true;
}
Shell editorShell= fEditor.getSite().getShell();
Shell activeShell= editorShell.getDisplay().getActiveShell();
if (editorShell == activeShell)
return true;
return false;
}
public boolean isOriginator(DocumentEvent event, IRegion subjectRegion) {
return false; //leave on external modification outside positions
}
}
private class EditorSynchronizer implements ILinkedModeListener {
public void left(LinkedModeModel model, int flags) {
linkedModeLeft();
if ((flags & ILinkedModeListener.UPDATE_CARET) != 0) {
doRename(fShowPreview);
}
}
public void resume(LinkedModeModel model, int flags) {
}
public void suspend(LinkedModeModel model) {
}
}
private class ExitPolicy extends DeleteBlockingExitPolicy {
public ExitPolicy(IDocument document) {
super(document);
}
@Override
public ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length) {
fShowPreview= (event.stateMask & SWT.CTRL) != 0
&& (event.character == SWT.CR || event.character == SWT.LF);
return super.doExit(model, event, offset, length);
}
}
private static RenameLinkedMode fgActiveLinkedMode;
private final CEditor fEditor;
private RenameInformationPopup fInfoPopup;
private Point fOriginalSelection;
private String fOriginalName;
private LinkedPosition fNamePosition;
private LinkedModeModel fLinkedModeModel;
private LinkedPositionGroup fLinkedPositionGroup;
private final FocusEditingSupport fFocusEditingSupport;
private boolean fShowPreview;
/**
* The operation on top of the undo stack when the rename is {@link #start()}ed, or
* <code>null</code> if rename has not been started or the undo stack was empty.
*/
private IUndoableOperation fStartingUndoOperation;
private IRegion[] fLocations;
public RenameLinkedMode(CEditor editor) {
Assert.isNotNull(editor);
fEditor= editor;
fFocusEditingSupport= new FocusEditingSupport();
}
public static RenameLinkedMode getActiveLinkedMode() {
if (fgActiveLinkedMode != null) {
ISourceViewer viewer= fgActiveLinkedMode.fEditor.getViewer();
if (viewer != null) {
StyledText textWidget= viewer.getTextWidget();
if (textWidget != null && !textWidget.isDisposed()) {
return fgActiveLinkedMode;
}
}
// Make sure we don't hold onto the active linked mode if anything went wrong with canceling.
fgActiveLinkedMode= null;
}
return null;
}
public void start() {
if (getActiveLinkedMode() != null) {
// For safety; should already be handled in CRenameAction
fgActiveLinkedMode.startFullDialog();
return;
}
ISourceViewer viewer= fEditor.getViewer();
fOriginalSelection= viewer.getSelectedRange();
final int offset= fOriginalSelection.x;
try {
fLocations = null;
Point selection= viewer.getSelectedRange();
final int secectionOffset = selection.x;
final int selectionLength = selection.y;
final IDocument document= viewer.getDocument();
ASTProvider.getASTProvider().runOnAST(fEditor.getInputCElement(), ASTProvider.WAIT_ACTIVE_ONLY,
new NullProgressMonitor(), new ASTRunnable() {
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit astRoot) throws CoreException {
if (astRoot == null)
return Status.CANCEL_STATUS;
IASTNodeSelector selector= astRoot.getNodeSelector(null);
IASTName name= selector.findEnclosingName(secectionOffset, selectionLength);
if (name != null) {
fOriginalName = name.toString();
fLocations = LinkedNamesFinder.findByName(astRoot, name);
}
return Status.OK_STATUS;
}
});
if (fLocations == null || fLocations.length == 0) {
return;
}
if (viewer instanceof ITextViewerExtension6) {
IUndoManager undoManager= ((ITextViewerExtension6) viewer).getUndoManager();
if (undoManager instanceof IUndoManagerExtension) {
IUndoManagerExtension undoManagerExtension= (IUndoManagerExtension) undoManager;
IUndoContext undoContext= undoManagerExtension.getUndoContext();
IOperationHistory operationHistory= OperationHistoryFactory.getOperationHistory();
fStartingUndoOperation= operationHistory.getUndoOperation(undoContext);
}
}
// Sort the locations starting with the one @ offset.
Arrays.sort(fLocations, new Comparator<IRegion>() {
public int compare(IRegion n1, IRegion n2) {
return rank(n1) - rank(n2);
}
/**
* Returns the absolute rank of a location. Location preceding <code>offset</code>
* are ranked last.
*
* @param location the location to compute the rank for
* @return the rank of the location with respect to the invocation offset
*/
private int rank(IRegion location) {
int relativeRank= location.getOffset() + location.getLength() - offset;
if (relativeRank < 0)
return Integer.MAX_VALUE + relativeRank;
else
return relativeRank;
}
});
fLinkedPositionGroup= new LinkedPositionGroup();
for (int i= 0; i < fLocations.length; i++) {
IRegion item= fLocations[i];
LinkedPosition linkedPosition = new LinkedPosition(document, item.getOffset(), item.getLength(), i);
if (i == 0) {
fNamePosition= linkedPosition;
}
fLinkedPositionGroup.addPosition(linkedPosition);
}
fLinkedModeModel= new LinkedModeModel();
fLinkedModeModel.addGroup(fLinkedPositionGroup);
fLinkedModeModel.forceInstall();
fLinkedModeModel.addLinkingListener(new EditorHighlightingSynchronizer(fEditor));
fLinkedModeModel.addLinkingListener(new EditorSynchronizer());
LinkedModeUI ui= new EditorLinkedModeUI(fLinkedModeModel, viewer);
ui.setExitPolicy(new ExitPolicy(document));
ui.setExitPosition(viewer, offset, 0, LinkedPositionGroup.NO_STOP);
ui.enter();
// By default full word is selected, restore original selection.
viewer.setSelectedRange(selection.x, selection.y);
if (viewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer;
registry.register(fFocusEditingSupport);
}
openSecondaryPopup();
fgActiveLinkedMode= this;
} catch (BadLocationException e) {
CUIPlugin.log(e);
}
}
void doRename(boolean showPreview) {
cancel();
Image image= null;
Label label= null;
fShowPreview|= showPreview;
try {
ISourceViewer viewer= fEditor.getViewer();
if (viewer instanceof SourceViewer) {
SourceViewer sourceViewer= (SourceViewer) viewer;
Control viewerControl= sourceViewer.getControl();
if (viewerControl instanceof Composite) {
Composite composite= (Composite) viewerControl;
Display display= composite.getDisplay();
// Flush pending redraw requests:
while (!display.isDisposed() && display.readAndDispatch()) {
}
// Copy editor area:
GC gc= new GC(composite);
Point size;
try {
size= composite.getSize();
image= new Image(gc.getDevice(), size.x, size.y);
gc.copyArea(image, 0, 0);
} finally {
gc.dispose();
gc= null;
}
// Persist editor area while executing refactoring:
label= new Label(composite, SWT.NONE);
label.setImage(image);
label.setBounds(0, 0, size.x, size.y);
label.moveAbove(null);
}
}
String newName= fNamePosition.getContent();
if (fOriginalName.equals(newName))
return;
RenameSupport renameSupport= undoAndCreateRenameSupport(newName);
if (renameSupport == null)
return;
Shell shell= fEditor.getSite().getShell();
boolean executed;
if (fShowPreview) { // could have been updated by undoAndCreateRenameSupport(..)
executed= renameSupport.openDialog(shell, true);
} else {
renameSupport.perform(shell, fEditor.getSite().getWorkbenchWindow());
executed= true;
}
if (executed) {
restoreFullSelection();
}
reconcile();
} catch (CoreException e) {
CUIPlugin.log(e);
} catch (InterruptedException e) {
// canceling is OK -> redo text changes in that case?
} catch (InvocationTargetException e) {
CUIPlugin.log(e);
} catch (BadLocationException e) {
CUIPlugin.log(e);
} finally {
if (label != null)
label.dispose();
if (image != null)
image.dispose();
}
}
public void cancel() {
if (fLinkedModeModel != null) {
fLinkedModeModel.exit(ILinkedModeListener.NONE);
}
linkedModeLeft();
}
private void restoreFullSelection() {
if (fOriginalSelection.y != 0) {
int originalOffset= fOriginalSelection.x;
LinkedPosition[] positions= fLinkedPositionGroup.getPositions();
for (int i= 0; i < positions.length; i++) {
LinkedPosition position= positions[i];
if (!position.isDeleted() && position.includes(originalOffset)) {
fEditor.getViewer().setSelectedRange(position.offset, position.length);
return;
}
}
}
}
private RenameSupport undoAndCreateRenameSupport(String newName) throws CoreException {
// Assumption: the linked mode model should be shut down by now.
final ISourceViewer viewer= fEditor.getViewer();
try {
if (!fOriginalName.equals(newName)) {
fEditor.getSite().getWorkbenchWindow().run(false, true, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
if (viewer instanceof ITextViewerExtension6) {
IUndoManager undoManager= ((ITextViewerExtension6) viewer).getUndoManager();
if (undoManager instanceof IUndoManagerExtension) {
IUndoManagerExtension undoManagerExtension= (IUndoManagerExtension) undoManager;
IUndoContext undoContext= undoManagerExtension.getUndoContext();
IOperationHistory operationHistory= OperationHistoryFactory.getOperationHistory();
while (undoManager.undoable()) {
if (fStartingUndoOperation != null &&
fStartingUndoOperation.equals(operationHistory.getUndoOperation(undoContext)))
return;
undoManager.undo();
}
}
}
}
});
}
} catch (InvocationTargetException e) {
throw new CoreException(new Status(IStatus.ERROR, CUIPlugin.getPluginId(),
RenameMessages.RenameLinkedMode_error_saving_editor, e));
} catch (InterruptedException e) {
// canceling is OK
return null;
} finally {
reconcile();
}
viewer.setSelectedRange(fOriginalSelection.x, fOriginalSelection.y);
if (newName.length() == 0)
return null;
IWorkingCopy workingCopy = getWorkingCopy();
IResource resource= workingCopy.getResource();
if (!(resource instanceof IFile)) {
return null;
}
CRefactoringArgument arg=
new CRefactoringArgument((IFile) resource, fOriginalSelection.x, fOriginalSelection.y);
CRenameProcessor processor= new CRenameProcessor(CRefactory.getInstance(), arg);
processor.setReplacementText(newName);
CRenameRefactoringPreferences preferences = new CRenameRefactoringPreferences();
processor.setSelectedOptions(preferences.getOptions());
processor.setScope(preferences.getInt(CRenameRefactoringPreferences.KEY_SCOPE));
processor.setWorkingSet(preferences.get(CRenameRefactoringPreferences.KEY_WORKING_SET_NAME));
RenameSupport renameSupport= RenameSupport.create(processor);
return renameSupport;
}
private void reconcile() throws CModelException {
IWorkingCopy workingCopy = getWorkingCopy();
synchronized (workingCopy) {
workingCopy.reconcile();
}
}
private IWorkingCopy getWorkingCopy() {
IEditorInput input = fEditor.getEditorInput();
IWorkingCopyManager manager = CUIPlugin.getDefault().getWorkingCopyManager();
return manager.getWorkingCopy(input);
}
public void startFullDialog() {
cancel();
try {
String newName= fNamePosition.getContent();
RenameSupport renameSupport= undoAndCreateRenameSupport(newName);
if (renameSupport != null)
renameSupport.openDialog(fEditor.getSite().getShell());
} catch (CoreException e) {
CUIPlugin.log(e);
} catch (BadLocationException e) {
CUIPlugin.log(e);
}
}
private void linkedModeLeft() {
fgActiveLinkedMode= null;
if (fInfoPopup != null) {
fInfoPopup.close();
}
ISourceViewer viewer= fEditor.getViewer();
if (viewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer;
registry.unregister(fFocusEditingSupport);
}
}
private void openSecondaryPopup() {
fInfoPopup= new RenameInformationPopup(fEditor, this);
fInfoPopup.open();
}
public boolean isCaretInLinkedPosition() {
return getCurrentLinkedPosition() != null;
}
public LinkedPosition getCurrentLinkedPosition() {
Point selection= fEditor.getViewer().getSelectedRange();
int start= selection.x;
int end= start + selection.y;
LinkedPosition[] positions= fLinkedPositionGroup.getPositions();
for (int i= 0; i < positions.length; i++) {
LinkedPosition position= positions[i];
if (position.includes(start) && position.includes(end))
return position;
}
return null;
}
public boolean isEnabled() {
try {
String newName= fNamePosition.getContent();
if (fOriginalName.equals(newName))
return false;
return CConventions.validateIdentifier(newName).isOK();
} catch (BadLocationException e) {
return false;
}
}
public boolean isOriginalName() {
try {
String newName= fNamePosition.getContent();
return fOriginalName.equals(newName);
} catch (BadLocationException e) {
return false;
}
}
}

View file

@ -109,5 +109,21 @@ public class RenameMessages extends NLS {
public static String RenameCSourceFolderChange_ErrorMsg;
public static String RenameCSourceFolderChange_Name0;
public static String RenameSourceFolder_0;
public static String RenameInformationPopup_delayJobName;
public static String RenameInformationPopup_EnterNewName;
public static String RenameInformationPopup_menu;
public static String RenameInformationPopup_OpenDialog;
public static String RenameInformationPopup_preferences;
public static String RenameInformationPopup_Preview;
public static String RenameInformationPopup_RenameInWorkspace;
public static String RenameInformationPopup_snap_bottom_right;
public static String RenameInformationPopup_snap_over_left;
public static String RenameInformationPopup_snap_over_right;
public static String RenameInformationPopup_snap_under_left;
public static String RenameInformationPopup_snap_under_right;
public static String RenameInformationPopup_SnapTo;
public static String RenameLinkedMode_error_saving_editor;
public static String RenameSupport_not_available;
public static String RenameSupport_dialog_title;
public static String TextSearch_monitor_categorizeMatches;
}

View file

@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2005, 2009 IBM Corporation and others.
# Copyright (c) 2005, 2010 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
@ -97,4 +97,20 @@ CRenameTopProcessor_wizard_title=Rename ''{0}''
RenameCSourceFolderChange_ErrorMsg=Folder {0} does not exist
RenameCSourceFolderChange_Name0=Rename source folder {0} to {1}
RenameSourceFolder_0=Rename C/C++ Source Folder
RenameInformationPopup_SnapTo=&Snap To
RenameInformationPopup_snap_under_left=&Under Left
RenameInformationPopup_snap_under_right=U&nder Right
RenameInformationPopup_snap_over_left=&Over Left
RenameInformationPopup_snap_over_right=O&ver Right
RenameInformationPopup_snap_bottom_right=&Bottom Right
RenameInformationPopup_menu=Menu
RenameInformationPopup_RenameInWorkspace=&Refactor
RenameInformationPopup_Preview=Pre&view...
RenameInformationPopup_OpenDialog=&Open Rename Dialog...
RenameInformationPopup_preferences=&Preferences...
RenameInformationPopup_EnterNewName=Enter new name, press {0} to refactor
RenameInformationPopup_delayJobName=delayed RenameInformationPopup
RenameLinkedMode_error_saving_editor=An error occurred while saving the editor.
RenameSupport_not_available=The refactoring operation is not available
RenameSupport_dialog_title=Rename Refactoring
TextSearch_monitor_categorizeMatches=categorizing matches

View file

@ -0,0 +1,204 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 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.lang.reflect.InvocationTargetException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.ltk.core.refactoring.RefactoringCore;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringExecutionHelper;
/**
* Central access point to execute rename refactorings.
*/
public class RenameSupport {
/** Flag indication that no additional update is to be performed. */
public static final int NONE= 0;
/** Flag indicating that references are to be updated as well. */
public static final int UPDATE_REFERENCES= 1 << 0;
/**
* Flag indicating that textual matches in comments and in string literals
* are to be updated as well.
*/
public static final int UPDATE_TEXTUAL_MATCHES= 1 << 6;
/** Flag indicating that the getter method is to be updated as well. */
public static final int UPDATE_GETTER_METHOD= 1 << 4;
/** Flag indicating that the setter method is to be updated as well. */
public static final int UPDATE_SETTER_METHOD= 1 << 5;
private CRenameRefactoring fRefactoring;
private RefactoringStatus fPreCheckStatus;
/**
* Executes some light weight precondition checking. If the returned status
* is an error then the refactoring can't be executed at all. However,
* returning an OK status doesn't guarantee that the refactoring can be
* executed. It may still fail while performing the exhaustive precondition
* checking done inside the methods <code>openDialog</code> or
* <code>perform</code>.
*
* The method is mainly used to determine enablement/disablement of actions.
*
* @return the result of the light weight precondition checking.
*
* @throws CoreException if an unexpected exception occurs while performing the checking.
*
* @see #openDialog(Shell)
* @see #perform(Shell, IRunnableContext)
*/
public IStatus preCheck() throws CoreException {
ensureChecked();
if (fPreCheckStatus.hasFatalError())
return fPreCheckStatus.getEntryMatchingSeverity(RefactoringStatus.FATAL).toStatus();
else
return Status.OK_STATUS;
}
/**
* Opens the refactoring dialog for this rename support.
*
* @param parent a shell used as a parent for the refactoring dialog.
* @throws CoreException if an unexpected exception occurs while opening the
* dialog.
*
* @see #openDialog(Shell, boolean)
*/
public void openDialog(Shell parent) throws CoreException {
openDialog(parent, false);
}
/**
* Opens the refactoring dialog for this rename support.
*
* <p>
* This method has to be called from within the UI thread.
* </p>
*
* @param shell a shell used as a parent for the refactoring, preview, or error dialog
* @param showPreviewOnly if <code>true</code>, the dialog skips all user input pages and
* directly shows the preview or error page. Otherwise, shows all pages.
* @return <code>true</code> if the refactoring has been executed successfully,
* <code>false</code> if it has been canceled or if an error has happened during
* initial conditions checking.
*
* @throws CoreException if an error occurred while executing the
* operation.
*
* @see #openDialog(Shell)
*/
public boolean openDialog(Shell shell, boolean showPreviewOnly) throws CoreException {
ensureChecked();
if (fPreCheckStatus.hasFatalError()) {
showInformation(shell, fPreCheckStatus);
return false;
}
return CRefactory.openDialog(shell, fRefactoring, showPreviewOnly);
}
/**
* Executes the rename refactoring without showing a dialog to gather
* additional user input (for example the new name of the <tt>ICElement</tt>).
* Only an error dialog is shown (if necessary) to present the result
* of the refactoring's full precondition checking.
* <p>
* The method has to be called from within the UI thread.
* </p>
*
* @param parent a shell used as a parent for the error dialog.
* @param context a {@link IRunnableContext} to execute the operation.
*
* @throws InterruptedException if the operation has been canceled by the
* user.
* @throws InvocationTargetException if an error occurred while executing the
* operation.
*
* @see #openDialog(Shell)
* @see IRunnableContext#run(boolean, boolean, org.eclipse.jface.operation.IRunnableWithProgress)
*/
public void perform(Shell parent, IRunnableContext context) throws InterruptedException, InvocationTargetException {
try {
ensureChecked();
if (fPreCheckStatus.hasFatalError()) {
showInformation(parent, fPreCheckStatus);
return;
}
CRenameProcessor renameProcessor = getRenameProcessor();
try {
renameProcessor.lockIndex();
fPreCheckStatus = renameProcessor.checkInitialConditions(new NullProgressMonitor());
if (fPreCheckStatus.hasFatalError()) {
showInformation(parent, fPreCheckStatus);
return;
}
RefactoringExecutionHelper helper= new RefactoringExecutionHelper(fRefactoring,
RefactoringCore.getConditionCheckingFailedSeverity(), renameProcessor.getSaveMode(),
parent, context);
helper.perform(true, true);
} finally {
renameProcessor.unlockIndex();
}
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
private RenameSupport(CRenameProcessor processor) {
fRefactoring= new CRenameRefactoring(processor);
}
private CRenameProcessor getRenameProcessor() {
return (CRenameProcessor) fRefactoring.getProcessor();
}
/**
* Creates a new rename support for the given {@link ICProject}.
*
* @param processor the {@link CRenameProcessor}
* @return the {@link RenameSupport}.
* @throws CoreException if an unexpected error occurred while creating
* the {@link RenameSupport}.
*/
public static RenameSupport create(CRenameProcessor processor) throws CoreException {
return new RenameSupport(processor);
}
private void ensureChecked() throws CoreException {
if (fPreCheckStatus == null) {
if (!fRefactoring.isApplicable()) {
fPreCheckStatus= RefactoringStatus.createFatalErrorStatus(RenameMessages.RenameSupport_not_available);
} else {
fPreCheckStatus= new RefactoringStatus();
}
}
}
private void showInformation(Shell parent, RefactoringStatus status) {
String message= status.getMessageMatchingSeverity(RefactoringStatus.FATAL);
MessageDialog.openInformation(parent, RenameMessages.RenameSupport_dialog_title, message);
}
}

View file

@ -39,6 +39,8 @@ import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
@ -74,6 +76,7 @@ public class CCorrectionAssistant extends QuickAssistAssistant {
CCorrectionProcessor processor= new CCorrectionProcessor(this);
setQuickAssistProcessor(processor);
enableColoredLabels(PlatformUI.getPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.USE_COLORED_LABELS));
setInformationControlCreator(getInformationControlCreator());
@ -119,8 +122,6 @@ public class CCorrectionAssistant extends QuickAssistAssistant {
fLightBulbUpdater.install();
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.contentassist.ContentAssistant#uninstall()
*/
@ -270,7 +271,6 @@ public class CCorrectionAssistant extends QuickAssistAssistant {
return bestOffset;
}
private static boolean isInside(int offset, int start, int end) {
return offset == start || offset == end || (offset > start && offset < end); // make sure to handle 0-length ranges
}

View file

@ -48,6 +48,7 @@ import org.eclipse.cdt.ui.text.IInvocationContext;
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.ui.actions.ActionUtil;
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.text.correction.proposals.LinkedNamesAssistProposal;
@ -70,16 +71,30 @@ public class CorrectionCommandHandler extends AbstractHandler {
* @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
*/
public Object execute(ExecutionEvent event) throws ExecutionException {
doExecute();
return null;
}
/**
* Try to execute the correction command.
*
* @return <code>true</code> iff the correction could be started
* @since 5.3
*/
public boolean doExecute() {
ISelection selection= fEditor.getSelectionProvider().getSelection();
ITranslationUnit tu= CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput());
IAnnotationModel model= CUIPlugin.getDefault().getDocumentProvider().getAnnotationModel(fEditor.getEditorInput());
if (selection instanceof ITextSelection && tu != null && model != null) {
if (!ActionUtil.isEditable(fEditor)) {
return false;
}
ICompletionProposal proposal= findCorrection(fId, fIsAssist, (ITextSelection) selection, tu, model);
if (proposal != null) {
invokeProposal(proposal, ((ITextSelection) selection).getOffset());
}
}
return null;
return false;
}
private ICompletionProposal findCorrection(String id, boolean isAssist, ITextSelection selection, ITranslationUnit tu, IAnnotationModel model) {

View file

@ -17,10 +17,8 @@ import org.eclipse.osgi.util.NLS;
* Helper class to get NLSed messages.
*/
public final class CorrectionMessages extends NLS {
private static final String BUNDLE_NAME= CorrectionMessages.class.getName();
static {
NLS.initializeMessages(BUNDLE_NAME, CorrectionMessages.class);
NLS.initializeMessages(CorrectionMessages.class.getName(), CorrectionMessages.class);
}
private CorrectionMessages() {
@ -40,4 +38,6 @@ public final class CorrectionMessages extends NLS {
public static String TUCorrectionProposal_error_message;
public static String LinkedNamesAssistProposal_proposalinfo;
public static String LinkedNamesAssistProposal_description;
public static String RenameRefactoringProposal_additionalInfo;
public static String RenameRefactoringProposal_name;
}

View file

@ -21,10 +21,13 @@ NoCorrectionProposal_description=No suggestions available
ChangeCorrectionProposal_error_title=Quick Fix
ChangeCorrectionProposal_error_message=An exception occurred while applying the quick fix.
ChangeCorrectionProposal_name_with_shortcut={0} ({1} direct access)
ChangeCorrectionProposal_name_with_shortcut={0} ({1})
TUCorrectionProposal_error_title=Quick Fix
TUCorrectionProposal_error_message=An exception occurred while applying the quick fix.
LinkedNamesAssistProposal_proposalinfo=Link all references for a local rename (does not change references in other files)
LinkedNamesAssistProposal_description=Rename in file
RenameRefactoringProposal_additionalInfo=Start the Rename refactoring
RenameRefactoringProposal_name=Rename in workspace

View file

@ -20,12 +20,14 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.IEditorPart;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.ui.text.IInvocationContext;
import org.eclipse.cdt.ui.text.IProblemLocation;
@ -34,7 +36,9 @@ import org.eclipse.cdt.ui.text.IQuickAssistProcessor;
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.text.correction.proposals.LinkedNamesAssistProposal;
import org.eclipse.cdt.internal.ui.text.correction.proposals.RenameRefactoringProposal;
/**
* see org.eclipse.cdt.ui.text.IQuickAssistProcessor
@ -66,11 +70,13 @@ public class QuickAssistProcessor implements IQuickAssistProcessor {
return status.isOK();
}
public ICCompletionProposal[] getAssists(final IInvocationContext context, final IProblemLocation[] problemLocations) throws CoreException {
public ICCompletionProposal[] getAssists(final IInvocationContext context,
final IProblemLocation[] problemLocations) throws CoreException {
final ArrayList<ICCompletionProposal> proposals= new ArrayList<ICCompletionProposal>();
ASTProvider.getASTProvider().runOnAST(context.getTranslationUnit(), ASTProvider.WAIT_ACTIVE_ONLY,
new NullProgressMonitor(), new ASTRunnable() {
new NullProgressMonitor(),
new ASTRunnable() {
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit astRoot) throws CoreException {
IASTNodeSelector selector= astRoot.getNodeSelector(null);
@ -84,6 +90,7 @@ public class QuickAssistProcessor implements IQuickAssistProcessor {
// Quick assists that show up also if there is an error/warning
getRenameLocalProposals(context, problemLocations, noErrorsAtLocation, proposals);
getRenameRefactoringProposal(context, problemLocations, noErrorsAtLocation, proposals);
}
}
return Status.OK_STATUS;
@ -113,4 +120,23 @@ public class QuickAssistProcessor implements IQuickAssistProcessor {
proposals.add(proposal);
}
private static boolean getRenameRefactoringProposal(IInvocationContext context, IProblemLocation[] locations,
boolean noErrorsAtLocation, Collection<ICCompletionProposal> proposals)
throws CoreException {
IEditorPart editor= CUIPlugin.getActivePage().getActiveEditor();
if (!(editor instanceof CEditor))
return false;
if (proposals == null) {
return true;
}
RenameRefactoringProposal proposal= new RenameRefactoringProposal((CEditor) editor);
if (!noErrorsAtLocation) {
proposal.setRelevance(1);
}
proposals.add(proposal);
return true;
}
}

View file

@ -0,0 +1,138 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 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.text.correction.proposals;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension6;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.cdt.ui.refactoring.actions.CRenameAction;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.internal.corext.util.Messages;
import org.eclipse.cdt.internal.ui.CPluginImages;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.editor.ICEditorActionDefinitionIds;
import org.eclipse.cdt.internal.ui.text.correction.CorrectionCommandHandler;
import org.eclipse.cdt.internal.ui.text.correction.CorrectionMessages;
import org.eclipse.cdt.internal.ui.text.correction.ICommandAccess;
/**
* A quick assist proposal that starts the Rename refactoring.
*/
public class RenameRefactoringProposal implements ICCompletionProposal, ICompletionProposalExtension6, ICommandAccess {
private final CEditor fEditor;
private final String fLabel;
private int fRelevance;
public RenameRefactoringProposal(CEditor editor) {
fEditor = editor;
fLabel= CorrectionMessages.RenameRefactoringProposal_name;
fRelevance= 8;
}
/*
* @see ICompletionProposal#apply(IDocument)
*/
public void apply(IDocument document) {
CRenameAction action= new CRenameAction();
action.setEditor(fEditor);
action.run();
}
/*
* @see ICompletionProposal#getSelection(IDocument)
*/
public Point getSelection(IDocument document) {
return null;
}
/*
* @see ICompletionProposal#getAdditionalProposalInfo()
*/
public String getAdditionalProposalInfo() {
return CorrectionMessages.RenameRefactoringProposal_additionalInfo;
}
/*
* @see ICompletionProposal#getDisplayString()
*/
public String getDisplayString() {
String shortCutString= CorrectionCommandHandler.getShortCutString(getCommandId());
if (shortCutString != null) {
return Messages.format(CorrectionMessages.ChangeCorrectionProposal_name_with_shortcut,
new String[] { fLabel, shortCutString });
}
return fLabel;
}
/*
* @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension6#getStyledDisplayString()
*/
public StyledString getStyledDisplayString() {
StyledString str= new StyledString(fLabel);
String shortCutString= CorrectionCommandHandler.getShortCutString(getCommandId());
if (shortCutString != null) {
String decorated= Messages.format(CorrectionMessages.ChangeCorrectionProposal_name_with_shortcut,
new String[] { fLabel, shortCutString });
return StyledCellLabelProvider.styleDecoratedString(decorated, StyledString.QUALIFIER_STYLER, str);
}
return str;
}
/*
* @see ICompletionProposal#getImage()
*/
public Image getImage() {
return CPluginImages.get(CPluginImages.IMG_CORRECTION_LINKED_RENAME);
}
/*
* @see ICompletionProposal#getContextInformation()
*/
public IContextInformation getContextInformation() {
return null;
}
/*
* @see ICCompletionProposal#getRelevance()
*/
public int getRelevance() {
return fRelevance;
}
/*
* @see ICCompletionProposal#getIdString()
*/
public String getIdString() {
return getCommandId();
}
/*
* @see ICommandAccess#getCommandId()
*/
public String getCommandId() {
return ICEditorActionDefinitionIds.RENAME_ELEMENT;
}
public void setRelevance(int relevance) {
fRelevance= relevance;
}
}

View file

@ -19,7 +19,9 @@ import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.compare.rangedifferencer.IRangeComparator;
import org.eclipse.compare.rangedifferencer.RangeDifference;
@ -63,13 +65,18 @@ import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.TextFileDocumentProvider;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.ide.ResourceUtil;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
import com.ibm.icu.text.MessageFormat;
@ -191,14 +198,15 @@ public class EditorUtility {
}
try {
if (!isLinked(file)) {
if (!file.isLinked(IResource.CHECK_ANCESTORS)) {
File tempFile = file.getRawLocation().toFile();
if (tempFile != null){
String canonicalPath = null;
try {
canonicalPath = tempFile.getCanonicalPath();
} catch (IOException e1) {}
} catch (IOException e) {
}
if (canonicalPath != null){
IPath path = new Path(canonicalPath);
@ -211,10 +219,15 @@ public class EditorUtility {
if (input != null) {
return openInEditor(input, getEditorID(input, file), activate);
}
} catch (CModelException e) {}
} catch (CModelException e) {
}
return null;
}
/**
* @deprecated use IResource.isLinked(IResource.CHECK_ANCESTORS) instead.
*/
@Deprecated
public static boolean isLinked(IFile file) {
if (file.isLinked())
return true;
@ -753,6 +766,117 @@ public class EditorUtility {
return cProject;
}
/**
* Returns an array of all editors that have an unsaved content. If the identical content is
* presented in more than one editor, only one of those editor parts is part of the result.
* @param skipNonResourceEditors if <code>true</code>, editors whose inputs do not adapt to {@link IResource}
* are not saved
*
* @return an array of dirty editor parts
* @since 5.3
*/
public static IEditorPart[] getDirtyEditors(boolean skipNonResourceEditors) {
Set<IEditorInput> inputs= new HashSet<IEditorInput>();
List<IEditorPart> result= new ArrayList<IEditorPart>(0);
IWorkbench workbench= PlatformUI.getWorkbench();
IWorkbenchWindow[] windows= workbench.getWorkbenchWindows();
for (int i= 0; i < windows.length; i++) {
IWorkbenchPage[] pages= windows[i].getPages();
for (int x= 0; x < pages.length; x++) {
IEditorPart[] editors= pages[x].getDirtyEditors();
for (int z= 0; z < editors.length; z++) {
IEditorPart ep= editors[z];
IEditorInput input= ep.getEditorInput();
if (inputs.add(input)) {
if (!skipNonResourceEditors || isResourceEditorInput(input)) {
result.add(ep);
}
}
}
}
}
return result.toArray(new IEditorPart[result.size()]);
}
private static boolean isResourceEditorInput(IEditorInput input) {
if (input instanceof MultiEditorInput) {
IEditorInput[] inputs= ((MultiEditorInput) input).getInput();
for (int i= 0; i < inputs.length; i++) {
if (inputs[i].getAdapter(IResource.class) != null) {
return true;
}
}
} else if (input.getAdapter(IResource.class) != null) {
return true;
}
return false;
}
/**
* Returns the editors to save before performing global C-related
* operations.
*
* @param saveUnknownEditors <code>true</code> iff editors with unknown buffer management should also be saved
* @return the editors to save
* @since 5.3
*/
public static IEditorPart[] getDirtyEditorsToSave(boolean saveUnknownEditors) {
Set<IEditorInput> inputs= new HashSet<IEditorInput>();
List<IEditorPart> result= new ArrayList<IEditorPart>(0);
IWorkbench workbench= PlatformUI.getWorkbench();
IWorkbenchWindow[] windows= workbench.getWorkbenchWindows();
for (int i= 0; i < windows.length; i++) {
IWorkbenchPage[] pages= windows[i].getPages();
for (int x= 0; x < pages.length; x++) {
IEditorPart[] editors= pages[x].getDirtyEditors();
for (int z= 0; z < editors.length; z++) {
IEditorPart ep= editors[z];
IEditorInput input= ep.getEditorInput();
if (!mustSaveDirtyEditor(ep, input, saveUnknownEditors))
continue;
if (inputs.add(input))
result.add(ep);
}
}
}
return result.toArray(new IEditorPart[result.size()]);
}
private static boolean mustSaveDirtyEditor(IEditorPart ep, IEditorInput input, boolean saveUnknownEditors) {
/*
* Goal: save all editors that could interfere with refactoring operations.
*
* Always save all editors for translation units that are not working copies.
* (Leaving them dirty would cause problems, since the file buffer could have been
* modified but the C model is not reconciled.)
*
* If <code>saveUnknownEditors</code> is <code>true</code>, save all editors
* whose implementation is probably not based on file buffers.
*/
IResource resource= (IResource) input.getAdapter(IResource.class);
if (resource == null)
return saveUnknownEditors;
ICElement element= CCorePlugin.getDefault().getCoreModel().create(resource);
if (element instanceof ITranslationUnit) {
ITranslationUnit tu= (ITranslationUnit) element;
if (getWorkingCopy(tu) == null) {
return true;
}
}
if (!(ep instanceof ITextEditor))
return saveUnknownEditors;
ITextEditor textEditor= (ITextEditor) ep;
IDocumentProvider documentProvider= textEditor.getDocumentProvider();
if (!(documentProvider instanceof TextFileDocumentProvider))
return saveUnknownEditors;
return false;
}
/**
* Return the regions of all lines which have changed in the given buffer since the
* last save occurred. Each region in the result spans over the size of at least one line.

View file

@ -0,0 +1,143 @@
/*******************************************************************************
* Copyright (c) 2008, 2010 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.viewsupport;
import java.io.File;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.osgi.util.TextProcessor;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.cdt.internal.corext.util.Strings;
/**
* A label provider for basic elements like paths. The label provider will make sure that the labels are correctly
* shown in RTL environments.
*
* @since 5.3
*/
public class BasicElementLabels {
// TextProcessor delimiters
private static final String CODE_DELIMITERS= TextProcessor.getDefaultDelimiters() + "<>()?,{}+-*!%=^|&;[]~"; //$NON-NLS-1$
private static final String FILE_PATTERN_DELIMITERS= TextProcessor.getDefaultDelimiters() + "*.?"; //$NON-NLS-1$
private static final String URL_DELIMITERS= TextProcessor.getDefaultDelimiters() + ":@?-"; //$NON-NLS-1$
/**
* Returns the label of a path.
*
* @param path the path
* @param isOSPath if <code>true</code>, the path represents an OS path, if <code>false</code> it is a workspace path.
* @return the label of the path to be used in the UI.
*/
public static String getPathLabel(IPath path, boolean isOSPath) {
String label;
if (isOSPath) {
label= path.toOSString();
} else {
label= path.makeRelative().toString();
}
return Strings.markLTR(label);
}
/**
* Returns the label of the path of a file.
*
* @param file the file
* @return the label of the file path to be used in the UI.
*/
public static String getPathLabel(File file) {
return Strings.markLTR(file.getAbsolutePath());
}
/**
* Returns the label for a file pattern like '*.java'
*
* @param name the pattern
* @return the label of the pattern.
*/
public static String getFilePattern(String name) {
return Strings.markLTR(name, FILE_PATTERN_DELIMITERS);
}
/**
* Returns the label for a URL, URI or URL part. Example is 'http://www.x.xom/s.html#1'
*
* @param name the URL string
* @return the label of the URL.
*/
public static String getURLPart(String name) {
return Strings.markLTR(name, URL_DELIMITERS);
}
/**
* Returns a label for a resource name.
*
* @param resource the resource
* @return the label of the resource name.
*/
public static String getResourceName(IResource resource) {
return Strings.markLTR(resource.getName());
}
/**
* Returns a label for a resource name.
*
* @param resourceName the resource name
* @return the label of the resource name.
*/
public static String getResourceName(String resourceName) {
return Strings.markLTR(resourceName);
}
/**
* Returns a label for C element name. Example is 'new Test<? extends List>() { ...}'.
* This method should only be used for simple element names. Use
* {@link CElementLabels} to create a label from a C element.
*
* @param name the C element name.
* @return the label for the C element
*/
public static String getCElementName(String name) {
return Strings.markCElementLabelLTR(name);
}
/**
* Returns a label for C code snippet used in a label. Example is 'Test test= new Test<? extends List>() { ...}'.
*
* @param string the C code snippet
* @return the label for the C code snippet
*/
public static String getCCodeString(String string) {
return Strings.markLTR(string, CODE_DELIMITERS);
}
/**
* Returns a label for a version name. Example is '1.4.1'
*
* @param name the version string
* @return the version label
*/
public static String getVersionName(String name) {
return Strings.markLTR(name);
}
/**
* Returns a label for a working set
*
* @param set the working set
* @return the label of the working set
*/
public static String getWorkingSetLabel(IWorkingSet set) {
return Strings.markLTR(set.getLabel());
}
}

View file

@ -41,6 +41,7 @@ import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.source.ISharedTextColors;
import org.eclipse.jface.text.templates.ContextTypeRegistry;
@ -657,6 +658,21 @@ public class CUIPlugin extends AbstractUIPlugin {
return fCombinedPreferenceStore;
}
/**
* Returns a section in the C UI plugin's dialog settings. If the section doesn't exist yet, it is created.
*
* @param name the name of the section
* @return the section of the given name
* @since 5.3
*/
public IDialogSettings getDialogSettingsSection(String name) {
IDialogSettings dialogSettings= getDialogSettings();
IDialogSettings section= dialogSettings.getSection(name);
if (section == null) {
section= dialogSettings.addNewSection(name);
}
return section;
}
/**
* Returns an array of all editors that have an unsaved content. If the identical content is

View file

@ -1130,6 +1130,26 @@ public class PreferenceConstants {
*/
public final static String CODEASSIST_PARAMETERS_FOREGROUND= "content_assist_parameters_foreground"; //$NON-NLS-1$
/**
* A named preference that controls whether all dirty editors are automatically saved before a refactoring is
* executed.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
* @since 5.3
*/
public static final String REFACTOR_SAVE_ALL_EDITORS= "Refactoring.savealleditors"; //$NON-NLS-1$
/**
* A named preference that controls whether certain refactorings use a lightweight UI when
* started from a C/C++ editor.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
* @since 5.3
*/
public static final String REFACTOR_LIGHTWEIGHT= "Refactor.lightweight"; //$NON-NLS-1$
/**
* A named preference that controls whether words containing digits should
* be skipped during spell checking.
@ -1479,7 +1499,6 @@ public class PreferenceConstants {
store.setDefault(PreferenceConstants.PREF_SHOW_CU_CHILDREN, true);
// This option has to be turned on for the spelling checker too work.
// As of 4.0, it doesn't produce false positives any more.
store.setDefault(PreferenceConstants.EDITOR_EVALUATE_TEMPORARY_PROBLEMS, true);
int sourceHoverModifier= SWT.MOD2;
@ -1489,7 +1508,7 @@ public class PreferenceConstants {
store.setDefault(EDITOR_SOURCE_HOVER_BACKGROUND_COLOR_SYSTEM_DEFAULT, true);
// coloring
// Coloring
PreferenceConverter.setDefault(store, EDITOR_MULTI_LINE_COMMENT_COLOR, new RGB(63, 127, 95));
store.setDefault(EDITOR_MULTI_LINE_COMMENT_BOLD, false);
store.setDefault(EDITOR_MULTI_LINE_COMMENT_ITALIC, false);
@ -1550,7 +1569,7 @@ public class PreferenceConstants {
store.setDefault(EDITOR_ASM_DIRECTIVE_BOLD, true);
store.setDefault(EDITOR_ASM_DIRECTIVE_ITALIC, false);
// folding
// Folding
store.setDefault(PreferenceConstants.EDITOR_FOLDING_ENABLED, false);
store.setDefault(PreferenceConstants.EDITOR_FOLDING_PROVIDER, "org.eclipse.cdt.ui.text.defaultFoldingProvider"); //$NON-NLS-1$
store.setDefault(PreferenceConstants.EDITOR_FOLDING_FUNCTIONS, false);
@ -1562,7 +1581,7 @@ public class PreferenceConstants {
store.setDefault(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, true);
store.setDefault(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, false);
// smart edit
// Smart edit
store.setDefault(PreferenceConstants.EDITOR_CLOSE_STRINGS, true);
store.setDefault(PreferenceConstants.EDITOR_CLOSE_BRACKETS, true);
store.setDefault(PreferenceConstants.EDITOR_CLOSE_ANGULAR_BRACKETS, true);
@ -1577,10 +1596,10 @@ public class PreferenceConstants {
store.setDefault(PreferenceConstants.REMOVE_TRAILING_WHITESPACE_LIMIT_TO_EDITED_LINES, true);
store.setDefault(PreferenceConstants.ENSURE_NEWLINE_AT_EOF, true);
// formatter profile
// Formatter profile
store.setDefault(PreferenceConstants.FORMATTER_PROFILE, FormatterProfileManager.DEFAULT_PROFILE);
// content assist
// Content assist
store.setDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES, "org.eclipse.cdt.ui.textProposalCategory\0"); //$NON-NLS-1$
store.setDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER, "org.eclipse.cdt.ui.parserProposalCategory:65539\0org.eclipse.cdt.ui.textProposalCategory:65541\0org.eclipse.cdt.ui.templateProposalCategory:2\0org.eclipse.cdt.ui.helpProposalCategory:5\0"); //$NON-NLS-1$
@ -1601,7 +1620,11 @@ public class PreferenceConstants {
PreferenceConstants.CODEASSIST_PARAMETERS_FOREGROUND,
findRGB(registry, ICThemeConstants.CODEASSIST_PARAMETERS_FOREGROUND, new RGB(0, 0, 0)));
// spell checking
// Refactoring.
store.setDefault(PreferenceConstants.REFACTOR_SAVE_ALL_EDITORS, false);
store.setDefault(PreferenceConstants.REFACTOR_LIGHTWEIGHT, true);
// Spell checking
store.setDefault(PreferenceConstants.SPELLING_LOCALE, "en_US"); //$NON-NLS-1$
String isInitializedKey= "spelling_locale_initialized"; //$NON-NLS-1$
if (!store.getBoolean(isInitializedKey)) {

View file

@ -122,7 +122,7 @@ public class OpenAction extends SelectionDispatchAction {
*/
@Override
public void run(ITextSelection selection) {
if (!ActionUtil.isProcessable(getShell(), fEditor))
if (!ActionUtil.isProcessable(fEditor))
return;
try {
ICElement element= SelectionConverter.codeResolve(fEditor, getShell(), getDialogTitle(),

View file

@ -1,16 +1,18 @@
/*******************************************************************************
* Copyright (c) 2005, 2009 Wind River Systems, Inc.
* Copyright (c) 2005, 2010 Wind River Systems, Inc.
* 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.ui.refactoring.actions;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.window.IShellProvider;
@ -18,8 +20,13 @@ import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.IInclude;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.IWorkingCopy;
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;
/**
* Launches a rename refactoring.
@ -29,17 +36,28 @@ import org.eclipse.cdt.internal.ui.refactoring.rename.CRefactory;
public class CRenameAction extends RefactoringAction {
public CRenameAction() {
super(Messages.CRenameAction_label);
super(Messages.CRenameAction_label);
setSaveRequired(false);
}
@Override
public void run(IShellProvider shellProvider, ICElement elem) {
CRefactory.getInstance().rename(shellProvider.getShell(), elem);
if (!ActionUtil.isEditable((CEditor) fEditor, shellProvider.getShell(), elem))
return;
CRefactory.getInstance().rename(shellProvider.getShell(), elem);
}
@Override
public void run(IShellProvider shellProvider, IWorkingCopy wc, ITextSelection s) {
CRefactory.getInstance().rename(shellProvider.getShell(), wc, s);
public void run(IShellProvider shellProvider, IWorkingCopy workingCopy, ITextSelection selection) {
if (!ActionUtil.isEditable((CEditor) fEditor))
return;
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
boolean lightweight= store.getBoolean(PreferenceConstants.REFACTOR_LIGHTWEIGHT);
if (lightweight) {
new RenameLinkedMode((CEditor) fEditor).start();
} else {
CRefactory.getInstance().rename(shellProvider.getShell(), workingCopy, selection);
}
}
@Override

View file

@ -34,9 +34,20 @@ public abstract class RefactoringAction extends Action {
protected ITextEditor fEditor;
private IWorkbenchSite fSite;
private ICElement fElement;
private boolean saveRequired;
public RefactoringAction(String label) {
super(label);
saveRequired = true;
}
/**
* Sets behavior with respect to saving dirty editors.
* @param saveRequired if <code>true</code>, dirty editors will be saved before refactoring.
* @since 5.3
*/
public void setSaveRequired(boolean saveRequired) {
this.saveRequired = saveRequired;
}
public void setEditor(IEditorPart editor) {
@ -55,9 +66,11 @@ public abstract class RefactoringAction extends Action {
@Override
public final void run() {
EclipseObjects.getActivePage().saveAllEditors(true);
if (EclipseObjects.getActivePage().getDirtyEditors().length != 0) {
return;
if (saveRequired) {
EclipseObjects.getActivePage().saveAllEditors(true);
if (EclipseObjects.getActivePage().getDirtyEditors().length != 0) {
return;
}
}
if (fEditor != null) {
ISelectionProvider provider= fEditor.getSelectionProvider();