Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 338655 - erroneous "Cyclic resolution of lazy links"
Summary: erroneous "Cyclic resolution of lazy links"
Status: CLOSED WORKSFORME
Alias: None
Product: TMF
Classification: Modeling
Component: Xtext (show other bugs)
Version: 2.0.0   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-03-02 07:07 EST by Henrik Rentz-Reichert CLA
Modified: 2011-04-07 04:49 EDT (History)
3 users (show)

See Also:


Attachments
Simple model to reproduce bug (367 bytes, application/octet-stream)
2011-03-02 07:07 EST, Henrik Rentz-Reichert CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Henrik Rentz-Reichert CLA 2011-03-02 07:07:22 EST
Created attachment 190133 [details]
Simple model to reproduce bug

In eTrice after migrating from Xtext 1.0.1 to 2.0.0 in fairly simple models a problem with link resolution occurs.

I have attached a simple model to reproduce the bug.
The problem can be reproduced with
HEAD of http://git.eclipse.org/c/etrice/org.eclipse.etrice.git/

When the // in front of RefinedState is removed an exception is thrown:

java.lang.AssertionError: Cyclic resolution of lazy links : RefinedState.base->ActorClass.base->RefinedState.base
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(LazyLinkingResource.java:159)
	at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getEObject(ResourceSetImpl.java:219)
	at org.eclipse.emf.ecore.util.EcoreUtil.resolve(EcoreUtil.java:202)
	at org.eclipse.emf.ecore.util.EcoreUtil.resolve(EcoreUtil.java:262)
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eResolveProxy(BasicEObjectImpl.java:1483)
	at org.eclipse.etrice.core.room.impl.RefinedStateImpl.getBase(RefinedStateImpl.java:76)
	at org.eclipse.etrice.core.naming.RoomQualifiedNameProvider.qualifiedName(RoomQualifiedNameProvider.java:30)
	at sun.reflect.GeneratedMethodAccessor56.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:288)
	at org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider$2.get(DefaultDeclarativeQualifiedNameProvider.java:61)
	at org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider$2.get(DefaultDeclarativeQualifiedNameProvider.java:1)
	at org.eclipse.xtext.util.OnChangeEvictingCache.get(OnChangeEvictingCache.java:46)
	at org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider.getFullyQualifiedName(DefaultDeclarativeQualifiedNameProvider.java:57)
	at org.eclipse.xtext.naming.IQualifiedNameProvider$AbstractImpl.apply(IQualifiedNameProvider.java:31)
	at org.eclipse.xtext.naming.IQualifiedNameProvider$AbstractImpl.apply(IQualifiedNameProvider.java:1)
	at org.eclipse.xtext.scoping.Scopes$2.apply(Scopes.java:90)
	at org.eclipse.xtext.scoping.Scopes$2.apply(Scopes.java:1)
	at com.google.common.collect.Iterators$8.next(Iterators.java:697)
	at com.google.common.collect.Iterators$7.computeNext(Iterators.java:602)
	at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:135)
	at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:130)
	at org.eclipse.xtext.scoping.impl.MultimapBasedSelectable.setExportedObjects(MultimapBasedSelectable.java:97)
	at org.eclipse.xtext.scoping.impl.MultimapBasedSelectable.<init>(MultimapBasedSelectable.java:36)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.internalGetImportedNamespaceResolvers(ImportedNamespaceAwareLocalScopeProvider.java:203)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider$2.get(ImportedNamespaceAwareLocalScopeProvider.java:191)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider$2.get(ImportedNamespaceAwareLocalScopeProvider.java:1)
	at org.eclipse.xtext.util.OnChangeEvictingCache.get(OnChangeEvictingCache.java:46)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getAllDescriptions(ImportedNamespaceAwareLocalScopeProvider.java:189)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getResourceScope(ImportedNamespaceAwareLocalScopeProvider.java:110)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getResourceScope(ImportedNamespaceAwareLocalScopeProvider.java:99)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getScope(ImportedNamespaceAwareLocalScopeProvider.java:87)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getScope(ImportedNamespaceAwareLocalScopeProvider.java:85)
	at org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.delegateGetScope(AbstractDeclarativeScopeProvider.java:72)
	at org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.getScope(AbstractDeclarativeScopeProvider.java:102)
	at org.eclipse.xtext.linking.impl.DefaultLinkingService.getScope(DefaultLinkingService.java:56)
	at org.eclipse.xtext.linking.impl.DefaultLinkingService.getLinkedObjects(DefaultLinkingService.java:110)
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(LazyLinkingResource.java:170)
	at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getEObject(ResourceSetImpl.java:219)
	at org.eclipse.emf.ecore.util.EcoreUtil.resolve(EcoreUtil.java:202)
	at org.eclipse.emf.ecore.util.EcoreUtil.resolve(EcoreUtil.java:262)
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eResolveProxy(BasicEObjectImpl.java:1483)
	at org.eclipse.etrice.core.room.impl.ActorClassImpl.getBase(ActorClassImpl.java:245)
	at org.eclipse.etrice.core.scoping.RoomScopeProvider.scope_RefinedState_base(RoomScopeProvider.java:568)
	at sun.reflect.GeneratedMethodAccessor57.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:288)
	at org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.polymorphicFindScopeForReferenceName(AbstractDeclarativeScopeProvider.java:136)
	at org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.getScope(AbstractDeclarativeScopeProvider.java:98)
	at org.eclipse.xtext.linking.impl.DefaultLinkingService.getScope(DefaultLinkingService.java:56)
	at org.eclipse.xtext.linking.impl.DefaultLinkingService.getLinkedObjects(DefaultLinkingService.java:110)
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(LazyLinkingResource.java:170)
	at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getEObject(ResourceSetImpl.java:219)
	at org.eclipse.emf.ecore.util.EcoreUtil.resolve(EcoreUtil.java:202)
	at org.eclipse.emf.ecore.util.EcoreUtil.resolve(EcoreUtil.java:262)
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eResolveProxy(BasicEObjectImpl.java:1483)
	at org.eclipse.etrice.core.room.impl.RefinedStateImpl.getBase(RefinedStateImpl.java:76)
	at org.eclipse.etrice.core.room.impl.RefinedStateImpl.eGet(RefinedStateImpl.java:120)
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eGet(BasicEObjectImpl.java:1021)
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eGet(BasicEObjectImpl.java:1013)
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eGet(BasicEObjectImpl.java:1008)
	at org.eclipse.xtext.resource.EObjectAtOffsetHelper.resolveCrossReferencedElement(EObjectAtOffsetHelper.java:59)
	at org.eclipse.xtext.resource.EObjectAtOffsetHelper.internalResolveElementAt(EObjectAtOffsetHelper.java:43)
	at org.eclipse.xtext.resource.EObjectAtOffsetHelper.resolveCrossReferencedElementAt(EObjectAtOffsetHelper.java:34)
	at org.eclipse.xtext.ui.editor.hyperlinking.HyperlinkHelper.createHyperlinksByOffset(HyperlinkHelper.java:78)
	at org.eclipse.xtext.ui.editor.hyperlinking.HyperlinkHelper.createHyperlinksByOffset(HyperlinkHelper.java:71)
	at org.eclipse.xtext.ui.editor.hyperlinking.DefaultHyperlinkDetector$1.exec(DefaultHyperlinkDetector.java:38)
	at org.eclipse.xtext.ui.editor.hyperlinking.DefaultHyperlinkDetector$1.exec(DefaultHyperlinkDetector.java:1)
	at org.eclipse.xtext.util.concurrent.AbstractReadWriteAcces.readOnly(AbstractReadWriteAcces.java:32)
	at org.eclipse.xtext.ui.editor.model.XtextDocument.readOnly(XtextDocument.java:86)
	at org.eclipse.xtext.ui.editor.hyperlinking.DefaultHyperlinkDetector.detectHyperlinks(DefaultHyperlinkDetector.java:36)
	at org.eclipse.jface.text.hyperlink.HyperlinkManager.findHyperlinks(HyperlinkManager.java:286)
	at org.eclipse.jface.text.hyperlink.HyperlinkManager.findHyperlinks(HyperlinkManager.java:258)
	at org.eclipse.jface.text.hyperlink.HyperlinkManager.mouseMove(HyperlinkManager.java:462)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:211)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4126)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3715)
	at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2697)
	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2661)
	at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2495)
	at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
