Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » unresolved jvmTypeReference as generic type parameter(jvmTypeReference unresolved as generic type parameter, but resolved as normal type )
unresolved jvmTypeReference as generic type parameter [message #1778699] Wed, 20 December 2017 10:20 Go to next message
paul lu is currently offline paul luFriend
Messages: 43
Registered: April 2013
Member
Hi,

I reproduced the case with a simpler example (xtext version 2.12),

test DSL file:
test.mydsl
element MyElement : String
collection MyCollection of MyElement

The expected Java is :
public class MyCollection implements Collection<String>{
..
}

where MyCollection is a collection type of the type of the MyElement.

The simple case reproduces the resolution of the jvm type in the following pattern:

For MyElement: String is resolved as :
MyElement --typeRef--> String

For MyCollection: String is resolved as :
MyCollection --elementRef--> MyElement ---typeRef--> String

It should have something to do with cyclic resolution, so actually I got the following generated Java:

			@SuppressWarnings("all")
			public class MyCollection implements /* Collection<Object> */ {
			  private String foo;
			  
			  private /* Collection<Object> */Object foos;
			}


Separating the files solves the problem only in Maven build and only when
the file containing "element MyElement : String" is loaded first by naming the file with something like aaaaa.mydsl (and another file named zzzz.mydsl)

I failed to get the expected result in Eclipse either.



the grammar:

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.annotations.XbaseWithAnnotations
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
	elements+=Entity*;
Entity:
	Element | Collection;

Element:
	'element' name=ID ':' typeRef=JvmTypeReference;

Collection:
	'collection' name=ID 'of' elementRef=[Element];


Jvm Inferrer:
class MyDslJvmModelInferrer extends AbstractModelInferrer {

	@Inject extension JvmTypesBuilder
	
	def dispatch void infer(Element element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		acceptor.accept(element.toClass(element.name))[
//			it.superTypes += element.typeRef.type.typeRef()
			it.superTypes += element.typeRef.cloneWithProxies
		]
	}
	def dispatch void infer(Collection collection, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		acceptor.accept(collection.toClass(collection.name))[
//			it.superTypes += "java.util.Collection".typeRef(
//				collection.elementRef.typeRef.type.typeRef
//			)
			it.superTypes += "java.util.Collection".typeRef(
				collection.elementRef.typeRef.cloneWithProxies
			)
			it.members += collection.toField("foo", collection.elementRef.typeRef.cloneWithProxies)
			it.members += collection.toField("foos", "java.util.Collection".typeRef(
				collection.elementRef.typeRef.cloneWithProxies
			))
		]
	}
}




It looks like the jvmType gets wrong only when used as type parameter,
private /* Collection<Object> */Object foos;

it gets right in :
private String foo

Unit test, grammar, and jvm inferrer are also attached.

Thanks
Re: unresolved jvmTypeReference as generic type parameter [message #1778701 is a reply to message #1778699] Wed, 20 December 2017 10:24 Go to previous messageGo to next message
paul lu is currently offline paul luFriend
Messages: 43
Registered: April 2013
Member
unit test attached.
Re: unresolved jvmTypeReference as generic type parameter [message #1778711 is a reply to message #1778701] Wed, 20 December 2017 11:21 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Without trying would have expected

elementRef.name.typeRef


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: unresolved jvmTypeReference as generic type parameter [message #1778723 is a reply to message #1778711] Wed, 20 December 2017 13:05 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
or

collection.elementRef.typeRef.qualifiedName.typeRef


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: unresolved jvmTypeReference as generic type parameter [message #1778739 is a reply to message #1778723] Wed, 20 December 2017 15:48 Go to previous messageGo to next message
paul lu is currently offline paul luFriend
Messages: 43
Registered: April 2013
Member
Thanks!

The example works with this approach.

I noticed in my original case the code also hits a cyclic resolution of JvmTypeReference.type.

I updated the case and reproduced the problem.

Jvm inferrer:
class MyDslJvmModelInferrer extends AbstractModelInferrer {
	@Inject extension JvmTypesBuilder
	def dispatch void infer(Element element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		acceptor.accept(element.toClass(element.name))[
			it.superTypes += "java.util.function.Supplier".typeRef(
				element.typeRef.qualifiedName.typeRef
			)
		]
	}
	def dispatch void infer(Collection collection, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		acceptor.accept(collection.toClass(collection.name))[
			it.superTypes += "java.util.Collection".typeRef(
				collection.elementRef.typeRef.qualifiedName.typeRef 
			)
		]
	}
}


2 DSL files:
'''
collection MyCollection of MyElement
''',
'''
element MyElement : String
'''
Reulsts:
import java.util.Collection;

@SuppressWarnings("all")
public class MyCollection implements Collection<String> {
}

import java.util.function.Supplier;

@SuppressWarnings("all")
public class MyElement implements Supplier<void> {
}

Both unit test and maven reproduces this code with invalid type parameter: Supplier<void>.

What I notice is a cyclic resolution happens here, as the builder gets in
org.eclipse.xtext.xbase.resource.BatchLinkableResource.handleCyclicResolution
and the JvmTypeReference.type resolution failed.

I attached the updated test case.

Thanks,
Re: unresolved jvmTypeReference as generic type parameter [message #1778741 is a reply to message #1778739] Wed, 20 December 2017 15:58 Go to previous messageGo to next message
paul lu is currently offline paul luFriend
Messages: 43
Registered: April 2013
Member
I expmerimented with the following inferrer:
class MyDslJvmModelInferrer extends AbstractModelInferrer {
	@Inject extension JvmTypesBuilder
	def dispatch void infer(Element element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		acceptor.accept(element.toClass(element.name))[
			it.superTypes += "java.util.function.Supplier".typeRef(
				element.typeRef.cloneWithProxies
			)
			it.members += element.toField("foo", element.typeRef.cloneWithProxies )
		]
	}
	def dispatch void infer(Collection collection, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		acceptor.accept(collection.toClass(collection.name))[
			it.superTypes += "java.util.Collection".typeRef(
				collection.elementRef.typeRef.qualifiedName.typeRef 
			)
		]
	}
}

and get the generated code:
import java.util.Collection;

@SuppressWarnings("all")
public class MyCollection implements Collection<String> {
}

import java.util.function.Supplier;

@SuppressWarnings("all")
public class MyElement implements /* Supplier<Object> */ { //place 1, should be Supplier<String>
  private String foo; //place 2
}

Here "String" is resolved in place 2
but not in place 1.
Re: unresolved jvmTypeReference as generic type parameter [message #1778745 is a reply to message #1778741] Wed, 20 December 2017 17:09 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
why always element.typeRef.cloneWithProxies

class MyDslJvmModelInferrer extends AbstractModelInferrer {
@Inject extension JvmTypesBuilder
def dispatch void infer(Element element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
acceptor.accept(element.toClass(element.name))[
it.superTypes += "java.util.function.Supplier".typeRef(
element.typeRef
)
it.members += element.toField("foo", element.typeRef )
]
}
def dispatch void infer(Collection collection, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
acceptor.accept(collection.toClass(collection.name))[
it.superTypes += "java.util.Collection".typeRef(
collection.elementRef.typeRef.qualifiedName.typeRef
)
]
}
}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: unresolved jvmTypeReference as generic type parameter [message #1778761 is a reply to message #1778745] Thu, 21 December 2017 05:08 Go to previous messageGo to next message
paul lu is currently offline paul luFriend
Messages: 43
Registered: April 2013
Member
Thanks for looking at this!

However, using this inferrer code below results in this generated code:
MyElement.java
import java.util.function.Supplier;

@SuppressWarnings("all")
public class MyElement implements /* Supplier<String> */ {
  private String foo;
}


Again, this is only reproduced in Maven build and unit test. Eclipse build produces the correct java code.

Dsl source:
src/main/java/zzzz.mydsl:
collection MyCollection of MyElement

src/main/java/a.mydsl:
element MyElement: String

The error only happens in the following loading order in maven log:
[INFO] Adding file 'file:/Users/paul/Projects/test-mydsl/my-app/src/main/java/zzzz.mydsl'
[INFO] Adding file 'file:/Users/paul/Projects/test-mydsl/my-app/src/main/java/a.mydsl'
...
[INFO] Starting validation for input: 'zzzz.mydsl'
[INFO] Starting validation for input: 'a.mydsl'
[INFO] Starting generator for input: 'zzzz.mydsl'
[INFO] Starting generator for input: 'a.mydsl'


Christian Dietrich wrote on Wed, 20 December 2017 12:09
why always element.typeRef.cloneWithProxies

class MyDslJvmModelInferrer extends AbstractModelInferrer {
@Inject extension JvmTypesBuilder
def dispatch void infer(Element element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
acceptor.accept(element.toClass(element.name))[
it.superTypes += "java.util.function.Supplier".typeRef(
element.typeRef
)
it.members += element.toField("foo", element.typeRef )
]
}
def dispatch void infer(Collection collection, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
acceptor.accept(collection.toClass(collection.name))[
it.superTypes += "java.util.Collection".typeRef(
collection.elementRef.typeRef.qualifiedName.typeRef
)
]
}
}

Re: unresolved jvmTypeReference as generic type parameter [message #1778764 is a reply to message #1778761] Thu, 21 December 2017 06:36 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Did you try to actually implement the supplier?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: unresolved jvmTypeReference as generic type parameter [message #1778770 is a reply to message #1778764] Thu, 21 December 2017 07:47 Go to previous messageGo to next message
paul lu is currently offline paul luFriend
Messages: 43
Registered: April 2013
Member
I just made up this example to reproduce the problem and for the convenience of discussion. The original case is more complicated,

but the reference resolution follows the same pattern. One element borrows the jvm reference in another element in another resource.

For MyCollection: String is resolved as :
MyCollection --elementRef--> MyElement ---typeRef--> String (1)

For MyElement: String is resolved as :
MyElement --typeRef--> String (2)

The debug shows, (1) happens first then (2) is happening as (1) needs to load another resource, and loading triggers installDerivedState

The logic gets in:
public class BatchLinkableResource ...
...
	@Override
	protected EObject handleCyclicResolution(Triple<EObject, EReference, INode> triple) throws AssertionError {
		if (!isValidationDisabled()) {
			EObject context = triple.getFirst();
			if (context.eClass() == TypesPackage.Literals.JVM_PARAMETERIZED_TYPE_REFERENCE) {
				// here we may end up with cyclic resolution requests in rare situations, e.g. for input types
				// like :
				/*
				 * package p;
				 * class C extends p.C.Bogus {}
				 */
				return null;



Thanks


Re: unresolved jvmTypeReference as generic type parameter [message #1778771 is a reply to message #1778770] Thu, 21 December 2017 08:02 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
can you please file a bug at https://github.com/eclipse/xtext-extras
with the reproducible example attached?


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: unresolved jvmTypeReference as generic type parameter [message #1778772 is a reply to message #1778771] Thu, 21 December 2017 08:04 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
----

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Thu, 21 December 2017 08:06]

Report message to a moderator

Re: unresolved jvmTypeReference as generic type parameter [message #1778773 is a reply to message #1778772] Thu, 21 December 2017 08:19 Go to previous message
paul lu is currently offline paul luFriend
Messages: 43
Registered: April 2013
Member
Issue is created
https://github.com/eclipse/xtext-extras/issues/216
Previous Topic:Problem with Multiline Comments
Next Topic:Content Assist problem
Goto Forum:
  


Current Time: Fri Mar 29 14:57:41 GMT 2024

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

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

Back to the top