Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get Parameter's PathItems from first child if doesn't exist #3801

Merged
merged 11 commits into from
Dec 7, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed parsing of `DateOnly` values generated in request executors [#3679](https://github.com/microsoft/kiota/issues/3679)
- Fixes generation of default values names for go constructor functions [#3436](https://github.com/microsoft/kiota/issues/3436)
- [Java] Removed the usage of reflection in `ApiClientBuilder` [`kiota-java#923`](https://github.com/microsoft/kiota-java/issues/923)
- Fixed a bug where path parameter type was not correctly detected during generation. [#3791](https://github.com/microsoft/kiota/issues/3791)

## [1.8.2] - 2023-11-08

Expand Down
23 changes: 21 additions & 2 deletions src/Kiota.Builder/KiotaBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Globalization;
using System.IO;
Expand Down Expand Up @@ -1080,9 +1081,10 @@ private CodeParameter GetIndexerParameterType(OpenApiUrlTreeNode currentNode, Op
var parameterName = string.Join(OpenAPIUrlTreeNodePathSeparator, currentNode.Path.Split(OpenAPIUrlTreeNodePathSeparator, StringSplitOptions.RemoveEmptyEntries)
.Skip(parentNode.Path.Count(static x => x == OpenAPIUrlTreeNodePathSeparator)))
.Trim(OpenAPIUrlTreeNodePathSeparator, ForwardSlash, '{', '}');
var parameter = currentNode.PathItems.TryGetValue(Constants.DefaultOpenApiLabel, out var pathItem) ? pathItem.Parameters
var pathItems = GetPathItems(currentNode);
var parameter = pathItems.TryGetValue(Constants.DefaultOpenApiLabel, out var pathItem) ? pathItem.Parameters
.Select(static x => new { Parameter = x, IsPathParameter = true })
.Union(currentNode.PathItems[Constants.DefaultOpenApiLabel].Operations.SelectMany(static x => x.Value.Parameters).Select(static x => new { Parameter = x, IsPathParameter = false }))
.Union(pathItems[Constants.DefaultOpenApiLabel].Operations.SelectMany(static x => x.Value.Parameters).Select(static x => new { Parameter = x, IsPathParameter = false }))
.OrderBy(static x => x.IsPathParameter)
.Select(static x => x.Parameter)
.FirstOrDefault(x => x.Name.Equals(parameterName, StringComparison.OrdinalIgnoreCase) && x.In == ParameterLocation.Path) :
Expand All @@ -1105,6 +1107,23 @@ private CodeParameter GetIndexerParameterType(OpenApiUrlTreeNode currentNode, Op
};
return result;
}
private static IDictionary<string, OpenApiPathItem> GetPathItems(OpenApiUrlTreeNode currentNode, bool validateIsParameterNode = true)
{
if ((!validateIsParameterNode || currentNode.IsParameter) && currentNode.PathItems.Any())
{
return currentNode.PathItems;
}

if (currentNode.Children.Any())
{
return currentNode.Children
.SelectMany(static x => GetPathItems(x.Value, false))
.DistinctBy(static x => x.Key, StringComparer.Ordinal)
.ToDictionary(static x => x.Key, static x => x.Value, StringComparer.Ordinal);
}

return ImmutableDictionary<string, OpenApiPathItem>.Empty;
}
private CodeIndexer[] CreateIndexer(string childIdentifier, string childType, CodeParameter parameter, OpenApiUrlTreeNode currentNode, OpenApiUrlTreeNode parentNode)
{
logger.LogTrace("Creating indexer {Name}", childIdentifier);
Expand Down
109 changes: 91 additions & 18 deletions tests/Kiota.Builder.Tests/KiotaBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6204,6 +6204,40 @@ public async Task IndexerTypeIsAccurateAndBackwardCompatibleIndexersAreAdded()
application/json:
schema:
$ref: '#/components/schemas/microsoft.graph.post'
/authors/{author-id}/posts:
baywet marked this conversation as resolved.
Show resolved Hide resolved
get:
parameters:
- name: author-id
in: path
required: true
description: The id of the author's posts to retrieve
schema:
type: string
format: uuid
responses:
200:
description: Success!
content:
application/json:
schema:
$ref: '#/components/schemas/microsoft.graph.post'
/actors/{actor-id}/foo/baz:
get:
parameters:
- name: actor-id
in: path
required: true
description: The id of the actor
schema:
type: string
format: uuid
responses:
200:
description: Success!
content:
application/json:
schema:
$ref: '#/components/schemas/microsoft.graph.post'
components:
schemas:
microsoft.graph.post:
Expand All @@ -6218,24 +6252,63 @@ public async Task IndexerTypeIsAccurateAndBackwardCompatibleIndexersAreAdded()
var document = await builder.CreateOpenApiDocumentAsync(fs);
var node = builder.CreateUriSpace(document!);
var codeModel = builder.CreateSourceModel(node);
var collectionRequestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.me.posts");
Assert.NotNull(collectionRequestBuilderNamespace);
var collectionRequestBuilder = collectionRequestBuilderNamespace.FindChildByName<CodeClass>("postsRequestBuilder");
var collectionIndexer = collectionRequestBuilder.Indexer;
Assert.NotNull(collectionIndexer);
Assert.Equal("integer", collectionIndexer.IndexParameter.Type.Name);
Assert.Equal("The id of the pet to retrieve", collectionIndexer.IndexParameter.Documentation.Description, StringComparer.OrdinalIgnoreCase);
Assert.False(collectionIndexer.IndexParameter.Type.IsNullable);
Assert.False(collectionIndexer.Deprecation.IsDeprecated);
var collectionStringIndexer = collectionRequestBuilder.FindChildByName<CodeIndexer>($"{collectionIndexer.Name}-string");
Assert.NotNull(collectionStringIndexer);
Assert.Equal("string", collectionStringIndexer.IndexParameter.Type.Name);
Assert.True(collectionStringIndexer.IndexParameter.Type.IsNullable);
Assert.True(collectionStringIndexer.Deprecation.IsDeprecated);
var itemRequestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.me.posts.item");
Assert.NotNull(itemRequestBuilderNamespace);
var itemRequestBuilder = itemRequestBuilderNamespace.FindChildByName<CodeClass>("postItemRequestBuilder");
Assert.Equal(collectionIndexer.ReturnType.Name, itemRequestBuilder.Name);

var postsCollectionRequestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.me.posts");
Assert.NotNull(postsCollectionRequestBuilderNamespace);
var postsCollectionRequestBuilder = postsCollectionRequestBuilderNamespace.FindChildByName<CodeClass>("postsRequestBuilder");
var postsCollectionIndexer = postsCollectionRequestBuilder.Indexer;
Assert.NotNull(postsCollectionIndexer);
Assert.Equal("integer", postsCollectionIndexer.IndexParameter.Type.Name);
Assert.Equal("The id of the pet to retrieve", postsCollectionIndexer.IndexParameter.Documentation.Description, StringComparer.OrdinalIgnoreCase);
Assert.False(postsCollectionIndexer.IndexParameter.Type.IsNullable);
Assert.False(postsCollectionIndexer.Deprecation.IsDeprecated);
var postsCollectionStringIndexer = postsCollectionRequestBuilder.FindChildByName<CodeIndexer>($"{postsCollectionIndexer.Name}-string");
Assert.NotNull(postsCollectionStringIndexer);
Assert.Equal("string", postsCollectionStringIndexer.IndexParameter.Type.Name);
Assert.True(postsCollectionStringIndexer.IndexParameter.Type.IsNullable);
Assert.True(postsCollectionStringIndexer.Deprecation.IsDeprecated);
var postsItemRequestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.me.posts.item");
Assert.NotNull(postsItemRequestBuilderNamespace);
var postsItemRequestBuilder = postsItemRequestBuilderNamespace.FindChildByName<CodeClass>("postItemRequestBuilder");
Assert.Equal(postsCollectionIndexer.ReturnType.Name, postsItemRequestBuilder.Name);

var authorsCollectionRequestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.authors");
Assert.NotNull(authorsCollectionRequestBuilderNamespace);
var authorsCollectionRequestBuilder = authorsCollectionRequestBuilderNamespace.FindChildByName<CodeClass>("authorsRequestBuilder");
var authorsCollectionIndexer = authorsCollectionRequestBuilder.Indexer;
Assert.NotNull(authorsCollectionIndexer);
Assert.Equal("Guid", authorsCollectionIndexer.IndexParameter.Type.Name);
Assert.Equal("The id of the author's posts to retrieve", authorsCollectionIndexer.IndexParameter.Documentation.Description, StringComparer.OrdinalIgnoreCase);
Assert.False(authorsCollectionIndexer.IndexParameter.Type.IsNullable);
Assert.False(authorsCollectionIndexer.Deprecation.IsDeprecated);
var authorsCllectionStringIndexer = authorsCollectionRequestBuilder.FindChildByName<CodeIndexer>($"{authorsCollectionIndexer.Name}-string");
Assert.NotNull(authorsCllectionStringIndexer);
Assert.Equal("string", authorsCllectionStringIndexer.IndexParameter.Type.Name);
Assert.True(authorsCllectionStringIndexer.IndexParameter.Type.IsNullable);
Assert.True(authorsCllectionStringIndexer.Deprecation.IsDeprecated);
var authorsItemRequestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.authors.item");
Assert.NotNull(authorsItemRequestBuilderNamespace);
var authorsItemRequestBuilder = authorsItemRequestBuilderNamespace.FindChildByName<CodeClass>("authorItemRequestBuilder");
Assert.Equal(authorsCollectionIndexer.ReturnType.Name, authorsItemRequestBuilder.Name);

var actorsCollectionRequestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.actors");
Assert.NotNull(actorsCollectionRequestBuilderNamespace);
var actorsCollectionRequestBuilder = actorsCollectionRequestBuilderNamespace.FindChildByName<CodeClass>("actorsRequestBuilder");
var actorsCollectionIndexer = actorsCollectionRequestBuilder.Indexer;
Assert.NotNull(actorsCollectionIndexer);
Assert.Equal("Guid", actorsCollectionIndexer.IndexParameter.Type.Name);
Assert.Equal("The id of the actor", actorsCollectionIndexer.IndexParameter.Documentation.Description, StringComparer.OrdinalIgnoreCase);
Assert.False(actorsCollectionIndexer.IndexParameter.Type.IsNullable);
Assert.False(actorsCollectionIndexer.Deprecation.IsDeprecated);
var actorsCllectionStringIndexer = actorsCollectionRequestBuilder.FindChildByName<CodeIndexer>($"{actorsCollectionIndexer.Name}-string");
Assert.NotNull(actorsCllectionStringIndexer);
Assert.Equal("string", actorsCllectionStringIndexer.IndexParameter.Type.Name);
Assert.True(actorsCllectionStringIndexer.IndexParameter.Type.IsNullable);
Assert.True(actorsCllectionStringIndexer.Deprecation.IsDeprecated);
var actorsItemRequestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.actors.item");
Assert.NotNull(actorsItemRequestBuilderNamespace);
var actorsItemRequestBuilder = actorsItemRequestBuilderNamespace.FindChildByName<CodeClass>("actorItemRequestBuilder");
Assert.Equal(actorsCollectionIndexer.ReturnType.Name, actorsItemRequestBuilder.Name);
}
[Fact]
public async Task MapsBooleanEnumToBooleanType()
Expand Down
Loading