Encountering EProxies after building projects in new workspace [message #1859681] |
Thu, 22 June 2023 09:33 |
Lars Fritsche Messages: 10 Registered: April 2017 |
Junior Member |
|
|
Hi,
I have a rather peculiar problem with my Xtext project, which works most of the times.
However, I encounter some errors when creating a new workspace, importing my projects from git and then building them.
This only happens for new workspaces or when I create some sort of dirty state by forcefully closing the runtime workspace from my developer workspace and then building the projects anew.
In both cases, I find that the resources given to me via the doGenerate method contain eproxies that I cannot resolve.
Yet, building a second time somehow solves these issues and the resources are intact.
Here is a small snippet of my grammar:
@Override
SlimRuleNodeContext: {SlimRuleNodeContext}
'[=]' (local?='local')? context = SlimRuleNode
;
@Override
SlimRuleNodeCreation: {SlimRuleNodeCreation}
'[+]' creation = SlimRuleNode
;
@Override
SlimRuleNode: {SlimRuleNode}
name = ID ':' type=[ecore::EClass | QualifiedName] ('{'
(contextEdges += SlimRuleEdgeContext |
createdEdges += SlimRuleEdgeCreation)*
'}')?
SlimRuleEdgeContext:
'[=]' context = SlimRuleSimpleEdge
;
SlimRuleEdgeCreation:
'[+]' creation = SlimRuleSimpleEdge
;
SlimRuleSimpleEdge returns SlimRuleEdge: {SlimRuleSimpleEdge}
'-' type=[ecore::EReference|ValidID] '->' target=[SlimRuleNode|ID]
;
;
I simplified it a bit and omitted some parts but the Overrides come from another common language of ours.
Now, I want to define two nodes with one edge edge between them just as in the following example:
[=] p : J.Package {
[+] -clazzes->c
}
[+] c : J.Clazz
What happens is that the first time doGenerate is called, I would get p and c as well as the SlimRuleEdgeCreation for the edge between p and c.
However, both the type of the edge (Packages and Clazzes are connected via a clazzes reference) and the target, which should by a crossreference to the element c are eproxies:
SlimRuleNodeContext: org.emoflon.ibex.tgg.tggl.tGGL.impl.SlimRuleNodeContextImpl@17a32f28 (local: false) (refining: false)
SlimRuleNodeContext.context: org.emoflon.ibex.tgg.tggl.tGGL.impl.SlimRuleNodeImpl@253e9c2d (name: p)
SlimRuleNode.context.createdEdges: org.emoflon.ibex.common.slimgt.slimGT.impl.SlimRuleEdgeCreationImpl@5722a66b
SlimRuleNode.context.createdEdges.creation: org.emoflon.ibex.common.slimgt.slimGT.impl.SlimRuleSimpleEdgeImpl@2e4ee9e0
SlimRuleNode.context.createdEdges.creation.target: org.emoflon.ibex.common.slimgt.slimGT.impl.SlimRuleNodeImpl@54c2fe94 (eProxyURI: platform:/resource/Java2Doc/src/org/emoflon/ibex/tgg/rules/Class2Doc.tggl#|2)
SlimRuleNode.context.createdEdges.creation.type: org.eclipse.emf.ecore.impl.EReferenceImpl@29dd10d2 (eProxyURI: platform:/resource/Java2Doc/src/org/emoflon/ibex/tgg/rules/Class2Doc.tggl#|1)
Did anyone encounter a similar problem and was able to solve it somehow?
As it stands, I am quite confused and not sure how to debug this.
I figured that the Scoper might not be robust enough for this startup problem and that there is some corner case that I didn't anticipate.
But it isn't called before doGenerate here.
Thanks in advance for any help!
Cheers
Lars
[Updated on: Thu, 22 June 2023 09:34] Report message to a moderator
|
|
|
|
Re: Encountering EProxies after building projects in new workspace [message #1859683 is a reply to message #1859682] |
Thu, 22 June 2023 10:23 |
Lars Fritsche Messages: 10 Registered: April 2017 |
Junior Member |
|
|
Hi,
thanks for the fast reply.
I'll try to debug both.
Regarding our features, there are indeed some special things happening.
These nodes from my last post are part of rules and these rules can extend each other.
Hence, an edge may reference a node from an entirely different rule, which may live in another file.
Not sure if this is related but one thing that we have to solve are naming collisions to make these references unambiguous.
In our language, a rule can extend from multiple rules, which means that we need aliases to distinguish between them, e.g., rule X refines Y as A, Y as B for cases where you want to extend your rule twice with structures from one the same rule.
However, importing nodes from another rule or in this case extending the same rule twice can lead to naming collisions (which we catch and highlight via the validator).
You can resolve these cases by overriding nodes and giving them a new name like "node x refines A.y, B.y" (because "node x refines Y.y, Y.y" would be ambiguous), which would basically merge them and solve the naming collision.
Yet, this means that we need QualifiedNames to identify where a node stems from and thus a special scope with two NameProviders (once with Alias (A.y,B.y) and once without (Y.y)).
But when it comes to creating Edges between elements, we rely on simple IDs as these collision must be resolved.
Hence, the scoper has to (transitively) search for nodes in other rules omitting those that have been overridden in the current rule.
Just in case that this scope and name provider is of interest I add it here:
public class TGGLAliasedRuleScope extends SimpleScope {
public TGGLAliasedRuleScope(Collection<TGGLRuleRefinementAliased> ruleRefinementAliases, Map<TGGRule, Collection<EObject>> rule2refinedNodes) {
super(calculcateScopes(ruleRefinementAliases, rule2refinedNodes));
}
// Collect all rule refinements and then create FQ scopes for each node
private static Iterable<IEObjectDescription> calculcateScopes(Collection<TGGLRuleRefinementAliased> ruleRefinementAliases, Map<TGGRule, Collection<EObject>> rule2refinedNodes) {
Map<String, String> ruleName2alias = new HashMap<>();
for(var alias : ruleRefinementAliases) {
ruleName2alias.put(alias.getSuperRule().getName(), alias.getName());
}
Collection<IEObjectDescription> scopes = new LinkedList<>();
for(var rule : rule2refinedNodes.keySet()) {
if(ruleName2alias.containsKey(rule.getName())) {
var aliasName = ruleName2alias.get(rule.getName());
var iterable = Scopes.scopedElementsFor(rule2refinedNodes.get(rule), new RuleAliasedNamedProvider(aliasName));
iterable.forEach(scopes::add);
}
var iterable = Scopes.scopedElementsFor(rule2refinedNodes.get(rule), new RuleAwareQualifiedNamedProvider(rule));
iterable.forEach(scopes::add);
}
return scopes;
}
@Override
public Iterable<IEObjectDescription> getElements(final EObject object) {
Iterable<IEObjectDescription> defaultImpl = super.getElements(object);
if (defaultImpl.iterator().hasNext())
return defaultImpl;
// If default does not work, try using the exact URI of object (no normalization etc)
Iterable<IEObjectDescription> localElements = getLocalElementsByEObject(object, EcoreUtil.getURI(object));
Iterable<IEObjectDescription> parentElements = getParentElements(new Provider<Iterable<IEObjectDescription>>() {
@Override
public Iterable<IEObjectDescription> get() {
return getParent().getElements(object);
}
});
Iterable<IEObjectDescription> result = Iterables.concat(localElements, parentElements);
return result;
}
}
class RuleAliasedNamedProvider extends DefaultDeclarativeQualifiedNameProvider {
private String aliasName;
public RuleAliasedNamedProvider(String aliasName) {
this.aliasName = aliasName;
}
@Override
public QualifiedName getFullyQualifiedName(EObject obj) {
if(obj instanceof SlimRuleNode node) {
var tggRule = SlimGTModelUtil.getContainer(obj, TGGRule.class);
if(tggRule == null)
return super.getFullyQualifiedName(obj);
IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
return converter.toQualifiedName(aliasName + "." + node.getName());
}
return super.getFullyQualifiedName(obj);
}
}
class RuleAwareQualifiedNamedProvider extends DefaultDeclarativeQualifiedNameProvider {
private TGGRule rule;
public RuleAwareQualifiedNamedProvider(TGGRule rule) {
this.rule = rule;
}
@Override
public QualifiedName getFullyQualifiedName(EObject obj) {
var tggRule = rule;
if(obj instanceof SlimRuleNode node) {
if(tggRule == null)
tggRule = SlimGTModelUtil.getContainer(obj, TGGRule.class);
if(tggRule == null)
return super.getFullyQualifiedName(obj);
IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
return converter.toQualifiedName(tggRule.getName() + "." + node.getName());
}
return super.getFullyQualifiedName(obj);
}
}
|
|
|
|
Powered by
FUDForum. Page generated in 0.03635 seconds