diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/quickfix/AssistQuickFixTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/quickfix/AssistQuickFixTest.java index 14647a0049a..e5185728075 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/quickfix/AssistQuickFixTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/quickfix/AssistQuickFixTest.java @@ -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 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 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 { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java index bbc8d4b0691..c3b5ca59833 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java @@ -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} + *

+ * This is used for performance optimization. + *

+ * @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 true if the given string only consists of - * white spaces according to Java. If the string is empty, true + * white spaces according to C. If the string is empty, true * is returned. * * @return true 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); + } + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java index 764e0f7f8a0..34b5e93efad 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java @@ -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); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.java index 0a9d425b337..3e3e88df8ff 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.java @@ -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; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.properties index d0b12f6543a..20753baf9a0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.properties @@ -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 diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionUtil.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionUtil.java index e3ddfb1a3a5..258e18b94ff 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionUtil.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionUtil.java @@ -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 editor and element 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 null 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 null + * @return true if the element can be edited, + * false 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; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/WorkbenchRunnableAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/WorkbenchRunnableAdapter.java index 92260b44b6f..c7ac58952b9 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/WorkbenchRunnableAdapter.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/WorkbenchRunnableAdapter.java @@ -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 IRunnableWithProgress that adapts and IWorkspaceRunnable * so that is can be executed inside IRunnableContext. OperationCanceledException * thrown by the adapted runnable are caught and re-thrown as a InterruptedException. */ -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 null to run with no lock at + * all. + * + * @param runnable the runnable + * @param rule the scheduling rule, or null + * @param transfer true 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) */ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java index 3fdc206a7df..cc03a60fdf5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java @@ -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); } /** diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java index aec11523d4a..b9214dd454b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java @@ -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