Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » implementing QualifiedNameProvider
implementing QualifiedNameProvider [message #1782012] Thu, 15 February 2018 23:53 Go to next message
Ruchika Kumar is currently offline Ruchika KumarFriend
Messages: 50
Registered: January 2017
Member
Hello,

I'm having trouble with using and implementing my own QualifiedNameProvider to reference model elements without a name attribute for cross-referencing. I have looked online for resources, such as:

https://christiandietrich.wordpress.com/tag/iqualifiednameprovider/
https://stackoverflow.com/questions/10316112/xtext-cross-reference-using-custom-terminal-rule
https://www.eclipse.org/forums/index.php/t/1076818/
https://www.eclipse.org/forums/index.php/t/172914/

Unfortunately, I am still stuck after two days of tryng to find the bug. I tried to simplify and asbtract the problem from my main project as best I can to facilitate debugging. Hopefully, you can help me.

First off, the grammar:

grammar org.xtext.example.mydsl2.MyDsl with org.eclipse.xtext.common.Terminals

generate myDsl "http://www.xtext.org/example/mydsl2/MyDsl"

Model:
	(components+=Component | gates+=Gate)*
	(connections += Connection)*
	(interactions+=Interaction)*
;
		
Component:
	'component' name=ID ';'
;

Gate:
	'gate' name=ID ';'
;

Connection:
	'connect' gateReferences+=GateReference 'to' gateReferences+=GateReference ';'
;
	
GateReference:
	component=[Component] '.' gate=[Gate]
;
	
Interaction:
	source=[GateReference | FQN] 'sends' value=INT 'to' target=[GateReference | FQN] ';'
;

FQN: 
	ID ('.' ID)*
;


Now, the toy example:

component c1;
component c2;
gate g1;

connect c1.g1 to c2.g1; 

c1.g1 sends 5 to c2.g1;


In the textual connection specification, it finds and underlines errors in above, but suggests exactly those same names as quick fixes. See attached images for more information.

To fix the problem, I would like to reference a GateReference in an Interaction with the following name : componentName.gateName
To go about this, I tried defining my own QualifiedNameProvider, shown below:

package org.xtext.example.mydsl2.scoping;

import org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider;
import org.eclipse.xtext.naming.QualifiedName;
import org.xtext.example.mydsl2.myDsl.GateReference;

public class MyQNProvider extends DefaultDeclarativeQualifiedNameProvider {
	
	protected QualifiedName qualifiedName(GateReference gateReference) {		
		return QualifiedName.create(gateReference.getComponent().getName(), gateReference.getGate().getName());		
	}
}



Updated the RuntimeModule as well:
package org.xtext.example.mydsl2;


import org.eclipse.xtext.naming.IQualifiedNameProvider;
import org.xtext.example.mydsl2.scoping.MyQNProvider;

/**
 * Use this class to register components to be used at runtime / without the Equinox extension registry.
 */
public class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {
		public Class<? extends IQualifiedNameProvider> bindIQualifiedNameProvider() {
		return MyQNProvider.class;
	}
}


I implemented a scope for the elements to see if that was part of the problem:
/*
 * generated by Xtext 2.12.0
 */
package org.xtext.example.mydsl2.scoping;

import java.util.List;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.Scopes;
import org.xtext.example.mydsl2.myDsl.GateReference;
import org.xtext.example.mydsl2.myDsl.MyDslPackage;

import com.google.inject.Inject;

/**
 * This class contains custom scoping description.
 * 
 * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#scoping
 * on how and when to use it.
 */
public class MyDslScopeProvider extends AbstractMyDslScopeProvider {

	@Inject
	MyQNProvider nameProvider;
	
	@Override
	public IScope getScope(EObject context, EReference reference) {		
		if (context instanceof Interaction && 
				(reference == MyDslPackage.Literals.INTERACTION__SOURCE || reference == MyDslPackage.Literals.INTERACTION__TARGET)) {
			EObject root =  EcoreUtil2.getRootContainer(context);
			return Scopes.scopeFor(EcoreUtil2.getAllContentsOfType(root, GateReference.class), nameProvider, IScope.NULLSCOPE);
		}
		return super.getScope(context, reference);
	}
}


Alas, the code shown above doesn't work. I also receive this worker error:

2238 [Worker-1] ERROR org.eclipse.xtext.linking.lazy.LazyLinkingResource  - Cyclic resolution of lazy links : GateReference.component->GateReference.component in resource 'platform:/resource/testProject/src/src_gen/test.mydsl2'.
org.eclipse.xtext.linking.lazy.LazyLinkingResource$CyclicLinkingException: Cyclic resolution of lazy links : GateReference.component->GateReference.component in resource 'platform:/resource/testProject/src/src_gen/test.mydsl2'.
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.handleCyclicResolution(LazyLinkingResource.java:302)
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(LazyLinkingResource.java:240)
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(LazyLinkingResource.java:222)
	at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getEObject(ResourceSetImpl.java:223)
	at org.eclipse.emf.ecore.util.EcoreUtil.resolve(EcoreUtil.java:201)
	at org.eclipse.emf.ecore.util.EcoreUtil.resolve(EcoreUtil.java:261)
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eResolveProxy(BasicEObjectImpl.java:1477)
	at org.xtext.example.mydsl2.myDsl.impl.GateReferenceImpl.getComponent(GateReferenceImpl.java:86)
	at org.xtext.example.mydsl2.scoping.MyQNProvider.qualifiedName(MyQNProvider.java:10)
	at sun.reflect.GeneratedMethodAccessor40.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:302)
	at org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider$2.get(DefaultDeclarativeQualifiedNameProvider.java:64)
	at org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider$2.get(DefaultDeclarativeQualifiedNameProvider.java:59)
	at org.eclipse.xtext.util.OnChangeEvictingCache.get(OnChangeEvictingCache.java:77)
	at org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider.getFullyQualifiedName(DefaultDeclarativeQualifiedNameProvider.java:59)
	at org.eclipse.xtext.naming.IQualifiedNameProvider$AbstractImpl.apply(IQualifiedNameProvider.java:32)
	at org.eclipse.xtext.naming.IQualifiedNameProvider$AbstractImpl.apply(IQualifiedNameProvider.java:29)
	at org.eclipse.xtext.scoping.Scopes$2.apply(Scopes.java:93)
	at org.eclipse.xtext.scoping.Scopes$2.apply(Scopes.java:90)
	at com.google.common.collect.Iterators$7.transform(Iterators.java:750)
	at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47)
	at com.google.common.collect.Iterators$6.computeNext(Iterators.java:616)
	at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:145)
	at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:140)
	at org.eclipse.xtext.scoping.impl.MultimapBasedSelectable.setExportedObjects(MultimapBasedSelectable.java:106)
	at org.eclipse.xtext.scoping.impl.MultimapBasedSelectable.<init>(MultimapBasedSelectable.java:36)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.internalGetAllDescriptions(ImportedNamespaceAwareLocalScopeProvider.java:243)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider$2.get(ImportedNamespaceAwareLocalScopeProvider.java:230)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider$2.get(ImportedNamespaceAwareLocalScopeProvider.java:227)
	at org.eclipse.xtext.util.OnChangeEvictingCache.get(OnChangeEvictingCache.java:77)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getAllDescriptions(ImportedNamespaceAwareLocalScopeProvider.java:227)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getResourceScope(ImportedNamespaceAwareLocalScopeProvider.java:120)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getResourceScope(ImportedNamespaceAwareLocalScopeProvider.java:109)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getScope(ImportedNamespaceAwareLocalScopeProvider.java:97)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getScope(ImportedNamespaceAwareLocalScopeProvider.java:95)
	at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getScope(ImportedNamespaceAwareLocalScopeProvider.java:95)
	at org.eclipse.xtext.scoping.impl.DelegatingScopeProvider.delegateGetScope(DelegatingScopeProvider.java:42)
	at org.eclipse.xtext.scoping.impl.DelegatingScopeProvider.getScope(DelegatingScopeProvider.java:38)
	at org.xtext.example.mydsl2.scoping.MyDslScopeProvider.getScope(MyDslScopeProvider.java:36)
	at org.eclipse.xtext.linking.impl.DefaultLinkingService.getScope(DefaultLinkingService.java:59)
	at org.eclipse.xtext.linking.impl.DefaultLinkingService.getLinkedObjects(DefaultLinkingService.java:120)
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(LazyLinkingResource.java:247)
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(LazyLinkingResource.java:222)
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.doResolveLazyCrossReference(LazyLinkingResource.java:189)
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.resolveLazyCrossReference(LazyLinkingResource.java:148)
	at org.eclipse.xtext.linking.lazy.LazyLinkingResource.resolveLazyCrossReferences(LazyLinkingResource.java:134)
	at org.eclipse.xtext.EcoreUtil2.resolveLazyCrossReferences(EcoreUtil2.java:498)
	at org.eclipse.xtext.ui.editor.reconciler.XtextDocumentReconcileStrategy.postParse(XtextDocumentReconcileStrategy.java:175)
	at org.eclipse.xtext.ui.editor.reconciler.XtextDocumentReconcileStrategy.doReconcile(XtextDocumentReconcileStrategy.java:153)
	at org.eclipse.xtext.ui.editor.reconciler.XtextDocumentReconcileStrategy.reconcile(XtextDocumentReconcileStrategy.java:67)
	at org.eclipse.xtext.ui.editor.reconciler.XtextReconciler.doRun(XtextReconciler.java:449)
	at org.eclipse.xtext.ui.editor.reconciler.XtextReconciler.access$3(XtextReconciler.java:429)
	at org.eclipse.xtext.ui.editor.reconciler.XtextReconciler$1.process(XtextReconciler.java:363)
	at org.eclipse.xtext.ui.editor.reconciler.XtextReconciler$1.process(XtextReconciler.java:1)
	at org.eclipse.xtext.util.concurrent.IUnitOfWork$Void.exec(IUnitOfWork.java:37)
	at org.eclipse.xtext.resource.OutdatedStateManager.exec(OutdatedStateManager.java:91)
	at org.eclipse.xtext.ui.editor.model.XtextDocument$XtextDocumentLocker.modify(XtextDocument.java:428)
	at org.eclipse.xtext.ui.editor.model.XtextDocument.internalModify(XtextDocument.java:162)
	at org.eclipse.xtext.ui.editor.reconciler.XtextReconciler.run(XtextReconciler.java:360)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:56)


