Added ANTLR. Fix Issue #20960 (#21230)

* Added ANTLR. Started work on issue 20960

* Ran generation scripts

* Excluded ANTLR generated files from JavaDoc generation

* Whitespace fix
This commit is contained in:
DavidGrath 2025-05-11 15:31:54 +01:00 committed by GitHub
parent 6344bfa779
commit 2fd1ee66cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 3374 additions and 46 deletions

View File

@ -145,6 +145,43 @@
<artifactId>maven-release-plugin</artifactId> <artifactId>maven-release-plugin</artifactId>
<version>${maven-release-plugin.version}</version> <version>${maven-release-plugin.version}</version>
</plugin> </plugin>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.13.2</version>
<executions>
<execution>
<phase>generate-test-sources</phase>
<goals>
<goal>antlr4</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDirectory>${basedir}/src/test/antlr4</sourceDirectory>
<libDirectory>${basedir}/src/test/antlr4/imports</libDirectory>
<outputDirectory>${project.build.directory}/generated-test-sources/antlr4</outputDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-test-sources/antlr4</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
<profiles> <profiles>
@ -464,6 +501,12 @@
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version> <version>${snakeyaml.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<repositories> <repositories>
<repository> <repository>

View File

@ -202,14 +202,14 @@ import {{packageName}}.infrastructure.ITransformForStorage
{{#-first}} {{#-first}}
// a set of all properties/fields (JSON key names) // a set of all properties/fields (JSON key names)
{{/-first}} {{/-first}}
openapiFields.add("{{baseName}}") openapiFields.add("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{/allVars}} {{/allVars}}
{{#requiredVars}} {{#requiredVars}}
{{#-first}} {{#-first}}
// a set of required properties/fields (JSON key names) // a set of required properties/fields (JSON key names)
{{/-first}} {{/-first}}
openapiRequiredFields.add("{{baseName}}") openapiRequiredFields.add("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{/requiredVars}} {{/requiredVars}}
} }
@ -248,26 +248,26 @@ import {{packageName}}.infrastructure.ITransformForStorage
{{#items.isModel}} {{#items.isModel}}
{{#required}} {{#required}}
// ensure the json data is an array // ensure the json data is an array
if (!jsonObj.get("{{{baseName}}}").isJsonArray) { if (!jsonObj.get("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}").isJsonArray) {
throw IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString())) throw IllegalArgumentException(String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be an array in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString()))
} }
// validate the required field `{{{baseName}}}` (array) // validate the required field `{{{baseName}}}` (array)
for (i in 0 until jsonObj.getAsJsonArray("{{{baseName}}}").size()) { for (i in 0 until jsonObj.getAsJsonArray("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}").size()) {
{{{items.dataType}}}.validateJsonElement(jsonObj.getAsJsonArray("{{{baseName}}}").get(i)) {{{items.dataType}}}.validateJsonElement(jsonObj.getAsJsonArray("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}").get(i))
} }
{{/required}} {{/required}}
{{^required}} {{^required}}
if (jsonObj["{{{baseName}}}"] != null && !jsonObj["{{{baseName}}}"].isJsonNull) { if (jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] != null && !jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonNull) {
if (jsonObj.getAsJsonArray("{{{baseName}}}") != null) { if (jsonObj.getAsJsonArray("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}") != null) {
// ensure the json data is an array // ensure the json data is an array
require(jsonObj["{{{baseName}}}"].isJsonArray) { require(jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonArray) {
String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()) String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be an array in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
} }
// validate the optional field `{{{baseName}}}` (array) // validate the optional field `{{{baseName}}}` (array)
for (i in 0 until jsonObj.getAsJsonArray("{{{baseName}}}").size()) { for (i in 0 until jsonObj.getAsJsonArray("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}").size()) {
{{{items.dataType}}}.validateJsonElement(jsonObj.getAsJsonArray("{{{baseName}}}").get(i)) {{{items.dataType}}}.validateJsonElement(jsonObj.getAsJsonArray("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}").get(i))
} }
} }
} }
@ -276,19 +276,19 @@ import {{packageName}}.infrastructure.ITransformForStorage
{{^items.isModel}} {{^items.isModel}}
{{^required}} {{^required}}
// ensure the optional json data is an array if present // ensure the optional json data is an array if present
if (jsonObj["{{{baseName}}}"] != null && !jsonObj["{{{baseName}}}"].isJsonNull) { if (jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] != null && !jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonNull) {
require(jsonObj["{{{baseName}}}"].isJsonArray()) { require(jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonArray()) {
String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()) String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be an array in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
} }
} }
{{/required}} {{/required}}
{{#required}} {{#required}}
// ensure the required json array is present // ensure the required json array is present
requireNotNull(jsonObj["{{{baseName}}}"]) { requireNotNull(jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"]) {
"Expected the field `{{{baseName}}}` to be an array in the JSON string but got `null`" "Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be an array in the JSON string but got `null`"
} }
require(jsonObj["{{{baseName}}}"].isJsonArray()) { require(jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonArray()) {
String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()) String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be an array in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
} }
{{/required}} {{/required}}
{{/items.isModel}} {{/items.isModel}}
@ -296,42 +296,42 @@ import {{packageName}}.infrastructure.ITransformForStorage
{{^isContainer}} {{^isContainer}}
{{#isString}} {{#isString}}
{{#notRequiredOrIsNullable}} {{#notRequiredOrIsNullable}}
if (jsonObj["{{{baseName}}}"] != null && !jsonObj["{{{baseName}}}"].isJsonNull) { if (jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] != null && !jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonNull) {
require(jsonObj.get("{{{baseName}}}").isJsonPrimitive) { require(jsonObj.get("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}").isJsonPrimitive) {
String.format("Expected the field `{{{baseName}}}` to be a primitive type in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()) String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be a primitive type in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
} }
} }
{{/notRequiredOrIsNullable}} {{/notRequiredOrIsNullable}}
{{^notRequiredOrIsNullable}} {{^notRequiredOrIsNullable}}
require(jsonObj["{{{baseName}}}"].isJsonPrimitive) { require(jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonPrimitive) {
String.format("Expected the field `{{{baseName}}}` to be a primitive type in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()) String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be a primitive type in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
} }
{{/notRequiredOrIsNullable}} {{/notRequiredOrIsNullable}}
{{/isString}} {{/isString}}
{{#isModel}} {{#isModel}}
{{#required}} {{#required}}
// validate the required field `{{{baseName}}}` // validate the required field `{{{baseName}}}`
{{{dataType}}}.validateJsonElement(jsonObj["{{{baseName}}}"]) {{{dataType}}}.validateJsonElement(jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"])
{{/required}} {{/required}}
{{^required}} {{^required}}
// validate the optional field `{{{baseName}}}` // validate the optional field `{{{baseName}}}`
if (jsonObj["{{{baseName}}}"] != null && !jsonObj["{{{baseName}}}"].isJsonNull) { if (jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] != null && !jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonNull) {
{{{dataType}}}.validateJsonElement(jsonObj["{{{baseName}}}"]) {{{dataType}}}.validateJsonElement(jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"])
} }
{{/required}} {{/required}}
{{/isModel}} {{/isModel}}
{{#isEnum}} {{#isEnum}}
{{#required}} {{#required}}
// validate the required field `{{{baseName}}}` // validate the required field `{{{baseName}}}`
require({{{datatypeWithEnum}}}.values().any { it.value == jsonObj["{{{baseName}}}"].asString }) { require({{{datatypeWithEnum}}}.values().any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
String.format("Expected the field `{{{baseName}}}` to be valid `{{{datatypeWithEnum}}}` enum value in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()) String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be valid `{{{datatypeWithEnum}}}` enum value in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
} }
{{/required}} {{/required}}
{{^required}} {{^required}}
// validate the optional field `{{{baseName}}}` // validate the optional field `{{{baseName}}}`
if (jsonObj["{{{baseName}}}"] != null && !jsonObj["{{{baseName}}}"].isJsonNull) { if (jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] != null && !jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonNull) {
require({{{datatypeWithEnum}}}.values().any { it.value == jsonObj["{{{baseName}}}"].asString }) { require({{{datatypeWithEnum}}}.values().any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
String.format("Expected the field `{{{baseName}}}` to be valid `{{{datatypeWithEnum}}}` enum value in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()) String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be valid `{{{datatypeWithEnum}}}` enum value in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
} }
} }
{{/required}} {{/required}}
@ -339,15 +339,15 @@ import {{packageName}}.infrastructure.ITransformForStorage
{{#isEnumRef}} {{#isEnumRef}}
{{#required}} {{#required}}
// validate the required field `{{{baseName}}}` // validate the required field `{{{baseName}}}`
require({{{dataType}}}.values().any { it.value == jsonObj["{{{baseName}}}"].asString }) { require({{{dataType}}}.values().any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
String.format("Expected the field `{{{baseName}}}` to be valid `{{{dataType}}}` enum value in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()) String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be valid `{{{dataType}}}` enum value in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
} }
{{/required}} {{/required}}
{{^required}} {{^required}}
// validate the optional field `{{{baseName}}}` // validate the optional field `{{{baseName}}}`
if (jsonObj["{{{baseName}}}"] != null && !jsonObj["{{{baseName}}}"].isJsonNull) { if (jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] != null && !jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonNull) {
require({{{dataType}}}.values().any { it.value == jsonObj["{{{baseName}}}"].asString }) { require({{{dataType}}}.values().any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
String.format("Expected the field `{{{baseName}}}` to be valid `{{{dataType}}}` enum value in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()) String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be valid `{{{dataType}}}` enum value in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
} }
} }
{{/required}} {{/required}}

View File

@ -2,5 +2,5 @@
/* {{{.}}} */ /* {{{.}}} */
{{/description}} {{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}} {{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{{baseName}}}") @field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}}

View File

@ -2,5 +2,5 @@
/* {{{.}}} */ /* {{{.}}} */
{{/description}} {{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}} {{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{{baseName}}}") @field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}

View File

@ -2,5 +2,5 @@
/* {{{.}}} */ /* {{{.}}} */
{{/description}} {{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}} {{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{{baseName}}}") @field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}}

View File

@ -2,5 +2,5 @@
/* {{{.}}} */ /* {{{.}}} */
{{/description}} {{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}} {{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{{baseName}}}") @field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}

View File

@ -2,5 +2,5 @@
/* {{{.}}} */ /* {{{.}}} */
{{/description}} {{/description}}
@JsonProperty("{{{baseName}}}") @JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{classname}}.{{nameInPascalCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}} {{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{classname}}.{{nameInPascalCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}}

View File

@ -2,5 +2,5 @@
/* {{{.}}} */ /* {{{.}}} */
{{/description}} {{/description}}
@JsonProperty("{{{baseName}}}") @JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{classname}}.{{nameInPascalCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}} {{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{classname}}.{{nameInPascalCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,514 @@
/**
* Kotlin Grammar for ANTLR v4
*
* Based on:
* http://jetbrains.github.io/kotlin-spec/#_grammars_and_parsing
* and
* http://kotlinlang.org/docs/reference/grammar.html
*
* Tested on
* https://github.com/JetBrains/kotlin/tree/master/compiler/testData/psi
*/
// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false
// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine
// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true
lexer grammar KotlinLexer;
import UnicodeClasses;
ShebangLine: '#!' ~[\u000A\u000D]* -> channel(HIDDEN);
DelimitedComment: '/*' ( DelimitedComment | .)*? '*/' -> channel(HIDDEN);
LineComment: '//' ~[\u000A\u000D]* -> channel(HIDDEN);
WS: [\u0020\u0009\u000C] -> skip;
NL: '\u000A' | '\u000D' '\u000A';
//SEPARATORS & OPERATIONS
RESERVED : '...';
DOT : '.';
COMMA : ',';
LPAREN : '(' -> pushMode(Inside);
RPAREN : ')';
LSQUARE : '[' -> pushMode(Inside);
RSQUARE : ']';
LCURL : '{';
RCURL : '}';
MULT : '*';
MOD : '%';
DIV : '/';
ADD : '+';
SUB : '-';
INCR : '++';
DECR : '--';
CONJ : '&&';
DISJ : '||';
EXCL : '!';
COLON : ':';
SEMICOLON : ';';
ASSIGNMENT : '=';
ADD_ASSIGNMENT : '+=';
SUB_ASSIGNMENT : '-=';
MULT_ASSIGNMENT : '*=';
DIV_ASSIGNMENT : '/=';
MOD_ASSIGNMENT : '%=';
ARROW : '->';
DOUBLE_ARROW : '=>';
RANGE : '..';
COLONCOLON : '::';
Q_COLONCOLON : '?::';
DOUBLE_SEMICOLON : ';;';
HASH : '#';
AT : '@';
QUEST : '?';
ELVIS : '?:';
LANGLE : '<';
RANGLE : '>';
LE : '<=';
GE : '>=';
EXCL_EQ : '!=';
EXCL_EQEQ : '!==';
AS_SAFE : 'as?';
EQEQ : '==';
EQEQEQ : '===';
SINGLE_QUOTE : '\'';
//KEYWORDS
RETURN_AT : 'return@' Identifier;
CONTINUE_AT : 'continue@' Identifier;
BREAK_AT : 'break@' Identifier;
FILE : '@file';
PACKAGE : 'package';
IMPORT : 'import';
CLASS : 'class';
INTERFACE : 'interface';
FUN : 'fun';
OBJECT : 'object';
VAL : 'val';
VAR : 'var';
TYPE_ALIAS : 'typealias';
CONSTRUCTOR : 'constructor';
BY : 'by';
COMPANION : 'companion';
INIT : 'init';
THIS : 'this';
SUPER : 'super';
TYPEOF : 'typeof';
WHERE : 'where';
IF : 'if';
ELSE : 'else';
WHEN : 'when';
TRY : 'try';
CATCH : 'catch';
FINALLY : 'finally';
FOR : 'for';
DO : 'do';
WHILE : 'while';
THROW : 'throw';
RETURN : 'return';
CONTINUE : 'continue';
BREAK : 'break';
AS : 'as';
IS : 'is';
IN : 'in';
NOT_IS : '!is' (WS | NL)+;
NOT_IN : '!in' (WS | NL)+;
OUT : 'out';
FIELD : '@field';
PROPERTY : '@property';
GET : '@get';
SET : '@set';
GETTER : 'get';
SETTER : 'set';
RECEIVER : '@receiver';
PARAM : '@param';
SETPARAM : '@setparam';
DELEGATE : '@delegate';
DYNAMIC : 'dynamic';
//MODIFIERS
PUBLIC : 'public';
PRIVATE : 'private';
PROTECTED : 'protected';
INTERNAL : 'internal';
ENUM : 'enum';
SEALED : 'sealed';
ANNOTATION : 'annotation';
DATA : 'data';
INNER : 'inner';
TAILREC : 'tailrec';
OPERATOR : 'operator';
INLINE : 'inline';
INFIX : 'infix';
EXTERNAL : 'external';
SUSPEND : 'suspend';
OVERRIDE : 'override';
ABSTRACT : 'abstract';
FINAL : 'final';
OPEN : 'open';
CONST : 'const';
LATEINIT : 'lateinit';
VARARG : 'vararg';
NOINLINE : 'noinline';
CROSSINLINE : 'crossinline';
REIFIED : 'reified';
//
QUOTE_OPEN : '"' -> pushMode(LineString);
TRIPLE_QUOTE_OPEN : '"""' -> pushMode(MultiLineString);
RealLiteral: FloatLiteral | DoubleLiteral;
FloatLiteral: (DoubleLiteral | IntegerLiteral) [fF];
DoubleLiteral:
((DecDigitNoZero DecDigit* | '0')? '.' | (DecDigitNoZero (DecDigit | '_')* DecDigit)? '.') (
DecDigit+
| DecDigit (DecDigit | '_')+ DecDigit
| DecDigit+ [eE] ('+' | '-')? DecDigit+
| DecDigit+ [eE] ('+' | '-')? DecDigit (DecDigit | '_')+ DecDigit
| DecDigit (DecDigit | '_')+ DecDigit [eE] ('+' | '-')? DecDigit+
| DecDigit (DecDigit | '_')+ DecDigit [eE] ('+' | '-')? DecDigit (DecDigit | '_')+ DecDigit
)
;
LongLiteral: (IntegerLiteral | HexLiteral | BinLiteral) 'L';
IntegerLiteral:
(
'0'
| DecDigitNoZero DecDigit*
| DecDigitNoZero (DecDigit | '_')+ DecDigit
| DecDigitNoZero DecDigit* [eE] ('+' | '-')? DecDigit+
| DecDigitNoZero DecDigit* [eE] ('+' | '-')? DecDigit (DecDigit | '_')+ DecDigit
| DecDigitNoZero (DecDigit | '_')+ DecDigit [eE] ('+' | '-')? DecDigit+
| DecDigitNoZero (DecDigit | '_')+ DecDigit [eE] ('+' | '-')? DecDigit (DecDigit | '_')+ DecDigit
)
;
fragment DecDigit: UNICODE_CLASS_ND;
fragment DecDigitNoZero: UNICODE_CLASS_ND_NoZeros;
fragment UNICODE_CLASS_ND_NoZeros:
'\u0031' ..'\u0039'
| '\u0661' ..'\u0669'
| '\u06f1' ..'\u06f9'
| '\u07c1' ..'\u07c9'
| '\u0967' ..'\u096f'
| '\u09e7' ..'\u09ef'
| '\u0a67' ..'\u0a6f'
| '\u0ae7' ..'\u0aef'
| '\u0b67' ..'\u0b6f'
| '\u0be7' ..'\u0bef'
| '\u0c67' ..'\u0c6f'
| '\u0ce7' ..'\u0cef'
| '\u0d67' ..'\u0d6f'
| '\u0de7' ..'\u0def'
| '\u0e51' ..'\u0e59'
| '\u0ed1' ..'\u0ed9'
| '\u0f21' ..'\u0f29'
| '\u1041' ..'\u1049'
| '\u1091' ..'\u1099'
| '\u17e1' ..'\u17e9'
| '\u1811' ..'\u1819'
| '\u1947' ..'\u194f'
| '\u19d1' ..'\u19d9'
| '\u1a81' ..'\u1a89'
| '\u1a91' ..'\u1a99'
| '\u1b51' ..'\u1b59'
| '\u1bb1' ..'\u1bb9'
| '\u1c41' ..'\u1c49'
| '\u1c51' ..'\u1c59'
| '\ua621' ..'\ua629'
| '\ua8d1' ..'\ua8d9'
| '\ua901' ..'\ua909'
| '\ua9d1' ..'\ua9d9'
| '\ua9f1' ..'\ua9f9'
| '\uaa51' ..'\uaa59'
| '\uabf1' ..'\uabf9'
| '\uff11' ..'\uff19'
;
HexLiteral: '0' [xX] HexDigit (HexDigit | '_')*;
fragment HexDigit: [0-9a-fA-F];
BinLiteral: '0' [bB] BinDigit (BinDigit | '_')*;
fragment BinDigit: [01];
BooleanLiteral: 'true' | 'false';
NullLiteral: 'null';
Identifier: (Letter | '_') (Letter | '_' | DecDigit)* | '`' ~('`')+ '`';
LabelReference: '@' Identifier;
LabelDefinition: Identifier '@';
FieldIdentifier: '$' Identifier;
CharacterLiteral: '\'' (EscapeSeq | .) '\'';
fragment EscapeSeq: UniCharacterLiteral | EscapedIdentifier;
fragment UniCharacterLiteral: '\\' 'u' HexDigit HexDigit HexDigit HexDigit;
fragment EscapedIdentifier: '\\' ('t' | 'b' | 'r' | 'n' | '\'' | '"' | '\\' | '$');
fragment Letter:
UNICODE_CLASS_LL
| UNICODE_CLASS_LM
| UNICODE_CLASS_LO
| UNICODE_CLASS_LT
| UNICODE_CLASS_LU
| UNICODE_CLASS_NL
;
mode Inside;
Inside_RPAREN : ')' -> popMode, type(RPAREN);
Inside_RSQUARE : ']' -> popMode, type(RSQUARE);
Inside_LPAREN : LPAREN -> pushMode(Inside), type(LPAREN);
Inside_LSQUARE : LSQUARE -> pushMode(Inside), type(LSQUARE);
Inside_LCURL : LCURL -> type(LCURL);
Inside_RCURL : RCURL -> type(RCURL);
Inside_DOT : DOT -> type(DOT);
Inside_COMMA : COMMA -> type(COMMA);
Inside_MULT : MULT -> type(MULT);
Inside_MOD : MOD -> type(MOD);
Inside_DIV : DIV -> type(DIV);
Inside_ADD : ADD -> type(ADD);
Inside_SUB : SUB -> type(SUB);
Inside_INCR : INCR -> type(INCR);
Inside_DECR : DECR -> type(DECR);
Inside_CONJ : CONJ -> type(CONJ);
Inside_DISJ : DISJ -> type(DISJ);
Inside_EXCL : EXCL -> type(EXCL);
Inside_COLON : COLON -> type(COLON);
Inside_SEMICOLON : SEMICOLON -> type(SEMICOLON);
Inside_ASSIGNMENT : ASSIGNMENT -> type(ASSIGNMENT);
Inside_ADD_ASSIGNMENT : ADD_ASSIGNMENT -> type(ADD_ASSIGNMENT);
Inside_SUB_ASSIGNMENT : SUB_ASSIGNMENT -> type(SUB_ASSIGNMENT);
Inside_MULT_ASSIGNMENT : MULT_ASSIGNMENT -> type(MULT_ASSIGNMENT);
Inside_DIV_ASSIGNMENT : DIV_ASSIGNMENT -> type(DIV_ASSIGNMENT);
Inside_MOD_ASSIGNMENT : MOD_ASSIGNMENT -> type(MOD_ASSIGNMENT);
Inside_ARROW : ARROW -> type(ARROW);
Inside_DOUBLE_ARROW : DOUBLE_ARROW -> type(DOUBLE_ARROW);
Inside_RANGE : RANGE -> type(RANGE);
Inside_RESERVED : RESERVED -> type(RESERVED);
Inside_COLONCOLON : COLONCOLON -> type(COLONCOLON);
Inside_Q_COLONCOLON : Q_COLONCOLON -> type(Q_COLONCOLON);
Inside_DOUBLE_SEMICOLON : DOUBLE_SEMICOLON -> type(DOUBLE_SEMICOLON);
Inside_HASH : HASH -> type(HASH);
Inside_AT : AT -> type(AT);
Inside_QUEST : QUEST -> type(QUEST);
Inside_ELVIS : ELVIS -> type(ELVIS);
Inside_LANGLE : LANGLE -> type(LANGLE);
Inside_RANGLE : RANGLE -> type(RANGLE);
Inside_LE : LE -> type(LE);
Inside_GE : GE -> type(GE);
Inside_EXCL_EQ : EXCL_EQ -> type(EXCL_EQ);
Inside_EXCL_EQEQ : EXCL_EQEQ -> type(EXCL_EQEQ);
Inside_NOT_IS : NOT_IS -> type(NOT_IS);
Inside_NOT_IN : NOT_IN -> type(NOT_IN);
Inside_AS_SAFE : AS_SAFE -> type(AS_SAFE);
Inside_EQEQ : EQEQ -> type(EQEQ);
Inside_EQEQEQ : EQEQEQ -> type(EQEQEQ);
Inside_SINGLE_QUOTE : SINGLE_QUOTE -> type(SINGLE_QUOTE);
Inside_QUOTE_OPEN : QUOTE_OPEN -> pushMode(LineString), type(QUOTE_OPEN);
Inside_TRIPLE_QUOTE_OPEN:
TRIPLE_QUOTE_OPEN -> pushMode(MultiLineString), type(TRIPLE_QUOTE_OPEN)
;
Inside_VAL : VAL -> type(VAL);
Inside_VAR : VAR -> type(VAR);
Inside_OBJECT : OBJECT -> type(OBJECT);
Inside_SUPER : SUPER -> type(SUPER);
Inside_IN : IN -> type(IN);
Inside_OUT : OUT -> type(OUT);
Inside_FIELD : FIELD -> type(FIELD);
Inside_FILE : FILE -> type(FILE);
Inside_PROPERTY : PROPERTY -> type(PROPERTY);
Inside_GET : GET -> type(GET);
Inside_SET : SET -> type(SET);
Inside_RECEIVER : RECEIVER -> type(RECEIVER);
Inside_PARAM : PARAM -> type(PARAM);
Inside_SETPARAM : SETPARAM -> type(SETPARAM);
Inside_DELEGATE : DELEGATE -> type(DELEGATE);
Inside_THROW : THROW -> type(THROW);
Inside_RETURN : RETURN -> type(RETURN);
Inside_CONTINUE : CONTINUE -> type(CONTINUE);
Inside_BREAK : BREAK -> type(BREAK);
Inside_RETURN_AT : RETURN_AT -> type(RETURN_AT);
Inside_CONTINUE_AT : CONTINUE_AT -> type(CONTINUE_AT);
Inside_BREAK_AT : BREAK_AT -> type(BREAK_AT);
Inside_IF : IF -> type(IF);
Inside_ELSE : ELSE -> type(ELSE);
Inside_WHEN : WHEN -> type(WHEN);
Inside_TRY : TRY -> type(TRY);
Inside_CATCH : CATCH -> type(CATCH);
Inside_FINALLY : FINALLY -> type(FINALLY);
Inside_FOR : FOR -> type(FOR);
Inside_DO : DO -> type(DO);
Inside_WHILE : WHILE -> type(WHILE);
Inside_PUBLIC : PUBLIC -> type(PUBLIC);
Inside_PRIVATE : PRIVATE -> type(PRIVATE);
Inside_PROTECTED : PROTECTED -> type(PROTECTED);
Inside_INTERNAL : INTERNAL -> type(INTERNAL);
Inside_ENUM : ENUM -> type(ENUM);
Inside_SEALED : SEALED -> type(SEALED);
Inside_ANNOTATION : ANNOTATION -> type(ANNOTATION);
Inside_DATA : DATA -> type(DATA);
Inside_INNER : INNER -> type(INNER);
Inside_TAILREC : TAILREC -> type(TAILREC);
Inside_OPERATOR : OPERATOR -> type(OPERATOR);
Inside_INLINE : INLINE -> type(INLINE);
Inside_INFIX : INFIX -> type(INFIX);
Inside_EXTERNAL : EXTERNAL -> type(EXTERNAL);
Inside_SUSPEND : SUSPEND -> type(SUSPEND);
Inside_OVERRIDE : OVERRIDE -> type(OVERRIDE);
Inside_ABSTRACT : ABSTRACT -> type(ABSTRACT);
Inside_FINAL : FINAL -> type(FINAL);
Inside_OPEN : OPEN -> type(OPEN);
Inside_CONST : CONST -> type(CONST);
Inside_LATEINIT : LATEINIT -> type(LATEINIT);
Inside_VARARG : VARARG -> type(VARARG);
Inside_NOINLINE : NOINLINE -> type(NOINLINE);
Inside_CROSSINLINE : CROSSINLINE -> type(CROSSINLINE);
Inside_REIFIED : REIFIED -> type(REIFIED);
Inside_BooleanLiteral : BooleanLiteral -> type(BooleanLiteral);
Inside_IntegerLiteral : IntegerLiteral -> type(IntegerLiteral);
Inside_HexLiteral : HexLiteral -> type(HexLiteral);
Inside_BinLiteral : BinLiteral -> type(BinLiteral);
Inside_CharacterLiteral : CharacterLiteral -> type(CharacterLiteral);
Inside_RealLiteral : RealLiteral -> type(RealLiteral);
Inside_NullLiteral : NullLiteral -> type(NullLiteral);
Inside_LongLiteral: LongLiteral -> type(LongLiteral);
Inside_Identifier : Identifier -> type(Identifier);
Inside_LabelReference : LabelReference -> type(LabelReference);
Inside_LabelDefinition : LabelDefinition -> type(LabelDefinition);
Inside_Comment : (LineComment | DelimitedComment) -> channel(HIDDEN);
Inside_WS : WS -> skip;
Inside_NL : NL -> skip;
mode LineString;
QUOTE_CLOSE: '"' -> popMode;
LineStrRef: FieldIdentifier;
LineStrText: ~('\\' | '"' | '$')+ | '$';
LineStrEscapedChar: '\\' . | UniCharacterLiteral;
LineStrExprStart: '${' -> pushMode(StringExpression);
mode MultiLineString;
TRIPLE_QUOTE_CLOSE: MultiLineStringQuote? '"""' -> popMode;
MultiLineStringQuote: '"'+;
MultiLineStrRef: FieldIdentifier;
MultiLineStrText: ~('\\' | '"' | '$')+ | '$';
MultiLineStrEscapedChar: '\\' .;
MultiLineStrExprStart: '${' -> pushMode(StringExpression);
MultiLineNL: NL -> skip;
mode StringExpression;
StrExpr_RCURL: RCURL -> popMode, type(RCURL);
StrExpr_LPAREN : LPAREN -> pushMode(Inside), type(LPAREN);
StrExpr_LSQUARE : LSQUARE -> pushMode(Inside), type(LSQUARE);
StrExpr_RPAREN : ')' -> type(RPAREN);
StrExpr_RSQUARE : ']' -> type(RSQUARE);
StrExpr_LCURL : LCURL -> pushMode(StringExpression), type(LCURL);
StrExpr_DOT : DOT -> type(DOT);
StrExpr_COMMA : COMMA -> type(COMMA);
StrExpr_MULT : MULT -> type(MULT);
StrExpr_MOD : MOD -> type(MOD);
StrExpr_DIV : DIV -> type(DIV);
StrExpr_ADD : ADD -> type(ADD);
StrExpr_SUB : SUB -> type(SUB);
StrExpr_INCR : INCR -> type(INCR);
StrExpr_DECR : DECR -> type(DECR);
StrExpr_CONJ : CONJ -> type(CONJ);
StrExpr_DISJ : DISJ -> type(DISJ);
StrExpr_EXCL : EXCL -> type(EXCL);
StrExpr_COLON : COLON -> type(COLON);
StrExpr_SEMICOLON : SEMICOLON -> type(SEMICOLON);
StrExpr_ASSIGNMENT : ASSIGNMENT -> type(ASSIGNMENT);
StrExpr_ADD_ASSIGNMENT : ADD_ASSIGNMENT -> type(ADD_ASSIGNMENT);
StrExpr_SUB_ASSIGNMENT : SUB_ASSIGNMENT -> type(SUB_ASSIGNMENT);
StrExpr_MULT_ASSIGNMENT : MULT_ASSIGNMENT -> type(MULT_ASSIGNMENT);
StrExpr_DIV_ASSIGNMENT : DIV_ASSIGNMENT -> type(DIV_ASSIGNMENT);
StrExpr_MOD_ASSIGNMENT : MOD_ASSIGNMENT -> type(MOD_ASSIGNMENT);
StrExpr_ARROW : ARROW -> type(ARROW);
StrExpr_DOUBLE_ARROW : DOUBLE_ARROW -> type(DOUBLE_ARROW);
StrExpr_RANGE : RANGE -> type(RANGE);
StrExpr_COLONCOLON : COLONCOLON -> type(COLONCOLON);
StrExpr_Q_COLONCOLON : Q_COLONCOLON -> type(Q_COLONCOLON);
StrExpr_DOUBLE_SEMICOLON : DOUBLE_SEMICOLON -> type(DOUBLE_SEMICOLON);
StrExpr_HASH : HASH -> type(HASH);
StrExpr_AT : AT -> type(AT);
StrExpr_QUEST : QUEST -> type(QUEST);
StrExpr_ELVIS : ELVIS -> type(ELVIS);
StrExpr_LANGLE : LANGLE -> type(LANGLE);
StrExpr_RANGLE : RANGLE -> type(RANGLE);
StrExpr_LE : LE -> type(LE);
StrExpr_GE : GE -> type(GE);
StrExpr_EXCL_EQ : EXCL_EQ -> type(EXCL_EQ);
StrExpr_EXCL_EQEQ : EXCL_EQEQ -> type(EXCL_EQEQ);
StrExpr_AS : AS -> type(IS);
StrExpr_IS : IS -> type(IN);
StrExpr_IN : IN;
StrExpr_NOT_IS : NOT_IS -> type(NOT_IS);
StrExpr_NOT_IN : NOT_IN -> type(NOT_IN);
StrExpr_AS_SAFE : AS_SAFE -> type(AS_SAFE);
StrExpr_EQEQ : EQEQ -> type(EQEQ);
StrExpr_EQEQEQ : EQEQEQ -> type(EQEQEQ);
StrExpr_SINGLE_QUOTE : SINGLE_QUOTE -> type(SINGLE_QUOTE);
StrExpr_QUOTE_OPEN : QUOTE_OPEN -> pushMode(LineString), type(QUOTE_OPEN);
StrExpr_TRIPLE_QUOTE_OPEN:
TRIPLE_QUOTE_OPEN -> pushMode(MultiLineString), type(TRIPLE_QUOTE_OPEN)
;
StrExpr_BooleanLiteral : BooleanLiteral -> type(BooleanLiteral);
StrExpr_IntegerLiteral : IntegerLiteral -> type(IntegerLiteral);
StrExpr_HexLiteral : HexLiteral -> type(HexLiteral);
StrExpr_BinLiteral : BinLiteral -> type(BinLiteral);
StrExpr_CharacterLiteral : CharacterLiteral -> type(CharacterLiteral);
StrExpr_RealLiteral : RealLiteral -> type(RealLiteral);
StrExpr_NullLiteral : NullLiteral -> type(NullLiteral);
StrExpr_LongLiteral : LongLiteral -> type(LongLiteral);
StrExpr_Identifier : Identifier -> type(Identifier);
StrExpr_LabelReference : LabelReference -> type(LabelReference);
StrExpr_LabelDefinition : LabelDefinition -> type(LabelDefinition);
StrExpr_Comment : (LineComment | DelimitedComment) -> channel(HIDDEN);
StrExpr_WS : WS -> skip;
StrExpr_NL : NL -> skip;

View File

@ -0,0 +1,819 @@
/**
* Kotlin Grammar for ANTLR v4
*
* Based on:
* http://jetbrains.github.io/kotlin-spec/#_grammars_and_parsing
* and
* http://kotlinlang.org/docs/reference/grammar.html
*
* Tested on
* https://github.com/JetBrains/kotlin/tree/master/compiler/testData/psi
*/
// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false
// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging
parser grammar KotlinParser;
options {
tokenVocab = KotlinLexer;
}
kotlinFile
: NL* preamble anysemi* (topLevelObject (anysemi+ topLevelObject?)*)? EOF
;
script
: NL* preamble anysemi* (expression (anysemi+ expression?)*)? EOF
;
preamble
: fileAnnotations? packageHeader importList
;
fileAnnotations
: fileAnnotation+
;
fileAnnotation
: (FILE COLON (LSQUARE unescapedAnnotation+ RSQUARE | unescapedAnnotation) semi?)+
;
packageHeader
: (modifierList? PACKAGE identifier semi?)?
;
importList
: importHeader*
;
importHeader
: IMPORT identifier (DOT MULT | importAlias)? semi?
;
importAlias
: AS simpleIdentifier
;
topLevelObject
: classDeclaration
| objectDeclaration
| functionDeclaration
| propertyDeclaration
| typeAlias
;
classDeclaration
: modifierList? (CLASS | INTERFACE) NL* simpleIdentifier (NL* typeParameters)? (
NL* primaryConstructor
)? (NL* COLON NL* delegationSpecifiers)? (NL* typeConstraints)? (
NL* classBody
| NL* enumClassBody
)?
;
primaryConstructor
: modifierList? (CONSTRUCTOR NL*)? classParameters
;
classParameters
: LPAREN (classParameter (COMMA classParameter)* COMMA?)? RPAREN
;
classParameter
: modifierList? (VAL | VAR)? simpleIdentifier COLON type (ASSIGNMENT expression)?
;
delegationSpecifiers
: annotations* delegationSpecifier (NL* COMMA NL* annotations* delegationSpecifier)*
;
delegationSpecifier
: constructorInvocation
| userType
| explicitDelegation
;
constructorInvocation
: userType callSuffix
;
explicitDelegation
: userType NL* BY NL* expression
;
classBody
: LCURL NL* classMemberDeclaration* NL* RCURL
;
classMemberDeclaration
: (
classDeclaration
| functionDeclaration
| objectDeclaration
| companionObject
| propertyDeclaration
| anonymousInitializer
| secondaryConstructor
| typeAlias
) anysemi+
;
anonymousInitializer
: INIT NL* block
;
secondaryConstructor
: modifierList? CONSTRUCTOR NL* functionValueParameters (
NL* COLON NL* constructorDelegationCall
)? NL* block?
;
constructorDelegationCall
: THIS NL* valueArguments
| SUPER NL* valueArguments
;
enumClassBody
: LCURL NL* enumEntries? (NL* SEMICOLON NL* classMemberDeclaration*)? NL* RCURL
;
enumEntries
: (enumEntry NL*)+ SEMICOLON?
;
enumEntry
: annotations* simpleIdentifier (NL* valueArguments)? (NL* classBody)? (NL* COMMA)?
;
functionDeclaration
: modifierList? FUN (NL* type NL* DOT)? (NL* typeParameters)? (NL* receiverType NL* DOT)? (
NL* identifier
)? NL* functionValueParameters (NL* COLON NL* type)? (NL* typeConstraints)? (NL* functionBody)?
;
functionValueParameters
: LPAREN (functionValueParameter (COMMA functionValueParameter)* COMMA?)? RPAREN
;
functionValueParameter
: modifierList? parameter (ASSIGNMENT expression)?
;
parameter
: simpleIdentifier COLON type
;
receiverType
: typeModifierList? (parenthesizedType | nullableType | typeReference)
;
functionBody
: block
| ASSIGNMENT NL* expression
;
objectDeclaration
: modifierList? OBJECT NL* simpleIdentifier (NL* primaryConstructor)? (
NL* COLON NL* delegationSpecifiers
)? (NL* classBody)?
;
companionObject
: modifierList? COMPANION NL* modifierList? OBJECT (NL* simpleIdentifier)? (
NL* COLON NL* delegationSpecifiers
)? (NL* classBody)?
;
propertyDeclaration
: modifierList? (VAL | VAR) (NL* typeParameters)? (NL* type NL* DOT)? (
NL* (multiVariableDeclaration | variableDeclaration)
) (NL* typeConstraints)? (NL* (BY | ASSIGNMENT) NL* expression)? (
NL* getter (semi setter)?
| NL* setter (semi getter)?
)?
;
multiVariableDeclaration
: LPAREN variableDeclaration (COMMA variableDeclaration)* RPAREN
;
variableDeclaration
: simpleIdentifier (COLON type)?
;
getter
: modifierList? GETTER
| modifierList? GETTER NL* LPAREN RPAREN (NL* COLON NL* type)? NL* (
block
| ASSIGNMENT NL* expression
)
;
setter
: modifierList? SETTER
| modifierList? SETTER NL* LPAREN (annotations | parameterModifier)* (
simpleIdentifier
| parameter
) RPAREN NL* functionBody
;
typeAlias
: modifierList? TYPE_ALIAS NL* simpleIdentifier (NL* typeParameters)? NL* ASSIGNMENT NL* type
;
typeParameters
: LANGLE NL* typeParameter (NL* COMMA NL* typeParameter)* (NL* COMMA)? NL* RANGLE
;
typeParameter
: modifierList? NL* (simpleIdentifier | MULT) (NL* COLON NL* type)?
;
type
: typeModifierList? (functionType | parenthesizedType | nullableType | typeReference)
;
typeModifierList
: (annotations | SUSPEND NL*)+
;
parenthesizedType
: LPAREN type RPAREN
;
nullableType
: (typeReference | parenthesizedType) NL* QUEST+
;
typeReference
: LPAREN typeReference RPAREN
| userType
| DYNAMIC
;
functionType
: (functionTypeReceiver NL* DOT NL*)? functionTypeParameters NL* ARROW (NL* type)
;
functionTypeReceiver
: parenthesizedType
| nullableType
| typeReference
;
userType
: simpleUserType (NL* DOT NL* simpleUserType)*
;
simpleUserType
: simpleIdentifier (NL* typeArguments)?
;
//parameters for functionType
functionTypeParameters
: LPAREN NL* (parameter | type)? (NL* COMMA NL* (parameter | type))* (NL* COMMA)? NL* RPAREN
;
typeConstraints
: WHERE NL* typeConstraint (NL* COMMA NL* typeConstraint)*
;
typeConstraint
: annotations* simpleIdentifier NL* COLON NL* type
;
block
: LCURL statements RCURL
;
statements
: anysemi* (statement (anysemi+ statement?)*)?
;
statement
: declaration
| blockLevelExpression
;
blockLevelExpression
: annotations* NL* expression
;
declaration
: labelDefinition* (classDeclaration | functionDeclaration | propertyDeclaration | typeAlias)
;
expression
: disjunction (assignmentOperator disjunction)*
;
disjunction
: conjunction (NL* DISJ NL* conjunction)*
;
conjunction
: equalityComparison (NL* CONJ NL* equalityComparison)*
;
equalityComparison
: comparison (equalityOperation NL* comparison)*
;
comparison
: namedInfix (comparisonOperator NL* namedInfix)?
;
namedInfix
: elvisExpression ((inOperator NL* elvisExpression)+ | (isOperator NL* type))?
;
elvisExpression
: infixFunctionCall (NL* ELVIS NL* infixFunctionCall)*
;
infixFunctionCall
: rangeExpression (simpleIdentifier NL* rangeExpression)*
;
rangeExpression
: additiveExpression (RANGE NL* additiveExpression)*
;
additiveExpression
: multiplicativeExpression (additiveOperator NL* multiplicativeExpression)*
;
multiplicativeExpression
: typeRHS (multiplicativeOperation NL* typeRHS)*
;
typeRHS
: prefixUnaryExpression (NL* typeOperation prefixUnaryExpression)*
;
prefixUnaryExpression
: prefixUnaryOperation* postfixUnaryExpression
;
postfixUnaryExpression
: (atomicExpression | callableReference) postfixUnaryOperation*
;
atomicExpression
: parenthesizedExpression
| literalConstant
| functionLiteral
| thisExpression // THIS labelReference?
| superExpression // SUPER (LANGLE type RANGLE)? labelReference?
| conditionalExpression // ifExpression, whenExpression
| tryExpression
| objectLiteral
| jumpExpression
| loopExpression
| collectionLiteral
| simpleIdentifier
| VAL identifier
;
parenthesizedExpression
: LPAREN expression RPAREN
;
callSuffix
: typeArguments valueArguments? annotatedLambda*
| valueArguments annotatedLambda*
| annotatedLambda+
;
annotatedLambda
: unescapedAnnotation* LabelDefinition? NL* functionLiteral
;
arrayAccess
: LSQUARE (expression (COMMA expression)*)? RSQUARE
;
valueArguments
: LPAREN (valueArgument (COMMA valueArgument)* (NL* COMMA)?)? RPAREN
;
typeArguments
: LANGLE NL* typeProjection (NL* COMMA typeProjection)* (NL* COMMA)? NL* RANGLE QUEST?
;
typeProjection
: typeProjectionModifierList? type
| MULT
;
typeProjectionModifierList
: varianceAnnotation+
;
valueArgument
: (simpleIdentifier NL* ASSIGNMENT NL*)? MULT? NL* expression
;
literalConstant
: BooleanLiteral
| IntegerLiteral
| stringLiteral
| HexLiteral
| BinLiteral
| CharacterLiteral
| RealLiteral
| NullLiteral
| LongLiteral
;
stringLiteral
: lineStringLiteral
| multiLineStringLiteral
;
lineStringLiteral
: QUOTE_OPEN (lineStringContent | lineStringExpression)* QUOTE_CLOSE
;
multiLineStringLiteral
: TRIPLE_QUOTE_OPEN (
multiLineStringContent
| multiLineStringExpression
| lineStringLiteral
| MultiLineStringQuote
)* TRIPLE_QUOTE_CLOSE
;
lineStringContent
: LineStrText
| LineStrEscapedChar
| LineStrRef
;
lineStringExpression
: LineStrExprStart expression RCURL
;
multiLineStringContent
: MultiLineStrText
| MultiLineStrEscapedChar
| MultiLineStrRef
;
multiLineStringExpression
: MultiLineStrExprStart expression RCURL
;
functionLiteral
: annotations* (
LCURL NL* statements NL* RCURL
| LCURL NL* lambdaParameters NL* ARROW NL* statements NL* RCURL
)
;
lambdaParameters
: lambdaParameter? (NL* COMMA NL* lambdaParameter)*
;
lambdaParameter
: variableDeclaration
| multiVariableDeclaration (NL* COLON NL* type)?
;
// https://kotlinlang.org/docs/reference/grammar.html#objectLiteral
objectLiteral
: OBJECT (NL* COLON NL* delegationSpecifiers)? NL* classBody?
;
collectionLiteral
: LSQUARE expression? (COMMA expression)* RSQUARE
;
thisExpression
: THIS LabelReference?
;
superExpression
: SUPER (LANGLE NL* type NL* RANGLE)? LabelReference?
;
conditionalExpression
: ifExpression
| whenExpression
;
ifExpression
: IF NL* LPAREN expression RPAREN NL* controlStructureBody? SEMICOLON? (
NL* ELSE NL* controlStructureBody?
)?
;
controlStructureBody
: block
| expression
;
whenExpression
: WHEN NL* (LPAREN expression RPAREN)? NL* LCURL NL* (whenEntry NL*)* NL* RCURL
;
whenEntry
: whenCondition (NL* COMMA NL* whenCondition)* NL* ARROW NL* controlStructureBody semi?
| ELSE NL* ARROW NL* controlStructureBody
;
whenCondition
: expression
| rangeTest
| typeTest
;
rangeTest
: inOperator NL* expression
;
typeTest
: isOperator NL* type
;
tryExpression
: TRY NL* block (NL* catchBlock)* (NL* finallyBlock)?
;
catchBlock
: CATCH NL* LPAREN annotations* simpleIdentifier COLON userType RPAREN NL* block
;
finallyBlock
: FINALLY NL* block
;
loopExpression
: forExpression
| whileExpression
| doWhileExpression
;
forExpression
: FOR NL* LPAREN annotations* (variableDeclaration | multiVariableDeclaration) IN expression RPAREN NL* controlStructureBody?
;
whileExpression
: WHILE NL* LPAREN expression RPAREN NL* controlStructureBody?
;
doWhileExpression
: DO NL* controlStructureBody? NL* WHILE NL* LPAREN expression RPAREN
;
jumpExpression
: THROW NL* expression
| (RETURN | RETURN_AT) expression?
| CONTINUE
| CONTINUE_AT
| BREAK
| BREAK_AT
;
callableReference
: (userType (QUEST NL*)*)? NL* (COLONCOLON | Q_COLONCOLON) NL* (identifier | CLASS)
| THIS NL* COLONCOLON NL* CLASS
;
assignmentOperator
: ASSIGNMENT
| ADD_ASSIGNMENT
| SUB_ASSIGNMENT
| MULT_ASSIGNMENT
| DIV_ASSIGNMENT
| MOD_ASSIGNMENT
;
equalityOperation
: EXCL_EQ
| EXCL_EQEQ
| EQEQ
| EQEQEQ
;
comparisonOperator
: LANGLE
| RANGLE
| LE
| GE
;
inOperator
: IN
| NOT_IN
;
isOperator
: IS
| NOT_IS
;
additiveOperator
: ADD
| SUB
;
multiplicativeOperation
: MULT
| DIV
| MOD
;
typeOperation
: AS
| AS_SAFE
| COLON
;
prefixUnaryOperation
: INCR
| DECR
| ADD
| SUB
| EXCL
| annotations
| labelDefinition
;
postfixUnaryOperation
: INCR
| DECR
| EXCL EXCL
| callSuffix
| arrayAccess
| NL* memberAccessOperator postfixUnaryExpression
;
memberAccessOperator
: DOT
| QUEST DOT
;
modifierList
: (annotations | modifier)+
;
modifier
: (
classModifier
| memberModifier
| visibilityModifier
| varianceAnnotation
| functionModifier
| propertyModifier
| inheritanceModifier
| parameterModifier
| typeParameterModifier
) NL*
;
classModifier
: ENUM
| SEALED
| ANNOTATION
| DATA
| INNER
;
memberModifier
: OVERRIDE
| LATEINIT
;
visibilityModifier
: PUBLIC
| PRIVATE
| INTERNAL
| PROTECTED
;
varianceAnnotation
: IN
| OUT
;
functionModifier
: TAILREC
| OPERATOR
| INFIX
| INLINE
| EXTERNAL
| SUSPEND
;
propertyModifier
: CONST
;
inheritanceModifier
: ABSTRACT
| FINAL
| OPEN
;
parameterModifier
: VARARG
| NOINLINE
| CROSSINLINE
;
typeParameterModifier
: REIFIED
;
labelDefinition
: LabelDefinition NL*
;
annotations
: (annotation | annotationList) NL*
;
annotation
: annotationUseSiteTarget NL* COLON NL* unescapedAnnotation
| LabelReference (NL* DOT NL* simpleIdentifier)* (NL* typeArguments)? (NL* valueArguments)?
;
annotationList
: annotationUseSiteTarget COLON LSQUARE unescapedAnnotation+ RSQUARE
| AT LSQUARE unescapedAnnotation+ RSQUARE
;
annotationUseSiteTarget
: FIELD
| FILE
| PROPERTY
| GET
| SET
| RECEIVER
| PARAM
| SETPARAM
| DELEGATE
;
unescapedAnnotation
: identifier typeArguments? valueArguments?
;
identifier
: simpleIdentifier (NL* DOT simpleIdentifier)*
;
simpleIdentifier
: Identifier
//soft keywords:
| ABSTRACT
| ANNOTATION
| BY
| CATCH
| COMPANION
| CONSTRUCTOR
| CROSSINLINE
| DATA
| DYNAMIC
| ENUM
| EXTERNAL
| FINAL
| FINALLY
| GETTER
| IMPORT
| INFIX
| INIT
| INLINE
| INNER
| INTERNAL
| LATEINIT
| NOINLINE
| OPEN
| OPERATOR
| OUT
| OVERRIDE
| PRIVATE
| PROTECTED
| PUBLIC
| REIFIED
| SEALED
| TAILREC
| SETTER
| VARARG
| WHERE
//strong keywords
| CONST
| SUSPEND
;
semi
: NL+
| NL* SEMICOLON NL*
;
anysemi
: NL
| SEMICOLON
;

View File

@ -19,9 +19,17 @@ package org.openapitools.codegen.kotlin;
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.*; import io.swagger.v3.oas.models.media.*;
import lombok.Getter;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.openapitools.codegen.*; import org.openapitools.codegen.*;
import org.openapitools.codegen.antlr4.KotlinLexer;
import org.openapitools.codegen.antlr4.KotlinParser;
import org.openapitools.codegen.antlr4.KotlinParserBaseListener;
import org.openapitools.codegen.config.CodegenConfigurator; import org.openapitools.codegen.config.CodegenConfigurator;
import org.openapitools.codegen.languages.KotlinClientCodegen; import org.openapitools.codegen.languages.KotlinClientCodegen;
import org.openapitools.codegen.languages.KotlinServerCodegen;
import org.openapitools.codegen.testutils.ConfigAssert; import org.openapitools.codegen.testutils.ConfigAssert;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
@ -30,11 +38,16 @@ import org.testng.annotations.Test;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.openapitools.codegen.CodegenConstants.*;
import static org.openapitools.codegen.languages.KotlinServerCodegen.Constants.INTERFACE_ONLY;
import static org.openapitools.codegen.languages.KotlinServerCodegen.Constants.RETURN_RESPONSE;
@SuppressWarnings("static-method") @SuppressWarnings("static-method")
public class KotlinClientCodegenModelTest { public class KotlinClientCodegenModelTest {
@ -481,6 +494,45 @@ public class KotlinClientCodegenModelTest {
"val adapterkotlin.String", "val adapterjava.math.BigDecimal"); "val adapterkotlin.String", "val adapterjava.math.BigDecimal");
} }
@Test(description = "Issue #20960")
private void givenSchemaObjectPropertyNameContainsDollarSignWhenGenerateThenDollarSignIsProperlyEscapedInAnnotation() throws Exception {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
KotlinClientCodegen codegen = new KotlinClientCodegen();
codegen.setOutputDir(output.getAbsolutePath());
Map<String, Object> properties = new HashMap<>();
// properties.put(CodegenConstants.LIBRARY, ClientLibrary.JVM_KTOR);
properties.put(CodegenConstants.ENUM_PROPERTY_NAMING, CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.UPPERCASE.toString());
properties.put(SERIALIZATION_LIBRARY, KotlinClientCodegen.SERIALIZATION_LIBRARY_TYPE.gson.toString());
properties.put(KotlinClientCodegen.GENERATE_ONEOF_ANYOF_WRAPPERS, true);
properties.put(API_PACKAGE, "com.toasttab.service.scim.api");
properties.put(MODEL_PACKAGE, "com.toasttab.service.scim.models");
properties.put(PACKAGE_NAME, "com.toasttab.service.scim");
codegen.additionalProperties().putAll(properties);
new DefaultGenerator().opts(new ClientOptInput()
.openAPI(TestUtils.parseSpec("src/test/resources/3_1/issue_20960.yaml"))
.config(codegen))
.generate();
String outputPath = output.getAbsolutePath() + "/src/main/kotlin/com/toasttab/service/scim";
Path baseGroupModel = Paths.get(outputPath + "/models/BaseGroupMembersInner.kt");
String baseGroupModelContent = Files.readString(baseGroupModel);
KotlinLexer kotlinLexer = new KotlinLexer(CharStreams.fromString(baseGroupModelContent));
KotlinTestUtils.SyntaxErrorListener syntaxErrorListener = new KotlinTestUtils.SyntaxErrorListener();
kotlinLexer.addErrorListener(syntaxErrorListener);
CommonTokenStream commonTokenStream = new CommonTokenStream(kotlinLexer);
KotlinParser kotlinParser = new KotlinParser(commonTokenStream);
kotlinParser.addErrorListener(syntaxErrorListener);
ParseTree parseTree = kotlinParser.kotlinFile();
ParseTreeWalker parseTreeWalker = new ParseTreeWalker();
KotlinTestUtils.CustomKotlinParseListener customKotlinParseListener = new KotlinTestUtils.CustomKotlinParseListener();
parseTreeWalker.walk(customKotlinParseListener, parseTree);
Assert.assertEquals(syntaxErrorListener.getSyntaxErrorCount(), 0);
Assert.assertEquals(customKotlinParseListener.getStringReferenceCount(), 0);
}
private static class ModelNameTest { private static class ModelNameTest {
private final String expectedName; private final String expectedName;
private final String expectedClassName; private final String expectedClassName;

View File

@ -1,10 +1,21 @@
package org.openapitools.codegen.kotlin; package org.openapitools.codegen.kotlin;
import lombok.Getter;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.checkerframework.checker.units.qual.C;
import org.openapitools.codegen.ClientOptInput; import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.DefaultGenerator; import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.TestUtils; import org.openapitools.codegen.TestUtils;
import org.openapitools.codegen.antlr4.KotlinLexer;
import org.openapitools.codegen.antlr4.KotlinParser;
import org.openapitools.codegen.antlr4.KotlinParserBaseListener;
import org.openapitools.codegen.languages.KotlinServerCodegen; import org.openapitools.codegen.languages.KotlinServerCodegen;
import org.openapitools.codegen.languages.KotlinSpringServerCodegen; import org.openapitools.codegen.languages.KotlinSpringServerCodegen;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.File; import java.io.File;
@ -12,13 +23,14 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import static org.openapitools.codegen.CodegenConstants.LIBRARY; import static org.openapitools.codegen.CodegenConstants.*;
import static org.openapitools.codegen.TestUtils.assertFileContains; import static org.openapitools.codegen.TestUtils.assertFileContains;
import static org.openapitools.codegen.TestUtils.assertFileNotContains; import static org.openapitools.codegen.TestUtils.assertFileNotContains;
import static org.openapitools.codegen.languages.AbstractKotlinCodegen.USE_JAKARTA_EE; import static org.openapitools.codegen.languages.AbstractKotlinCodegen.USE_JAKARTA_EE;
import static org.openapitools.codegen.languages.KotlinServerCodegen.Constants.INTERFACE_ONLY; import static org.openapitools.codegen.languages.KotlinServerCodegen.Constants.*;
import static org.openapitools.codegen.languages.KotlinServerCodegen.Constants.JAXRS_SPEC;
import static org.openapitools.codegen.languages.features.BeanValidationFeatures.USE_BEANVALIDATION; import static org.openapitools.codegen.languages.features.BeanValidationFeatures.USE_BEANVALIDATION;
public class KotlinServerCodegenTest { public class KotlinServerCodegenTest {
@ -252,4 +264,51 @@ public class KotlinServerCodegenTest {
"@get:Size(max=50)" "@get:Size(max=50)"
); );
} }
@DataProvider(name = "dollarEscapeTest")
private Object[][] createData() {
return new Object[][]{
new Object[]{JAXRS_SPEC},
new Object[]{JAVALIN5},
new Object[]{JAVALIN6},
};
}
@Test(description = "Issue #20960", dataProvider = "dollarEscapeTest")
public void givenSchemaObjectPropertyNameContainsDollarSignWhenGenerateThenDollarSignIsProperlyEscapedInAnnotation(String library) throws Exception {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
KotlinServerCodegen codegen = new KotlinServerCodegen();
codegen.setOutputDir(output.getAbsolutePath());
Map<String, Object> properties = new HashMap<>();
properties.put(CodegenConstants.LIBRARY, library);
properties.put(CodegenConstants.ENUM_PROPERTY_NAMING, CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.UPPERCASE.toString());
properties.put(INTERFACE_ONLY, true);
properties.put(RETURN_RESPONSE, true);
properties.put(API_PACKAGE, "com.toasttab.service.scim.api");
properties.put(MODEL_PACKAGE, "com.toasttab.service.scim.models");
properties.put(PACKAGE_NAME, "com.toasttab.service.scim");
codegen.additionalProperties().putAll(properties);
new DefaultGenerator().opts(new ClientOptInput()
.openAPI(TestUtils.parseSpec("src/test/resources/3_1/issue_20960.yaml"))
.config(codegen))
.generate();
String outputPath = output.getAbsolutePath() + "/src/main/kotlin/com/toasttab/service/scim";
Path baseGroupModel = Paths.get(outputPath + "/models/BaseGroupMembersInner.kt");
String baseGroupModelContent = Files.readString(baseGroupModel);
KotlinLexer kotlinLexer = new KotlinLexer(CharStreams.fromString(baseGroupModelContent));
KotlinTestUtils.SyntaxErrorListener syntaxErrorListener = new KotlinTestUtils.SyntaxErrorListener();
kotlinLexer.addErrorListener(syntaxErrorListener);
CommonTokenStream commonTokenStream = new CommonTokenStream(kotlinLexer);
KotlinParser kotlinParser = new KotlinParser(commonTokenStream);
kotlinParser.addErrorListener(syntaxErrorListener);
ParseTree parseTree = kotlinParser.kotlinFile();
ParseTreeWalker parseTreeWalker = new ParseTreeWalker();
KotlinTestUtils.CustomKotlinParseListener customKotlinParseListener = new KotlinTestUtils.CustomKotlinParseListener();
parseTreeWalker.walk(customKotlinParseListener, parseTree);
Assert.assertTrue(syntaxErrorListener.getSyntaxErrorCount() == 0);
Assert.assertTrue(customKotlinParseListener.getStringReferenceCount() == 0);
}
} }

View File

@ -1,6 +1,10 @@
package org.openapitools.codegen.kotlin; package org.openapitools.codegen.kotlin;
import kotlin.script.experimental.jvm.util.KotlinJars; import kotlin.script.experimental.jvm.util.KotlinJars;
import lombok.Getter;
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
import org.jetbrains.kotlin.cli.common.config.ContentRootsKt; import org.jetbrains.kotlin.cli.common.config.ContentRootsKt;
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer; import org.jetbrains.kotlin.cli.common.messages.MessageRenderer;
@ -15,6 +19,8 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys;
import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.config.JVMConfigurationKeys; import org.jetbrains.kotlin.config.JVMConfigurationKeys;
import org.jetbrains.kotlin.config.JvmTarget; import org.jetbrains.kotlin.config.JvmTarget;
import org.openapitools.codegen.antlr4.KotlinParser;
import org.openapitools.codegen.antlr4.KotlinParserBaseListener;
import java.io.*; import java.io.*;
import java.net.MalformedURLException; import java.net.MalformedURLException;
@ -96,4 +102,33 @@ public class KotlinTestUtils {
return isDisposed; return isDisposed;
} }
} }
public static class CustomKotlinParseListener extends KotlinParserBaseListener {
@Getter
private int stringReferenceCount = 0;
@Override
public void exitLineStringContent(KotlinParser.LineStringContentContext ctx) {
if(ctx.LineStrRef() != null) {
stringReferenceCount++;
}
}
@Override
public void exitMultiLineStringContent(KotlinParser.MultiLineStringContentContext ctx) {
if(ctx.MultiLineStrRef() != null) {
stringReferenceCount++;
}
}
}
public static class SyntaxErrorListener extends BaseErrorListener {
@Getter
private int syntaxErrorCount = 0;
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
syntaxErrorCount++;
}
}
} }

View File

@ -0,0 +1,147 @@
# Slightly modified from the original
openapi: 3.1.0
info:
version: 5.0.5
title: Internal Users SCIM
description: ...
tags:
- name: Groups
description: ...
paths:
/v3/internal/scim/Groups/{id}:
get:
summary: 'Get group by id'
description: ...
externalDocs:
url: 'https://datatracker.ietf.org/doc/html/rfc7644#section-3.2'
description: 'RFC 7644, Section 3.2'
operationId: getGroup
tags:
- Groups
parameters:
- $ref: '#/components/parameters/GroupIdInPath'
responses:
'200':
description: Successful response
content:
application/scim+json:
schema:
$ref: '#/components/schemas/Group'
application/json:
schema:
$ref: '#/components/schemas/Group'
components:
parameters:
GroupIdInPath:
name: id
in: path
description: |
The unique identifier of a group
required: true
schema:
type: string
format: uuid
schemas:
Meta:
type: object
description: ...
externalDocs:
url: 'https://datatracker.ietf.org/doc/html/rfc7643#section-3.1'
description: 'RFC 7643, Section 3.1'
properties:
resourceType:
type: string
description: ...
examples:
- 'ResourceType'
created:
type: string
format: date-time
description: ...
examples:
- '2024-07-21T17:32:28Z'
lastModified:
type: string
format: date-time
description: ...
location:
type: string
description: ...
version:
type: string
description: ...
BaseGroup:
type: object
description: ...
externalDocs:
url: 'https://datatracker.ietf.org/doc/html/rfc7643#section-4'
description: 'RFC 7643, Section 4'
required:
- members
properties:
members:
type: array
description: ...
items:
type: object
required:
- value
- $refRequired
properties:
value:
type: string
format: uuid
description: ...
$ref:
type:
- "string"
- "null"
description: ...
$refRequired:
type:
- "string"
- "null"
description: ...
$refOneOf:
type: object
oneOf: [
{
"type": integer
},
{
"type": "boolean"
}
]
default: [ ] # default is for `PUT` request
Group:
type: object
description: ...
externalDocs:
url: 'https://datatracker.ietf.org/doc/html/rfc7643#section-4'
description: 'RFC 7643, Section 4'
required:
- schemas
- id
- displayName
- members
allOf:
- type: object
properties:
schemas:
type: array
description: ...
items:
type: string
id:
type: string
format: uuid
readOnly: true
description: ...
displayName:
type: string
readOnly: true
description: ...
- $ref: '#/components/schemas/BaseGroup'

View File

@ -269,6 +269,7 @@
<maxmemory>1g</maxmemory> <maxmemory>1g</maxmemory>
<failOnWarnings>false</failOnWarnings> <failOnWarnings>false</failOnWarnings>
<doclint>none</doclint> <doclint>none</doclint>
<excludePackageNames>org.openapitools.codegen.antlr4</excludePackageNames>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>