1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 10:16:03 +02:00

Fix for 236160: C Block comment closes on next line when # is a first character on line

Patch by Andrew Gvozdev
This commit is contained in:
Anton Leherbauer 2008-07-07 09:13:00 +00:00
parent 236fe5b939
commit eb8598c083
5 changed files with 894 additions and 122 deletions

View file

@ -0,0 +1,377 @@
/*******************************************************************************
* Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Anton Leherbauer (Wind River Systems) - initial API and implementation
* Andrew Gvozdev
*******************************************************************************/
package org.eclipse.cdt.ui.tests.text;
import junit.framework.TestSuite;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.ui.tests.BaseUITestCase;
import org.eclipse.cdt.internal.core.model.ext.SourceRange;
import org.eclipse.cdt.internal.ui.editor.CEditor;
/**
* Tests for the AddBlockCommentAction.
*
* @since 5.0
*/
public class AddBlockCommentTest extends BaseUITestCase {
private ICProject fCProject;
public static TestSuite suite() {
return suite(AddBlockCommentTest.class, "_");
}
private CEditor fEditor;
private IDocument fDocument;
/*
* The class describes a position on a line counting in ordinary people way,
* starting from 1.
*/
static class LinePosition {
private int line;
private int position;
private IDocument fDoc;
LinePosition(int line, int positionOnLine, IDocument doc) {
this.line = line;
this.position = positionOnLine;
this.fDoc = doc;
}
int getOffset() throws BadLocationException {
return fDoc.getLineOffset(line-1) + position-1;
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
final String PROJECT= "BlockComment";
// Using any existing file just to open CEditor, the content is not used
final String filename= "/BlockComment/src/sample/Before.cpp";
fCProject= EditorTestHelper.createCProject(PROJECT, "resources/formatter");
fCProject.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.TAB);
fEditor= (CEditor) EditorTestHelper.openInEditor(ResourceTestHelper.findFile(filename), true);
fDocument= EditorTestHelper.getSourceViewer(fEditor).getDocument();
// Delete contents
fDocument.set("");
}
@Override
protected void tearDown() throws Exception {
EditorTestHelper.closeEditor(fEditor);
if (fCProject != null)
CProjectHelper.delete(fCProject);
super.tearDown();
}
/**
* Run an action to comment block defined by line positions
* and assert that the result matches the expected result.
* "Before" and "After" are taken from test comments.
*
* @param startLinePosition
* @param endLinePosition
* @throws Exception
*/
protected void assertFormatterResult(
LinePosition startLinePosition,
LinePosition endLinePosition) throws Exception {
StringBuffer[] contents= getContentsForTest(2);
String before = contents[0].toString();
String after = contents[1].toString();
fDocument.set(before);
SourceRange range = new SourceRange( startLinePosition.getOffset(),
endLinePosition.getOffset()-startLinePosition.getOffset() );
fEditor.setSelection(range, true);
IAction commentAction= fEditor.getAction("AddBlockComment");
assertNotNull("No AddBlockComment action", commentAction);
commentAction.setEnabled(true);
commentAction.run();
String expected= after;
assertEquals(expected, fDocument.get());
}
/**
* Run an action to comment block defined by line positions
* and assert that the result matches the expected result.
* "Before" and "After" are taken from test comments.
*
* @param startLinePosition
* @param endLinePosition
* @param before editor contents before the operation
* @param after expected editor contents after the operation
* @throws Exception
*/
protected void assertFormatterResult(
LinePosition startLinePosition,
LinePosition endLinePosition,
String before,
String after) throws Exception {
fDocument.set(before);
SourceRange range = new SourceRange( startLinePosition.getOffset(),
endLinePosition.getOffset()-startLinePosition.getOffset() );
fEditor.setSelection(range, true);
IAction commentAction= fEditor.getAction("AddBlockComment");
assertNotNull("No AddBlockComment action", commentAction);
commentAction.setEnabled(true);
commentAction.run();
String expected= after;
assertEquals(expected, fDocument.get());
}
//int i, j, k;
//int i, /*j,*/ k;
public void testCommentPlain() throws Exception {
LinePosition startSelection = new LinePosition(1,8,fDocument);
LinePosition endSelection = new LinePosition(1,10,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i,
// j,
// k;
//int /*i,
// j,*/
// k;
public void testCommentPartialLines1() throws Exception {
LinePosition startSelection = new LinePosition(1,5,fDocument);
LinePosition endSelection = new LinePosition(2,7,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i,
// j,
// k;
//int i,
///* j,
// k*/;
public void testCommentPartialLines2() throws Exception {
LinePosition startSelection = new LinePosition(2,1,fDocument);
LinePosition endSelection = new LinePosition(3,6,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i;
//int j;
//int k;
//int i;
///*int j;*/
//int k;
public void testCommentExactlyOneLine() throws Exception {
LinePosition startSelection = new LinePosition(2,1,fDocument);
LinePosition endSelection = new LinePosition(3,1,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i;
//int j;
//int k;
//int l;
//int i;
///*
//int j;
//int k;
//*/
//int l;
public void testCommentTwoOrMoreLines() throws Exception {
LinePosition startSelection = new LinePosition(2,1,fDocument);
LinePosition endSelection = new LinePosition(4,1,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//const int i;
///*const*/ int i;
public void testCommentFirstCharacterInFile() throws Exception {
LinePosition startSelection = new LinePosition(1,1,fDocument);
LinePosition endSelection = new LinePosition(1,6,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//#include <x>
//#include <y>
///*#include <x>*/
//#include <y>
public void testCommentPreprocessorFirstLine() throws Exception {
LinePosition startSelection = new LinePosition(1,1,fDocument);
LinePosition endSelection = new LinePosition(1,6,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i; // comment
//int j;
//int i; /*// comment*/
//int j;
public void testCommentCppComment() throws Exception {
LinePosition startSelection = new LinePosition(1,10,fDocument);
LinePosition endSelection = new LinePosition(1,12,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//#include <x>
//#include <y>
//#include <z>
//#include <x>
///*#include <y>*/
//#include <z>
public void testCommentSpecialPartition() throws Exception {
LinePosition startSelection = new LinePosition(2,1,fDocument);
LinePosition endSelection = new LinePosition(3,1,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//#include <x>
// #include \
// <y>
//#include <z>
//#include <x>
///*
// #include \
// <y>
//*/
//#include <z>
public void testCommentSpecialPartitionExtra() throws Exception {
LinePosition startSelection = new LinePosition(2,8,fDocument);
LinePosition endSelection = new LinePosition(2,10,fDocument);
assertFormatterResult(startSelection,endSelection);
}
///*comment*/
//int i;
///*comment*/
//int i;
public void testCommentCommentNoScrewUp() throws Exception {
LinePosition startSelection = new LinePosition(1,1,fDocument);
LinePosition endSelection = new LinePosition(2,1,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i;
///*comment*/
//int j;
///*int i;
//comment*/
//int j;
public void testCommentMergeUp() throws Exception {
LinePosition startSelection = new LinePosition(1,1,fDocument);
LinePosition endSelection = new LinePosition(2,5,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i;
///*comment*/
//int j;
//int i;
///*comment
//int j;*/
public void testCommentMergeDown() throws Exception {
LinePosition startSelection = new LinePosition(2,5,fDocument);
LinePosition endSelection = new LinePosition(3,7,fDocument);
assertFormatterResult(startSelection,endSelection);
}
///*comment1*/
///*comment2*/
//int i;
///*comment1
//comment2*/
//int i;
public void testCommentMergeComments() throws Exception {
LinePosition startSelection = new LinePosition(1,5,fDocument);
LinePosition endSelection = new LinePosition(2,5,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//
//
//
///*
//
//*/
public void testCommentEndOfFileNoLoopingPlease() throws Exception {
// Don't care much about formatting but no looping please
LinePosition startSelection = new LinePosition(2,1,fDocument);
LinePosition endSelection = new LinePosition(3,1,fDocument);
assertFormatterResult(startSelection,endSelection);
}
public void testCommentLastCharacterNoEOL() throws Exception {
String before = "int i;";
String after = "/*int i;*/";
LinePosition startSelection = new LinePosition(1,1,fDocument);
LinePosition endSelection = new LinePosition(1,7,fDocument);
assertFormatterResult(startSelection,endSelection,before,after);
}
public void testCommentLastCppCommentNoEOL() throws Exception {
String before = "//int i;";
String after = "/*//int i;*/";
LinePosition startSelection = new LinePosition(1,3,fDocument);
LinePosition endSelection = new LinePosition(1,7,fDocument);
assertFormatterResult(startSelection,endSelection,before,after);
}
public void testMixedEOLs() throws Exception {
String before =
"int i;\r\n"
+ "int j;\n"
+ "int k;";
String after =
"/*\r\n"
+ "int i;\r\n"
+ "int j;\n"
+ "*/\n"
+ "int k;";
LinePosition startSelection = new LinePosition(1,1,fDocument);
LinePosition endSelection = new LinePosition(3,1,fDocument);
assertFormatterResult(startSelection,endSelection,before,after);
}
}

View file

@ -0,0 +1,340 @@
/*******************************************************************************
* Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Anton Leherbauer (Wind River Systems) - initial API and implementation
* Andrew Gvozdev
*******************************************************************************/
package org.eclipse.cdt.ui.tests.text;
import junit.framework.TestSuite;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.text.IDocument;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.ui.tests.BaseUITestCase;
import org.eclipse.cdt.ui.tests.text.AddBlockCommentTest.LinePosition;
import org.eclipse.cdt.internal.core.model.ext.SourceRange;
import org.eclipse.cdt.internal.ui.editor.CEditor;
/**
* Tests for the RemoveBlockCommentAction.
*
* @since 5.0
*/
public class RemoveBlockCommentTest extends BaseUITestCase {
private ICProject fCProject;
public static TestSuite suite() {
return suite(RemoveBlockCommentTest.class, "_");
}
private CEditor fEditor;
private IDocument fDocument;
@Override
protected void setUp() throws Exception {
super.setUp();
final String PROJECT= "BlockComment";
// Using any existing file just to open CEditor, the content is not used
final String filename= "/BlockComment/src/sample/Before.cpp";
fCProject= EditorTestHelper.createCProject(PROJECT, "resources/formatter");
fCProject.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.TAB);
fEditor= (CEditor) EditorTestHelper.openInEditor(ResourceTestHelper.findFile(filename), true);
fDocument= EditorTestHelper.getSourceViewer(fEditor).getDocument();
// Delete contents
fDocument.set("");
}
@Override
protected void tearDown() throws Exception {
EditorTestHelper.closeEditor(fEditor);
if (fCProject != null)
CProjectHelper.delete(fCProject);
super.tearDown();
}
/**
* Run an action to comment block defined by line positions
* and assert that the result matches the expected result.
* "Before" and "After" are taken from test comments.
*
* @param startLinePosition
* @param endLinePosition
* @throws Exception
*/
protected void assertFormatterResult(
LinePosition startLinePosition,
LinePosition endLinePosition) throws Exception {
StringBuffer[] contents= getContentsForTest(2);
String before = contents[0].toString();
String after = contents[1].toString();
fDocument.set(before);
SourceRange range = new SourceRange( startLinePosition.getOffset(),
endLinePosition.getOffset()-startLinePosition.getOffset() );
fEditor.setSelection(range, true);
IAction commentAction= fEditor.getAction("RemoveBlockComment");
assertNotNull("No RemoveBlockComment action", commentAction);
commentAction.setEnabled(true);
commentAction.run();
String expected= after;
assertEquals(expected, fDocument.get());
}
/**
* Run an action to comment block defined by line positions
* and assert that the result matches the expected result.
* "Before" and "After" are taken from test comments.
*
* @param startLinePosition
* @param endLinePosition
* @param before editor contents before the operation
* @param after expected editor contents after the operation
* @throws Exception
*/
protected void assertFormatterResult(
LinePosition startLinePosition,
LinePosition endLinePosition,
String before,
String after) throws Exception {
fDocument.set(before);
SourceRange range = new SourceRange( startLinePosition.getOffset(),
endLinePosition.getOffset()-startLinePosition.getOffset() );
fEditor.setSelection(range, true);
IAction commentAction= fEditor.getAction("RemoveBlockComment");
assertNotNull("No RemoveBlockComment action", commentAction);
commentAction.setEnabled(true);
commentAction.run();
String expected= after;
assertEquals(expected, fDocument.get());
}
//int i, /*j,*/ k;
//int i, j, k;
public void testUncommentPlain() throws Exception {
LinePosition startSelection = new LinePosition(1,10,fDocument);
LinePosition endSelection = new LinePosition(1,11,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int /*j,*/ k;
//int j, k;
public void testRightBorderIn() throws Exception {
LinePosition startSelection = new LinePosition(1,10,fDocument);
LinePosition endSelection = new LinePosition(1,11,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int /*j,*/ k;
//int /*j,*/ k;
public void testRightBorderOut() throws Exception {
LinePosition startSelection = new LinePosition(1,11,fDocument);
LinePosition endSelection = new LinePosition(1,12,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//123456789-123
//int /*j,*/ k;
//int j, k;
public void testLeftBorderIn() throws Exception {
LinePosition startSelection = new LinePosition(1,5,fDocument);
LinePosition endSelection = new LinePosition(1,6,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int /*j,*/ k;
//int /*j,*/ k;
public void testLeftBorderOut() throws Exception {
LinePosition startSelection = new LinePosition(1,4,fDocument);
LinePosition endSelection = new LinePosition(1,5,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int /*i,
// j,*/
// k;
//int i,
// j,
// k;
public void testUncommentPartialLines1() throws Exception {
LinePosition startSelection = new LinePosition(1,7,fDocument);
LinePosition endSelection = new LinePosition(2,2,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i,
///* j,
// k*/;
//int i,
// j,
// k;
public void testUncommentPartialLines2() throws Exception {
LinePosition startSelection = new LinePosition(2,1,fDocument);
LinePosition endSelection = new LinePosition(3,8,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i;
///*int j;*/
//int k;
//int i;
//int j;
//int k;
public void testUncommentExactlyOneLineNoLoopingPlease() throws Exception {
LinePosition startSelection = new LinePosition(2,1,fDocument);
LinePosition endSelection = new LinePosition(3,1,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i;
///*
//int j;
//int k;
//*/
//int l;
//int i;
//int j;
//int k;
//int l;
public void testUncommentTwoOrMoreLines() throws Exception {
LinePosition startSelection = new LinePosition(2,1,fDocument);
LinePosition endSelection = new LinePosition(4,1,fDocument);
assertFormatterResult(startSelection,endSelection);
}
///*const*/ int i;
//const int i;
public void testUncommentFirstCharacterInFile() throws Exception {
LinePosition startSelection = new LinePosition(1,1,fDocument);
LinePosition endSelection = new LinePosition(1,6,fDocument);
assertFormatterResult(startSelection,endSelection);
}
///*#include <x>*/
//#include <y>
//#include <x>
//#include <y>
public void testUncommentPreprocessorFirstLine() throws Exception {
LinePosition startSelection = new LinePosition(1,1,fDocument);
LinePosition endSelection = new LinePosition(1,6,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//int i; /*// comment*/
//int j;
//int i; // comment
//int j;
public void testUncommentCppComment() throws Exception {
LinePosition startSelection = new LinePosition(1,10,fDocument);
LinePosition endSelection = new LinePosition(1,12,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//#include <x>
///*#include <y>*/
//#include <z>
//#include <x>
//#include <y>
//#include <z>
public void testUncommentSpecialPartition() throws Exception {
LinePosition startSelection = new LinePosition(2,1,fDocument);
LinePosition endSelection = new LinePosition(3,1,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//#include <x>
///*
// #include \
// <y>
//*/
//#include <z>
//#include <x>
// #include \
// <y>
//#include <z>
public void testUncommentSpecialPartitionExtra() throws Exception {
LinePosition startSelection = new LinePosition(3,8,fDocument);
LinePosition endSelection = new LinePosition(3,10,fDocument);
assertFormatterResult(startSelection,endSelection);
}
///*int i;*/
///*int j;*/
//int k;
//int i;
//int j;
//int k;
public void testUncommentConnectedComments() throws Exception {
LinePosition startSelection = new LinePosition(1,5,fDocument);
LinePosition endSelection = new LinePosition(2,5,fDocument);
assertFormatterResult(startSelection,endSelection);
}
//
///*
//
//*/
//
//
public void testUncommentEndOfFile() throws Exception {
LinePosition startSelection = new LinePosition(3,1,fDocument);
LinePosition endSelection = new LinePosition(5,2,fDocument);
assertFormatterResult(startSelection,endSelection);
}
public void testMixedEOLs() throws Exception {
String before =
"/*\r\n"
+ "int i;\r\n"
+ "int j;\n"
+ "*/\n"
+ "int k;";
String after =
"int i;\r\n"
+ "int j;\n"
+ "int k;";
LinePosition startSelection = new LinePosition(2,1,fDocument);
LinePosition endSelection = new LinePosition(3,1,fDocument);
assertFormatterResult(startSelection,endSelection,before,after);
}
}

View file

@ -70,5 +70,9 @@ public class TextTestSuite extends TestSuite {
// compare tests
addTest(CStructureCreatorTest.suite());
// block comment tests
addTest(AddBlockCommentTest.suite());
addTest(RemoveBlockCommentTest.suite());
}
}

View file

@ -8,27 +8,28 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
* Andrew Gvozdev - http://bugs.eclipse.org/236160
*******************************************************************************/
package org.eclipse.cdt.internal.ui.actions;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
import org.eclipse.core.runtime.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.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.cdt.ui.text.ICPartitions;
/**
* Action that encloses the editor's current selection with Java block comment terminators
* Action that encloses the editor's current selection with C block comment terminators
* (<code>&#47;&#42;</code> and <code>&#42;&#47;</code>).
*
* @since 3.0
@ -47,127 +48,149 @@ public class AddBlockCommentAction extends BlockCommentAction {
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)
*/
@Override
protected void runInternal(ITextSelection selection, IDocumentExtension3 docExtension, Edit.EditFactory factory) throws BadLocationException, BadPartitioningException {
int selectionOffset= selection.getOffset();
int selectionEndOffset= selectionOffset + selection.getLength();
List<Edit> edits= new LinkedList<Edit>();
ITypedRegion partition= docExtension.getPartition(ICPartitions.C_PARTITIONING, selectionOffset, false);
handleFirstPartition(partition, edits, factory, selectionOffset);
while (partition.getOffset() + partition.getLength() < selectionEndOffset) {
partition= handleInteriorPartition(partition, edits, factory, docExtension);
}
protected void runInternal(ITextSelection selection,
IDocumentExtension3 docExtension, Edit.EditFactory factory)
throws BadLocationException, BadPartitioningException {
handleLastPartition(partition, edits, factory, selectionEndOffset);
if ( !(docExtension instanceof IDocument) ) return;
List<Edit> edits= new LinkedList<Edit>();
ITypedRegion firstPartition = docExtension.getPartition(ICPartitions.C_PARTITIONING,
selection.getOffset(), false);
ITypedRegion lastPartition = docExtension.getPartition(ICPartitions.C_PARTITIONING,
selection.getOffset() + selection.getLength() - 1, false);
int commentAreaStart = selection.getOffset();
int commentAreaEnd = selection.getOffset()+selection.getLength();
// Include special partitions fully in the comment area
if (isSpecialPartition(firstPartition.getType())) {
commentAreaStart = firstPartition.getOffset();
}
if (isSpecialPartition(lastPartition.getType())) {
commentAreaEnd = lastPartition.getOffset() + lastPartition.getLength();
}
Region estimatedCommentArea = new Region(commentAreaStart,commentAreaEnd-commentAreaStart);
Region commentArea = handleEnclosingPartitions(estimatedCommentArea, lastPartition,
(IDocument)docExtension, factory, edits);
handleInteriorPartition(commentArea, firstPartition, docExtension, factory, edits);
executeEdits(edits);
}
/**
* Handle the first partition of the selected text.
* Add enclosing comment tags for the whole area to be commented
*
* @param partition
* @param edits
* @param factory
* @param offset
* @param commentArea initial comment area which can be adjusted
* @param lastPartition last partition
* @param doc document
* @param factory Edit factory
* @param edits List of edits to update the document
* @return new possibly adjusted comment area
* @throws BadLocationException
*/
private void handleFirstPartition(ITypedRegion partition, List<Edit> edits, Edit.EditFactory factory, int offset) throws BadLocationException {
private Region handleEnclosingPartitions(Region commentArea,
ITypedRegion lastPartition, IDocument doc, Edit.EditFactory factory,
List<Edit> edits) throws BadLocationException {
int partOffset= partition.getOffset();
String partType= partition.getType();
int commentAreaStart = commentArea.getOffset();
int commentAreaEnd = commentArea.getOffset() + commentArea.getLength();
Assert.isTrue(partOffset <= offset, "illegal partition"); //$NON-NLS-1$
String commentStartTag = getCommentStart(); // "/*"
String commentEndTag = getCommentEnd(); // "*/"
// 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
String startLineEOL = doc.getLineDelimiter(doc.getLineOfOffset(commentAreaStart));
if (startLineEOL==null) startLineEOL=""; //$NON-NLS-1$
String endLineEOL = doc.getLineDelimiter(doc.getLineOfOffset(commentAreaEnd-1));
if (endLineEOL==null) endLineEOL=""; //$NON-NLS-1$
boolean isLeftEol = commentAreaStart<startLineEOL.length()
|| doc.get(commentAreaStart-startLineEOL.length(),startLineEOL.length()).equals(startLineEOL);
boolean isRightEol = doc.get(commentAreaEnd-endLineEOL.length(),endLineEOL.length()).equals(endLineEOL);
if (isLeftEol && isRightEol) {
// Block of full lines found
int areaStartLine = doc.getLineOfOffset(commentAreaStart+startLineEOL.length());
int areaEndLine = doc.getLineOfOffset(commentAreaEnd-endLineEOL.length());
if (areaStartLine!=areaEndLine) {
// If multiple full lines arrange inserting comment tags on their own lines
commentStartTag = getCommentStart()+startLineEOL;
commentEndTag = getCommentEnd()+endLineEOL;
} else {
// If one full line insert end comment tag on the same line (before the EOL)
commentAreaEnd = commentAreaEnd-endLineEOL.length();
}
} else {
if (lastPartition.getType() == ICPartitions.C_SINGLE_LINE_COMMENT
|| lastPartition.getType() == ICPartitions.C_SINGLE_LINE_DOC_COMMENT) {
// C++ comments "//" partition ends with EOL, insert end comment tag before it
// on the same line, so we get something like /*// text*/
commentAreaEnd = commentAreaEnd-endLineEOL.length();
}
}
edits.add(factory.createEdit(commentAreaStart, 0, commentStartTag));
edits.add(factory.createEdit(commentAreaEnd, 0, commentEndTag));
return new Region(commentAreaStart,commentAreaEnd-commentAreaStart);
}
/**
* Handles the end of the given partition and the start of the next partition, which is returned.
* Make all inside partitions join in one comment, in particular remove
* all enclosing comment tokens of the inside partitions.
*
* @param partition
* @param edits
* @param factory
* @param docExtension
* @param commentArea comment area region
* @param partition first partition
* @param docExtension document
* @param factory EditFactory
* @param List of edits to update the document
* @throws BadLocationException
* @throws BadPartitioningException
* @return the region
*/
private ITypedRegion handleInteriorPartition(ITypedRegion partition, List<Edit> 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();
private void handleInteriorPartition(IRegion commentArea,
ITypedRegion partition, IDocumentExtension3 docExtension,
Edit.EditFactory factory, List<Edit> edits)
throws BadLocationException, BadPartitioningException {
if (partType == ICPartitions.C_MULTI_LINE_COMMENT) {
// already in a comment - remove ending mark
edits.add(factory.createEdit(partEndOffset - tokenLength, tokenLength, "")); //$NON-NLS-1$
int commentAreaEnd = commentArea.getOffset() + commentArea.getLength();
int prevPartitionEnd = -1;
int partitionEnd = partition.getOffset()+partition.getLength();
final int startCommentTokenLength = getCommentStart().length();
final int endCommentTokenLength = getCommentEnd().length();
while (partitionEnd<=commentAreaEnd) {
if (partition.getType() == ICPartitions.C_MULTI_LINE_COMMENT
|| partition.getType() == ICPartitions.C_MULTI_LINE_DOC_COMMENT) {
// already in a comment - remove start/end tokens
edits.add(factory.createEdit(partition.getOffset(), startCommentTokenLength, "")); //$NON-NLS-1$
edits.add(factory.createEdit(partitionEnd - endCommentTokenLength, endCommentTokenLength, "")); //$NON-NLS-1$
}
// advance to next partition
prevPartitionEnd = partitionEnd;
partition= docExtension.getPartition(ICPartitions.C_PARTITIONING, partitionEnd, false);
partitionEnd = partition.getOffset() + partition.getLength();
// break the loop if we get stuck and no advance was made
if (partitionEnd<=prevPartitionEnd) break;
}
// advance to next partition
partition= docExtension.getPartition(ICPartitions.C_PARTITIONING, partEndOffset, false);
partType= partition.getType();
// start of next partition
if (partType == ICPartitions.C_MULTI_LINE_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<Edit> 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.
* Returns whether <code>partType</code> is special, i.e. a <code>String</code>,
* <code>Character</code>, or <code>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 == ICPartitions.C_CHARACTER
|| partType == ICPartitions.C_STRING
|| partType == ICPartitions.C_SINGLE_LINE_COMMENT
|| partType == ICPartitions.C_PREPROCESSOR;
return partType != IDocument.DEFAULT_CONTENT_TYPE;
}
/*
* @see org.eclipse.jdt.internal.ui.actions.BlockCommentAction#validSelection(org.eclipse.jface.text.ITextSelection)
*/
@Override
protected boolean isValidSelection(ITextSelection selection) {
return selection != null && !selection.isEmpty() && selection.getLength() > 0;

View file

@ -7,8 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
* Andrew Gvozdev - http://bugs.eclipse.org/236160
*******************************************************************************/
package org.eclipse.cdt.internal.ui.actions;
import java.util.LinkedList;
@ -17,7 +17,9 @@ import java.util.ResourceBundle;
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.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.ui.texteditor.ITextEditor;
@ -25,7 +27,7 @@ import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.cdt.ui.text.ICPartitions;
/**
* Action that removes the enclosing comment marks from a Java block comment.
* Action that removes the enclosing comment marks from a C block comment.
*
* @since 3.0
*/
@ -44,44 +46,70 @@ public class RemoveBlockCommentAction extends BlockCommentAction {
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)
*/
@Override
protected void runInternal(ITextSelection selection, IDocumentExtension3 docExtension, Edit.EditFactory factory) throws BadPartitioningException, BadLocationException {
if ( !(docExtension instanceof IDocument) ) return;
List<Edit> edits= new LinkedList<Edit>();
int tokenLength= getCommentStart().length();
int offset= selection.getOffset();
int endOffset= offset + selection.getLength();
int partitionStart = -1;
int partitionEnd = selection.getOffset();
ITypedRegion partition= docExtension.getPartition(ICPartitions.C_PARTITIONING, offset, false);
int partOffset= partition.getOffset();
int partEndOffset= partOffset + partition.getLength();
while (partEndOffset < endOffset) {
if (partition.getType() == ICPartitions.C_MULTI_LINE_COMMENT) {
edits.add(factory.createEdit(partOffset, tokenLength, "")); //$NON-NLS-1$
edits.add(factory.createEdit(partEndOffset - tokenLength, tokenLength, "")); //$NON-NLS-1$
do {
ITypedRegion partition = docExtension.getPartition(ICPartitions.C_PARTITIONING, partitionEnd, false);
if (partition.getOffset() <= partitionStart) {
// If we did not advance break the loop
break;
}
partition= docExtension.getPartition(ICPartitions.C_PARTITIONING, partEndOffset, false);
partOffset= partition.getOffset();
partEndOffset= partOffset + partition.getLength();
}
if (partition.getType() == ICPartitions.C_MULTI_LINE_COMMENT) {
edits.add(factory.createEdit(partOffset, tokenLength, "")); //$NON-NLS-1$
edits.add(factory.createEdit(partEndOffset - tokenLength, tokenLength, "")); //$NON-NLS-1$
}
partitionStart = partition.getOffset();
partitionEnd = partitionStart + partition.getLength();
if (partition.getType() == ICPartitions.C_MULTI_LINE_COMMENT
|| partition.getType() == ICPartitions.C_MULTI_LINE_DOC_COMMENT) {
uncommentPartition((IDocument)docExtension, factory, edits, partitionStart, partitionEnd);
}
} while (partitionEnd < selection.getOffset()+selection.getLength());
executeEdits(edits);
}
/*
* @see org.eclipse.jdt.internal.ui.actions.AddBlockCommentAction#validSelection(org.eclipse.jface.text.ITextSelection)
*/
private void uncommentPartition(IDocument doc, Edit.EditFactory factory,
List<Edit> edits, int partitionStart, int partitionEnd)
throws BadLocationException {
int startCommentTokenLength = getCommentStart().length();
int endCommentTokenLength = getCommentEnd().length();
// Remove whole line (with EOL) if it contains start or end comment tag
// and nothing else
if (partitionStart >= 0) {
IRegion lineRegion = doc.getLineInformationOfOffset(partitionStart);
String lineContent = doc.get(lineRegion.getOffset(), lineRegion.getLength());
// start comment tag '/*'
if (lineContent.equals(getCommentStart())) {
String eol = doc.getLineDelimiter(doc.getLineOfOffset(partitionStart));
if (eol!=null) {
startCommentTokenLength = startCommentTokenLength+eol.length();
}
}
}
int commentContentEnd = partitionEnd - endCommentTokenLength;
if (partitionEnd < doc.getLength()) {
IRegion lineRegion = doc.getLineInformationOfOffset(partitionEnd);
String lineContent = doc.get(lineRegion.getOffset(), lineRegion.getLength());
// end comment tag '*/'
if (lineContent.equals(getCommentEnd())) {
String eol = doc.getLineDelimiter(doc.getLineOfOffset(partitionEnd));
if (eol!=null) {
endCommentTokenLength = endCommentTokenLength + eol.length();
}
}
}
edits.add(factory.createEdit(partitionStart, startCommentTokenLength, "")); //$NON-NLS-1$
edits.add(factory.createEdit(commentContentEnd, endCommentTokenLength, "")); //$NON-NLS-1$
}
@Override
protected boolean isValidSelection(ITextSelection selection) {
return selection != null && !selection.isEmpty() && selection.getLength() > 0;