Home » Modeling » TMF (Xtext) » How to Cross-reference sub-elements ?(Trying to cross reference sub-elements of type declaration)
() 1 Vote
|
Re: How to Cross-reference sub-elements ? [message #549538 is a reply to message #549525] |
Tue, 27 July 2010 06:57 |
|
Hello Cyril,
welcome to Xtext. The solution for your problem is called "scoping". (see Scoping - especially dclarative scoping in the docs). by default References in Xtext are not aware of their context. in your case at MyCarDescription it shows you all CarTypes for the reference myCarType and not only those that fit myCar.
So what can you do. You have to change YourDsl Scope Provider
Here the sample for MyCarDescription
public class MyDslScopeProvider extends AbstractDeclarativeScopeProvider {
public IScope scope_MyCarDescription_myCarType(MyCarDescription mcd, EReference ref) {
return Scopes.scopeFor(mcd.getMyCar().getElements());
}
}
Regards
Christian
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
| |
Re: How to Cross-reference sub-elements ? [message #552050 is a reply to message #549822] |
Tue, 10 August 2010 16:05 |
Cyril Messages: 18 Registered: July 2010 |
Junior Member |
|
|
Hello,
I went further into the above solution and encounter a case when scope is given to the validator but not to content-assist, can you help get around this ?
So I added to my grammar the following :
BrandDescription :
'For the car brand ' brandname=[Cars] ', the following colored types exist : '
(elements+=ColorCarTypeDefinition)+
;
ColorCarTypeDefinition :
coloredcartype=[CarType] ' = ' color=ID ;
then I added to my ScopeProvider :
// Gives scope to editor validator but not to content-assist, why ?
public IScope scope_ColorCarTypeDefinition_coloredcartype(ColorCarTypeDefinition colorCarTypeDefinition, EReference ref) {
return Scopes.scopeFor(((BrandDescription)colorCarTypeDefinition.eContainer()).getBrandname().getElements());
}
we can see that when I write :
For the car brand Chrysler , the following colored types exist :
Voyager = blue
Horizon = red
Hybrid = yellow
That it correctly validates Voyager and Horizon but not Hybrid, that's great!
However content-assist does not work and does not propose 'Voyager and Horizon'. Can you tell me how I can correct my scope provider code in order to solve this.
Thanks a lot for your time
Cyril
[Updated on: Thu, 12 August 2010 15:32] Report message to a moderator
|
|
| |
Re: How to Cross-reference sub-elements ? [message #552556 is a reply to message #552200] |
Thu, 12 August 2010 15:48 |
Cyril Messages: 18 Registered: July 2010 |
Junior Member |
|
|
Thanks Meinte for your reply.
>(I'm not sure how the + modifier in "(elements+=ColorCarTypeDefinition)+" ensures that the generated parser will expect ColorCarTypeDefinition
To answer your comment I changed to :
BrandDescription :
'For the car brand ' brandname=[Cars] ', the following colored types exist : '
(elements+=ColorCarTypeDefinition)*
=>NO CHANGE
>You could verify this by typing 'V' and hitting Ctrl/Cmd-Space.
Result is:
V =
>Simple but unelegant solution: prepend ColorCarTypeDefinition with a token like "def" or something.
Could you develop your suggestion ?
If I look at some code for the content-assistant :
package org.xtext.example.mydsl.ui.contentassist;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.*;
import org.eclipse.xtext.common.ui.contentassist.TerminalsProposalProvider;
import org.eclipse.xtext.ui.editor.contentassist.ICompletionProposalAcceptor;
import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext;
/**
* Represents a generated, default implementation of interface {@link IProposalProvider}.
* Methods are dynamically dispatched on the first parameter, i.e., you can override them
* with a more concrete subtype.
*/
public class AbstractMyDslProposalProvider extends TerminalsProposalProvider {
...
public void completeColorCarTypeDefinition_Coloredcartype(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
lookupCrossReference(((CrossReference)assignment.getTerminal()), context, acceptor);
}
public void completeColorCarTypeDefinition_Color(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
completeRuleCall(((RuleCall)assignment.getTerminal()), context, acceptor);
}
...
public void complete_ColorCarTypeDefinition(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
// subclasses may override
}
}
I just started to read about how to customize content assist today in the middle of thousands other things.
If you have any example where I could speed up my training on this, or any other hints, I will greatly appreciate it.
Thanks for your time.
Cyril
|
|
| | |
Re: How to Cross-reference sub-elements ? [message #552708 is a reply to message #552604] |
Fri, 13 August 2010 08:53 |
Cyril Messages: 18 Registered: July 2010 |
Junior Member |
|
|
Wise remarks Alex as usual, thank you !
Most of the time, it gets a little bit technical to read your posts for non xtext pro like myself and I end up guessing around your suggestions.
This time I replaced my scope provider like this :
public IScope scope_ColorCarTypeDefinition_coloredcartype(EObject context, EReference ref) {
BrandDescription b=extractBrandDescriptionFromContext(context);
return Scopes.scopeFor(b.getBrandname().getElements());
}
private BrandDescription extractBrandDescriptionFromContext(EObject context) {
return (BrandDescription) context.eContainer();
}
Not too sure if that's what you suggested, but I tried to launch in debug, and observed when invoking code completion that it's (as you imagine) filling the EOject context parameter with Types others than ColorCarTypeDefinition.
What you're saying is that the default implementation goes through other parents types (shoud I say econtainers?) of ColorCarTypeDefinition and returns somehow fully qualified names which are not interpreted by content assist (the latter only proposing structure like IDs)
Great, I guess I understand that minor part
This interesting understood point does not however lead me to a hint of solution:
-Should I know and develop more complex Scope Provider code ?
-Is the behavior between validator and content assistant not suppose to work together around the same scoping code ?
Reading Dennis' Tables scopes thread made me feel less lonely on this
Can you still help us with sample solutions ?
(My simple grammar isn't a good base ?)
I would think this is something that comes up quite often for people working with xtext to want content-assist to go through inner scopes.
Since it works for the validator, what do I need to tell content-assist to be inspired identicly ?
On your last remarks "do not use keywords that include white spaces.", I'm not sure I got that part as well.
First of all, the power of content assist is to be used quite often for sentences which are uniques.
Why would we want to ctrl space 3 times with intermediate space bar touches to write "I own a" , when we can do it twice and have content assist put together "I own a " followed by a proposed list of words ?
Nevertheless, I tried :
'I' 'own' 'a' myCar=[Cars] 'of' 'type' myCarType=[CarType];
And Validator or content-assist did not like the last word 'a' or 'type' and the junction with the cross reference.
I did not observe the strange error you mention with two spaces before the equals.
In any cases, thanks so much for your suggestion, I am really eager to get the solution on how to write nice content-assist code; but I am guessing it's not that simple
Thanks for your time.
Cyril
|
|
|
Re: How to Cross-reference sub-elements ? [message #552726 is a reply to message #552708] |
Fri, 13 August 2010 09:21 |
Alexander Nittka Messages: 1193 Registered: July 2009 |
Senior Member |
|
|
> This time I replaced my scope provider like this :
>
> public IScope scope_ColorCarTypeDefinition_coloredcartype(EObject
> context, EReference ref) {
> BrandDescription b=extractBrandDescriptionFromContext(context);
> return Scopes.scopeFor(b.getBrandname().getElements());
> }
>
> private BrandDescription extractBrandDescriptionFromContext(EObject
> context) {
> return (BrandDescription) context.eContainer();
> }
This is basically the same as you had before. The point of the
extractBrandDescription...method is that it is not sufficient to return
the casted context.eContainer(). What if context is an instance of
BrandDescription already. In this case you should return context instead
of context.eContainer.
> Not too sure if that's what you suggested, but I tried to launch in
> debug, and observed when invoking code completion that it's (as you
> imagine) filling the EOject context parameter with Types others than
> ColorCarTypeDefinition.
See. So you have to react to the different types in different ways.
> What you're saying is that the default implementation goes through other
> parents types (shoud I say econtainers?) of ColorCarTypeDefinition and
> returns somehow fully qualified names which are not interpreted by
> content assist (the latter only proposing structure like IDs) Great, I
> guess I understand that minor part :)
Not quite. The default implementation looks for custom scoping
functions, starting with the most specific context type if it does not
find one, it tries to find a method with the type of the context's
container.
In your orignal implementation (context type ColorCarTypeDefinition) no
matching custom method could be found, so the "DefaultScoping" was
applied creating a scope with fully qualified names.
By changing the context parameter to EObject, you make sure that the
custom scoping function is found but now you have to make sure that the
context element is treated correctly.
An alternative would be to use your original scoping function and
public IScope
scope_ColorCarTypeDefinition_coloredcartype(BrandDescription context,
EReference ref) {
return Scopes.scopeFor(context.getBrandname().getElements());
}
> -Is the behavior between validator and content assistant not suppose to
> work together around the same scoping code ?
They do. But the setup is slightly different. Roughly speaking, the
validation can assume that the model is fully instantiated, code
completion cannot (as you wouldn't hit code completion if everything is
there already). This causes the context types to differ, which you have
to take into account when implementing the scoping methods.
> On your last remarks "do not use keywords that include white spaces.",
> I'm not sure I got that part as well.
The basic problem is if you have a keyword "I own" (with one space), you
cannot write "I own" (with two spaces) in the model.
> First of all, the power of content assist is to be used quite often for
> sentences which are uniques.
> Why would we want to ctrl space 3 times with intermediate space bar
> touches to write "I own a" , when we can do it twice and have content
> assist put together "I own a " followed by a proposed list of words ?
Well, how about writing a template that proposes "I own a
*variableForCar* of type *variableForType*" in one go. The variables are
used to allow further content assists *within* the template proposal.
See the documentation on template proposals in the Xtext documentation
and http://blogs.itemis.de/stundzig/archives/474 (you won't need your
own template variable resolver)
Alex
Need training, onsite consulting or any other kind of help for Xtext?
Go visit http://xtext.itemis.com or send a mail to xtext@itemis.de
|
|
|
Re: How to Cross-reference sub-elements ? [message #552729 is a reply to message #552708] |
Fri, 13 August 2010 09:36 |
Alexander Nittka Messages: 1193 Registered: July 2009 |
Senior Member |
|
|
> On your last remarks "do not use keywords that include white spaces.",
> Nevertheless, I tried :
> 'I' 'own' 'a' myCar=[Cars] 'of' 'type' myCarType=[CarType];
> And Validator or content-assist did not like the last word 'a' or 'type'
> and the junction with the cross reference.
Of course you have to remove the spaces from *all* keywords in the
grammar. Basically everything placed in single or double quotes is a
keyword (stuff in terminal rules excluded).
I bet type was marked as an error as "type " (with space) is a keyword
in the CarType definition.
Alex
Need training, onsite consulting or any other kind of help for Xtext?
Go visit http://xtext.itemis.com or send a mail to xtext@itemis.de
|
|
|
Goto Forum:
Current Time: Fri Apr 26 00:33:36 GMT 2024
Powered by FUDForum. Page generated in 0.03615 seconds
|