A note: in my original project, I'm importing an ecore model and am not allowed to change it in any way. I'm quite limited in terms of allowable grammar specifications, so if is possible to
fix the problem without changing the grammar, that would be awesome.

Thanks in advance
  • Attachment: error1.png
    (Size: 6.34KB, Downloaded 78 times)
  • Attachment: error2.png
    (Size: 6.78KB, Downloaded 75 times)

[Updated on: Thu, 15 February 2018 23:57]

Report message to a moderator

Re: implementing QualifiedNameProvider [message #1782021 is a reply to message #1782012] Fri, 16 February 2018 05:53 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
You cannot Access references in the Nameprovider.
You can use nodemodelutils top obtain the Text written
And use that to produce the qualified name

Is there a reason you do the traversal in your scooeprovider
Doing a more directed collection might be more optimal


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: implementing QualifiedNameProvider [message #1782398 is a reply to message #1782021] Thu, 22 February 2018 16:47 Go to previous messageGo to next message
Mathieu Boucher is currently offline Mathieu BoucherFriend
Messages: 5
Registered: October 2017
Junior Member
Hi Christian,

I'm actually having a very similar problem right now. I implemented the poster's original code and tried adding your suggestions, namely in the qualifedNameProvider

package org.xtext.example.mydsl2.scoping;

import org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.xtext.example.mydsl2.myDsl.GateReference;

public class MyQNProvider extends  DefaultDeclarativeQualifiedNameProvider {
	
	protected QualifiedName qualifiedName(GateReference gateReference) {
		String gateReferenceText = NodeModelUtils.getNode(gateReference).getText().trim();
		return QualifiedName.create(gateReferenceText);
	}
}


there are no runtime error, but the code still doesn't seem to accept the gateReference's name when used in an interaction.

component c1;
component c2;
gate g1;

connect c1.g1 to c2.g1; 

c1.g1 sends 5 to c2.g1; //says that it couldn't resolve reference to both GateReference c1.g1 and c2.g1 


I used the same scoping class as the poster's one.

Is there something I'm missing?
Re: implementing QualifiedNameProvider [message #1782399 is a reply to message #1782021] Thu, 22 February 2018 16:47 Go to previous messageGo to next message
Mathieu Boucher is currently offline Mathieu BoucherFriend
Messages: 5
Registered: October 2017
Junior Member
Hi Christian,

I'm actually having a very similar problem right now. I implemented the poster's original code and tried adding your suggestions, namely in the qualifedNameProvider

package org.xtext.example.mydsl2.scoping;

import org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.xtext.example.mydsl2.myDsl.GateReference;

public class MyQNProvider extends  DefaultDeclarativeQualifiedNameProvider {
	
	protected QualifiedName qualifiedName(GateReference gateReference) {
		String gateReferenceText = NodeModelUtils.getNode(gateReference).getText().trim();
		return QualifiedName.create(gateReferenceText);
	}
}


there are no runtime error, but the code still doesn't seem to accept the gateReference's name when used in an interaction.

component c1;
component c2;
gate g1;

connect c1.g1 to c2.g1; 

c1.g1 sends 5 to c2.g1; //says that it couldn't resolve reference to both GateReference c1.g1 and c2.g1 


I used the same scoping class as the poster's one.

Is there something I'm missing?
Re: implementing QualifiedNameProvider [message #1782400 is a reply to message #1782021] Thu, 22 February 2018 16:48 Go to previous messageGo to next message
Mathieu Boucher is currently offline Mathieu BoucherFriend
Messages: 5
Registered: October 2017
Junior Member
Hi Christian,

I'm actually having a very similar problem right now. I implemented the poster's original code and tried adding your suggestions, namely in the qualifedNameProvider

package org.xtext.example.mydsl2.scoping;

import org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.xtext.example.mydsl2.myDsl.GateReference;

public class MyQNProvider extends  DefaultDeclarativeQualifiedNameProvider {
	
	protected QualifiedName qualifiedName(GateReference gateReference) {
		String gateReferenceText = NodeModelUtils.getNode(gateReference).getText().trim();
		return QualifiedName.create(gateReferenceText);
	}
}


there are no runtime error, but the code still doesn't seem to accept the gateReference's name when used in an interaction.

component c1;
component c2;
gate g1;

connect c1.g1 to c2.g1; 

c1.g1 sends 5 to c2.g1; //says that it couldn't resolve reference to both GateReference c1.g1 and c2.g1 


I used the same scoping class as the poster's one.

Is there something I'm missing?
Re: implementing QualifiedNameProvider [message #1782401 is a reply to message #1782021] Thu, 22 February 2018 16:48 Go to previous messageGo to next message
Mathieu Boucher is currently offline Mathieu BoucherFriend
Messages: 5
Registered: October 2017
Junior Member
Hi Christian,

I'm actually having a very similar problem right now. I implemented the poster's original code and tried adding your suggestions, namely in the qualifedNameProvider

package org.xtext.example.mydsl2.scoping;

import org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.xtext.example.mydsl2.myDsl.GateReference;

public class MyQNProvider extends  DefaultDeclarativeQualifiedNameProvider {
	
	protected QualifiedName qualifiedName(GateReference gateReference) {
		String gateReferenceText = NodeModelUtils.getNode(gateReference).getText().trim();
		return QualifiedName.create(gateReferenceText);
	}
}


there are no runtime error, but the code still doesn't seem to accept the gateReference's name when used in an interaction.

component c1;
component c2;
gate g1;

connect c1.g1 to c2.g1; 

c1.g1 sends 5 to c2.g1; //says that it couldn't resolve reference to both GateReference c1.g1 and c2.g1 


I used the same scoping class as the poster's one.

Is there something I'm missing?
Re: implementing QualifiedNameProvider [message #1782405 is a reply to message #1782401] Thu, 22 February 2018 17:42 Go to previous message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
the segements you call QualifiedNAme.create(segment1,...,segementn) may not contain "."


public class MyQNProvider extends DefaultDeclarativeQualifiedNameProvider {

protected QualifiedName qualifiedName(GateReference gateReference) {
String gateReferenceText1 = NodeModelUtils.findNodesForFeature(gateReference, MyDslPackage.Literals.GATE_REFERENCE__COMPONENT).get(0).getText().trim();
String gateReferenceText2 = NodeModelUtils.findNodesForFeature(gateReference, MyDslPackage.Literals.GATE_REFERENCE__GATE).get(0).getText().trim();
return QualifiedName.create(gateReferenceText1,gateReferenceText2);
}
}



or

public class MyQNProvider extends DefaultDeclarativeQualifiedNameProvider {

protected QualifiedName qualifiedName(GateReference gateReference) {
String gateReferenceText = NodeModelUtils.getNode(gateReference).getText().trim();
return getConverter().toQualifiedName(gateReferenceText);
}
}



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Previous Topic:Allow negative unary expression in combination with subtraction
Next Topic:Expression supertype doesn't work properly
Goto Forum:
  


Current Time: Tue Apr 16 19:47:06 GMT 2024

Powered by FUDForum. Page generated in 0.84720 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top