A common use case when developing languages is the requirement to refer to existing concepts of other languages. Xtext makes this very easy for other self defined DSLs. However, it is often very useful to have access to the available types of the Java Virtual Machine. The JVM types Ecore model enables clients to do exactly this. It is possible to create cross-references to classes, interfaces, and their fields and methods. Basically every information about the structural concepts of the Java type system is available via the JVM types. This includes annotations and their specific values and enumeration literals as well.
The implementation will be selected transparently depending on how the client code is executed. If the environment is a plain stand-alone Java or OSGi environment, the java.lang.reflect API will be used to deduce the necessary data. On the contrary, the type-model will be created from the live data of the JDT in an interactive Eclipse environment. All this happens transparently for the clients behind the scenes via different implementations that are bound to specific interfaces by means of Google Guice.
Using the JVM types model is very simple. First of all, the grammar has to import the JavaVMTypes Ecore model. Thanks to content assist this is easy to spot in the list of proposals.
import "http://www.eclipse.org/xtext/common/JavaVMTypes" as jvmTypes
The next step is to actually refer to an imported concept. Let's define a mapping to available Java types for the simple data types in the domain model language. This can be done with a simple cross-reference:
// simple cross reference to a Java type
DataType:
'datatype' name=ID
'mapped-to' javaType=[jvmTypes::JvmType|QualifiedName];
After regenerating your language, it will be allowed to define a type Date that maps to the Date like this:
datatype Date mapped-to java.util.Date
These two steps will provide a nice integration into the Eclipse JDT. There is Find References on Java methods, fields and types that will reveal results in your language files. Go To Declaration works as expected and content assist will propose the list of available types. Even the import statements will also apply for Java types.
There are several customization hooks in the runtime layer of the JVM types and on the editor side as well:
The AbstractTypeScopeProvider (src) can be used to create scopes for members with respect to the override semantics of the Java language. Of course it is possible to use this implementation to create scopes for types as well.
As the Java VM types expose a lot of information about visibility, parameter- and return types, generics, available annotations or enumeration literals, it is very easy to define constraints for the referred types.
The ITypesProposalProvider (src) can be used to provide optimized proposals based on various filter criteria. The most common selector can be used directly via createSubTypeProposals(..). The implementation is optimized and uses the JDT Index directly to minimize the effort for object instantiation. The class TypeMatchFilters (src) provides a comprehensive set of reusable filters that can be easily combined to reduce the list of proposals to a smaller number of valid entries.