Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Creating Cross-Reference between XExpression and XVariableDeclaration outside of XBlockExpression
Creating Cross-Reference between XExpression and XVariableDeclaration outside of XBlockExpression [message #1726279] Fri, 11 March 2016 01:11 Go to next message
Larry LeBron is currently offline Larry LeBronFriend
Messages: 124
Registered: October 2015
Senior Member
In my grammar, I am extending Xbase and using both XVariableDeclaration and XExpression, but I unfortunately need to work outside of XBlockExpression due to language design constraints.

I have everything working without errors, and my XExpressions can reference variables declared in my XVariableDeclarations, but the reference is occurring only at the level of the inferred class.

My variable declarations always have the warning: "the value of local variable is not used", even if they're used in an XExpression. Additionally, I do not get context assist recommendations including the variable declaration when writing an XExpression where the variable declaration should be in scope. Lastly, if I select "go to declaration" from inside an XExpression in Eclipse, instead of taking me to the variable declaration, it takes me to the name of the entity which is inferred as a class to contain the variable declaration and expression.

Any advice on the best way to solve this? I'm assuming it requires some bit of customizing scope, but there seem to be a few places to do that. What is the best practice? Thanks!

If it helps, here is a grammar, inferrer and a bit of sample code demonstrating the issue. I've made a small project solely to demonstrate this. I'll upload it with this post, in case that's helpful. The file extension is .xvartest

Here is some sample code. In this example, the first "x" is the variable declaration, and the second x is a reference to this declaration from an XExpression. There are no errors, but all of the issues I mentioned above exist.

Example:
entity myEnt {
	var x;
	exp x;
}


Here is the generated class for that:
public class myEnt {
  private Object x;
  
  public Object component2() {
    return this.x;
  }
}


Here is the grammar:
grammar org.xtext.example.XvarTest with org.eclipse.xtext.xbase.Xbase

generate xvarTest "http://www.xtext.org/example/XvarTest"

Model:
	entities += Entity*
;

Entity:
	'entity' name=ID '{'
		components += EntityComponent+
	'}'
;

EntityComponent:
	VarDecl | ExpressionComponent
;
	
VarDecl:
	decl=XVariableDeclaration';'
;

ExpressionComponent:
	'exp' exp=XExpression ';'
;


Here is the inferrer for Entity:
def void inferEntity(Entity entity, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		acceptor.accept(entity.toClass(entity.name)[
			var componentNum = 0
			
			for (component : entity.components) {
				componentNum++
				
				if (component instanceof VarDecl) {
					val varDecl = component as VarDecl
					val decl = varDecl.decl as XVariableDeclaration 
					members += entity.toField(decl.name, decl.type) [
						decl.right
					]
				} else if (component instanceof ExpressionComponent) {
					val exprComp = component as ExpressionComponent
					val expr = exprComp.exp
						members += entity.toMethod("component"+componentNum, typeRef(Object)) [
						body=expr
					]
				}
			}
		])
	}
  • Attachment: xvartest.zip
    (Size: 2.23MB, Downloaded 103 times)
Re: Creating Cross-Reference between XExpression and XVariableDeclaration outside of XBlockExpressio [message #1726287 is a reply to message #1726279] Fri, 11 March 2016 05:46 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14355
Registered: July 2009
Senior Member
why xvariabledeclaration?!?

NotXVariableDeclaration:
	{NotXVariableDeclaration}
	(writeable?='var'|'val') (=>(type=JvmTypeReference name=ValidID) | name=ValidID) ('=' right=XExpression)?;



val decl = varDecl.decl as NotXVariableDeclaration 
					members += decl.toField(decl.name, decl.type?:inferredType) [
						initializer = decl.right
					]


you dont get any completion cause xtext does not know any context if you write simply exp

you could try to workaround this but i dont know if this will help

ExpressionComponent:
	 exp=MyXBlockExpression
;

MyXBlockExpression returns xbase::XExpression: 
	{xbase::XBlockExpression}
	'exp' expressions+=XExpressionOrVarDeclaration ";";




Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Creating Cross-Reference between XExpression and XVariableDeclaration outside of XBlockExpressio [message #1726303 is a reply to message #1726287] Fri, 11 March 2016 08:53 Go to previous messageGo to next message
Larry LeBron is currently offline Larry LeBronFriend
Messages: 124
Registered: October 2015
Senior Member
Thanks for the recommendation. Switching to a custom implementation of variable declaration did the trick. Makes sense, since the validator warning was specifically tied to XVariableDeclaration.

As far as the context goes, unfortunately that workaround didn't seem to work off the bat.

There are two pieces to this:



  • Having Eclipse's "open declaration" jump to the variable declaration instead of jumping to the entity name
  • Populating content assist for exp with varDecl names


As far as getting "open declaration" to work, any hint at what state would need to be established to get a varDecl reference from an expression working as a "true" reference?

It looks like implementing this in the UI ProposalProvider works to get the variable declaration added in the content assist, though I'm not sure if it's the best implementation:


	override completeExpressionComponent_Exp(EObject expressionComponent, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		/* No proposal */
		if (!(expressionComponent instanceof ExpressionComponent) ) {
			return;
		}
		
		val entity = (expressionComponent as ExpressionComponent).eContainer;			
		
		(entity as Entity).components.forEach [
			if (it instanceof VarDecl) {
				val decl = it as VarDecl
				acceptor.accept (
					createCompletionProposal (
						decl.name, 
						decl.name, 
						null,
						context
					)
				)
			}	
		]
	}
Re: Creating Cross-Reference between XExpression and XVariableDeclaration outside of XBlockExpressio [message #1726304 is a reply to message #1726303] Fri, 11 March 2016 09:23 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14355
Registered: July 2009
Senior Member
hi

i tried that with xtext 2.9.2 and it does both

- Content assist (thus MyXBlockExpression )
- and reference: use the variable decl as source for the inferrer


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Creating Cross-Reference between XExpression and XVariableDeclaration outside of XBlockExpressio [message #1726305 is a reply to message #1726304] Fri, 11 March 2016 09:30 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14355
Registered: July 2009
Senior Member
(varDecl.toField)

Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Creating Cross-Reference between XExpression and XVariableDeclaration outside of XBlockExpressio [message #1726373 is a reply to message #1726305] Fri, 11 March 2016 22:41 Go to previous messageGo to next message
Larry LeBron is currently offline Larry LeBronFriend
Messages: 124
Registered: October 2015
Senior Member
Christian, I am again majorly in your debt.

Until this moment, I hadn't fully grasped the importance of choosing the source for the typerBuilder functions in the inferrer!

Yes, this completely works. Thank you very much!!
Re: Creating Cross-Reference between XExpression and XVariableDeclaration outside of XBlockExpressio [message #1726609 is a reply to message #1726373] Tue, 15 March 2016 05:24 Go to previous messageGo to next message
Larry LeBron is currently offline Larry LeBronFriend
Messages: 124
Registered: October 2015
Senior Member
A small follow-up on this.

With your suggested grammar, I do get content assist for the ExpressionComponent, which is great, but I do not for the VarDecl.

A reminder of that grammar (which you proposed below):

VarDecl:
	{VarDecl}
	(writeable?='var'|'val') (=>(type=JvmTypeReference name=ValidID) | name=ValidID) ('=' right=XExpression)?;

ExpressionComponent:
	 exp=MyXBlockExpression
;

MyXBlockExpression returns xbase::XExpression: 
	{xbase::XBlockExpression}
	'exp' expressions+=XExpressionOrVarDeclaration ";";


So, following your pattern, I tried making this change, assuming that if both used the "MyXBlockExpression" then everything would work:

VarDecl:
	{VarDecl}
	(writeable?='var'|'val') (=>(type=JvmTypeReference name=ValidID) | name=ValidID) ('=' right=MyXBlockExpression)? ';' ;

ExpressionComponent:
	 'exp' exp=MyXBlockExpression ';'
;

MyXBlockExpression returns xbase::XExpression: 
	{xbase::XBlockExpression}
	expressions+=XExpression;


This compiles fine, but I lose partial functionality of the content assist. When I first request proposals for the MyXBlockExpression piece of the grammar, I get no concrete proposals. However, once I've begun an XExpression, then content assist works.

For example:

Entity ent {
   var String s = "test";
   exp [content assist at this point does not include 's'] // content assist request 1
   exp "hello" + [content assist this point DOES include 's'] // content assist request 2
}


So, it seems like, at content assist request 1, the parser has not fully entered the MyXBlockExpression rule, or something of that nature.

I tried this experimental alteration of the grammar, making a dedicated XBlockExpression rule for both varDecl and expressionComponent, and everything works, but it's not as elegant and won't work for all situations:


VarDecl:
	{VarDecl}
	(writeable?='var'|'val') (=>(type=JvmTypeReference name=ValidID) | name=ValidID) (right=MyXBlockAssignment)? ;

MyXBlockAssignment returns xbase::XExpression: 
	{xbase::XBlockExpression}
	'=' expressions+=XExpression ';';

ExpressionComponent:
	 exp=MyXBlockExpression
;
MyXBlockExpression returns xbase::XExpression: 
	{xbase::XBlockExpression}
	'exp' expressions+=XExpression ';';


Is there a way to make my first example work? Perhaps I'm just missing something simple, like a specific use of "=>" ?
Re: Creating Cross-Reference between XExpression and XVariableDeclaration outside of XBlockExpressio [message #1726610 is a reply to message #1726609] Tue, 15 March 2016 05:28 Go to previous message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14355
Registered: July 2009
Senior Member
You have to debug proposal provider to see what's happens. Cannot help you
with that cause it would've too time intense


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Previous Topic:Xtext web editor -- as Orion plugin?
Next Topic:Standalone Testing Main function
Goto Forum:
  


Current Time: Thu Oct 06 07:23:54 GMT 2022

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

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

Back to the top