From c4ca43c1ac79961a51bfd13f8a039d13eb6bac37 Mon Sep 17 00:00:00 2001 From: Anton Leherbauer Date: Mon, 22 Nov 2010 11:28:19 +0000 Subject: [PATCH] Bug 245747 - There is no way to format all the source files in a CDT project --- .../cdt/internal/corext/util/CModelUtil.java | 251 ++++++----- .../internal/ui/actions/ActionMessages.java | 12 + .../ui/actions/ActionMessages.properties | 14 + .../CNavigatorEditActionProvider.java | 41 +- .../cdt/ui/actions/FormatAllAction.java | 418 ++++++++++++++++++ .../cdt/ui/actions/GenerateActionGroup.java | 14 +- 6 files changed, 621 insertions(+), 129 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/FormatAllAction.java diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/CModelUtil.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/CModelUtil.java index acc5776d15d..33756948eea 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/CModelUtil.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/CModelUtil.java @@ -1,117 +1,134 @@ -/******************************************************************************* - * Copyright (c) 2004, 2007 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 Rational Software - Initial API and implementation - * Markus Schorn (Wind River Systems) - *******************************************************************************/ -package org.eclipse.cdt.internal.corext.util; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; - -import org.eclipse.cdt.core.model.ICContainer; -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.core.model.ISourceRoot; -import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.core.model.IWorkingCopy; - -import org.eclipse.cdt.internal.ui.util.EditorUtility; - -public class CModelUtil { - /** - * Returns the working copy CU of the given CU. If the CU is already a - * working copy or the CU has no working copy the input CU is returned. - */ - public static ITranslationUnit toWorkingCopy(ITranslationUnit unit) { - if (!unit.isWorkingCopy()) { - ITranslationUnit workingCopy= EditorUtility.getWorkingCopy(unit); - if (workingCopy != null) { - return workingCopy; - } - } - return unit; - } - - public static ITranslationUnit toOriginal(ITranslationUnit unit){ - if (unit.isWorkingCopy()) { - return (((IWorkingCopy) unit).getOriginalElement()); - } - return unit; - } - - /** - * Returns the source root of ICElement. If the given - * element is already a source root, the element itself is returned. - */ - public static ISourceRoot getSourceRoot(ICElement element) { - ICElement root = element; - while (root != null) { - if (root instanceof ISourceRoot) - return (ISourceRoot)root; - ICElement parent = root.getAncestor(ICElement.C_CCONTAINER); - if (parent == root) - return null; - root = parent; - } - return null; - } - - /** - * Returns the source folder of ICElement. If the given - * element is already a source folder, the element itself is returned. - */ - public static ICContainer getSourceFolder(ICElement element) { - ICContainer folder = null; - if (element != null) { - boolean foundSourceRoot = false; - ICElement curr = element; - while (curr != null && !foundSourceRoot) { - if (curr instanceof ICContainer && folder == null) { - folder = (ICContainer)curr; - } - foundSourceRoot = (curr instanceof ISourceRoot); - curr = curr.getParent(); - } - if (folder == null) { - ICProject cproject = element.getCProject(); - folder = cproject.findSourceRoot(cproject.getProject()); - } - } - return folder; - } - - /** - * Returns true if the given source root is - * referenced. This means it is own by a different project but is referenced - * by the root's parent. Returns false if the given root - * doesn't have an underlying resource. - */ - public static boolean isReferenced(ISourceRoot root) { - IResource resource= root.getResource(); - if (resource != null) { - IProject project= resource.getProject(); - IProject container= root.getCProject().getProject(); - return !container.equals(project); - } - return false; - } - - /** - * Returns the translation unit the element belongs to or null if it does not. - */ - public static ITranslationUnit getTranslationUnit(ICElement elem) { - while (elem != null) { - if (elem instanceof ITranslationUnit) { - return (ITranslationUnit) elem; - } - elem= elem.getParent(); - } - return null; - } -} +/******************************************************************************* + * Copyright (c) 2004, 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 Rational Software - Initial API and implementation + * Markus Schorn (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.corext.util; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICContainer; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICModelStatus; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ISourceRoot; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.IWorkingCopy; + +import org.eclipse.cdt.internal.ui.util.EditorUtility; + +public class CModelUtil { + /** + * Returns the working copy CU of the given CU. If the CU is already a + * working copy or the CU has no working copy the input CU is returned. + */ + public static ITranslationUnit toWorkingCopy(ITranslationUnit unit) { + if (!unit.isWorkingCopy()) { + ITranslationUnit workingCopy= EditorUtility.getWorkingCopy(unit); + if (workingCopy != null) { + return workingCopy; + } + } + return unit; + } + + public static ITranslationUnit toOriginal(ITranslationUnit unit){ + if (unit.isWorkingCopy()) { + return (((IWorkingCopy) unit).getOriginalElement()); + } + return unit; + } + + /** + * Returns the source root of ICElement. If the given + * element is already a source root, the element itself is returned. + */ + public static ISourceRoot getSourceRoot(ICElement element) { + ICElement root = element; + while (root != null) { + if (root instanceof ISourceRoot) + return (ISourceRoot)root; + ICElement parent = root.getAncestor(ICElement.C_CCONTAINER); + if (parent == root) + return null; + root = parent; + } + return null; + } + + /** + * Returns the source folder of ICElement. If the given + * element is already a source folder, the element itself is returned. + */ + public static ICContainer getSourceFolder(ICElement element) { + ICContainer folder = null; + if (element != null) { + boolean foundSourceRoot = false; + ICElement curr = element; + while (curr != null && !foundSourceRoot) { + if (curr instanceof ICContainer && folder == null) { + folder = (ICContainer)curr; + } + foundSourceRoot = (curr instanceof ISourceRoot); + curr = curr.getParent(); + } + if (folder == null) { + ICProject cproject = element.getCProject(); + folder = cproject.findSourceRoot(cproject.getProject()); + } + } + return folder; + } + + /** + * Returns true if the given source root is + * referenced. This means it is own by a different project but is referenced + * by the root's parent. Returns false if the given root + * doesn't have an underlying resource. + */ + public static boolean isReferenced(ISourceRoot root) { + IResource resource= root.getResource(); + if (resource != null) { + IProject project= resource.getProject(); + IProject container= root.getCProject().getProject(); + return !container.equals(project); + } + return false; + } + + /** + * Returns the translation unit the element belongs to or null if it does not. + */ + public static ITranslationUnit getTranslationUnit(ICElement elem) { + while (elem != null) { + if (elem instanceof ITranslationUnit) { + return (ITranslationUnit) elem; + } + elem= elem.getParent(); + } + return null; + } + + /* + * Don't log not-exists exceptions + */ + public static boolean isExceptionToBeLogged(CoreException exception) { + if (!(exception instanceof CModelException)) + return true; + CModelException ce= (CModelException)exception; + ICModelStatus status = ce.getCModelStatus(); + if (status == null || !status.doesNotExist()) + return true; + return false; + } + +} 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 3e3e88df8ff..bb59cbe20ae 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 @@ -79,6 +79,18 @@ public class ActionMessages extends NLS { public static String SurroundWithTemplateMenuAction_NoneApplicable; public static String CopyTreeAction_problem; public static String CopyTreeAction_clipboard_busy; + public static String FormatAllAction_label; + public static String FormatAllAction_tooltip; + public static String FormatAllAction_description; + public static String FormatAllAction_status_description; + public static String FormatAllAction_multi_status_title; + public static String FormatAllAction_error_title; + public static String FormatAllAction_error_message; + public static String FormatAllAction_operation_description; + public static String FormatAllAction_failedvalidateedit_title; + public static String FormatAllAction_failedvalidateedit_message; + public static String FormatAllAction_noundo_title; + public static String FormatAllAction_noundo_message; static { // Initialize resource bundle. 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 20753baf9a0..c27f42bce76 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 @@ -95,3 +95,17 @@ SurroundWithTemplateMenuAction_NoneApplicable=(no template applicable) CopyTreeAction_problem=Problem Copying to Clipboard CopyTreeAction_clipboard_busy=There was a problem when accessing the system clipboard. Retry? + +FormatAllAction_label=&Format +FormatAllAction_tooltip=Format all selected C/C++ files +FormatAllAction_description=Format all selected C/C++ files +FormatAllAction_status_description=Problems while formatting some files. See 'Details' for more information. +FormatAllAction_multi_status_title=Format +FormatAllAction_error_title=Format +FormatAllAction_error_message=Unexpected error while formatting. See log for details. + +FormatAllAction_operation_description=Formatting... +FormatAllAction_failedvalidateedit_title=Format +FormatAllAction_failedvalidateedit_message=Problems while accessing selected files. +FormatAllAction_noundo_title=Format +FormatAllAction_noundo_message='Undo' is not supported by this operation. Do you want to continue? diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/navigator/CNavigatorEditActionProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/navigator/CNavigatorEditActionProvider.java index b00d09bd796..906901ce305 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/navigator/CNavigatorEditActionProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/navigator/CNavigatorEditActionProvider.java @@ -14,9 +14,13 @@ package org.eclipse.cdt.internal.ui.navigator; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IViewPart; import org.eclipse.ui.actions.ActionContext; import org.eclipse.ui.navigator.CommonActionProvider; import org.eclipse.ui.navigator.ICommonActionExtensionSite; +import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite; + +import org.eclipse.cdt.ui.actions.GenerateActionGroup; import org.eclipse.cdt.internal.ui.actions.SelectionConverter; @@ -26,24 +30,39 @@ import org.eclipse.cdt.internal.ui.actions.SelectionConverter; public class CNavigatorEditActionProvider extends CommonActionProvider { private CNavigatorEditActionGroup fEditGroup; - - private ICommonActionExtensionSite fSite; + private GenerateActionGroup fGenerateGroup; /* * @see org.eclipse.ui.navigator.CommonActionProvider#init(org.eclipse.ui.navigator.ICommonActionExtensionSite) */ @Override public void init(ICommonActionExtensionSite anActionSite) { - fSite = anActionSite; - fEditGroup = new CNavigatorEditActionGroup(fSite.getViewSite().getShell()); + super.init(anActionSite); + + fEditGroup = new CNavigatorEditActionGroup(anActionSite.getViewSite().getShell()); + + ICommonViewerWorkbenchSite workbenchSite= null; + if (anActionSite.getViewSite() instanceof ICommonViewerWorkbenchSite) { + workbenchSite= (ICommonViewerWorkbenchSite) anActionSite.getViewSite(); + } + if (workbenchSite != null) { + if (workbenchSite.getPart() != null && workbenchSite.getPart() instanceof IViewPart) { + IViewPart viewPart= (IViewPart) workbenchSite.getPart(); + + fGenerateGroup = new GenerateActionGroup(viewPart); + } + } } /* * @see org.eclipse.ui.actions.ActionGroup#dispose() */ @Override - public void dispose() { + public void dispose() { fEditGroup.dispose(); + if (fGenerateGroup != null) { + fGenerateGroup.dispose(); + } } /* @@ -52,6 +71,9 @@ public class CNavigatorEditActionProvider extends CommonActionProvider { @Override public void fillActionBars(IActionBars actionBars) { fEditGroup.fillActionBars(actionBars); + if (fGenerateGroup != null) { + fGenerateGroup.fillActionBars(actionBars); + } } /* @@ -60,6 +82,9 @@ public class CNavigatorEditActionProvider extends CommonActionProvider { @Override public void fillContextMenu(IMenuManager menu) { fEditGroup.fillContextMenu(menu); + if (fGenerateGroup != null) { + fGenerateGroup.fillContextMenu(menu); + } } /* @@ -74,6 +99,9 @@ public class CNavigatorEditActionProvider extends CommonActionProvider { } else { fEditGroup.setContext(context); } + if (fGenerateGroup != null) { + fGenerateGroup.setContext(context); + } } /* @@ -82,5 +110,8 @@ public class CNavigatorEditActionProvider extends CommonActionProvider { @Override public void updateActionBars() { fEditGroup.updateActionBars(); + if (fGenerateGroup != null) { + fGenerateGroup.updateActionBars(); + } } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/FormatAllAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/FormatAllAction.java new file mode 100644 index 00000000000..3b37dfda3a9 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/FormatAllAction.java @@ -0,0 +1,418 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.cdt.ui.actions; + +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.eclipse.core.filebuffers.FileBuffers; +import org.eclipse.core.filebuffers.ITextFileBuffer; +import org.eclipse.core.filebuffers.ITextFileBufferManager; +import org.eclipse.core.filebuffers.LocationKind; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRunnable; +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.MultiStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.DocumentRewriteSession; +import org.eclipse.jface.text.DocumentRewriteSessionType; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension; +import org.eclipse.jface.text.IDocumentExtension4; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.formatter.FormattingContext; +import org.eclipse.jface.text.formatter.FormattingContextProperties; +import org.eclipse.jface.text.formatter.IFormattingContext; +import org.eclipse.jface.text.formatter.MultiPassContentFormatter; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.PlatformUI; + +import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICContainer; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.model.ISourceRoot; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.ui.CDTUITools; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.corext.util.Resources; + +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +import org.eclipse.cdt.internal.ui.actions.ActionMessages; +import org.eclipse.cdt.internal.ui.actions.WorkbenchRunnableAdapter; +import org.eclipse.cdt.internal.ui.dialogs.OptionalMessageDialog; +import org.eclipse.cdt.internal.ui.text.CFormattingStrategy; +import org.eclipse.cdt.internal.ui.util.EditorUtility; +import org.eclipse.cdt.internal.ui.util.ExceptionHandler; + +/** + * Formats the code of the translation units contained in the selection. + *

+ * The action is applicable to selections containing elements of + * type ITranslationUnit, ICContainer + * and ICProject. + *

+ *

+ * This class may be instantiated; it is not intended to be subclassed. + *

+ * + * @since 5.3 + * + * @noextend This class is not intended to be subclassed by clients. + */ +public class FormatAllAction extends SelectionDispatchAction { + + /* + * Class implements IObjectActionDelegate + */ + public static class ObjectDelegate implements IObjectActionDelegate { + private FormatAllAction fAction; + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + fAction= new FormatAllAction(targetPart.getSite()); + } + public void run(IAction action) { + fAction.run(); + } + public void selectionChanged(IAction action, ISelection selection) { + if (fAction == null) + action.setEnabled(false); + } + } + + private DocumentRewriteSession fRewriteSession; + + /** + * Creates a new FormatAllAction. The action requires + * that the selection provided by the site's selection provider is of type + * org.eclipse.jface.viewers.IStructuredSelection. + * + * @param site the site providing context information for this action + */ + public FormatAllAction(IWorkbenchSite site) { + super(site); + setText(ActionMessages.FormatAllAction_label); + setToolTipText(ActionMessages.FormatAllAction_tooltip); + setDescription(ActionMessages.FormatAllAction_description); + + PlatformUI.getWorkbench().getHelpSystem().setHelp(this, ICHelpContextIds.FORMAT_ALL); + } + + + @Override + public void selectionChanged(ITextSelection selection) { + // do nothing + } + + @Override + public void selectionChanged(IStructuredSelection selection) { + setEnabled(isEnabled(selection)); + } + + private ITranslationUnit[] getTranslationUnits(IStructuredSelection selection) { + HashSet result= new HashSet(); + Object[] selected= selection.toArray(); + for (int i= 0; i < selected.length; i++) { + try { + if (selected[i] instanceof ICElement) { + ICElement elem= (ICElement) selected[i]; + if (elem.exists()) { + switch (elem.getElementType()) { + case ICElement.C_UNIT: + result.add(elem); + break; + case ICElement.C_CCONTAINER: + collectTranslationUnits((ICContainer) elem, result); + break; + case ICElement.C_PROJECT: + collectTranslationUnits((ICProject) elem, result); + break; + } + } + } else if (selected[i] instanceof IProject) { + final IProject project = (IProject) selected[i]; + if (CoreModel.hasCNature(project)) { + collectTranslationUnits(CoreModel.getDefault().create(project), result); + } + } + } catch (CModelException e) { + CUIPlugin.log(e); + } + } + return result.toArray(new ITranslationUnit[result.size()]); + } + + private void collectTranslationUnits(ICProject project, Collection result) throws CModelException { + ISourceRoot[] roots = project.getSourceRoots(); + for (ISourceRoot root : roots) { + collectTranslationUnits(root, result); + } + } + + private void collectTranslationUnits(ICContainer container, Collection result) throws CModelException { + ICElement[] children= container.getChildren(); + for (int i= 0; i < children.length; i++) { + ICElement elem= children[i]; + if (elem.exists()) { + switch (elem.getElementType()) { + case ICElement.C_UNIT: + result.add(elem); + break; + case ICElement.C_CCONTAINER: + collectTranslationUnits((ICContainer) elem, result); + break; + } + } + } + } + + private boolean isEnabled(IStructuredSelection selection) { + Object[] selected= selection.toArray(); + for (int i= 0; i < selected.length; i++) { + if (selected[i] instanceof ICElement) { + ICElement elem= (ICElement) selected[i]; + if (elem.exists()) { + switch (elem.getElementType()) { + case ICElement.C_UNIT: + case ICElement.C_CCONTAINER: + case ICElement.C_PROJECT: + return true; + } + } + } else if (selected[i] instanceof IProject) { + if (CoreModel.hasCNature((IProject) selected[i])) { + return true; + } + } + } + return false; + } + + @Override + public void run(ITextSelection selection) { + } + + @Override + public void run(IStructuredSelection selection) { + ITranslationUnit[] tus= getTranslationUnits(selection); + if (tus.length == 0) + return; + if (tus.length > 1) { + int returnCode= OptionalMessageDialog.open("FormatAll", //$NON-NLS-1$ + getShell(), + ActionMessages.FormatAllAction_noundo_title, + null, + ActionMessages.FormatAllAction_noundo_message, + MessageDialog.WARNING, + new String[] {IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL}, + 0); + if (returnCode != OptionalMessageDialog.NOT_SHOWN && + returnCode != Window.OK ) return; + } + + IStatus status= Resources.makeCommittable(getResources(tus), getShell()); + if (!status.isOK()) { + ErrorDialog.openError(getShell(), ActionMessages.FormatAllAction_failedvalidateedit_title, ActionMessages.FormatAllAction_failedvalidateedit_message, status); + return; + } + + runOnMultiple(tus); + } + + private IResource[] getResources(ITranslationUnit[] tus) { + IResource[] res= new IResource[tus.length]; + for (int i= 0; i < res.length; i++) { + res[i]= tus[i].getResource(); + } + return res; + } + + /** + * Perform format all on the given translation units. + * @param tus The translation units to format. + */ + public void runOnMultiple(final ITranslationUnit[] tus) { + try { + String message= ActionMessages.FormatAllAction_status_description; + final MultiStatus status= new MultiStatus(CUIPlugin.PLUGIN_ID, IStatus.OK, message, null); + + if (tus.length == 1) { + EditorUtility.openInEditor(tus[0]); + } + + PlatformUI.getWorkbench().getProgressService().run(true, true, new WorkbenchRunnableAdapter(new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) { + doRunOnMultiple(tus, status, monitor); + } + })); // workspace lock + if (!status.isOK()) { + String title= ActionMessages.FormatAllAction_multi_status_title; + ErrorDialog.openError(getShell(), title, null, status); + } + } catch (InvocationTargetException e) { + ExceptionHandler.handle(e, getShell(), ActionMessages.FormatAllAction_error_title, ActionMessages.FormatAllAction_error_message); + } catch (InterruptedException e) { + // Canceled by user + } catch (CoreException e) { + ExceptionHandler.handle(e, getShell(), ActionMessages.FormatAllAction_error_title, ActionMessages.FormatAllAction_error_message); + } + } + + private static Map getFomatterSettings(ICProject project) { + return new HashMap(project.getOptions(true)); + } + + private void doFormat(IDocument document, Map options) { + final IFormattingContext context = new FormattingContext(); + try { + context.setProperty(FormattingContextProperties.CONTEXT_PREFERENCES, options); + context.setProperty(FormattingContextProperties.CONTEXT_DOCUMENT, Boolean.valueOf(true)); + + final MultiPassContentFormatter formatter= new MultiPassContentFormatter(ICPartitions.C_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE); + formatter.setMasterStrategy(new CFormattingStrategy()); + + try { + startSequentialRewriteMode(document); + formatter.format(document, context); + } finally { + stopSequentialRewriteMode(document); + } + } finally { + context.dispose(); + } + } + + @SuppressWarnings("deprecation") + private void startSequentialRewriteMode(IDocument document) { + if (document instanceof IDocumentExtension4) { + IDocumentExtension4 extension= (IDocumentExtension4) document; + fRewriteSession= extension.startRewriteSession(DocumentRewriteSessionType.SEQUENTIAL); + } else if (document instanceof IDocumentExtension) { + IDocumentExtension extension= (IDocumentExtension) document; + extension.startSequentialRewrite(false); + } + } + + @SuppressWarnings("deprecation") + private void stopSequentialRewriteMode(IDocument document) { + if (document instanceof IDocumentExtension4) { + IDocumentExtension4 extension= (IDocumentExtension4) document; + extension.stopRewriteSession(fRewriteSession); + } else if (document instanceof IDocumentExtension) { + IDocumentExtension extension= (IDocumentExtension)document; + extension.stopSequentialRewrite(); + } + } + + private void doRunOnMultiple(ITranslationUnit[] tus, MultiStatus status, IProgressMonitor monitor) throws OperationCanceledException { + if (monitor == null) { + monitor= new NullProgressMonitor(); + } + monitor.setTaskName(ActionMessages.FormatAllAction_operation_description); + + monitor.beginTask("", tus.length * 4); //$NON-NLS-1$ + try { + Map lastOptions= null; + ICProject lastProject= null; + + for (int i= 0; i < tus.length; i++) { + ITranslationUnit tu= tus[i]; + IPath path= tu.getPath(); + if (lastProject == null || lastOptions == null|| !lastProject.equals(tu.getCProject())) { + lastProject= tu.getCProject(); + lastOptions= getFomatterSettings(lastProject); + } + + ILanguage language= null; + try { + language= tu.getLanguage(); + } catch (CoreException exc) { + // use fallback CPP + language= GPPLanguage.getDefault(); + } + + // use working copy if available + ITranslationUnit wc = CDTUITools.getWorkingCopyManager().findSharedWorkingCopy(tu); + if (wc != null) { + tu = wc; + } + lastOptions.put(DefaultCodeFormatterConstants.FORMATTER_TRANSLATION_UNIT, tu); + lastOptions.put(DefaultCodeFormatterConstants.FORMATTER_LANGUAGE, language); + lastOptions.put(DefaultCodeFormatterConstants.FORMATTER_CURRENT_FILE, tu.getResource()); + + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + + ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager(); + try { + try { + manager.connect(path, LocationKind.IFILE, new SubProgressMonitor(monitor, 1)); + + monitor.subTask(path.makeRelative().toString()); + ITextFileBuffer fileBuffer= manager.getTextFileBuffer(path, LocationKind.IFILE); + boolean wasDirty = fileBuffer.isDirty(); + + formatTranslationUnit(fileBuffer, lastOptions); + + if (fileBuffer.isDirty() && !wasDirty) { + fileBuffer.commit(new SubProgressMonitor(monitor, 2), false); + } else { + monitor.worked(2); + } + } finally { + manager.disconnect(path, LocationKind.IFILE, new SubProgressMonitor(monitor, 1)); + } + } catch (CoreException e) { + status.add(e.getStatus()); + } + } + } finally { + monitor.done(); + } + } + + private void formatTranslationUnit(final ITextFileBuffer fileBuffer, final Map options) { + if (fileBuffer.isShared()) { + getShell().getDisplay().syncExec(new Runnable() { + public void run() { + doFormat(fileBuffer.getDocument(), options); + } + }); + } else { + doFormat(fileBuffer.getDocument(), options); // run in context thread + } + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/GenerateActionGroup.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/GenerateActionGroup.java index 43f889ea340..60f8dde5980 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/GenerateActionGroup.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/GenerateActionGroup.java @@ -131,7 +131,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange // private OrganizeIncludesAction fOrganizeIncludes; // private SortMembersAction fSortMembers; private SortLinesAction fSortLines; -// private FormatAllAction fFormatAll; + private FormatAllAction fFormatAll; // private CopyQualifiedNameAction fCopyQualifiedNameAction; // private static final String QUICK_MENU_ID= "org.eclipse.cdt.ui.edit.text.c.source.quickMenu"; //$NON-NLS-1$ @@ -286,8 +286,8 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange // fSortMembers= new SortMembersAction(site); // fSortMembers.setActionDefinitionId(ICEditorActionDefinitionIds.SORT_MEMBERS); // -// fFormatAll= new FormatAllAction(site); -// fFormatAll.setActionDefinitionId(ICEditorActionDefinitionIds.FORMAT); + fFormatAll= new FormatAllAction(site); + fFormatAll.setActionDefinitionId(ICEditorActionDefinitionIds.FORMAT); // // fCleanUp= new CleanUpAction(site); // fCleanUp.setActionDefinitionId(ICEditorActionDefinitionIds.CLEAN_UP); @@ -304,7 +304,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange // fCleanUp.update(selection); // fOrganizeIncludes.update(selection); // fSortMembers.update(selection); -// fFormatAll.update(selection); + fFormatAll.update(selection); if (selection instanceof IStructuredSelection) { IStructuredSelection ss= (IStructuredSelection)selection; fAddBookmark.selectionChanged(ss); @@ -324,7 +324,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange // registerSelectionListener(provider, fExternalizeStrings); // registerSelectionListener(provider, fFindNLSProblems); // registerSelectionListener(provider, fOrganizeIncludes); -// registerSelectionListener(provider, fFormatAll); + registerSelectionListener(provider, fFormatAll); // registerSelectionListener(provider, fSortMembers); registerSelectionListener(provider, fAddTaskAction); // registerSelectionListener(provider, fCleanUp); @@ -439,7 +439,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange source.add(new Separator(GROUP_COMMENT)); // added+= addAction(source, fAddCppDocStub); source.add(new Separator(GROUP_EDIT)); -// added+= addAction(source, fFormatAll); + added+= addAction(source, fFormatAll); source.add(new Separator(GROUP_ORGANIZE)); added+= addAction(source, fAddInclude); // added+= addAction(source, fOrganizeIncludes); @@ -497,7 +497,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange // editor provides its own implementation of these actions. actionBar.setGlobalActionHandler(IDEActionFactory.BOOKMARK.getId(), fAddBookmark); actionBar.setGlobalActionHandler(IDEActionFactory.ADD_TASK.getId(), fAddTaskAction); -// actionBar.setGlobalActionHandler(CdtActionConstants.FORMAT, fFormatAll); + actionBar.setGlobalActionHandler(CdtActionConstants.FORMAT, fFormatAll); } else { // actionBar.setGlobalActionHandler(CopyQualifiedNameAction.ACTION_HANDLER_ID, fCopyQualifiedNameAction); }