diff options
author | angelozerr | 2018-08-01 15:35:42 +0000 |
---|---|---|
committer | Mickael Istria | 2018-08-03 07:15:45 +0000 |
commit | fe1f173989deb9f16974d0c78d55f68c04a07462 (patch) | |
tree | d75e3894334ac161536142c44bf560273a6d37e5 /org.eclipse.ui.genericeditor.tests | |
parent | 839c84221733f9fc9c6adc7a0a23d4132d79b92a (diff) | |
download | eclipse.platform.text-fe1f173989deb9f16974d0c78d55f68c04a07462.tar.gz eclipse.platform.text-fe1f173989deb9f16974d0c78d55f68c04a07462.tar.xz eclipse.platform.text-fe1f173989deb9f16974d0c78d55f68c04a07462.zip |
Bug 520659 - [generic editor] Default Code folding for generic editorI20180803-2000
should use IndentFoldingStrategy
Change-Id: If023933536584f07960fcb6b99c6dedcf6f6be1c
Signed-off-by: angelozerr <angelo.zerr@gmail.com>
Diffstat (limited to 'org.eclipse.ui.genericeditor.tests')
5 files changed, 326 insertions, 0 deletions
diff --git a/org.eclipse.ui.genericeditor.tests/plugin.xml b/org.eclipse.ui.genericeditor.tests/plugin.xml index 1d81989bb2a..a65580a0934 100644 --- a/org.eclipse.ui.genericeditor.tests/plugin.xml +++ b/org.eclipse.ui.genericeditor.tests/plugin.xml @@ -235,6 +235,23 @@ </highlightReconciler> </extension> <extension + point="org.eclipse.ui.genericeditor.foldingReconcilers"> + <foldingReconciler + class="org.eclipse.ui.genericeditor.tests.contributions.FoldingReconciler" + contentType="org.eclipse.ui.genericeditor.tests.content-type-bar"> + </foldingReconciler> + <foldingReconciler + class="org.eclipse.ui.genericeditor.tests.contributions.FoldingReconciler" + contentType="org.eclipse.ui.genericeditor.tests.enabled-when-content-type"> + <enabledWhen> + <test + forcePluginActivation="true" + property="org.eclipse.ui.genericeditor.tests.contributions.enabled"> + </test> + </enabledWhen> + </foldingReconciler> + </extension> + <extension point="org.eclipse.core.expressions.propertyTesters"> <propertyTester class="org.eclipse.ui.genericeditor.tests.contributions.EnabledPropertyTester" diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/FoldingTest.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/FoldingTest.java new file mode 100644 index 00000000000..d8d66bf8eb2 --- /dev/null +++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/FoldingTest.java @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2018 Angelo ZERR. + * 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: + * Angelo Zerr <angelo.zerr@gmail.com> - [generic editor] Default Code folding for generic editor should use IndentFoldingStrategy - Bug 520659 + */ +package org.eclipse.ui.genericeditor.tests; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import org.eclipse.swt.widgets.Display; + +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.projection.ProjectionAnnotation; +import org.eclipse.jface.text.source.projection.ProjectionViewer; +import org.eclipse.jface.text.tests.util.DisplayHelper; + +import org.eclipse.ui.genericeditor.tests.contributions.EnabledPropertyTester; + +public class FoldingTest extends AbstratGenericEditorTest { + + @Override + protected void createAndOpenFile() throws Exception { + //leave editor creation to individual tests + } + + @Test + public void testDefaultIndentFoldingOneFold() throws Exception { + createAndOpenFile("bar.xml", "<a>\n b</a>"); + checkFolding(pos(0, 10)); + } + + @Test + public void testDefaultIndentFoldingTwoFold() throws Exception { + createAndOpenFile("bar.xml", "<a>\n <b>\n c\n </b>\n</a>"); + checkFolding(pos(0, 19), pos(4, 9)); + } + + @Test + public void testCustomFoldingReconciler() throws Exception { + createAndOpenFile("bar.txt", "<a>\n <b>\n c\n </b>\n</a>\n"); + checkFolding(pos(0, 24), pos(5, 14)); + } + + @Test + public void testEnabledWhenCustomFoldingReconciler() throws Exception { + EnabledPropertyTester.setEnabled(true); + createAndOpenFile("enabledWhen.txt", "<a>\n <b>\n c\n </b>\n</a>\n"); + checkFolding(pos(0, 24), pos(5, 14)); + cleanFileAndEditor(); + + EnabledPropertyTester.setEnabled(false); + createAndOpenFile("enabledWhen.txt", "<a>\n <b>\n c\n </b>\n</a>\n"); + checkFolding(); + } + + private static Position pos(int offset, int length) { + return new Position(offset, length); + } + + private void checkFolding(Position... expectedPositions) { + if (expectedPositions == null) { + expectedPositions= new Position[0]; + } + waitForAnnotations(expectedPositions.length); + List<Annotation> folderAnnotations= getAnnotationsFromAnnotationModel(); + Assert.assertEquals(expectedPositions.length, folderAnnotations.size()); + List<Position> actualPositions= new ArrayList<>(expectedPositions.length); + for (int i= 0; i < expectedPositions.length; i++) { + Annotation folderAnnotation= folderAnnotations.get(i); + Position actualPosition= getProjectionAnnotationModel().getPosition(folderAnnotation); + actualPositions.add(actualPosition); + } + // Sort actual positions by offset + Collections.sort(actualPositions, (p1, p2) -> p1.offset - p2.offset); + Assert.assertArrayEquals(expectedPositions, actualPositions.toArray()); + } + + private IAnnotationModel getProjectionAnnotationModel() { + ProjectionViewer dp= (ProjectionViewer) editor.getAdapter(ITextViewer.class); + IAnnotationModel am= dp.getProjectionAnnotationModel(); + return am; + } + + private void waitForAnnotations(int count) { + new DisplayHelper() { + @Override + protected boolean condition() { + return getAnnotationsFromAnnotationModel().size() == count; + } + }.waitForCondition(Display.getDefault(), 2000); + } + + private List<Annotation> getAnnotationsFromAnnotationModel() { + List<Annotation> annotationList= new ArrayList<>(); + Iterator<Annotation> annotationIterator= getProjectionAnnotationModel().getAnnotationIterator(); + while (annotationIterator.hasNext()) { + Annotation ann= annotationIterator.next(); + if (ann.getType().equals(ProjectionAnnotation.TYPE)) { + annotationList.add(ann); + } + } + return annotationList; + } +} diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/GenericEditorTestSuite.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/GenericEditorTestSuite.java index ee4c1940719..6ab16ce9db0 100644 --- a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/GenericEditorTestSuite.java +++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/GenericEditorTestSuite.java @@ -22,6 +22,7 @@ import org.junit.runners.Suite.SuiteClasses; StylingTest.class, HoverTest.class, EditorTest.class, + FoldingTest.class, AutoEditTest.class, ReconcilerTest.class, HighlightTest.class diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/FoldingReconciler.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/FoldingReconciler.java new file mode 100644 index 00000000000..7a13de4b76e --- /dev/null +++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/FoldingReconciler.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2017 Red Hat 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: + * Lucas Bullen (Red Hat Inc.) - initial implementation + *******************************************************************************/ +package org.eclipse.ui.genericeditor.tests.contributions; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.reconciler.Reconciler; +import org.eclipse.jface.text.source.projection.ProjectionViewer; + +public class FoldingReconciler extends Reconciler { + + private FoldingStrategy fStrategy; + + public FoldingReconciler() { + fStrategy = new FoldingStrategy(); + this.setReconcilingStrategy(fStrategy, IDocument.DEFAULT_CONTENT_TYPE); + } + + @Override + public void install(ITextViewer textViewer) { + super.install(textViewer); + ProjectionViewer pViewer =(ProjectionViewer)textViewer; + fStrategy.setProjectionViewer(pViewer); + } +}
\ No newline at end of file diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/FoldingStrategy.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/FoldingStrategy.java new file mode 100644 index 00000000000..aeae3176324 --- /dev/null +++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/FoldingStrategy.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2017 Red Hat 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: + * Lucas Bullen (Red Hat Inc.) - initial implementation + *******************************************************************************/ +package org.eclipse.ui.genericeditor.tests.contributions; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IProgressMonitor; +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.reconciler.DirtyRegion; +import org.eclipse.jface.text.reconciler.IReconcilingStrategy; +import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.projection.ProjectionAnnotation; +import org.eclipse.jface.text.source.projection.ProjectionViewer; + +public class FoldingStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension { + + private IDocument document; + private String oldDocument; + private ProjectionViewer projectionViewer; + private List<Annotation> oldAnnotations = new ArrayList<>(); + private List<Position> oldPositions = new ArrayList<>(); + + @Override + public void setDocument(IDocument document) { + this.document = document; + } + + public void setProjectionViewer(ProjectionViewer projectionViewer) { + this.projectionViewer = projectionViewer; + } + + @Override + public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) { + initialReconcile(); + } + + @Override + public void reconcile(IRegion partition) { + initialReconcile(); + } + + @Override + public void initialReconcile() { + if(document.get().equals(oldDocument)) return; + oldDocument = document.get(); + + List<Position> positions = getNewPositionsOfAnnotations(); + + List<Position> positionsToRemove = new ArrayList<>(); + List<Annotation> annotationToRemove = new ArrayList<>(); + + for (Position position : oldPositions) { + if(!positions.contains(position)) { + projectionViewer.getProjectionAnnotationModel().removeAnnotation(oldAnnotations.get(oldPositions.indexOf(position))); + positionsToRemove.add(position); + annotationToRemove.add(oldAnnotations.get(oldPositions.indexOf(position))); + }else { + positions.remove(position); + } + } + oldPositions.removeAll(positionsToRemove); + oldAnnotations.removeAll(annotationToRemove); + + for (Position position : positions) { + Annotation annotation = new ProjectionAnnotation(); + projectionViewer.getProjectionAnnotationModel().addAnnotation(annotation, position); + oldPositions.add(position); + oldAnnotations.add(annotation); + } + } + + private static enum SearchingFor { + START_OF_TAG, START_OF_WORD, END_OF_WORD, END_OF_LINE + } + + private List<Position> getNewPositionsOfAnnotations(){ + List<Position> positions = new ArrayList<>(); + Map<String, Integer> startOfAnnotation = new HashMap<>(); + SearchingFor searchingFor = SearchingFor.START_OF_TAG; + + int characters = document.getLength(); + int currentCharIndex = 0; + + int wordStartIndex = 0; + int sectionStartIndex = 0; + String word = ""; + + try { + while (currentCharIndex < characters) { + char currentChar = document.getChar(currentCharIndex); + switch (searchingFor) { + case START_OF_TAG: + if(currentChar == '<') { + char nextChar = document.getChar(currentCharIndex+1); + if(nextChar != '?') { + sectionStartIndex = currentCharIndex; + searchingFor = SearchingFor.START_OF_WORD; + } + } + break; + case START_OF_WORD: + if(Character.isLetter(currentChar)) { + wordStartIndex = currentCharIndex; + searchingFor = SearchingFor.END_OF_WORD; + } + break; + case END_OF_WORD: + if(!Character.isLetter(currentChar)) { + word = document.get(wordStartIndex, currentCharIndex - wordStartIndex); + if(startOfAnnotation.containsKey(word)) { + searchingFor = SearchingFor.END_OF_LINE; + }else { + startOfAnnotation.put(word, sectionStartIndex); + searchingFor = SearchingFor.START_OF_TAG; + } + } + break; + case END_OF_LINE: + if(currentChar == '\n') { + int start = startOfAnnotation.get(word); + if(document.getLineOfOffset(start) != document.getLineOfOffset(currentCharIndex)) { + positions.add(new Position(start,currentCharIndex + 1 - start)); + } + startOfAnnotation.remove(word); + searchingFor = SearchingFor.START_OF_TAG; + } + break; + } + currentCharIndex++; + } + } catch (BadLocationException e) { + // skip the remainder of file due to error + } + return positions; + } + + @Override + public void setProgressMonitor(IProgressMonitor monitor) { + // no progress monitor used + } + +}
\ No newline at end of file |