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

Fixes duplicated Id suffix in indexers. #4547

Merged
merged 1 commit into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Fixed a bug where TypeScript deserialization would fail on Uppercase properties.[#4479](https://github.com/microsoft/kiota/issues/4479)
- Changed URI template generation to reuse templates when required templates are absent across operations.
- Fixed path deduplication logic to avoid double `Id` suffixes in indexer names in scenarios where the `Id` suffix is already present.[#4519](https://github.com/microsoft/kiota/issues/4519)
- Updated reserved name providers for Java and Php so that "object" can be escaped.
- Fixes request builder disambiguation when child nodes had different prefixes for different paths with same parameters.[#4448](https://github.com/microsoft/kiota/issues/4448)
- Do not generate CS8603 warnings when enabling backing store in CSharp generation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ internal static void MergeIndexNodesAtSameLevel(this OpenApiUrlTreeNode node, IL
node.Children.Remove(indexNode.Key);
var oldSegmentName = indexNode.Value.Segment.Trim('{', '}').CleanupSymbolName();
var segmentIndex = indexNode.Value.Path.Split('\\', StringSplitOptions.RemoveEmptyEntries).ToList().IndexOf(indexNode.Value.Segment);
var newSegmentParameterName = oldSegmentName.EndsWith("-id", StringComparison.OrdinalIgnoreCase) ? oldSegmentName : $"{{{oldSegmentName}-id}}";
var newSegmentParameterName = oldSegmentName.EndsWith("-id", StringComparison.OrdinalIgnoreCase) ? oldSegmentName : $"{{{oldSegmentName.TrimSuffix("id", StringComparison.OrdinalIgnoreCase)}-id}}";
indexNode.Value.Path = indexNode.Value.Path.Replace(indexNode.Key, newSegmentParameterName, StringComparison.OrdinalIgnoreCase);
indexNode.Value.AddDeduplicatedSegment(newSegmentParameterName);
node.Children.Add(newSegmentParameterName, indexNode.Value);
Expand Down
3 changes: 3 additions & 0 deletions src/Kiota.Builder/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,4 +290,7 @@ public static string CleanupXMLString(this string? original)
/// <returns></returns>
public static bool EqualsIgnoreCase(this string? a, string? b)
=> string.Equals(a, b, StringComparison.OrdinalIgnoreCase);

public static string TrimSuffix(this string s, string suffix, StringComparison stringComparison = StringComparison.Ordinal) =>
!string.IsNullOrEmpty(s) && !string.IsNullOrEmpty(suffix) && s.EndsWith(suffix, stringComparison) ? s[..^suffix.Length] : s;
}
2 changes: 0 additions & 2 deletions src/Kiota.Builder/Writers/Go/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,4 @@ public static string TrimCollectionAndPointerSymbols(this string s) =>
public static string TrimPackageReference(this string s) =>
!string.IsNullOrEmpty(s) && s.Contains('.', StringComparison.InvariantCultureIgnoreCase) ? s.Split('.').Last() : s;

public static string TrimSuffix(this string s, string suffix) =>
!string.IsNullOrEmpty(s) && suffix != null && s.EndsWith(suffix, StringComparison.Ordinal) ? s[..^suffix.Length] : s;
}
Original file line number Diff line number Diff line change
Expand Up @@ -1068,9 +1068,9 @@ public void repro4085()
Assert.Null(GetChildNodeByPath(resultNode, "{thingId}"));
Assert.Null(GetChildNodeByPath(resultNode, "{differentThingId}"));

var differentThingId = GetChildNodeByPath(resultNode, "{differentThingId-id}");
Assert.Equal("\\path\\{differentThingId-id}", differentThingId.Path);
Assert.Equal("{+baseurl}/path/{differentThingId%2Did}", differentThingId.GetUrlTemplate());
var differentThingId = GetChildNodeByPath(resultNode, "{differentThing-id}");
Assert.Equal("\\path\\{differentThing-id}", differentThingId.Path);
Assert.Equal("{+baseurl}/path/{differentThing%2Did}", differentThingId.GetUrlTemplate());
}

[Theory]
Expand Down
2 changes: 1 addition & 1 deletion tests/Kiota.Builder.Tests/KiotaBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,7 @@ public async Task TrimsInheritanceUnusedModelsWithUnion()
Assert.NotNull(modelsNS.FindChildByName<CodeClass>("EducationUser", false));
Assert.Null(modelsNS.FindChildByName<CodeClass>("AuditEvent", false));
}
private static async Task<Stream> GetDocumentStream(string document)
internal static async Task<Stream> GetDocumentStream(string document)
{
var ms = new MemoryStream();
await using var tw = new StreamWriter(ms, Encoding.UTF8, leaveOpen: true);
Expand Down
85 changes: 84 additions & 1 deletion tests/Kiota.Builder.Tests/Refiners/GoLanguageRefinerTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Kiota.Builder.CodeDOM;
using Kiota.Builder.Configuration;
using Kiota.Builder.Refiners;

using Microsoft.Extensions.Logging;
using Moq;
using Xunit;

namespace Kiota.Builder.Tests.Refiners;
Expand Down Expand Up @@ -439,6 +442,86 @@ public async Task SupportsTypeSpecificOverrideIndexers()
Assert.NotNull(model.Methods.SingleOrDefault(static x => x.IsOfKind(CodeMethodKind.IndexerBackwardCompatibility) && x.Name.Equals("ByIdInteger") && x.OriginalIndexer != null && x.OriginalIndexer.IndexParameter.Type.Name.Equals("Integer", StringComparison.OrdinalIgnoreCase)));
Assert.NotNull(model.Methods.SingleOrDefault(static x => x.IsOfKind(CodeMethodKind.IndexerBackwardCompatibility) && x.Name.Equals("ById") && x.OriginalIndexer != null && x.OriginalIndexer.IndexParameter.Type.Name.Equals("string", StringComparison.OrdinalIgnoreCase)));
}

