NEW - bug 251856: [Core] NodeContentAdapter does not work

https://bugs.eclipse.org/bugs/show_bug.cgi?id=251856
This commit is contained in:
jkohnlein 2008-10-23 15:14:08 +00:00
parent 7b671a9152
commit 191481e84c
3 changed files with 256 additions and 10 deletions

View file

@ -37,7 +37,8 @@ public class NodeContentAdapter extends EContentAdapter {
}
else {
AbstractNode predecessor = parent.getChildren().get(position - 1);
updateNodeInfo(child, new NodeInfo((predecessor.getOffset() + predecessor.getLength()), predecessor.endLine()));
updateNodeInfo(child, new NodeInfo((predecessor.getOffset() + predecessor.getLength()),
predecessor.endLine()));
}
break;
case Notification.REMOVE:
@ -63,6 +64,7 @@ public class NodeContentAdapter extends EContentAdapter {
@Override
protected void setTarget(EObject target) {
super.setTarget(target);
if (target instanceof AbstractNode) {
AbstractNode targetNode = (AbstractNode) target;
CompositeNode parent = targetNode.getParent();
@ -74,7 +76,8 @@ public class NodeContentAdapter extends EContentAdapter {
}
else {
AbstractNode predecessor = siblings.get(index - 1);
updateNodeInfo(targetNode, new NodeInfo((predecessor.getOffset() + predecessor.getLength()), predecessor.endLine()));
updateNodeInfo(targetNode, new NodeInfo((predecessor.getOffset() + predecessor.getLength()),
predecessor.endLine()));
}
}
else {
@ -86,21 +89,30 @@ public class NodeContentAdapter extends EContentAdapter {
static class NodeInfo {
int offset;
int line;
public NodeInfo(int offset, int line) {
this.offset = offset;
this.line = line;
}
}
/**
* Set <code>info</code> on <code>node</code> and then descent into the
* contents of node updating length and offset.
*
* @param node
* @param info
* @return
*/
protected NodeInfo updateNodeInfoInContents(AbstractNode node, NodeInfo info) {
node.setOffset(info.offset);
node.setLine(info.line);
if (node instanceof LeafNode) {
node.setLength(((LeafNode)node).getText().length());
node.setLength(((LeafNode) node).getText().length());
info.offset += node.getLength();
info.line = node.endLine();
} else if (node instanceof CompositeNode) {
}
else if (node instanceof CompositeNode) {
int length = 0;
for (AbstractNode child : ((CompositeNode) node).getChildren()) {
info = updateNodeInfoInContents(child, info);
@ -111,16 +123,46 @@ public class NodeContentAdapter extends EContentAdapter {
return info;
}
protected AbstractNode updateNodeInfo(AbstractNode node, NodeInfo info) {
protected void updateNodeInfo(AbstractNode node, NodeInfo info) {
updateNodeInfoInContents(node, info);
updateFollowingNodes(node, info);
}
/**
* If a node in a tree changes its size, the offset of all following nodes
* (successors, their contents, successors of the parent and their content)
* must be updated.
*
* @param node
* @param info
*/
protected void updateFollowingNodes(AbstractNode node, NodeInfo info) {
CompositeNode parent = node.getParent();
if (parent != null) {
EList<AbstractNode> siblings = parent.getChildren();
int index = siblings.indexOf(node);
for (int i = index + 1; i < siblings.size(); ++i) {
info = updateNodeInfoInContents(siblings.get(i), info);
int parentLength=0;
for (int i = 0; i < siblings.size(); ++i) {
AbstractNode sibling = siblings.get(i);
parentLength += sibling.getLength();
if(i > index) {
info = updateNodeInfoInContents(sibling, info);
}
}
parent.setLength(parentLength);
updateFollowingNodes(parent, info);
}
return node;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.emf.common.notify.impl.AdapterImpl#isAdapterForType(java.
* lang.Object)
*/
@Override
public boolean isAdapterForType(Object type) {
return type == NodeContentAdapter.class;
}
}

View file

@ -12,6 +12,7 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
@ -137,5 +138,33 @@ public class NodeUtil {
}
return null;
}
public static CompositeNode findLastCompositeGrandChild(CompositeNode parentNode) {
EList<AbstractNode> children = parentNode.getChildren();
for(int i=children.size()-1; i>=0; --i) {
AbstractNode child = children.get(i);
if (child instanceof CompositeNode) {
return findLastCompositeGrandChild((CompositeNode) child);
}
}
return parentNode;
}
public static void checkOffsetConsistency(CompositeNode rootNode) {
int currentOffset = rootNode.getOffset();
for(AbstractNode child:rootNode.getChildren()) {
if(child.getOffset() != currentOffset) {
throw new IllegalStateException("Invalid offset: Should be " + currentOffset + " but is " + child.getOffset() + "\n" + child.serialize());
}
if(child instanceof CompositeNode) {
checkOffsetConsistency((CompositeNode) child);
}
int serializedLength = child.serialize().length();
if(child.getLength() != serializedLength) {
throw new IllegalStateException("Invalid length: Should be " + serializedLength + " but is " + child.getLength() + "\n" + child.serialize());
}
currentOffset += serializedLength;
}
}
}

View file

@ -0,0 +1,175 @@
/*******************************************************************************
* Copyright (c) 2008 itemis AG (http://www.itemis.eu) 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.parsetree;
import junit.framework.TestCase;
/**
* @author Jan Köhnlein - Initial contribution and API
*/
public class NodeContentAdapterTest extends TestCase {
private static final String TEXT0 = "Tests\n";
private static final String TEXT1 = "are\n";
private static final String TEXT2 = "so\n";
private static final String TEXT3 = "great\n";
private static final String TEXT4 = "not\n";
private CompositeNode root;
private CompositeNode comp0;
private CompositeNode comp1;
private LeafNode leaf0;
private LeafNode leaf1;
private LeafNode leaf2;
private LeafNode leaf3;
private NodeContentAdapter contentAdapter;
/**
* root +- leaf0
* +- comp0 +- leaf1
* +- comp1 +- leaf2
* +- leaf3
*/
@Override
protected void setUp() throws Exception {
root = ParsetreeFactory.eINSTANCE.createCompositeNode();
contentAdapter = new NodeContentAdapter();
}
private void createTree(CompositeNode root) {
comp0 = ParsetreeFactory.eINSTANCE.createCompositeNode();
comp1 = ParsetreeFactory.eINSTANCE.createCompositeNode();
leaf0 = ParsetreeFactory.eINSTANCE.createLeafNode();
leaf1 = ParsetreeFactory.eINSTANCE.createLeafNode();
leaf2 = ParsetreeFactory.eINSTANCE.createLeafNode();
leaf3 = ParsetreeFactory.eINSTANCE.createLeafNode();
leaf0.setText(TEXT0);
leaf1.setText(TEXT1);
leaf2.setText(TEXT2);
leaf3.setText(TEXT3);
root.getChildren().add(leaf0);
root.getChildren().add(comp0);
comp0.getChildren().add(leaf1);
root.getChildren().add(comp1);
comp1.getChildren().add(leaf2);
root.getChildren().add(leaf3);
}
public void testAdaptContainment() throws Exception {
createTree(root);
root.eAdapters().add(contentAdapter);
assertInitialSetting();
}
public void testAdaptOnAdd() throws Exception {
root.eAdapters().add(contentAdapter);
createTree(root);
assertInitialSetting();
}
private void assertInitialSetting() {
assertTrue(comp0.eAdapters().contains(contentAdapter));
assertTrue(comp1.eAdapters().contains(contentAdapter));
assertTrue(leaf0.eAdapters().contains(contentAdapter));
assertTrue(leaf1.eAdapters().contains(contentAdapter));
assertTrue(leaf2.eAdapters().contains(contentAdapter));
assertTrue(leaf3.eAdapters().contains(contentAdapter));
assertEquals(0, root.getOffset());
assertEquals(0, leaf0.getOffset());
assertEquals(TEXT0.length(), comp0.getOffset());
assertEquals(TEXT0.length(), leaf1.getOffset());
assertEquals(TEXT0.length() + TEXT1.length(), comp1.getOffset());
assertEquals(TEXT0.length() + TEXT1.length(), leaf2.getOffset());
assertEquals(TEXT0.length() + TEXT1.length() + TEXT2.length(), leaf3.getOffset());
assertEquals(TEXT0.length() + TEXT1.length() + TEXT2.length() + TEXT3.length(), root.getLength());
assertEquals(TEXT0.length(), leaf0.getLength());
assertEquals(TEXT1.length(), comp0.getLength());
assertEquals(TEXT1.length(), leaf1.getLength());
assertEquals(TEXT2.length(), comp1.getLength());
assertEquals(TEXT2.length(), leaf2.getLength());
assertEquals(TEXT3.length(), leaf3.getLength());
assertEquals(1, root.getLine());
assertEquals(1, leaf0.getLine());
assertEquals(2, comp0.getLine());
assertEquals(2, leaf1.getLine());
assertEquals(3, comp1.getLine());
assertEquals(3, leaf2.getLine());
assertEquals(4, leaf3.getLine());
}
public void testRemove() throws Exception {
createTree(root);
root.eAdapters().add(contentAdapter);
comp0.getChildren().remove(leaf1);
assertEquals(0, root.getOffset());
assertEquals(0, leaf0.getOffset());
assertEquals(TEXT0.length(), comp0.getOffset());
assertEquals(TEXT0.length(), comp1.getOffset());
assertEquals(TEXT0.length(), leaf2.getOffset());
assertEquals(TEXT0.length() + TEXT2.length(), leaf3.getOffset());
assertEquals(TEXT0.length() + TEXT2.length() + TEXT3.length(), root.getLength());
assertEquals(TEXT0.length(), leaf0.getLength());
assertEquals(0, comp0.getLength());
assertEquals(TEXT2.length(), comp1.getLength());
assertEquals(TEXT2.length(), leaf2.getLength());
assertEquals(TEXT3.length(), leaf3.getLength());
assertEquals(1, root.getLine());
assertEquals(1, leaf0.getLine());
assertEquals(2, comp0.getLine());
assertEquals(2, comp1.getLine());
assertEquals(2, leaf2.getLine());
assertEquals(3, leaf3.getLine());
}
public void testAdd() throws Exception {
createTree(root);
root.eAdapters().add(contentAdapter);
LeafNode leaf4 = ParsetreeFactory.eINSTANCE.createLeafNode();
leaf4.setText(TEXT4);
comp0.getChildren().add(0, leaf4);
assertEquals(0, root.getOffset());
assertEquals(0, leaf0.getOffset());
assertEquals(TEXT0.length(), comp0.getOffset());
assertEquals(TEXT0.length(), leaf4.getOffset());
assertEquals(TEXT0.length() + TEXT4.length(), leaf1.getOffset());
assertEquals(TEXT0.length() + TEXT1.length() + TEXT4.length(), comp1.getOffset());
assertEquals(TEXT0.length() + TEXT1.length() + TEXT4.length(), leaf2.getOffset());
assertEquals(TEXT0.length() + TEXT1.length() + TEXT2.length() + TEXT4.length(), leaf3.getOffset());
assertEquals(TEXT0.length() + TEXT1.length() + TEXT2.length() + TEXT3.length() + TEXT4.length(), root.getLength());
assertEquals(TEXT0.length(), leaf0.getLength());
assertEquals(TEXT4.length() + TEXT1.length(), comp0.getLength());
assertEquals(TEXT4.length(), leaf4.getLength());
assertEquals(TEXT1.length(), leaf1.getLength());
assertEquals(TEXT2.length(), comp1.getLength());
assertEquals(TEXT2.length(), leaf2.getLength());
assertEquals(TEXT3.length(), leaf3.getLength());
assertEquals(1, root.getLine());
assertEquals(1, leaf0.getLine());
assertEquals(2, comp0.getLine());
assertEquals(2, leaf4.getLine());
assertEquals(3, leaf1.getLine());
assertEquals(4, comp1.getLine());
assertEquals(4, leaf2.getLine());
assertEquals(5, leaf3.getLine());
}
}