Skip to content

Commit 1a4cfda

Browse files
committed
more enhancements
- implement `escapeUnsafeCharacters` for Julia code gen - not escaping `baseName` for `CodegenParameter` and `CodegenProperty` anymore, they interfere with other ops - added a mustache lambda `escapeDollar` and used that instead
1 parent bfc1033 commit 1a4cfda

File tree

6 files changed

+94
-36
lines changed

6 files changed

+94
-36
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJuliaCodegen.java

+10-9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import org.slf4j.LoggerFactory;
2121

2222
import com.google.common.base.CaseFormat;
23+
import com.google.common.collect.ImmutableMap;
24+
import com.samskivert.mustache.Mustache.Lambda;
25+
import org.openapitools.codegen.templating.mustache.EscapeChar;
2326

2427
public abstract class AbstractJuliaCodegen extends DefaultCodegen {
2528
protected final Logger LOGGER = LoggerFactory.getLogger(AbstractJuliaCodegen.class);
@@ -336,7 +339,7 @@ public String toDefaultValue(Schema schema) {
336339

337340
@Override
338341
public String escapeUnsafeCharacters(String input) {
339-
return input;
342+
return input.replace("#=", "#_=").replace("=#", "=_#");
340343
}
341344

342345
/**
@@ -348,12 +351,6 @@ public String escapeQuotationMark(String input) {
348351
return input.replace("\"", "\\\"");
349352
}
350353

351-
protected String escapeBaseName(String name) {
352-
// replace all $ not prefixed with \ with a \
353-
name = name.replaceAll("(?<!\\\\)\\$", "\\\\\\$");
354-
return name;
355-
}
356-
357354
protected String escapeRegex(String pattern) {
358355
pattern = pattern.replaceAll("\\\\\\\\", "\\\\");
359356
pattern = pattern.replaceAll("^/", "");
@@ -371,7 +368,6 @@ protected String escapeRegex(String pattern) {
371368
@Override
372369
public CodegenParameter fromParameter(Parameter param, Set<String> imports) {
373370
CodegenParameter parameter = super.fromParameter(param, imports);
374-
parameter.baseName = escapeBaseName(parameter.baseName);
375371
if (parameter.pattern != null) {
376372
parameter.pattern = escapeRegex(parameter.pattern);
377373
}
@@ -395,7 +391,6 @@ public CodegenParameter fromParameter(Parameter param, Set<String> imports) {
395391
@Override
396392
public CodegenProperty fromProperty(String name, Schema schema, boolean required) {
397393
CodegenProperty property = super.fromProperty(name, schema, required);
398-
property.baseName = escapeBaseName(property.baseName);
399394
// if the name needs any escaping, we set it to var"name"
400395
if (needsVarEscape(property.name)) {
401396
property.name = "var\"" + property.name + "\"";
@@ -465,4 +460,10 @@ public CodegenOperation fromOperation(String path,
465460

466461
return op;
467462
}
463+
464+
@Override
465+
protected ImmutableMap.Builder<String, Lambda> addMustacheLambdas() {
466+
return super.addMustacheLambdas()
467+
.put("escapeDollar", new EscapeChar("(?<!\\\\)\\$", "\\\\\\$"));
468+
}
468469
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
3+
* Copyright 2018 SmartBear Software
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.openapitools.codegen.templating.mustache;
19+
20+
import com.samskivert.mustache.Mustache;
21+
import com.samskivert.mustache.Template;
22+
23+
import java.io.IOException;
24+
import java.io.Writer;
25+
26+
/**
27+
* Escapes the desired character if not escaped already, e.g. $ => \$.
28+
*
29+
* Register:
30+
* <pre>
31+
* additionalProperties.put("escapeDollar", new EscapeChar("(?<!\\\\)\\$", "\\\\\\$"));
32+
* </pre>
33+
*
34+
* Use:
35+
* <pre>
36+
* {{#lambda.escapeDollar}}{{name}}{{/lambda.escapeDollar}}
37+
* </pre>
38+
*/
39+
public class EscapeChar implements Mustache.Lambda {
40+
private String matchPattern;
41+
private String replacement;
42+
43+
/**
44+
* Constructs a new instance of {@link EscapeChar}, with the desired character to escape
45+
*/
46+
public EscapeChar(String matchPattern, String replacement) {
47+
this.matchPattern = matchPattern;
48+
this.replacement = replacement;
49+
}
50+
51+
@Override
52+
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
53+
String text = fragment.execute();
54+
text = text.replaceAll(matchPattern, replacement);
55+
writer.write(text);
56+
}
57+
}

modules/openapi-generator/src/main/resources/julia-client/api.mustache

+5-5
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,20 @@ function _oacinternal_{{operationId}}(_api::{{classname}}{{#allParams}}{{#requir
4848
{{/allParams}}
4949
_ctx = OpenAPI.Clients.Ctx(_api.client, "{{httpMethod}}", _returntypes_{{operationId}}, "{{path}}", [{{#authMethods}}"{{name}}", {{/authMethods}}]{{#bodyParam}}, {{paramName}}{{/bodyParam}})
5050
{{#pathParams}}
51-
OpenAPI.Clients.set_param(_ctx.path, "{{baseName}}", {{paramName}}{{#isListContainer}}; collection_format="{{collectionFormat}}"{{/isListContainer}}) # type {{dataType}}
51+
OpenAPI.Clients.set_param(_ctx.path, "{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", {{paramName}}{{#isListContainer}}; collection_format="{{collectionFormat}}"{{/isListContainer}}) # type {{dataType}}
5252
{{/pathParams}}
5353
{{#queryParams}}
54-
OpenAPI.Clients.set_param(_ctx.query, "{{baseName}}", {{paramName}}{{#isListContainer}}; collection_format="{{collectionFormat}}"{{/isListContainer}}) # type {{dataType}}
54+
OpenAPI.Clients.set_param(_ctx.query, "{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", {{paramName}}{{#isListContainer}}; collection_format="{{collectionFormat}}"{{/isListContainer}}) # type {{dataType}}
5555
{{/queryParams}}
5656
{{#headerParams}}
57-
OpenAPI.Clients.set_param(_ctx.header, "{{baseName}}", {{paramName}}{{#isListContainer}}; collection_format="{{collectionFormat}}"{{/isListContainer}}) # type {{dataType}}
57+
OpenAPI.Clients.set_param(_ctx.header, "{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", {{paramName}}{{#isListContainer}}; collection_format="{{collectionFormat}}"{{/isListContainer}}) # type {{dataType}}
5858
{{/headerParams}}
5959
{{#formParams}}
6060
{{^isFile}}
61-
OpenAPI.Clients.set_param(_ctx.form, "{{baseName}}", {{paramName}}{{#isListContainer}}; collection_format="{{collectionFormat}}"{{/isListContainer}}) # type {{dataType}}
61+
OpenAPI.Clients.set_param(_ctx.form, "{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", {{paramName}}{{#isListContainer}}; collection_format="{{collectionFormat}}"{{/isListContainer}}) # type {{dataType}}
6262
{{/isFile}}
6363
{{#isFile}}
64-
OpenAPI.Clients.set_param(_ctx.file, "{{baseName}}", {{paramName}}) # type {{dataType}}
64+
OpenAPI.Clients.set_param(_ctx.file, "{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", {{paramName}}) # type {{dataType}}
6565
{{/isFile}}
6666
{{/formParams}}
6767
OpenAPI.Clients.set_header_accept(_ctx, [{{#produces}}"{{{mediaType}}}", {{/produces}}])

modules/openapi-generator/src/main/resources/julia-client/partial_model_single.mustache

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ Base.@kwdef mutable struct {{classname}} <: OpenAPI.APIModel
1818

1919
function {{classname}}({{#allVars}}{{{name}}}, {{/allVars}})
2020
{{#allVars}}
21-
OpenAPI.validate_property({{classname}}, Symbol("{{baseName}}"), {{{name}}})
21+
OpenAPI.validate_property({{classname}}, Symbol("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"), {{{name}}})
2222
{{/allVars}}
2323
return new({{#allVars}}{{{name}}}, {{/allVars}})
2424
end
2525
end # type {{classname}}
2626

27-
const _property_types_{{classname}} = Dict{Symbol,String}({{#allVars}}Symbol("{{baseName}}")=>"{{datatype}}", {{/allVars}})
27+
const _property_types_{{classname}} = Dict{Symbol,String}({{#allVars}}Symbol("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")=>"{{datatype}}", {{/allVars}})
2828
OpenAPI.property_type(::Type{ {{classname}} }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_{{classname}}[name]))}
2929

3030
function check_required(o::{{classname}})
@@ -39,18 +39,18 @@ end
3939
function OpenAPI.validate_property(::Type{ {{classname}} }, name::Symbol, val)
4040
{{#allVars}}
4141
{{#isEnum}}
42-
if name === Symbol("{{baseName}}")
42+
if name === Symbol("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
4343
OpenAPI.validate_param(name, "{{classname}}", :enum, val, [{{#_enum}}"{{.}}"{{^-last}}, {{/-last}}{{/_enum}}])
4444
end
4545
{{/isEnum}}
4646
{{^isEnum}}
4747
{{#format}}
48-
if name === Symbol("{{baseName}}")
48+
if name === Symbol("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
4949
OpenAPI.validate_param(name, "{{classname}}", :format, val, "{{format}}")
5050
end
5151
{{/format}}
5252
{{#hasValidation}}
53-
if name === Symbol("{{baseName}}")
53+
if name === Symbol("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
5454
{{#maxLength}}
5555
OpenAPI.validate_param(name, "{{classname}}", :maxLength, val, {{maxLength}})
5656
{{/maxLength}}

modules/openapi-generator/src/main/resources/julia-server/api.mustache

+12-12
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ function {{operationId}}_read(handler)
66
function {{operationId}}_read_handler(req::HTTP.Request)
77
openapi_params = Dict{String,Any}(){{#hasPathParams}}
88
path_params = HTTP.getparams(req){{#pathParams}}
9-
openapi_params["{{baseName}}"] = OpenAPI.Servers.to_param({{dataType}}, path_params, "{{baseName}}", {{#required}}required=true, {{/required}}{{#isListContainer}}collection_format="{{collectionFormat}}", {{/isListContainer}}){{/pathParams}}{{/hasPathParams}}{{#hasQueryParams}}
9+
openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] = OpenAPI.Servers.to_param({{dataType}}, path_params, "{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", {{#required}}required=true, {{/required}}{{#isListContainer}}collection_format="{{collectionFormat}}", {{/isListContainer}}){{/pathParams}}{{/hasPathParams}}{{#hasQueryParams}}
1010
query_params = HTTP.queryparams(URIs.URI(req.target)){{#queryParams}}
11-
openapi_params["{{baseName}}"] = OpenAPI.Servers.to_param({{dataType}}, query_params, "{{baseName}}", {{#required}}required=true, {{/required}}{{#isListContainer}}collection_format="{{collectionFormat}}", {{/isListContainer}}){{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}}
11+
openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] = OpenAPI.Servers.to_param({{dataType}}, query_params, "{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", {{#required}}required=true, {{/required}}{{#isListContainer}}collection_format="{{collectionFormat}}", {{/isListContainer}}){{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}}
1212
headers = Dict{String,String}(HTTP.headers(req)){{#headerParams}}
13-
openapi_params["{{baseName}}"] = OpenAPI.Servers.to_param({{dataType}}, headers, "{{baseName}}", {{#required}}required=true, {{/required}}{{#isListContainer}}collection_format="{{collectionFormat}}", {{/isListContainer}}){{/headerParams}}{{/hasHeaderParams}}{{#hasBodyParam}}{{#bodyParams}}
14-
openapi_params["{{baseName}}"] = OpenAPI.Servers.to_param_type({{dataType}}, String(req.body)){{/bodyParams}}{{/hasBodyParam}}{{#hasFormParams}}
13+
openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] = OpenAPI.Servers.to_param({{dataType}}, headers, "{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", {{#required}}required=true, {{/required}}{{#isListContainer}}collection_format="{{collectionFormat}}", {{/isListContainer}}){{/headerParams}}{{/hasHeaderParams}}{{#hasBodyParam}}{{#bodyParams}}
14+
openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] = OpenAPI.Servers.to_param_type({{dataType}}, String(req.body)){{/bodyParams}}{{/hasBodyParam}}{{#hasFormParams}}
1515
form_data = HTTP.parse_multipart_form(req){{#formParams}}
16-
openapi_params["{{baseName}}"] = OpenAPI.Servers.to_param({{dataType}}, form_data, "{{baseName}}"; multipart=true, isfile={{#isFile}}true{{/isFile}}{{^isFile}}false{{/isFile}}, {{#required}}required=true, {{/required}}{{#isListContainer}}collection_format="{{collectionFormat}}", {{/isListContainer}}){{/formParams}}{{/hasFormParams}}
16+
openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] = OpenAPI.Servers.to_param({{dataType}}, form_data, "{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"; multipart=true, isfile={{#isFile}}true{{/isFile}}{{^isFile}}false{{/isFile}}, {{#required}}required=true, {{/required}}{{#isListContainer}}collection_format="{{collectionFormat}}", {{/isListContainer}}){{/formParams}}{{/hasFormParams}}
1717
req.context[:openapi_params] = openapi_params
1818

1919
return handler(req)
@@ -25,22 +25,22 @@ function {{operationId}}_validate(handler)
2525
openapi_params = req.context[:openapi_params]
2626
{{#allParams}}{{#hasValidation}}
2727
{{#maxLength}}
28-
OpenAPI.validate_param("{{baseName}}", "{{operationId}}", :maxLength, openapi_params["{{baseName}}"], {{maxLength}})
28+
OpenAPI.validate_param("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", "{{operationId}}", :maxLength, openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"], {{maxLength}})
2929
{{/maxLength}}
3030
{{#minLength}}
31-
OpenAPI.validate_param("{{baseName}}", "{{operationId}}", :minLength, openapi_params["{{baseName}}"], {{minLength}})
31+
OpenAPI.validate_param("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", "{{operationId}}", :minLength, openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"], {{minLength}})
3232
{{/minLength}}
3333
{{#maximum}}
34-
OpenAPI.validate_param("{{baseName}}", "{{operationId}}", :maximum, openapi_params["{{baseName}}"], {{maximum}}, {{#exclusiveMaximum}}true{{/exclusiveMaximum}}{{^exclusiveMaximum}}false{{/exclusiveMaximum}})
34+
OpenAPI.validate_param("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", "{{operationId}}", :maximum, openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"], {{maximum}}, {{#exclusiveMaximum}}true{{/exclusiveMaximum}}{{^exclusiveMaximum}}false{{/exclusiveMaximum}})
3535
{{/maximum}}
3636
{{#minimum}}
37-
OpenAPI.validate_param("{{baseName}}", "{{operationId}}", :minimum, openapi_params["{{baseName}}"], {{minimum}}, {{#exclusiveMinimum}}true{{/exclusiveMinimum}}{{^exclusiveMinimum}}false{{/exclusiveMinimum}})
37+
OpenAPI.validate_param("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", "{{operationId}}", :minimum, openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"], {{minimum}}, {{#exclusiveMinimum}}true{{/exclusiveMinimum}}{{^exclusiveMinimum}}false{{/exclusiveMinimum}})
3838
{{/minimum}}
3939
{{#maxItems}}
40-
OpenAPI.validate_param("{{baseName}}", "{{operationId}}", :maxItems, openapi_params["{{baseName}}"], {{maxItems}})
40+
OpenAPI.validate_param("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", "{{operationId}}", :maxItems, openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"], {{maxItems}})
4141
{{/maxItems}}
4242
{{#minItems}}
43-
OpenAPI.validate_param("{{baseName}}", "{{operationId}}", :minItems, openapi_params["{{baseName}}"], {{minItems}})
43+
OpenAPI.validate_param("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", "{{operationId}}", :minItems, openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"], {{minItems}})
4444
{{/minItems}}
4545
{{/hasValidation}}{{/allParams}}
4646
return handler(req)
@@ -50,7 +50,7 @@ end
5050
function {{operationId}}_invoke(impl; post_invoke=nothing)
5151
function {{operationId}}_invoke_handler(req::HTTP.Request)
5252
openapi_params = req.context[:openapi_params]
53-
ret = impl.{{operationId}}(req::HTTP.Request{{#allParams}}{{#required}}, openapi_params["{{baseName}}"]{{/required}}{{/allParams}};{{#allParams}}{{^required}} {{paramName}}=get(openapi_params, "{{baseName}}", nothing),{{/required}}{{/allParams}})
53+
ret = impl.{{operationId}}(req::HTTP.Request{{#allParams}}{{#required}}, openapi_params["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"]{{/required}}{{/allParams}};{{#allParams}}{{^required}} {{paramName}}=get(openapi_params, "{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}", nothing),{{/required}}{{/allParams}})
5454
resp = OpenAPI.Servers.server_response(ret)
5555
return (post_invoke === nothing) ? resp : post_invoke(req, resp)
5656
end

modules/openapi-generator/src/main/resources/julia-server/partial_model_single.mustache

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ Base.@kwdef mutable struct {{classname}} <: OpenAPI.APIModel
1818

1919
function {{classname}}({{#allVars}}{{{name}}}, {{/allVars}})
2020
{{#allVars}}
21-
OpenAPI.validate_property({{classname}}, Symbol("{{baseName}}"), {{{name}}})
21+
OpenAPI.validate_property({{classname}}, Symbol("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"), {{{name}}})
2222
{{/allVars}}
2323
return new({{#allVars}}{{{name}}}, {{/allVars}})
2424
end
2525
end # type {{classname}}
2626

27-
const _property_types_{{classname}} = Dict{Symbol,String}({{#allVars}}Symbol("{{baseName}}")=>"{{datatype}}", {{/allVars}})
27+
const _property_types_{{classname}} = Dict{Symbol,String}({{#allVars}}Symbol("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")=>"{{datatype}}", {{/allVars}})
2828
OpenAPI.property_type(::Type{ {{classname}} }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_{{classname}}[name]))}
2929

3030
function check_required(o::{{classname}})
@@ -39,18 +39,18 @@ end
3939
function OpenAPI.validate_property(::Type{ {{classname}} }, name::Symbol, val)
4040
{{#allVars}}
4141
{{#isEnum}}
42-
if name === Symbol("{{baseName}}")
42+
if name === Symbol("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
4343
OpenAPI.validate_param(name, "{{classname}}", :enum, val, [{{#allowableValues}}{{#values}}"{{{this}}}"{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}])
4444
end
4545
{{/isEnum}}
4646
{{^isEnum}}
4747
{{#format}}
48-
if name === Symbol("{{baseName}}")
48+
if name === Symbol("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
4949
OpenAPI.validate_param(name, "{{classname}}", :format, val, "{{format}}")
5050
end
5151
{{/format}}
5252
{{#hasValidation}}
53-
if name === Symbol("{{baseName}}")
53+
if name === Symbol("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
5454
{{#maxLength}}
5555
OpenAPI.validate_param(name, "{{classname}}", :maxLength, val, {{maxLength}})
5656
{{/maxLength}}

0 commit comments

Comments
 (0)