[Fact]
public async Task ValidatesNamingOfRequestBuilderDoesNotRepeatIdCharacter()
{
var tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
await using var fs = await KiotaBuilderTests.GetDocumentStream(@"openapi: 3.0.1
info:
title: OData Service for namespace microsoft.graph
description: This OData service is located at https://graph.microsoft.com/v1.0
version: 1.0.1
servers:
- url: https://graph.microsoft.com/v1.0
paths:
/groups/{id}:
get:
summary: Get Group by Id
operationId: groups_GetById
parameters:
- name: id
in: path
description: The id of the group
required : true
schema :
type: string
format: uuid
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/microsoft.graph.directoryObject'
/groups/{groupId}/member/{id}:
get:
summary: Get member by Id
operationId: member_GetById
parameters:
- name: groupId
in: path
description: The id of the group
required : true
schema :
type: string
format: uuid
- name: id
in: path
description: The id of the member
required : true
schema :
type: string
format: uuid
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/microsoft.graph.directoryObject'
components:
schemas:
microsoft.graph.directoryObject:
title: directoryObject
type: object
properties:
deletedDateTime:
type: string
pattern: '^[0-9]{4,}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]([.][0-9]{1,12})?(Z|[+-][0-9][0-9]:[0-9][0-9])$'
format: date-time
nullable: true");
var mockLogger = new Mock<ILogger<KiotaBuilder>>();
var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", OpenAPIFilePath = tempFilePath }, new HttpClient());
var document = await builder.CreateOpenApiDocumentAsync(fs);
var node = builder.CreateUriSpace(document);
var codeModel = builder.CreateSourceModel(node);
await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.Go }, codeModel);
var requestBuilder = codeModel.FindChildByName<CodeClass>("groupsRequestBuilder");
var indexerMethods = requestBuilder.Methods.Where(static method =>
method.IsOfKind(CodeMethodKind.IndexerBackwardCompatibility)).ToArray();
Assert.Equal(2, indexerMethods.Length);
Assert.Equal("ByGroupId", indexerMethods[0].Name);
Assert.Equal("ByGroupIdGuid", indexerMethods[1].Name);
}
[Fact]
public async Task AddsExceptionInheritanceOnErrorClasses()
{
Expand Down
Loading