Home » Modeling » TMF (Xtext) » scope implementation
scope implementation [message #527727] |
Fri, 16 April 2010 09:37 |
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 09:55 |
Sven Efftinge Messages: 1823 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
|
|
| |
Re: scope implementation [message #528142 is a reply to message #527754] |
Mon, 19 April 2010 14:03 |
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 15:12 |
Sebastian Zarnekow Messages: 3118 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 #528378 is a reply to message #528190] |
Tue, 20 April 2010 10:19 |
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 10:33 |
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 :
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 13:00 |
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 :
(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 #529072 is a reply to message #528630] |
Thu, 22 April 2010 19:32 |
Sebastian Zarnekow Messages: 3118 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
|
|
| | | |
Goto Forum:
Current Time: Thu Dec 12 17:23:36 GMT 2024
Powered by FUDForum. Page generated in 0.05121 seconds
|