Xcore is a textual format to define ecore models. This not only makes editing and reading much more convenient but has other cool advantages as well. Xcore, for instance, allows to embed Xbase expressions to define logic within EOperations and the like.
In this session you will learn, why and when using Xcore is a good idea and how to use it with Xtext languages. I will explain talk about which URIs to use, and how to properly configure the MWE2 file as well as more complicated setups, with multiple languages and mixtures of ecore, xcore and generated models.
5. You will come to the point…
Where you want to take control…
6. Problem
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
elements+=AbstractElement*;
AbstractElement:
Element | SecondElement | ThirdElement
;
Element:
'Element' name=ID ref=[AbstractElement]
;
SecondElement:
'SecondElement' name=ID
;
ThirdElement:
'ThirdElement' name=ID
;
Example
7. Problem
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
elements+=AbstractElement*;
AbstractElement:
Element | SecondElement | ThirdElement
;
Element:
'Element' name=ID ref=[AbstractElement]
;
SecondElement:
'SecondElement' name=ID
;
ThirdElement:
'ThirdElement' name=ID
;
Example
8. grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
elements+=AbstractElement*;
AbstractElement:
Element | SecondElement | ThirdElement
;
Element:
'Element' name=ID ref=[Referenceable]
;
SecondElement:
'SecondElement' name=ID
;
ThirdElement:
'ThirdElement' name=ID
;
Referenceable:
SecondElement | ThirdElement
;
Never invoked by the parser
Example
Fake Rules to influence EMF Generator
9. For rapid prototyping the generated model is fine
When to stay with the generated model
10. For rapid prototyping the generated model is fine
Automatic synchronisation from grammar to model
When to stay with the generated model
11. For rapid prototyping the generated model is fine
Automatic synchronisation from grammar to model
If you do not need to introduce fake rules
When to stay with the generated model
28. Don’t forget the Xcore dependency
Caused by: org.xml.sax.SAXParseExceptionpublicId: platform:/resource/org.xtext.example.mydsl.model/model/MyDsl.xcore; systemId:
platform:/resource/org.xtext.example.mydsl.model/model/MyDsl.xcore; lineNumber: 1; columnNumber: 1; Content is not allowed in
prolog.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:441)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1436)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:999)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:
510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
Invokes XcoreStandaloneSetup to register *.xcore
33. Caused by: java.lang.IllegalStateException: Problem parsing 'classpath:/org/xtext/example/
mydsl/MyDsl.xtext':
TransformationDiagnostic: null:9 Cannot find compatible feature name in sealed EClass
Greeting from imported package http://www.xtext.org/example/mydsl/MyDsl: The type 'Greeting'
does not have a feature 'name'. (ErrorCode: CannotCreateTypeInSealedMetamodel)
at org.eclipse.xtext.generator.LanguageConfig.setUri(LanguageConfig.java:247)
... 42 more
You will face that Exception
34. Caused by: java.lang.IllegalStateException: Problem parsing 'classpath:/org/xtext/example/
mydsl/MyDsl.xtext':
TransformationDiagnostic: null:9 Cannot find compatible feature name in sealed EClass
Greeting from imported package http://www.xtext.org/example/mydsl/MyDsl: The type 'Greeting'
does not have a feature 'name'. (ErrorCode: CannotCreateTypeInSealedMetamodel)
at org.eclipse.xtext.generator.LanguageConfig.setUri(LanguageConfig.java:247)
... 42 more
You will face that Exception
Ecore
model
Xcore
model
Proxy not resolvable
Index is not aware of genmodel
that the Xcore model links against
Proxy
35. But I added that stuff in the StandaloneSetup…?
36. But I added that stuff in the StandaloneSetup…?
ResourceSet
Resource
Resource
Resource
Resource
ResourceSet
Resource
Resource
44. More complex example
Xtext DSL Xtext DSL
Languages referencing each other
Plugin
Xtext
DSL 1
Plugin
Xtext
DSL 1
Problem
Circular dependency
Buddypolicy
45. Introduce a Ecore model as a protocol
Xtext DSL Xtext DSL
Ecore
model
Generated
Model
Generated
Model
46. grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
import "http://www.xtext.org/common/model" as common
PackageDeclaration returns common::PackageDeclaration:
'package' name=FQN
content+=Element
;
Element returns common::NamedElement:
{Element}
'element' name=ID '{'
ref=[common::Referenceable | FQN]?
'}'
;
FQN:
ID ('.' ID)*
;
Introduce a Ecore model as a protocol
47. grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
import "http://www.xtext.org/common/model" as common
PackageDeclaration returns common::PackageDeclaration:
'package' name=FQN
content+=Element
;
Element returns common::NamedElement:
{Element}
'element' name=ID '{'
ref=[common::Referenceable | FQN]?
'}'
;
FQN:
ID ('.' ID)*
;
Introduce a Ecore model as a protocol
53. grammar org.xtext.example.firstdsl.Lang with org.eclipse.xtext.common.Terminals
import "org.xtext.example.myfirstdsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "http://www.xtext.org/common/model" as common
import "org.xtext.example.myseconddsl" as second
PackageDeclaration returns common::PackageDeclaration :
'package' name=FQN
content+=FirstElement*
;
FirstElement :
'element' name=ID '{'
ref=[second::SecondElement| FQN]?
'}'
;
FQN:
ID ('.' ID)*
;
A lot of imports…
54. grammar org.xtext.example.firstdsl.Lang with org.eclipse.xtext.common.Terminals
import "org.xtext.example.myfirstdsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "http://www.xtext.org/common/model" as common
import "org.xtext.example.myseconddsl" as second
PackageDeclaration returns common::PackageDeclaration :
'package' name=FQN
content+=FirstElement*
;
FirstElement :
'element' name=ID '{'
ref=[second::SecondElement| FQN]?
'}'
;
FQN:
ID ('.' ID)*
;
Have same root node…
55. grammar org.xtext.example.firstdsl.Lang with org.eclipse.xtext.common.Terminals
import "org.xtext.example.myfirstdsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "http://www.xtext.org/common/model" as common
import "org.xtext.example.myseconddsl" as second
PackageDeclaration returns common::PackageDeclaration :
'package' name=FQN
content+=FirstElement*
;
FirstElement :
'element' name=ID '{'
ref=[second::SecondElement| FQN]?
'}'
;
FQN:
ID ('.' ID)*
;
Use implicitly imported classifier
57. grammar org.xtext.example.firstdsl.Lang with org.eclipse.xtext.common.Terminals
import "org.xtext.example.myfirstdsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "http://www.xtext.org/common/model" as common
import "org.xtext.example.myseconddsl" as second
PackageDeclaration returns common::PackageDeclaration :
'package' name=FQN
content+=FirstElement*
;
FirstElement :
'element' name=ID '{'
ref=[second::SecondElement| FQN]?
'}'
;
FQN:
ID ('.' ID)*
;
But there is a small problem
58. grammar org.xtext.example.firstdsl.Lang with org.eclipse.xtext.common.Terminals
import "org.xtext.example.myfirstdsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "http://www.xtext.org/common/model" as common
import "org.xtext.example.myseconddsl" as second
PackageDeclaration returns common::PackageDeclaration :
'package' name=FQN
content+=FirstElement*
;
FirstElement :
'element' name=ID '{'
ref=[second::SecondElement| FQN]?
'}'
;
FQN:
ID ('.' ID)*
;
CA is showing both elements?
59. grammar org.xtext.example.firstdsl.Lang with org.eclipse.xtext.common.Terminals
import "org.xtext.example.myfirstdsl"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "http://www.xtext.org/common/model" as common
import "org.xtext.example.myseconddsl" as second
PackageDeclaration returns common::PackageDeclaration :
'package' name=FQN
content+=FirstElement*
;
FirstElement :
'element' name=ID '{'
ref=[second::SecondElement| FQN]?
'}'
;
FQN:
ID ('.' ID)*
;
CA is showing both elements?
60. Xtext DSL Xtext DSL
Ecore
model
Xcore
model
Xcore
model
generated
Model
generated
Model
One way to solve that…
62. One way to solve that…
grammar org.xtext.example.seconddsl.Lang with org.eclipse.xtext.common.Terminals
generate generatedSecondModel "http://www.xtext.org/generatedSecondModel"
import "org.xtext.example.myseconddsl"
import "http://www.xtext.org/common/model" as common
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "org.xtext.example.myfirstdsl" as first
PackageDeclaration returns common::PackageDeclaration :
'package' name=FQN
content+=SecondElement*
;
SecondElement returns SecondElement:
{CustomSecondElement}
'element' name=ID '{'
ref=[first::FirstElement | FQN]?
'}'
;
FQN:
ID ('.' ID)*
;
63. One way to solve that…
grammar org.xtext.example.seconddsl.Lang with org.eclipse.xtext.common.Terminals
generate generatedSecondModel "http://www.xtext.org/generatedSecondModel"
import "org.xtext.example.myseconddsl"
import "http://www.xtext.org/common/model" as common
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "org.xtext.example.myfirstdsl" as first
PackageDeclaration returns common::PackageDeclaration :
'package' name=FQN
content+=SecondElement*
;
SecondElement returns SecondElement:
{CustomSecondElement}
'element' name=ID '{'
ref=[first::FirstElement | FQN]?
'}'
;
FQN:
ID ('.' ID)*
;
64. But when I run it….
[ERROR]: GeneratorException: (Element: -UNKNOWN-; Reported by: Generator)
java.lang.RuntimeException: Could not find a GenModel for EPackage 'http://www.xtext.org/
generatedSecondModel' from http://www.xtext.org/generatedSecondModel
If the missing GenModel has been generated via EMFGeneratorFragment or EcoreGeneratorFragment make
sure to run it first in the workflow.
If you have a *.genmodel-file, make sure to register it via
StandaloneSetup.registerGenModelFile(String)
at org.eclipse.xtext.generator.GenModelAccess.getGenModelResource(GenModelAccess.java:137)
at org.eclipse.xtext.generator.GenModelAccess.getGenPackage(GenModelAccess.java:85)
65. But when I run it….
// generates Java API for the generated EPackages
fragment = ecore.EMFGeneratorFragment auto-inject {}
Don’t forget the EMFGeneratorFragment
[ERROR]: GeneratorException: (Element: -UNKNOWN-; Reported by: Generator)
java.lang.RuntimeException: Could not find a GenModel for EPackage 'http://www.xtext.org/
generatedSecondModel' from http://www.xtext.org/generatedSecondModel
If the missing GenModel has been generated via EMFGeneratorFragment or EcoreGeneratorFragment make
sure to run it first in the workflow.
If you have a *.genmodel-file, make sure to register it via
StandaloneSetup.registerGenModelFile(String)
at org.eclipse.xtext.generator.GenModelAccess.getGenModelResource(GenModelAccess.java:137)
at org.eclipse.xtext.generator.GenModelAccess.getGenPackage(GenModelAccess.java:85)
76. Pittfalls
Set modelDirectory in Xcore files explicitly
@GenModel(modelDirectory="./src-gen")
package org.xtext.example.myfirstdsl
import common.NamedElement
import common.Referenceable
class FirstElement extends NamedElement, Referenceable {
refers Referenceable ref
}
77. Pittfalls
Don’t use classpath URIs in MWE2
var fileExtensions = "first"
var projectName = "org.xtext.example.firstdsl.lang"
var runtimeProject = "../${projectName}"
var generateXtendStub = true
//var grammarURI = "classpath:/org/xtext/example/firstdsl/Lang.xtext"
var grammarURI = "platform:/resource/${projectName}/src/org/xtext/example/firstdsl/Lang.xtext"
78. Pittfalls
Explicitly set path to generate Java classes
// generates Java API for the generated EPackages
fragment = ecore.EMFGeneratorFragment auto-inject {
javaModelDirectory = "/${projectName}/src-gen"
}