Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Linker does not check type
Linker does not check type [message #870533] Tue, 08 May 2012 14:57 Go to next message
Reiner Hille is currently offline Reiner HilleFriend
Messages: 18
Registered: July 2009
Junior Member
Hi all,
assume I have the following simple Java-like grammar:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals

generate myDsl "www.xtext.org/example/mydsl/MyDsl"

Lib:
	(classes+=Class)*;

Class:
	'class' name=ID '{'
	(member+=Member)*
	'}';

Member:
	Field | Method;

Field:
	type=Type name=ID;

Method:
	type=Type name=ID '(' ')' '{'
	(statements+=Statement)*
	'}';

Type:
	'int';

Statement:
	(VariableDeclaration | Selection) ';';

Selection:
	object=[VariableDeclaration] '.' (member=[Field] | member=[Method] '(' ')');

VariableDeclaration:
	type=[Class] name=ID;


Then I generate, run the target platform and test the editor for the grammar with following snippet:
class A {
 int afield
 int aMethod() {
 }

 int test () {
  A var1;
  var1.afield;
  var1.aMethod;
  var1.afield();
  var1.aMethod();
 }
}


There is no error marker shown. However, the grammar clearly requires a method to be called with parenthesis and fields without.
The linker simply resolved the references to the members "aMethod" and "afield" by name, ignoring the contraint in the grammar:
 object=[VariableDeclaration] '.' (member=[Field] | member=[Method] '(' ')');

Of cause both, "Field" and "Method" inherit from the same EMF class "Member", thus the linker can set those "wrong" cross references.
The problem here happens in DefaultLinkingService.getLinkedObjects()
	public List<EObject> getLinkedObjects(EObject context, EReference ref, INode node)
			throws IllegalNodeException {
		final EClass requiredType = ref.getEReferenceType();
		if (requiredType == null)
			return Collections.<EObject> emptyList();

		final String crossRefString = getCrossRefNodeAsString(node);
		if (crossRefString != null && !crossRefString.equals("")) {
			if (logger.isDebugEnabled()) {
				logger.debug("before getLinkedObjects: node: '" + crossRefString + "'");
			}
				
			final IScope scope = getScope(context, ref);
			QualifiedName qualifiedLinkName =  qualifiedNameConverter.toQualifiedName(crossRefString);
			IEObjectDescription eObjectDescription = scope.getSingleElement(qualifiedLinkName);
			if (logger.isDebugEnabled()) {
				logger.debug("after getLinkedObjects: node: '" + crossRefString + "' result: " + eObjectDescription);
			}
			if (eObjectDescription != null) 
				return Collections.singletonList(eObjectDescription.getEObjectOrProxy());
		}
		return Collections.emptyList();
	}

In the first line it only checks the required type from the ref's target type - which is in our case "Member".
Additionally it should also check the type that is given my the grammar, similar like the following pseudo-code:
 if (node instanceof LeafNode) {
  LeafNode memberLeafNode = (LeafNode) node;
  EObject grammarElement = memberLeafNode.getGrammarElement();
  if (grammarElement instanceof CrossReference) {
    CrossReference xref = (CrossReference) grammarElement;
    EClassifier classifier = xref.getType().getClassifier(); 
    // TODO: Check if resolved EObject is instance of this classifier
  }
 }

I did a similar thing in a custom validator, but this was quire ugly, as the LeafNode is not directly accessable. And I think that Xtext could do this automatically. What do you think?

Reiner.
Re: Linker does not check type [message #870537 is a reply to message #870533] Tue, 08 May 2012 15:18 Go to previous messageGo to next message
Holger Schill is currently offline Holger SchillFriend
Messages: 75
Registered: July 2009
Member
Hi Reiner,

it could be solved much easier:

grammar org.xtext.example.mydsl.MyDsl with
org.eclipse.xtext.common.Terminals

generate myDsl "www.xtext.org/example/mydsl/MyDsl"

Lib:
(classes+=Class)*;

Class:
'class' name=ID '{'
(member+=Member)*
'}';

Member:
Field | Method;

Field:
type=Type name=ID;

Method:
type=Type name=MethodDecl '{'
(statements+=Statement)*
'}';

Type:
'int';

Statement:
(VariableDeclaration | Selection) ';';

Selection:
object=[VariableDeclaration] '.' (member=[Field] |
member=[Method|MethodDecl]);

VariableDeclaration:
type=[Class] name=ID;

MethodDecl:
ID '(' ')'
;


Cheers,
Holger

--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com


--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com
Re: Linker does not check type [message #870544 is a reply to message #870537] Tue, 08 May 2012 15:51 Go to previous messageGo to next message
Reiner Hille is currently offline Reiner HilleFriend
Messages: 18
Registered: July 2009
Junior Member
Thanks Holger,
using this crosslink terminal feature is indeed something that I didn't really know - and that is really cool.
If I want to add parameters, is the right way to go like this?:
Method:
	type=Type name=MethodDecl (params+=VariableDeclaration)* ')' '{'
	(statements+=Statement)*
	'}';

Type:
	'int';

Statement:
	(VariableDeclaration | Selection) ';';

Selection:
	object=[VariableDeclaration] '.' (member=[Field] |
	member=[Method|MethodDecl] (args+=ID)* ')');

VariableDeclaration:
	type=[Class] name=ID;

MethodDecl:
	ID '(' ;


Anyway: Is the propsosed check in the linker valid?
Re: Linker does not check type [message #870705 is a reply to message #870544] Wed, 09 May 2012 12:01 Go to previous messageGo to next message
Holger Schill is currently offline Holger SchillFriend
Messages: 75
Registered: July 2009
Member
With this grammar it should work. But nor you'll need a typesyteme. You
may have a look at xbase where all this is already solved in a common
way. BTW: You check is not valid in the case that the stuff with the
braches is solved.

grammar org.xtext.example.mydsl.MyDsl with
org.eclipse.xtext.common.Terminals

generate myDsl "www.xtext.org/example/mydsl/MyDsl"

Lib:
(classes+=Class)*;

Class:
'class' name=ID '{'
(member+=Member)*
'}';

Member:
Field | Method;

Field:
type=Type name=ID;

Method:
type=Type name=ID '{'
(statements+=Statement)*
'}';

Type:
'int';

Statement:
(VariableDeclaration | Selection) ';';

Selection:
object=[VariableDeclaration] '.' call=FeatureCall;

FeatureCall:
FieldCall | MethodCall
;

FieldCall:
field=[Field]
;

MethodCall:
method=[Method] => '('( args+=ID ("," args+=ID)*)? ')'
;

VariableDeclaration:
type=[Class] name=ID;

--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com


--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com
Re: Linker does not check type [message #871344 is a reply to message #870533] Sat, 12 May 2012 08:47 Go to previous message
Lorenzo Bettini is currently offline Lorenzo BettiniFriend
Messages: 1812
Registered: July 2009
Location: Firenze, Italy
Senior Member
Hi Reiner

your grammar looks similar to the Featherweight Java I implemented in
Xtext, (the implementation is now an example in Xsemantics DSL,
http://xsemantics.sourceforge.net/xsemantics-documentation/FJ-example.html#FJ)

hope this helps
Lorenzo

On 05/08/2012 04:58 PM, Reiner Hille wrote:
> Hi all,
> assume I have the following simple Java-like grammar:
>
> grammar org.xtext.example.mydsl.MyDsl with
> org.eclipse.xtext.common.Terminals
>
> generate myDsl "www.xtext.org/example/mydsl/MyDsl"
>
> Lib:
> (classes+=Class)*;
>
> Class:
> 'class' name=ID '{'
> (member+=Member)*
> '}';
>
> Member:
> Field | Method;
>
> Field:
> type=Type name=ID;
>
> Method:
> type=Type name=ID '(' ')' '{'
> (statements+=Statement)*
> '}';
>
> Type:
> 'int';
>
> Statement:
> (VariableDeclaration | Selection) ';';
>
> Selection:
> object=[VariableDeclaration] '.' (member=[Field] | member=[Method] '('
> ')');
>
> VariableDeclaration:
> type=[Class] name=ID;
>
>
> Then I generate, run the target platform and test the editor for the
> grammar with following snippet:
>
> class A {
> int afield
> int aMethod() {
> }
>
> int test () {
> A var1;
> var1.afield;
> var1.aMethod;
> var1.afield();
> var1.aMethod();
> }
> }
>
>
> There is no error marker shown. However, the grammar clearly requires a
> method to be called with parenthesis and fields without.
> The linker simply resolved the references to the members "aMethod" and
> "afield" by name, ignoring the contraint in the grammar:
>
> object=[VariableDeclaration] '.' (member=[Field] | member=[Method] '('
> ')');
>
> Of cause both, "Field" and "Method" inherit from the same EMF class
> "Member", thus the linker can set those "wrong" cross references. The
> problem here happens in DefaultLinkingService.getLinkedObjects()
>
> public List<EObject> getLinkedObjects(EObject context, EReference ref,
> INode node)
> throws IllegalNodeException {
> final EClass requiredType = ref.getEReferenceType();
> if (requiredType == null)
> return Collections.<EObject> emptyList();
>
> final String crossRefString = getCrossRefNodeAsString(node);
> if (crossRefString != null && !crossRefString.equals("")) {
> if (logger.isDebugEnabled()) {
> logger.debug("before getLinkedObjects: node: '" + crossRefString + "'");
> }
>
> final IScope scope = getScope(context, ref);
> QualifiedName qualifiedLinkName =
> qualifiedNameConverter.toQualifiedName(crossRefString);
> IEObjectDescription eObjectDescription =
> scope.getSingleElement(qualifiedLinkName);
> if (logger.isDebugEnabled()) {
> logger.debug("after getLinkedObjects: node: '" + crossRefString + "'
> result: " + eObjectDescription);
> }
> if (eObjectDescription != null) return
> Collections.singletonList(eObjectDescription.getEObjectOrProxy());
> }
> return Collections.emptyList();
> }
>
> In the first line it only checks the required type from the ref's target
> type - which is in our case "Member".
> Additionally it should also check the type that is given my the grammar,
> similar like the following pseudo-code:
>
> if (node instanceof LeafNode) {
> LeafNode memberLeafNode = (LeafNode) node;
> EObject grammarElement = memberLeafNode.getGrammarElement();
> if (grammarElement instanceof CrossReference) {
> CrossReference xref = (CrossReference) grammarElement;
> EClassifier classifier = xref.getType().getClassifier(); // TODO: Check
> if resolved EObject is instance of this classifier
> }
> }
>
> I did a similar thing in a custom validator, but this was quire ugly, as
> the LeafNode is not directly accessable. And I think that Xtext could do
> this automatically. What do you think?
>
> Reiner.


--
Lorenzo Bettini, PhD in Computer Science, DI, Univ. Torino
ICQ# lbetto, 16080134 (GNU/Linux User # 158233)
HOME: http://www.lorenzobettini.it MUSIC: http://www.purplesucker.com
http://www.myspace.com/supertrouperabba
BLOGS: http://tronprog.blogspot.com http://longlivemusic.blogspot.com
http://www.gnu.org/software/src-highlite
http://www.gnu.org/software/gengetopt
http://www.gnu.org/software/gengen http://doublecpp.sourceforge.net


Previous Topic:dangling reference error in XBlockExpression when accessing properties
Next Topic:Eclipse Juno + XTEXT 2.3 = SWT Error
Goto Forum:
  


Current Time: Fri Apr 26 18:30:28 GMT 2024

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

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

Back to the top