From 19ce7cc1375e680a188c7d799d0154148f95666e Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Wed, 21 Dec 2016 01:02:47 -0500 Subject: [PATCH] Bug 507138 - Avoid collisions between the keys of CProjectAnnotations used for statement folding This is mostly to mitigate the effects of a bug in ProjectionViewer (bug 509559). See the discussion in bug 507138 for details. Change-Id: Icf36b54d6a11892f02214a168ef1c9c284478710 --- .../cdt/ui/tests/text/FoldingTest.java | 70 +++++++++++++++++-- .../DefaultCFoldingStructureProvider.java | 10 +-- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/FoldingTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/FoldingTest.java index 846097a5e4e..53e4b89b770 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/FoldingTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/FoldingTest.java @@ -14,13 +14,15 @@ 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.Iterator; import java.util.List; +import java.util.Set; import junit.framework.Test; -import junit.framework.TestCase; import junit.framework.TestSuite; +import org.eclipse.core.runtime.Path; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; @@ -33,17 +35,20 @@ import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel; 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.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.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.text.folding.DefaultCFoldingStructureProvider.CProjectionAnnotation; /** * Code folding tests. */ -public class FoldingTest extends TestCase { +public class FoldingTest extends BaseUITestCase { private static class ProjectionPosition extends Position implements IProjectionPosition, IRegion { private int fCaptionOffset; @@ -67,9 +72,9 @@ public class FoldingTest extends TestCase { private ICProject fCProject; private final String fTestFilename= "/FoldingTest/src/FoldingTest.cpp"; - private static CEditor fEditor; + private CEditor fEditor; - private static SourceViewer fSourceViewer; + private SourceViewer fSourceViewer; public static Test suite() { return new TestSuite(FoldingTest.class); @@ -81,8 +86,20 @@ public class FoldingTest extends TestCase { @Override protected void setUp() throws Exception { + super.setUp(); fCProject= EditorTestHelper.createCProject(PROJECT, LINKED_FOLDER); + + StringBuilder[] contents = getContentsForTest(1); + assert contents.length == 1; + 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(); store.setValue(PreferenceConstants.EDITOR_FOLDING_ENABLED, true); @@ -91,7 +108,7 @@ public class FoldingTest extends TestCase { store.setValue(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, false); store.setValue(PreferenceConstants.EDITOR_FOLDING_HEADERS, false); - fEditor= (CEditor) EditorTestHelper.openInEditor(ResourceTestHelper.findFile(fTestFilename), true); + fEditor= (CEditor) EditorTestHelper.openInEditor(ResourceTestHelper.findFile(filename), true); fSourceViewer= EditorTestHelper.getSourceViewer(fEditor); assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 300)); } @@ -198,6 +215,7 @@ public class FoldingTest extends TestCase { return positions.toArray(new Position[positions.size()]); } + // public void testInitialFolding() throws BadLocationException { Position[] actual= getFoldingPositions(); Position[] expected= new Position[] { @@ -244,6 +262,7 @@ public class FoldingTest extends TestCase { assertEqualPositions(expected, actual); } + // public void testToggleFolding_Bug186729() throws BadLocationException { fEditor.getAction("FoldingToggle").run(); IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); @@ -283,6 +302,7 @@ public class FoldingTest extends TestCase { assertEqualPositions(expected, actual); } + // public void testToggleFoldingNoASTRequired() throws BadLocationException { fEditor.getAction("FoldingToggle").run(); IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); @@ -311,4 +331,44 @@ public class FoldingTest extends TestCase { assertEqualPositions(expected, actual); } + private void assertNoKeyCollisions() { + ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class); + assertNotNull(model); + int annotations = 0; + Set keys = new HashSet<>(); + for (Iterator iter= model.getAnnotationIterator(); iter.hasNext(); ) { + Annotation ann= iter.next(); + if (ann instanceof CProjectionAnnotation) { + ++annotations; + System.out.println("key is: " + ((CProjectionAnnotation) ann).getElement()); + keys.add(((CProjectionAnnotation) ann).getElement()); + System.out.println(" after adding key, set has size " + keys.size()); + } + } + assertEquals(annotations, keys.size()); + } + + // int func(const char*); + // + // void foo() { + // if (func("a looooooooooooooooooooooooooong string") == 1) { + // } + // if (func("a looooooooooooooooooooooooooong string") == 2) { + // } + // } + public void testStatementsSharingFirst32Chars_507138() throws BadLocationException { + assertNoKeyCollisions(); + } + + // bool func(); + // + // void foo() { + // if (func()) { + // } + // if (func()) { + // } + // } + public void testIdenticalStatements_507138() throws BadLocationException { + assertNoKeyCollisions(); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingStructureProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingStructureProvider.java index 1a1e206d7c6..0cbc972fedd 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingStructureProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingStructureProvider.java @@ -514,7 +514,7 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi } - private static class CProjectionAnnotation extends ProjectionAnnotation { + public static class CProjectionAnnotation extends ProjectionAnnotation { public final static int CMODEL= 0; public final static int COMMENT= 1; @@ -1085,11 +1085,13 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi existingPosition.setOffset(newPosition.getOffset()); existingPosition.setLength(newPosition.getLength()); if (collapseChanged) { - if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() change annotation " + newAnnotation); //$NON-NLS-1$ + if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() change annotation due to collapse state change " + newAnnotation); //$NON-NLS-1$ if (newAnnotation.isCollapsed()) existingAnnotation.markCollapsed(); else existingAnnotation.markExpanded(); + } else { + if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() change annotation due to position change " + newAnnotation); //$NON-NLS-1$ } updates.add(existingAnnotation); } @@ -1278,7 +1280,6 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi return map; } - private void computeFoldingStructure(final FoldingStructureComputationContext ctx) { if (fCommentFoldingEnabled) { // compute comment positions from partitioning @@ -1491,8 +1492,7 @@ public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvi private Object computeKey(Position pos, FoldingStructureComputationContext ctx) { try { final IDocument document= ctx.getDocument(); - IRegion line= document.getLineInformationOfOffset(pos.offset); - return document.get(pos.offset, Math.min(32, line.getOffset() + line.getLength() - pos.offset)); + return document.getLineOfOffset(pos.offset); } catch (BadLocationException exc) { return exc; }