EObjectDescription userData and information from other Resources [message #1832605] |
Mon, 21 September 2020 12:51  |
Eclipse User |
|
|
|
Hi,
TL;DR I want to know if there is an Xtext standard solution for having resource description user data refer to information from cross-references outside its own Resource.
To illustrate, let me take this example from the tutorial:
mydsl.xtext:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Domainmodel:
(elements+=AbstractElement)*;
PackageDeclaration:
'package' name=QualifiedName '{'
(elements+=AbstractElement)*
'}';
AbstractElement:
PackageDeclaration | Type | Import;
QualifiedName:
ID ('.' ID)*;
Import:
'import' importedNamespace=QualifiedNameWithWildcard;
QualifiedNameWithWildcard:
QualifiedName '.*'?;
Type:
DataType | Entity;
DataType:
'datatype' name=ID;
Entity:
'entity' name=ID ('extends' superType=[Entity|QualifiedName])? '{'
(features+=Feature)*
'}';
Feature:
(many?='many')? name=ID ':' type=[Type|QualifiedName];
and two files in that language:
one.mydsl:
package one {
entity upper {
}
}
two.mydsl:
package two {
import one.*
entity lower extends upper {
}
}
I want to implement my own ResourceDescriptionStrategy which adds user data in a way so I can directly query for the superclass of a given entitie's IEObjectDescription without the need for proxy resolution (for performance reasons. Let's say I want a fast way to query the Xtext index for a type and without resolving it's proxy to navigate to the supertype and check something with that).
The trivial approach would be to implement the ResourceDescriptionStrategy like this:
package org.xtext.example.mydsl.resource;
import java.util.Collections;
import javax.inject.Inject;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.naming.IQualifiedNameProvider;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.EObjectDescription;
import org.eclipse.xtext.resource.IDefaultResourceDescriptionStrategy;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.resource.impl.DefaultResourceDescriptionStrategy;
import org.eclipse.xtext.util.IAcceptor;
import org.xtext.example.mydsl.myDsl.Entity;
public class MyResourceDescriptionStrategy extends DefaultResourceDescriptionStrategy implements IDefaultResourceDescriptionStrategy
{
@Inject
IQualifiedNameProvider qnProvider;
@Override
public boolean createEObjectDescriptions(final EObject eObject, final IAcceptor<IEObjectDescription> acceptor)
{
if (eObject instanceof Entity)
{
Entity type = (Entity) eObject;
QualifiedName typeName = this.qnProvider.getFullyQualifiedName(type);
IEObjectDescription desc;
Entity superType = type.getSuperType();
if (superType != null)
{
QualifiedName superTypeName = this.qnProvider.getFullyQualifiedName(superType);
// PROBLEM: superType is (can be) a proxy, then superTypeName is null!
String superNameString = superTypeName != null ? superTypeName.toString() : "";
desc = EObjectDescription.create(typeName, type, Collections.singletonMap("superType", superNameString));
}
else
{
desc = EObjectDescription.create(typeName, type);
}
acceptor.accept(desc);
return true;
}
else
{
return super.createEObjectDescriptions(eObject, acceptor);
}
}
}
but this does not work (of course) because superType is imported from a different resource and therefore is a proxy here.
I could take the name of the superclass from the node model, but I still could not resolve it to its qualified name because it's imported (even via wildcard in this case).
I have seen a solution for this which uses a ForwardingMap as UserData which is evaluated lazily on access, later, after the indexing phase. But that seems a bit hacky for my taste and consumes memory because the ForwardingMap will hold on to the eObject, so it cannot be garbage collected...
I thought that problem (using data from cross-references in user data) might be a problem that is more common, but I have not found a common solution for that (or I am looking in the wrong places, or I am overlooking something obvious...?).
Any help would be appreciated! Thanks in advance!
Best,
Stefan
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.04745 seconds