Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Help debugging a scope provider
Help debugging a scope provider [message #1765920] Wed, 14 June 2017 13:32 Go to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
I am trying to add a scope provider for a DSL. The DSL code is as follows:

Caste Moose() {
   action Sheep  (Horse:Int) {
   		create dog of Moose (2);
   		var Camel : Int;
   		Camel := 3;	
   }		
   action Pig (Horse:Int) {
   	  Camel := 2;
   }
}


The code added to the ScopeProvider class for VarNames is:

if (context instanceof VarName) {
  // Work up through containers.
  val varsInScope = new ArrayList<VarName>
  var currentContainer = reference.eContainer
  while (currentContainer !== null) {
    switch currentContainer {
      ForStatement:
        if (currentContainer.newVar !== null) 
          varsInScope.add(currentContainer.newVar)
        WithStatement:
          if (currentContainer.newVar !== null)
           varsInScope.add(currentContainer.newVar)
	Statements: {
          val locals = EcoreUtil2.getAllContentsOfType(currentContainer,
                               LocalVariableDeclaration)
          locals.forEach([local | varsInScope.add(local.getVar().name)])
        }
	CasteDeclaration: {
	  val globals = EcoreUtil2.getAllContentsOfType(currentContainer, 
                                 VarDeclaration)
	  globals.forEach([global | varsInScope.add(global.getVar().name)])
        }
      }
      currentContainer = currentContainer.eContainer
  }
  return Scopes.scopeFor(varsInScope)
}


Looking at the Outline view in the runtime Eclipse, I can see correctly that the declarations of Pig and Sheep are in different branches of the common declaration of Moose, and so one should not be reached by a chain of containment from the other. Nonetheless the IDE continues to state that Camel is in scope in Pig, and when asked to "go to declaration" goes to the one inside Sheep. Can anyone help with this? I tried with initializing currentContainer to both reference.eContainer and context.eContainer and the result was the same. Is it possible to produce debug output in a context provider in this way?

Re: Help debugging a scope provider [message #1765930 is a reply to message #1765920] Wed, 14 June 2017 13:47 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
can you give some more context regarding the grammar you use

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765931 is a reply to message #1765930] Wed, 14 June 2017 13:51 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
another point:

var currentContainer = reference.eContainer
while (currentContainer !== null) {

walks up to the root

=> everything i a child of that root

=>

CasteDeclaration: {
val globals = EcoreUtil2.getAllContentsOfType(currentContainer,
VarDeclaration)
globals.forEach([global | varsInScope.add(global.getVar().name)])

will find everything


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765951 is a reply to message #1765931] Wed, 14 June 2017 14:52 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Hi:

The grammar for Statements is:
Statements:
	code+=Statement*
;

Statement:
	LocalVariableDeclaration |
	PrimaryStatement |
	IfStatement |
	CaseStatement |
	WhileStatement |
	ForStatement |
	RepeatStatement |
	LoopStatement |
	WhenStatement |
	TillStatement |
	WithStatement |
	';'
;
LocalVariableDeclaration:
	VAR var=VarNameAndType (':=' initial=Expression)? ';'
;


The VarDeclaration grammar rule is only applied in the context of the top level CasteDeclaration:

CasteDeclaration:
	CASTE castename=CasteName '(' params=FormalParamList? ')'
	    (EXTEND parent=[CasteName|ID])?
	'{'
	  observes+=ObserveDeclaration*
	  vars+=VarDeclaration*
	  actions+=ActionDeclaration*
	  init=InitDeclaration?
	  routine=RoutineDeclaration?
	'}'
	;
VarDeclaration:
	state?=STATE? VAR var=VarNameAndType ';'
;


Therefore while I understand that doing getAllContentsOfType should find everything, there should be no Statements block which is a common ancestor of Sheep and Pig (I have confirmed this in the Outline view), and the search for all VarDeclarations should not find the declaration of Camel because it is not a VarDeclaration, it is a LocalVariableDeclaration.
Re: Help debugging a scope provider [message #1765953 is a reply to message #1765951] Wed, 14 June 2017 14:55 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
what i understand

- caste is the root
- it has vars (the one you are searching for)
- and it has ActionDeclaration. which have vars.

=> caste.getAllContentsOfType will give you the vars it directly has and the vars of its actions

=> camel is a grand child of caste Moose
=> it is visible inside Sheep and inside pig


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765960 is a reply to message #1765953] Wed, 14 June 2017 15:26 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Quote:
- caste is the root
- it has vars (the one you are searching for)
- and it has ActionDeclaration. which have vars.


ActionDeclaration:
    internal?=INTERNAL? ACTION name=ActionName '(' params=FormalParamList ')' '{' body=Statements '}'	
;


ActionDeclaration has vars, but they are inside the Statements block.

In the context of Statements the DSL VAR keyword matches the rule LocalVariableDeclaration, not VarDeclaration.

Therefore, ActionDeclaration should have no child or grandchild VarDeclarations, only LocalVariableDeclarations (I have confirmed this in the outline).

Therefore the LocalVariableDeclarations inside Action should not be found when getting all VarDeclarations on the Caste, because they are not VarDeclarations, they are LocalVariableDeclarations.

[Updated on: Wed, 14 June 2017 15:30]

Report message to a moderator

Re: Help debugging a scope provider [message #1765961 is a reply to message #1765960] Wed, 14 June 2017 15:30 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
well i can only guess without anything at hands.
you are sure the decls dont come from an accidental super.getScope call?

and: if you scope VarNames

how can it point to a VarDeclaration and a LocalVariableDeclaration ?!? as your scoping implys


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765963 is a reply to message #1765961] Wed, 14 June 2017 15:44 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
I haven't ever written super.getScope() myself, is it used internally somewhere?

As for scoping VarNames, my understanding is that the Context object is where in the parse tree the reference was found, is that right? So if a VarName is in say, an assignment statement, it will work out from that assignment looking for LocalVariableDeclarations in surrounding Statements or VarDeclarations in surrounding Castes.

What I am hoping it will do is:
Camel := 3
- VarName Reference Camel
-> In AssPrimary in AssField in Assignable in Assignment in PrimaryStatement Camel := 3
-> In Statements (body of Sheep) which also contains LocalVariableDeclaration Camel which is added to the list
-> In ActionDeclaration
-> In CasteDeclaration Moose which has no VarDeclarations
Therefore Camel in scope because it was found in the Statements.

Camel := 2
- Varname Reference Camel
-> In AssPrimary in AssField in Assignable in Assignment in PrimaryStatement Camel := 2
-> In Statements (body of Pig) which has no LocalVariableDeclarations
-> In ActionDeclaration
-> In CasteDeclaration Moose which has no VarDeclarations
Therefore not in scope because the list of possible variables is empty.

VarName is internally referred to in LocalVariableDeclaration and VarDeclaration but has no reference brackets in those contexts so I presume does not trigger scope checking?

[Updated on: Wed, 14 June 2017 15:47]

Report message to a moderator

Re: Help debugging a scope provider [message #1765964 is a reply to message #1765963] Wed, 14 June 2017 15:49 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
yes but i dont see in your grammar snippets how

- VarDeclaration

and

- VarName (the reference) look like


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765965 is a reply to message #1765964] Wed, 14 June 2017 15:50 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
=> can you share a grammar with camel, actions and the vars and rererences and a complete scope provider class

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765969 is a reply to message #1765965] Wed, 14 June 2017 15:55 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Entire grammar:

grammar obuaop.Caople with org.eclipse.xtext.common.Terminals

generate caople "http://www.Caople.obuaop"

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





Model hidden (WS, ML_COMMENT, SL_COMMENT):
	imports=ImportClause?
	uses=UsesClause?
	caste=CasteDeclaration
	;
	
CasteDeclaration:
	CASTE castename=CasteName '(' params=FormalParamList? ')'
	    (EXTEND parent=[CasteName|ID])?
	'{'
	  observes+=ObserveDeclaration*
	  vars+=VarDeclaration*
	  actions+=ActionDeclaration*
	  init=InitDeclaration?
	  routine=RoutineDeclaration?
	'}'
	;
	
ImportClause:
	IMPORT (defPackNames+=ID) (',' defPackNames+=ID)* ';'
;

UsesClause:
	USES (importCasteNames+=CasteName) (',' importCasteNames+=CasteName)* ';'
;

ObserveDeclaration:
	OBSERVE scope=ScopeType observed=ID IN? castes+=[CasteName] (',' castes+=[CasteName])* ';'
;

VarDeclaration:
	state?=STATE? VAR var=VarNameAndType ';'
;

ActionDeclaration:
    internal?=INTERNAL? ACTION name=ActionName '(' params=FormalParamList ')' '{' body=Statements '}'	
;

InitDeclaration:
	INIT '{' body=Statements '}'
;

RoutineDeclaration:
	BODY '{' body=Statements '}'
;

Statements:
	code+=Statement*
;

Statement:
	LocalVariableDeclaration |
	PrimaryStatement |
	IfStatement |
	CaseStatement |
	WhileStatement |
	ForStatement |
	RepeatStatement |
	LoopStatement |
	WhenStatement |
	TillStatement |
	WithStatement |
	';'
;

LocalVariableDeclaration:
	VAR var=VarNameAndType (':=' initial=Expression)? ';'
;

PrimaryStatement:
	{Assignment} target=Assignable ":=" val=Expression ';' |
	{Call} action=[ActionName] '(' params=ActualParamList ')' ';' |
	{Create} CREATE name=AgentName OF caste=[CasteName] '(' params=ActualParamList ')' 
	         (FROM ceIp=Expression)? (AT leeIp=Expression)?  |
	{Super} SUPER ( params=ActualParamList ) |
	{Join} JOIN (caste=[CasteName]) '(' params=ActualParamList ')' |
	{Suspend} SUSPEND (caste=[CasteName]) |
	{Resume} RESUME (caste=[CasteName]) |
	{Quit} QUIT (caste=[CasteName]) 
	
;

IfStatement:
	IF '(' condition=Expression ')' '{' trueBranch=Statements '}'
	(=> ELSE '{' falseBranch=Statements '}' )
;

CaseStatement:
	CASE '(' condition=Expression ')' '{'
	  ((matches+=Expression) '->' '{' (bodies+=Statements) '}')+
	  (ELSE '{' (elseBody=Statements) '}')?
	'}'
;

WhileStatement:
	WHILE '(' condition=Expression ')' '{' (body=Statements) '}' 
;

RepeatStatement:
	REPEAT '{' (body=Statements) '}' UNTIL '(' condition=Expression ')'
;

LoopStatement:
    LOOP '{' body=Statements '}'
;

ForStatement:
	FOR (var=[VarName] | VAR newVar=VarName) 
	 ((":=" startValue=ExpAdditive TO endValue=ExpAdditive) |
	  (IN forList=Expression))
	'{' body=Statements '}'	
;

WithStatement:
	WITH '(' (var=[VarName] | VAR newVar=VarName) '=' (old=Expression) ')' '{' body=Statements '}'
;

WhenStatement:
	WHEN EventExpression '{' body=Statements '}' 
;

TillStatement:
	TILL EventExpression '{' body=Statements '}'
;

EventExpression:
	EXIST (agent=VarName) IN (caste=[CasteName]) |
	((agent=VarName) | SELF) ':' (action=ActionName) '(' params=ActualParamList? ')'
;

Assignable: {Operation} left=AssField ('[' index=Expression ']')?;
AssField: {Operation} left=AssPrimary ('.' field=[FieldName])?;
AssPrimary: var=[VarName] ;


// Herewith the joy of left factored operators with priority

Expression: ExpBinOr;
ExpBinOr: {Operation} left=ExpBinAnd (ops+='||' rights+=ExpBinAnd)*;
ExpBinAnd: {Operation} left=ExpEquality (ops+='&&' rights+=ExpEquality)*;
ExpEquality: {Operation} left=ExpRelational (ops+=('==' | '!=') rights+=ExpRelational)*;
ExpRelational: {Operation} left=ExpAdditive (ops+=('<' | '>' | '<=' | '=>') rights+=ExpAdditive)*;
ExpAdditive: {Operation} left=ExpMulti (ops+=('+' | '-') rights+=ExpMulti)*;
ExpMulti: {Operation} left=ExpUnary (ops+=("*" | "/" | "%") right+=ExpUnary)*;
ExpUnary: {Operation} op=("!" | "-" | "+")? left=ExpElement ;
ExpElement: {Operation} left=ExpField ('[' index=Expression ']')?;
ExpField: {Operation} left=ExpPrimary ('.' field=[FieldName])?;
ExpPrimary: literal=Literal | var=[VarName] ('#' state=[VarName] ) ;



Literal:
	{StringLiteral} string=STRING |
	{IntLiteral} int=INT |
	{BoolLiteral} bool=BOOL |
	{RealLiteral} real=RealLiteral |
	{StructLiteral} struct=StructuredLiteral |
	{EnumLiteral} enumValue=[EnumValue]
;


RealLiteral returns ecore::EDouble:
	INT '.' INT 
;

StructuredLiteral:
	type=[TypeName] ':' (list=ListLiteral | struct=StructLiteral)
;

ListLiteral:
	'[' members+=Literal (',' members+=Literal)* ']'
;

StructLiteral:
	'{' fields+=[FieldName] ':' values+=Literal (',' fields+=[FieldName] ':' values+=Literal)* '}'
;

StateExpression:
	agent=[VarName] '#' state=[VarName]
;

enum BOOL:
	TRUE='true' | TRUE='True' | TRUE='TRUE' |
	FALSE='false' | FALSE='False' | FALSE='FALSE'
;

ScopeType:
	ONLY | SOME | ALL
;


FormalParamList:
	params+=VarNameAndType (',' params+=VarNameAndType)* 
;

ActualParamList:
	params+=Expression (',' params+=Expression)*
;

VarNameAndType:
	name=VarName ':' type=Type
;

FieldNameAndType:
	name=FieldName ':' type=Type
;



Type:
	TYPE_INTEGER | 
	TYPE_REAL | 
	TYPE_BOOL | 
	TYPE_STRING |
	AGENT ('{' agent=[CasteName | ID] '}' ) |
	type=[TypeName | ID] |
	structDef |
	listDef |
	enumDef
;

structDef:
	STRUCT '{'
	  ((fields+=FieldNameAndType) ';')+
	'}'
;

listDef:
	LIST '{' elementType=Type '}'
;

enumDef:
	ENUM '{' enumValues+=EnumValue ( ',' enumValues+=EnumValue )* '}'
;

// Identifier types for contextual inference

CasteName:
	name=ID
;

TypeName:
	name=ID
;

EnumValue:
	name=ID
;

VarName:
	name=ID
;

FieldName:
	name=ID
;

ActionName:
	name=ID
;

AgentName:
	name=ID
;

terminal CASTE : "caste" | "Caste" | "CASTE";
terminal AGENT : "agent" | "Agent" | "AGENT";
terminal EXTEND : "extend" | "Extend" | "EXTEND";
terminal TYPE_INTEGER : "int" | "Int" | "INT";
terminal TYPE_REAL : "real" | "Real" | "REAL";
terminal TYPE_BOOL : "bool" | "Bool" | "BOOL";
terminal TYPE_STRING : "string" | "String" | "STRING";
// terminal TYPE_AGENT : "agent" | "Agent" | "AGENT";
terminal IMPORT : "import" | "Import" | "IMPORT";
terminal USES : "uses" | "Uses" | "USES";
terminal STRUCT : "struct" | "Struct" | "STRUCT";
terminal LIST : "list" | "List" | "LIST";
terminal ENUM : "enum" | "Enum" | "ENUM";
terminal OBSERVE : "observe" | "Observe" | "OBSERVE";
terminal ONLY : "only" | "Only" | "ONLY";
terminal SOME : "some" | "Some" | "SOME";
terminal ALL : "all" | "All" | "ALL";
terminal IN : "in" | "In" | "IN";
terminal STATE : "state" | "State" | "STATE";
terminal VAR : "var" | "Var" | "VAR";
terminal ACTION : "action" | "Action" | "ACTION";
terminal INTERNAL : "internal" | "Internal" | "INTERNAL";
terminal INIT : "init" | "Init" | "INIT";
terminal BODY : "body" | "Body" | "BODY";
terminal IF : "if" | "If" | "IF";
terminal ELSE : "else" | "Else" | "ELSE";
terminal CASE : "case" | "Case" | "CASE";
terminal WHILE : "while" | "While" | "WHILE";
terminal REPEAT : "repeat" | "Repeat" | "REPEAT";
terminal UNTIL : "until" | "Until" | "UNTIL";
terminal LOOP : "loop" | "Loop" | "LOOP";
terminal FOR : "for" | "For" | "FOR";
terminal TO : "to" | "To" | "TO";
terminal WITH : "with" | "With" | "WITH";
terminal WHEN : "when" | "When" | "WHEN";
terminal TILL : "till" | "Till" | "TILL";
terminal EXIST : "exist" | "Exist" | "EXIST";
terminal SELF : "self" | "Self" | "SELF";
terminal CREATE : "create" | "Create" | "CREATE";
terminal OF : "of" | "Of" | "OF" ;
terminal FROM: 'from' | "From" | "FROM" ;
terminal AT: 'at' | "At" | "AT" ;
terminal SUPER: "super" | "Super" | "SUPER";
terminal JOIN: "join" | "Join" | "JOIN" ;
terminal SUSPEND: "suspend" | "Suspend" | "SUSPEND" ;
terminal RESUME: "resume" | "Resume" | "RESUME" ;
terminal QUIT: "quit" | "Quit" | "QUIT" ;


// WS, ID, and INT are defined by the Xtext standard terminals



Scope Provider:

class CaopleScopeProvider extends AbstractCaopleScopeProvider {

	
	 def GetScope(EObject context, EReference reference) {
		if (context instanceof CasteName) {
			// Caste names only come from two places: the uses clause, and the definition
			// itself.
			val rootElement = EcoreUtil2.getRootContainer(context)
			val usesElements = EcoreUtil2.getAllContentsOfType(rootElement, UsesClause)
			val usedCasteNames = new ArrayList<CasteName>
			usesElements.forEach([UsesClause ue | usedCasteNames.addAll(EcoreUtil2.getAllContentsOfType(ue, CasteName))]);
			val casteDefinitions = EcoreUtil2.getAllContentsOfType(rootElement, CasteDeclaration)
			casteDefinitions.forEach([CasteDeclaration cd | usedCasteNames.add(cd.castename)]);
			return Scopes.scopeFor(usedCasteNames);
		}
		if (context instanceof VarName) {
			// Work up through containers.
			val varsInScope = new ArrayList<VarName>
			var currentContainer = reference.eContainer
			while (currentContainer !== null) {
				switch currentContainer {
					ForStatement:
						if (currentContainer.newVar !== null) varsInScope.add(currentContainer.newVar)
					
					WithStatement:
						if (currentContainer.newVar !== null) varsInScope.add(currentContainer.newVar)
						
					Statements: {
						val locals = EcoreUtil2.getAllContentsOfType(currentContainer, LocalVariableDeclaration)
						locals.forEach([local | varsInScope.add(local.getVar().name)])
					}
					
					CasteDeclaration: {
						val globals = EcoreUtil2.getAllContentsOfType(currentContainer, VarDeclaration)
					    globals.forEach([global | varsInScope.add(global.getVar().name)])	
					}
				}
				currentContainer = currentContainer.eContainer
			}
			return Scopes.scopeFor(varsInScope)
				                                                                          
		}
	}
	
	
}

Re: Help debugging a scope provider [message #1765975 is a reply to message #1765969] Wed, 14 June 2017 16:15 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Hi, the scope provider naming looks bad to me should be


override getScope(EObject context, EReference reference) {
if (...) {
return ....
}
return IScope.NULLSCOPE // or super.getScope(context, reference)

}

then reference you scope looks like

AssPrimary: var=[VarName] ;

=> you actually reference a VarName

AssPrimary: var=[VarName] ;

=> your if/else are wrong
the context is where you are, the reference is where you point to

=> maybe

override getScope(EObject context, EReference reference) {
		if (reference.EType == MyDslPackage.Literals.CASTE_NAME) {
			// Caste names only come from two places: the uses clause, and the definition
			// itself.
			val rootElement = EcoreUtil2.getRootContainer(context)
			val usesElements = EcoreUtil2.getAllContentsOfType(rootElement, UsesClause)
			val usedCasteNames = new ArrayList<CasteName>
			usesElements.forEach([UsesClause ue | usedCasteNames.addAll(EcoreUtil2.getAllContentsOfType(ue, CasteName))]);
			val casteDefinitions = EcoreUtil2.getAllContentsOfType(rootElement, CasteDeclaration)
			casteDefinitions.forEach([CasteDeclaration cd | usedCasteNames.add(cd.castename)]);
			return Scopes.scopeFor(usedCasteNames);
		}
		if (reference == MyDslPackage.Literals.ASS_PRIMARY__VAR) {
			// Work up through containers.
			val varsInScope = new ArrayList<VarName>
			var currentContainer = context.eContainer
			while (currentContainer !== null) {
				switch currentContainer {
					ForStatement:
						if (currentContainer.newVar !== null) varsInScope.add(currentContainer.newVar)
					
					WithStatement:
						if (currentContainer.newVar !== null) varsInScope.add(currentContainer.newVar)
						
					Statements: {
						val locals = EcoreUtil2.getAllContentsOfType(currentContainer, LocalVariableDeclaration)
						locals.forEach([local | varsInScope.add(local.getVar().name)])
					}
					
					CasteDeclaration: {
						val globals = EcoreUtil2.getAllContentsOfType(currentContainer, VarDeclaration)
					    globals.forEach([global | varsInScope.add(global.getVar().name)])	
					}
				}
				currentContainer = currentContainer.eContainer
			}
			return Scopes.scopeFor(varsInScope)
				                                                                          
		}
		//maybe super.getScope(context, reference)
		return IScope.NULLSCOPE
	}



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765976 is a reply to message #1765975] Wed, 14 June 2017 16:20 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Could you explain that about the reference a bit more? "The reference is where you point to" but if we still need to determine what is in scope, how can the parser know what it points to (since it would need to point to something in scope)?

At the moment I don't understand this line
if (reference == MyDslPackage.Literals.ASS_PRIMARY__VAR) {


At all, AssPrimary's Var feature is not a Literal, and why would the reference be equal to this? Would a different variable reference be equal to the same thing? Also this typing should be applied to variables used in any expression not just assignments (although the test was on assignments)

Edit: Also unfortunately the code above did not fix the problem.

[Updated on: Wed, 14 June 2017 16:29]

Report message to a moderator

Re: Help debugging a scope provider [message #1765977 is a reply to message #1765976] Wed, 14 June 2017 16:32 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
xtext derives a ecore metamodel from your grammar.

in my case

generate myDsl "http://www.xtext.org/example/mydsl3/MyDsl"

AssPrimary: var=[VarName] ;

and emf generates contstants for classes, attributes and references

=> package = MyDslPackage (in your case caoplePackage)

inside the inner interface literals are the constants.

the are like <TyoeName>__<refname>

so

ASS_PRIMARY__VAR

or

reference.EType == MyDslPackage.Literals.CASTE_NAME if you want to know what type the name is of (EReference.EType)

when xtext calls scope it says:

here is my context. this the the object in the ast where i am at
and here is the EReference (the xxx=[]) thingy that i am currently scoping

=> you need to file out where you are and what you scope (if else in the scope method)
and then collect the stuff


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765979 is a reply to message #1765977] Wed, 14 June 2017 16:40 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Ok, thanks. So context is equivalent to reference.econtainer? Because at the time when we do the scoping we must be parsing the reference? Or can they be done at different times?
Re: Help debugging a scope provider [message #1765982 is a reply to message #1765979] Wed, 14 June 2017 17:03 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
no

reference.eContainer is the EClass
context is the "instance" of that EClass.
(during content assist it might be an ancestor as well)


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765983 is a reply to message #1765982] Wed, 14 June 2017 17:05 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
and no

xtext first parses the model
then xtext index entries are built.
then the model is linked

=> when you scope the ast (with emphasis on TREE) is already there so you can walk up and down as you do it.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765985 is a reply to message #1765983] Wed, 14 June 2017 17:13 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Ok, thanks. Sorry for being a bit dense, but I am having trouble understanding this...
Quote:

reference.eContainer is the EClass


Reference.eContainer, in Java terms, is an instance of class EObject. An EClass is also a Java instance of EObject. So am I right in what you're saying is that Reference.eContainer returns an EObject with ground type EClass; and that object represents the prototype of the type of container the reference is within. So if the reference is within (say) an Assignable, then reference.eContainer will point to a Java-object representing the TMF-prototype of the Assignable class? Meanwhile, context will point to an EObject representing the actual instance? So context.eClass() == reference.eContainer ?


Re: Help debugging a scope provider [message #1765987 is a reply to message #1765985] Wed, 14 June 2017 17:20 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
yes context.eClass() == reference.eContainer is correct if you leave type inhertiance out of the play

EClass is a Prototype of an EObject
it has EAttributes and EReferences that describe values (EAttribute) and complex values/objects (EReference with containmaint=true) and cross references (EReference with containmaint=false)

An EObject and its values are instances of these prototypes


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765990 is a reply to message #1765987] Wed, 14 June 2017 17:28 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Ok, so is context.eContainer also a prototype rather than an instance? Is this bug coming up because we are calling getAllContentsOfType on a prototype?
Re: Help debugging a scope provider [message #1765991 is a reply to message #1765990] Wed, 14 June 2017 17:34 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
no

context.eContainer is the parent

my kitchens eContainer is my flat
your kitchens eContainer is your flat



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765992 is a reply to message #1765991] Wed, 14 June 2017 17:35 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
So the meaning of the eContainer property in an eObject changes with the ground type of that EObject? :(

Is there any way to get debug output from the scope provider?

[Updated on: Wed, 14 June 2017 17:38]

Report message to a moderator

Re: Help debugging a scope provider [message #1765994 is a reply to message #1765991] Wed, 14 June 2017 17:37 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Parent: "parent" name=ID "{"
child=Child
"}";

Child: "c" name=ID;

parent P1 {
c c1
}

parent P2 {
c c2
}

c1.eContainer == P1
c2.eContainer == P2

c1.eContainingFeature == "child"
c1.eClass == "Child"
p1.eClass == "Parent"


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765995 is a reply to message #1765994] Wed, 14 June 2017 17:38 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
no eContainer == parent

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765997 is a reply to message #1765994] Wed, 14 June 2017 17:40 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
I can see that it works like this within the parse tree, but based on what you said above about the prototype, if c2 is being manipulated as an EReference then its EContainer is suddenly "Parent", not P2 anymore.

Is there any way to get debug output from a scope provider? Thanks very much for all the help here by the way!
Re: Help debugging a scope provider [message #1765998 is a reply to message #1765995] Wed, 14 June 2017 17:41 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
seeee

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1765999 is a reply to message #1765998] Wed, 14 June 2017 17:46 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
c2 is not a reference

Thing: "t" name=ID "{" children=Child+ "}";

Child: name=ID ("ref" ref=[Child])?

EClass: Thing, Child
EAttribute: Thing__Name, Child__Name
EReference(Containment): Thing__Children
EReference(Non COntainment/Reference): Child__Ref

Child__Ref.eContainer ==Child
Thing__Children.eContainer == Thing

u do use eContainer in 99,9999999999999% only for EObject, not for eAttribtues or EReferences


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1766000 is a reply to message #1765999] Wed, 14 June 2017 17:52 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Ah! So the reference passed to the scope provider isn't the actual reference in the generated syntax tree, but an indicator to the link within the abstract tree that's causing it to be interpreted as a reference? That makes a lot more sense.

I'm not sure what your PNG was meant to illustrate, I know that Pig is a LocalVariableDeclaration inside Sheep, but it is still not a VarDeclaration nor within a common Statements object with Camel.
Re: Help debugging a scope provider [message #1766001 is a reply to message #1766000] Wed, 14 June 2017 17:55 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Yes

Consider

Child : ref1=[...] ref2=[...]


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1766002 is a reply to message #1766001] Wed, 14 June 2017 17:56 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
It will tell you

I am scoping ref1

Or

I am scoping ref2


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1766013 is a reply to message #1766002] Wed, 14 June 2017 18:33 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Ok, thanks! One other question though. Is it possible to change the type of an object in response to scoping? For example, in the spec above an ID in expression context can be an EnumType or a VarName. Is there a way to say "if there is an Enum value in scope that matches, it's an EnumType, otherwise it's a VarName" or to change this in response to scope processing?
Re: Help debugging a scope provider [message #1766014 is a reply to message #1766013] Wed, 14 June 2017 18:53 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
In Xtext everything is possible but
That would be far besides the road
To do this


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1766016 is a reply to message #1766014] Wed, 14 June 2017 19:00 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
so the easier solution is to have a generic reference

aka:

GenericType: TypeA | TypeB;
....


SomeRef: ref=[GenericType]


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1766029 is a reply to message #1766016] Wed, 14 June 2017 23:09 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
The problem with this is that the two possibilities for GenericType end up reducing to the same terminal, ID. Unless there is some way to fail over from one to the other?
Re: Help debugging a scope provider [message #1766038 is a reply to message #1766029] Thu, 15 June 2017 04:55 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Can you be a bit more specific on the exact place in your grammar of this issue

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1766141 is a reply to message #1766038] Fri, 16 June 2017 12:00 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Hi:

ExpPrimary: literal=Literal | var=[VarName] ('#' state=[VarName] ) ;

Literal:
	{StringLiteral} string=STRING |
	{IntLiteral} int=INT |
	{BoolLiteral} bool=BOOL |
	{RealLiteral} real=RealLiteral |
	{StructLiteral} struct=StructuredLiteral |
	{EnumLiteral} enumValue=[EnumValue]
;

EnumValue:
	name=ID
;

VarName:
	name=ID
;


ExpPrimary => VarName => ID and ExpPrimary => Literal => EnumValue => ID both end up reducing to ID. Is there a way to tell XText, "if a reference to an EnumValue is not found, then this reference parser rule doesn't match, so try an alternative parser rule, ie a VarName reference?" Because at the moment the parser generates an error whenever a VarName is used in a PrimaryExp context saying that it is a missing EnumValue.

[Updated on: Fri, 16 June 2017 12:00]

Report message to a moderator

Re: Help debugging a scope provider [message #1766142 is a reply to message #1766141] Fri, 16 June 2017 12:05 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Also how can I get a debug view on my ScopeProvider? I have tried adding breakpoints to the scopeProvider class but they are ignored, even when I run in debug mode doing unit tests (so that there is no runtime eclipse). Output to console from the scopeProvider also seems to be ignored, is there a separate logging class I can use?
Re: Help debugging a scope provider [message #1766155 is a reply to message #1766142] Fri, 16 June 2017 14:27 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
There must be something wrong with you scope provider vor test

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1766159 is a reply to message #1766155] Fri, 16 June 2017 15:58 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
Of course there is something wrong with it, I wouldn't be trying to debug it if there wasn't would I? :) Do you mean there's a possibility that the method isn't running at all? Does it need to be registered somewhere? I just altered the standard class that was generated when I created the project.
Re: Help debugging a scope provider [message #1766161 is a reply to message #1766159] Fri, 16 June 2017 16:34 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Hi does the signature look like

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Help debugging a scope provider [message #1766162 is a reply to message #1766161] Fri, 16 June 2017 17:06 Go to previous messageGo to next message
Mark Green is currently offline Mark GreenFriend
Messages: 37
Registered: June 2017
Member
GetScope had a capital G... *head-desk* Sorry for all the hassle.
Re: Help debugging a scope provider [message #1766164 is a reply to message #1766162] Fri, 16 June 2017 17:25 Go to previous message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
well i thought you have changed this as i proposed before

Quote:

Hi, the scope provider naming looks bad to me should be


override getScope(EObject context, EReference reference) {


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Previous Topic:language server output directory and builds
Next Topic:Preferences page for Templates
Goto Forum:
  


Current Time: Fri Mar 29 01:26:17 GMT 2024

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

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

Back to the top