Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » scope implementation
scope implementation [message #527727] Fri, 16 April 2010 05:37 Go to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
Hi,

I Try to implement a scope provider for a small test grammar.

this is the first version :


import 'http://www.eclipse.org/emf/2002/Ecore' as ecore  

Model :
	(imports+=Import)*
	test=Test
;

Test : 
	'test' type=[ecore::EClass] ':' attribute= [ecore::EStructuralFeature] ';'
;


I want "attribute" is one of the attribute if the "type" class.

So I implement a scope provider :

public IScope scope_Test_attribute(Test test, EReference ref) {
		EList<IScopedElement> scopelist = new BasicEList<IScopedElement>();
		EClass type = test.getType().getName();
		if (type != null) {
			for (EStructuralFeature feature : UtilsMethods.getFeatures(type)) {
			scopelist.add(ScopedElement.create(feature.getName(), feature));
			}
		}
		return new SimpleScope(scopelist);
	}


By this way, it work well. But I would like to do something more complexe.
So my new grammar is :

Test : 
	'test' type=[ecore::EClass] ':' attribute=FieldAccessor ';'
;

FieldAccessor2 :
	feature = [ecore::EStructuralFeature]
;



and the new scope provider implementation is :

	public IScope scope_FieldAccessor2_feature(FieldAccessor2 accessor, EReference ref) {
		EList<IScopedElement> scopelist = new BasicEList<IScopedElement>();
		EObject eContainer = accessor.eContainer();
		if (eContainer instanceof Test) {
			Test test = (Test) eContainer;
			EClass type =  test.getType().getName();
			if (type != null) {
				for (EStructuralFeature feature : UtilsMethods.getFeatures(type)) {
					System.out.println("fieldAccessor : add feature " + feature.getName());
					scopelist.add(ScopedElement.create(feature.getName(), feature));
				}		
			}
		}
		SimpleScope simpleScope = new SimpleScope(scopelist);
		return simpleScope;
	}


So, by this way, if I write a no valid attribute, xtext underline the attribute in red. that's good. but the content assist doesn't work. In did, the content assist propose me all visible attributes of my ecore file and not only the attributes of the selected class.

Maybe I know why it doesn't work.
when the contant assis call :
 scope_FieldAccessor2_feature(...)
the Test object is not yet create.
so the line :
EObject eContainer = accessor.eContainer();
return null. So the default scope provider is Called.

Do you think it is the right reason? and how can I resolve this problem?

thanks,

Jérémie
Re: scope implementation [message #527733 is a reply to message #527727] Fri, 16 April 2010 05:55 Go to previous messageGo to next message
Sven Efftinge is currently offline Sven Efftinge
Messages: 1759
Registered: July 2009
Senior Member
In contents assist the closest already parsed context object is passed,
which is an instance of Test not an instance of FieldAccessor2.

If you change the signature of your scope method like the following both
should work fine:

public IScope scope_FieldAccessor2_feature(Test test, EReference ref)

Sven

jeremie schrieb:

>
> Test : 'test' type=[ecore::EClass] ':' attribute=FieldAccessor ';'
> ;
>
> FieldAccessor2 :
> feature = [ecore::EStructuralFeature]
> ;
>
>
>
> and the new scope provider implementation is :
>
>
> public IScope scope_FieldAccessor2_feature(FieldAccessor2 accessor,
> EReference ref) {
> EList<IScopedElement> scopelist = new BasicEList<IScopedElement>();
> EObject eContainer = accessor.eContainer();
> if (eContainer instanceof Test) {
> Test test = (Test) eContainer;
> EClass type = test.getType().getName();
> if (type != null) {
> for (EStructuralFeature feature :
> UtilsMethods.getFeatures(type)) {
> System.out.println("fieldAccessor : add feature " +
> feature.getName());
>
> scopelist.add(ScopedElement.create(feature.getName(), feature));
> }
> }
> }
> SimpleScope simpleScope = new SimpleScope(scopelist);
> return simpleScope;
> }
>
>
> So, by this way, if I write a no valid attribute, xtext underline the
> attribute in red. that's good. but the content assist doesn't work. In
> did, the content assist propose me all visible attributes of my ecore
> file and not only the attributes of the selected class.
>
> Maybe I know why it doesn't work.
> when the contant assis call : scope_FieldAccessor2_feature(...) the
> Test object is not yet create.
> so the line : EObject eContainer = accessor.eContainer(); return null.
> So the default scope provider is Called.
>
> Do you think it is the right reason? and how can I resolve this problem?
>
> thanks,
>
> Jérémie


--
Need professional support for Xtext and EMF?
Go to: http://xtext.itemis.com
Twitter : @svenefftinge
Blog : blog.efftinge.de


--
Need professional support on Xtext or Xtend?
Mail to: xtext (at) itemis.com
Twitter : @svenefftinge
Blog : blog.efftinge.de
Re: scope implementation [message #527754 is a reply to message #527733] Fri, 16 April 2010 07:47 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
oh thanks!

it works well.

Really thanks.

Jérémie
Re: scope implementation [message #528142 is a reply to message #527754] Mon, 19 April 2010 10:03 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
Hello,

I complicate a little my grammar. Now I would like to access to Operations too.
So this is my new Grammar :

Test : 
	'test' type=[ecore::EClass] ':' accessor=Aceessor2 ';'
;

Aceessor2 :
	FieldAccessor2 | MethodCall2
;

FieldAccessor2 :
	feature = [ecore::EStructuralFeature]
;

MethodCall2 :
	call = [ecore::EOperation]
;



and this is my scope provider implementation :

public IScope scope_MethodCall2_call(Test test, EReference ref) {
		EList<IScopedElement> scopelist = new BasicEList<IScopedElement>();
		EClass type = test.getType();
		for (EOperation operation : UtilsMethods.getOperations(type)) {
			scopelist.add(ScopedElement.create(operation.getName(), operation));
		}
		return new SimpleScope(scopelist);
	}
	
	public IScope scope_FieldAccessor2_feature(Test test, EReference ref) {
		EList<IScopedElement> scopelist = new BasicEList<IScopedElement>();
		EClass type = test.getType();
		for (EStructuralFeature feature : UtilsMethods.getFeatures(type)) {
			scopelist.add(ScopedElement.create(feature.getName(), feature));
		}
		return new SimpleScope(scopelist);
	}


By this way, the content assist work well. but after all operations are underline in red. the erore message is :
Couldn't resolve reference to EStructuralFeature <methosName>

The program can only see Attributes and not methods. In fact, the program only go to the method :
public IScope scope_FieldAccessor2_feature(Test test, EReference)

end not in the function :
public IScope scope_MethodCall2_call(Test test, EReference ref)


but If I modify my grammar by this way :

Aceessor2 :
 MethodCall2 |	FieldAccessor2 
;


It is the opposite, the program now car see method and not attribute :

The arror message is now :
Couldn't resolve reference to EOperation <attribute name>


Can you help me please

Jérémie
Re: scope implementation [message #528175 is a reply to message #528142] Mon, 19 April 2010 11:12 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian Zarnekow
Messages: 2809
Registered: July 2009
Senior Member
Hi Jeremie,

I assume that you had to enable backtracking in your grammar to make it
compilable, right?

Your concrete syntax looks like this:

Test: 'test' ID ':' Accessor2 ';'
Accessor2: FieldAccessor2 | MethodCall2;
FieldAccessor2: ID;
MethodCall: ID;

(I removed any assignment and replaced crossreferences by their
respective representation in the concrete syntax)
The parser cannot decide whether to create a FieldAccessor or a
MethodCall. That's why backtracking chooses the winner by first come
first serve according to the alternatives in your grammar.
To make things work for you, you'ld have to destinguish both
alternatives on the concrete syntax level or use a common supertype for
the fields and methods in the cross reference,

Test :
'test' type=[ecore::EClass] ':' reference=FieldOrMethodReference ';'
;

FieldOrMethodReference :
fieldOrMethod=[FieldOrMethod]
;

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 19.04.10 16:03, schrieb jeremie:
> Hello,
>
> I complicate a little my grammar. Now I would like to access to
> Operations too.
> So this is my new Grammar :
>
>
> Test : 'test' type=[ecore::EClass] ':' accessor=Aceessor2 ';'
> ;
>
> Aceessor2 :
> FieldAccessor2 | MethodCall2
> ;
>
> FieldAccessor2 :
> feature = [ecore::EStructuralFeature]
> ;
>
> MethodCall2 :
> call = [ecore::EOperation]
> ;
>
>
>
> and this is my scope provider implementation :
>
>
> public IScope scope_MethodCall2_call(Test test, EReference ref) {
> EList<IScopedElement> scopelist = new BasicEList<IScopedElement>();
> EClass type = test.getType();
> for (EOperation operation : UtilsMethods.getOperations(type)) {
> scopelist.add(ScopedElement.create(operation.getName(), operation));
> }
> return new SimpleScope(scopelist);
> }
>
> public IScope scope_FieldAccessor2_feature(Test test, EReference ref) {
> EList<IScopedElement> scopelist = new BasicEList<IScopedElement>();
> EClass type = test.getType();
> for (EStructuralFeature feature : UtilsMethods.getFeatures(type)) {
> scopelist.add(ScopedElement.create(feature.getName(), feature));
> }
> return new SimpleScope(scopelist);
> }
>
>
> By this way, the content assist work well. but after all operations are
> underline in red. the erore message is :
> Couldn't resolve reference to EStructuralFeature <methosName>
> The program can only see Attributes and not methods. In fact, the
> program only go to the method :
>
> public IScope scope_FieldAccessor2_feature(Test test, EReference)
>
> end not in the function :
>
> public IScope scope_MethodCall2_call(Test test, EReference ref)
>
>
> but If I modify my grammar by this way :
>
>
> Aceessor2 :
> MethodCall2 | FieldAccessor2 ;
>
>
> It is the opposite, the program now car see method and not attribute :
>
> The arror message is now :
>
> Couldn't resolve reference to EOperation <attribute name>
>
>
> Can you help me please
>
> Jérémie
Re: scope implementation [message #528177 is a reply to message #528175] Mon, 19 April 2010 11:30 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
yes I have enable backtracking.
I am looking for your solution.
Thanks
Re: scope implementation [message #528190 is a reply to message #528177] Mon, 19 April 2010 12:09 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
I am sorry, I don't really understand your solution. I think that ...

I try this grammar :

Test :
'test' type=[ecore::EClass] ':' reference=FieldOrMethodReference ';'
;

FieldOrMethodReference :
	fieldOrMethod=[FieldOrMethod]
;

FieldOrMethod : FieldAccessor2 | MethodCall2;

FieldAccessor2 :
	feature = [ecore::EStructuralFeature]
;

MethodCall2 :
	call = [ecore::EOperation]
;


But now I don't really know how to implement the scope provider because here the cross reference [FieldOrMethod] contain other cross reference inside : [ecore::EStructuralFeature] and [ecore::EOperation].

I think there are some important principles of XText that I don't understand yet.

Jérémie
Re: scope implementation [message #528192 is a reply to message #528190] Mon, 19 April 2010 12:13 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian Zarnekow
Messages: 2809
Registered: July 2009
Senior Member
Hi Jérémie,

sorry, I should have been more specific here:

Test :
'test' type=[ecore::EClass] ':' reference=FieldOrMethodReference ';'
;

FieldOrMethodReference :
fieldOrMethod=[ecore::ETypedElement]
;

Your scope provider has to narrow the list of scoped elements to
subtypes of EOperation or EStructuralFeature.
There is no way to define the semantics for this kind of cross reference
in the grammar itself.

Hope that helps,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com


Am 19.04.10 18:09, schrieb jeremie:
> I am sorry, I don't really understand your solution. I think that ...
>
> I try this grammar :
>
>
> Test :
> 'test' type=[ecore::EClass] ':' reference=FieldOrMethodReference ';'
> ;
>
> FieldOrMethodReference :
> fieldOrMethod=[FieldOrMethod]
> ;
>
> FieldOrMethod : FieldAccessor2 | MethodCall2;
>
> FieldAccessor2 :
> feature = [ecore::EStructuralFeature]
> ;
>
> MethodCall2 :
> call = [ecore::EOperation]
> ;
>
>
> But now I don't really know how to implement the scope provider because
> here the cross reference [FieldOrMethod] contain other cross reference
> inside : [ecore::EStructuralFeature] and [ecore::EOperation].
>
> I think there are some important principles of XText that I don't
> understand yet.
>
> Jérémie
Re: scope implementation [message #528215 is a reply to message #528192] Mon, 19 April 2010 13:40 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
Thanks a lot a new time;

It works. Smile

Jérémie
Re: scope implementation [message #528378 is a reply to message #528190] Tue, 20 April 2010 06:19 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
Hello,

I Still have a new problem with my grammar. (exactly two problems, but for the second, I have to explicate more precisely my grammar, it won't be easy, so I try to resolve this problem alone).

In the precedents messages, Sebastian told me, that I have to use EtypedElement instead of EStructureFeature and EOperation, and it works;

I can now do something like this :
Test EClass1 : attribute1
Test EClass2 : method1


I would like to do some particular treatment for the EOperation. I would like to do something like that :
Test EClass2 : method1(arg1, arg2)


in my grammar I have this rules :
MethodCall : 
     name=[ecore::EOperation] '(' arguments=ArgumentList ')'
;

ArgumentList :
    arguement=Expression (',' next=ArgumentList)?
;


Is it possible to use these rules in my grammar written in the precedents messages?

Thanks Jérémie

Re: scope implementation [message #528630 is a reply to message #528378] Wed, 21 April 2010 06:33 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
Hi,

I am sorry to disturb you again, but I really don't manage to resolve my second problem.
The problem of the precedent message with EOperation and EStructuralElement is still here but is minor. My problem is to treat Expression which look like this :

[CODE]
this.reference1.attribute2.method(arg1, arg2);
or
adapted.attribute1.method2(arg1, arg2);

/CODE]

so my grammar look like this :

ChainableExpression :
 	AtomElement ({CallExpression.receiver=current} '.' accessor=ChainableExpression)?
;
 
AtomElement returns ChainableExpression :
	value=SimpleAccessor 
;

SimpleAccessor :
	ThisAccessor|
	AdaptedAccessor|
	accessor = [ecore::ETypedElement]
;

ThisAccessor :
	this = 'this'
;
AdaptedAccessor :
	adapted = 'adapted'
;



("this" and "adapted" represent an object)

my problem is still with the implementation of the scope provider.
Actually :
adapted.attribute1

work, the content assist propose to me the good elements. but
adapted.attribute1.method2

work bad. in fact, the content assist propose to me for attribute2 alle the elements of the "adapted" object.

this is my scope provider :

public IScope scope_SimpleAccessor_accessor(CallExpression expr, EReference ref) {
		EList<IScopedElement> scopelist = new BasicEList<IScopedElement>();
		EObject receiver = expr.getReceiver();
		if (receiver != null) {
			EClass type = analyzer.getType(receiver);
			if (type != null) {
				for (EStructuralFeature feature : UtilsMethods.getFeatures(type)) {				scopelist.add(ScopedElement.create(feature.getName(), feature));
				}
			}
		}
		return new SimpleScope(scopelist);
	}


analyser.getType return the type of an element or an expression. (it use an AdapterSwitch implementation);

With the debugger I can see that sometimes the receiver = null. Some other time the reveicerver is not null, he contain a sImpleElement ant the field Acceccor of SimpleElement contain a cross reference to a typedElement, but all the element of the TypedElement are null (eType = null, name = null...)
I don't really understand what appends.

maybe my scope provider or my grammar is not well formed.
I really hope you can help me, I am completely block now.

thanks,

Jeremie
Re: scope implementation [message #528674 is a reply to message #528378] Wed, 21 April 2010 09:00 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
The problem is really that all element of the receiver are null:

I try on an example :

adapted.label.;

(label is a String)
at this moment, (after the '.'), when I launch the content assist, my scope provider method is launch :
public IScope scope_SimpleAccessor_accessor(CallExpression expr, EReference ref) {
		EList<IScopedElement> scopelist = new BasicEList<IScopedElement>();
		EObject receiver = expr.getReceiver();
		if (receiver != null) {
			EClass type = analyzer.getType(receiver);
			if (type != null) {
				for (EStructuralFeature feature : scopelist.add(ScopedElement.create(feature.getName(), feature));
				}
			}
		}
		return new SimpleScope(scopelist);
	}


In this method, the receiver is an EAttribute, that's good (label is an attribute of the adapted object). but all elements in this attributs are null. (etype = null, name = null, instead of etype = EString, name = label). I don't understand why this element are null.
At this point, the method analyser.getType(receiver) don't work. so, I think that xtext go to the parent node in the AST, so xtext analyse this expression instead :
adapted.label;
where the receiver is "adapted"
that's why the content assist propose me all ETypedElement from the "adatped" object and not from "label".

I hope all this will help you to understand my problem. If you have any questions or you want more precisions, don't hesitate to ask.

jérémie

Re: scope implementation [message #528913 is a reply to message #528674] Thu, 22 April 2010 07:45 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
Should I write this problem in a new topic?
jérémie
Re: scope implementation [message #528921 is a reply to message #528913] Thu, 22 April 2010 08:06 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian Zarnekow
Messages: 2809
Registered: July 2009
Senior Member
Hi Jéremie,

I marked you last question as read by accident. I'll come back to this
one later this day.

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 22.04.10 13:45, schrieb jeremie:
> Should I write this problem in a new topic?
> jérémie
Re: scope implementation [message #528926 is a reply to message #528921] Thu, 22 April 2010 08:18 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
thanks Sebastien Smile
Re: scope implementation [message #529072 is a reply to message #528630] Thu, 22 April 2010 15:32 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian Zarnekow
Messages: 2809
Registered: July 2009
Senior Member
Hi Jeremie,

I guess the scope provider impl does not match your grammar - the
various attributes of your receiver are null thus I suspect it to be an
unresolved proxy.

Your grammar looks like this:

ChainableExpression :
AtomElement ({CallExpression.receiver=current} '.'
accessor=ChainableExpression)?
;

Please try to alter it slightly:

ChainableExpression :
AtomElement ({CallExpression.receiver=current} '.' accessor=Atom)*
;

This should help to create a decent model for expressions like
this.receiver.feature which result in a model

ChainableExpression
|- receiver - ChainableExpression
| |- receiver - AtomElement (this)
| '- accessor - AtomElement (receiver)
'- accessor - AtomElement (feature)

I hope this serves as a good starting point to get the scoping right.

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 21.04.10 12:33, schrieb jeremie:
> Hi,
> I am sorry to disturb you again, but I really don't manage to resolve my
> second problem.
> The problem of the precedent message with EOperation and
> EStructuralElement is still here but is minor. My problem is to treat
> Expression which look like this :
>
> [CODE]
> this.reference1.attribute2.method(arg1, arg2);
> or
> adapted.attribute1.method2(arg1, arg2);
>
> /CODE]
>
> so my grammar look like this :
>
>
> ChainableExpression :
> AtomElement ({CallExpression.receiver=current} '.'
> accessor=ChainableExpression)?
> ;
>
> AtomElement returns ChainableExpression :
> value=SimpleAccessor ;
>
> SimpleAccessor :
> ThisAccessor|
> AdaptedAccessor|
> accessor = [ecore::ETypedElement]
> ;
>
> ThisAccessor :
> this = 'this'
> ;
> AdaptedAccessor :
> adapted = 'adapted'
> ;
>
>
>
> ("this" and "adapted" represent an object)
>
> my problem is still with the implementation of the scope provider.
> Actually :
>
> adapted.attribute1
>
> work, the content assist propose to me the good elements. but
>
> adapted.attribute1.method2
>
> work bad. in fact, the content assist propose to me for attribute2 alle
> the elements of the "adapted" object.
>
> this is my scope provider :
>
>
> public IScope scope_SimpleAccessor_accessor(CallExpression expr,
> EReference ref) {
> EList<IScopedElement> scopelist = new BasicEList<IScopedElement>();
> EObject receiver = expr.getReceiver();
> if (receiver != null) {
> EClass type = analyzer.getType(receiver);
> if (type != null) {
> for (EStructuralFeature feature : UtilsMethods.getFeatures(type)) {
> scopelist.add(ScopedElement.create(feature.getName(), feature));
> }
> }
> }
> return new SimpleScope(scopelist);
> }
>
>
> analyser.getType return the type of an element or an expression. (it use
> an AdapterSwitch implementation);
>
> With the debugger I can see that sometimes the receiver = null. Some
> other time the reveicerver is not null, he contain a sImpleElement ant
> the field Acceccor of SimpleElement contain a cross reference to a
> typedElement, but all the element of the TypedElement are null (eType =
> null, name = null...)
> I don't really understand what appends.
>
> maybe my scope provider or my grammar is not well formed.
> I really hope you can help me, I am completely block now.
>
> thanks,
> Jeremie
Re: scope implementation [message #529171 is a reply to message #529072] Fri, 23 April 2010 05:33 Go to previous messageGo to next message
jeremie is currently offline jeremie
Messages: 233
Registered: April 2010
Senior Member
Hi Sebastian,

One time again this forum help me. Ah the solution was so easy. I am confused.

Really thanks,

Jérémie
Re: scope implementation [message #546753 is a reply to message #527727] Wed, 14 July 2010 02:27 Go to previous messageGo to next message
Alex is currently offline Alex
Messages: 114
Registered: June 2010
Senior Member
Hi,

I'm trying to implement a ScopeProvider, too. But my first prblem is, that IScopedElement nor ScopedElement can be found...

Do I have to implement them on my own?
Re: scope implementation [message #546757 is a reply to message #546753] Wed, 14 July 2010 02:40 Go to previous message
Christian Dietrich is currently offline Christian Dietrich
Messages: 6143
Registered: July 2009
Senior Member
Hi Alex,

the scoping API has changed from 0.7.2 to 1.0.0. this is why you cannot find IScopedElement and ScopedElement. Have a look at Docs and the sample projects that come with Xtext (File -> New -> Example) to get an Idea what you can do.

Regards
Christian
Previous Topic:Anyone still using 0.72?
Next Topic:[Xtext] Some information about Xtext.
Goto Forum:
  


Current Time: Wed Jul 30 23:25:15 EDT 2014

Powered by FUDForum. Page generated in 0.02470 seconds