diff options
author | cvs2svn | 2004-12-03 21:13:53 +0000 |
---|---|---|
committer | cvs2svn | 2004-12-03 21:13:53 +0000 |
commit | f918490dbfc47752b5acfec4482bf8c274a59caf (patch) | |
tree | 57a9965b216e09e373489fdd38cd13d6344916d6 | |
parent | 3b2f0a3873bef074448be854357acf552d180e3e (diff) | |
download | org.eclipse.cdt-f918490dbfc47752b5acfec4482bf8c274a59caf.tar.gz org.eclipse.cdt-f918490dbfc47752b5acfec4482bf8c274a59caf.tar.xz org.eclipse.cdt-f918490dbfc47752b5acfec4482bf8c274a59caf.zip |
This commit was manufactured by cvs2svn to create branch 'cdt_21'.
Cherrypick from master 2004-12-03 21:13:52 UTC Alain Magloire <alain@qnx.com> '2004-12-03 Alain Magloire':
core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/AddBlockCommentAction.java
core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/BlockCommentAction.java
core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/RemoveBlockCommentAction.java
core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICPartitions.java
4 files changed, 637 insertions, 0 deletions
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/AddBlockCommentAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/AddBlockCommentAction.java new file mode 100644 index 00000000000..dde4a3c61c9 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/AddBlockCommentAction.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.ui.actions; + +import java.util.LinkedList; +import java.util.List; +import java.util.ResourceBundle; + +import org.eclipse.cdt.internal.ui.text.ICPartitions; +import org.eclipse.jface.text.Assert; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPartitioningException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * Action that encloses the editor's current selection with Java block comment terminators + * (<code>/*</code> and <code>*/</code>). + * + * @since 3.0 + */ +public class AddBlockCommentAction extends BlockCommentAction { + /** + * Creates a new instance. + * + * @param bundle the resource bundle + * @param prefix a prefix to be prepended to the various resource keys + * (described in <code>ResourceAction</code> constructor), or + * <code>null</code> if none + * @param editor the text editor + */ + public AddBlockCommentAction(ResourceBundle bundle, String prefix, ITextEditor editor) { + super(bundle, prefix, editor); + } + + /* + * @see org.eclipse.jdt.internal.ui.actions.BlockCommentAction#runInternal(org.eclipse.jface.text.ITextSelection, org.eclipse.jface.text.IDocumentExtension3, org.eclipse.jdt.internal.ui.actions.BlockCommentAction.Edit.EditFactory) + */ + protected void runInternal(ITextSelection selection, IDocumentExtension3 docExtension, Edit.EditFactory factory) throws BadLocationException, BadPartitioningException { + int selectionOffset= selection.getOffset(); + int selectionEndOffset= selectionOffset + selection.getLength(); + List edits= new LinkedList(); + ITypedRegion partition= docExtension.getPartition(IDocumentExtension3.DEFAULT_PARTITIONING, selectionOffset, false); + + handleFirstPartition(partition, edits, factory, selectionOffset); + + while (partition.getOffset() + partition.getLength() < selectionEndOffset) { + partition= handleInteriorPartition(partition, edits, factory, docExtension); + } + + handleLastPartition(partition, edits, factory, selectionEndOffset); + + executeEdits(edits); + } + + /** + * Handle the first partition of the selected text. + * + * @param partition + * @param edits + * @param factory + * @param offset + */ + private void handleFirstPartition(ITypedRegion partition, List edits, Edit.EditFactory factory, int offset) throws BadLocationException { + + int partOffset= partition.getOffset(); + String partType= partition.getType(); + + Assert.isTrue(partOffset <= offset, "illegal partition"); //$NON-NLS-1$ + + // first partition: mark start of comment + if (partType == IDocument.DEFAULT_CONTENT_TYPE) { + // Java code: right where selection starts + edits.add(factory.createEdit(offset, 0, getCommentStart())); + } else if (isSpecialPartition(partType)) { + // special types: include the entire partition + edits.add(factory.createEdit(partOffset, 0, getCommentStart())); + } // javadoc: no mark, will only start after comment + + } + + /** + * Handles the end of the given partition and the start of the next partition, which is returned. + * + * @param partition + * @param edits + * @param factory + * @param docExtension + * @throws BadLocationException + * @throws BadPartitioningException + * @return the region + */ + private ITypedRegion handleInteriorPartition(ITypedRegion partition, List edits, Edit.EditFactory factory, IDocumentExtension3 docExtension) throws BadPartitioningException, BadLocationException { + + // end of previous partition + String partType= partition.getType(); + int partEndOffset= partition.getOffset() + partition.getLength(); + int tokenLength= getCommentStart().length(); + + /*boolean wasJavadoc= false; // true if the previous partition is javadoc + + if (partType == IJavaPartitions.JAVA_DOC) { + + wasJavadoc= true; + + } else*/ + if (partType == ICPartitions.C_MULTILINE_COMMENT) { + + // already in a comment - remove ending mark + edits.add(factory.createEdit(partEndOffset - tokenLength, tokenLength, "")); //$NON-NLS-1$ + + } + + // advance to next partition + partition= docExtension.getPartition(IDocumentExtension3.DEFAULT_PARTITIONING, partEndOffset, false); + partType= partition.getType(); + + // start of next partition +// if (wasJavadoc) { +// +// // if previous was javadoc, and the current one is not, then add block comment start +// if (partType == IDocument.DEFAULT_CONTENT_TYPE +// || isSpecialPartition(partType)) { +// edits.add(factory.createEdit(partition.getOffset(), 0, getCommentStart())); +// } +// +// } else { // !wasJavadoc + + /*if (partType == IJavaPartitions.JAVA_DOC) { + // if next is javadoc, end block comment before + edits.add(factory.createEdit(partition.getOffset(), 0, getCommentEnd())); + } else*/ if (partType == ICPartitions.C_MULTILINE_COMMENT) { + // already in a comment - remove startToken + edits.add(factory.createEdit(partition.getOffset(), getCommentStart().length(), "")); //$NON-NLS-1$ + } +// } + + return partition; + } + + /** + * Handles the end of the last partition. + * + * @param partition + * @param edits + * @param factory + * @param endOffset + */ + private void handleLastPartition(ITypedRegion partition, List edits, Edit.EditFactory factory, int endOffset) throws BadLocationException { + + String partType= partition.getType(); + + if (partType == IDocument.DEFAULT_CONTENT_TYPE) { + // normal java: end comment where selection ends + edits.add(factory.createEdit(endOffset, 0, getCommentEnd())); + } else if (isSpecialPartition(partType)) { + // special types: consume entire partition + edits.add(factory.createEdit(partition.getOffset() + partition.getLength(), 0, getCommentEnd())); + } + + } + + /** + * Returns whether <code>partType</code> is special, i.e. a Java <code>String</code>, + * <code>Character</code>, or <code>Line End Comment</code> partition. + * + * @param partType the partition type to check + * @return <code>true</code> if <code>partType</code> is special, <code>false</code> otherwise + */ + private boolean isSpecialPartition(String partType) { + return /*partType == IJavaPartitions.JAVA_CHARACTER + || */partType == ICPartitions.C_STRING + || partType == ICPartitions.C_SINGLE_LINE_COMMENT; + } + + /* + * @see org.eclipse.jdt.internal.ui.actions.BlockCommentAction#validSelection(org.eclipse.jface.text.ITextSelection) + */ + protected boolean isValidSelection(ITextSelection selection) { + return selection != null && !selection.isEmpty() && selection.getLength() > 0; + } + + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/BlockCommentAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/BlockCommentAction.java new file mode 100644 index 00000000000..b115ad082c7 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/BlockCommentAction.java @@ -0,0 +1,327 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.ui.actions; + +import java.util.Iterator; +import java.util.List; +import java.util.ResourceBundle; + +import org.eclipse.jface.text.Assert; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPartitioningException; +import org.eclipse.jface.text.BadPositionCategoryException; +import org.eclipse.jface.text.DefaultPositionUpdater; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.IPositionUpdater; +import org.eclipse.jface.text.IRewriteTarget; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.ITextEditorExtension2; +import org.eclipse.ui.texteditor.TextEditorAction; + +/** + * Common block comment code. + * + * @since 3.0 + */ +public abstract class BlockCommentAction extends TextEditorAction { + /** + * Creates a new instance. + * @param bundle + * @param prefix + * @param editor + */ + public BlockCommentAction(ResourceBundle bundle, String prefix, ITextEditor editor) { + super(bundle, prefix, editor); + } + + /** + * An edit is a kind of <code>DocumentEvent</code>, in this case an edit instruction, that is + * affiliated with a <code>Position</code> on a document. The offset of the document event is + * not stored statically, but taken from the affiliated <code>Position</code>, which gets + * updated when other edits occur. + */ + static class Edit extends DocumentEvent { + + /** + * Factory for edits which manages the creation, installation and destruction of + * position categories, position updaters etc. on a certain document. Once a factory has + * been obtained, <code>Edit</code> objects can be obtained from it which will be linked to + * the document by positions of one position category. + * <p>Clients are required to call <code>release</code> once the <code>Edit</code>s are not + * used any more, so the positions can be discarded.</p> + */ + public static class EditFactory { + + /** The position category basename for this edits. */ + private static final String CATEGORY= "__positionalEditPositionCategory"; //$NON-NLS-1$ + + /** The count of factories. */ + private static int fgCount= 0; + + /** This factory's category. */ + private final String fCategory; + private IDocument fDocument; + private IPositionUpdater fUpdater; + + /** + * Creates a new <code>EditFactory</code> with an unambiguous position category name. + * @param document the document that is being edited. + */ + public EditFactory(IDocument document) { + fCategory= CATEGORY + fgCount++; + fDocument= document; + } + + /** + * Creates a new edition on the document of this factory. + * + * @param offset the offset of the edition at the point when is created. + * @param length the length of the edition (not updated via the position update mechanism) + * @param text the text to be replaced on the document + * @return an <code>Edit</code> reflecting the edition on the document + */ + public Edit createEdit(int offset, int length, String text) throws BadLocationException { + + if (!fDocument.containsPositionCategory(fCategory)) { + fDocument.addPositionCategory(fCategory); + fUpdater= new DefaultPositionUpdater(fCategory); + fDocument.addPositionUpdater(fUpdater); + } + + Position position= new Position(offset); + try { + fDocument.addPosition(fCategory, position); + } catch (BadPositionCategoryException e) { + Assert.isTrue(false); + } + return new Edit(fDocument, length, text, position); + } + + /** + * Releases the position category on the document and uninstalls the position updater. + * <code>Edit</code>s managed by this factory are not updated after this call. + */ + public void release() { + if (fDocument != null && fDocument.containsPositionCategory(fCategory)) { + fDocument.removePositionUpdater(fUpdater); + try { + fDocument.removePositionCategory(fCategory); + } catch (BadPositionCategoryException e) { + Assert.isTrue(false); + } + fDocument= null; + fUpdater= null; + } + } + } + + /** The position in the document where this edit be executed. */ + private Position fPosition; + + /** + * Creates a new edition on <code>document</code>, taking its offset from <code>position</code>. + * + * @param document the document being edited + * @param length the length of the edition + * @param text the replacement text of the edition + * @param position the position keeping the edition's offset + */ + protected Edit(IDocument document, int length, String text, Position position) { + super(document, 0, length, text); + fPosition= position; + } + + /* + * @see org.eclipse.jface.text.DocumentEvent#getOffset() + */ + public int getOffset() { + return fPosition.getOffset(); + } + + /** + * Executes the edition on document. The offset is taken from the position. + * + * @throws BadLocationException if the execution of the document fails. + */ + public void perform() throws BadLocationException { + getDocument().replace(getOffset(), getLength(), getText()); + } + + } + + public void run() { + if (!isEnabled()) + return; + + ITextEditor editor= getTextEditor(); + if (editor == null || !ensureEditable(editor)) + return; + + ITextSelection selection= getCurrentSelection(); + if (!isValidSelection(selection)) + return; + + if (!validateEditorInputState()) + return; + + IDocumentProvider docProvider= editor.getDocumentProvider(); + IEditorInput input= editor.getEditorInput(); + if (docProvider == null || input == null) + return; + + IDocument document= docProvider.getDocument(input); + if (document == null) + return; + + IDocumentExtension3 docExtension; + if (document instanceof IDocumentExtension3) + docExtension= (IDocumentExtension3) document; + else + return; + + IRewriteTarget target= (IRewriteTarget)editor.getAdapter(IRewriteTarget.class); + if (target != null) { + target.beginCompoundChange(); + } + + Edit.EditFactory factory= new Edit.EditFactory(document); + + try { + runInternal(selection, docExtension, factory); + + } catch (BadLocationException e) { + // can happen on concurrent modification, deletion etc. of the document + // -> don't complain, just bail out + } catch (BadPartitioningException e) { + // should not happen + Assert.isTrue(false, "bad partitioning"); //$NON-NLS-1$ + } finally { + factory.release(); + + if (target != null) { + target.endCompoundChange(); + } + } + } + + /** + * Calls <code>perform</code> on all <code>Edit</code>s in <code>edits</code>. + * + * @param edits a list of <code>Edit</code>s + * @throws BadLocationException if an <code>Edit</code> threw such an exception. + */ + protected void executeEdits(List edits) throws BadLocationException { + for (Iterator it= edits.iterator(); it.hasNext();) { + Edit edit= (Edit) it.next(); + edit.perform(); + } + } + + /** + * Ensures that the editor is modifyable. If the editor is an instance of + * <code>ITextEditorExtension2</code>, its <code>validateEditorInputState</code> method + * is called, otherwise, the result of <code>isEditable</code> is returned. + * + * @param editor the editor to be checked + * @return <code>true</code> if the editor is editable, <code>false</code> otherwise + */ + protected boolean ensureEditable(ITextEditor editor) { + Assert.isNotNull(editor); + + if (editor instanceof ITextEditorExtension2) { + ITextEditorExtension2 ext= (ITextEditorExtension2) editor; + return ext.validateEditorInputState(); + } + + return editor.isEditable(); + } + + /* + * @see org.eclipse.ui.texteditor.IUpdate#update() + */ + public void update() { + super.update(); + + if (isEnabled()) { + if (!canModifyEditor() || !isValidSelection(getCurrentSelection())) + setEnabled(false); + } + } + + /** + * Returns the editor's selection, or <code>null</code> if no selection can be obtained or the + * editor is <code>null</code>. + * + * @return the selection of the action's editor, or <code>null</code> + */ + protected ITextSelection getCurrentSelection() { + ITextEditor editor= getTextEditor(); + if (editor != null) { + ISelectionProvider provider= editor.getSelectionProvider(); + if (provider != null) { + ISelection selection= provider.getSelection(); + if (selection instanceof ITextSelection) + return (ITextSelection) selection; + } + } + return null; + } + + /** + * Runs the real command once all the editor, document, and selection checks have succeeded. + * + * @param selection the current selection we are being called for + * @param docExtension the document extension where we get the partitioning from + * @param factory the edit factory we can use to create <code>Edit</code>s + * @throws BadLocationException if an edition fails + * @throws BadPartitioningException if a partitioning call fails + */ + protected abstract void runInternal(ITextSelection selection, IDocumentExtension3 docExtension, Edit.EditFactory factory) throws BadLocationException, BadPartitioningException; + + /** + * Checks whether <code>selection</code> is valid. + * + * @param selection the selection to check + * @return <code>true</code> if the selection is valid, <code>false</code> otherwise + */ + protected abstract boolean isValidSelection(ITextSelection selection); + + /** + * Returns the text to be inserted at the selection start. + * + * @return the text to be inserted at the selection start + */ + protected String getCommentStart() { + // for now: no space story + return "/*"; //$NON-NLS-1$ + } + + /** + * Returns the text to be inserted at the selection end. + * + * @return the text to be inserted at the selection end + */ + protected String getCommentEnd() { + // for now: no space story + return "*/"; //$NON-NLS-1$ + } + + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/RemoveBlockCommentAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/RemoveBlockCommentAction.java new file mode 100644 index 00000000000..5733327285e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/RemoveBlockCommentAction.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.ui.actions; + +import java.util.LinkedList; +import java.util.List; +import java.util.ResourceBundle; + +import org.eclipse.cdt.internal.ui.text.ICPartitions; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPartitioningException; +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * Action that removes the enclosing comment marks from a Java block comment. + * + * @since 3.0 + */ +public class RemoveBlockCommentAction extends BlockCommentAction { + + /** + * Creates a new instance. + * + * @param bundle the resource bundle + * @param prefix a prefix to be prepended to the various resource keys + * (described in <code>ResourceAction</code> constructor), or + * <code>null</code> if none + * @param editor the text editor + */ + public RemoveBlockCommentAction(ResourceBundle bundle, String prefix, ITextEditor editor) { + super(bundle, prefix, editor); + } + + /* + * @see org.eclipse.jdt.internal.ui.actions.AddBlockCommentAction#runInternal(org.eclipse.jface.text.ITextSelection, org.eclipse.jface.text.IDocumentExtension3, org.eclipse.jdt.internal.ui.actions.AddBlockCommentAction.Edit.EditFactory) + */ + protected void runInternal(ITextSelection selection, IDocumentExtension3 docExtension, Edit.EditFactory factory) throws BadPartitioningException, BadLocationException { + List edits= new LinkedList(); + int tokenLength= getCommentStart().length(); + + int offset= selection.getOffset(); + int endOffset= offset + selection.getLength(); + + ITypedRegion partition= docExtension.getPartition(IDocumentExtension3.DEFAULT_PARTITIONING, offset, false); + int partOffset= partition.getOffset(); + int partEndOffset= partOffset + partition.getLength(); + + while (partEndOffset < endOffset) { + + if (partition.getType() == ICPartitions.C_MULTILINE_COMMENT) { + edits.add(factory.createEdit(partOffset, tokenLength, "")); //$NON-NLS-1$ + edits.add(factory.createEdit(partEndOffset - tokenLength, tokenLength, "")); //$NON-NLS-1$ + } + + partition= docExtension.getPartition(IDocumentExtension3.DEFAULT_PARTITIONING, partEndOffset, false); + partOffset= partition.getOffset(); + partEndOffset= partOffset + partition.getLength(); + } + + if (partition.getType() == ICPartitions.C_MULTILINE_COMMENT) { + edits.add(factory.createEdit(partOffset, tokenLength, "")); //$NON-NLS-1$ + edits.add(factory.createEdit(partEndOffset - tokenLength, tokenLength, "")); //$NON-NLS-1$ + } + + executeEdits(edits); + } + + /* + * @see org.eclipse.jdt.internal.ui.actions.AddBlockCommentAction#validSelection(org.eclipse.jface.text.ITextSelection) + */ + protected boolean isValidSelection(ITextSelection selection) { + return selection != null && !selection.isEmpty(); + } + + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICPartitions.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICPartitions.java new file mode 100644 index 00000000000..3b0407fe762 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ICPartitions.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.cdt.internal.ui.text; + +/** + * + * The name of the C partitioning. + * @since 3.0 + */ +public interface ICPartitions { + + public final static String SKIP= "__skip"; //$NON-NLS-1$ + public final static String C_MULTILINE_COMMENT= "c_multi_line_comment"; //$NON-NLS-1$ + public final static String C_SINGLE_LINE_COMMENT= "c_single_line_comment"; //$NON-NLS-1$ + public final static String C_STRING= "c_string"; //$NON-NLS-1$ + +} |