From 1d0dc60a4e7c96b2acc4602713e6054c6b23678f Mon Sep 17 00:00:00 2001 From: Jonathan Eskew Date: Thu, 28 Mar 2024 11:28:25 -0400 Subject: [PATCH] Apply `sealed` modifier to types loaded from ARM JSON only if `additionalProperties` was set to `false` in the source --- .../CompileTimeImportTests.cs | 54 +++++++++++++++++++ .../ArmDeclarationToExpressionConverter.cs | 16 +++--- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/src/Bicep.Core.IntegrationTests/CompileTimeImportTests.cs b/src/Bicep.Core.IntegrationTests/CompileTimeImportTests.cs index c6f48d5f239..fcb7635f427 100644 --- a/src/Bicep.Core.IntegrationTests/CompileTimeImportTests.cs +++ b/src/Bicep.Core.IntegrationTests/CompileTimeImportTests.cs @@ -2258,4 +2258,58 @@ public void Copy_index_argument_in_copy_variables_imported_from_json_is_replaced } """)); } + + [TestMethod] + public void Tuple_imported_from_json_is_recompiled_to_a_valid_schema() + { + var typesBicep = """ + @export() + type t = { + p: { + a: [ + { + b: string + c: string + } + ] + } + } + """; + + var expectedCompilationOfTupleA = """ + { + "type": "array", + "prefixItems": [ + { + "type": "object", + "properties": { + "b": { + "type": "string" + }, + "c": { + "type": "string" + } + } + } + ], + "items": false + } + """; + + var resultFromBicep = CompilationHelper.Compile( + ("types.bicep", typesBicep), + ("main.bicep", "import {t} from 'types.bicep'")); + + resultFromBicep.Should().NotHaveAnyCompilationBlockingDiagnostics(); + resultFromBicep.Template.Should().NotBeNull(); + resultFromBicep.Template.Should().HaveJsonAtPath("definitions.t.properties.p.properties.a", expectedCompilationOfTupleA); + + var resultFromJson = CompilationHelper.Compile( + ("types.json", CompilationHelper.Compile(typesBicep).Template!.ToString()), + ("main.bicep", "import {t} from 'types.json'")); + + resultFromJson.Should().NotHaveAnyCompilationBlockingDiagnostics(); + resultFromJson.Template.Should().NotBeNull(); + resultFromJson.Template.Should().HaveJsonAtPath("definitions.t.properties.p.properties.a", expectedCompilationOfTupleA); + } } diff --git a/src/Bicep.Core/Emit/CompileTimeImports/ArmDeclarationToExpressionConverter.cs b/src/Bicep.Core/Emit/CompileTimeImports/ArmDeclarationToExpressionConverter.cs index 18ed5c4c0af..dd916d818cf 100644 --- a/src/Bicep.Core/Emit/CompileTimeImports/ArmDeclarationToExpressionConverter.cs +++ b/src/Bicep.Core/Emit/CompileTimeImports/ArmDeclarationToExpressionConverter.cs @@ -134,28 +134,28 @@ private record TypeModifiers(Expression? Description, Expression? Sealed); private TypeModifiers GetTypeModifiers(ITemplateSchemaNode schemaNode) => new( - GetDescription(schemaNode) is string description ? ExpressionFactory.CreateStringLiteral(description, sourceSyntax) : null, - schemaNode.Metadata?.Value is JToken md && ConvertToExpression(ImmutableDictionary.Empty, md) is ObjectExpression @object + Description: GetDescription(schemaNode) is string description ? ExpressionFactory.CreateStringLiteral(description, sourceSyntax) : null, + Metadata: schemaNode.Metadata?.Value is JToken md && ConvertToExpression(ImmutableDictionary.Empty, md) is ObjectExpression @object ? ExcludingPropertiesNamed(@object, LanguageConstants.MetadataDescriptionPropertyName, LanguageConstants.MetadataExportedPropertyName) : null, - schemaNode.Type?.Value switch + Secure: schemaNode.Type?.Value switch { TemplateParameterType.SecureString or TemplateParameterType.SecureObject => ExpressionFactory.CreateBooleanLiteral(true, sourceSyntax), _ => null, }, - schemaNode.MinLength?.Value is long minLength + MinLength: schemaNode.MinLength?.Value is long minLength ? ExpressionFactory.CreateIntegerLiteral(minLength, sourceSyntax) : null, - schemaNode.MaxLength?.Value is long maxLength + MaxLength: schemaNode.MaxLength?.Value is long maxLength ? ExpressionFactory.CreateIntegerLiteral(maxLength, sourceSyntax) : null, - schemaNode.MinValue?.Value is long minValue + MinValue: schemaNode.MinValue?.Value is long minValue ? ExpressionFactory.CreateIntegerLiteral(minValue, sourceSyntax) : null, - schemaNode.MaxValue?.Value is long maxValue + MaxValue: schemaNode.MaxValue?.Value is long maxValue ? ExpressionFactory.CreateIntegerLiteral(maxValue, sourceSyntax) : null, - schemaNode.AdditionalProperties?.BooleanValue is false || schemaNode.Items?.BooleanValue is false + Sealed: schemaNode.AdditionalProperties?.BooleanValue is false ? ExpressionFactory.CreateBooleanLiteral(true, sourceSyntax) : null);