forked from Azure/azure-sdk-for-net
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement resource detection and generate ReourceData (Azure#47730)
- Loading branch information
Showing
19 changed files
with
547 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
eng/packages/http-client-csharp/generator/Azure.Generator/src/AzureOutputLibrary.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,83 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using Azure.Generator.Mgmt.Models; | ||
using Azure.Generator.Providers; | ||
using Azure.Generator.Utilities; | ||
using Microsoft.Generator.CSharp.ClientModel; | ||
using Microsoft.Generator.CSharp.Providers; | ||
using System.Collections.Generic; | ||
|
||
namespace Azure.Generator | ||
{ | ||
/// <inheritdoc/> | ||
public class AzureOutputLibrary : ScmOutputLibrary | ||
{ | ||
// TODO: categorize clients into operationSets, which contains operations sharing the same Path | ||
private Dictionary<string, OperationSet> _pathToOperationSetMap; | ||
private Dictionary<string, HashSet<OperationSet>> _resourceDataBySpecNameMap; | ||
|
||
/// <inheritdoc/> | ||
public AzureOutputLibrary() | ||
{ | ||
_pathToOperationSetMap = CategorizeClients(); | ||
_resourceDataBySpecNameMap = EnsureResourceDataMap(); | ||
} | ||
|
||
private Dictionary<string, HashSet<OperationSet>> EnsureResourceDataMap() | ||
{ | ||
var result = new Dictionary<string, HashSet<OperationSet>>(); | ||
foreach (var operationSet in _pathToOperationSetMap.Values) | ||
{ | ||
if (operationSet.TryGetResourceDataSchema(out var resourceSpecName, out var resourceSchema)) | ||
{ | ||
// if this operation set corresponds to a SDK resource, we add it to the map | ||
if (!result.TryGetValue(resourceSpecName!, out HashSet<OperationSet>? value)) | ||
{ | ||
value = new HashSet<OperationSet>(); | ||
result.Add(resourceSpecName!, value); | ||
} | ||
value.Add(operationSet); | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private Dictionary<string, OperationSet> CategorizeClients() | ||
{ | ||
var result = new Dictionary<string, OperationSet>(); | ||
foreach (var inputClient in AzureClientPlugin.Instance.InputLibrary.InputNamespace.Clients) | ||
{ | ||
var requestPathList = new HashSet<string>(); | ||
foreach (var operation in inputClient.Operations) | ||
{ | ||
var path = operation.GetHttpPath(); | ||
requestPathList.Add(path); | ||
if (result.TryGetValue(path, out var operationSet)) | ||
{ | ||
operationSet.Add(operation); | ||
} | ||
else | ||
{ | ||
operationSet = new OperationSet(path, inputClient) | ||
{ | ||
operation | ||
}; | ||
result.Add(path, operationSet); | ||
} | ||
} | ||
} | ||
|
||
// TODO: add operation set for the partial resources here | ||
|
||
return result; | ||
} | ||
|
||
/// <inheritdoc/> | ||
// TODO: generate resources and collections | ||
protected override TypeProvider[] BuildTypeProviders() => [.. base.BuildTypeProviders(), new RequestContextExtensionsDefinition()]; | ||
|
||
internal bool IsResource(string name) => _resourceDataBySpecNameMap.ContainsKey(name); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
115 changes: 115 additions & 0 deletions
115
eng/packages/http-client-csharp/generator/Azure.Generator/src/Mgmt/Models/OperationSet.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using Azure.Core; | ||
using Azure.Generator.Utilities; | ||
using Microsoft.Generator.CSharp.Input; | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
|
||
namespace Azure.Generator.Mgmt.Models | ||
{ | ||
/// <summary> | ||
/// An <see cref="OperationSet"/> represents a collection of <see cref="Operation"/> with the same request path. | ||
/// </summary> | ||
internal class OperationSet : IReadOnlyCollection<InputOperation>, IEquatable<OperationSet> | ||
{ | ||
private readonly InputClient? _inputClient; | ||
|
||
/// <summary> | ||
/// The raw request path of string of the operations in this <see cref="OperationSet"/> | ||
/// </summary> | ||
public string RequestPath { get; } | ||
|
||
/// <summary> | ||
/// The operation set | ||
/// </summary> | ||
private HashSet<InputOperation> _operations; | ||
|
||
public int Count => _operations.Count; | ||
|
||
public OperationSet(string requestPath, InputClient? inputClient) | ||
{ | ||
_inputClient = inputClient; | ||
RequestPath = requestPath; | ||
_operations = new HashSet<InputOperation>(); | ||
} | ||
|
||
/// <summary> | ||
/// Add a new operation to this <see cref="OperationSet"/> | ||
/// </summary> | ||
/// <param name="operation">The operation to be added</param> | ||
/// <exception cref="InvalidOperationException">when trying to add an operation with a different path from <see cref="RequestPath"/></exception> | ||
public void Add(InputOperation operation) | ||
{ | ||
var path = operation.GetHttpPath(); | ||
if (path != RequestPath) | ||
throw new InvalidOperationException($"Cannot add operation with path {path} to OperationSet with path {RequestPath}"); | ||
_operations.Add(operation); | ||
} | ||
|
||
public IEnumerator<InputOperation> GetEnumerator() => _operations.GetEnumerator(); | ||
|
||
IEnumerator IEnumerable.GetEnumerator() => _operations.GetEnumerator(); | ||
|
||
public override int GetHashCode() | ||
{ | ||
return RequestPath.GetHashCode(); | ||
} | ||
|
||
public bool Equals([AllowNull] OperationSet other) | ||
{ | ||
if (other is null) | ||
return false; | ||
|
||
return RequestPath == other.RequestPath; | ||
} | ||
|
||
/// <summary> | ||
/// Get the operation with the given verb. | ||
/// We cannot have two operations with the same verb under the same request path, therefore this method is only returning one operation or null | ||
/// </summary> | ||
/// <param name="method"></param> | ||
/// <returns></returns> | ||
public InputOperation? GetOperation(RequestMethod method) | ||
{ | ||
foreach (var operation in _operations) | ||
{ | ||
if (operation.HttpMethod == method.ToString()) | ||
return operation; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
|
||
|
||
private InputOperation? FindBestOperation() | ||
{ | ||
// first we try GET operation | ||
var getOperation = FindOperation(RequestMethod.Get); | ||
if (getOperation != null) | ||
return getOperation; | ||
// if no GET operation, we return PUT operation | ||
var putOperation = FindOperation(RequestMethod.Put); | ||
if (putOperation != null) | ||
return putOperation; | ||
|
||
// if no PUT or GET, we just return the first one | ||
return _operations.FirstOrDefault(); | ||
} | ||
|
||
public InputOperation? FindOperation(RequestMethod method) | ||
{ | ||
return this.FirstOrDefault(operation => operation.HttpMethod == method.ToString()); | ||
} | ||
|
||
public override string? ToString() | ||
{ | ||
return RequestPath; | ||
} | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
...ckages/http-client-csharp/generator/Azure.Generator/src/Providers/ResourceDataProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using Microsoft.Generator.CSharp.Input; | ||
using Microsoft.Generator.CSharp.Providers; | ||
using System.IO; | ||
|
||
namespace Azure.Generator.Providers | ||
{ | ||
internal class ResourceDataProvider : ModelProvider | ||
{ | ||
private readonly InputModelType _inputModel; | ||
|
||
public ResourceDataProvider(InputModelType inputModel) : base(inputModel) | ||
{ | ||
_inputModel = inputModel; | ||
} | ||
|
||
protected override string BuildName() => $"{base.BuildName()}Data"; | ||
|
||
protected override string BuildRelativeFilePath() => Path.Combine("src", "Generated", $"{Name}.cs"); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
...lient-csharp/generator/Azure.Generator/src/Providers/ResourceDataSerializationProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using Microsoft.Generator.CSharp.ClientModel.Providers; | ||
using Microsoft.Generator.CSharp.Input; | ||
using Microsoft.Generator.CSharp.Providers; | ||
using System.IO; | ||
|
||
namespace Azure.Generator.Providers | ||
{ | ||
internal class ResourceDataSerializationProvider : MrwSerializationTypeDefinition | ||
{ | ||
public ResourceDataSerializationProvider(InputModelType inputModel, ModelProvider modelProvider) : base(inputModel, modelProvider) | ||
{ | ||
} | ||
|
||
protected override string BuildName() => $"{base.BuildName()}Data"; | ||
|
||
protected override string BuildRelativeFilePath() => Path.Combine("src", "Generated", $"{Name}.Serialization.cs"); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
eng/packages/http-client-csharp/generator/Azure.Generator/src/Utilities/InputExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using Microsoft.Generator.CSharp.Input; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace Azure.Generator.Utilities | ||
{ | ||
internal static class InputExtensions | ||
{ | ||
/// <summary> | ||
/// Union all the properties on myself and all the properties from my parents | ||
/// </summary> | ||
/// <param name="inputModel"></param> | ||
/// <returns></returns> | ||
internal static IEnumerable<InputModelProperty> GetAllProperties(this InputModelType inputModel) | ||
{ | ||
return inputModel.GetAllBaseModels().SelectMany(parentInputModelType => parentInputModelType.Properties).Concat(inputModel.Properties); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
...ackages/http-client-csharp/generator/Azure.Generator/src/Utilities/OperationExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using Microsoft.Generator.CSharp.Input; | ||
using System; | ||
using System.Linq; | ||
|
||
namespace Azure.Generator.Utilities | ||
{ | ||
internal static class OperationExtensions | ||
{ | ||
public static string GetHttpPath(this InputOperation operation) | ||
{ | ||
var path = operation.Path; | ||
// Do not trim the tenant resource path '/'. | ||
return (path?.Length == 1 ? path : path?.TrimEnd('/')) ?? | ||
throw new InvalidOperationException($"Cannot get HTTP path from operation {operation.Name}"); | ||
} | ||
|
||
public static OperationResponse? GetServiceResponse(this InputOperation operation, int code = 200) | ||
{ | ||
return operation.Responses.FirstOrDefault(r => r.StatusCodes.Contains(code)); | ||
} | ||
} | ||
} |
Oops, something went wrong.