Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 347419

Summary: CrossReferenceSerializer ignores existing INode while serializing
Product: [Modeling] TMF Reporter: Mark Christiaens <mark.g.j.christiaens>
Component: XtextAssignee: Project Inbox <tmf.xtext-inbox>
Status: CLOSED DUPLICATE QA Contact:
Severity: normal    
Priority: P3 CC: knut.wannheden, mark.g.j.christiaens
Version: 2.0.0   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:

Description Mark Christiaens CLA 2011-05-27 05:06:20 EDT
Build Identifier: 20110301-1815

From time to time, the org.eclipse.xtext.parsetree.reconstr.impl.CrossReferenceSerializer does not use the existing node model while serializing although it is valid to do so.  The cause seems to be this code: 

	public String serializeCrossRef(EObject context, CrossReference grammarElement, EObject target, INode node) {
		final EReference ref = GrammarUtil.getReference(grammarElement, context.eClass());
		String text = null;
		if (node != null) {
			List<EObject> objects = linkingService.getLinkedObjects(context, ref, node);
			if (objects.contains(target))
				return ITokenSerializer.KEEP_VALUE_FROM_NODE_MODEL;
		}
		text = getUnconvertedLinkText(target, ref, context);
		if (text != null)
			return getConvertedValue(text, grammarElement);
		if (node != null) {
			return linkingHelper.getCrossRefNodeAsString(node, false);
		}
		return null;
	}

I debugged the execution of this piece of code and what is happening is:
linkingService.getLinkedObject (...) returns a list with one PROXY object pointing to the declaration of the thing that needs to be serialized.  Note, it's a proxy and not a regular EMF object.  I think that is fine and to be expected according to the contract of the linking service.
then if (objects.contains(target)) fails because the target is an actual object and not a proxy.  
So, I was thinking that it makes sense to replace #serializeCrossRef with:

	private String oldSerializeCrossRef(EObject context,
			CrossReference grammarElement, EObject target, INode node) {
		final EReference ref = GrammarUtil.getReference(grammarElement, context.eClass());
		String text = null;
		if (node != null) {
			List<EObject> objects = linkingService.getLinkedObjects(context, ref, node);
			final URI targetUri = EcoreUtil.getURI(target);
			
			for (EObject object : objects) {
				final URI objectUri = EcoreUtil.getURI(object);
				if (targetUri.equals(objectUri)) {
					return ITokenSerializer.KEEP_VALUE_FROM_NODE_MODEL;
				}
			}
		}
		
		text = getUnconvertedLinkText(target, ref, context);
		if (text != null)
			return getConvertedValue(text, grammarElement);
		if (node != null) {
			return linkingHelper.getCrossRefNodeAsString(node, false);
		}
		return null;
	}

Reproducible: Always
Comment 1 Mark Christiaens CLA 2011-05-27 05:06:55 EDT
I'm using Xtext 2.0 M7
Comment 2 Knut Wannheden CLA 2011-05-27 05:53:01 EDT
This seems to be a duplicate of 325435. I had almost completely forgotten about this one :-) As a workaround we use our own subclass which also compares the object's URI.

*** This bug has been marked as a duplicate of bug 325435 ***