Skip to content

Commit

Permalink
Merge pull request #5348 from microsoft/fix/array-union
Browse files Browse the repository at this point in the history
fix: missing array of primitive types in union or intersection types
  • Loading branch information
baywet authored Sep 6, 2024
2 parents 00554b5 + f8f274e commit bb00862
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 17 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Fixed a bug where collection/array of primitive types members for union/intersection types would be ignored. [#5283](https://github.com/microsoft/kiota/issues/5283)
- Fixed a when generating a plugin when only an operation is selected in the root node in the extension. [#5300](https://github.com/microsoft/kiota/issues/5300)

## [1.18.0] - 2024-09-05
Expand Down Expand Up @@ -1444,4 +1445,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Initial GitHub release

16 changes: 8 additions & 8 deletions it/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,7 @@
"Rationale": "https://github.com/microsoft/kiota/issues/2957"
}
],
"IdempotencySuppressions": [
]
"IdempotencySuppressions": []
},
"apisguru::twilio.com:api": {
"ExcludePatterns": [
Expand Down Expand Up @@ -253,6 +252,10 @@
{
"Language": "ruby",
"Rationale": "https://github.com/microsoft/kiota/issues/1816"
},
{
"Language": "php",
"Rationale": "https://github.com/microsoft/kiota/issues/5354"
}
],
"IdempotencySuppressions": [
Expand Down Expand Up @@ -301,13 +304,10 @@
"Rationale": "https://github.com/microsoft/kiota/issues/1816"
}
],
"IdempotencySuppressions": [
]
"IdempotencySuppressions": []
},
"apisguru::apis.guru": {
"Suppressions": [
],
"IdempotencySuppressions": [
]
"Suppressions": [],
"IdempotencySuppressions": []
}
}
2 changes: 2 additions & 0 deletions src/Kiota.Builder/KiotaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1744,6 +1744,8 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo
if (string.IsNullOrEmpty(className))
if (GetPrimitiveType(currentSchema) is CodeType primitiveType && !string.IsNullOrEmpty(primitiveType.Name))
{
if (currentSchema.IsArray())
primitiveType.CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Complex;
if (!unionType.ContainsType(primitiveType))
unionType.AddType(primitiveType);
continue;
Expand Down
11 changes: 4 additions & 7 deletions src/Kiota.Builder/Writers/TypeScript/CodeFunctionWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private void WriteComposedTypeDeserializer(CodeFunction codeElement, LanguageWri
if (GetOriginalComposedType(composedParam) is not { } composedType) return;

writer.StartBlock("return {");
foreach (var mappedType in composedType.Types.Where(x => !IsPrimitiveType(x, composedType)))
foreach (var mappedType in composedType.Types.Where(x => !IsPrimitiveType(x, composedType, false)))
{
var functionName = GetDeserializerFunctionName(codeElement, mappedType);
var variableName = composedParam.Name.ToFirstCharacterLowerCase();
Expand All @@ -86,12 +86,12 @@ private void WriteComposedTypeSerializer(CodeFunction codeElement, LanguageWrite
{
if (GetOriginalComposedType(composedParam) is not { } composedType) return;

if (composedType.IsComposedOfPrimitives(IsPrimitiveType))
if (composedType.IsComposedOfPrimitives((x, y) => IsPrimitiveType(x, y, false)))
{
var paramName = composedParam.Name.ToFirstCharacterLowerCase();
writer.WriteLine($"if ({paramName} === undefined || {paramName} === null) return;");
writer.StartBlock($"switch (typeof {paramName}) {{");
foreach (var type in composedType.Types.Where(x => IsPrimitiveType(x, composedType)))
foreach (var type in composedType.Types.Where(x => IsPrimitiveType(x, composedType, false)))
{
WriteCaseStatementForPrimitiveTypeSerialization(type, "key", paramName, codeElement, writer);
}
Expand Down Expand Up @@ -327,11 +327,8 @@ private string FindFunctionInNameSpace(string functionName, CodeElement codeElem
CodeFunction[] codeFunctions = myNamespace.FindChildrenByName<CodeFunction>(functionName).ToArray();

var codeFunction = Array.Find(codeFunctions,
func => func.GetImmediateParentOfType<CodeNamespace>().Name == myNamespace.Name);

if (codeFunction == null)
func => func.GetImmediateParentOfType<CodeNamespace>().Name == myNamespace.Name) ??
throw new InvalidOperationException($"Function {functionName} not found in namespace {myNamespace.Name}");

return conventions.GetTypeString(new CodeType { TypeDefinition = codeFunction }, codeElement, false);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,9 @@ TYPE_LOWERCASE_BOOLEAN or
};
}

public static bool IsPrimitiveType(CodeType codeType, CodeComposedTypeBase codeComposedTypeBase) => IsPrimitiveType(GetTypescriptTypeString(codeType, codeComposedTypeBase));
public static bool IsPrimitiveType(CodeType codeType, CodeComposedTypeBase codeComposedTypeBase) => IsPrimitiveType(codeType, codeComposedTypeBase, true);

public static bool IsPrimitiveType(CodeType codeType, CodeComposedTypeBase codeComposedTypeBase, bool includeCollectionInformation) => IsPrimitiveType(GetTypescriptTypeString(codeType, codeComposedTypeBase, includeCollectionInformation));

internal static string RemoveInvalidDescriptionCharacters(string originalDescription) => originalDescription?.Replace("\\", "/", StringComparison.OrdinalIgnoreCase) ?? string.Empty;
public override bool WriteShortDescription(IDocumentedElement element, LanguageWriter writer, string prefix = "", string suffix = "")
Expand Down
83 changes: 83 additions & 0 deletions tests/Kiota.Builder.Tests/KiotaBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2841,6 +2841,89 @@ public void SquishesLonelyNullablesBothAnyOf()
Assert.Null(codeModel.FindChildByName<CodeClass>("createUploadSessionResponseMember1"));
}
[Fact]
public void SupportsArraysInComposedTypes()
{
var anyOfSchema = new OpenApiSchema
{
Type = "object",
AdditionalPropertiesAllowed = false,
Properties = new Dictionary<string, OpenApiSchema> {
{
"date", new OpenApiSchema {
AnyOf = [
new OpenApiSchema {
Type = "string",
},
new OpenApiSchema {
Type = "array",
Items = new OpenApiSchema {
Type = "string",
},
},
]
}
}
},
Reference = new OpenApiReference
{
Id = "anyOfNullable",
Type = ReferenceType.Schema
},
UnresolvedReference = false
};
var document = new OpenApiDocument
{
Paths = new OpenApiPaths
{
["createUploadSession"] = new OpenApiPathItem
{
Operations = {
[OperationType.Get] = new OpenApiOperation
{
Responses = new OpenApiResponses
{
["200"] = new OpenApiResponse
{
Content = new Dictionary<string, OpenApiMediaType> {
["application/json"] = new OpenApiMediaType
{
Schema = anyOfSchema
}
}
}
}
}
}
}
},
Components = new OpenApiComponents
{
Schemas = new Dictionary<string, OpenApiSchema> {
{
"anyOfNullable", anyOfSchema
}
},
},
};
var mockLogger = new Mock<ILogger<KiotaBuilder>>();
var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient);
builder.SetOpenApiDocument(document);
var node = builder.CreateUriSpace(document);
var codeModel = builder.CreateSourceModel(node);
var anyOfClass = codeModel.FindChildByName<CodeClass>("anyOfNullable");
Assert.NotNull(anyOfClass);
var dateProperty = anyOfClass.FindChildByName<CodeProperty>("date", false);
Assert.NotNull(dateProperty);
if (dateProperty.Type is not CodeIntersectionType unionType)
Assert.Fail("Date property type is not a union type");
else
{
Assert.Equal(2, unionType.Types.Count());
Assert.Contains(unionType.Types, x => x.Name.Equals("string", StringComparison.OrdinalIgnoreCase) && x.CollectionKind is CodeTypeBase.CodeTypeCollectionKind.None);
Assert.Contains(unionType.Types, x => x.Name.Equals("string", StringComparison.OrdinalIgnoreCase) && x.CollectionKind is CodeTypeBase.CodeTypeCollectionKind.Complex);
}
}
[Fact]
public void SupportsNullableAnyOf()
{
var anyOfSchema = new OpenApiSchema
Expand Down

0 comments on commit bb00862

Please sign in to comment.