forked from loafle/openapi-generator-original
fix: wrong typespec generation for all-of with single ref (#21139)
This commit is contained in:
parent
d02c0f493e
commit
0462bed734
@ -45,19 +45,18 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
||||
## LANGUAGE PRIMITIVES
|
||||
|
||||
<ul class="column-ul">
|
||||
<li>AnyType</li>
|
||||
<li>Atom</li>
|
||||
<li>Boolean</li>
|
||||
<li>Decimal</li>
|
||||
<li>Float</li>
|
||||
<li>Integer</li>
|
||||
<li>List</li>
|
||||
<li>Map</li>
|
||||
<li>PID</li>
|
||||
<li>String</li>
|
||||
<li>Tuple</li>
|
||||
<li>Date.t</li>
|
||||
<li>DateTime.t</li>
|
||||
<li>String.t</li>
|
||||
<li>any()</li>
|
||||
<li>binary()</li>
|
||||
<li>boolean()</li>
|
||||
<li>float()</li>
|
||||
<li>integer()</li>
|
||||
<li>list()</li>
|
||||
<li>map()</li>
|
||||
<li>nil</li>
|
||||
<li>number()</li>
|
||||
</ul>
|
||||
|
||||
## RESERVED WORDS
|
||||
|
@ -180,44 +180,55 @@ public class ElixirClientCodegen extends DefaultCodegen {
|
||||
*/
|
||||
languageSpecificPrimitives = new HashSet<>(
|
||||
Arrays.asList(
|
||||
"Integer",
|
||||
"Float",
|
||||
"Decimal",
|
||||
"Boolean",
|
||||
"String",
|
||||
"List",
|
||||
"Atom",
|
||||
"Map",
|
||||
"AnyType",
|
||||
"Tuple",
|
||||
"PID",
|
||||
// This is a workaround, since the DefaultCodeGen uses our elixir TypeSpec
|
||||
// datetype to evaluate the primitive
|
||||
"integer()",
|
||||
"float()",
|
||||
"number()",
|
||||
"boolean()",
|
||||
"String.t",
|
||||
"Date.t",
|
||||
"DateTime.t",
|
||||
"binary()",
|
||||
"list()",
|
||||
"map()",
|
||||
"any()"));
|
||||
"any()",
|
||||
"nil"));
|
||||
|
||||
// ref:
|
||||
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
|
||||
typeMapping = new HashMap<>();
|
||||
typeMapping.put("integer", "Integer");
|
||||
typeMapping.put("long", "Integer");
|
||||
typeMapping.put("number", "Float");
|
||||
typeMapping.put("float", "Float");
|
||||
typeMapping.put("double", "Float");
|
||||
typeMapping.put("string", "String");
|
||||
typeMapping.put("byte", "Integer");
|
||||
typeMapping.put("boolean", "Boolean");
|
||||
typeMapping.put("Date", "Date");
|
||||
typeMapping.put("DateTime", "DateTime");
|
||||
typeMapping.put("file", "String");
|
||||
typeMapping.put("map", "Map");
|
||||
typeMapping.put("array", "List");
|
||||
typeMapping.put("list", "List");
|
||||
typeMapping.put("object", "Map");
|
||||
typeMapping.put("binary", "String");
|
||||
typeMapping.put("ByteArray", "String");
|
||||
typeMapping.put("UUID", "String");
|
||||
typeMapping.put("URI", "String");
|
||||
// primitive types
|
||||
typeMapping.put("string", "String.t");
|
||||
typeMapping.put("number", "number()");
|
||||
typeMapping.put("integer", "integer()");
|
||||
typeMapping.put("boolean", "boolean()");
|
||||
typeMapping.put("array", "list()");
|
||||
typeMapping.put("object", "map()");
|
||||
typeMapping.put("map", "map()");
|
||||
typeMapping.put("null", "nil");
|
||||
// string formats
|
||||
typeMapping.put("byte", "String.t");
|
||||
typeMapping.put("binary", "binary()");
|
||||
typeMapping.put("password", "String.t");
|
||||
typeMapping.put("uuid", "String.t");
|
||||
typeMapping.put("email", "String.t");
|
||||
typeMapping.put("uri", "String.t");
|
||||
typeMapping.put("file", "String.t");
|
||||
// integer formats
|
||||
typeMapping.put("int32", "integer()");
|
||||
typeMapping.put("int64", "integer()");
|
||||
typeMapping.put("long", "integer()");
|
||||
// float formats
|
||||
typeMapping.put("float", "float()");
|
||||
typeMapping.put("double", "float()");
|
||||
typeMapping.put("decimal", "float()");
|
||||
// date-time formats
|
||||
typeMapping.put("date", "Date.t");
|
||||
typeMapping.put("date-time", "DateTime.t");
|
||||
// other
|
||||
typeMapping.put("ByteArray", "binary()");
|
||||
typeMapping.put("DateTime", "DateTime.t");
|
||||
typeMapping.put("UUID", "String.t");
|
||||
|
||||
|
||||
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE,
|
||||
"The main namespace to use for all classes. e.g. Yay.Pets"));
|
||||
@ -570,49 +581,19 @@ public class ElixirClientCodegen extends DefaultCodegen {
|
||||
*/
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
if (ModelUtils.isAnyType(p)) {
|
||||
return "any()";
|
||||
} else if(ModelUtils.isFreeFormObject(p, null)) {
|
||||
return "%{optional(String.t) => any()}";
|
||||
} else if (ModelUtils.isArraySchema(p)) {
|
||||
if (ModelUtils.isArraySchema(p)) {
|
||||
Schema inner = ModelUtils.getSchemaItems(p);
|
||||
return "[" + getTypeDeclaration(inner) + "]";
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
Schema inner = ModelUtils.getAdditionalProperties(p);
|
||||
return "%{optional(String.t) => " + getTypeDeclaration(inner) + "}";
|
||||
} else if (ModelUtils.isPasswordSchema(p)) {
|
||||
return "String.t";
|
||||
} else if (ModelUtils.isEmailSchema(p)) {
|
||||
return "String.t";
|
||||
} else if (ModelUtils.isByteArraySchema(p)) {
|
||||
return "binary()";
|
||||
} else if (ModelUtils.isUUIDSchema(p)) {
|
||||
return "String.t";
|
||||
} else if (ModelUtils.isDateSchema(p)) {
|
||||
return "Date.t";
|
||||
} else if (ModelUtils.isDateTimeSchema(p)) {
|
||||
return "DateTime.t";
|
||||
} else if (ModelUtils.isObjectSchema(p)) {
|
||||
return "map()";
|
||||
} else if (ModelUtils.isIntegerSchema(p)) {
|
||||
return "integer()";
|
||||
} else if (ModelUtils.isNumberSchema(p)) {
|
||||
return "float()";
|
||||
} else if (ModelUtils.isBinarySchema(p) || ModelUtils.isFileSchema(p)) {
|
||||
return "String.t";
|
||||
} else if (ModelUtils.isBooleanSchema(p)) {
|
||||
return "boolean()";
|
||||
} else if (!StringUtils.isEmpty(p.get$ref())) {
|
||||
switch (super.getTypeDeclaration(p)) {
|
||||
case "String":
|
||||
return "String.t";
|
||||
default:
|
||||
return this.moduleName + ".Model." + super.getTypeDeclaration(p) + ".t";
|
||||
String refType = super.getTypeDeclaration(p);
|
||||
if (languageSpecificPrimitives.contains(refType)) {
|
||||
return refType;
|
||||
} else {
|
||||
return this.moduleName + ".Model." + refType + ".t";
|
||||
}
|
||||
} else if (ModelUtils.isFileSchema(p)) {
|
||||
return "String.t";
|
||||
} else if (ModelUtils.isStringSchema(p)) {
|
||||
return "String.t";
|
||||
} else if (p.getType() == null) {
|
||||
return "any()";
|
||||
}
|
||||
@ -630,14 +611,11 @@ public class ElixirClientCodegen extends DefaultCodegen {
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type))
|
||||
return toModelName(type);
|
||||
} else
|
||||
type = openAPIType;
|
||||
return toModelName(type);
|
||||
return typeMapping.get(openAPIType);
|
||||
} else {
|
||||
return toModelName(openAPIType);
|
||||
}
|
||||
}
|
||||
|
||||
class ExtendedCodegenResponse extends CodegenResponse {
|
||||
@ -784,24 +762,6 @@ public class ElixirClientCodegen extends DefaultCodegen {
|
||||
this.operationIdCamelCase = o.operationIdCamelCase;
|
||||
}
|
||||
|
||||
private void translateBaseType(StringBuilder returnEntry, String baseType) {
|
||||
switch (baseType) {
|
||||
case "AnyType":
|
||||
returnEntry.append("any()");
|
||||
break;
|
||||
case "Boolean":
|
||||
returnEntry.append("boolean()");
|
||||
break;
|
||||
case "Float":
|
||||
returnEntry.append("float()");
|
||||
break;
|
||||
default:
|
||||
returnEntry.append(baseType);
|
||||
returnEntry.append(".t");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public String typespec() {
|
||||
StringBuilder sb = new StringBuilder("@spec ");
|
||||
sb.append(underscore(operationId));
|
||||
@ -819,16 +779,10 @@ public class ElixirClientCodegen extends DefaultCodegen {
|
||||
for (CodegenResponse response : this.responses) {
|
||||
ExtendedCodegenResponse exResponse = (ExtendedCodegenResponse) response;
|
||||
StringBuilder returnEntry = new StringBuilder();
|
||||
if (exResponse.baseType == null) {
|
||||
returnEntry.append("nil");
|
||||
} else if (exResponse.containerType == null) { // not container (array, map, set)
|
||||
returnEntry.append(normalizeTypeName(exResponse.dataType, exResponse.primitiveType));
|
||||
if (exResponse.schema != null) {
|
||||
returnEntry.append(getTypeDeclaration((Schema) exResponse.schema));
|
||||
} else {
|
||||
if (exResponse.containerType.equals("array") || exResponse.containerType.equals("set")) {
|
||||
returnEntry.append(exResponse.dataType);
|
||||
} else if (exResponse.containerType.equals("map")) {
|
||||
returnEntry.append("map()");
|
||||
}
|
||||
returnEntry.append(normalizeTypeName(exResponse.dataType, exResponse.primitiveType));
|
||||
}
|
||||
uniqueResponseTypes.add(returnEntry.toString());
|
||||
}
|
||||
@ -845,14 +799,11 @@ public class ElixirClientCodegen extends DefaultCodegen {
|
||||
if (baseType == null) {
|
||||
return "nil";
|
||||
}
|
||||
if (isPrimitive || "String.t".equals(baseType)) {
|
||||
if (isPrimitive || languageSpecificPrimitives.contains(baseType)) {
|
||||
return baseType;
|
||||
}
|
||||
if (!baseType.startsWith(moduleName + ".Model.")) {
|
||||
baseType = moduleName + ".Model." + baseType;
|
||||
}
|
||||
if (!baseType.endsWith(".t")) {
|
||||
baseType += ".t";
|
||||
baseType = moduleName + ".Model." + baseType + ".t";
|
||||
}
|
||||
return baseType;
|
||||
}
|
||||
|
@ -1337,6 +1337,29 @@ paths:
|
||||
responses:
|
||||
200:
|
||||
description: The instance started successfully
|
||||
/fake/all-of-with-local-single-ref:
|
||||
get:
|
||||
tags:
|
||||
- fake
|
||||
responses:
|
||||
200:
|
||||
description: Successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/Foo"
|
||||
/fake/all-of-with-remote-single-ref:
|
||||
get:
|
||||
tags:
|
||||
- fake
|
||||
responses:
|
||||
200:
|
||||
description: Successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AllOfWithSingleRef"
|
||||
servers:
|
||||
- url: "http://{server}.swagger.io:{port}/v2"
|
||||
description: petstore server
|
||||
|
@ -9,6 +9,60 @@ defmodule OpenapiPetstore.Api.Fake do
|
||||
alias OpenapiPetstore.Connection
|
||||
import OpenapiPetstore.RequestBuilder
|
||||
|
||||
@doc """
|
||||
|
||||
### Parameters
|
||||
|
||||
- `connection` (OpenapiPetstore.Connection): Connection to server
|
||||
- `opts` (keyword): Optional parameters
|
||||
|
||||
### Returns
|
||||
|
||||
- `{:ok, OpenapiPetstore.Model.Foo.t}` on success
|
||||
- `{:error, Tesla.Env.t}` on failure
|
||||
"""
|
||||
@spec fake_all_of_with_local_single_ref_get(Tesla.Env.client, keyword()) :: {:ok, any()} | {:error, Tesla.Env.t}
|
||||
def fake_all_of_with_local_single_ref_get(connection, _opts \\ []) do
|
||||
request =
|
||||
%{}
|
||||
|> method(:get)
|
||||
|> url("/fake/all-of-with-local-single-ref")
|
||||
|> Enum.into([])
|
||||
|
||||
connection
|
||||
|> Connection.request(request)
|
||||
|> evaluate_response([
|
||||
{200, OpenapiPetstore.Model.Foo}
|
||||
])
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
||||
### Parameters
|
||||
|
||||
- `connection` (OpenapiPetstore.Connection): Connection to server
|
||||
- `opts` (keyword): Optional parameters
|
||||
|
||||
### Returns
|
||||
|
||||
- `{:ok, OpenapiPetstore.Model.AllOfWithSingleRef.t}` on success
|
||||
- `{:error, Tesla.Env.t}` on failure
|
||||
"""
|
||||
@spec fake_all_of_with_remote_single_ref_get(Tesla.Env.client, keyword()) :: {:ok, OpenapiPetstore.Model.AllOfWithSingleRef.t} | {:error, Tesla.Env.t}
|
||||
def fake_all_of_with_remote_single_ref_get(connection, _opts \\ []) do
|
||||
request =
|
||||
%{}
|
||||
|> method(:get)
|
||||
|> url("/fake/all-of-with-remote-single-ref")
|
||||
|> Enum.into([])
|
||||
|
||||
connection
|
||||
|> Connection.request(request)
|
||||
|> evaluate_response([
|
||||
{200, OpenapiPetstore.Model.AllOfWithSingleRef}
|
||||
])
|
||||
end
|
||||
|
||||
@doc """
|
||||
for Java apache and Java native, test toUrlQueryString for maps with BegDecimal keys
|
||||
|
||||
@ -180,14 +234,14 @@ defmodule OpenapiPetstore.Api.Fake do
|
||||
|
||||
- `connection` (OpenapiPetstore.Connection): Connection to server
|
||||
- `opts` (keyword): Optional parameters
|
||||
- `:body` (float()): Input number as post body
|
||||
- `:body` (number()): Input number as post body
|
||||
|
||||
### Returns
|
||||
|
||||
- `{:ok, float()}` on success
|
||||
- `{:ok, number()}` on success
|
||||
- `{:error, Tesla.Env.t}` on failure
|
||||
"""
|
||||
@spec fake_outer_number_serialize(Tesla.Env.client, keyword()) :: {:ok, float()} | {:error, Tesla.Env.t}
|
||||
@spec fake_outer_number_serialize(Tesla.Env.client, keyword()) :: {:ok, number()} | {:error, Tesla.Env.t}
|
||||
def fake_outer_number_serialize(connection, opts \\ []) do
|
||||
optional_params = %{
|
||||
:body => :body
|
||||
@ -464,7 +518,7 @@ defmodule OpenapiPetstore.Api.Fake do
|
||||
### Parameters
|
||||
|
||||
- `connection` (OpenapiPetstore.Connection): Connection to server
|
||||
- `number` (float()): None
|
||||
- `number` (number()): None
|
||||
- `double` (float()): None
|
||||
- `pattern_without_delimiter` (String.t): None
|
||||
- `byte` (binary()): None
|
||||
@ -485,7 +539,7 @@ defmodule OpenapiPetstore.Api.Fake do
|
||||
- `{:ok, nil}` on success
|
||||
- `{:error, Tesla.Env.t}` on failure
|
||||
"""
|
||||
@spec test_endpoint_parameters(Tesla.Env.client, float(), float(), String.t, binary(), keyword()) :: {:ok, nil} | {:error, Tesla.Env.t}
|
||||
@spec test_endpoint_parameters(Tesla.Env.client, number(), float(), String.t, binary(), keyword()) :: {:ok, nil} | {:error, Tesla.Env.t}
|
||||
def test_endpoint_parameters(connection, number, double, pattern_without_delimiter, byte, opts \\ []) do
|
||||
optional_params = %{
|
||||
:integer => :form,
|
||||
@ -623,7 +677,7 @@ defmodule OpenapiPetstore.Api.Fake do
|
||||
### Parameters
|
||||
|
||||
- `connection` (OpenapiPetstore.Connection): Connection to server
|
||||
- `body` (%{optional(String.t) => any()}): request body
|
||||
- `body` (map()): request body
|
||||
- `opts` (keyword): Optional parameters
|
||||
|
||||
### Returns
|
||||
|
@ -54,7 +54,7 @@ defmodule OpenapiPetstore.Api.Store do
|
||||
- `{:ok, %{}}` on success
|
||||
- `{:error, Tesla.Env.t}` on failure
|
||||
"""
|
||||
@spec get_inventory(Tesla.Env.client, keyword()) :: {:ok, map()} | {:error, Tesla.Env.t}
|
||||
@spec get_inventory(Tesla.Env.client, keyword()) :: {:ok, %{optional(String.t) => integer()}} | {:error, Tesla.Env.t}
|
||||
def get_inventory(connection, _opts \\ []) do
|
||||
request =
|
||||
%{}
|
||||
|
@ -12,7 +12,7 @@ defmodule OpenapiPetstore.Model.ArrayOfArrayOfNumberOnly do
|
||||
]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
:ArrayArrayNumber => [[float()]] | nil
|
||||
:ArrayArrayNumber => [[number()]] | nil
|
||||
}
|
||||
|
||||
def decode(value) do
|
||||
|
@ -12,7 +12,7 @@ defmodule OpenapiPetstore.Model.ArrayOfNumberOnly do
|
||||
]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
:ArrayNumber => [float()] | nil
|
||||
:ArrayNumber => [number()] | nil
|
||||
}
|
||||
|
||||
def decode(value) do
|
||||
|
@ -13,8 +13,8 @@ defmodule OpenapiPetstore.Model.FakeBigDecimalMap200Response do
|
||||
]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
:someId => float() | nil,
|
||||
:someMap => %{optional(String.t) => float()} | nil
|
||||
:someId => number() | nil,
|
||||
:someMap => %{optional(String.t) => number()} | nil
|
||||
}
|
||||
|
||||
def decode(value) do
|
||||
|
@ -30,10 +30,10 @@ defmodule OpenapiPetstore.Model.FormatTest do
|
||||
:integer => integer() | nil,
|
||||
:int32 => integer() | nil,
|
||||
:int64 => integer() | nil,
|
||||
:number => float(),
|
||||
:number => number(),
|
||||
:float => float() | nil,
|
||||
:double => float() | nil,
|
||||
:decimal => String.t | nil,
|
||||
:decimal => float() | nil,
|
||||
:string => String.t | nil,
|
||||
:byte => binary(),
|
||||
:binary => String.t | nil,
|
||||
@ -45,12 +45,8 @@ defmodule OpenapiPetstore.Model.FormatTest do
|
||||
:pattern_with_digits_and_delimiter => String.t | nil
|
||||
}
|
||||
|
||||
alias OpenapiPetstore.Deserializer
|
||||
|
||||
def decode(value) do
|
||||
value
|
||||
|> Deserializer.deserialize(:date, :date, nil)
|
||||
|> Deserializer.deserialize(:dateTime, :datetime, nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -23,7 +23,6 @@ defmodule OpenapiPetstore.Model.MixedPropertiesAndAdditionalPropertiesClass do
|
||||
|
||||
def decode(value) do
|
||||
value
|
||||
|> Deserializer.deserialize(:dateTime, :datetime, nil)
|
||||
|> Deserializer.deserialize(:map, :map, OpenapiPetstore.Model.Animal)
|
||||
end
|
||||
end
|
||||
|
@ -24,25 +24,21 @@ defmodule OpenapiPetstore.Model.NullableClass do
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
:integer_prop => integer() | nil,
|
||||
:number_prop => float() | nil,
|
||||
:number_prop => number() | nil,
|
||||
:boolean_prop => boolean() | nil,
|
||||
:string_prop => String.t | nil,
|
||||
:date_prop => Date.t | nil,
|
||||
:datetime_prop => DateTime.t | nil,
|
||||
:array_nullable_prop => [%{optional(String.t) => any()}] | nil,
|
||||
:array_and_items_nullable_prop => [%{optional(String.t) => any()}] | nil,
|
||||
:array_items_nullable => [%{optional(String.t) => any()}] | nil,
|
||||
:object_nullable_prop => %{optional(String.t) => any()} | nil,
|
||||
:object_and_items_nullable_prop => %{optional(String.t) => any()} | nil,
|
||||
:object_items_nullable => %{optional(String.t) => any()} | nil
|
||||
:array_nullable_prop => [map()] | nil,
|
||||
:array_and_items_nullable_prop => [map()] | nil,
|
||||
:array_items_nullable => [map()] | nil,
|
||||
:object_nullable_prop => %{optional(String.t) => map()} | nil,
|
||||
:object_and_items_nullable_prop => %{optional(String.t) => map()} | nil,
|
||||
:object_items_nullable => %{optional(String.t) => map()} | nil
|
||||
}
|
||||
|
||||
alias OpenapiPetstore.Deserializer
|
||||
|
||||
def decode(value) do
|
||||
value
|
||||
|> Deserializer.deserialize(:date_prop, :date, nil)
|
||||
|> Deserializer.deserialize(:datetime_prop, :datetime, nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -12,7 +12,7 @@ defmodule OpenapiPetstore.Model.NumberOnly do
|
||||
]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
:JustNumber => float() | nil
|
||||
:JustNumber => number() | nil
|
||||
}
|
||||
|
||||
def decode(value) do
|
||||
|
@ -16,7 +16,7 @@ defmodule OpenapiPetstore.Model.ObjectWithDeprecatedFields do
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
:uuid => String.t | nil,
|
||||
:id => float() | nil,
|
||||
:id => number() | nil,
|
||||
:deprecatedRef => OpenapiPetstore.Model.DeprecatedModel.t | nil,
|
||||
:bars => [String.t] | nil
|
||||
}
|
||||
|
@ -25,11 +25,8 @@ defmodule OpenapiPetstore.Model.Order do
|
||||
:complete => boolean() | nil
|
||||
}
|
||||
|
||||
alias OpenapiPetstore.Deserializer
|
||||
|
||||
def decode(value) do
|
||||
value
|
||||
|> Deserializer.deserialize(:shipDate, :datetime, nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -14,7 +14,7 @@ defmodule OpenapiPetstore.Model.OuterComposite do
|
||||
]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
:my_number => float() | nil,
|
||||
:my_number => number() | nil,
|
||||
:my_string => String.t | nil,
|
||||
:my_boolean => boolean() | nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user