org.eclipse.xtext.nodemodel.impl.RootNode Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2010 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.nodemodel.impl;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import com.google.common.collect.Lists;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public class RootNode extends CompositeNodeWithSemanticElementAndSyntaxError {
private String completeContent;
private int[] lineBreakOffsets;
/**
* @return null
the root node does not have any parent.
*/
@Override
public CompositeNode getParent() {
return null;
}
@Override
public ICompositeNode getRootNode() {
return this;
}
@Override
public int getTotalOffset() {
return 0;
}
@Override
public int getTotalLength() {
return getCompleteContent().length();
}
@Override
public String getText() {
return getCompleteContent();
}
public int getIndex() {
return 0;
}
protected void basicSetCompleteContent(String completeContent) {
this.completeContent = completeContent;
this.lineBreakOffsets = computeLineBreaks(completeContent);
}
/**
* Returns an array that contains the offsets of each line break in the input.
* Note that the result is not a copy but the actually internal data structure of
* this node.
* @return an array of offsets of each line break in the input or null
* if the {@link #completeContent} has not been set.
* @since 2.0
*/
protected int[] basicGetLineBreakOffsets() {
return lineBreakOffsets;
}
public String getCompleteContent() {
return completeContent;
}
@Override
public INode getNextSibling() {
return null;
}
@Override
public INode getPreviousSibling() {
return null;
}
@Override
protected AbstractNode basicGetNextSibling() {
return this;
}
@Override
protected AbstractNode basicGetPreviousSibling() {
return this;
}
@Override
protected boolean basicHasPreviousSibling() {
return false;
}
@Override
protected boolean basicHasNextSibling() {
return false;
}
@Override
public boolean hasPreviousSibling() {
return false;
}
@Override
public boolean hasNextSibling() {
return false;
}
@Override
public boolean hasSiblings() {
return false;
}
@Override
protected void basicSetNextSibling(AbstractNode next) {
throw new UnsupportedOperationException();
}
@Override
protected void basicSetPreviousSibling(AbstractNode prev) {
throw new UnsupportedOperationException();
}
@Override
protected void basicSetParent(CompositeNode parent) {
throw new UnsupportedOperationException();
}
/**
* Computes the line breaks in the given text and returns an array of offsets.
* A line break is either \r\n
, \n
, or a single \r
.
* This implementation was heavily adapted from org.eclipse.jface.text.DefaultLineTracker
.
* @param text the text whose line-breaks should be computed. May not be null
.
* @return the array of line-break offsets in the given text. May be empty but is never null
.
* @since 2.0
*/
protected int[] computeLineBreaks(String text) {
List list = Lists.newArrayListWithExpectedSize(50);
char ch;
int length= text.length();
for (int i= 0; i < length; i++) {
ch= text.charAt(i);
if (ch == '\r') {
list.add(i);
if (i + 1 < length) {
if (text.charAt(i + 1) == '\n') {
i++;
}
}
} else if (ch == '\n') {
list.add(i);
}
}
int[] result = new int[list.size()];
for(int i = 0; i < result.length; i++) {
result[i] = list.get(i).intValue();
}
return result;
}
@Override
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
super.readData(in, context);
basicSetCompleteContent(context.getCompleteContent());
int totalLength = fixupOffsets(this, 0);
if (totalLength != getCompleteContent().length()) {
throw new IllegalStateException("The length of the resource's content was " + getCompleteContent().length()
+ " but the length calculated based upon the serialized form of the RootNode was " + totalLength);
}
}
private int fixupOffsets(INode node, int nodeOffset) {
if (node instanceof LeafNode) {
LeafNode leafNode = (LeafNode) node;
leafNode.basicSetTotalOffset(nodeOffset);
return leafNode.getTotalLength() + nodeOffset;
}
if (node instanceof CompositeNode) {
CompositeNode compositeNode = (CompositeNode) node;
int currentOffset = nodeOffset;
AbstractNode firstChild = compositeNode.basicGetFirstChild();
if (firstChild != null) {
AbstractNode it = firstChild;
do {
currentOffset = fixupOffsets(it, currentOffset);
it = it.basicGetNextSibling();
} while (it != firstChild);
}
return currentOffset;
}
return 0;
}
@Override
NodeType getNodeId() {
return NodeType.RootNode;
}
/**
* @since 2.3
* @noreference This method is not intended to be referenced by clients.
*/
public void fillGrammarElementToIdMap(Map grammarElementToIdMap,
List grammarIdToURIMap) {
fillGrammarElementToIdMap(0, grammarElementToIdMap, grammarIdToURIMap);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy