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

Fix importing tagged unions from compiled JSON #13733

Merged
merged 1 commit into from Mar 28, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -773,5 +773,93 @@ public void User_defined_discriminated_objects_can_amend_resource_derived_discri
}
""");
}

[TestMethod]
public void Tagged_unions_can_be_imported_from_json_templates()
{
var test1Bicep = """
@export()
type testType = {
subType: subType[]
}

@discriminator('type')
type subType = testSub1 | testSub2 | testSub3

type testSub1 = {
type: '1'
subOption1: string
}

type testSub2 = {
type: '2'
subOption2: int
}

type testSub3 = {
type: '3'
subOption3: bool
}
""";

static string expectedSubTypeSchema(string extension) => $$"""
{
"type": "object",
"discriminator": {
"propertyName": "type",
"mapping": {
"1": {
"$ref": "#/definitions/_1.testSub1"
},
"2": {
"$ref": "#/definitions/_1.testSub2"
},
"3": {
"$ref": "#/definitions/_1.testSub3"
}
}
},
"metadata": {
"__bicep_imported_from!": {
"sourceTemplate": "test1.{{extension}}"
}
}
}
""";

static string mainTypesBicep(string extension) => $$"""
import { testType } from 'test1.{{extension}}'

@export()
type mainType = {
name: string
test: testType[]?
}
""";

var mainBicep = """
import { mainType } from 'main.types.bicep'

param main mainType

output mainOut object = main
""";

var resultFromBicep = CompilationHelper.Compile(
("test1.bicep", test1Bicep),
("main.types.bicep", mainTypesBicep("bicep")),
("main.bicep", mainBicep));

resultFromBicep.Template.Should().NotBeNull();
resultFromBicep.Template.Should().HaveJsonAtPath("$.definitions['_1.subType']", expectedSubTypeSchema("bicep"));

var resultFromJson = CompilationHelper.Compile(
("test1.json", CompilationHelper.Compile(test1Bicep).Template!.ToString()),
("main.types.bicep", mainTypesBicep("json")),
("main.bicep", mainBicep));

resultFromJson.Template.Should().NotBeNull();
resultFromJson.Template.Should().HaveJsonAtPath("$.definitions['_1.subType']", expectedSubTypeSchema("json"));
}
}
}
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Collections.Immutable;
using System.Linq;
using Azure.Deployments.Core.Definitions.Schema;
using Azure.Deployments.Core.Entities;
using Azure.Deployments.Expression.Engines;
Expand Down Expand Up @@ -361,6 +363,20 @@ private TypeExpression ConvertObjectNodeToTypeExpression(ITemplateSchemaNode sch
modifiers.Sealed);
}

if (schemaNode.Discriminator is { } discriminatorConstraint)
{
var unionMembers = discriminatorConstraint.Mapping.OrderByAscendingOrdinalInsensitively(kvp => kvp.Key)
.Select(kvp => ConvertToTypeExpression(kvp.Value))
.ToImmutableArray();

return new DiscriminatedObjectTypeExpression(sourceSyntax,
new(string.Empty,
TypeSymbolValidationFlags.Default,
discriminatorConstraint.PropertyName.Value,
unionMembers.Select(expression => expression.ExpressedType)),
unionMembers);
}

return new ObjectTypeExpression(sourceSyntax,
new(string.Empty,
TypeSymbolValidationFlags.Default,
Expand Down
Expand Up @@ -132,5 +132,13 @@ private static IEnumerable<ArmIdentifier> EnumerateReferencesUsedIn(ITemplateSch
yield return nested;
}
}

if (schemaNode.Discriminator is { } discriminatorConstraint)
{
foreach (var nested in discriminatorConstraint.Mapping.Values.SelectMany(EnumerateReferencesUsedIn))
{
yield return nested;
}
}
}
}