diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b29ce5103195a3a893f2b1a51326018f7ef26ff5..ed535eb48a6c031065c01a7739f54d80eb863d71 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -32,8 +32,8 @@ stages: script: - "./gradlew setDevVersionForCI" - "./gradlew publish" - except: - - main + only: + - dev .publish_main: stage: publish @@ -78,12 +78,12 @@ publish_main11: ragdoc_build: image: name: "git-st.inf.tu-dresden.de:4567/jastadd/ragdoc-builder" - entrypoint: [""] stage: ragdoc needs: - test11 script: - JAVA_FILES=$(find grammar2uml/src/ -name '*.java') + - echo $JAVA_FILES | wc -l - /ragdoc-builder/start-builder.sh -excludeGenerated -d data/ $JAVA_FILES only: - dev @@ -95,7 +95,6 @@ ragdoc_build: ragdoc_view: image: name: "git-st.inf.tu-dresden.de:4567/jastadd/ragdoc-view:relations" - entrypoint: [""] stage: ragdoc needs: - ragdoc_build @@ -104,7 +103,7 @@ ragdoc_view: - mkdir -p pages/docs/ragdoc - OUTPUT_DIR=$(pwd -P)/pages/docs/ragdoc - cd /ragdoc-view/src/ && rm -rf data && ln -s $DATA_DIR - - /ragdoc-view/build-view.sh --output-path=$OUTPUT_DIR + - BASE_HREF=/grammar2uml/ragdoc/ /ragdoc-view/build-view.sh --output-path=$OUTPUT_DIR only: - dev - main @@ -126,4 +125,5 @@ pages: paths: - public/ only: + - dev - main diff --git a/grammar2uml/src/main/java/de/tudresden/inf/st/jastadd/grammar2uml/compiler/Grammar2UmlProcessor.java b/grammar2uml/src/main/java/de/tudresden/inf/st/jastadd/grammar2uml/compiler/Grammar2UmlProcessor.java index f07e453c1f4260c1e5e2f770df3f1c6cc63efdf1..22d6d5211cafb09bb800d53a0d44fd09136bd438 100644 --- a/grammar2uml/src/main/java/de/tudresden/inf/st/jastadd/grammar2uml/compiler/Grammar2UmlProcessor.java +++ b/grammar2uml/src/main/java/de/tudresden/inf/st/jastadd/grammar2uml/compiler/Grammar2UmlProcessor.java @@ -36,31 +36,69 @@ public class Grammar2UmlProcessor { return this; } + /** + * Write debugging information while reading in grammar files. + * @param value whether to write debugging information + * @return this + */ public Grammar2UmlProcessor setVerbose(boolean value) { this.verbose = value; return this; } + /** + * Add folders to the representation. The folder needs to be initialized. + * @param folders initialized folders to be added + * @return this + */ public Grammar2UmlProcessor addFolder(Folder... folders) { Collections.addAll(this.folders, folders); return this; } + /** + * Configure to use one folder per given grammar file. + * @param value whether to use default folders + * @return this + */ public Grammar2UmlProcessor setUseDefaultFolders(boolean value) { useDefaultFolders = value; return this; } + /** + * Add a callback to run after the complete parsed program has been parsed. + * @param callback a function to be run, given the processed grammar files + * @return this + */ public Grammar2UmlProcessor addPostProcessing(Consumer<Grammar2Uml> callback) { this.callbacks.add(callback); return this; } + /** + * Sets the new definition to style the representation. + * + * This is a method that can alter the style for each {#{@link TypeDecl}}. + * @param definition the new style definition + * @return this + */ public Grammar2UmlProcessor setStyleDefinition(StyleDefinition definition) { this.styleDefinition = definition; return this; } + /** + * Writes the representation to the given destination file. + * + * The file extension is used to decide the output type. + * Supported extensions are: md, html, png, pdf, svg. + * + * <br> + * <b>Note:</b> PDF requires additional dependencies, see <a href="https://plantuml.com/pdf">https://plantuml.com/pdf</a> + * @param destination the file to write to + * @throws CompilerException if generation or writing the file has failed + */ public void writeFile(Path destination) throws CompilerException { build(); @@ -108,6 +146,15 @@ public class Grammar2UmlProcessor { } } + /** + * Create separate diagrams for each grammar file. + * + * Types from other grammar files are depicted using boxes with dashed borders. + * @param destinationDirectory a directory where all files shall be written to + * @param extension the file extension to be used for all diagrams + * @throws CompilerException if generation or writing the file has failed + * @see #writeFile(Path) method writeFile for supported file extensions + */ public void generateSeparateGrammarDiagrams(Path destinationDirectory, String extension) throws CompilerException { build(); @@ -197,11 +244,11 @@ public class Grammar2UmlProcessor { } grammar2uml.setStyleDefinition(styleDefinition); - callbacks.forEach(consumer -> consumer.accept(grammar2uml)); - grammar2uml.setProgram(program); grammar2uml.treeResolveAll(); + callbacks.forEach(consumer -> consumer.accept(grammar2uml)); + if (!grammar2uml.errors().isEmpty()) { System.err.println("Errors:"); for (ErrorMessage e : grammar2uml.errors()) { diff --git a/grammar2uml/src/main/java/de/tudresden/inf/st/jastadd/grammar2uml/compiler/SimpleMain.java b/grammar2uml/src/main/java/de/tudresden/inf/st/jastadd/grammar2uml/compiler/SimpleMain.java index 71f9b7d82d162da0c6cd4300374c301b4c417d36..8e9b269e5981e91153942fa15ee1299b72622f07 100644 --- a/grammar2uml/src/main/java/de/tudresden/inf/st/jastadd/grammar2uml/compiler/SimpleMain.java +++ b/grammar2uml/src/main/java/de/tudresden/inf/st/jastadd/grammar2uml/compiler/SimpleMain.java @@ -33,7 +33,7 @@ public class SimpleMain { .addFolder() .addPostProcessing(grammar2Uml -> {}) .addGrammar("src/main/jastadd/Grammar2Uml.relast", - "src/gen/jastadd-sources/relast.preprocessor/RelAst.relast") + "src/gen/jastadd-sources/relast.preprocessor/RelAst.relast") .setStyleDefinition((typeDecl, style) -> { switch (typeDecl.getName()) { case "Component": diff --git a/grammar2uml/src/main/resources/grammar2umlVersion.properties b/grammar2uml/src/main/resources/grammar2umlVersion.properties index c1ab792e6390c194ba5f59630ed61deed54f594c..1b6f9fba77a949f4802f567423cdaff207d59ee7 100644 --- a/grammar2uml/src/main/resources/grammar2umlVersion.properties +++ b/grammar2uml/src/main/resources/grammar2umlVersion.properties @@ -1,2 +1,2 @@ -#Fri Aug 26 14:06:56 CEST 2022 -version=0.2.5 +#Fri Sep 30 14:31:26 CEST 2022 +version=0.2.6 diff --git a/pages/docs/adding.md b/pages/docs/adding.md index 4fbae9782363a4b203247c4f575150aac75bfa90..954476557eb0e9f8602bf0ec646b2a1eeeab3383 100644 --- a/pages/docs/adding.md +++ b/pages/docs/adding.md @@ -1,8 +1,9 @@ -# Add grammar2uml to your project +# Add Grammar2uml to your project -To use `Grammar2uml`, adjust your `build.gradle` as follows. +There are two ways, how to use Grammar2uml: As a Gradle task, or programmatically. +The latter offers more ways for configuration. -Set up the maven package source as repository: +For both, the repository has to added within `build.gradle`: ```gradle repositories { @@ -14,7 +15,11 @@ repositories { } ``` -Add `Grammar2uml` as a dependency: +## Usage as Gradle task + +To use `Grammar2uml` via Gradle task, adjust your `build.gradle` as follows. + +Add `Grammar2uml` as a dependency via a configuration: ``` configurations { @@ -22,11 +27,11 @@ configurations { } dependencies { - grammar2uml group: 'de.tudresden.inf.st', name: 'grammar2uml', version: '0.2.2' + grammar2uml group: 'de.tudresden.inf.st', name: 'grammar2uml', version: '<VERSION>' } ``` -Add a task to create your visualization: +Then, add a task to create your visualization: ``` task grammar2uml(type: JavaExec) { @@ -38,7 +43,7 @@ task grammar2uml(type: JavaExec) { } ``` -## Build from source (not recommended) +### Build from source (not recommended) If you want to build `Grammar2Uml` from source, first build the fat-jar from the [repository](https://git-st.inf.tu-dresden.de/jastadd/grammar2uml). The normal jar does not suffice, as it lacks the information on needed dependencies. @@ -65,3 +70,15 @@ dependencies { ``` The path to the jar file may need to be changed according to your project structure. + +## Programmatically Usage + +To use `Grammar2uml` programmatically, a similar setup is needed. + +Add `Grammar2uml` as an implementation dependency: + +``` +dependencies { + implementation group: 'de.tudresden.inf.st', name: 'grammar2uml', version: '<VERSION>' +} +``` diff --git a/pages/docs/index.md b/pages/docs/index.md index a19a53409c8849b7d961311cd3fe2fc529a0f4f5..d5427337501a227a2e3e50937d980232d8436408 100644 --- a/pages/docs/index.md +++ b/pages/docs/index.md @@ -7,26 +7,4 @@ The tool called `Grammar2Uml` ([see in repo](https://git-st.inf.tu-dresden.de/ja Every nonterminal will be shown as a rectangular box with its terminal children listed within it. Children are shown as containment relations between parent and child, whereas relations and intrinsic references are shown using arrows. -Furthermore, more options may be specified. - -| Name | Description | -|----------------------|-------------------------------------------------------------------------| -| `--output` | target file to be generated (default: `uml.md` or `uml.png`, depending on `--printSource`) | -| `--inputGrammar2Uml` | grammar2uml definition file, see [below](#grammar2uml-definition-file). | -| `--printSource` | If set, the output will be the source code instead of a png. (default: create a png) | -| `--defaultFolders` | If set, creates a default folder per grammar file. (default: use one global folder) | -| `--help` | Print usage and exit. | -| `--version` | Print version and exit. | -| `--verbose` | Print more messages while compiling. | - -## Grammar2uml definition file - -To structure the generated visualization, any number of nonterminals can be grouped with folders. -Either specify the option `--defaultFolders` to use one folder per input grammar file, or specify a grammar2uml definition file. -The definition file has a simple syntax, it is a list of folder specifications. One specifications looks like - -``` -folder FOLDER_NAME : NT1, NT2, ..., NT_n -``` - -It produces one folder named `FOLDER_NAME` containing all nonterminals (`NT1`, `NT2`, ..., `NT_n`) following it. +Furthermore, more options may be specified, as described in ["Usage as Gradle task"](using.md#usage-as-gradle-task). diff --git a/pages/docs/using.md b/pages/docs/using.md new file mode 100644 index 0000000000000000000000000000000000000000..1c2ff84d196bd2dcf7fdd071e2c10e05c5402cf9 --- /dev/null +++ b/pages/docs/using.md @@ -0,0 +1,84 @@ +# Using grammar2uml + +There are two ways, how to use Grammar2uml: As a Gradle task, or programmatically. +The latter offers more ways for configuration. + +## Usage as Gradle task + +When starting the Gradle task, the following parameters can be provided: + +| Name | Description | +|----------------------|--------------------------------------------------------------------------------------------| +| `--output` | target file to be generated (default: `uml.md` or `uml.png`, depending on `--printSource`) | +| `--inputGrammar2Uml` | grammar2uml definition file, see [below](#grammar2uml-definition-file). | +| `--printSource` | If set, the output will be the source code instead of a png. (default: create a png) | +| `--defaultFolders` | If set, creates a default folder per grammar file. (default: use one global folder) | +| `--help` | Print usage and exit. | +| `--version` | Print version and exit. | +| `--verbose` | Print more messages while compiling. | + +### Grammar2uml definition file + +To structure the generated visualization, any number of nonterminals can be grouped with folders. +Either specify the option `--defaultFolders` to use one folder per input grammar file, or specify a grammar2uml definition file. +The definition file has a simple syntax, it is a list of folder specifications. One specifications looks like + +``` +folder FOLDER_NAME : NT1, NT2, ..., NT_n +``` + +It produces one folder named `FOLDER_NAME` containing all nonterminals (`NT1`, `NT2`, ..., `NT_n`) following it. + +## Programmatically Usage + +After [adding Grammar2uml to your project](adding.md#programmatically-usage), you can start creating a representation of the grammar. +Here is one example with a `Model` containing nodes of type `Robot`, `Joint` and `EndEffector` amongst others. +It is explained in detail below. + +```java +import de.tudresden.inf.st.jastadd.grammar2uml.compiler.Grammar2UmlProcessor; +import org.jastadd.relast.compiler.CompilerException; + +public class Main { + public static void main(String[] args) throws CompilerException { + Grammar2UmlProcessor processor = new Grammar2UmlProcessor(); // (1) + processor + .addGrammar("src/main/jastadd/Model.relast", + "src/gen/jastadd-sources/common/shared.relast") // (2) + .setVerbose(true) // (3) + .setStyleDefinition((typeDecl, style) -> { // (4) + switch (typeDecl.getName()) { + case "Robot": + case "Joint": + style.setInlineAsSuperType(true); // (4.1) + break; + case "EndEffector": + style.setBackgroundColor("blue\\9932CC"); // (4.2) + } + }) + .setUseDefaultFolders(true); // (5) + processor.writeFile(Paths.get("api.md")); // (6) + processor.writeFile(Paths.get("api.png")); // (6) + + processor.generateSeparateGrammarDiagrams(Paths.get("."), "png"); // (7) + } +} +``` + +Grammar2uml uses the [Builder design pattern](https://en.wikipedia.org/wiki/Builder_pattern) as well as a [fluent API](https://en.wikipedia.org/wiki/Fluent_interface). +That means, first, all settings are specified (2-5), and only after a "dump"-method is called (6,7) the actual representation is created. + +The steps in detail: + +- (1) In the beginning, a new `Grammar2UmlProcessor` is created. This is uses the same internals as the [Gradle task](#usage-as-gradle-task). +- (2) Using this processor, the grammar files, that shall be included in the representation have to be specified. Currently, all types used in production rules have to be defined, i.e., the total grammar has to be complete. Otherwise, an error is raised. +- (3) [Optional] To output information helpful for debugging problems, verbose processing can be turned on. +- (4) [Optional] There is one entry point for styling types in the representation. + - (4.1) One possibility is to replace the normal inheritance relation with an inline notation (no conformance with UML) to reduce the number of arrows for inheritance. If a type `SubA` inherits from `A` and for the type `A`, this option is activated, then the former is represented using the label `SubA : A`. + - (4.2) The background color of the type box can be defined using `setBackgroundColor`. +- (5) [Optional] If multiple grammar files have been passed in step (2), then there is the option to create a folder for each file containing all types defined in it. This way, types are better grouped by their defining grammar file. +- (6) To create a representation containing all types, the method `writeFile` is used. It deduces the type of output from the file extension. +- (7) It is also possible to create separate grammar diagrams, i.e., one for each grammar file with other used types depicted as boxes with dashed borders. + +To summarise the required steps: Create a processor, specify grammar files, configure the representation, and write the output. +For more configuration options, please consult the [API Docs of Grammar2UmlProcessor](../ragdoc/#/type/Grammar2UmlProcessor). diff --git a/pages/mkdocs.yml b/pages/mkdocs.yml index 771bf572ac3a8af453bc38a0205e71337d1298a5..add2083170b81768b2dbd086ac8b5e27abbd5594 100644 --- a/pages/mkdocs.yml +++ b/pages/mkdocs.yml @@ -5,6 +5,7 @@ site_dir: ../public nav: - "Grammar2uml": index.md - "Add to your project": adding.md + - "Using Grammar2uml": using.md - "API documentation": ragdoc/index.html theme: