1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 515101: Control folding on doc and non-doc comments

Change-Id: I77b5cc2209d52877318182009b4de8e9491a85f7
This commit is contained in:
Jonah Graham 2017-04-14 11:38:46 +01:00
parent 18a6002f07
commit 501fa87934
9 changed files with 627 additions and 217 deletions

View file

@ -0,0 +1,251 @@
/*******************************************************************************
* Copyright (c) 2014, 2017 Kichwa Coders Ltd. 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:
* Jonah Graham (Kichwa Coders) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.text;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.preference.IPreferenceStore;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
/**
* Test doxygen style comment folding. This parametrized test checks all the
* combinations of doxygen enabled or not along with initially folding these
* types of comments:
* <ul>
* <li>File Header comments
* {@link PreferenceConstants#EDITOR_FOLDING_HEADERS}</li>
* <li>Block comments that are not doxygen comments
* {@link PreferenceConstants#EDITOR_FOLDING_NON_DOC_COMMENTS}</li>
* <li>Block comments taht are doxygen comments
* {@link PreferenceConstants#EDITOR_FOLDING_DOC_COMMENTS}</li>
* </ul>
*/
@RunWith(Parameterized.class)
public class FoldingCommentsTest extends FoldingTestBase {
@Parameters(name = "{index}: doxygenDoctool = {0}, headerComments = {1}, nonDocComments = {2}, docComments = {3}")
public static Iterable<Object[]> data() {
List<Object[]> params = new ArrayList<>();
for (int i = 0; i <= 0xf; i++) {
boolean doxygenDoctool = (i & 1) == 1;
boolean headerComments = (i & 2) == 2;
boolean nonDocComments = (i & 4) == 4;
boolean docComments = (i & 8) == 8;
params.add(new Object[] { doxygenDoctool, headerComments, nonDocComments, docComments });
}
return params;
}
@Rule
public TestName fTestName = new TestName();
@Parameter(0)
public boolean fDoxygenDoctool;
@Parameter(1)
public boolean fHeaderComments;
@Parameter(2)
public boolean fNonDocComments;
@Parameter(3)
public boolean fDocComments;
public FoldingCommentsTest() {
super();
}
@Before
@Override
public void setUp() throws Exception {
// extract real method name from test name
String name = fTestName.getMethodName().substring(0, fTestName.getMethodName().indexOf('['));
setName(name);
if (fDoxygenDoctool) {
setDoctoolToDoxygen();
}
IPreferenceStore store = CUIPlugin.getDefault().getPreferenceStore();
store.setValue(PreferenceConstants.EDITOR_FOLDING_ENABLED, true);
store.setValue(PreferenceConstants.EDITOR_FOLDING_COMMENTS, true);
store.setValue(PreferenceConstants.EDITOR_FOLDING_DOC_COMMENTS, fDocComments);
store.setValue(PreferenceConstants.EDITOR_FOLDING_NON_DOC_COMMENTS, fNonDocComments);
store.setValue(PreferenceConstants.EDITOR_FOLDING_HEADERS, fHeaderComments);
super.setUp();
}
@After
@Override
public void tearDown() throws Exception {
super.tearDown();
setDoctoolToNone();
IPreferenceStore store = CUIPlugin.getDefault().getPreferenceStore();
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_ENABLED);
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_COMMENTS);
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_DOC_COMMENTS);
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_NON_DOC_COMMENTS);
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_HEADERS);
}
///*
// * Header comment
// */
//
///**
// * func doxy comment
// */
//void func1() {}
//
///// func doxy comment (no folding on this sinlg-line comment)
//void func2() {}
//
///*
// * non-doxy comment
// */
//void func3() {}
//
//// non-doxy comment (no folding on this sinlg-line comment)
//void func4() {}
//
//// single-line many times comment
//// line 2 of comment
//void func5() {}
//
///// single-line many time doxy comment
///// line 2 of comment
//void func6() {}
//
///* single line non-doxy */
//void func7() {}
//
///** single line doxy */
//void func8() {}
//
///* adjacent single line non-doxy */
///* line 2 */
//void func9() {}
//
///** adjacent single line doxy */
///** line 2 */
//void func10() {}
//
///** adjacent single lines of different types, first line takes precedence */
///* line 2 */
//void func11a() {}
//
///** adjacent single lines of different types, first line takes precedence */
//// line 2
//void func11a() {}
//
///** adjacent single lines of different types, first line takes precedence */
///// line 2
//void func12a() {}
//
///* adjacent single lines of different types, first line takes precedence */
///** line 2 */
//void func11b() {}
//
///* adjacent single lines of different types, first line takes precedence */
//// line 2
//void func11b() {}
//
///* adjacent single lines of different types, first line takes precedence */
///// line 2
//void func12b() {}
//
//// adjacent single lines of different types, first line takes precedence
///* line 2 */
//void func11c() {}
//
//// adjacent single lines of different types, first line takes precedence
///* line 2 */
//void func11c() {}
//
//// adjacent single lines of different types, first line takes precedence
///// line 2
//void func12c() {}
//
///// adjacent single lines of different types, first line takes precedence
///* line 2 */
//void func11d() {}
//
///// adjacent single lines of different types, first line takes precedence
//// line 2
//void func11d() {}
//
///// adjacent single lines of different types, first line takes precedence
///* line 2 */
//void func12d() {}
//
// // single line not on first column
// // does not get collapsed
//void func13() {}
//
// /* multi line not on first column
// * does get collapsed
// */
//void func14() {}
//
// /** multi line doxy not on first column
// * does get collapsed
// */
//void func15() {}
//
//
@Test
public void testCommentsFolding() throws Exception {
// When not using doxygen, doc comments are never identified and
// are all treated as non-doc comments
boolean docComments = fDoxygenDoctool ? fDocComments : fNonDocComments;
PositionAndCollapsed[] actual = getFoldingPositions();
PositionAndCollapsed[] expected = new PositionAndCollapsed[] {
createPosition(0, 2, 1, fHeaderComments),
createPosition(4, 6, 5, docComments),
createPosition(12, 14, 13, fNonDocComments),
createPosition(20, 21, fNonDocComments),
createPosition(24, 25, docComments),
createPosition(34, 35, fNonDocComments),
createPosition(38, 39, docComments),
createPosition(42, 43, docComments),
createPosition(46, 47, docComments),
createPosition(50, 51, docComments),
createPosition(54, 55, fNonDocComments),
createPosition(58, 59, fNonDocComments),
createPosition(62, 63, fNonDocComments),
createPosition(66, 67, fNonDocComments),
createPosition(70, 71, fNonDocComments),
createPosition(74, 75, fNonDocComments),
createPosition(78, 79, docComments),
createPosition(82, 83, docComments),
createPosition(86, 87, docComments),
createPosition(94, 96, fNonDocComments),
createPosition(99, 101, docComments), };
assertEquals(toString(expected), toString(actual));
assertEqualPositions(expected, actual);
}
}

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2016 Wind River Systems, Inc. and others. * Copyright (c) 2006, 2017 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -8,41 +8,22 @@
* Contributors: * Contributors:
* Anton Leherbauer (Wind River Systems) - initial API and implementation * Anton Leherbauer (Wind River Systems) - initial API and implementation
* Elazar Leibovich (The Open University) - extra folding test * Elazar Leibovich (The Open University) - extra folding test
* Jonah Graham (Kichwa Coders) - extract most of FoldingTest into FoldingTestBase
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.ui.tests.text; package org.eclipse.cdt.ui.tests.text;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.projection.IProjectionPosition;
import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel; import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
import org.eclipse.ui.PartInitException;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.ui.testplugin.EditorTestHelper;
import org.eclipse.cdt.ui.testplugin.ResourceTestHelper;
import org.eclipse.cdt.ui.tests.BaseUITestCase;
import org.eclipse.cdt.ui.text.doctools.IDocCommentOwner;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager; import org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager;
import org.eclipse.cdt.internal.ui.text.doctools.NullDocCommentOwner; import org.eclipse.cdt.internal.ui.text.doctools.NullDocCommentOwner;
import org.eclipse.cdt.internal.ui.text.folding.DefaultCFoldingStructureProvider.CProjectionAnnotation; import org.eclipse.cdt.internal.ui.text.folding.DefaultCFoldingStructureProvider.CProjectionAnnotation;
@ -53,34 +34,7 @@ import junit.framework.TestSuite;
/** /**
* Code folding tests. * Code folding tests.
*/ */
public class FoldingTest extends BaseUITestCase { public class FoldingTest extends FoldingTestBase {
private static class ProjectionPosition extends Position implements IProjectionPosition, IRegion {
private int fCaptionOffset;
ProjectionPosition(int offset, int length, int captionOffset) {
super(offset, length);
fCaptionOffset= captionOffset;
}
@Override
public int computeCaptionOffset(IDocument document) throws BadLocationException {
return fCaptionOffset;
}
@Override
public IRegion[] computeProjectionRegions(IDocument document) throws BadLocationException {
return new IRegion[] { this };
}
}
private static final String LINKED_FOLDER= "resources/folding";
private static final String PROJECT= "FoldingTest";
private ICProject fCProject;
private final String fTestFilename= "/FoldingTest/src/FoldingTest.cpp";
private CEditor fEditor;
private SourceViewer fSourceViewer;
private IFile fFileUnderTest;
public static Test suite() { public static Test suite() {
return new TestSuite(FoldingTest.class); return new TestSuite(FoldingTest.class);
@ -92,173 +46,37 @@ public class FoldingTest extends BaseUITestCase {
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp();
fCProject= EditorTestHelper.createCProject(PROJECT, LINKED_FOLDER);
StringBuilder[] contents = getContentsForTest(1);
assertEquals("test requires exactly one test block", 1, contents.length);
String code = contents[0].toString();
String filename;
if (code.trim().isEmpty()) {
filename = fTestFilename;
} else {
TestSourceReader.createFile(fCProject.getProject(), new Path("FoldingTest.cpp"), code);
filename = "/FoldingTest/FoldingTest.cpp";
}
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
store.setValue(PreferenceConstants.EDITOR_FOLDING_ENABLED, true); store.setValue(PreferenceConstants.EDITOR_FOLDING_ENABLED, true);
store.setValue(PreferenceConstants.EDITOR_FOLDING_STATEMENTS, true); store.setValue(PreferenceConstants.EDITOR_FOLDING_STATEMENTS, true);
store.setValue(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, true); store.setValue(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, true);
store.setValue(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, false); store.setValue(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, false);
store.setValue(PreferenceConstants.EDITOR_FOLDING_COMMENTS, false);
store.setValue(PreferenceConstants.EDITOR_FOLDING_HEADERS, false); store.setValue(PreferenceConstants.EDITOR_FOLDING_HEADERS, false);
fFileUnderTest = ResourceTestHelper.findFile(filename);
openEditor(); super.setUp();
}
private void openEditor() throws PartInitException {
fEditor= (CEditor) EditorTestHelper.openInEditor(fFileUnderTest, true);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 300));
}
private void closeEditor() {
EditorTestHelper.closeEditor(fEditor);
} }
@Override @Override
protected void tearDown () throws Exception { protected void tearDown() throws Exception {
closeEditor(); super.tearDown();
if (fCProject != null)
CProjectHelper.delete(fCProject);
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_ENABLED); store.setToDefault(PreferenceConstants.EDITOR_FOLDING_ENABLED);
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_STATEMENTS); store.setToDefault(PreferenceConstants.EDITOR_FOLDING_STATEMENTS);
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED); store.setToDefault(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED);
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE); store.setToDefault(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE);
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_COMMENTS);
store.setToDefault(PreferenceConstants.EDITOR_FOLDING_HEADERS); store.setToDefault(PreferenceConstants.EDITOR_FOLDING_HEADERS);
// Set doctool to none. // Set doctool to none.
DocCommentOwnerManager.getInstance().setWorkspaceCommentOwner(NullDocCommentOwner.INSTANCE); DocCommentOwnerManager.getInstance().setWorkspaceCommentOwner(NullDocCommentOwner.INSTANCE);
super.tearDown();
}
private void setDoctoolToDoxygen() throws PartInitException {
// When the workspace comment owner changes, all open editors are
// re-opened asynchronously, within the test that async is a problem
// because we lose the handle and have no real condition to wait on.
// Instead close and reopen editor within this method.
closeEditor();
// Set doctool to doxygen.
IDocCommentOwner[] registeredOwners = DocCommentOwnerManager.getInstance().getRegisteredOwners();
IDocCommentOwner doxygenOwner = null;
for (IDocCommentOwner owner : registeredOwners) {
if (owner.getID().contains("doxygen")) {
assertNull("More than one owner looks like doxygen", doxygenOwner);
doxygenOwner = owner;
}
}
DocCommentOwnerManager.getInstance().setWorkspaceCommentOwner(doxygenOwner);
// see comment above closeEditor call above.
openEditor();
}
protected void assertEqualPositions(Position[] expected, Position[] actual) throws BadLocationException {
assertEquals(expected.length, actual.length);
IDocument document= fSourceViewer.getDocument();
for (int i= 0, n= expected.length; i < n; i++) {
final Position exp = expected[i];
int expectedStartLine= document.getLineOfOffset(exp.getOffset());
int expectedEndLine= document.getLineOfOffset(exp.getOffset()+exp.getLength());
final Position act = actual[i];
int actualStartLine= document.getLineOfOffset(act.getOffset());
int actualEndLine= document.getLineOfOffset(act.getOffset()+exp.getLength());
assertEquals(exp.isDeleted(), act.isDeleted());
assertEquals(expectedStartLine, actualStartLine);
assertEquals(expectedEndLine, actualEndLine);
if (exp instanceof IProjectionPosition) {
int expectedCaptionOffset= ((IProjectionPosition)exp).computeCaptionOffset(document);
int expectedCaptionLine= document.getLineOfOffset(exp.getOffset() + expectedCaptionOffset);
int actualCaptionLine= actualStartLine;
if (act instanceof IProjectionPosition) {
int actualCaptionOffset= ((IProjectionPosition)act).computeCaptionOffset(document);
actualCaptionLine= document.getLineOfOffset(exp.getOffset() + actualCaptionOffset);
}
assertEquals(expectedCaptionLine, actualCaptionLine);
}
}
}
protected Position createPosition(int startLine, int endLine) throws BadLocationException {
IDocument document= fSourceViewer.getDocument();
int startOffset= document.getLineOffset(startLine);
int endOffset= document.getLineOffset(endLine) + document.getLineLength(endLine);
return new Position(startOffset, endOffset - startOffset);
}
protected Position createPosition(int startLine, int endLine, int captionLine) throws BadLocationException {
IDocument document= fSourceViewer.getDocument();
int startOffset= document.getLineOffset(startLine);
int endOffset= document.getLineOffset(endLine) + document.getLineLength(endLine);
int captionOffset= document.getLineOffset(captionLine);
return new ProjectionPosition(startOffset, endOffset - startOffset, captionOffset - startOffset);
}
String toString(Position[] positions) throws BadLocationException {
StringBuilder buf= new StringBuilder();
IDocument document= fSourceViewer.getDocument();
buf.append("Position[] expected= new Position[] {\n");
for (int i= 0, n= positions.length; i < n; i++) {
Position position= positions[i];
int startLine= document.getLineOfOffset(position.getOffset());
int endLine= document.getLineOfOffset(position.getOffset()+position.getLength()-1);
int captionLine= startLine;
if (position instanceof IProjectionPosition) {
final int captionOffset = ((IProjectionPosition)position).computeCaptionOffset(document);
captionLine= document.getLineOfOffset(position.getOffset() + captionOffset);
}
buf.append("\tcreatePosition(");
buf.append(startLine);
buf.append(", ");
buf.append(endLine);
if (captionLine != startLine) {
buf.append(", ");
buf.append(captionLine);
}
buf.append("),\n");
}
buf.append("};\n");
return buf.toString();
}
protected Position[] getFoldingPositions() {
List<Position> positions= new ArrayList<Position>();
ProjectionAnnotationModel model= (ProjectionAnnotationModel)fEditor.getAdapter(ProjectionAnnotationModel.class);
assertNotNull(model);
for (Iterator<Annotation> iter= model.getAnnotationIterator(); iter.hasNext(); ) {
Annotation ann= iter.next();
Position pos= model.getPosition(ann);
positions.add(pos);
}
Collections.sort(positions, new Comparator<Position>() {
@Override
public int compare(Position p0, Position p1) {
return p0.offset - p1.offset;
}});
return positions.toArray(new Position[positions.size()]);
} }
// //
public void testInitialFolding() throws BadLocationException { public void testInitialFolding() throws Exception {
Position[] actual= getFoldingPositions(); PositionAndCollapsed[] actual= getFoldingPositions();
Position[] expected= new Position[] { PositionAndCollapsed[] expected= new PositionAndCollapsed[] {
createPosition(0, 2, 1), createPosition(0, 2, 1),
createPosition(4, 7), createPosition(4, 7),
createPosition(9, 12), createPosition(9, 12),
@ -297,7 +115,7 @@ public class FoldingTest extends BaseUITestCase {
createPosition(120, 122), createPosition(120, 122),
createPosition(123, 126), createPosition(123, 126),
createPosition(129, 130), createPosition(129, 130),
}; };
assertEquals(toString(expected), toString(actual)); assertEquals(toString(expected), toString(actual));
assertEqualPositions(expected, actual); assertEqualPositions(expected, actual);
} }
@ -309,8 +127,8 @@ public class FoldingTest extends BaseUITestCase {
store.setValue(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, false); store.setValue(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, false);
fEditor.getAction("FoldingToggle").run(); fEditor.getAction("FoldingToggle").run();
Position[] actual= getFoldingPositions(); PositionAndCollapsed[] actual= getFoldingPositions();
Position[] expected= new Position[] { PositionAndCollapsed[] expected= new PositionAndCollapsed[] {
createPosition(0, 2, 1), createPosition(0, 2, 1),
createPosition(4, 7), createPosition(4, 7),
createPosition(29, 31, 30), createPosition(29, 31, 30),
@ -337,7 +155,7 @@ public class FoldingTest extends BaseUITestCase {
createPosition(119, 127), createPosition(119, 127),
createPosition(120, 122), createPosition(120, 122),
createPosition(123, 126), createPosition(123, 126),
}; };
assertEquals(toString(expected), toString(actual)); assertEquals(toString(expected), toString(actual));
assertEqualPositions(expected, actual); assertEqualPositions(expected, actual);
} }
@ -350,8 +168,8 @@ public class FoldingTest extends BaseUITestCase {
store.setValue(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, false); store.setValue(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, false);
fEditor.getAction("FoldingToggle").run(); fEditor.getAction("FoldingToggle").run();
Position[] actual= getFoldingPositions(); PositionAndCollapsed[] actual= getFoldingPositions();
Position[] expected= new Position[] { PositionAndCollapsed[] expected= new PositionAndCollapsed[] {
createPosition(0, 2, 1), createPosition(0, 2, 1),
createPosition(4, 7), createPosition(4, 7),
createPosition(29, 31, 30), createPosition(29, 31, 30),
@ -434,10 +252,12 @@ public class FoldingTest extends BaseUITestCase {
///// line 3 ///// line 3
//void func4() {} //void func4() {}
public void testCollapseAdjacentSingleLineDocComments() throws Exception { public void testCollapseAdjacentSingleLineDocComments() throws Exception {
setDoctoolToDoxygen(); runWithEditorClosed(() -> {
setDoctoolToDoxygen();
});
Position[] actual= getFoldingPositions(); PositionAndCollapsed[] actual= getFoldingPositions();
Position[] expected= new Position[] { PositionAndCollapsed[] expected= new PositionAndCollapsed[] {
createPosition(0, 2, 1), createPosition(0, 2, 1),
createPosition(4, 5), createPosition(4, 5),
createPosition(8, 9), createPosition(8, 9),

View file

@ -0,0 +1,264 @@
/*******************************************************************************
* Copyright (c) 2006, 2017 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
* Jonah Graham (Kichwa Coders) - extract most of FoldingTest into FoldingTestBase
*******************************************************************************/
package org.eclipse.cdt.ui.tests.text;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.projection.IProjectionPosition;
import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
import org.eclipse.ui.PartInitException;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.ui.testplugin.EditorTestHelper;
import org.eclipse.cdt.ui.testplugin.ResourceTestHelper;
import org.eclipse.cdt.ui.tests.BaseUITestCase;
import org.eclipse.cdt.ui.text.doctools.IDocCommentOwner;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.text.doctools.DocCommentOwnerManager;
import org.eclipse.cdt.internal.ui.text.doctools.NullDocCommentOwner;
abstract public class FoldingTestBase extends BaseUITestCase {
protected static class ProjectionPosition extends Position implements IProjectionPosition, IRegion {
private int fCaptionOffset;
ProjectionPosition(int offset, int length, int captionOffset) {
super(offset, length);
fCaptionOffset= captionOffset;
}
@Override
public int computeCaptionOffset(IDocument document) throws BadLocationException {
return fCaptionOffset;
}
@Override
public IRegion[] computeProjectionRegions(IDocument document) throws BadLocationException {
return new IRegion[] { this };
}
}
protected static class PositionAndCollapsed {
public Position position;
public boolean isCollapsed;
public PositionAndCollapsed(Position position, boolean isCollapsed) {
this.position = position;
this.isCollapsed = isCollapsed;
}
}
private static final String LINKED_FOLDER = "resources/folding";
private static final String PROJECT = "FoldingTest";
private ICProject fCProject;
private final String fTestFilename = "/FoldingTest/src/FoldingTest.cpp";
protected CEditor fEditor;
private SourceViewer fSourceViewer;
private IFile fFileUnderTest;
public FoldingTestBase() {
super();
}
public FoldingTestBase(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
fCProject= EditorTestHelper.createCProject(PROJECT, LINKED_FOLDER);
StringBuilder[] contents = getContentsForTest(1);
assertEquals("test requires exactly one test block", 1, contents.length);
String code = contents[0].toString();
String filename;
if (code.trim().isEmpty()) {
filename = fTestFilename;
} else {
TestSourceReader.createFile(fCProject.getProject(), new Path("FoldingTest.cpp"), code);
filename = "/FoldingTest/FoldingTest.cpp";
}
fFileUnderTest = ResourceTestHelper.findFile(filename);
openEditor();
}
private void openEditor() throws PartInitException {
fEditor= (CEditor) EditorTestHelper.openInEditor(fFileUnderTest, true);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 300));
}
private void closeEditor() {
EditorTestHelper.closeEditor(fEditor);
}
@Override
protected void tearDown() throws Exception {
closeEditor();
if (fCProject != null)
CProjectHelper.delete(fCProject);
super.tearDown();
}
protected void runWithEditorClosed(Runnable runnable) throws PartInitException {
// When the workspace comment owner changes, all open editors are
// re-opened asynchronously, within the test that async is a problem
// because we lose the handle and have no real condition to wait on.
// Instead close and reopen editor within this method.
closeEditor();
runnable.run();
openEditor();
}
/**
* Set the doctool to None. This method should be run with the editor
* closed, see {@link #runWithEditorClosed(Runnable)}
*/
protected void setDoctoolToNone() {
DocCommentOwnerManager.getInstance().setWorkspaceCommentOwner(NullDocCommentOwner.INSTANCE);
}
/**
* Set the doctool to Doxygen. This method should be run with the editor
* closed, see {@link #runWithEditorClosed(Runnable)}
*/
protected void setDoctoolToDoxygen() {
IDocCommentOwner[] registeredOwners = DocCommentOwnerManager.getInstance().getRegisteredOwners();
IDocCommentOwner doxygenOwner = null;
for (IDocCommentOwner owner : registeredOwners) {
if (owner.getID().contains("doxygen")) {
assertNull("More than one owner looks like doxygen", doxygenOwner);
doxygenOwner = owner;
}
}
DocCommentOwnerManager.getInstance().setWorkspaceCommentOwner(doxygenOwner);
}
protected void assertEqualPositions(PositionAndCollapsed[] expected, PositionAndCollapsed[] actual) throws BadLocationException {
assertEquals(expected.length, actual.length);
IDocument document= fSourceViewer.getDocument();
for (int i= 0, n= expected.length; i < n; i++) {
final Position exp = expected[i].position;
int expectedStartLine= document.getLineOfOffset(exp.getOffset());
int expectedEndLine= document.getLineOfOffset(exp.getOffset()+exp.getLength());
final Position act = actual[i].position;
int actualStartLine= document.getLineOfOffset(act.getOffset());
int actualEndLine= document.getLineOfOffset(act.getOffset()+exp.getLength());
assertEquals(exp.isDeleted(), act.isDeleted());
assertEquals(expectedStartLine, actualStartLine);
assertEquals(expectedEndLine, actualEndLine);
if (exp instanceof IProjectionPosition) {
int expectedCaptionOffset= ((IProjectionPosition)exp).computeCaptionOffset(document);
int expectedCaptionLine= document.getLineOfOffset(exp.getOffset() + expectedCaptionOffset);
int actualCaptionLine= actualStartLine;
if (act instanceof IProjectionPosition) {
int actualCaptionOffset= ((IProjectionPosition)act).computeCaptionOffset(document);
actualCaptionLine= document.getLineOfOffset(exp.getOffset() + actualCaptionOffset);
}
assertEquals(expectedCaptionLine, actualCaptionLine);
}
assertEquals(expected[i].isCollapsed, actual[i].isCollapsed);
}
}
protected PositionAndCollapsed createPosition(int startLine, int endLine) throws BadLocationException {
return createPosition(startLine, endLine, false);
}
protected PositionAndCollapsed createPosition(int startLine, int endLine, boolean collapsed) throws BadLocationException {
IDocument document= fSourceViewer.getDocument();
int startOffset= document.getLineOffset(startLine);
int endOffset= document.getLineOffset(endLine) + document.getLineLength(endLine);
Position position = new Position(startOffset, endOffset - startOffset);
return new PositionAndCollapsed(position, collapsed);
}
protected PositionAndCollapsed createPosition(int startLine, int endLine, int captionLine) throws BadLocationException {
return createPosition(startLine, endLine, captionLine, false);
}
protected PositionAndCollapsed createPosition(int startLine, int endLine, int captionLine, boolean collapsed) throws BadLocationException {
IDocument document= fSourceViewer.getDocument();
int startOffset= document.getLineOffset(startLine);
int endOffset= document.getLineOffset(endLine) + document.getLineLength(endLine);
int captionOffset= document.getLineOffset(captionLine);
Position position = new ProjectionPosition(startOffset, endOffset - startOffset, captionOffset - startOffset);
return new PositionAndCollapsed(position, collapsed);
}
protected String toString(PositionAndCollapsed[] positionAndCollapseds) throws BadLocationException {
StringBuilder buf= new StringBuilder();
IDocument document= fSourceViewer.getDocument();
buf.append("PositionAndCollapsed[] expected= new PositionAndCollapsed[] {\n");
for (int i= 0, n= positionAndCollapseds.length; i < n; i++) {
Position position= positionAndCollapseds[i].position;
int startLine= document.getLineOfOffset(position.getOffset());
int endLine= document.getLineOfOffset(position.getOffset()+position.getLength()-1);
int captionLine= startLine;
if (position instanceof IProjectionPosition) {
final int captionOffset = ((IProjectionPosition)position).computeCaptionOffset(document);
captionLine= document.getLineOfOffset(position.getOffset() + captionOffset);
}
buf.append("\tcreatePosition(");
buf.append(startLine);
buf.append(", ");
buf.append(endLine);
if (captionLine != startLine) {
buf.append(", ");
buf.append(captionLine);
}
if (positionAndCollapseds[i].isCollapsed) {
buf.append(", true");
}
buf.append("),\n");
}
buf.append("};\n");
return buf.toString();
}
protected PositionAndCollapsed[] getFoldingPositions() {
List<PositionAndCollapsed> positionAndCollapseds= new ArrayList<PositionAndCollapsed>();
ProjectionAnnotationModel model= (ProjectionAnnotationModel)fEditor.getAdapter(ProjectionAnnotationModel.class);
assertNotNull(model);
for (Iterator<Annotation> iter= model.getAnnotationIterator(); iter.hasNext(); ) {
Annotation ann= iter.next();
ProjectionAnnotation proAnn = (ProjectionAnnotation)ann;
Position pos= model.getPosition(ann);
positionAndCollapseds.add(new PositionAndCollapsed(pos, proAnn.isCollapsed()));
}
Collections.sort(positionAndCollapseds, new Comparator<PositionAndCollapsed>() {
@Override
public int compare(PositionAndCollapsed p0, PositionAndCollapsed p1) {
return p0.position.offset - p1.position.offset;
}});
return positionAndCollapseds.toArray(new PositionAndCollapsed[positionAndCollapseds.size()]);
}
}

View file

@ -55,6 +55,7 @@ import org.eclipse.cdt.ui.tests.text.doctools.DocCommentTestSuite;
// folding tests // folding tests
FoldingTest.class, FoldingTest.class,
FoldingCommentsTest.class,
// basic editing tests // basic editing tests
BasicCEditorTest.class, BasicCEditorTest.class,

View file

@ -58,6 +58,9 @@ public class DefaultCFoldingPreferenceBlock implements ICFoldingPreferenceBlock
} }
}; };
private Button fInactiveCodeFoldingCheckBox; private Button fInactiveCodeFoldingCheckBox;
private Button fDocCommentsFoldingCheckBox;
private Button fNonDocCommentsFoldingCheckBox;
private Button fHeaderCommentsFoldingCheckBox;
public DefaultCFoldingPreferenceBlock() { public DefaultCFoldingPreferenceBlock() {
@ -74,6 +77,8 @@ public class DefaultCFoldingPreferenceBlock implements ICFoldingPreferenceBlock
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_METHODS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_METHODS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_STRUCTURES)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_STRUCTURES));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_COMMENTS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_COMMENTS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_DOC_COMMENTS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_NON_DOC_COMMENTS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_HEADERS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_HEADERS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED));
@ -107,7 +112,9 @@ public class DefaultCFoldingPreferenceBlock implements ICFoldingPreferenceBlock
addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_methods, PreferenceConstants.EDITOR_FOLDING_METHODS, 0); addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_methods, PreferenceConstants.EDITOR_FOLDING_METHODS, 0);
addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_structures, PreferenceConstants.EDITOR_FOLDING_STRUCTURES, 0); addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_structures, PreferenceConstants.EDITOR_FOLDING_STRUCTURES, 0);
addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_comments, PreferenceConstants.EDITOR_FOLDING_COMMENTS, 0); addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_comments, PreferenceConstants.EDITOR_FOLDING_COMMENTS, 0);
addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_headers, PreferenceConstants.EDITOR_FOLDING_HEADERS, 0); fDocCommentsFoldingCheckBox = addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_doc_comments, PreferenceConstants.EDITOR_FOLDING_DOC_COMMENTS, 20);
fNonDocCommentsFoldingCheckBox = addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_non_doc_comments, PreferenceConstants.EDITOR_FOLDING_NON_DOC_COMMENTS, 20);
fHeaderCommentsFoldingCheckBox = addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_headers, PreferenceConstants.EDITOR_FOLDING_HEADERS, 20);
fInactiveCodeFoldingCheckBox= addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_inactive_code, PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, 0); fInactiveCodeFoldingCheckBox= addCheckBox(group, FoldingMessages.DefaultCFoldingPreferenceBlock_inactive_code, PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, 0);
return inner; return inner;
@ -143,6 +150,13 @@ public class DefaultCFoldingPreferenceBlock implements ICFoldingPreferenceBlock
if (PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED.equals(key)) { if (PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED.equals(key)) {
fInactiveCodeFoldingCheckBox.setEnabled(fOverlayStore.getBoolean(key)); fInactiveCodeFoldingCheckBox.setEnabled(fOverlayStore.getBoolean(key));
} }
if (PreferenceConstants.EDITOR_FOLDING_COMMENTS.equals(key)) {
boolean enabled = fOverlayStore.getBoolean(key);
fDocCommentsFoldingCheckBox.setEnabled(enabled);
fNonDocCommentsFoldingCheckBox.setEnabled(enabled);
fHeaderCommentsFoldingCheckBox.setEnabled(enabled);
}
} }
/* /*

View file

@ -442,13 +442,31 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi
fMap.put(annotation, position); fMap.put(annotation, position);
} }
/**
* Returns <code>true</code> if documentation comments should be collapsed.
*
* @return <code>true</code> if documentation comments should be collapsed
*/
public boolean collapseDocComments() {
return collapseComments() && fCollapseDocComments;
}
/**
* Returns <code>true</code> if non-documentation comments should be collapsed.
*
* @return <code>true</code> if non-documentation comments should be collapsed
*/
public boolean collapseNonDocComments() {
return collapseComments() && fCollapseNonDocComments;
}
/** /**
* Returns <code>true</code> if header comments should be collapsed. * Returns <code>true</code> if header comments should be collapsed.
* *
* @return <code>true</code> if header comments should be collapsed * @return <code>true</code> if header comments should be collapsed
*/ */
public boolean collapseHeaderComments() { public boolean collapseHeaderComments() {
return fAllowCollapsing && fCollapseHeaderComments; return collapseComments() && fCollapseHeaderComments;
} }
/** /**
@ -867,6 +885,8 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi
private boolean fCollapseHeaderComments= true; private boolean fCollapseHeaderComments= true;
private boolean fCollapseComments= false; private boolean fCollapseComments= false;
private boolean fCollapseDocComments= false;
private boolean fCollapseNonDocComments= false;
private boolean fCollapseMacros= false; private boolean fCollapseMacros= false;
private boolean fCollapseFunctions= true; private boolean fCollapseFunctions= true;
private boolean fCollapseStructures= true; private boolean fCollapseStructures= true;
@ -1035,8 +1055,10 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi
fCollapseStructures= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_STRUCTURES); fCollapseStructures= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_STRUCTURES);
fCollapseMacros= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_MACROS); fCollapseMacros= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_MACROS);
fCollapseMethods= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS); fCollapseMethods= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS);
fCollapseHeaderComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS);
fCollapseComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_COMMENTS); fCollapseComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_COMMENTS);
fCollapseDocComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_DOC_COMMENTS);
fCollapseNonDocComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_NON_DOC_COMMENTS);
fCollapseHeaderComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS);
fCollapseInactiveCode= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE); fCollapseInactiveCode= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE);
fPreprocessorBranchFoldingEnabled= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED); fPreprocessorBranchFoldingEnabled= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED);
fStatementsFoldingEnabled= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_STATEMENTS); fStatementsFoldingEnabled= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_STATEMENTS);
@ -1506,14 +1528,21 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi
* @throws BadLocationException * @throws BadLocationException
*/ */
private void computeFoldingStructure(ITypedRegion[] partitions, FoldingStructureComputationContext ctx) throws BadLocationException { private void computeFoldingStructure(ITypedRegion[] partitions, FoldingStructureComputationContext ctx) throws BadLocationException {
boolean collapse = ctx.collapseComments(); boolean collapseDoc = ctx.collapseDocComments();
boolean collapseNonDoc = ctx.collapseNonDocComments();
IDocument doc= ctx.getDocument(); IDocument doc= ctx.getDocument();
int startLine = -1; int startLine = -1;
int endLine = -1; int endLine = -1;
boolean startLineIsDocComment = false;
List<Tuple> comments= new ArrayList<Tuple>(); List<Tuple> comments= new ArrayList<Tuple>();
ModifiableRegion commentRange = new ModifiableRegion(); ModifiableRegion commentRange = new ModifiableRegion();
for (ITypedRegion partition : partitions) { for (ITypedRegion partition : partitions) {
boolean singleLine= false; boolean singleLine= false;
boolean collapse = collapseNonDoc;
if (ICPartitions.C_MULTI_LINE_DOC_COMMENT.equals(partition.getType())
|| ICPartitions.C_SINGLE_LINE_DOC_COMMENT.equals(partition.getType())) {
collapse = collapseDoc;
}
if (ICPartitions.C_MULTI_LINE_COMMENT.equals(partition.getType()) if (ICPartitions.C_MULTI_LINE_COMMENT.equals(partition.getType())
|| ICPartitions.C_MULTI_LINE_DOC_COMMENT.equals(partition.getType())) { || ICPartitions.C_MULTI_LINE_DOC_COMMENT.equals(partition.getType())) {
Position position= createCommentPosition(alignRegion(partition, ctx, true)); Position position= createCommentPosition(alignRegion(partition, ctx, true));
@ -1521,7 +1550,8 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi
if (startLine >= 0 && endLine - startLine >= fMinCommentLines) { if (startLine >= 0 && endLine - startLine >= fMinCommentLines) {
Position projection = createCommentPosition(alignRegion(commentRange, ctx, true)); Position projection = createCommentPosition(alignRegion(commentRange, ctx, true));
if (projection != null) { if (projection != null) {
comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection)); boolean collapseLast = startLineIsDocComment ? collapseDoc : collapseNonDoc;
comments.add(new Tuple(new CProjectionAnnotation(collapseLast, doc.get(projection.offset, Math.min(16, projection.length)), true), projection));
} }
startLine= -1; startLine= -1;
} }
@ -1547,11 +1577,14 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi
if (startLine >= 0 && endLine - startLine >= fMinCommentLines) { if (startLine >= 0 && endLine - startLine >= fMinCommentLines) {
Position projection = createCommentPosition(alignRegion(commentRange, ctx, true)); Position projection = createCommentPosition(alignRegion(commentRange, ctx, true));
if (projection != null) { if (projection != null) {
comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection)); boolean collapseLast = startLineIsDocComment ? collapseDoc : collapseNonDoc;
comments.add(new Tuple(new CProjectionAnnotation(collapseLast, doc.get(projection.offset, Math.min(16, projection.length)), true), projection));
} }
} }
startLine = lineNr; startLine = lineNr;
endLine = lineNr; endLine = lineNr;
startLineIsDocComment = ICPartitions.C_MULTI_LINE_DOC_COMMENT.equals(partition.getType())
|| ICPartitions.C_SINGLE_LINE_DOC_COMMENT.equals(partition.getType());
commentRange.offset = lineRegion.getOffset(); commentRange.offset = lineRegion.getOffset();
commentRange.length = lineRegion.getLength(); commentRange.length = lineRegion.getLength();
} else { } else {
@ -1564,7 +1597,8 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi
if (startLine >= 0 && endLine - startLine >= fMinCommentLines) { if (startLine >= 0 && endLine - startLine >= fMinCommentLines) {
Position projection = createCommentPosition(alignRegion(commentRange, ctx, true)); Position projection = createCommentPosition(alignRegion(commentRange, ctx, true));
if (projection != null) { if (projection != null) {
comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection)); boolean collapseLast = startLineIsDocComment ? collapseDoc : collapseNonDoc;
comments.add(new Tuple(new CProjectionAnnotation(collapseLast, doc.get(projection.offset, Math.min(16, projection.length)), true), projection));
} }
} }
if (!comments.isEmpty()) { if (!comments.isEmpty()) {

View file

@ -27,6 +27,8 @@ public final class FoldingMessages extends NLS {
public static String DefaultCFoldingPreferenceBlock_methods; public static String DefaultCFoldingPreferenceBlock_methods;
public static String DefaultCFoldingPreferenceBlock_structures; public static String DefaultCFoldingPreferenceBlock_structures;
public static String DefaultCFoldingPreferenceBlock_comments; public static String DefaultCFoldingPreferenceBlock_comments;
public static String DefaultCFoldingPreferenceBlock_doc_comments;
public static String DefaultCFoldingPreferenceBlock_non_doc_comments;
public static String DefaultCFoldingPreferenceBlock_headers; public static String DefaultCFoldingPreferenceBlock_headers;
public static String DefaultCFoldingPreferenceBlock_inactive_code; public static String DefaultCFoldingPreferenceBlock_inactive_code;
public static String DefaultCFoldingPreferenceBlock_preprocessor_enabled; public static String DefaultCFoldingPreferenceBlock_preprocessor_enabled;

View file

@ -18,6 +18,8 @@ DefaultCFoldingPreferenceBlock_functions= &Functions
DefaultCFoldingPreferenceBlock_methods= M&ethods DefaultCFoldingPreferenceBlock_methods= M&ethods
DefaultCFoldingPreferenceBlock_structures= &Structures DefaultCFoldingPreferenceBlock_structures= &Structures
DefaultCFoldingPreferenceBlock_comments= &Comments DefaultCFoldingPreferenceBlock_comments= &Comments
DefaultCFoldingPreferenceBlock_doc_comments= &Documentation Tool Comments
DefaultCFoldingPreferenceBlock_non_doc_comments= &Non-Documentation Tool Comments
DefaultCFoldingPreferenceBlock_headers= &Header Comments DefaultCFoldingPreferenceBlock_headers= &Header Comments
DefaultCFoldingPreferenceBlock_inactive_code= &Inactive Preprocessor Branches DefaultCFoldingPreferenceBlock_inactive_code= &Inactive Preprocessor Branches
DefaultCFoldingPreferenceBlock_preprocessor_enabled= Enable folding of preprocessor branches (#if/#endif) DefaultCFoldingPreferenceBlock_preprocessor_enabled= Enable folding of preprocessor branches (#if/#endif)

View file

@ -885,6 +885,26 @@ public class PreferenceConstants {
*/ */
public static final String EDITOR_FOLDING_COMMENTS= "editor_folding_default_comments"; //$NON-NLS-1$ public static final String EDITOR_FOLDING_COMMENTS= "editor_folding_default_comments"; //$NON-NLS-1$
/**
* A named preference that stores the value for document comment folding for the default folding provider.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 6.2
*/
public static final String EDITOR_FOLDING_DOC_COMMENTS= "editor_folding_default_doc_comments"; //$NON-NLS-1$
/**
* A named preference that stores the value for non-document comment folding for the default folding provider.
* <p>
* Value is of type <code>Boolean</code>.
* </p>
*
* @since 6.2
*/
public static final String EDITOR_FOLDING_NON_DOC_COMMENTS= "editor_folding_default_non_doc_comments"; //$NON-NLS-1$
/** /**
* A named preference that stores the value for header comment folding for the default folding provider. * A named preference that stores the value for header comment folding for the default folding provider.
* <p> * <p>
@ -2211,6 +2231,8 @@ public class PreferenceConstants {
store.setDefault(EDITOR_FOLDING_METHODS, false); store.setDefault(EDITOR_FOLDING_METHODS, false);
store.setDefault(EDITOR_FOLDING_MACROS, false); store.setDefault(EDITOR_FOLDING_MACROS, false);
store.setDefault(EDITOR_FOLDING_COMMENTS, false); store.setDefault(EDITOR_FOLDING_COMMENTS, false);
store.setDefault(EDITOR_FOLDING_DOC_COMMENTS, false);
store.setDefault(EDITOR_FOLDING_NON_DOC_COMMENTS, false);
store.setDefault(EDITOR_FOLDING_HEADERS, true); store.setDefault(EDITOR_FOLDING_HEADERS, true);
store.setDefault(EDITOR_FOLDING_INACTIVE_CODE, false); store.setDefault(EDITOR_FOLDING_INACTIVE_CODE, false);
store.setDefault(EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, false); store.setDefault(EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, false);