Skip to content

Commit

Permalink
Merge branch 'main' into shem/remove_stringify_primitive_types
Browse files Browse the repository at this point in the history
  • Loading branch information
shemogumbe authored Oct 22, 2024
2 parents 6acb5c2 + cb6f67c commit b04f415
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 103 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed a bug where composed types wrappers would not build in CSharp.
- Fixed a bug where the type name for inherited inline models would be incorrect. [#5610](https://github.com/microsoft/kiota/issues/5610)
- Fixes typing inconsistencies in generated code and libraries in Python [kiota-python#333](https://github.com/microsoft/kiota-python/issues/333)
- Fixes generation of superfluous fields for Models with discriminator due to refiners adding the same properties to the same model [#4178](https://github.com/microsoft/kiota/issues/4178).

## [1.19.1] - 2024-10-11

Expand Down
2 changes: 1 addition & 1 deletion it/python/requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,5 @@ sniffio==1.3.1 ; python_version >= '3.7'

uritemplate==4.1.1 ; python_version >= '3.6'

yarl==1.15.5 ; python_version >= '3.7'
yarl==1.16.0 ; python_version >= '3.7'

96 changes: 48 additions & 48 deletions it/typescript/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions it/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
"devDependencies": {
"@es-exec/esbuild-plugin-start": "^0.0.5",
"@stylistic/eslint-plugin-ts": "^2.9.0",
"@types/node": "^22.7.7",
"@typescript-eslint/eslint-plugin": "^8.10.0",
"@typescript-eslint/parser": "^8.10.0",
"@types/node": "^22.7.8",
"@typescript-eslint/eslint-plugin": "^8.11.0",
"@typescript-eslint/parser": "^8.11.0",
"esbuild": "^0.24.0",
"eslint": "^9.13.0",
"eslint-config-prettier": "^9.1.0",
Expand Down
28 changes: 26 additions & 2 deletions src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -485,8 +485,10 @@ private static CodeType ConvertComposedTypeToWrapper(CodeClass codeClass, CodeCo
if (!supportsInnerClasses)
{
var @namespace = codeClass.GetImmediateParentOfType<CodeNamespace>();
if (@namespace.FindChildByName<CodeClass>(codeComposedType.Name, false) is CodeClass { OriginalComposedType: null })
if (@namespace.FindChildByName<CodeClass>(codeComposedType.Name, false) is { OriginalComposedType: null })
codeComposedType.Name = $"{codeComposedType.Name}Wrapper";
if (GetAlreadyExistingComposedCodeType(@namespace, codeComposedType) is { } existingCodeType)
return existingCodeType;
newClass = @namespace.AddClass(new CodeClass
{
Name = codeComposedType.Name,
Expand All @@ -499,8 +501,10 @@ private static CodeType ConvertComposedTypeToWrapper(CodeClass codeClass, CodeCo
Deprecation = codeComposedType.Deprecation,
}).Last();
}
else if (codeComposedType.TargetNamespace is CodeNamespace targetNamespace)
else if (codeComposedType.TargetNamespace is { } targetNamespace)
{
if (GetAlreadyExistingComposedCodeType(targetNamespace, codeComposedType) is { } existingCodeType)
return existingCodeType;
newClass = targetNamespace.AddClass(new CodeClass
{
Name = codeComposedType.Name,
Expand All @@ -523,6 +527,8 @@ private static CodeType ConvertComposedTypeToWrapper(CodeClass codeClass, CodeCo
{
if (codeComposedType.Name.Equals(codeClass.Name, StringComparison.OrdinalIgnoreCase) || codeClass.FindChildByName<CodeProperty>(codeComposedType.Name, false) is not null)
codeComposedType.Name = $"{codeComposedType.Name}Wrapper";
if (GetAlreadyExistingComposedCodeType(codeClass, codeComposedType) is { } existingCodeType)
return existingCodeType;
newClass = codeClass.AddInnerClass(new CodeClass
{
Name = codeComposedType.Name,
Expand Down Expand Up @@ -602,6 +608,24 @@ private static CodeType ConvertComposedTypeToWrapper(CodeClass codeClass, CodeCo
ActionOf = codeComposedType.ActionOf,
};
}

private static CodeType? GetAlreadyExistingComposedCodeType(IBlock targetNamespace, CodeComposedTypeBase codeComposedType)
{
if (targetNamespace.FindChildByName<CodeClass>(codeComposedType.Name, false) is { OriginalComposedType: not null } existingClass && existingClass.OriginalComposedType.Name.Equals(codeComposedType.Name, StringComparison.OrdinalIgnoreCase))
{ // the composed type was already added/created and the typeDefinition(codeclass) is already present in the namespace/class.
return new CodeType
{
Name = codeComposedType.Name,
TypeDefinition = existingClass,
CollectionKind = codeComposedType.CollectionKind,
IsNullable = codeComposedType.IsNullable,
ActionOf = codeComposedType.ActionOf,
};
}

return null;
}

protected static void MoveClassesWithNamespaceNamesUnderNamespace(CodeElement currentElement)
{
if (currentElement is CodeClass currentClass &&
Expand Down
97 changes: 97 additions & 0 deletions tests/Kiota.Builder.Tests/KiotaBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,103 @@ public async Task DoesntConflictOnModelsNamespaceAsync()
Assert.NotNull(innerRequestBuilderNS.FindChildByName<CodeClass>("InnerRequestBuilder", false));

}
[Theory]
[InlineData(GenerationLanguage.CSharp)]
[InlineData(GenerationLanguage.Java)]
[InlineData(GenerationLanguage.TypeScript)]
[InlineData(GenerationLanguage.Python)]
[InlineData(GenerationLanguage.Go)]
[InlineData(GenerationLanguage.PHP)]
[InlineData(GenerationLanguage.Ruby)]
public async Task DoesNotAddSuperflousFieldsToModelsAsync(GenerationLanguage language)
{
var tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
await using var fs = await GetDocumentStreamAsync(@"openapi: 3.0.3
info:
title: Example API
version: 1.0.0
servers:
- url: ""https://localhost:8080""
paths:
""/api/all"":
post:
requestBody:
content:
application/json:
schema:
$ref: ""#/components/schemas/AorB""
required: true
responses:
""200"":
$ref: ""#/components/responses/AorBResponse""
components:
schemas:
A:
type: object
required:
- type
properties:
type:
type: string
default: ""a""
B:
type: object
required:
- type
properties:
type:
type: string
default: ""b""
AorB:
oneOf:
- $ref: ""#/components/schemas/A""
- $ref: ""#/components/schemas/B""
discriminator:
propertyName: type
mapping:
a: ""#/components/schemas/A""
b: ""#/components/schemas/B""
responses:
AorBResponse:
description: mandatory
content:
application/json:
schema:
$ref: ""#/components/schemas/AorB""");
var mockLogger = new Mock<ILogger<KiotaBuilder>>();
var generationConfiguration = new GenerationConfiguration { ClientClassName = "Graph", OpenAPIFilePath = tempFilePath, Language = language }; // we can use any language that creates wrapper types for composed types in different ways
var builder = new KiotaBuilder(mockLogger.Object, generationConfiguration, _httpClient);
var document = await builder.CreateOpenApiDocumentAsync(fs);
var node = builder.CreateUriSpace(document);
var codeModel = builder.CreateSourceModel(node);
await builder.ApplyLanguageRefinementAsync(generationConfiguration, codeModel, CancellationToken.None);
var requestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.api.all");
Assert.NotNull(requestBuilderNamespace);
if (language == GenerationLanguage.TypeScript || language == GenerationLanguage.Go)
{// these languages use CodeFiles
var requestExecutorMethod = codeModel.FindChildByName<CodeMethod>("post");
Assert.NotNull(requestExecutorMethod);
var returnType = requestExecutorMethod.ReturnType as CodeType;
var returnTypeDefinition = returnType.TypeDefinition as CodeInterface;
if (language == GenerationLanguage.TypeScript)
{
Assert.Equal(2, returnTypeDefinition.Properties.Count());
}
if (language == GenerationLanguage.Go)
{
Assert.Equal(4, returnTypeDefinition.Methods.Count());// a getter and a setter for each property in Go.
}
}
else
{
var allRequestBuilderClass = requestBuilderNamespace.FindChildByName<CodeClass>("allRequestBuilder", false);
var executor = allRequestBuilderClass.Methods.FirstOrDefault(m => m.IsOfKind(CodeMethodKind.RequestExecutor));
Assert.NotNull(executor);
var returnType = executor.ReturnType as CodeType;
var returnTypeDefinition = returnType.TypeDefinition as CodeClass;
Assert.Equal(2, returnTypeDefinition.Properties.Count());
}
}
[Fact]
public async Task NamesComponentsInlineSchemasProperlyAsync()
{
Expand Down
Loading

0 comments on commit b04f415

Please sign in to comment.