Here is more detail about how I attempted to build an xbase project. See the previous page here for an explanation of what I am trying to do.
Run new xtext project wizard | |
I entered the project name, language name and extension (the part after the '.' which identifies the filetype of our DSL. | |
Copy and paste the grammar below into the 'Editor.xtext' file. | |
grammar com.euclideanspace.euclid.Editor with org.eclipse.xtext.xbase.annotations.XbaseWithAnnotations generate euclidmodel "https://www.euclideanspace.com/euclid" import "http://www.eclipse.org/xtext/xbase/Xbase" as xbase import "http://www.eclipse.org/xtext/xbase/Xtype" as xtype import "http://www.eclipse.org/Xtext/Xbase/XAnnotations" as annotations import "http://www.eclipse.org/xtext/common/JavaVMTypes" as types File returns EuclidFile : ('package' package=QualifiedName ';'?)? (imports+=Import)* (euclidTypes+=Type)* ; Import returns EuclidImport : 'import' ( (static?='static' extension?='extension'? importedType=[types::JvmType|QualifiedName] '.' '*') | importedType=[types::JvmType|QualifiedName] | importedNamespace=QualifiedNameWithWildCard) ';'? ; QualifiedNameWithWildCard : QualifiedName '.' '*'; Type returns EuclidTypeDeclaration : {EuclidTypeDeclaration} annotations+=XAnnotation* ({EuclidClass.annotationInfo = current} 'public'? abstract?='abstract'? 'class' name=ValidID ('<' typeParameters+=JvmTypeParameter (',' typeParameters+=JvmTypeParameter)* '>')? ("extends" extends=JvmParameterizedTypeReference)? ('implements' implements+=JvmParameterizedTypeReference (',' implements+=JvmParameterizedTypeReference)*)?'{' (members+=Member)* '}' |{EuclidAnnotationType.annotationInfo = current} 'annotation' name=ValidID '{' (members+=AnnotationField)* '}' ) ; AnnotationField returns EuclidField : annotations+=XAnnotation* (type=JvmTypeReference | (final?='val' | 'var') type=JvmTypeReference?) name=ValidID ('=' initialValue=XExpression)? ';'? ; Member returns EuclidMember: {EuclidMember} annotations+=XAnnotation* ( {EuclidField.annotationInfo = current} visibility=Visibility? (extension?='extension' (final?='val' | 'var')? type=JvmTypeReference name=ValidID? | static?='static'? (type=JvmTypeReference | (final?='val' | 'var') type=JvmTypeReference?) name=ValidID) ('=' initialValue=XExpression)? ';'? | {EuclidFunction.annotationInfo = current} ('def' | override?='override') visibility=Visibility? static?='static'? (dispatch?='dispatch'?) ('<' typeParameters+=JvmTypeParameter (',' typeParameters+=JvmTypeParameter)* '>')? ( =>(returnType=JvmTypeReference createExtensionInfo=CreateExtensionInfo name=ValidID '(') | =>(returnType=JvmTypeReference name=ValidID '(') | =>(createExtensionInfo=CreateExtensionInfo name=ValidID '(') | name=ValidID '(' ) (parameters+=Parameter (',' parameters+=Parameter)*)? ')' ('throws' exceptions+=JvmTypeReference (',' exceptions+=JvmTypeReference)*)? (expression=XBlockExpression)? | {EuclidConstructor.annotationInfo = current} visibility=Visibility? 'new' ('<' typeParameters+=JvmTypeParameter (',' typeParameters+=JvmTypeParameter)* '>')? '(' (parameters+=Parameter (',' parameters+=Parameter)*)? ')' ('throws' exceptions+=JvmTypeReference (',' exceptions+=JvmTypeReference)*)? expression=XBlockExpression ) ; CreateExtensionInfo: 'create' (name=ValidID ':')? createExpression=XExpression ; ValidID: ID | 'create' | 'annotation' ; Parameter returns EuclidParameter: annotations+=XAnnotation* parameterType=JvmTypeReference varArg?='...'? name=ValidID; enum Visibility returns types::JvmVisibility: PUBLIC = 'public' | PROTECTED = 'protected' | PRIVATE = 'private'; XStringLiteral returns xbase::XExpression: SimpleStringLiteral ; SimpleStringLiteral returns xbase::XExpression: {xbase::XStringLiteral} value=STRING ; |
|
Run mwe2 file. This seems to detect that this is a xbase project and creates 'jvmmodel/EditorJvmModelInferrer.xtend' instead of 'generator/EditorGenerator.xtend' to hold the code generator. |
|
Copy and paste the following code into the 'jvmmodel/EditorJvmModelInferrer.xtend'file: | |
package com.euclideanspace.euclid.jvmmodel
import com.google.inject.Inject
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.eclipse.xtext.xbase.jvmmodel.JvmVisibilityExtension
import com.euclideanspace.euclid.euclidmodel.EuclidFile
import com.euclideanspace.euclid.euclidmodel.EuclidAnnotationType
import com.euclideanspace.euclid.euclidmodel.EuclidClass
import com.euclideanspace.euclid.euclidmodel.EuclidConstructor
import com.euclideanspace.euclid.euclidmodel.EuclidField
import com.euclideanspace.euclid.euclidmodel.EuclidFunction
import static org.eclipse.xtext.util.Strings.*
import org.eclipse.xtext.common.types.JvmOperation
import org.eclipse.xtext.common.types.JvmField
import org.eclipse.xtext.common.types.JvmTypeReference
import org.eclipse.xtext.common.types.JvmConstructor
/**
* The dispatch method {@code infer} is called for each instance of the
* given element's type that is contained in a resource.
*
* @param element
* the model to create one or more
* {@link org.eclipse.xtext.common.types.JvmDeclaredType declared
* types} from.
* @param acceptor
* each created
* {@link org.eclipse.xtext.common.types.JvmDeclaredType type}
* without a container should be passed to the acceptor in order
* get attached to the current resource. The acceptor's
* {@link IJvmDeclaredTypeAcceptor#accept(org.eclipse.xtext.common.types.JvmDeclaredType)
* accept(..)} method takes the constructed empty type for the
* pre-indexing phase. This one is further initialized in the
* indexing phase using the closure you pass to the returned
* {@link org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor.IPostIndexingInitializing#initializeLater(org.eclipse.xtext.xbase.lib.Procedures.Procedure1)
* initializeLater(..)}.
* @param isPreIndexingPhase
* whether the method is called in a pre-indexing phase, i.e.
* when the global index is not yet fully updated. You must not
* rely on linking using the index if isPreIndexingPhase is
* |
|
Run mwe2 file again | |
We then right click on 'plugin.xml' and select Run As -> Eclipse Application which starts up a new instance of Eclipse. We then use File -> New -> Plug in Project to create a project. | |
We click on 'Next' and give the project a name. | |
Click on 'Next' again. I'm not sure if the project needs an activator? |
|
Don't select a template and click on finish. | |
When prompted for 'Open Associated Perspective' choose yes. | |
add xbase.lib bundle as a dependency. This can be done by selecting MANIFEST.MF and on the 'Dependency tab click 'add'. Select org.eclipse.xtext.xbase.lib. |
|
Create a new file in the source directory with the appropriate extension for the project. | |
Choose 'yes' when prompted to add Xtext nature. |
If we get problems with operators as on this screen shot:
It may be because the xtend Library is not yet added to the build path, if so we can do the following:
In the second instance of Eclipse, in the package exporer, right click on the JRE System Library directory. Then select Build Path, configure build path. | |
In the Libraries tab click on the 'add library' button. | |
Select 'Xtend Library' and when this dialog button comes up click on finish. |
Next Steps
For other information that I am gathering about xbase see these pages: