Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Trouble with a JvmModelInferrer using Maven
Trouble with a JvmModelInferrer using Maven [message #1766079] Thu, 15 June 2017 13:19
Dominique Toupin is currently offline Dominique ToupinFriend
Messages: 1
Registered: June 2017
Location: Repentigny, Quebec, Canad...
Junior Member
Hi,

We are having an issue with our DSL that I had to do pretty hard debugging to figure out.

In our grammar, we define Attribute(s) this way:
Attributes:
	'attributes' name=ValidID
	'{'
		definitions+=Attribute*
	'}'
;

Attribute returns xbase::XExpression:
	{Attribute} (transient='transient')? type=JvmTypeReference name=ValidID ('=' defaultValue=XLiteral)?
;


We can then refers to this Attribute in an Assignment:
Assignment returns xbase::XExpression:
	{Assignment}
	'set' address=DotExpression ('@' attribute=[Attribute] ('.' key=ID)?)?
	op=('='|':=')
	expression=(XExpression|XBlockExpression)
;


The TypeComputer compute the expectations this way when an attribute is present:
				// Assignment has a @attribute added. So we are referring to the PropertyAttribute
				switch (type : assignment.attribute.type)
				{
					JvmParameterizedTypeReference case type.arguments.size == 0:
					{
						// Simple type
						val typeRef = state.referenceOwner.toLightweightTypeReference(type)
						state.withExpectation(typeRef).computeTypes(assignment.expression)
					}


Our JvmModelInferrer on the other hand infers the model for Attribute(s) this way:
	def dispatch infer(Attributes attributes, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase)
	{
		acceptor.accept(attributes.toClass(attributes.fullyQualifiedName)) [ inferredClass |
			inferredClass => [
				visibility = JvmVisibility.PUBLIC
				final = true
			]

			inferredClass.members += attributes.definitions.filter(Attribute).map [ attribute |
				val genericAttributeType = typeRef("com.pc360.configurator.property.attributes.PropertyAttribute", attribute.type)

				attributes.toField(attribute.name, genericAttributeType) => [
					visibility = JvmVisibility.PUBLIC
					static = true
					final = true
					initializer = attribute
				]
			]
		]
	}


Everything seemed to work fine in Eclipse but when we attempted to generate the java source files using Maven, we had a very unpleasant surprise; the inferred java type to the field generated for the attribute named "visible" was
/*PropertyAttribute<Boolean>*/ Object
which indicated that the type could not be resolved... Things got way more strange when we realized that in the same Attributes section we had several other Boolean attributes which yielded the correct result, that we could move the attribute around in the faulty attribute and it would always be that attribute that would be "wrong", and just by modifying the name of the attribute the inferred JVM model was OK...

After pretty intense debugging, we figured out the problem: when generating the sources from Maven, the order of the processed elements is not the same as in Eclipse and in our case with Maven, before the Jvm Model
is inferred for the Attributes, the TypeComputer comes across an Assignment which happens to use the "visible" attribute. Because of that, the "type" property of the attribute is accessed, triggering the Scoping for the context which in turn trigger the Jvm Model inferring. At that point, the Attributes Model is inferred and when we process the "visible" attribute and once again ask for that attribute type, the result is "unknown" because we are in a cyclic dependency...

We were able to "fix" this problem with a super flacky hack: in the JvmModelInferrer, if the attribute name is "visible", always use java.lang.Boolean...
	def dispatch infer(Attributes attributes, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase)
	{
		val booleanType = typeRef("java.lang.Boolean")
		acceptor.accept(attributes.toClass(attributes.fullyQualifiedName)) [ inferredClass |
			inferredClass => [
				visibility = JvmVisibility.PUBLIC
				final = true
			]

			inferredClass.members += attributes.definitions.filter(Attribute).map [ attribute |
				val genericAttributeType = typeRef("com.pc360.configurator.property.attributes.PropertyAttribute", if (attribute.name == "visible") booleanType else attribute.type)

				attributes.toField(attribute.name, genericAttributeType) => [
					visibility = JvmVisibility.PUBLIC
					static = true
					final = true
					initializer = attribute
				]
			]
		]
	}


There must be another way to fix this...

Thank you for your help!

Dominique T.
Previous Topic:Where to find the old version to dowload of Xtext
Next Topic:Embedding ANTLR3 Island Parser in Xtext
Goto Forum:
  


Current Time: Sat Apr 20 03:32:15 GMT 2024

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

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

Back to the top