From e452d260ffc97ba5d95b651af87b4acd35d8d2f8 Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Tue, 7 Sep 2004 20:25:17 +0000 Subject: [PATCH] 2004-09-07 Alain Magloire Part of the uncoming work to supply formatting in CDT * src/org/eclipse/cdt/internal/corext/CodeFormatterUtil.java * src/org/eclipse/cdt/internal/ui/editor/CEditor.java * src/org/eclipse/cdt/internal/ui/text/CFormatingStrategy.java * src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java * plugin.properties * plugin.xml --- core/org.eclipse.cdt.ui/ChangeLog | 10 + core/org.eclipse.cdt.ui/plugin.properties | 3 + core/org.eclipse.cdt.ui/plugin.xml | 12 + .../corext/util/CodeFormatterUtil.java | 134 +++++++++++ .../cdt/internal/ui/editor/CEditor.java | 1 + .../ui/editor/CEditorActionContributor.java | 6 + .../internal/ui/text/CFormattingStrategy.java | 209 ++++++++++++------ .../ui/text/CSourceViewerConfiguration.java | 23 +- 8 files changed, 314 insertions(+), 84 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/CodeFormatterUtil.java diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index 8c0de95816c..04de3889e16 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,13 @@ +2004-09-07 Alain Magloire + + Part of the uncoming work to supply formatting in CDT + * src/org/eclipse/cdt/internal/corext/CodeFormatterUtil.java + * src/org/eclipse/cdt/internal/ui/editor/CEditor.java + * src/org/eclipse/cdt/internal/ui/text/CFormatingStrategy.java + * src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java + * plugin.properties + * plugin.xml + 2004-09-07 Chris Wiebe comment out old class wizard diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties index f4218779ca2..a7ea61fcfb9 100644 --- a/core/org.eclipse.cdt.ui/plugin.properties +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -84,6 +84,9 @@ ActionDefinition.finddecl.description= Find Declaration ActionDefinition.findrefs.name= Find References ActionDefinition.findrefs.description= Find References +ActionDefinition.format.name=Format +ActionDefinition.format.description=Format Source Code + CEditor.name=C/C++ Editor CPluginPreferencePage.name=C/C++ CPluginEditorPreferencePage.name=Editor diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index c22ababe7c8..591c410567c 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -614,6 +614,18 @@ description="%category.source.description" id="org.eclipse.cdt.ui.category.source"> + + + + null if the code could not be formatted for the given kind. + * @throws IllegalArgumentException If the offset and length are not inside the string, a + * IllegalArgumentException is thrown. + */ + public static TextEdit format(int kind, IDocument document, int offset, int length, int indentationLevel, String lineSeparator, Map options) { + if (offset < 0 || length < 0 || offset + length > document.getLength()) { + throw new IllegalArgumentException("offset or length outside of string. offset: " + offset + ", length: " + length + ", string size: " + document.getLength()); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + } + CodeFormatter formatter = ToolFactory.createCodeFormatter(options); + if (formatter != null) { + return formatter.format(kind, document, offset, length, indentationLevel, lineSeparator); + } + return null; + } + + public static TextEdit format(int kind, IDocument document, int indentationLevel, String lineSeparator, Map options) { + return format(kind, document, 0, document.getLength(), indentationLevel, lineSeparator, options); + } + + + private static TextEdit shifEdit(TextEdit oldEdit, int diff) { + TextEdit newEdit; + if (oldEdit instanceof ReplaceEdit) { + ReplaceEdit edit= (ReplaceEdit) oldEdit; + newEdit= new ReplaceEdit(edit.getOffset() - diff, edit.getLength(), edit.getText()); + } else if (oldEdit instanceof InsertEdit) { + InsertEdit edit= (InsertEdit) oldEdit; + newEdit= new InsertEdit(edit.getOffset() - diff, edit.getText()); + } else if (oldEdit instanceof DeleteEdit) { + DeleteEdit edit= (DeleteEdit) oldEdit; + newEdit= new DeleteEdit(edit.getOffset() - diff, edit.getLength()); + } else if (oldEdit instanceof MultiTextEdit) { + newEdit= new MultiTextEdit(); + } else { + return null; // not supported + } + TextEdit[] children= oldEdit.getChildren(); + for (int i= 0; i < children.length; i++) { + TextEdit shifted= shifEdit(children[i], diff); + if (shifted != null) { + newEdit.addChild(shifted); + } + } + return newEdit; + } + + private static Document createDocument(String string, Position[] positions) throws IllegalArgumentException { + Document doc= new Document(string); + try { + if (positions != null) { + final String POS_CATEGORY= "myCategory"; //$NON-NLS-1$ + + doc.addPositionCategory(POS_CATEGORY); + doc.addPositionUpdater(new DefaultPositionUpdater(POS_CATEGORY) { + protected boolean notDeleted() { + if (fOffset < fPosition.offset && (fPosition.offset + fPosition.length < fOffset + fLength)) { + fPosition.offset= fOffset + fLength; // deleted positions: set to end of remove + return false; + } + return true; + } + }); + for (int i= 0; i < positions.length; i++) { + try { + doc.addPosition(POS_CATEGORY, positions[i]); + } catch (BadLocationException e) { + throw new IllegalArgumentException("Position outside of string. offset: " + positions[i].offset + ", length: " + positions[i].length + ", string size: " + string.length()); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + } + } + } + } catch (BadPositionCategoryException cannotHappen) { + // can not happen: category is correctly set up + } + return doc; + } + + +} 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 073906ec715..a592efaa220 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 @@ -668,6 +668,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS addAction(menu, IContextMenuConstants.GROUP_GENERATE, "ContentAssistProposal"); //$NON-NLS-1$ addAction(menu, IContextMenuConstants.GROUP_GENERATE, "AddIncludeOnSelection"); //$NON-NLS-1$ + addAction(menu, IContextMenuConstants.GROUP_GENERATE, "Format"); //$NON-NLS-1$ addAction(menu, IContextMenuConstants.GROUP_GENERATE, "ShowInCView"); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorActionContributor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorActionContributor.java index 3365003d9b9..44724ecb6b3 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorActionContributor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorActionContributor.java @@ -81,6 +81,7 @@ public class CEditorActionContributor extends TextEditorActionContributor { protected CEditor fCEditor; protected RetargetTextEditorAction fContentAssist; + protected RetargetTextEditorAction fFormatter; protected RetargetTextEditorAction fAddInclude; protected RetargetTextEditorAction fOpenOnSelection; protected SelectionAction fShiftLeft; @@ -107,6 +108,9 @@ public class CEditorActionContributor extends TextEditorActionContributor { fContentAssist = new RetargetTextEditorAction(bundle, "ContentAssistProposal."); //$NON-NLS-1$ fContentAssist.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); + fFormatter = new RetargetTextEditorAction(bundle, "Format."); //$NON-NLS-1$ + fFormatter.setActionDefinitionId(ICEditorActionDefinitionIds.FORMAT); + fAddInclude = new RetargetTextEditorAction(bundle, "AddIncludeOnSelection."); //$NON-NLS-1$ fAddInclude.setActionDefinitionId(ICEditorActionDefinitionIds.ADD_INCLUDE); @@ -152,6 +156,7 @@ public class CEditorActionContributor extends TextEditorActionContributor { editMenu.add(new Separator(IContextMenuConstants.GROUP_GENERATE)); editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, fContentAssist); editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, fAddInclude); + editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, fFormatter); editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, fOpenOnSelection); } } @@ -198,6 +203,7 @@ public class CEditorActionContributor extends TextEditorActionContributor { fContentAssist.setAction(getAction(textEditor, "ContentAssistProposal")); //$NON-NLS-1$ fAddInclude.setAction(getAction(textEditor, "AddIncludeOnSelection")); //$NON-NLS-1$ fOpenOnSelection.setAction(getAction(textEditor, "OpenOnSelection")); //$NON-NLS-1$ + fFormatter.setAction(getAction(textEditor, "Format")); //$NON-NLS-1$ } /* diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java index 47571145cb9..ff3b7d6911c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java @@ -1,89 +1,162 @@ -/******************************************************************************* - * Copyright (c) 2000, 2004 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * QNX Software Systems - Initial API and implementation - *******************************************************************************/ +/* + * Created on Aug 16, 2004 + * + * Copyright 2004, QNX Software Systems Ltd. All Rights Reserved. + * + * This source code may contain confidential information of QNX Software + * Systems Ltd. (QSSL) and its licensors. Any use, reproduction, + * modification, disclosure, distribution or transfer of this software, + * or any software which includes or is based upon any of this code, is + * prohibited unless expressly authorized by QSSL by written agreement. For + * more information (including whether this source code file has been + * published) please email licensing@qnx.com. + */ package org.eclipse.cdt.internal.ui.text; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.filetype.ICFileType; +import org.eclipse.cdt.core.filetype.ICFileTypeConstants; +import org.eclipse.cdt.core.formatter.CodeFormatter; +import org.eclipse.cdt.core.formatter.CodeFormatterConstants; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.text.Assert; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.formatter.IFormattingStrategy; -import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.TextUtilities; +import org.eclipse.jface.text.TypedPosition; +import org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy; +import org.eclipse.jface.text.formatter.FormattingContextProperties; +import org.eclipse.jface.text.formatter.IFormattingContext; +import org.eclipse.text.edits.MalformedTreeException; +import org.eclipse.text.edits.TextEdit; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +/** + * @author AChapiro + */ +public class CFormattingStrategy extends ContextBasedFormattingStrategy { + -import org.eclipse.cdt.internal.formatter.CCodeFormatter; + /** Documents to be formatted by this strategy */ + private final LinkedList fDocuments= new LinkedList(); + /** Partitions to be formatted by this strategy */ + private final LinkedList fPartitions= new LinkedList(); - -public class CFormattingStrategy implements IFormattingStrategy { - - - private String fInitialIndentation; - private ISourceViewer fViewer; - - - public CFormattingStrategy(ISourceViewer viewer) { - fViewer = viewer; - } /** - * @see IFormattingStrategy#format(String, boolean, String, int[]) + * Creates a new java formatting strategy. + */ + public CFormattingStrategy() { + super(); + } + + /* + * @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#format() */ - public String format(String content, boolean isLineStart, String indentation, int[] positions) { - //ConfigurableOption[] options= CUIPlugin.getDefault().getCodeFormatterOptions(); - CCodeFormatter formatter= new CCodeFormatter(/* null options */); + public void format() { + super.format(); - //IDocument doc= fViewer.getDocument(); - //String lineDelimiter= getLineDelimiterFor(doc); - //formatter.options.setLineSeparator(lineDelimiter); + final IDocument document= (IDocument)fDocuments.removeFirst(); + final TypedPosition partition= (TypedPosition)fPartitions.removeFirst(); + + if (document != null && partition != null) { + Map options = getPreferences(); + try { + + final TextEdit edit= CodeFormatterUtil.format(CodeFormatter.K_COMPILATION_UNIT, + document, + partition.getOffset(), + partition.getLength(), + 0, + TextUtilities.getDefaultLineDelimiter(document), + getPreferences()); + + if (edit != null) + edit.apply(document); + + } catch (MalformedTreeException exception) { + CUIPlugin.getDefault().log(exception); + } catch (BadLocationException exception) { + // Can only happen on concurrent document modification - log and bail out + CUIPlugin.getDefault().log(exception); + } + } + } - - //formatter.setPositionsToMap(positions); - return formatter.formatSourceString(content); - } - /** - * @see IFormattingStrategy#formatterStarts(String) + /* + * @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#formatterStarts(org.eclipse.jface.text.formatter.IFormattingContext) */ - public void formatterStarts(String initialIndentation) { - fInitialIndentation= initialIndentation; + public void formatterStarts(final IFormattingContext context) { + prepareFormattingContext(context); + super.formatterStarts(context); + + fPartitions.addLast(context.getProperty(FormattingContextProperties.CONTEXT_PARTITION)); + fDocuments.addLast(context.getProperty(FormattingContextProperties.CONTEXT_MEDIUM)); } - /** - * @see IFormattingStrategy#formatterStops() + + /* + * @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#formatterStops() */ public void formatterStops() { + super.formatterStops(); + + fPartitions.clear(); + fDocuments.clear(); + } + + private IFile getActiveFile() { + IFile file = null; + IEditorPart editor = + CUIPlugin.getDefault().getWorkbench(). + getActiveWorkbenchWindow(). + getActivePage().getActiveEditor(); + IEditorInput input = editor.getEditorInput(); + if(input instanceof IFileEditorInput) { + file = ((IFileEditorInput)input).getFile(); + } + return file; } - /** - * Embodies the policy which line delimiter to use when inserting into - * a document - */ - private static String getLineDelimiterFor(IDocument doc) { - String lineDelim= null; - try { - lineDelim= doc.getLineDelimiter(0); - } catch (BadLocationException e) { - } - if (lineDelim == null) { - String systemDelimiter= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ - String[] lineDelims= doc.getLegalLineDelimiters(); - for (int i= 0; i < lineDelims.length; i++) { - if (lineDelims[i].equals(systemDelimiter)) { - lineDelim= systemDelimiter; - break; - } + private void prepareFormattingContext(final IFormattingContext context) { + Map preferences; + ParserLanguage language = ParserLanguage.CPP; + IFile activeFile = getActiveFile(); + if(null != activeFile) { + IProject currentProject = activeFile.getProject(); + Assert.isNotNull(currentProject); + // pick the language + if (CoreModel.hasCCNature(currentProject)) { + language = ParserLanguage.CPP; + } else { + // for C project try to guess. + ICFileType type = CCorePlugin.getDefault().getFileType(currentProject, + activeFile.getFullPath().lastSegment()); + String lid = type.getLanguage().getId(); + if(lid != null && lid.equals(ICFileTypeConstants.LANG_C)) + language = ParserLanguage.C; } - if (lineDelim == null) { - lineDelim= lineDelims.length > 0 ? lineDelims[0] : systemDelimiter; - } - } - return lineDelim; + preferences= new HashMap(CoreModel.getDefault().create( + activeFile.getProject()).getOptions(true)); + } else + preferences= new HashMap(CCorePlugin.getOptions()); + + preferences.put(CodeFormatterConstants.FORMATTER_LANGUAGE, language); + preferences.put(CodeFormatterConstants.FORMATTER_CURRENT_FILE, activeFile); + + context.storeToMap(CUIPlugin.getDefault().getPreferenceStore(), preferences, false); + context.setProperty(FormattingContextProperties.CONTEXT_PREFERENCES, preferences); + + return; } - - + } - - diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java index 8a440fab129..f12d91b0276 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java @@ -24,16 +24,14 @@ import org.eclipse.jface.text.ITextViewerExtension2; import org.eclipse.jface.text.contentassist.ContentAssistant; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContentAssistant; -import org.eclipse.jface.text.formatter.ContentFormatter; import org.eclipse.jface.text.formatter.IContentFormatter; -import org.eclipse.jface.text.formatter.IFormattingStrategy; +import org.eclipse.jface.text.formatter.MultiPassContentFormatter; import org.eclipse.jface.text.information.IInformationPresenter; import org.eclipse.jface.text.presentation.IPresentationReconciler; import org.eclipse.jface.text.presentation.PresentationReconciler; import org.eclipse.jface.text.reconciler.IReconciler; import org.eclipse.jface.text.reconciler.Reconciler; import org.eclipse.jface.text.rules.DefaultDamagerRepairer; -import org.eclipse.jface.text.rules.DefaultPartitioner; import org.eclipse.jface.text.rules.RuleBasedScanner; import org.eclipse.jface.text.source.IAnnotationHover; import org.eclipse.jface.text.source.ISourceViewer; @@ -51,10 +49,6 @@ public class CSourceViewerConfiguration extends SourceViewerConfiguration { /** Key used to look up display tab width */ public final static String PREFERENCE_TAB_WIDTH= "org.eclipse.cdt.editor.tab.width"; //$NON-NLS-1$ - /** Key used to look up code formatter tab size */ - private final static String CODE_FORMATTER_TAB_SIZE= "org.eclipse.cdt.formatter.tabulation.size"; //$NON-NLS-1$ - /** Key used to look up code formatter tab character */ - private final static String CODE_FORMATTER_TAB_CHAR= "org.eclipse.cdt.formatter.tabulation.char"; //$NON-NLS-1$ private CTextTools fTextTools; private CEditor fEditor; @@ -364,18 +358,15 @@ public class CSourceViewerConfiguration extends SourceViewerConfiguration { * @see SourceViewerConfiguration#getContentFormatter(ISourceViewer) */ public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) { - String[] types= new String[] { - DefaultPartitioner.CONTENT_TYPES_CATEGORY - }; - ContentFormatter formatter= new ContentFormatter(); - IFormattingStrategy strategy= new CFormattingStrategy(sourceViewer); - - formatter.setFormattingStrategy(strategy, IDocument.DEFAULT_CONTENT_TYPE); - formatter.enablePartitionAwareFormatting(false); - formatter.setPartitionManagingPositionCategories(types); + final MultiPassContentFormatter formatter = + new MultiPassContentFormatter(getConfiguredDocumentPartitioning(sourceViewer), + IDocument.DEFAULT_CONTENT_TYPE); + formatter.setMasterStrategy(new CFormattingStrategy()); return formatter; + + } protected IPreferenceStore getPreferenceStore() {