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 2d351bfc741..0de8306d920 100644 --- a/src/Bicep.Core/Emit/CompileTimeImports/ArmDeclarationToExpressionConverter.cs +++ b/src/Bicep.Core/Emit/CompileTimeImports/ArmDeclarationToExpressionConverter.cs @@ -136,28 +136,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);