Comment 1 Sebastian Zarnekow CLA 2011-03-02 07:52:51 EST
Please check whether your qualified name computation relies on resolved links.
Comment 2 Henrik Rentz-Reichert CLA 2011-03-02 08:41:28 EST
I've slightly changed my qualified name computation for refined states by additionally testing !base.eIsProxy()


    public QualifiedName qualifiedName(RefinedState rs) {
    	QualifiedName fqn = QualifiedName.create();
		BaseState base = rs.getBase();
		if (base!=null && !base.eIsProxy())
		{
			fqn = QualifiedName.create(base.getName());
			EObject parent = base.eContainer();
			while (parent instanceof BaseState) {
				fqn = QualifiedName.create(((BaseState)parent).getName()).append(fqn);
				parent = parent.eContainer();
			}
		}
		return fqn;
    }

But this didn't change the problem. The code is not even hit during reproduction and a complete removal of this method also didn't change the behavior.
Comment 3 Sebastian Zarnekow CLA 2011-03-02 09:17:47 EST
If rs.getBase() tries to resolve a proxy, you'll end up with a cylcic resolution. Are you sure that the offending line is not hit?
Comment 4 Henrik Rentz-Reichert CLA 2011-03-02 09:30:58 EST
(In reply to comment #3)
> If rs.getBase() tries to resolve a proxy, you'll end up with a cylcic
> resolution. Are you sure that the offending line is not hit?

Oops, you are right, it is hit. I had the breakpoint in the line following that.
But
- how can I avoid this problem? I never saw that in Xtext 1.0.1. Should I surround that with a try/catch?
- even for a valid model I encounter this cyclic reference: the qualified name provider tries to resolve the base of the RefinedState. This calls the scope provider which resolves the actor classes base class. During the resolution of this proxy the cycle is detected.

This is the simple most model to reproduce (by invoking validation):

RoomModel test {
	
	ActorClass Base {
		Behavior {
			StateMachine {
				State sBase {}
			}
		}
	}
	
	ActorClass Derived extends Base {
		Behavior {
			StateMachine {
				RefinedState sBase {}
			}
		}
	}
}
Comment 5 Sven Efftinge CLA 2011-03-26 15:24:30 EDT
It is usually not a good idea to rely on cross reference resolution within the qualified name provider.
Is that really necessary?

In Xtext 2.0 the code which throws the CyclicResolutionException has been put into a template method so you could override it try to handle this case differently. But the real source of the problems is that the qualified name provider relies on resolving cross references.

Sorry, that we cannot do much about it.
Comment 6 Henrik Rentz-Reichert CLA 2011-03-28 10:43:18 EDT
Thanks Sven,

I think I can drop the qualified name computation for the RefinedState and ensure to have no duplicate names by validation.
So far that seems to work.

However, why was this no problem in Xtext 1.0.1?
I really haven't understood where in my example should be a cycle...

-Henrik

(In reply to comment #5)
> It is usually not a good idea to rely on cross reference resolution within the
> qualified name provider.
> Is that really necessary?
> 
> In Xtext 2.0 the code which throws the CyclicResolutionException has been put
> into a template method so you could override it try to handle this case
> differently. But the real source of the problems is that the qualified name
> provider relies on resolving cross references.
> 
> Sorry, that we cannot do much about it.
Comment 7 Sven Efftinge CLA 2011-03-28 23:57:29 EDT
(In reply to comment #6)
> However, why was this no problem in Xtext 1.0.1?

I should have been a problem with Xtext 1.0 as well.

> I really haven't understood where in my example should be a cycle...

The problem is that the scope provider uses the ResourceDescriptionManager to compute the IEObjectDescription. If you resolve cross references during computation of IEObjectDescription (qualified name provider is used internally) the computation itself needs scoping. That again needs IEObjectDescriptions, etc.... bang.
Comment 8 Henrik Rentz-Reichert CLA 2011-04-06 09:39:50 EDT
(In reply to comment #7)
> (In reply to comment #6)
> > However, why was this no problem in Xtext 1.0.1?
> 
> I should have been a problem with Xtext 1.0 as well.

No, definitely not!

The following example validates perfectly using Xtext 1.0.1 using the above mentioned qualified name provider.
No duplicate name errors and valid cross references.
Btw: the qualified name provider is called exactly once per RefinedState during validation (e.g. when the model changes) and the cross references already are resolved at the time of invocation.
On the other hand in Xtext 2.0 the cross references are not (yet) resolved when the qualified name provider is invoked.

org.eclipse.xtext.resource.impl.DefaultResourceDescription.computeExportedObjects()

RoomModel inherit {

	ActorClass Base {
		Behavior {
			StateMachine {
				State base0
				State base1 {
					subgraph {
						State nested
					}
				}
			}
		}
	}

	ActorClass Derived extends Base {
		Behavior {
			StateMachine {
				RefinedState base0 {
					subgraph {
						State added
						State also_added
					}
				}
				RefinedState base1 {
					subgraph {
						State added
					}
				}
				RefinedState base1.nested {
					subgraph {
						State added
					}
				}
			}
		}
	}
}
Comment 9 Henrik Rentz-Reichert CLA 2011-04-06 09:50:08 EDT
I should have mentioned that in Xtext 2.0 without the qualified name provider for refined states the reference in
RefinedState base1.nested
can not be resolved - even though content assist proposed and inserted it.

I wouldn't insist on this point if I came along without that. But I realized that I don't know how I can solve the problems described in this and the last comment.

Please see also my post http://www.eclipse.org/forums/index.php?t=msg&th=207306&start=0&S=0fae87a01ef3645ea840e9b722d7b204
Comment 10 Sven Efftinge CLA 2011-04-07 04:49:18 EDT
I've responded to the mentioned newsgroup thread.