#19 Xbase's new JvmUnknownTypeReference
New nice little feature of the Xtext 2.4 is the use of JvmUnknownTypeReference instead of the 'null' to represent references to missing types. In this episode, you will see the differences between Xtext 2.3 and Xtext 2.4 in creation and use of type references.
- Download:
- source code Project Files in Zip (914 KB)
- mp4 Full Size H.264 Video (19 MB)
- m4v Smaller H.264 Video (10.8 MB)
- webm Full Size VP8 Video (11.1 MB)
- ogv Full Size Theora Video (24.4 MB)
Differences between Xtext 2.3 and Xtext 2.4
The class references can be created using JvmTypesBuilder.newTypeRef(...)
extension method. In following snippet we will use references to following missing types:
test.MyEntity1Interface
orentity.fullyQualifiedName + "Interface"
test.MyEntity1Factory
orentity.fullyQualifiedName + "Factory"
Implementing interface, that doesn't exist
DomainmodelJvmModelInferrer.xtend
...
acceptor.accept(entity.toClass(entity.fullyQualifiedName)).initializeLater [
...
// ADDED
superTypes += entity.newTypeRef(entity.fullyQualifiedName + "Interface")
...
]
... acceptor.accept(entity.toClass(entity.fullyQualifiedName)).initializeLater [ ... // ADDED superTypes += entity.newTypeRef(entity.fullyQualifiedName + "Interface") ... ]
- Xtext 2.3 implements no interface:
src-gen/test/MyEntity1.java
public class MyEntity1 {
...
}
public class MyEntity1 { ... }
- Xtext 2.4 implements missing interface producing java compilation error:
src-gen/test/MyEntity1.java
public class MyEntity1 implements test.MyEntity1Interface {
...
}
public class MyEntity1 implements test.MyEntity1Interface { ... }
Defining field of type, that doesn't exist
DomainmodelJvmModelInferrer.xtend
...
acceptor.accept(entity.toClass(entity.fullyQualifiedName)).initializeLater [
...
// ADDED
members += entity.toField("factory", newTypeRef(entity.fullyQualifiedName + "Factory"))
...
]
... acceptor.accept(entity.toClass(entity.fullyQualifiedName)).initializeLater [ ... // ADDED members += entity.toField("factory", newTypeRef(entity.fullyQualifiedName + "Factory")) ... ]
- Xtext 2.3 defines a field of type
Object
and a comment with a warning:
src-gen/test/MyEntity1.java
public class MyEntity1 {
private Object /* problem during compilation, see error log*/ factory;
...
}
...
public class MyEntity1 { private Object /* problem during compilation, see error log*/ factory; ... } ...
- Xtext 2.4 defines a field of missing type producing java compilation error:
src-gen/test/MyEntity1.java
public class MyEntity1 implements test.MyEntity1Interface {
private test.MyEntity1Factory factory;
...
}
public class MyEntity1 implements test.MyEntity1Interface { private test.MyEntity1Factory factory; ... }
Appending types in the body = [ ... ]
parts
- In Xtext 2.3 you have to do a 'null' check after creating a new type reference:
DomainmodelJvmModelInferrer.xtend
body = [
...
// ADDED
val factoryTypeRef = entity.newTypeRef(entity.fullyQualifiedName + "Factory")
if (factoryTypeRef != null) {
newLine
it.append(factoryTypeRef.type)
it.append(" factory = null;")
}
...
]
body = [ ... // ADDED val factoryTypeRef = entity.newTypeRef(entity.fullyQualifiedName + "Factory") if (factoryTypeRef != null) { newLine it.append(factoryTypeRef.type) it.append(" factory = null;") } ... ]
In case entity.fullyQualifiedName + "Factory"
not found, no local variable get defined.
- In Xtext 2.4 you can easily implement your own
append(ref)
method to reference missing types:
DomainmodelJvmModelInferrer.xtend
body = [
...
// ADDED
newLine
val ref = entity.newTypeRef(entity.fullyQualifiedName + "Factory")
append(ref)
append(" a;")
]
...
def append(IAppendable it, JvmTypeReference typeRef) {
if (typeRef instanceof JvmUnknownTypeReference) {
append(typeRef.getQualifiedName('.'))
} else {
append(typeRef.type)
}
}
body = [ ... // ADDED newLine val ref = entity.newTypeRef(entity.fullyQualifiedName + "Factory") append(ref) append(" a;") ] ... def append(IAppendable it, JvmTypeReference typeRef) { if (typeRef instanceof JvmUnknownTypeReference) { append(typeRef.getQualifiedName('.')) } else { append(typeRef.type) } }
In case test.MyEntity1Factory
not found, the local variable still get defined:
src-gen/test/MyEntity1.java
...
public MyEntity1(final Procedure1<MyEntity1> initializer) {
initializer.apply(this);
test.MyEntity1Factory a;
}
...
... public MyEntity1(final Procedure1<MyEntity1> initializer) { initializer.apply(this); test.MyEntity1Factory a; } ...