Workshop On Xtext

4,536 views
4,377 views

Published on

With Sebastian Zarnekow and Moritz Eysholdt
Hands-on Workshop at Code Generation 2009

Published in: Technology
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,536
On SlideShare
0
From Embeds
0
Number of Embeds
215
Actions
Shares
0
Downloads
236
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide

Workshop On Xtext

  1. 1. Software Installation • You‘ll find a CD with the required software on your desk • Unzip the Eclipse distribution matching your OS Windows users: Use a location close to the root directory • Run the Eclipse executable • Choose File -> Import -> Existing projects into workspace • Select Archive file and choose workspace.zip from the CD
  2. 2. Workshop Moritz Eysholdt, Sebastian Zarnekow, Jan Köhnlein
  3. 3. Moritz Eysholdt Jan Köhnlein Sebastian Zarnekow
  4. 4. Moritz Eysholdt Jan Köhnlein Sebastian Zarnekow
  5. 5. Moritz Eysholdt Jan Köhnlein Sebastian Zarnekow
  6. 6. What is a Domain Specific Language (DSL)?
  7. 7. A domain-specific language (DSL) is a formal, processable language targeting at a specific viewpoint or aspect of a system.
  8. 8. A domain-specific language (DSL) is a formal, processable language targeting at a specific viewpoint or aspect of a system. Its semantics, flexibility and notation is designed in order to support working with that viewpoint as good as possible.
  9. 9. Why would I want to use a DSL?
  10. 10. GPL vs DSL
  11. 11. GPL vs DSL
  12. 12. GPL vs DSL
  13. 13. Abstraction
  14. 14. Why isn‘t everybody using DSLs?
  15. 15. Complicated Expensive
  16. 16. Isn‘t text a little bit old- fashioned?
  17. 17. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true;
  18. 18. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • High-level views public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true;
  19. 19. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • High-level views public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) } • Detailed views && left.getEPackage().getNsURI().equals(right.getEPackage().g protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true;
  20. 20. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • High-level views public boolean internalIsSameStructure(EObject left, EObject right) { • ++counter; Suggests non-formalism if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) } • Detailed views && left.getEPackage().getNsURI().equals(right.getEPackage().g protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true;
  21. 21. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • High-level views public boolean internalIsSameStructure(EObject left, EObject right) { • ++counter; Suggests non-formalism if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) } • Detailed views && left.getEPackage().getNsURI().equals(right.getEPackage().g • Formal protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true;
  22. 22. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • High-level views public boolean internalIsSameStructure(EObject left, EObject right) { • ++counter; Suggests non-formalism if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri • Individual tools return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) } • Detailed views && left.getEPackage().getNsURI().equals(right.getEPackage().g • Formal protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true;
  23. 23. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • High-level views public boolean internalIsSameStructure(EObject left, EObject right) { • ++counter; Suggests non-formalism if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri • Individual tools return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) } • Detailed views && left.getEPackage().getNsURI().equals(right.getEPackage().g • Formal protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( • Well established tools for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true;
  24. 24. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • High-level views public boolean internalIsSameStructure(EObject left, EObject right) { • ++counter; Suggests non-formalism if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri • Individual tools return false; } List<EObject> leftChildren = getRelevantChildren(left); • Hard to evolve List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) } • Detailed views && left.getEPackage().getNsURI().equals(right.getEPackage().g • Formal protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( • Well established tools for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true;
  25. 25. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • High-level views public boolean internalIsSameStructure(EObject left, EObject right) { • ++counter; Suggests non-formalism if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri • Individual tools return false; } List<EObject> leftChildren = getRelevantChildren(left); • Hard to evolve List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) } • Detailed views && left.getEPackage().getNsURI().equals(right.getEPackage().g • Formal protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( • Well established tools for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { } } • Easy to evolve i.remove(); return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true;
  26. 26. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • High-level views public boolean internalIsSameStructure(EObject left, EObject right) { • ++counter; Suggests non-formalism if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri • Individual tools return false; } List<EObject> leftChildren = getRelevantChildren(left); • Hard to evolve List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r • Editing with mouse } return false; for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) } • Detailed views && left.getEPackage().getNsURI().equals(right.getEPackage().g • Formal protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( • Well established tools for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { } } • Easy to evolve i.remove(); return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true;
  27. 27. } protected String getErrorMessage() { return errorMessage.toString(); } Graphics public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • High-level views public boolean internalIsSameStructure(EObject left, EObject right) { • ++counter; Suggests non-formalism if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri • Individual tools return false; } List<EObject> leftChildren = getRelevantChildren(left); • Hard to evolve List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r • Editing with mouse } return false; for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } Text return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) } • Detailed views && left.getEPackage().getNsURI().equals(right.getEPackage().g • Formal protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents( • Well established tools for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { } • Easy to evolve i.remove(); • } } Editing with keyboard return relevantChildren; protected boolean isRelevantChild(EObject container, EObject child) { return true;
  28. 28. Showtime ! • In your Eclipse workbench • Choose Run->Run configurations... • Double click on Eclipse Application • Go to the Arguments tab and add -XX:MaxPermSize=128m to the VM arguments • Click on Run
  29. 29. A Guided Example entity Conference { property Name : String on Attendees refs many Pers Sp eakers refs many Speaker } entity Person { property Name : String } { enti ty Speaker extends Person n Sessions refs many Sessio } entity Session { property Title: String property IsTutorial : Bool }
  30. 30. Grammar Language grammar org.xtext.cg2009.Entities with org.eclipse.xtext.common.Terminals generate entities "http://www.xtext.org/cg2009/Entities" Model : (entities += Entity)+; Entity returns Entity: 'entity' name=ID ('extends' superType=[Entity])? '{' (properties+=Property)* '}'; Property: SimpleProperty | ReferenceProperty; SimpleProperty: 'property' name=ID ':' type=('String'|'Number'|'Bool'); ReferenceProperty : name=ID 'refs' ('one' | many?='many')? type=[Entity];
  31. 31. Edit SQL with Xtext CREATE TABLE Conferences ( id INTEGER NOT NULL PRIMARY KEY, • Only ) name CHAR(50) Create-Statements • List of columns
  32. 32. Edit SQL with Xtext CREATE TABLE Conferences ( id INTEGER NOT NULL PRIMARY KEY, name CHAR(50) • Enhance with ) Foreign Keys CREATE TABLE Speaker ( name CHAR(50), id INTEGER, FOREIGN KEY (id) REFERENCES Conference(id) )
  33. 33. What’s wrong with it?
  34. 34. Cross References
  35. 35. Cross References Model Element
  36. 36. Cross References Element Name Model Element
  37. 37. Cross References Element Name resolve Model Element
  38. 38. Cross References Element Name resolve determin Model Element
  39. 39. Problem: Names may not be ambiguous.
  40. 40. Problem: Names may not be ambiguous. Solution: Implement a ScopeProvider!
  41. 41. Problem: Names may not be ambiguous. Solution: Implement a ScopeProvider! A Scope is a context specific, hierarchical collection of all reachable model elements and their respective names.
  42. 42. Scope Provider Make Foreign Keys work! public IScope scope_ForeignKey_from( ForeignKey context, EReference reference) { Table fromTable = (Table) context.eContainer(); return createTableScope(fromTable); }
  43. 43. Meta-Model Inference grammar org.xtext.codeGeneration.Entities with org.eclipse.xtext.common.Terminals generate entities "http://www.xtext.org/CG2009/Entities" Model : (entities += Entity)+; Entity returns Entity: 'entity' name=ID ('extends' superType=[Entity])? '{' (properties+=Property)* '}'; Property: SimpleProperty | ReferenceProperty; SimpleProperty: 'property' name=ID ':' type=('String'|'Number'|'Bool'); ReferenceProperty : name=ID 'refs' ('one' | many?='many')? type=[Entity];
  44. 44. Model Conferences with Xtext How do I create a language for an existing meta-model?
  45. 45. Model Conferences with Xtext
  46. 46. Validate Your Conference 1. Have a look at the generated Validator-Stub. 2. Implement some checks for your language. 3. Check out the results. @Check public void checkSpeakersName(Speaker speaker) { assertTrue("Speaker's name is to short.", ConferencesLanguagePackage.SPEAKER__NAME, speaker.getName().length() >= 2); }
  47. 47. Convention over Configuration
  48. 48. Configured with Google Guice class MyDslRuntimeModule extends DefaultRuntimeModule { Class<? extends ServiceInterface> bindService() { return MyServiceImplementation.class; } }
  49. 49. Extensible Language Generator • Generates a lot of Java code • Composed of fragments • Customizable • Add your own fragments!
  50. 50. http://www.wordle.net/
  51. 51. Formatting Pretty Printing Code Beautification import <Literature.entities> entity City {Int id; String name;} entity Store { Int id; String name; Int city references City. id; }
  52. 52. Formatting Pretty Printing Code Beautification import <Literature.entities> entity City {Int id; String name;} entity Store { Int id; String name; Int import <Literature.entities> city references entity City { City. Int id; id; } String name; } entity Store { Int id; String name; Int city references City.id; }
  53. 53. Formatting Pretty Printing Code Beautification import <Literature.entities> entity City {Int id; String name;} entity Store { Int id; String name; Int import <Literature.entities> city references entity City { City. Int id; id; } String name; } entity Store { Int id; String name; Int city references City.id; }
  54. 54. Formatting Pretty Printing Code Beautification import <Literature.entities> entity City {Int id; String name;} entity Store { Int id; String name; Int import <Literature.entities> city references entity City { City. Int id; id; } String name; } entity Store { Int id; String name; Int city references City.id; § 1. At ... do ... } § 2. At ... do ... § 3. At ... do ... § 4. At ... do ... ...
  55. 55. Integration with EMF
  56. 56. Integration with EMF eclipse Any EMF-based modeling Code Generator GMF Editor P R O J E C T Component
  57. 57. Integration with EMF eclipse Any EMF-based modeling Code Generator GMF Editor P R O J E C T Component <<abstract>> XMIResource Resource
  58. 58. Integration with EMF eclipse Any EMF-based modeling Code Generator GMF Editor P R O J E C T Component <<abstract>> XMIResource Resource
  59. 59. Integration with EMF eclipse Any EMF-based modeling Code Generator GMF Editor P R O J E C T Component <<abstract>> XMI XMIResource Resource
  60. 60. Integration with EMF eclipse Any EMF-based modeling Code Generator GMF Editor P R O J E C T Component <<abstract>> XMI XMIResource Resource
  61. 61. Integration with EMF eclipse Any EMF-based modeling Code Generator GMF Editor P R O J E C T Component <<abstract>> XMI XMIResource Resource XtextResource
  62. 62. Integration with EMF eclipse Any EMF-based modeling Code Generator GMF Editor P R O J E C T Component <<abstract>> XMI XMIResource Resource XtextResource
  63. 63. Integration with EMF eclipse Any EMF-based modeling Code Generator GMF Editor P R O J E C T Component <<abstract>> XMI XMIResource Resource XtextResource Text
  64. 64. Integration with EMF eclipse Any EMF-based modeling Code Generator GMF Editor P R O J E C T Component <<abstract>> XMI XMIResource Resource XtextResource Text Parser Linker Serializer ValueConverter ScopeProvider Formatter
  65. 65. EMF Index • Indexes all resources in workspace • Query elements and cross-references • Efficient scoping
  66. 66. EMF Index • Indexes all resources in workspace • Query elements and cross-references • Efficient scoping Load Resources
  67. 67. Learn more at http://www.xtext.org

×