Extending scope with dynamic references [message #1817902] |
Mon, 02 December 2019 16:28 |
kct kct 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.
|
|
|
|
Powered by
FUDForum. Page generated in 0.04003 seconds