Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Cross-linking to alternative representations (not always having the 'name' attribute)?
Cross-linking to alternative representations (not always having the 'name' attribute)? [message #670266] Fri, 13 May 2011 10:19 Go to next message
Pavol Mederly is currently offline Pavol MederlyFriend
Messages: 3
Registered: May 2011
Junior Member
Hello,

in my language I would like to declare variables in two ways - using an explicit variable name (i.e. "variable <type> <name>") or using implicit name, derived from the type name (i.e. just "variable <type>").

Then I would like to link to both kinds of these definitions, i.e. having "ref <variable-name>".

E.g.

type Type1;
variable Type1 var1; // explicit form
variable Type1; // implicit form (it should declare variable 'type1')
ref var1; // this works
ref type1; // this is desired but does not work


The grammar currently looks like this:

All:
(variables+=Variable | types+=Type | references+=Reference)*;

Type: 'type' name=ID ';';

Variable:
'variable' type=[Type] name=ID? ';' ;

Reference:
'ref' item=[Variable] ';' ;


What is the best way to achieve this goal? (I would like to have the "Ctrl-Space"
functionality as well.) Also, it should be usable with namespaces - after trying hardly (and unsuccessfully) in that context, however, I have prepared this simple example to show the essence of the problem.

I know that I have to initialize the 'name' attribute of the implicit variable declarations somehow, but I do not know how. Or I have to customize IQualifiedNameProvider to return a name derived from the name of type (in the 'implicit' version). However, I am not able to determine the type name at the runtime (in the IQualifiedNameProvider), as I always get "Cyclic resolution of lazy links" errors.

Please, how to best achieve that goal?

Thank you in advance.
Pavol

PS: here is the code for the modified IQualifiedNameProvider, taken out from the original context:

public String getQualifiedName(final EObject obj) 
{
  return cache.get(Tuples.pair(obj, "fqn"), obj.eResource(), new Provider<String>()
  {
    public String get() 
    {
      EObject temp = obj;
      String value;
      if (temp instanceof Variable)
      {
        Variable v = (Variable) temp;
	value = v.getName();
	if (value != null)
	  return value;
					
	value = v.getType().getName();  // here it cycles!
	if (value == null || "".equals(value))
	  return null;
	else
	  return Character.toLowerCase(value.charAt(0)) + value.substring(1);
      }

      String name = qualifiedName.invoke(temp);
      if (name != null)
        return name;

      value = resolver.getValue(temp);
      if (value == null)
        return null;
				
      while (temp.eContainer() != null) {
        temp = temp.eContainer();
        String parentsName = getQualifiedName(temp);
        if (parentsName != null)
          return parentsName + getDelimiter() + value;
      }
      return value;
    }
  });
Re: Cross-linking to alternative representations (not always having the 'name' attribute)? [message #670514 is a reply to message #670266] Sat, 14 May 2011 15:47 Go to previous messageGo to next message
Alexander Nittka is currently offline Alexander NittkaFriend
Messages: 1193
Registered: July 2009
Senior Member
Hi,

my first approach would also be to go via a custom qualified name provider. However, do not implement the interface but rather extend DefaultDeclarativeQualifiedNameProvider and use the polymorphic dispatch.
Implement a method qualifiedName(Variable x) and return the "super" call if the name attribute is set and your default type name if not.

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: Cross-linking to alternative representations (not always having the 'name' attribute)? [message #670792 is a reply to message #670514] Sun, 15 May 2011 15:16 Go to previous messageGo to next message
Pavol Mederly is currently offline Pavol MederlyFriend
Messages: 3
Registered: May 2011
Junior Member
Hello Alex,

thank you for the reply. I've tried it, creating own QNameProvider as you have suggested:

public String qualifiedName(Variable var)
{
    if (var.getName() != null)
        return var.getName();
    else
        return var.getType().getName();
}

However, I get the same errors are before: An internal error occurred during: "Xtext validation". Cyclic resolution of lazy links : Variable.type->Variable.type.

After some experiments it seems that the problem is in that the variable type is a reference (not a simple terminal):

Variable: 
  'variable' type=[Type] name=ID? ';' ;

The "type" ecore feature is then a proxy. The VariableImpl.getType() method fails when trying to resolve EObject proxy for "type". More specifically, when resolving "type" proxy it seems that the framework tries to determine QNames for (all?) entities in the source file, our variable element being among them (there comes the cycle - it calls again the getType() and eResolveProxy(type) within it).

Out of total despair I tried to modify ANTLR grammar description, changing a type-matching part of the rule for Variable like this:

typename=RULE_ID
{
    // original code
    createLeafNode(grammarAccess.getVariableAccess().getTypeTypeCrossReference_1_0(), "type");
    // added code
    System.out.println("Setting type name: " + typename); 
    try {
        set(
          $current, 
	  "name",
	  typename,
	  "ID", 
	  lastConsumedNode);
    } catch (ValueConverterException vce) {
      handleValueConverterException(vce);
    }
} 

Being a novice in Xtext/Ecore/ANTLR it is a pure guess, unfortunately Sad Actually, it seems to work, but such a modification of a generated code is obviously rather unclean and I'm not sure if it has not any unexpected negative consequences (i.e. will it really work?).

Is there a cleaner way? Perhaps by using some more sophisticated action in Xtext grammar? (BTW, what are allowed kinds of Xtext actions? In the documentation I have only saw {Class} and {Class.feature=current} ones...)

Thank you in advance!
Pavol
Re: Cross-linking to alternative representations (not always having the 'name' attribute)? [message #670823 is a reply to message #670792] Sun, 15 May 2011 18:37 Go to previous messageGo to next message
Alexander Nittka is currently offline Alexander NittkaFriend
Messages: 1193
Registered: July 2009
Senior Member
Hi,

currently, I have no idea for a clean solution. The main problem is that the name calculation is done before the linking (of course, as the linking depends on the names of elements). Hence resolving cross references (as opposed to containment references) during the name calculation is a bit of a problem.

You can of course bind your own parser (it is not necessary to edit the generated sources). Extend the generated one only overriding the problematic method and bind your implementation in the runtime module. But in your case, I would rather "hack" the qualified name calculation.

If your sample is not simplified too much, something like the following might be good enough for you.
String qualifiedName(Variable var){
		if (var.getName() != null){
			return var.getName();
		}
	    else{
	    	//go to the parse tree and extract the actual string used for referencing
	    	//note that you have to substitute MyDslPackage with the package of your language
			List<AbstractNode> typeNodes=NodeUtil.findNodesForFeature(var, MyDslPackage.eINSTANCE.getVariable_Type());
			//brute force concatenation, please actually test that the terminal rule behind the abstract node (LeafNode)
			//is not a comment, otherwise the comment is added to the name, same is true for white spaces
			String name="";
			for (AbstractNode abstractNode : typeNodes) {
				name+=abstractNode.serialize();
			}
			//trim is just a quick and dirty workaround
	        return name.trim().toLowerCase();

	    }
	}


Alex

P.S.: please note that this is really a quick and dirty workaround
Re: Cross-linking to alternative representations (not always having the 'name' attribute)? [message #670917 is a reply to message #670823] Mon, 16 May 2011 07:59 Go to previous message
Pavol Mederly is currently offline Pavol MederlyFriend
Messages: 3
Registered: May 2011
Junior Member
Hello Alex,

I've done it as you have suggested (including testing the GrammarElement/RuleCall behind the LeafNode), and it works perfectly, even in my original context.

Thanks a lot for the solution! Smile

Pavol
Previous Topic:Xtend2 - try/catch resulting in invalid xblockexpression
Next Topic:Ctr+Clik
Goto Forum:
  


Current Time: Fri Apr 26 22:15:52 GMT 2024

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

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

Back to the top