In my model I have more objects from which are later generated Java classes.
E.g. in one file is defined
Object A {
operation getList B
}
And in other file:
Object B {
operation getList A
}
1) From this 2 interfaces should be generated:
interface A {
java.util.List<B> getListOfBs();
}
interface B {
java.util.List<A> getListOfAs();
}
2) Instead it is newly generated like this:
interface A {
/* java.util.List<B> */ Object getListOfBs();
}
interface B {
/* java.util.List<A> */ Object getListOfAs();
}
This happens only when I run Project -> Clean... action in Eclipse.
After I change something in my model and save it everything is generated fine, it looks like first example.
As I was debuging my inferrer I noticed that return type of created method is defined as JvmParameterizedTypeReference: java.util.List<JvmUnknownTypeReference: A>.
Is there a way to generate classes right also after clean in Eclipse?
EDIT
I have now example that duplicates my problem. It is really needed to have so many model files, otherwise everything run OK.
I created new Xtext project with defaults. My xtext file:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.Xbase
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
ModelDomain:
SubPackageDeclaration
elements+=DataModelItem*;
SubPackageDeclaration:
'subPackage' subPackageName=ID;
DataModelItem:
DataType | DataObject | DataEnum;
DataType:
'DataType' name=ID type=JvmParameterizedTypeReference;
DataObject:
'DataObject' name=ID '{'
('lists' '{'
(lists+=DataAttribute)*
'}')?
'}';
DataEnum:
'DataEnum' name=ID '{'
values+=ID (',' values+=ID)*
'}';
DataAttribute:
(transient?='transient')? type=[DataModelItem|QualifiedName] name=ID;
and inferrer:
package org.xtext.example.mydsl.jvmmodel
import com.google.inject.Inject
import org.eclipse.xtext.common.types.JvmTypeReference
import org.eclipse.xtext.common.types.TypesFactory
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.xtext.example.mydsl.myDsl.DataEnum
import org.xtext.example.mydsl.myDsl.DataModelItem
import org.xtext.example.mydsl.myDsl.DataObject
import org.xtext.example.mydsl.myDsl.DataType
import org.xtext.example.mydsl.myDsl.SubPackageDeclaration
class MyDslJvmModelInferrer extends AbstractModelInferrer {
@Inject extension JvmTypesBuilder
@Inject private TypesFactory typesFactory
def dispatch void infer(DataEnum dataEnum, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
var packageName = ""
if (dataEnum.eContainer != null && dataEnum.eContainer instanceof SubPackageDeclaration) {
var implDec = (dataEnum.eContainer as SubPackageDeclaration)
packageName = "data.model." + implDec.subPackageName
}
val qualifiedName = packageName + "." + dataEnum.name.toFirstUpper
acceptor.accept(
dataEnum.toEnumerationType(qualifiedName) [
for (value : dataEnum.values) {
val jvmLiteral = typesFactory.createJvmEnumerationLiteral
jvmLiteral.simpleName = value
jvmLiteral.^static = true
var t1 = typesFactory.createJvmParameterizedTypeReference
t1.type = it
jvmLiteral.type = t1
members += jvmLiteral
}
])
}
def dispatch void infer(DataObject dataObject, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
var packageName = ""
if (dataObject.eContainer != null && dataObject.eContainer instanceof SubPackageDeclaration) {
var implDec = (dataObject.eContainer as SubPackageDeclaration)
packageName = "data.model." + implDec.subPackageName
}
val qualifiedName = packageName + "." + dataObject.name.toFirstUpper
acceptor.accept(
dataObject.toInterface(qualifiedName) [
superTypes += dataObject.newTypeRef("data.model.core.IDataObject")
for (list : dataObject.lists) {
val JvmTypeReference ^void = dataObject.newTypeRef(Void.TYPE)
val JvmTypeReference listTypeRef = convertToJvmType(list.type)
if (listTypeRef != null && !isPreIndexingPhase) {
val removeMethod = list.toMethod("remove" + list.name.toFirstUpper, ^void) [
parameters += list.toParameter(list.name, listTypeRef)
]
members += removeMethod
removeMethod.setAbstract(true);
val returnType = dataObject.newTypeRef("java.util.List", listTypeRef)
val allMethod = list.toMethod("get" + list.name.toFirstUpper + "List", returnType)[]
allMethod.setAbstract(true);
members += allMethod
}
}
val denyLoading = dataObject.toMethod("denyLoading", dataObject.newTypeRef(Void.TYPE))[]
denyLoading.setAbstract(true);
members += denyLoading
])
}
def public JvmTypeReference convertToJvmType(DataModelItem modelItem) {
var JvmTypeReference typeRef
if (modelItem instanceof DataType) {
var typeData = (modelItem as DataType)
typeRef = typeData.type.cloneWithProxies
} else if (modelItem instanceof DataEnum) {
var typeDec = (modelItem.eContainer as SubPackageDeclaration)
var typePackageName = "data.model." + typeDec.subPackageName
val typeData = modelItem as DataEnum
typeRef = typeData.newTypeRef(typePackageName + "." + typeData.name)
} else if (modelItem.eContainer != null) {
var typeDec = (modelItem.eContainer as SubPackageDeclaration)
var typePackageName = "data.model." + typeDec.subPackageName
var typeQName = typePackageName + "." + modelItem.name
typeRef = modelItem.newTypeRef(typeQName)
}
return typeRef
}
}
Then I have these 6 mydsl files:
1. address.mydsl
subPackage address DataObject PhoneNumber { lists { PhoneNumberType types } } DataObject Contact { lists { PhoneNumber phoneNumber } } DataObject Address { lists { PhoneNumber phoneNumber } } DataEnum PhoneNumberType { BUSINESS_PHONE , BUSINESS_FAX , BUSINESS_MOBILE , HOME_PHONE , HOME_MOBILE , HOME_FAX } DataEnum Gender { FEMALE , MALE }
2. asset.mydsl
subPackage asset DataObject Asset { lists { LiabilityCase liabilityCase} } DataObject VehicleEquipment { lists { Address address } } DataObject LiabilityCase { } DataObject AssetVehicle { lists { VehicleEquipment serial VehicleEquipment extra } } DataObject Tires { } DataObject RentalObject { lists { Asset vehicle Asset mob Asset prop Asset estate Asset asset } } DataEnum AssetCondition { NEW , USED , DEMO } DataEnum VehicleColorType { STANDARD , PEARL_EFFECT , METALLIC , SPECIAL } DataEnum TiresType { SUMMER , WINTER } DataEnum AssetClass { VEHICLE , MOB , PROPERTY , ESTATE }
3. businessPartner.mydsl
subPackage businesspartner DataEnum BusinessPartnerType { INDIVIDUAL , ORGANISATION } DataObject BusinessPartner { lists { Address address Contact contact BpTransactions transaction BpAdvisorRelation advisor } } DataObject BpRiskParameters { } DataObject BpTransactions { } DataObject BalanceDetails { } DataObject BpAdvisorRelation { } DataEnum AdvisorType { ADVISOR , ADVISOR_BO , ADMINISTRATOR }
4. invoice.mydsl
subPackage invoice DataObject Invoice{ lists { Receipt receipt } } DataObject Receipt { lists { InvoiceItem item } } DataObject ReceiptFleet { } DataObject InvoiceItem{ } DataEnum InvoiceCategory { OBJECT, SERVICE ,INVOICES } DataEnum InvoiceType { INCOMING, OUTGOING } DataEnum InvoiceStatus { OPEN, PARTIALLY_COMPLETE, COMPLETE } DataEnum ItemUnit { UNIT, PALETTE, DOZEN, LITRE } DataEnum ItemIdType { LICENSE_PLATE, CARD_NUMBER, OBJECT_ID }
5. securities.mydsl
subPackage securities DataObject Securities {} DataEnum SecuritiesType {PARTNER_APPLICANT, GUARANTOR,SOMETHING_ELSE}
6. types.mydsl
subPackage types DataType String java.lang.String DataType Integer java.lang.Integer DataType Double java.lang.Double DataType Date java.util.Date DataType Boolean java.lang.Boolean DataType Void java.lang.Void
Generated interfaces extends data.model.core.IDataObject
. This interface has no methods. After clean action in Eclipse I can see that getPhoneNumberList method is generated as
public abstract /* List<data.model.address.PhoneNumber> */Object getPhoneNumberList();
and also other methods, but others are OK.
I tested it with Xtext 2.5 and 2.3 with the same result.
I get error in the Console saying:
2 [Worker-4] ERROR org.eclipse.xtext.common.types.access.jdt.JdtTypeProvider - [Working copy] PhoneNumber.java [in data.model.address [in src-gen [in test]]] does not exist
Java Model Exception: Java Model Status [[Working copy] PhoneNumber.java [in data.model.address [in src-gen [in test]]] does not exist]
but I don't know how to fix it.