Skip to content

Commit

Permalink
[csharp-netcore] Better handling of oneOf/anyOf with duplicated data …
Browse files Browse the repository at this point in the history
…type (#15377)

* better handling of oneOf/anyOf with duplicated data type

* update generichost template

* remove newline in eof

* bug fix (#15413)

---------

Co-authored-by: devhl-labs <[email protected]>
  • Loading branch information
wing328 and devhl-labs committed May 5, 2023
1 parent 76c05b2 commit 7259d81
Show file tree
Hide file tree
Showing 332 changed files with 3,796 additions and 20 deletions.
1 change: 0 additions & 1 deletion docs/generators/csharp-netcore.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|packageVersion|C# package version.| |1.0.0|
|releaseNote|Release note, default to 'Minor update'.| |Minor update|
|returnICollection|Return ICollection&lt;T&gt; instead of the concrete type.| |false|
|skipOneOfAnyOfGetter|Skip the generation of getter for sub-schemas in oneOf/anyOf models.| |false|
|sourceFolder|source folder for generated code| |src|
|targetFramework|The target .NET framework version. To target multiple frameworks, use `;` as the separator, e.g. `netstandard2.1;netcoreapp3.1`|<dl><dt>**netstandard1.3**</dt><dd>.NET Standard 1.3 compatible</dd><dt>**netstandard1.4**</dt><dd>.NET Standard 1.4 compatible</dd><dt>**netstandard1.5**</dt><dd>.NET Standard 1.5 compatible</dd><dt>**netstandard1.6**</dt><dd>.NET Standard 1.6 compatible</dd><dt>**netstandard2.0**</dt><dd>.NET Standard 2.0 compatible</dd><dt>**netstandard2.1**</dt><dd>.NET Standard 2.1 compatible</dd><dt>**netcoreapp3.1**</dt><dd>.NET Core 3.1 compatible (End of Support 13 Dec 2022)</dd><dt>**net47**</dt><dd>.NET Framework 4.7 compatible</dd><dt>**net48**</dt><dd>.NET Framework 4.8 compatible</dd><dt>**net6.0**</dt><dd>.NET 6.0 compatible</dd><dt>**net7.0**</dt><dd>.NET 7.0 compatible</dd></dl>|netstandard2.0|
|useCollection|Deserialize array types to Collection&lt;T&gt; instead of List&lt;T&gt;.| |false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8035,11 +8035,20 @@ private List<CodegenProperty> getComposedProperties(List<Schema> xOfCollection,
return null;
}
List<CodegenProperty> xOf = new ArrayList<>();
Set<String> dataTypeSet = new HashSet<>(); // to keep track of dataType
int i = 0;
for (Schema xOfSchema : xOfCollection) {
CodegenProperty cp = fromProperty(collectionName + "_" + i, xOfSchema, false);
xOf.add(cp);
i += 1;

if (dataTypeSet.contains(cp.dataType)) {
// add "x-duplicated-data-type" to indicate if the dataType already occurs before
// in other sub-schemas of allOf/anyOf/oneOf
cp.vendorExtensions.putIfAbsent("x-duplicated-data-type", true);
} else {
dataTypeSet.add(cp.dataType);
}
}
return xOf;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,6 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
protected boolean needsCustomHttpMethod = false;
protected boolean needsUriBuilder = false;

// skip generation of getter for oneOf/anyOf sub-schemas to avoid duplicate getter
// when the subschemas are of the same type but with different constraints (e.g. array of string)
protected boolean skipOneOfAnyOfGetter = false;

public CSharpNetCoreClientCodegen() {
super();

Expand Down Expand Up @@ -331,10 +327,6 @@ public CSharpNetCoreClientCodegen() {
CodegenConstants.CASE_INSENSITIVE_RESPONSE_HEADERS_DESC,
this.caseInsensitiveResponseHeaders);

addSwitch(CodegenConstants.SKIP_ONEOF_ANYOF_GETTER,
CodegenConstants.SKIP_ONEOF_ANYOF_GETTER_DESC,
this.skipOneOfAnyOfGetter);

regexModifiers = new HashMap<>();
regexModifiers.put('i', "IgnoreCase");
regexModifiers.put('m', "Multiline");
Expand Down Expand Up @@ -806,7 +798,6 @@ public void processOpts() {
syncBooleanProperty(additionalProperties, CodegenConstants.OPTIONAL_METHOD_ARGUMENT, this::setOptionalMethodArgumentFlag, optionalMethodArgumentFlag);
syncBooleanProperty(additionalProperties, CodegenConstants.NON_PUBLIC_API, this::setNonPublicApi, isNonPublicApi());
syncBooleanProperty(additionalProperties, CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, this::setUseOneOfDiscriminatorLookup, this.useOneOfDiscriminatorLookup);
syncBooleanProperty(additionalProperties, CodegenConstants.SKIP_ONEOF_ANYOF_GETTER, this::setSkipOneOfAnyOfGetter, this.skipOneOfAnyOfGetter);
syncBooleanProperty(additionalProperties, "supportsFileParameters", this::setSupportsFileParameters, this.supportsFileParameters);

final String testPackageName = testPackageName();
Expand Down Expand Up @@ -1187,14 +1178,6 @@ public boolean getUseOneOfDiscriminatorLookup() {
return this.useOneOfDiscriminatorLookup;
}

public void setSkipOneOfAnyOfGetter(boolean skipOneOfAnyOfGetter) {
this.skipOneOfAnyOfGetter = skipOneOfAnyOfGetter;
}

public boolean getSkipOneOfAnyOfGetter() {
return this.skipOneOfAnyOfGetter;
}

@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,18 @@
JsonTokenType startingTokenType = utf8JsonReader.TokenType;
{{#composedSchemas.anyOf}}
{{^vendorExtensions.x-duplicated-data-type}}
Utf8JsonReader {{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}}Reader = utf8JsonReader;
bool {{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}}Deserialized = Client.ClientUtils.TryDeserialize<{{{dataType}}}>(ref {{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}}Reader, jsonSerializerOptions, out {{{dataType}}}{{^isBoolean}}{{nrt?}}{{/isBoolean}} {{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}});

{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.anyOf}}
{{#composedSchemas.oneOf}}
{{^vendorExtensions.x-duplicated-data-type}}
Utf8JsonReader {{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}}Reader = utf8JsonReader;
bool {{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}}Deserialized = Client.ClientUtils.TryDeserialize<{{{dataType}}}>(ref {{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}}Reader, jsonSerializerOptions, out {{{dataType}}}{{^isBoolean}}{{nrt?}}{{/isBoolean}} {{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}});

{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.oneOf}}
{{#composedSchemas.allOf}}
{{^isInherited}}
Expand Down Expand Up @@ -186,9 +190,11 @@
{{/-last}}
{{/nonNullableVars}}
{{#composedSchemas.oneOf}}
{{^vendorExtensions.x-duplicated-data-type}}
if ({{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}}Deserialized)
return new {{classname}}({{#lambda.joinWithComma}}{{#lambda.camelcase_param}}{{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}}{{/lambda.camelcase_param}} {{#model.composedSchemas.allOf}}{{^isInherited}}{{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}}{{/isInherited}}{{/model.composedSchemas.allOf}}{{#model.composedSchemas.anyOf}}{{#lambda.camelcase_param}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.camelcase_param}} {{/model.composedSchemas.anyOf}}{{#allVars}}{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} {{/allVars}}{{/lambda.joinWithComma}});

{{/vendorExtensions.x-duplicated-data-type}}
{{#-last}}
throw new JsonException();
{{/-last}}
Expand All @@ -207,8 +213,27 @@
/// <exception cref="NotImplementedException"></exception>
public override void Write(Utf8JsonWriter writer, {{classname}} {{#lambda.camelcase_param}}{{classname}}{{/lambda.camelcase_param}}, JsonSerializerOptions jsonSerializerOptions)
{
{{#composedSchemas.anyOf}}
{{^vendorExtensions.x-duplicated-data-type}}
System.Text.Json.JsonSerializer.Serialize(writer, {{#lambda.camelcase_param}}{{classname}}{{/lambda.camelcase_param}}.{{#lambda.titlecase}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.titlecase}}, jsonSerializerOptions);

{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.anyOf}}
{{#composedSchemas.oneOf}}
{{^vendorExtensions.x-duplicated-data-type}}
System.Text.Json.JsonSerializer.Serialize(writer, {{#lambda.camelcase_param}}{{classname}}{{/lambda.camelcase_param}}.{{#lambda.titlecase}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.titlecase}}, jsonSerializerOptions);

{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.oneOf}}
{{#composedSchemas.allOf}}
{{^isInherited}}
System.Text.Json.JsonSerializer.Serialize(writer, {{#lambda.camelcase_param}}{{classname}}{{/lambda.camelcase_param}}.{{#lambda.titlecase}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.titlecase}}, jsonSerializerOptions);

{{^composedSchemas}}
writer.WriteStartObject();

{{/isInherited}}
{{/composedSchemas.allOf}}
{{#allVars}}
{{#isString}}
{{^isMap}}
Expand Down Expand Up @@ -322,5 +347,6 @@
{{/allVars}}

writer.WriteEndObject();
{{/composedSchemas}}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
{{>visibility}} partial class {{classname}}{{#parent}} : {{{.}}}{{/parent}}{{>ImplementsIEquatable}}{{>ImplementsValidatable}}
{
{{#composedSchemas.oneOf}}
{{^vendorExtensions.x-duplicated-data-type}}
/// <summary>
/// Initializes a new instance of the <see cref="{{classname}}" /> class.
/// </summary>
Expand Down Expand Up @@ -36,6 +37,7 @@
{{/allVars}}
}

{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.oneOf}}
{{^composedSchemas.oneOf}}
/// <summary>
Expand Down Expand Up @@ -103,6 +105,7 @@
{{/isEnum}}
{{/vars}}
{{#composedSchemas.anyOf}}
{{^vendorExtensions.x-duplicated-data-type}}
/// <summary>
/// {{description}}{{^description}}Gets or Sets {{#lambda.titlecase}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.titlecase}}{{/description}}
/// </summary>{{#description}}
Expand All @@ -115,8 +118,10 @@
{{/deprecated}}
public {{{dataType}}}{{nrt?}} {{#lambda.titlecase}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.titlecase}} { get; {{^isReadOnly}}set; {{/isReadOnly}}}

{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.anyOf}}
{{#composedSchemas.oneOf}}
{{^vendorExtensions.x-duplicated-data-type}}
/// <summary>
/// {{description}}{{^description}}Gets or Sets {{#lambda.titlecase}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.titlecase}}{{/description}}
/// </summary>{{#description}}
Expand All @@ -129,6 +134,7 @@
{{/deprecated}}
public {{{dataType}}}{{nrt?}} {{#lambda.titlecase}}{{baseType}}{{#isArray}}{{{dataFormat}}}{{/isArray}}{{/lambda.titlecase}} { get; {{^isReadOnly}}set; {{/isReadOnly}}}

{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.oneOf}}
{{#composedSchemas.allOf}}
{{^isInherited}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

{{/isNullable}}
{{#composedSchemas.anyOf}}
{{^vendorExtensions.x-duplicated-data-type}}
{{^isNull}}
/// <summary>
/// Initializes a new instance of the <see cref="{{classname}}" /> class
Expand All @@ -38,6 +39,7 @@
}

{{/isNull}}
{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.anyOf}}

private Object _actualInstance;
Expand Down Expand Up @@ -66,6 +68,7 @@
}
}
{{#composedSchemas.anyOf}}
{{^vendorExtensions.x-duplicated-data-type}}
{{^isNull}}

/// <summary>
Expand All @@ -78,6 +81,7 @@
return ({{{dataType}}})this.ActualInstance;
}
{{/isNull}}
{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.anyOf}}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

{{/isNullable}}
{{#composedSchemas.oneOf}}
{{^vendorExtensions.x-duplicated-data-type}}
{{^isNull}}
/// <summary>
/// Initializes a new instance of the <see cref="{{classname}}" /> class
Expand All @@ -38,6 +39,7 @@
}

{{/isNull}}
{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.oneOf}}

private Object _actualInstance;
Expand Down Expand Up @@ -65,8 +67,8 @@
}
}
}
{{^skipOneOfAnyOfGetter}}
{{#composedSchemas.oneOf}}
{{^vendorExtensions.x-duplicated-data-type}}
{{^isNull}}

/// <summary>
Expand All @@ -79,8 +81,8 @@
return ({{{dataType}}})this.ActualInstance;
}
{{/isNull}}
{{/vendorExtensions.x-duplicated-data-type}}
{{/composedSchemas.oneOf}}
{{/skipOneOfAnyOfGetter}}

/// <summary>
/// Returns the string presentation of the object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2273,3 +2273,9 @@ components:
unescapedLiteralString:
type: string
default: C:\Users\username
OneOfString:
oneOf:
- type: string
pattern: ^a
- type: string
pattern: ^b
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ docs/NullableGuidClass.md
docs/NullableShape.md
docs/NumberOnly.md
docs/ObjectWithDeprecatedFields.md
docs/OneOfString.md
docs/Order.md
docs/OuterComposite.md
docs/OuterEnum.md
Expand Down Expand Up @@ -180,6 +181,7 @@ src/Org.OpenAPITools/Model/NullableGuidClass.cs
src/Org.OpenAPITools/Model/NullableShape.cs
src/Org.OpenAPITools/Model/NumberOnly.cs
src/Org.OpenAPITools/Model/ObjectWithDeprecatedFields.cs
src/Org.OpenAPITools/Model/OneOfString.cs
src/Org.OpenAPITools/Model/Order.cs
src/Org.OpenAPITools/Model/OuterComposite.cs
src/Org.OpenAPITools/Model/OuterEnum.cs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ Class | Method | HTTP request | Description
- [Model.NullableShape](docs/NullableShape.md)
- [Model.NumberOnly](docs/NumberOnly.md)
- [Model.ObjectWithDeprecatedFields](docs/ObjectWithDeprecatedFields.md)
- [Model.OneOfString](docs/OneOfString.md)
- [Model.Order](docs/Order.md)
- [Model.OuterComposite](docs/OuterComposite.md)
- [Model.OuterEnum](docs/OuterEnum.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2200,6 +2200,12 @@ components:
default: C:\Users\username
type: string
type: object
OneOfString:
oneOf:
- pattern: ^a
type: string
- pattern: ^b
type: string
_foo_get_default_response:
example:
string:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Org.OpenAPITools.Model.OneOfString

## Properties

Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------

[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* OpenAPI Petstore
*
* This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\
*
* The version of the OpenAPI document: 1.0.0
* Generated by: https://github.com/openapitools/openapi-generator.git
*/


using Xunit;

using System;
using System.Linq;
using System.IO;
using System.Collections.Generic;
using Org.OpenAPITools.Model;
using Org.OpenAPITools.Client;
using System.Reflection;
using Newtonsoft.Json;

namespace Org.OpenAPITools.Test.Model
{
/// <summary>
/// Class for testing OneOfString
/// </summary>
/// <remarks>
/// This file is automatically generated by OpenAPI Generator (https://openapi-generator.tech).
/// Please update the test case below to test the model.
/// </remarks>
public class OneOfStringTests : IDisposable
{
// TODO uncomment below to declare an instance variable for OneOfString
//private OneOfString instance;

public OneOfStringTests()
{
// TODO uncomment below to create an instance of OneOfString
//instance = new OneOfString();
}

public void Dispose()
{
// Cleanup when everything is done.
}

/// <summary>
/// Test an instance of OneOfString
/// </summary>
[Fact]
public void OneOfStringInstanceTest()
{
// TODO uncomment below to test "IsType" OneOfString
//Assert.IsType<OneOfString>(instance);
}



}

}
Loading

0 comments on commit 7259d81

Please sign in to comment.