Skip to content

Commit 65c93d3

Browse files
update the way we get singleton resource suffix (#3119)
* update the way we get singleton resource suffix * regenerate * regenerate * add a more complicated test case
1 parent 39ad373 commit 65c93d3

File tree

15 files changed

+127
-23
lines changed

15 files changed

+127
-23
lines changed

samples/Azure.Management.Storage/Generated/BlobContainerResource.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/Azure.Management.Storage/Generated/StorageAccountResource.cs

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/Azure.ResourceManager.Sample/Generated/VirtualMachineScaleSetResource.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/AutoRest.CSharp/Mgmt/Decorator/SingletonDetection.cs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,49 @@
66
using System.Linq;
77
using AutoRest.CSharp.Input;
88
using AutoRest.CSharp.Mgmt.Models;
9+
using AutoRest.CSharp.Utilities;
910

1011
namespace AutoRest.CSharp.Mgmt.Decorator;
1112

1213
internal static class SingletonDetection
1314
{
1415
private static string[] SingletonKeywords = { "default", "latest", "current" };
1516

16-
private static ConcurrentDictionary<OperationSet, string?> _singletonResourceCache = new ConcurrentDictionary<OperationSet, string?>();
17+
private static ConcurrentDictionary<OperationSet, SingletonResourceSuffix?> _singletonResourceCache = new ConcurrentDictionary<OperationSet, SingletonResourceSuffix?>();
1718

1819
public static bool IsSingletonResource(this OperationSet operationSet)
1920
{
2021
return operationSet.TryGetSingletonResourceSuffix(out _);
2122
}
2223

23-
public static bool TryGetSingletonResourceSuffix(this OperationSet operationSet, [MaybeNullWhen(false)] out string singletonIdSuffix)
24+
public static bool TryGetSingletonResourceSuffix(this OperationSet operationSet, [MaybeNullWhen(false)] out SingletonResourceSuffix suffix)
2425
{
25-
singletonIdSuffix = null;
26-
if (_singletonResourceCache.TryGetValue(operationSet, out singletonIdSuffix))
27-
return singletonIdSuffix != null;
26+
suffix = null;
27+
if (_singletonResourceCache.TryGetValue(operationSet, out suffix))
28+
return suffix != null;
2829

29-
bool result = IsSingleton(operationSet, out singletonIdSuffix);
30-
_singletonResourceCache.TryAdd(operationSet, singletonIdSuffix);
30+
bool result = IsSingleton(operationSet, out var singletonIdSuffix);
31+
suffix = ParseSingletonIdSuffix(operationSet, singletonIdSuffix);
32+
_singletonResourceCache.TryAdd(operationSet, suffix);
3133
return result;
3234
}
3335

36+
private static SingletonResourceSuffix? ParseSingletonIdSuffix(OperationSet operationSet, string? singletonIdSuffix)
37+
{
38+
if (singletonIdSuffix == null)
39+
return null;
40+
41+
var segments = singletonIdSuffix.Split('/', System.StringSplitOptions.RemoveEmptyEntries);
42+
43+
// check if even segments
44+
if (segments.Length % 2 != 0)
45+
{
46+
throw new ErrorHelpers.ErrorException($"the singleton suffix set for operation set {operationSet.RequestPath} must have even segments, but got {singletonIdSuffix}");
47+
}
48+
49+
return SingletonResourceSuffix.Parse(segments);
50+
}
51+
3452
private static bool IsSingleton(OperationSet operationSet, [MaybeNullWhen(false)] out string singletonIdSuffix)
3553
{
3654
// we should first check the configuration for the singleton settings

src/AutoRest.CSharp/Mgmt/Generation/MgmtClientBaseWriter.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,11 +342,12 @@ protected string GetResourceCollectionMethodArgumentList(ResourceCollection reso
342342
return string.Join(", ", GetParametersForCollectionEntry(resourceCollection).Select(p => p.Name));
343343
}
344344

345-
protected virtual void WriteSingletonResourceEntry(Resource resource, string singletonResourceIdSuffix, MethodSignature signature)
345+
protected virtual void WriteSingletonResourceEntry(Resource resource, SingletonResourceSuffix singletonResourceIdSuffix, MethodSignature signature)
346346
{
347347
// we cannot guarantee that the singleResourceSuffix can only have two segments (it has many different cases),
348348
// therefore instead of using the extension method of ResourceIdentifier, we are just concatting this as a string
349-
_writer.Line($"return new {resource.Type.Name}({ArmClientReference}, new {typeof(ResourceIdentifier)}(Id.ToString() + \"/{singletonResourceIdSuffix}\"));");
349+
_writer.UseNamespace(typeof(ResourceIdentifier).Namespace!);
350+
_writer.Line($"return new {resource.Type.Name}({ArmClientReference}, {singletonResourceIdSuffix.BuildResourceIdentifier($"Id")});");
350351
}
351352

352353
protected virtual MethodSignatureModifiers GetMethodModifiers() => Public | Virtual;

src/AutoRest.CSharp/Mgmt/Generation/MgmtExtensionWriter.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using AutoRest.CSharp.Utilities;
1212
using AutoRest.CSharp.Output.Models.Requests;
1313
using static AutoRest.CSharp.Output.Models.MethodSignatureModifiers;
14+
using Azure.Core;
1415

1516
namespace AutoRest.CSharp.Mgmt.Generation
1617
{
@@ -89,8 +90,9 @@ protected override void WriteResourceCollectionEntry(ResourceCollection resource
8990
}
9091
}
9192

92-
protected override void WriteSingletonResourceEntry(Resource resource, string singletonResourceSuffix, MethodSignature signature)
93+
protected override void WriteSingletonResourceEntry(Resource resource, SingletonResourceSuffix singletonResourceSuffix, MethodSignature signature)
9394
{
95+
_writer.UseNamespace(typeof(ResourceIdentifier).Namespace!);
9496
if (IsArmCore)
9597
{
9698
base.WriteSingletonResourceEntry(resource, singletonResourceSuffix, signature);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using AutoRest.CSharp.Generation.Writers;
8+
using Azure.Core;
9+
10+
namespace AutoRest.CSharp.Mgmt.Models
11+
{
12+
internal class SingletonResourceSuffix
13+
{
14+
public static SingletonResourceSuffix Parse(string[] segments)
15+
{
16+
// put the segments in pairs
17+
var pairs = new List<(string Key, string Value)>();
18+
for (int i = 0; i < segments.Length; i += 2)
19+
{
20+
pairs.Add((segments[i], segments[i + 1]));
21+
}
22+
23+
return new SingletonResourceSuffix(pairs);
24+
}
25+
26+
private IReadOnlyList<(string Key, string Value)> _pairs;
27+
28+
private SingletonResourceSuffix(IReadOnlyList<(string Key, string Value)> pairs)
29+
{
30+
_pairs = pairs;
31+
}
32+
33+
public FormattableString BuildResourceIdentifier(FormattableString originalId)
34+
{
35+
var list = new List<FormattableString>() { originalId };
36+
for (int i = 0; i < _pairs.Count; i++)
37+
{
38+
var key = _pairs[i].Key;
39+
var value = _pairs[i].Value;
40+
if (key == Segment.Providers)
41+
{
42+
// when we have a providers, we must have a next pair
43+
i++;
44+
var nextKey = _pairs[i].Key;
45+
var nextValue = _pairs[i].Value;
46+
list.Add($"{nameof(ResourceIdentifier.AppendProviderResource)}({value:L}, {nextKey:L}, {nextValue:L})");
47+
}
48+
else
49+
{
50+
// if not, we just call the method to append this pair
51+
list.Add($"{nameof(ResourceIdentifier.AppendChildResource)}({key:L}, {value:L})");
52+
}
53+
}
54+
55+
return list.Join(".");
56+
}
57+
}
58+
}

src/AutoRest.CSharp/Mgmt/Output/Resource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ private static IEnumerable<Operation> GetClientOperations(OperationSet operation
170170

171171
public bool IsSingleton => SingletonResourceIdSuffix != null;
172172

173-
public string? SingletonResourceIdSuffix { get; }
173+
public SingletonResourceSuffix? SingletonResourceIdSuffix { get; }
174174

175175
private bool? _isTaggable;
176176
public bool IsTaggable => GetIsTaggable();
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License
3+
4+
using System;
5+
using AutoRest.CSharp.Generation.Writers;
6+
using AutoRest.CSharp.Mgmt.Models;
7+
using NUnit.Framework;
8+
9+
namespace AutoRest.TestServer.Tests.Mgmt.Unit
10+
{
11+
public class SingletonResourceSuffixTests
12+
{
13+
[TestCase("test/default", @"Id.AppendChildResource(""test"", ""default"")")]
14+
[TestCase("providers/Microsoft.Compute/test/default", @"Id.AppendProviderResource(""Microsoft.Compute"", ""test"", ""default"")")]
15+
[TestCase("providers/Microsoft.Compute/test1/name/test2/default", @"Id.AppendProviderResource(""Microsoft.Compute"", ""test1"", ""name"").AppendChildResource(""test2"", ""default"")")]
16+
[TestCase("providers/Microsoft.Compute/test1/name/test2/name2/test3/default", @"Id.AppendProviderResource(""Microsoft.Compute"", ""test1"", ""name"").AppendChildResource(""test2"", ""name2"").AppendChildResource(""test3"", ""default"")")]
17+
public void ValidateBuildResourceIdentifier(string suffixString, string expected)
18+
{
19+
var segments = suffixString.Split('/', StringSplitOptions.RemoveEmptyEntries);
20+
var suffix = SingletonResourceSuffix.Parse(segments);
21+
var result = suffix.BuildResourceIdentifier($"Id");
22+
var writer = new CodeWriter();
23+
Assert.AreEqual(expected, writer.Append(result).ToString(false).Trim());
24+
}
25+
}
26+
}

test/AutoRest.TestServer.Tests/Mgmt/Unit/StringExtensionsTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ namespace AutoRest.TestServer.Tests.Mgmt
99
{
1010
public class StringExtensionsTests
1111
{
12-
1312
[TestCase("MetadataRole", "MetadataRoles")]
1413
[TestCase("KeyInformation", "AllKeyInformation")]
1514
[TestCase("RoleMetadata", "AllRoleMetadata")]

0 commit comments

Comments
 (0)