diff --git a/.editorconfig b/.editorconfig index 70db4634..8e776c56 100644 --- a/.editorconfig +++ b/.editorconfig @@ -28,3 +28,7 @@ end_of_line = crlf [*.yml] indent_style = space indent_size = 2 + +[{*.xtext,*.xtend,*.java}] +indent_style = tab +indent_size = 4 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9bd345b7..6b8b8809 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,6 +9,16 @@ on: - master jobs: + mdlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: DavidAnson/markdownlint-cli2-action@v15 + with: + globs: | + **/*.md + !build/**/*.md + !bin/**/*.md build: runs-on: ubuntu-latest steps: diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 00000000..6df9e685 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,7 @@ +{ + "MD013": { + "line_length": 80, + "code_block_line_length": 120, + "tables": false + } +} diff --git a/.vscode/settings.json b/.vscode/settings.json index fa63a3c9..0f8deb00 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,5 +9,6 @@ ], "url": "./schema/yang-lsp-settings-schema.json" } - ] + ], + "markdownlint.ignore": ".gitignore" } diff --git a/README.md b/README.md index fd453eb6..5bf215b9 100644 --- a/README.md +++ b/README.md @@ -3,22 +3,25 @@ [![GH Build Status](https://github.com/TypeFox/yang-lsp/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/TypeFox/yang-lsp/actions/workflows/main.yml) [![Build status](https://ci.appveyor.com/api/projects/status/96eo9k5yo0wtpj50/branch/master?svg=true)](https://ci.appveyor.com/project/kittaakos/yang-lsp/branch/master) -A language server for YANG (see [Language Server Protocol](https://github.com/Microsoft/language-server-protocol)). +A language server for YANG (see [Language Server Protocol][lsp]). ## Usage The language server application is available in two distributions: - `yang-language-server_.zip` (plain language server) -- `yang-language-server_diagram-extension_.zip` (language server with diagram extension for [sprotty](https://github.com/theia-ide/sprotty)) +- `yang-language-server_diagram-extension_.zip` (language server with + diagram extension for [sprotty][sprotty]) -Both variants include start scripts to launch the background process. Connect its input/output streams to your host application in order to communicate with the language server. +Both variants include start scripts to launch the background process. Connect +its input/output streams to your host application in order to communicate with +the language server. The YANG Language Server is currently being used in -- [YANGSTER](https://github.com/theia-ide/yangster) based on [Theia](https://github.com/theia-ide/theia) (incl. diagram extension) -- [Yang VS Code](https://github.com/TypeFox/yang-vscode) available on the [VS Marketplace](https://marketplace.visualstudio.com/items?itemName=typefox.yang-vscode) -- [Yang Eclipse](https://github.com/theia-ide/yang-eclipse) +- [YANGSTER][yangster] based on [Theia][theia] (incl. diagram extension) +- [YANG VS Code][yang-vscode] available on the [VS Marketplace][yang-vscode-vsm] +- [YANG Eclipse][yang-eclipse] ## Build @@ -32,11 +35,25 @@ The YANG Language Server is currently being used in The yang-lsp is the base of multiple binaries -| Repository | Client | Binary | Bin Repo | CI | Trigger | -| ---------- | ------ | ------ | -------- | --- | ------- | -| [yang-lsp](https://github.com/TypeFox/yangs-lsp) | LSP | JAR + script | GH Action Artifacts | [GH Action](https://github.com/TypeFox/yang-lsp/actions/workflows/main.yml) | GH Commit / PR | -| [yangster](https://github.com/theia-ide/yangster) | Theia Browser | Docker image | Docker Hub | [Docker Hub](https://hub.docker.com/r/typefox/yangster/builds) | GitHub hook / Jenkins pipeline| -| | Theia | Theia extension| npm | [Jenkins](http://services.typefox.io/open-source/jenkins/job/yangster/) | `yarn run publish` | -| [yangster-electron](https://github.com/theia-ide/yangster-electron) | Theia Electron | executables | ? | ? | ? | -| [yang-eclipse](https://github.com/theia-ide/yang-eclipse) | Eclipse | p2 update site | Eclipse Marketplace | [Jenkins](http://services.typefox.io/open-source/jenkins/job/yang-eclipse/) | GitHub hook / Jenkins pipeline | -| [yang-vscode](https://github.com/TypeFox/yang-vscode) | VSCode | VSCode extension | VSCode Marketplace | - | `vsce` | +| Repository | Client | Binary | Bin Repo | CI | Trigger | +| -------------------------------------- | -------------- | ---------------- | ------------------- | -------------------------- | ------- | +| [yang-lsp][yang-lsp] | LSP | JAR + script | GH Action Artifacts | [GH Action][yang-lsp-ci] | GH Commit / PR | +| [yangster][yangster] | Theia Browser | Docker image | Docker Hub | [Docker Hub][yangster-ci] | GitHub hook / Jenkins pipeline| +| | Theia | Theia extension | npm | [Jenkins][yangster-ci2] | `yarn run publish` | +| [yangster-electron][yangster-electron] | Theia Electron | executables | ? | ? | ? | +| [yang-eclipse][yang-eclipse] | Eclipse | p2 update site | Eclipse Marketplace | [Jenkins][yang-eclipse-ci] | GitHub hook / Jenkins pipeline | +| [yang-vscode][yang-vscode] | VSCode | VSCode extension | VSCode Marketplace | - | `vsce` | + +[lsp]: https://github.com/Microsoft/language-server-protocol +[sprotty]: https://github.com/theia-ide/sprotty +[yang-lsp]: https://github.com/TypeFox/yang-lsp +[yang-lsp-ci]: https://github.com/TypeFox/yang-lsp/actions/workflows/main.yml +[theia]: https://github.com/theia-ide/theia +[yangster]: https://github.com/theia-ide/yangster +[yangster-ci]: https://hub.docker.com/r/typefox/yangster/builds +[yangster-ci2]: http://services.typefox.io/open-source/jenkins/job/yangster/ +[yangster-electron]: https://github.com/theia-ide/yangster-electron +[yang-vscode]: https://github.com/TypeFox/yang-vscode +[yang-vscode-vsm]: https://marketplace.visualstudio.com/items?itemName=typefox.yang-vscode +[yang-eclipse]: https://github.com/theia-ide/yang-eclipse +[yang-eclipse-ci]: http://services.typefox.io/open-source/jenkins/job/yang-eclipse/ diff --git a/docs/Extensions.md b/docs/Extensions.md index 7c566bb4..0fbd22f6 100644 --- a/docs/Extensions.md +++ b/docs/Extensions.md @@ -1,7 +1,8 @@ # Extensions -The yang-lsp allows to have additional third party extensions, configured through `yang.settings`. -For details on file format and schema see [Settings.md](./Settings.md). +The yang-lsp allows to have additional third party extensions, configured +through `yang.settings`. For details on file format and schema see +[Settings.md](./Settings.md). So far two different kinds of extensions are supported : @@ -10,7 +11,9 @@ So far two different kinds of extensions are supported : ## Create a Validator -A validator extension is a Java class that implements the interface `io.typefox.yang.validation.IValidatorExtension`. +A validator extension is a Java class that implements the interface +`io.typefox.yang.validation.IValidatorExtension`. + Here is a small example: ```java @@ -50,7 +53,7 @@ class MyCommand implements ICommandExtension { * return a list of commands. A command string is used as ID internally and as a label in the UI. */ override getCommands() { - #[COMMAND] + #[COMMAND] } /** diff --git a/docs/Processing_Files.md b/docs/Processing_Files.md index ca851505..8a62d5a7 100644 --- a/docs/Processing_Files.md +++ b/docs/Processing_Files.md @@ -1,8 +1,13 @@ # Processing YANG files -As yang-lsp contains all the tools to parse, link and validate YANG models. If you want to further process the YANG files you authored with yang-lsp it makes sense to make reuse of the existing functionality. +As yang-lsp contains all the tools to parse, link and validate YANG models. If +you want to further process the YANG files you authored with yang-lsp it makes +sense to make reuse of the existing functionality. -Here is some example code in Xtend for an application that reads in all YANG files from a given directory. The files are parsed into our YANG EMF model, all cross-references are resolved and all files are validated. If there are no errors, the method `generate()` is called for all resources: +Here is some example code in Xtend for an application that reads in all YANG +files from a given directory. The files are parsed into our YANG EMF model, all +cross-references are resolved and all files are validated. If there are no +errors, the method `generate()` is called for all resources: ```xtend package io.typefox.yang.example @@ -66,7 +71,7 @@ class StandaloneExample { } ``` -A number of useful helper methods can be found in the [utils package](https://github.com/TypeFox/yang-lsp/tree/master/yang-lsp/io.typefox.yang/src/main/java/io/typefox/yang/utils) +A number of useful helper methods can be found in the [utils package][1] Here is sample `build.gradle` to build the above class: @@ -98,3 +103,5 @@ dependencies { compile 'com.google.inject:guice:3.0' } ``` + +[1]: https://github.com/TypeFox/yang-lsp/tree/master/yang-lsp/io.typefox.yang/src/main/java/io/typefox/yang/utils diff --git a/docs/Settings.md b/docs/Settings.md index b32d08af..6e7144a2 100644 --- a/docs/Settings.md +++ b/docs/Settings.md @@ -1,17 +1,18 @@ # Settings -The yang-lsp allows users to configure various settings, through settings files. +The yang-lsp allows users to configure various settings, through setting files. The settings file has the name `yang.settings` and can be located - at the root of a project - in the user's directory under `~/.yang/yang.settings`. The file syntax is a [JSON with Comments][1], and its [JSON Schema][2] can be -found [here](../schema/yang-lsp-settings-schema.json). +found [here][3]. ## Disable Code Lens -If you don't want to see the code lenses you can turn it of with the following property: +If you don't want to see the code lenses you can turn it of with the following +property: ```json { @@ -21,7 +22,10 @@ If you don't want to see the code lenses you can turn it of with the following p ## Excluded Paths -Many IDEs and tools copy YANG files into another folder within the same project. As the YANG LSP treats all files within a project the same, this usually infers issues about duplicate elements. To avoid that, you can exclude several directories in the project setting `excludePath`, e.g. +Many IDEs and tools copy YANG files into another folder within the same +project. As the YANG LSP treats all files within a project the same, this +usually informs issues about duplicate elements. To avoid that, you can exclude +several directories in the project setting `excludePath`, e.g. ```json { @@ -29,11 +33,16 @@ Many IDEs and tools copy YANG files into another folder within the same project. } ``` -exludes the default output folder of Maven/Gradle and Eclipse JDT. The path elements are project relative directory names. You can specify multiple elements separated with a colon. The file separator is always `/` independent from the OS. +exludes the default output folder of Maven/Gradle and Eclipse JDT. The path +elements are project relative directory names. You can specify multiple elements +separated with a colon. The file separator is always `/` independent from the +OS. ## YANG Libraries -Often you don't specify a self contained set of YANG models but rely on existing standard libs instead, e.g. from the IETF. Thes don't necessarily reside in your workspace. To specify such libraries, use `yangPath` +Often you don't specify a self contained set of YANG models but rely on existing +standard libs instead, e.g. from the IETF. These don't necessarily reside in +your workspace. To specify such libraries, use `yangPath` ```json { @@ -41,21 +50,36 @@ Often you don't specify a self contained set of YANG models but rely on existing } ``` -You can specify individual files, directories (contents will be added recursively) or ZIP files. The file name format is OS specific, and so is the path separator (`;` on Windows, `:` elsewhere). +If `yangPath` is provided to refer to an SDK location which includes a version +of the project's YANG models that need to be ignored, following approach can be +used. + +```json +{ + "yangPath": "/path/to/sdk/yang/dir", + "yangPathIgnore": "/path/to/sdk/yang/dir/project" +} +``` + +You can specify individual files, directories (contents will be added +recursively) or ZIP files. The file name format is OS specific, and so is the +path separator (`;` on Windows, `:` elsewhere). ## Extensions -The settings is used to register an extension. Please find the details [here](Extensions.md). +The settings is used to register an extension. Please find the details [here][4]. ## Diagnostics -The user can change the severity of diagnostics, by setting the value of a diagnostic preference key to either +The user can change the severity of diagnostics, by setting the value of a +diagnostic preference key to either - `"error"` - `"warning"` - `"ignore"` -The settings contains a `diagnostics` section in which the serverioties for the below diagnostics can be adjusted. +The settings contains a `diagnostics` section in which the serverioties for the +below diagnostics can be adjusted. An example : ```json @@ -66,23 +90,26 @@ An example : } ``` -### Diagnostic Codes +### Diagnostic Issue Codes #### `substatement-cardinality` -Issue code that are entangled with cardinality problems of container statement's sub-statements. +Issue code that are entangled with cardinality problems of container statement's +sub-statements. (default severity: error) #### `unexpected-statement` -Issue code indicating an invalid sub-statement inside its parent statement container. +Issue code indicating an invalid sub-statement inside its parent statement +container. (default severity: error) #### `substatement-ordering` -Issue code for cases when a sub-statement incorrectly precedes another sub-statement. +Issue code for cases when a sub-statement incorrectly precedes another +sub-statement. (default severity: error) @@ -94,7 +121,8 @@ Issue code that is used when a module has anything but {@code '1.1'} version. #### `type-error` -Errors for types. Such as invalid type restriction, range error, fraction-digits issue. +Errors for types. Such as invalid type restriction, range error, fraction-digits +issue. (default severity: error) @@ -110,7 +138,8 @@ A duplicate local name. #### `missing-revision` -Diagnostic that indicates a module is available in multiple revisions when no revision is provided on an import. +Diagnostic that indicates a module is available in multiple revisions when no +revision is provided on an import. (default severity: warning) @@ -140,26 +169,30 @@ Issue code when the revision date does not conform the "YYYY-MM-DD" format. #### `revision-order` -Issue code that applies on a revision if that is not in a reverse chronological order. +Issue code that applies on a revision if that is not in a reverse chronological +order. (default severity: warning) #### `bad-type-name` -Issue code when the name of a type does not conform with the existing constraints. -For instance; the name contains any invalid characters, or equals to any YANG built-in type name. +Issue code when the name of a type does not conform with the existing +constraints. For instance, the name contains any invalid characters, or equals +to any YANG built-in type name. (default severity: error) #### `bad-include-yang-version` -Issue code when there is an inconsistency between a module's version and the version of the included modules. +Issues code when there is an inconsistency between a module's version and the +version of the included modules. (fixed severity: error) #### `bad-import-yang-version` -Issue code when there is an inconsistency between a module's version and the version of the included modules. +Issues code when there is an inconsistency between a module's version and the +version of the included modules. (fixed severity: error) @@ -177,13 +210,15 @@ Issue code indicating that all assigned values in an enumerable must be unique. #### `enumerable-restriction-name` -Issue code indicating that an enumerable introduces a new name that is not declared among the parent restriction. +Issue code indicating that an enumerable introduces a new name that is not +declared among the parent restriction. (default severity: error) #### `enumerable-restriction-value` -Issue code indicating that an enumerable introduces a new value that is not declared among the parent restriction. +Issue code indicating that an enumerable introduces a new value that is not +declared among the parent restriction. (default severity: error) @@ -207,44 +242,51 @@ Controls the indentation string when formatting or serializing yang files. #### `invalid-config` -Issue code when a `config=true` is a child of a `config=false` (see ) +Issue code when a `config=true` is a child of a `config=false` +(see ) (default severity: error) #### `invalid-augmentation` -Issue code when an augmented node declares invalid sub-statements. For instance when an augmented leaf node has leaf nodes. +Issue code when an augmented node declares invalid sub-statements. For instance, +when an augmented leaf node has leaf nodes. (default severity: error) #### `invalid-default` -Issue code for cases when the a choice has default value and the mandatory sub-statement is "true". +Issue code for cases when the a choice has default value and the mandatory +sub-statement is "true". (default severity: error) #### `mandatory-after-default-case` -Issue code when any mandatory nodes are declared after the default case in a "choice". +Issue code when any mandatory nodes are declared after the default case in a +"choice". (default severity: error) #### `invalid-action-ancestor` -Issue code when an action (or notification) has a "list" ancestor node without a "key" statement. -Also applies, when an action (or notification) is declared within another action, rpc or notification. +Issue code when an action (or notification) has a "list" ancestor node without a +"key" statement. Also applies, when an action (or notification) is declared +within another action, rpc or notification. (default severity: error) #### `identity-cycle` -Issue code when an identity references itself, either directly or indirectly through a chain of other identities. +Issue code when an identity references itself, either directly or indirectly +through a chain of other identities. (default severity: error) #### `leaf-key-with-if-feature` -This issue code is used when a leaf node is declared as a list key and have any "if-feature" statements. +This issue code is used when a leaf node is declared as a list key and have any +"if-feature" statements. (default severity: error) @@ -280,3 +322,5 @@ Diagnostic for unresolvable Xpath expressions. [1]: https://code.visualstudio.com/docs/languages/json#_json-with-comments [2]: https://json-schema.org/ +[3]: ../schema/yang-lsp-settings-schema.json +[4]: ./Extensions.md diff --git a/schema/yang-lsp-settings-schema.json b/schema/yang-lsp-settings-schema.json index 45b71fd5..37162380 100644 --- a/schema/yang-lsp-settings-schema.json +++ b/schema/yang-lsp-settings-schema.json @@ -16,11 +16,18 @@ }, "excludePath": { "description": "The path elements are project relative directory names.\nYou can specify multiple elements separated with a colon ':'.\nThe file separator is always '/' independent from the OS", - "type": "string" + "type": "string", + "default": "" }, "yangPath": { "description": "You can specify individual files, directories (contents will be added recursively) or ZIP files.\nThe file name format is OS specific, and so is the path separator (';' on Windows, ':' elsewhere).", - "type": "string" + "type": "string", + "default": "" + }, + "yangPathIgnore": { + "description": "You can specify individual files or directories to be ignored from `yangPath`.\nThe file name format is OS specific, and so is the path separator (';' on Windows, ':' elsewhere).", + "type": "string", + "default": "" }, "extension": { "description": "YANG LSP extension settings", diff --git a/yang-lsp/io.typefox.yang.ide/src/test/resources/RIFT.ware/readme.md b/yang-lsp/io.typefox.yang.ide/src/test/resources/RIFT.ware/readme.md index 32e1a402..ebdffd93 100644 --- a/yang-lsp/io.typefox.yang.ide/src/test/resources/RIFT.ware/readme.md +++ b/yang-lsp/io.typefox.yang.ide/src/test/resources/RIFT.ware/readme.md @@ -1,3 +1,5 @@ -These test files have been copied from +# RIFT.ware -https://github.com/arun11299/RIFT.ware/tree/master/modules/ext/yang/yuma/yuma123-2.2.5/netconf/modules/test/pass \ No newline at end of file +These test files have been copied from [arun11299/RIFT.ware][1] + +[1]: https://github.com/arun11299/RIFT.ware/tree/master/modules/ext/yang/yuma/yuma123-2.2.5/netconf/modules/test/pass diff --git a/yang-lsp/io.typefox.yang/src/main/java/io/typefox/yang/utils/YangPathProvider.xtend b/yang-lsp/io.typefox.yang/src/main/java/io/typefox/yang/utils/YangPathProvider.xtend index bfddb236..4bcdfca8 100644 --- a/yang-lsp/io.typefox.yang/src/main/java/io/typefox/yang/utils/YangPathProvider.xtend +++ b/yang-lsp/io.typefox.yang/src/main/java/io/typefox/yang/utils/YangPathProvider.xtend @@ -21,6 +21,7 @@ import org.eclipse.xtext.util.internal.Log class YangPathProvider { public static val YANG_PATH = new PreferenceKey("yangPath", "") + public static val YANG_PATH_IGNORE = new PreferenceKey("yangPathIgnore", "") @Inject PreferenceValuesProvider preferenceProvider @Inject Provider resourceSetProvider @@ -38,12 +39,20 @@ class YangPathProvider { ] val prefs = preferenceProvider.getPreferenceValues(resource) val yangpath = prefs.getPreference(YANG_PATH) + val yangignorepath = prefs.getPreference(YANG_PATH_IGNORE) + val List yangignoredpaths = newArrayList + if (!yangignorepath.isNullOrEmpty) { + Splitter.on(File.pathSeparator).split(yangpath).forEach [ + val file = new File(it) + yangignoredpaths += file + ] + } val resourceDescriptions = newArrayList if (!yangpath.isNullOrEmpty) { val resourceSet = resourceSetProvider.get(); Splitter.on(File.pathSeparator).split(yangpath).forEach [ val file = new File(it) - file.process(resourceSet) + file.process(resourceSet, yangignoredpaths) ] resourceSet.resources.forEach [ try { @@ -57,15 +66,11 @@ class YangPathProvider { return resourceDescriptions } - private def void process(File file, ResourceSet resourceSet) { + private def void process(File file, ResourceSet resourceSet, List ignoredFiles) { try { - if (!file.canRead) + if (!file.canRead) { return - else if (file.isDirectory) - file.listFiles.forEach[process(resourceSet)] - else if (file.name.endsWith('.yang')) - resourceSet.getResource(URI.createFileURI(file.absolutePath), true) - else if (file.name.endsWith('.zip')) { + } else if (!file.isDirectory && file.name.endsWith('.zip')) { val zipFile = new ZipFile(file) val entries = zipFile.entries val zipFileUri = URI.createFileURI(file.absolutePath).toString @@ -77,9 +82,20 @@ class YangPathProvider { resource.load(zipFile.getInputStream(entry), null) } } + } else { + for (ignoredfile : ignoredFiles) { + if (file.absolutePath == ignoredfile.absolutePath) { + return + } + } + if (file.isDirectory) { + file.listFiles.forEach[process(resourceSet, ignoredFiles)] + } else if (file.name.endsWith('.yang')) { + resourceSet.getResource(URI.createFileURI(file.absolutePath), true) + } } - } catch (Throwable e) { - LOG.error('Error loading yangPath resource ' + URI.toString, e) - } + } catch (Throwable e) { + LOG.error('Error loading yangPath resource ' + URI.toString, e) + } } } diff --git a/yang-lsp/release.md b/yang-lsp/release.md index 61b99d03..f90e5dc6 100644 --- a/yang-lsp/release.md +++ b/yang-lsp/release.md @@ -1,13 +1,25 @@ # Steps to follow - Create local branch e.g. `release-0.5.0` -- Update the version to `version = '0.5.0'` in `yang-lsp/gradle/versions.gradle` and commit +- Update the version to `version = '0.5.0'` in `yang-lsp/gradle/versions.gradle` + and commit - Create a tag named `v0.5.0` and push tags to remote -- Go to [Releases](https://github.com/TypeFox/yang-lsp/releases) GitHub page and initiate a new release by clicking __Draft a new release__ -- Select `v0.5.0` tag from the __Choose a tag__ dropdown, fill out the form and click __Publish release__ -- A [Release](https://github.com/TypeFox/yang-lsp/actions/workflows/release.yml) GH Action will start building and publishing the maven artifacts to the OSS staging repository -- After a successful build copy build artifacts `language-server_0.5.0.zip` and `yang-language-server_diagram-extension_0.5.0.zip` to the release assets. You can edit an existing release by clicking the __Edit__ icon and upload files using drag and drop. -- Go to [OSS Staging Repository](https://oss.sonatype.org/#stagingRepositories) and __Close__ -> __Release__ the staging yang repositories -- Check the released version inside the [maven repo](https://repo1.maven.org/maven2/io/typefox/yang/) +- Go to [Releases](https://github.com/TypeFox/yang-lsp/releases) GitHub page and + initiate a new release by clicking __Draft a new release__ +- Select `v0.5.0` tag from the __Choose a tag__ dropdown, fill out the form and + click __Publish release__ +- A [Release](https://github.com/TypeFox/yang-lsp/actions/workflows/release.yml) + GH Action will start building and publishing the maven artifacts to the OSS + staging repository +- After a successful build copy build artifacts `language-server_0.5.0.zip` and + `yang-language-server_diagram-extension_0.5.0.zip` to the release assets. You + can edit an existing release by clicking the __Edit__ icon and upload files + using drag and drop. +- Go to [OSS Staging Repository](https://oss.sonatype.org/#stagingRepositories) + and __Close__ -> __Release__ the staging yang repositories +- Check the released version inside the [maven repo][1] - Check if dependent projects (yang-vscode) need to be updated -- Switch to master. Change gradle version to next snapshot e.g. 0.5.1-SNAPSHOT and commit. +- Switch to master. Change gradle version to next snapshot e.g. 0.5.1-SNAPSHOT + and commit. + +[1]: https://repo1.maven.org/maven2/io/typefox/yang/