| /******************************************************************************* |
| * Copyright (c) 2007, 2015 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.text.tests; |
| |
| import static org.junit.Assert.assertTrue; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.Position; |
| import org.eclipse.jface.text.source.Annotation; |
| import org.eclipse.jface.text.source.AnnotationModel; |
| import org.eclipse.jface.text.source.IAnnotationModel; |
| import org.eclipse.jface.text.source.IAnnotationModelListener; |
| |
| /** |
| * Tests the {@link org.eclipse.jface.text.source.IAnnotationModelExtension2}. |
| * |
| * @since 3.4 |
| */ |
| public class AnnotationModelExtension2Test { |
| |
| public class OldAnnotationModel implements IAnnotationModel { |
| |
| private final HashMap<Annotation, Position> fAnnotations= new HashMap<>(); |
| |
| @Override |
| public void addAnnotation(Annotation annotation, Position position) { |
| fAnnotations.put(annotation, position); |
| } |
| |
| @Override |
| public void addAnnotationModelListener(IAnnotationModelListener listener) { |
| } |
| |
| @Override |
| public void connect(IDocument document) { |
| } |
| |
| @Override |
| public void disconnect(IDocument document) { |
| } |
| |
| @Override |
| public Iterator<Annotation> getAnnotationIterator() { |
| return fAnnotations.keySet().iterator(); |
| } |
| |
| @Override |
| public Position getPosition(Annotation annotation) { |
| return fAnnotations.get(annotation); |
| } |
| |
| @Override |
| public void removeAnnotation(Annotation annotation) { |
| fAnnotations.remove(annotation); |
| } |
| |
| @Override |
| public void removeAnnotationModelListener(IAnnotationModelListener listener) { |
| } |
| |
| public void removeAllAnnotations() { |
| fAnnotations.clear(); |
| } |
| } |
| |
| private static final int MODEL_COUNT= 3; |
| |
| private Document fDocument; |
| private AnnotationModel fAnnotationModel; |
| private AnnotationModel fNewInnerModel; |
| private OldAnnotationModel fOldInnerModel; |
| |
| private Annotation fInside; |
| private Annotation fBefore; |
| private Annotation fAfter; |
| private Annotation fInsideIn; |
| private Annotation fInsideOut; |
| private Annotation fBeforeIn; |
| private Annotation fBoforeOut; |
| private Annotation fAfterIn; |
| private Annotation fAfterOut; |
| |
| @Before |
| public void setUp() { |
| fDocument= new Document("How much wood\nwould a woodchuck chuck\nif a woodchuck\ncould chuck wood?\n42"); |
| |
| fAnnotationModel= new AnnotationModel(); |
| |
| fNewInnerModel= new AnnotationModel(); |
| fAnnotationModel.addAnnotationModel("model1", fNewInnerModel); |
| |
| fOldInnerModel= new OldAnnotationModel(); |
| fAnnotationModel.addAnnotationModel("model2", fOldInnerModel); |
| |
| fInside= new Annotation(false); |
| fInsideIn= new Annotation(false); |
| fInsideOut= new Annotation(false); |
| |
| fBefore= new Annotation(false); |
| fBeforeIn= new Annotation(false); |
| fBoforeOut= new Annotation(false); |
| |
| fAfter= new Annotation(false); |
| fAfterIn= new Annotation(false); |
| fAfterOut= new Annotation(false); |
| |
| fAnnotationModel.connect(fDocument); |
| } |
| |
| @After |
| public void tearDown() { |
| fAnnotationModel.disconnect(fDocument); |
| } |
| |
| private void assertEquals(Annotation[] expected, Annotation[] actual, IAnnotationModel insideModel, IAnnotationModel beforeModel, IAnnotationModel afterModel) { |
| HashSet<Annotation> expectedSet= new HashSet<>(Arrays.asList(expected)); |
| for (int i= 0; i < actual.length; i++) { |
| if (!expectedSet.contains(actual[i])) { |
| String message= "Unexpected annotation " + getName(actual[i]) + " in result with models [" + getAnnotationModelNames(insideModel, beforeModel, afterModel) + "]"; |
| assertTrue(message, false); |
| } |
| expectedSet.remove(actual[i]); |
| } |
| |
| if (!expectedSet.isEmpty()) { |
| String message= "Missing annotations in result with models [" + getAnnotationModelNames(insideModel, beforeModel, afterModel) + "]"; |
| for (Iterator<Annotation> iterator= expectedSet.iterator(); iterator.hasNext();) { |
| Annotation missing= iterator.next(); |
| message= message + "\n" + getName(missing); |
| } |
| assertTrue(message, false); |
| } |
| } |
| |
| private String getAnnotationModelNames(IAnnotationModel insideModel, IAnnotationModel beforeModel, IAnnotationModel afterModel) { |
| return "inside: " + getAnnotationModelName(insideModel) + " before: " + getAnnotationModelName(beforeModel) + " after: " + getAnnotationModelName(afterModel); |
| } |
| |
| private String getAnnotationModelName(IAnnotationModel model) { |
| if (model == fAnnotationModel) { |
| return "'Top'"; |
| } else if (model == fNewInnerModel) { |
| return "'New inner'"; |
| } else if (model == fOldInnerModel) { |
| return "'Old inner'"; |
| } |
| |
| return "'Unknown'"; |
| } |
| |
| private String getName(Annotation annotation) { |
| Position position= fAnnotationModel.getPosition(annotation); |
| return "[" + position.getOffset() + ", " + position.getLength() + "]"; |
| } |
| |
| /* |
| * The annotations are added to the annotations models |
| * as following: |
| * |
| * 0-beforeout-9 21-afterout--30 |
| * 0--beforein---11 19---afterin---30 |
| * 0--before----10 20--after-----30 |
| * |
| * 10--region----20 |
| * |
| * 10--inside----20 |
| * 11-insidein-19 |
| * 9---insideout---21 |
| */ |
| private void addAnnotations(IAnnotationModel insideModel, IAnnotationModel beforeModel, IAnnotationModel afterModel) { |
| insideModel.addAnnotation(fInside, new Position(10, 11)); |
| insideModel.addAnnotation(fInsideIn, new Position(11, 9)); |
| insideModel.addAnnotation(fInsideOut, new Position(9, 13)); |
| |
| beforeModel.addAnnotation(fBefore, new Position(0, 11)); |
| beforeModel.addAnnotation(fBeforeIn, new Position(0, 12)); |
| beforeModel.addAnnotation(fBoforeOut, new Position(0, 10)); |
| |
| afterModel.addAnnotation(fAfter, new Position(20, 11)); |
| afterModel.addAnnotation(fAfterIn, new Position(19, 12)); |
| afterModel.addAnnotation(fAfterOut, new Position(21, 10)); |
| } |
| |
| private void removeAnnotations() { |
| fAnnotationModel.removeAllAnnotations(); |
| fNewInnerModel.removeAllAnnotations(); |
| fOldInnerModel.removeAllAnnotations(); |
| } |
| |
| private Annotation[] getAnnotations(boolean lookAhead, boolean lookBehind) { |
| Iterator<Annotation> iterator= fAnnotationModel.getAnnotationIterator(10, 11, lookAhead, lookBehind); |
| |
| ArrayList<Annotation> result= new ArrayList<>(); |
| while (iterator.hasNext()) { |
| result.add(iterator.next()); |
| } |
| |
| return result.toArray(new Annotation[result.size()]); |
| } |
| |
| private void assertPermutations(boolean lookAhead, boolean lookBehind, Annotation[] expected) { |
| for (int i= 0; i < MODEL_COUNT; i++) { |
| for (int j= 0; j < MODEL_COUNT; j++) { |
| for (int k= 0; k < MODEL_COUNT; k++) { |
| IAnnotationModel insideModel= getModel(i); |
| IAnnotationModel beforeModel= getModel(j); |
| IAnnotationModel afterModel= getModel(k); |
| |
| addAnnotations(insideModel, beforeModel, afterModel); |
| |
| Annotation[] actual= getAnnotations(lookAhead, lookBehind); |
| assertEquals(expected, actual, insideModel, beforeModel, afterModel); |
| |
| removeAnnotations(); |
| } |
| } |
| } |
| } |
| |
| private IAnnotationModel getModel(int number) { |
| switch (number) { |
| case 0: |
| return fAnnotationModel; |
| case 1: |
| return fNewInnerModel; |
| case 2: |
| return fOldInnerModel; |
| default: |
| break; |
| } |
| return null; |
| } |
| |
| @Test |
| public void testInside() throws Exception { |
| Annotation[] expected= new Annotation[] { fInside, fInsideIn }; |
| assertPermutations(false, false, expected); |
| } |
| |
| @Test |
| public void testAhead() throws Exception { |
| Annotation[] expected= new Annotation[] { fInside, fInsideIn, fBefore, fBeforeIn }; |
| assertPermutations(true, false, expected); |
| } |
| |
| @Test |
| public void testBehind() throws Exception { |
| Annotation[] expected= new Annotation[] { fInside, fInsideIn, fAfter, fAfterIn }; |
| assertPermutations(false, true, expected); |
| } |
| |
| @Test |
| public void testAheadBehind() throws Exception { |
| Annotation[] expected= new Annotation[] { fInside, fInsideIn, fInsideOut, fAfter, fAfterIn, fBefore, fBeforeIn }; |
| assertPermutations(true, true, expected); |
| } |
| |
| } |