Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Extending scope with dynamic references
Extending scope with dynamic references [message #1817902] Mon, 02 December 2019 16:28 Go to next message
kct kct is currently offline kct kctFriend
Messages: 1
Registered: December 2019
Junior Member
Hello.

I created a minimal project to describe my problem. I attached it to the post for reproducing the error, along with the DSL project.
Here is the grammar used in the sample project :

Model:
	elements+=Element*;
	
Element:
	Domain | DtDefinition;

Domain:
	'declare' 'Domain' name=ID;

DtDefinition:
	'create' 'DtDefinition' name=ID '{'
		'domain:' domain=[Domain]
	'}'
;


For each "DtDefinition" created, I want to be able to create a "virtual Domain" (i.e. with no explicit declaration in a .mydsl file), using the DtDefinition name.
For example, when I create a DtDefinition with name DtFirstDef, a virtual domain with name DoDtFirstDefDto should be created. This domain could then be refered to in a new DtDefinition.

The following test1.mydsl file describes this:
declare Domain DoFirstDomain

create DtDefinition DtFirstDef {
	domain:DoFirstDomain
}

create DtDefinition DtSecondDef {
	domain: DoDtFirstDefDto
}


I read a lot of posts in this forum and read the "Implementing Domain Specific Languages with Xtext and Xtend - Second Edition" book, and I understand that overriding the getScope() method of a custom ScopeProvider is the way to go (feel free to correct me here and point to better solutions :) ).

My custom scope provider runs that way:

class MyDslScopeProvider extends AbstractMyDslScopeProvider {

	@Inject
	ResourceDescriptionsProvider provider;
	
	override getScope(EObject context, EReference reference) {
		
		// we only need to generate domains when the editor tries to resolve scope for a domain	inside a DtDefinition	
		if (reference == MyDslPackage.Literals.DT_DEFINITION__DOMAIN) {
			// a set of unique names
			val Set<String> addedDomains = new HashSet<String>();
			
			// get live DtDefinitions for current file
			var	topContainer = context.eContainer
			if (topContainer !== null)
			{
				while (topContainer.eContainer !== null) {
					topContainer = topContainer.eContainer
					for (item : topContainer.eContents) {
						if (item instanceof DtDefinition) {
							if (item.getName() !== null) {
								// for each DtDefinition found, create a domain name
								addedDomains.add("Do"+ item.getName().toString()+"Dto");
							}
						}
					}
				}
			}
			
			// get DtDefinitions from all resources
			val IResourceDescriptions descriptions  = provider.createResourceDescriptions();
			if (descriptions !== null) {
				for (IResourceDescription resDescription :  descriptions.getAllResourceDescriptions()) {
					val listOfDtDefinitionDescriptions = resDescription.getExportedObjectsByType(MyDslPackage.eINSTANCE.getDtDefinition());
					
					for(definition : listOfDtDefinitionDescriptions) {
						// for each DtDefinition found, create a domain name
						addedDomains.add("Do"+ definition.getName().toString()+"Dto");
					}
				}
			}
			
			// create a list of "virtual" object descriptions to add to scope
			val List<IEObjectDescription> objectDescriptionsToAdd = new ArrayList
		
			for (item : addedDomains) {
				val EObject someObject = MyDslFactory.eINSTANCE.create(MyDslPackage.Literals.DOMAIN)
				val QualifiedName name = QualifiedName.create(item)
				objectDescriptionsToAdd.add(EObjectDescription.create(name, someObject))
				reference.eResource.contents.add(someObject)
			}
			//return new scope extending parent scope with virtual object descriptions
			return (new SimpleScope(super.getScope(context, reference), objectDescriptionsToAdd))
		}
		// return parent scope if nothing to add to it
		return super.getScope(context, reference);
	}
}


My questions:


  • Everything works fine, even content assist (proposes the generated domains), if I do not "clean" the project where test1.mydsl is used. When I do clean it, I get errors anywhere I make a reference to a "virtual domain" (see screenshot attached). It seems that getScope is called during clean, but no resource descriptions are found at that time, so nothing gets generated in my custom getScope(). Am I missing something here ?
    (Note : something is weird here, as the quickfix seems to propose the very value I used (here DoFtFirstDefDto)).

  • Is overriding getScope the right way to achieve my goal ?


Thanks in advance for your help.
Re: Extending scope with dynamic references [message #1817961 is a reply to message #1817902] Tue, 03 December 2019 16:16 Go to previous message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 13628
Registered: July 2009
Senior Member
hi,

you might also have a look at the concept of an IDerivedStateComputer


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Previous Topic:Performance implication of using xtextResource.getContents().get(0)
Next Topic:How to run a java main class in an environment created with Xtext
Goto Forum:
  


Current Time: Tue Oct 20 17:30:18 GMT 2020

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

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

Back to the top