# endgen This is a converter tool that reads a DSL and generates output files. Endgen is Open Source Software using the [Apache Software License v2.0](http://www.apache.org/licenses/LICENSE-2.0) ## Motivation The motivation behind this tool is that I wanted to generate boilerplate code for handling HTTP Endpoints (hence the endgen name). I had one project written in Scala using the [Tapir](https://tapir.softwaremill.com/) library. Another Java project using [Spring](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html) Boot. In both of these projects had a very simple endpoints only supporting POST, taking some datatype as payload and using the same response type. That's a lot of boilerplate, especially in the Scala case where the payload datatype had to be written in several separate files (for endpoint-definitions, circe serializer support etc). So I wrote a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) parsed by an [ANTLR4](https://www.antlr.org) parser and a code generator using [freemarker](https://freemarker.apache.org). ## DSL example In the simplest form the DSL looks like this ``` /some/endpoint <- SomeType(foo:String) ``` This gets parsed into an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) which is this case holds a list of Path segments and a data strucutre representing the input/body type. ## Code generation example When the parser is done reading the DSL it will look in a directory for [freemarker](https://freemarker.apache.org) templates. For each template it finds it sends in the AST. The resulting file (per template) is written to an output directory. The idea being that you can take these files and probably adapt them before checking them into your project. Endgen does not aim to be a roundtrip tool (i.e. reading the generated source, or being smart in updating them etc). It is also a very limited DSL, you can for example not express what type of HTTP Verb to use or declare response codes. There are no plans to extend the DSL to do that either. ## DSL This is the ANTLR grammar for the root of the DSL ```antlrv4 document : generatorconfig? (namedTypeDeclaration|endpoint)* ; ``` Meaning that the DSL file has an optional `generatorconfig` block at the top. Then you can write either; a type definition, or an endpoint declaration, as many times as you like. Here is an example: ``` { package: se.rutdev.senash, ending: .scala } /some/endpoint <- SomeType(foo:String) Embedded(foo:Bar) /some/other/endpoint <- (bar:Seq[Embedded]) ``` This consists of a config block with 2 items, the 'package' and the 'ending' deinfition. These are available to be used in the freemarker template as a Map of String-keys to String-values. `/some/endpoint <- SomeType(foo:String)` is an endpoint declaration. It declares one endpoint that have a request body data type called `SomeType` that has a field called `foo` of the type `String`. The DSL uses Scala convention of writing data types after the field name separated by a colon. Of course the DSL parser does not know anything about java or scala types, as far as it is concerned these are 2 strings and the first one is just named field-name and the other string is named field-type. `Embedded(foo:Bar)` is a `namedTypeDeclaration` which is parsed the same way as the request type above. But isn't tied to a specific endpoint. `/some/other/endpoint <- (bar:Seq[Embedded])` is another endpoint declaration. However this time the request body is not named in the DSL. But all datatypes must have a name so it will simply name it after the last path segment and tack on the string 'Request' at the end. So the AST till contain a datatype named `endpointRequest` with a field named `bar` and a type-field with the value `Seq[Embedded]`. Again, the parser does not care about, or know anything about what code is generated, so it has not semantic knowledge if these are actual datatypes in the code it generates or if they make sense in java/scala/lua/rust or whatever you decide to generate in the templates. The only 'semantic' validation the parser performs is to check that not two types have the same name. ### DSL config The only key in the config block the generator looks at is called `ending`, this will be used as the file ending for the resulting file of applying the freemarker template. ## Generating