2014-03-07 66 views
1

在我的模型中,我有更多的對象是以後生成的Java類。 例如在一個文件中被定義如何在Xtext中生成方法時避免JvmParameterizedTypeReference:java.util.List <JvmUnknownTypeReference:A>?

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(); 
} 

只有當我在Eclipse中運行Project - > Clean ...時纔會發生這種情況。
我改變了我的模型中的東西,並保存它,一切都生成好,它看起來像第一個例子。 當我調試我的推理者時,我注意到創建方法的返回類型被定義爲JvmParameterizedTypeReference:java.util.List < JvmUnknownTypeReference:A >

有沒有一種方法可以在Eclipse中清理後生成類?

編輯 我現在有一個重複我的問題的例子。真的需要有這麼多的模型文件,否則一切都運行正常。 我使用默認值創建了新的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. 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 

生成接口擴展爲data.model.core.IDataObject。這個接口沒有方法。後在Eclipse 乾淨行動,我可以看到getPhoneNumberList方法作爲

public abstract /* List<data.model.address.PhoneNumber> */Object getPhoneNumberList(); 

以及其他方法產生,但其他都OK。
我用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] 

,但我不知道如何解決它。

回答

2

看起來您嘗試在索引階段解析交叉引用。請小心在#toClass調用的初始化程序塊中定義推斷的類型和接口的方法。這應該工作。您的代碼應該是這樣的:

myObject.toClass(myObject.name) [ clazz | 
    myObject.operations.forEach [ op | 
    clazz.members += op.toMethod(getMethodName(op), getMethodType(op)) [ 
     .. 
    ] 
    ] 
] 

如果你想從初始化塊是指其他類型的,你必須初始化分成兩個部分。任何依賴於將被推斷的其他類型的代碼都必須進入初始化後面的部分,例如,

在你的具體的例子,推理工作對我來說,如果我用這個方法:

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") 
     ]).initializeLater[ 
      for (list : dataObject.lists) { 
       val JvmTypeReference ^void = dataObject.newTypeRef(Void.TYPE) 
       if (!isPreIndexingPhase) { 
        val JvmTypeReference listTypeRef = convertToJvmType(list.type) 
        if (listTypeRef != null) { 
         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 
     ] 
} 

這一切是必要的,因爲類型都有他們可以參考之前充分收集。

+0

我不能在這個項目中有任何類我只需要接口。但即使當我用myObject.toInterface嘗試它時,我仍然有同樣的問題。 有趣的是,當我在更簡單的項目中執行操作時,就像我的示例一樣,它工作正常。然後我在調試中看到返回類型: JvmParameterizedTypeReference:java.util.List borism

+0

嗨,如果你有時間,我更新了我的問題並添加了整個示例。 – borism

+0

感謝您澄清問題。我更新了答案。 –