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:













