Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » ScopeProvider: comparing references
ScopeProvider: comparing references [message #1522721] Mon, 22 December 2014 13:46 Go to next message
Marc Schlegel is currently offline Marc SchlegelFriend
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 Wink ?
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 Go to previous messageGo to next message
Marc Schlegel is currently offline Marc SchlegelFriend
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:

  1. Global - referencing elements in another DSL
  2. 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 #1524648 is a reply to message #1523180] Tue, 23 December 2014 15:26 Go to previous messageGo to next message
Yoel Pinhas is currently offline Yoel PinhasFriend
Messages: 17
Registered: October 2013
Junior Member
Here are my two cents:

In this case i would follow on the best practice keeping "loose grammar and strict validation", given by the xtext master Sebastian Zarnekow

this translates to keeping the scope provider "as is" without filtering
def IScope scope_Group_persons(Group g, EReference ref){
	//val definedPersons = ....
	//return Scopes::scopeFor(definedPersons.filter[p| 
!g.persons.contains(p)]);
	val legalPersons = ... the persons you allow to add, not filtering dup's
	return Scopes::scopeFor(legalPersons);
}



an supplying a validation check for each person whose eContainer is a group and is already found in the group
@Check void checkThatPersonIsNotDuplicatedInGroup(Person p) {
	if (p.isInGroup) {
		if (p.group.isDuplicated(p)) 
			error(...)
	}
}

the pseudo code above is ofcourse just an example, you should probably write the extension methods (isInGroup(Person p)/isDuplicated(Group g, Person p) and group(Person p)) so it makes sense.

what you gain from this approach is better user experience. if someone add the same person twice you can throw errors to the exact person tokens that are producing the error.
Re: ScopeProvider: comparing references [message #1524937 is a reply to message #1524648] Tue, 23 December 2014 19:14 Go to previous messageGo to next message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 69
Registered: July 2009
Member
Thanks for your reply, this is exactly how I implemented it today.

But I still wonder why I can work with the cross-reference in ProposalProvider and not within the ScopeProvider?
It woule be nice to get some deeper understanding why I cannot resolve the lazy link (proxy) even when I try to force it.
Re: ScopeProvider: comparing references [message #1525850 is a reply to message #1524937] Wed, 24 December 2014 07:41 Go to previous messageGo to next message
Yoel Pinhas is currently offline Yoel PinhasFriend
Messages: 17
Registered: October 2013
Junior Member
I'm glad your problem is resolved Smile
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
Re: ScopeProvider: comparing references [message #1526068 is a reply to message #1525850] Wed, 24 December 2014 10:36 Go to previous messageGo to next message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 69
Registered: July 2009
Member
Thank you very much, this is a good explanation.
I remember that I got some LazyLinkingException when I tried to force the evaluation for the proxy.

I probably should finally read the book about grammars in DSLs by Terence Parr Smile

Again, thank you for your time.
Re: ScopeProvider: comparing references [message #1526198 is a reply to message #1526068] Wed, 24 December 2014 12:24 Go to previous message
Yoel Pinhas is currently offline Yoel PinhasFriend
Messages: 17
Registered: October 2013
Junior Member
Your welcome Smile

I don't know the author or the book you mentioned. It's always good to learn
I can recommend a book I read: "Implementing Domain-Specific Languages with Xtext and Xtend" by Lorenzo Bettini.
Also, I can recommend the Compilers course from coursera https://www.coursera.org/course/compilers

Yoel.

Previous Topic:[Xtext 2.8] : Cross-references howto with indexed references
Next Topic:Imported library source not being indexed
Goto Forum:
  


Current Time: Thu Sep 26 17:46:03 GMT 2024

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

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

Back to the top