mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-15 08:18:55 +00:00
Merge pull request #1358 from rablewis/1262
[#1262] Prevent infinite loop with NodeIterator.
This commit is contained in:
commit
04aedc416e
10 changed files with 440 additions and 0 deletions
|
@ -0,0 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 Robert Lewis 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.impl.AbstractNode;
|
||||
|
||||
/**
|
||||
* @author Robert Lewis - Initial contribution and API
|
||||
*/
|
||||
public class BasicNodeIterable extends org.eclipse.xtext.nodemodel.impl.BasicNodeIterable {
|
||||
|
||||
protected BasicNodeIterable(AbstractNode startWith) {
|
||||
super(startWith);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 Robert Lewis 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.impl.AbstractNode;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Robert Lewis - Initial contribution and API
|
||||
*/
|
||||
public class BasicNodeIterableTest {
|
||||
|
||||
@Test
|
||||
public void forEachTest() {
|
||||
AbstractNode alpha = BasicNodeIteratorTest.nodeWithTwoSiblings();
|
||||
BasicNodeIterable iterable = new BasicNodeIterable(alpha);
|
||||
|
||||
List<String> tokens = new ArrayList<String>();
|
||||
for (INode node : iterable) {
|
||||
tokens.add(node.getText());
|
||||
}
|
||||
|
||||
Assert.assertEquals("alpha", tokens.get(0));
|
||||
Assert.assertEquals("beta", tokens.get(1));
|
||||
Assert.assertEquals("gamma", tokens.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forEachReverseTest() {
|
||||
AbstractNode alpha = BasicNodeIteratorTest.nodeWithTwoSiblings();
|
||||
BasicNodeIterable iterable = new BasicNodeIterable(alpha);
|
||||
|
||||
List<String> tokens = new ArrayList<String>();
|
||||
for (INode node : iterable.reverse()) {
|
||||
tokens.add(node.getText());
|
||||
}
|
||||
|
||||
Assert.assertEquals("gamma", tokens.get(0));
|
||||
Assert.assertEquals("beta", tokens.get(1));
|
||||
Assert.assertEquals("alpha", tokens.get(2));
|
||||
}
|
||||
|
||||
@Test(expected=NullPointerException.class)
|
||||
public void testStartWithNullThrowsNPE() {
|
||||
new BasicNodeIterable(null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 Robert Lewis 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.impl.AbstractNode;
|
||||
|
||||
/**
|
||||
* @author Robert Lewis - Initial contribution and API
|
||||
*/
|
||||
public class BasicNodeIterator extends org.eclipse.xtext.nodemodel.impl.BasicNodeIterator {
|
||||
|
||||
public BasicNodeIterator(AbstractNode startWith) {
|
||||
super(startWith);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 Robert Lewis 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.impl.EObjectImpl;
|
||||
import org.eclipse.xtext.nodemodel.impl.AbstractNode;
|
||||
import org.eclipse.xtext.nodemodel.impl.NodeModelBuilder;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Robert Lewis - Initial contribution and API
|
||||
*/
|
||||
public class BasicNodeIteratorTest {
|
||||
|
||||
private static AbstractNode getSingleNode() {
|
||||
return new RootNode();
|
||||
}
|
||||
|
||||
public static AbstractNode nodeWithTwoSiblings() {
|
||||
NodeModelBuilder builder = new NodeModelBuilder();
|
||||
String text = "alpha beta gamma";
|
||||
|
||||
RootNode root = new RootNode();
|
||||
root.basicSetCompleteContent(text);
|
||||
|
||||
EObject alpha = new EObjectImpl() {};
|
||||
builder.newLeafNode(text.indexOf("alpha"), "alpha".length(), alpha, false, null, root);
|
||||
|
||||
EObject beta = new EObjectImpl() {};
|
||||
builder.newLeafNode(text.indexOf("beta"), "beta".length(), beta, false, null, root);
|
||||
|
||||
EObject gamma = new EObjectImpl() {};
|
||||
builder.newLeafNode(text.indexOf("gamma"), "gamma".length(), gamma, false, null, root);
|
||||
|
||||
return root.basicGetFirstChild();
|
||||
|
||||
}
|
||||
|
||||
@Test(expected=NullPointerException.class)
|
||||
public void testStartWithNullThrowsNPE() {
|
||||
new BasicNodeIterator(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleNodeHasNext() {
|
||||
AbstractNode single = getSingleNode();
|
||||
BasicNodeIterator it = new BasicNodeIterator(single);
|
||||
|
||||
Assert.assertTrue(it.hasNext());
|
||||
it.next();
|
||||
|
||||
Assert.assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
@Test(expected=NoSuchElementException.class)
|
||||
public void testNextTooFarThrowsException() {
|
||||
AbstractNode single = getSingleNode();
|
||||
BasicNodeIterator it = new BasicNodeIterator(single);
|
||||
|
||||
it.next();
|
||||
|
||||
it.next();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterateThreeNodes() {
|
||||
AbstractNode alpha = nodeWithTwoSiblings();
|
||||
BasicNodeIterator it = new BasicNodeIterator(alpha);
|
||||
|
||||
Assert.assertTrue(it.hasNext());
|
||||
it.next();
|
||||
|
||||
Assert.assertTrue(it.hasNext());
|
||||
it.next();
|
||||
|
||||
Assert.assertTrue(it.hasNext());
|
||||
it.next();
|
||||
|
||||
Assert.assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleNodeHasPrevious() {
|
||||
AbstractNode single = getSingleNode();
|
||||
BasicNodeIterator it = new BasicNodeIterator(single);
|
||||
|
||||
Assert.assertTrue(it.hasPrevious());
|
||||
it.previous();
|
||||
|
||||
Assert.assertFalse(it.hasPrevious());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIteratePreviousStartsWithLastNode() {
|
||||
AbstractNode alpha = nodeWithTwoSiblings();
|
||||
BasicNodeIterator it = new BasicNodeIterator(alpha);
|
||||
|
||||
INode result = it.previous();
|
||||
|
||||
Assert.assertEquals("gamma", result.getText());
|
||||
}
|
||||
|
||||
@Test(expected=NoSuchElementException.class)
|
||||
public void testPreviousTooFarThrowsException() {
|
||||
AbstractNode single = getSingleNode();
|
||||
BasicNodeIterator it = new BasicNodeIterator(single);
|
||||
|
||||
it.previous();
|
||||
|
||||
it.previous();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterateThreeNodesInReverse() {
|
||||
AbstractNode alpha = nodeWithTwoSiblings();
|
||||
BasicNodeIterator it = new BasicNodeIterator(alpha);
|
||||
|
||||
Assert.assertTrue(it.hasPrevious());
|
||||
it.previous();
|
||||
|
||||
Assert.assertTrue(it.hasPrevious());
|
||||
it.previous();
|
||||
|
||||
Assert.assertTrue(it.hasPrevious());
|
||||
it.previous();
|
||||
|
||||
Assert.assertFalse(it.hasPrevious());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 Robert Lewis 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Robert Lewis - Initial contribution and API
|
||||
*/
|
||||
public class NodeIterableTest {
|
||||
|
||||
@Test
|
||||
public void forEachTest() {
|
||||
INode alpha = NodeIteratorTest.nodeWithTwoSiblings();
|
||||
NodeIterable iterable = new NodeIterable(alpha);
|
||||
|
||||
List<String> tokens = new ArrayList<String>();
|
||||
for (INode node : iterable) {
|
||||
tokens.add(node.getText());
|
||||
}
|
||||
|
||||
Assert.assertEquals("alpha", tokens.get(0));
|
||||
Assert.assertEquals("beta", tokens.get(1));
|
||||
Assert.assertEquals("gamma", tokens.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forEachReverseTest() {
|
||||
INode alpha = NodeIteratorTest.nodeWithTwoSiblings();
|
||||
NodeIterable iterable = new NodeIterable(alpha);
|
||||
|
||||
List<String> tokens = new ArrayList<String>();
|
||||
for (INode node : iterable.reverse()) {
|
||||
tokens.add(node.getText());
|
||||
}
|
||||
|
||||
Assert.assertEquals("gamma", tokens.get(0));
|
||||
Assert.assertEquals("beta", tokens.get(1));
|
||||
Assert.assertEquals("alpha", tokens.get(2));
|
||||
}
|
||||
|
||||
@Test(expected=NullPointerException.class)
|
||||
public void testStartWithNullThrowsNPE() {
|
||||
new NodeIterable(null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 Robert Lewis 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.util;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.impl.EObjectImpl;
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.impl.NodeModelBuilder;
|
||||
import org.eclipse.xtext.nodemodel.impl.RootNode;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Robert Lewis - Initial contribution and API
|
||||
*/
|
||||
public class NodeIteratorTest {
|
||||
|
||||
private static INode getSingleNode() {
|
||||
return new RootNode();
|
||||
}
|
||||
|
||||
public static INode nodeWithTwoSiblings() {
|
||||
NodeModelBuilder builder = new NodeModelBuilder();
|
||||
String text = "alpha beta gamma";
|
||||
|
||||
ICompositeNode root = builder.newRootNode(text);
|
||||
|
||||
EObject alpha = new EObjectImpl() {};
|
||||
ILeafNode alphaNode = builder.newLeafNode(text.indexOf("alpha"), "alpha".length(), alpha, false, null, root);
|
||||
|
||||
EObject beta = new EObjectImpl() {};
|
||||
builder.newLeafNode(text.indexOf("beta"), "beta".length(), beta, false, null, root);
|
||||
|
||||
EObject gamma = new EObjectImpl() {};
|
||||
builder.newLeafNode(text.indexOf("gamma"), "gamma".length(), gamma, false, null, root);
|
||||
|
||||
return alphaNode;
|
||||
}
|
||||
|
||||
@Test(expected=NullPointerException.class)
|
||||
public void testStartWithNullThrowsNPE() {
|
||||
new NodeIterator(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleNodeHasNext() {
|
||||
INode single = getSingleNode();
|
||||
NodeIterator it = new NodeIterator(single);
|
||||
|
||||
Assert.assertTrue(it.hasNext());
|
||||
it.next();
|
||||
|
||||
Assert.assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
@Test(expected=NoSuchElementException.class)
|
||||
public void testNextTooFarThrowsException() {
|
||||
INode single = getSingleNode();
|
||||
NodeIterator it = new NodeIterator(single);
|
||||
|
||||
it.next();
|
||||
|
||||
it.next();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterateThreeNodes() {
|
||||
INode alpha = nodeWithTwoSiblings();
|
||||
NodeIterator it = new NodeIterator(alpha);
|
||||
|
||||
Assert.assertTrue(it.hasNext());
|
||||
it.next();
|
||||
|
||||
Assert.assertTrue(it.hasNext());
|
||||
it.next();
|
||||
|
||||
Assert.assertTrue(it.hasNext());
|
||||
it.next();
|
||||
|
||||
Assert.assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleNodeHasPrevious() {
|
||||
INode single = getSingleNode();
|
||||
NodeIterator it = new NodeIterator(single);
|
||||
|
||||
Assert.assertTrue(it.hasPrevious());
|
||||
it.previous();
|
||||
|
||||
Assert.assertFalse(it.hasPrevious());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIteratePreviousStartsWithLastNode() {
|
||||
INode alpha = nodeWithTwoSiblings();
|
||||
NodeIterator it = new NodeIterator(alpha);
|
||||
|
||||
INode result = it.previous();
|
||||
|
||||
Assert.assertEquals("gamma", result.getText());
|
||||
}
|
||||
|
||||
@Test(expected=NoSuchElementException.class)
|
||||
public void testPreviousTooFarThrowsException() {
|
||||
INode single = getSingleNode();
|
||||
NodeIterator it = new NodeIterator(single);
|
||||
|
||||
it.previous();
|
||||
|
||||
it.previous();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterateThreeNodesInReverse() {
|
||||
INode alpha = nodeWithTwoSiblings();
|
||||
NodeIterator it = new NodeIterator(alpha);
|
||||
|
||||
Assert.assertTrue(it.hasPrevious());
|
||||
it.previous();
|
||||
|
||||
Assert.assertTrue(it.hasPrevious());
|
||||
it.previous();
|
||||
|
||||
Assert.assertTrue(it.hasPrevious());
|
||||
it.previous();
|
||||
|
||||
Assert.assertFalse(it.hasPrevious());
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.BidiIterable;
|
||||
import org.eclipse.xtext.nodemodel.BidiIterator;
|
||||
import org.eclipse.xtext.nodemodel.util.ReversedBidiIterator;
|
||||
|
@ -12,6 +14,7 @@ public class BasicNodeIterable implements BidiIterable<AbstractNode> {
|
|||
private final AbstractNode startWith;
|
||||
|
||||
protected BasicNodeIterable(AbstractNode startWith) {
|
||||
Objects.requireNonNull(startWith);
|
||||
this.startWith = startWith;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.BidiIterator;
|
||||
|
||||
|
@ -23,6 +24,7 @@ public class BasicNodeIterator extends UnmodifiableIterator<AbstractNode> implem
|
|||
private AbstractNode lastReturned;
|
||||
|
||||
protected BasicNodeIterator(AbstractNode startWith) {
|
||||
Objects.requireNonNull(startWith);
|
||||
this.startWith = startWith;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.eclipse.xtext.nodemodel.util;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.BidiIterable;
|
||||
import org.eclipse.xtext.nodemodel.BidiIterator;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
|
@ -12,6 +14,7 @@ public class NodeIterable implements BidiIterable<INode> {
|
|||
private final INode startWith;
|
||||
|
||||
public NodeIterable(INode startWith) {
|
||||
Objects.requireNonNull(startWith);
|
||||
this.startWith = startWith;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
package org.eclipse.xtext.nodemodel.util;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.BidiIterator;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
|
@ -23,6 +24,7 @@ public class NodeIterator extends UnmodifiableIterator<INode> implements BidiIte
|
|||
private INode lastReturned;
|
||||
|
||||
public NodeIterator(INode startWith) {
|
||||
Objects.requireNonNull(startWith);
|
||||
this.startWith = startWith;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue