[bug 489547] Allow to provide offset and length for

SyntheticLinkingLeafNode

Change-Id: I4d723aa426e4f09a48cbee2187e98c5d60900920
Signed-off-by: akosyakov <anton.kosyakov@typefox.io>
This commit is contained in:
akosyakov 2016-03-16 13:44:19 +01:00
parent 21096429a2
commit 7baa4b3d69
2 changed files with 115 additions and 166 deletions

View file

@ -7,23 +7,17 @@
*******************************************************************************/
package org.eclipse.xtext.linking.lazy;
import static java.util.Collections.*;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.XtextFactory;
import org.eclipse.xtext.nodemodel.BidiTreeIterable;
import org.eclipse.xtext.nodemodel.BidiTreeIterator;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
import org.eclipse.xtext.nodemodel.util.NodeTreeIterator;
import org.eclipse.xtext.nodemodel.util.ReversedBidiTreeIterable;
import org.eclipse.xtext.util.ITextRegion;
import org.eclipse.xtext.util.ITextRegionWithLineInformation;
import org.eclipse.xtext.util.TextRegion;
import org.eclipse.xtext.util.TextRegionWithLineInformation;
import org.eclipse.xtext.nodemodel.impl.CompositeNode;
import org.eclipse.xtext.nodemodel.impl.LeafNode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.parser.IParseResult;
import org.eclipse.xtext.resource.XtextResource;
import com.google.inject.Inject;
@ -39,179 +33,99 @@ public class SyntheticLinkingSupport {
private LazyLinker lazyLinker;
public void createAndSetProxy(EObject obj, EReference eRef, String crossRefString) {
lazyLinker.createAndSetProxy(obj, new SyntheticLinkingLeafNode(obj, crossRefString), eRef);
createAndSetProxy(obj, eRef, crossRefString, 0, 1);
}
/**
* @since 2.10
*/
public void createAndSetProxy(EObject obj, EReference eRef, String crossRefString, int offset, int length) {
INode crossReferenceNode = createCrossReferenceNode(obj, eRef, crossRefString, offset, length);
lazyLinker.createAndSetProxy(obj, crossReferenceNode, eRef);
}
/**
* @since 2.10
*/
protected INode createCrossReferenceNode(EObject obj, EReference eRef, String crossRefString, int offset, int length) {
CompositeNode parent = getParent(obj, eRef, crossRefString, offset, length);
EObject grammarElement = getGrammarElement(obj, eRef, crossRefString, offset, length);
return new SyntheticLinkingLeafNode(obj, crossRefString, offset, length, grammarElement, parent);
}
/**
* @since 2.10
*/
protected EObject getGrammarElement(EObject obj, EReference eRef, String crossRefString, int offset, int length) {
return XtextFactory.eINSTANCE.createKeyword();
}
/**
* @since 2.10
*/
protected CompositeNode getParent(EObject obj, EReference eRef, String crossRefString, int offset, int length) {
ICompositeNode node = NodeModelUtils.getNode(obj);
if (node != null) {
ICompositeNode rootNode = node.getRootNode();
if (rootNode instanceof CompositeNode)
return (CompositeNode) rootNode;
}
Resource resource = obj.eResource();
if (resource instanceof XtextResource) {
IParseResult parseResult = ((XtextResource) resource).getParseResult();
if (parseResult != null) {
ICompositeNode rootNode = parseResult.getRootNode();
if (rootNode instanceof CompositeNode)
return (CompositeNode) rootNode;
}
}
return null;
}
}
class SyntheticLinkingLeafNode implements ILeafNode, BidiTreeIterable<INode> {
private final static int OFFSET = 0;
private final static int LENGTH = 1;
private final static int LINE = -1;
class SyntheticLinkingLeafNode extends LeafNode {
private final String text;
private final EObject grammarElement;
private final EObject semanticElement;
public SyntheticLinkingLeafNode(EObject semanticElement, String text) {
public SyntheticLinkingLeafNode(EObject semanticElement, String text, int offset, int length, EObject grammarElement, CompositeNode parent) {
this.text = text;
this.semanticElement = semanticElement;
this.grammarElement = XtextFactory.eINSTANCE.createKeyword();
}
@Override
public ICompositeNode getParent() {
return null;
basicSetTotalOffset(offset);
basicSetTotalLength(length);
basicSetGrammarElement(grammarElement);
basicSetParent(parent);
}
@Override
public boolean hasSiblings() {
return false;
}
@Override
public boolean hasPreviousSibling() {
return false;
}
@Override
public boolean hasNextSibling() {
return false;
}
@Override
public INode getPreviousSibling() {
return null;
}
@Override
public INode getNextSibling() {
return null;
}
@Override
public ICompositeNode getRootNode() {
return null;
}
@Override
public Iterable<ILeafNode> getLeafNodes() {
return emptyList();
}
@Override
public int getTotalOffset() {
return OFFSET;
}
@Override
public int getOffset() {
return OFFSET;
}
@Override
public int getTotalLength() {
return LENGTH;
}
@Override
public int getLength() {
return LENGTH;
}
@Override
public int getTotalEndOffset() {
return LENGTH;
}
@Override
public int getEndOffset() {
return LENGTH;
}
@Override
public int getTotalStartLine() {
return LINE;
}
@Override
public int getStartLine() {
return LINE;
}
@Override
public int getTotalEndLine() {
return LINE;
}
@Override
public int getEndLine() {
return LINE;
}
@Override
public String getText() {
return text;
}
@Override
public EObject getGrammarElement() {
return grammarElement;
}
@Override
public EObject getSemanticElement() {
return semanticElement;
}
@Override
public boolean hasDirectSemanticElement() {
return true;
}
@Override
public SyntaxErrorMessage getSyntaxErrorMessage() {
return null;
}
@Override
public BidiTreeIterable<INode> getAsTreeIterable() {
return this;
protected EObject basicGetSemanticElement() {
return semanticElement;
}
@Override
public BidiTreeIterator<INode> iterator() {
return new NodeTreeIterator(this);
protected boolean basicHasSiblings() {
return false;
}
@Override
public BidiTreeIterable<INode> reverse() {
return new ReversedBidiTreeIterable<INode>(this);
protected boolean basicHasNextSibling() {
return false;
}
@Override
public ITextRegion getTextRegion() {
return new TextRegion(OFFSET, LENGTH);
}
@Override
public ITextRegion getTotalTextRegion() {
return new TextRegion(OFFSET, LENGTH);
}
@Override
public ITextRegionWithLineInformation getTextRegionWithLineInformation() {
return new TextRegionWithLineInformation(OFFSET, LENGTH, LINE, LINE);
}
@Override
public ITextRegionWithLineInformation getTotalTextRegionWithLineInformation() {
return new TextRegionWithLineInformation(OFFSET, LENGTH, LINE, LINE);
}
@Override
public boolean isHidden() {
protected boolean basicHasPreviousSibling() {
return false;
}

View file

@ -16,7 +16,10 @@ import org.eclipse.xtext.linking.importedURI.ImportedURIPackage;
import org.eclipse.xtext.linking.importedURI.Main;
import org.eclipse.xtext.linking.importedURI.Type;
import org.eclipse.xtext.linking.lazy.SyntheticLinkingSupport;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.resource.XtextResourceSet;
import org.eclipse.xtext.util.LineAndColumn;
import org.junit.Test;
/**
@ -43,32 +46,64 @@ public class Bug437669Test extends AbstractXtextTests {
}
@Test
public void testUnresolved() {
public void testUnresolved_01() {
Type type = resolve("BlaBlaBla");
Resource resource = type.eResource();
assertEquals(resource.getErrors().toString(), 1, resource.getErrors().size());
Diagnostic diagnostic = (Diagnostic) resource.getErrors().get(0);
assertEquals(-1, diagnostic.getLine());
assertEquals(0, diagnostic.getOffset());
assertEquals(1, diagnostic.getLength());
assertEquals(1, diagnostic.getLine());
assertEquals(1, diagnostic.getColumn());
assertEquals("Couldn't resolve reference to Type 'BlaBlaBla'.", diagnostic.getMessage());
}
private Type resolve(String text) {
@Test
public void testUnresolved_02() {
Type type = getContext();
INode nameNode = NodeModelUtils.findNodesForFeature(type, ImportedURIPackage.Literals.TYPE__NAME).get(0);
resolve(type, "BlaBlaBla", nameNode.getOffset(), nameNode.getLength());
Resource resource = type.eResource();
assertEquals(resource.getErrors().toString(), 1, resource.getErrors().size());
LineAndColumn lineAndColumn = NodeModelUtils.getLineAndColumn(nameNode, nameNode.getOffset());
Diagnostic diagnostic = (Diagnostic) resource.getErrors().get(0);
assertEquals(nameNode.getOffset(), diagnostic.getOffset());
assertEquals(nameNode.getLength(), diagnostic.getLength());
assertEquals(lineAndColumn.getLine(), diagnostic.getLine());
assertEquals(lineAndColumn.getColumn(), diagnostic.getColumn());
assertEquals("Couldn't resolve reference to Type 'BlaBlaBla'.", diagnostic.getMessage());
}
protected Type resolve(String text) {
Type type = getContext();
return resolve(type, text);
}
protected Type resolve(Type type, String text) {
SyntheticLinkingSupport syntheticLinkingSupport = get(SyntheticLinkingSupport.class);
syntheticLinkingSupport.createAndSetProxy(type, ImportedURIPackage.Literals.TYPE__EXTENDS, text);
EcoreUtil.resolveAll(type.eResource().getResourceSet());
return type;
}
protected Type resolve(Type type, String text, int offset, int length) {
SyntheticLinkingSupport syntheticLinkingSupport = get(SyntheticLinkingSupport.class);
syntheticLinkingSupport.createAndSetProxy(type, ImportedURIPackage.Literals.TYPE__EXTENDS, text, offset, length);
EcoreUtil.resolveAll(type.eResource().getResourceSet());
return type;
}
protected Type getContext() {
XtextResourceSet resourceSet = get(XtextResourceSet.class);
resourceSet.setClasspathURIContext(getClass().getClassLoader());
URI uri = URI.createURI("classpath:/org/eclipse/xtext/linking/02.importuritestlanguage");
Resource resource = resourceSet.getResource(uri, true);
Main main = (Main) resource.getContents().get(0);
Type type = main.getTypes().get(0);
SyntheticLinkingSupport syntheticLinkingSupport = get(SyntheticLinkingSupport.class);
syntheticLinkingSupport.createAndSetProxy(type, ImportedURIPackage.Literals.TYPE__EXTENDS, text);
EcoreUtil.resolveAll(resourceSet);
return type;
return main.getTypes().get(0);
}
}