ScopeProvider: comparing references [message #1522721] |
Mon, 22 December 2014 13:46 |
Marc Schlegel Messages: 69 Registered: July 2009 |
Member |
|
|
Hello everyone
I have a working example where I use lokal references and cross-references to another DSL.
Now I would like to customize the Scope: I have a list-attribut and I want to exclude elements from the scope that are already in my current list.
Person: name=ID;
Group:
name=ID
persons+=[Person]
;
My first thought was that I just check if one of the defined elements has already been used
def IScope scope_Group_persons(Group g, EReference ref){
val definedPersons = ....
return Scopes::scopeFor(definedPersons.filter[p| !g.persons.contains(p)]);
}
With this solution I get Errors "could not resove reference to x".
Then I realized that the reference is a new object rather than a Java-Reference, so I thought I have to compare actual values.
def IScope scope_Group_persons(Group g, EReference ref){
val definedPersons = ....
val usedPersons = g.persons;
return Scopes::scopeFor(definedPersons.filter[p|g.persons.filter[x|x.name.equals(p.name)].empty]);
}
Now x.name gives me a Nullpointer because in the reference no attribute is set?
Can someoneexplain how this works in Xtext, especially why a reference is not a reference ?
Thanks
EDIT: After some more reading I figured out that references are using proxies. I am trying to resolve those now, but I wonder why other examples are working without resolving proxies.
According to the docu, working with the proxies is recommendet. I tested a lot with EcoreUtils.resolve but the reference still is an empty proxy
[Updated on: Mon, 22 December 2014 17:25] Report message to a moderator
|
|
|
Re: ScopeProvider: comparing references [message #1523180 is a reply to message #1522721] |
Mon, 22 December 2014 19:41 |
Marc Schlegel Messages: 69 Registered: July 2009 |
Member |
|
|
After some more thinking about the issue I realize that some more information is probably helpfull.
My DSL uses two types of cross-references:
- Global - referencing elements in another DSL
- Lokal - referencing only elements within the lokal file
My current problem is only related to the lokal scope which I would like to customize:
As far as I understood the documentation, the proxies are used to postpone the parsing of referenced files. In my case, I get the proxy also for the lokal cross-references and I have not been able to resolve them (myproxyobject.eResource is always null).
I also tried using FilterinScope but this ends with the same problem...I cannot compare the objects (or attributes).
Hope this clarifies my problem.
EDIT: I could solve my requirement by implementing a ProposalProvider in the ui-plugin.
class SomeDslProposalProvider extends AbstractProzessDslProposalProvider {
override completeGroup_Persons(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
lookupCrossReference(
assignment.terminal as CrossReference,
context,
acceptor,
[!(model as Group).persons.contains((EObjectOrProxy as Person))]
)
}
} This way I access the cross-reference without a proxy and my contains works as expected.
I would still like to know how to achieve this using Scoping.
[Updated on: Tue, 23 December 2014 09:10] Report message to a moderator
|
|
|
|
|
Re: ScopeProvider: comparing references [message #1525850 is a reply to message #1524937] |
Wed, 24 December 2014 07:41 |
Yoel Pinhas Messages: 17 Registered: October 2013 |
Junior Member |
|
|
I'm glad your problem is resolved
you ask a very good question
I am no xtext expert, but i'll try my best to answer
I think that the issue you are referring to stems from the inherent problems concerning compilation in general, namely 'lazy linking' due to cyclic dependencies.
so, why do we need lazy liking in the first place?
If you compile a tree structure (no cycles), perhaps you can do some eager evaluation (fully resolve objects when you first encounter them).
but... life are not that simple
most real world code is a graph. A graph that contain cycles. You quickly bang your head in the classic chicken/egg scenario
class Person {
Person parent
List[Person] sibling
}
class A { B b }
class B { A a }
We can handle cycles with lazy evaluation
when we encounter Person, you can't fully resolve it because it refers itself
when you try to fully resolve class A, you go to B and from there you return to A and so on
so one solution is to keep a small note, a lazy object which is an object containing very little information: name and URI. this object can be fully resolved later when we have a full mapping of all elements
so, we still didn't get an answer the question "why can't we resolve references in the ScopeProvider as we do in the Proposals?"
I think that this is because linking is done before proposals. The scope provider is called by the linking service, and at that stage most references are still not resolved.
After the linking phase is finished- proposal can enjoy a more resolved tree (and some proposals use the scope provider only this time the tree is fully/mostly resolved)
I'm not certain that this is the *exact* way it is done in xtext but I have a hunch that this is the spirit
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03780 seconds