Skip to content

Commit 36d875f

Browse files
Refactor provisioning CreateCSharpTypeCore (Azure#59150)
* Fix provisioning nullable type wrapping Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Document regular model test blocker Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Link regular model test blocker Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump provisioning generator dependencies Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump provisioning generator dependencies Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Avoid duplicating provisioning peer dependencies Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Avoid duplicating provisioning peer dependencies Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent d68e93e commit 36d875f

12 files changed

Lines changed: 1228 additions & 751 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<Solution>
22
<Project Path="Azure.Generator.Provisioning/src/Azure.Generator.Provisioning.csproj" />
3+
<Project Path="Azure.Generator.Provisioning/test/Azure.Generator.Provisioning.Tests.csproj" />
34
</Solution>

eng/packages/http-client-csharp-provisioning/generator/Azure.Generator.Provisioning/src/ProvisioningGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public ProvisioningGenerator(GeneratorContext context) : base(context)
4343
public override ProvisioningOutputLibrary OutputLibrary => _outputLibrary ??= new ProvisioningOutputLibrary();
4444

4545
/// <inheritdoc/>
46-
public override ManagementTypeFactory TypeFactory { get; }
46+
public override ProvisioningTypeFactory TypeFactory { get; }
4747

4848
/// <inheritdoc/>
4949
protected override void Configure()

eng/packages/http-client-csharp-provisioning/generator/Azure.Generator.Provisioning/src/ProvisioningTypeFactory.cs

Lines changed: 8 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Azure.Generator.Management;
55
using Azure.Generator.Provisioning.Primitives;
66
using Azure.Generator.Provisioning.Providers;
7+
using Azure.Generator.Provisioning.Utilities;
78
using Azure.Provisioning;
89
using Azure.Provisioning.Primitives;
910
using Microsoft.TypeSpec.Generator.Input;
@@ -56,48 +57,21 @@ protected override string BuildResourceProviderName()
5657
// Let the mgmt base resolve known system types (ResourceIdentifier, AzureLocation, etc.)
5758
var mgmtType = base.CreateCSharpTypeCore(inputType);
5859

59-
// For model types: if resolved to a system type that's a ProvisionableConstruct, return as-is.
60-
// Otherwise, for non-ProvisionableConstruct system types (ResponseError from mgmt),
61-
// wrap in BicepValue<T> since they can't be used with DefineModelProperty.
62-
if (inputType is InputModelType)
60+
if (mgmtType != null && BicepTypeHelpers.IsProvisioningType(mgmtType))
6361
{
64-
if (mgmtType != null && mgmtType.IsFrameworkType
65-
&& !typeof(ProvisionableConstruct).IsAssignableFrom(mgmtType.FrameworkType))
66-
{
67-
return new CSharpType(typeof(BicepValue<>), mgmtType);
68-
}
6962
return mgmtType;
7063
}
7164

72-
// For enum types, wrap in BicepValue<T>
73-
// System enums: mgmtType is the system CSharpType
74-
// Non-system enums: mgmtType is our ProvisioningEnumProvider.Type
75-
if (inputType is InputEnumType)
76-
{
77-
if (mgmtType != null)
78-
return new CSharpType(typeof(BicepValue<>), mgmtType);
79-
// Fallback: shouldn't happen now that ProvisioningEnumProvider is wired up
80-
return new CSharpType(typeof(BicepValue<>), typeof(string));
81-
}
82-
83-
// For array types, produce BicepList<T> — element type should NOT be BicepValue-wrapped
84-
if (inputType is InputArrayType arrayType)
65+
if (mgmtType != null && mgmtType.IsList)
8566
{
86-
var elementType = GetUnwrappedCSharpType(arrayType.ValueType);
87-
if (elementType != null)
88-
return new CSharpType(typeof(BicepList<>), elementType);
67+
return new CSharpType(typeof(BicepList<>), UnwrapBicepValue(mgmtType.Arguments[0]));
8968
}
9069

91-
// For dictionary types, produce BicepDictionary<TValue> — value type should NOT be BicepValue-wrapped
92-
if (inputType is InputDictionaryType dictType)
70+
if (mgmtType != null && mgmtType.IsDictionary)
9371
{
94-
var valueType = GetUnwrappedCSharpType(dictType.ValueType);
95-
if (valueType != null)
96-
return new CSharpType(typeof(BicepDictionary<>), valueType);
72+
return new CSharpType(typeof(BicepDictionary<>), UnwrapBicepValue(mgmtType.Arguments[1]));
9773
}
9874

99-
// For all other non-model, non-enum types resolved by base (primitives, date/time, duration, etc.),
100-
// wrap in BicepValue<T>
10175
if (mgmtType != null)
10276
{
10377
return new CSharpType(typeof(BicepValue<>), mgmtType);
@@ -106,31 +80,8 @@ protected override string BuildResourceProviderName()
10680
return mgmtType;
10781
}
10882

109-
/// <summary>
110-
/// Resolves an InputType to its raw CSharpType without BicepValue wrapping.
111-
/// Used for BicepList/BicepDictionary element types which handle wrapping internally.
112-
/// </summary>
113-
private CSharpType? GetUnwrappedCSharpType(InputType inputType)
114-
{
115-
// For model types, check provisioning mapping first, then fall back to base
116-
if (inputType is InputModelType inputModel)
117-
{
118-
if (KnownProvisioningTypes.TryGetProvisioningType(inputModel.CrossLanguageDefinitionId, out var provType))
119-
return provType;
120-
return base.CreateCSharpTypeCore(inputType) ?? CreateCSharpType(inputType);
121-
}
122-
123-
// For enum types, check provisioning mapping first, then fall back to base
124-
if (inputType is InputEnumType inputEnum)
125-
{
126-
if (KnownProvisioningTypes.TryGetProvisioningType(inputEnum.CrossLanguageDefinitionId, out var provEnumType))
127-
return provEnumType;
128-
return base.CreateCSharpTypeCore(inputType) ?? typeof(string);
129-
}
130-
131-
// For all other types, use the base resolution (returns raw .NET type)
132-
return base.CreateCSharpTypeCore(inputType);
133-
}
83+
private static CSharpType UnwrapBicepValue(CSharpType type)
84+
=> BicepTypeHelpers.IsBicepValueType(type) ? type.Arguments[0] : type;
13485

13586
/// <inheritdoc/>
13687
protected override ModelProvider? CreateModelCore(InputModelType model)

eng/packages/http-client-csharp-provisioning/generator/Azure.Generator.Provisioning/src/Utilities/BicepTypeHelpers.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,22 @@ public static bool IsModelType(CSharpType type)
2626
{
2727
if (IsBicepValueType(type) || IsBicepListType(type) || IsBicepDictionaryType(type))
2828
return false;
29+
if (type.IsEnum)
30+
return false;
2931
if (!type.IsFrameworkType)
3032
return true;
3133
return typeof(ProvisionableConstruct).IsAssignableFrom(type.FrameworkType);
3234
}
3335

36+
/// <summary>
37+
/// Returns true if the type is already represented as a provisioning type.
38+
/// </summary>
39+
public static bool IsProvisioningType(CSharpType type)
40+
=> IsBicepValueType(type)
41+
|| IsBicepListType(type)
42+
|| IsBicepDictionaryType(type)
43+
|| IsModelType(type);
44+
3445
/// <summary>
3546
/// Returns true if the type is <see cref="BicepValue{T}"/>.
3647
/// </summary>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>$(LtsTargetFramework)</TargetFrameworks>
5+
<IsGeneratorLibrary>false</IsGeneratorLibrary>
6+
<IsTestProject>true</IsTestProject>
7+
<ImplicitUsings>enable</ImplicitUsings>
8+
<Nullable>enable</Nullable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="NUnit" />
13+
<PackageReference Include="NUnit3TestAdapter" />
14+
<PackageReference Include="Microsoft.NET.Test.Sdk" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<ProjectReference Include="..\src\Azure.Generator.Provisioning.csproj" />
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<None Update="TestHelpers\Configuration.json">
23+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
24+
</None>
25+
</ItemGroup>
26+
27+
</Project>

0 commit comments

Comments
 (0)