В моей модели у меня есть больше объектов, из которых позже создаются классы Java. Например. в одном файле определяется
Object A {
operation getList B
}
И в другом файле:
Object B {
operation getList A
}
1) Из этого должны быть сгенерированы 2 интерфейса:
interface A {
java.util.List<B> getListOfBs();
}
interface B {
java.util.List<A> getListOfAs();
}
2) Вместо этого он создается заново следующим образом:
interface A {
/* java.util.List<B> */ Object getListOfBs();
}
interface B {
/* java.util.List<A> */ Object getListOfAs();
}
Это происходит только тогда, когда я запускаю действие Project -> Clean... в Eclipse.
После того, как я что-то изменил в своей модели и сохранил ее, все сгенерировано нормально, это выглядит как первый пример. Когда я отлаживал свой механизм вывода, я заметил, что возвращаемый тип созданного метода определяется как JvmParameterizedTypeReference: java.util.List‹JvmUnknownTypeReference: A›.
Есть ли способ генерировать классы сразу после очистки в Eclipse?
EDIT Теперь у меня есть пример, который дублирует мою проблему. Очень нужно иметь так много файлов модели, иначе все работает нормально. Я создал новый проект Xtext со значениями по умолчанию. Мой xtext-файл:
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;
и вывод:
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
}
}
Затем у меня есть эти 6 файлов mydsl:
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. актив.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. счет-фактура.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. ценные бумаги.mydsl
subPackage securities DataObject Securities {} DataEnum SecuritiesType {PARTNER_APPLICANT, GUARANTOR,SOMETHING_ELSE}
6. типы.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
Сгенерированные интерфейсы расширяют data.model.core.IDataObject
. Этот интерфейс не имеет методов. После действия clean в Eclipse я вижу, что метод getPhoneNumberList генерируется как
public abstract /* List<data.model.address.PhoneNumber> */Object getPhoneNumberList();
а также другие методы, но с другими все в порядке.
Я протестировал его с Xtext 2.5 и 2.3 с тем же результатом.
Я получаю сообщение об ошибке в консоли:
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]
но я не знаю, как это исправить.