diff --git a/src/Bicep.Core.IntegrationTests/NestedResourceTests.cs b/src/Bicep.Core.IntegrationTests/NestedResourceTests.cs index 6653153f0fc..689ae22cd40 100644 --- a/src/Bicep.Core.IntegrationTests/NestedResourceTests.cs +++ b/src/Bicep.Core.IntegrationTests/NestedResourceTests.cs @@ -828,7 +828,7 @@ public void Nested_resource_detects_invalid_child_resource_literal_names() } resource res3 'child' = { - name: '${res1.name}/res2' + name: '${res1.name}/res3' } } "); diff --git a/src/Bicep.Core.IntegrationTests/ParentPropertyResourceTests.cs b/src/Bicep.Core.IntegrationTests/ParentPropertyResourceTests.cs index 4fc110a34b3..86358d566d0 100644 --- a/src/Bicep.Core.IntegrationTests/ParentPropertyResourceTests.cs +++ b/src/Bicep.Core.IntegrationTests/ParentPropertyResourceTests.cs @@ -409,7 +409,7 @@ public void Parent_property_detects_invalid_child_resource_literal_names() resource res3 'Microsoft.Rp1/resource1/child2@2020-06-01' = { parent: res1 - name: '${res1.name}/res2' + name: '${res1.name}/res3' } "); diff --git a/src/Bicep.Core.IntegrationTests/ScenarioTests.cs b/src/Bicep.Core.IntegrationTests/ScenarioTests.cs index 55bcf8e4f96..e75559e5eaf 100644 --- a/src/Bicep.Core.IntegrationTests/ScenarioTests.cs +++ b/src/Bicep.Core.IntegrationTests/ScenarioTests.cs @@ -3097,11 +3097,11 @@ public void Test_Issue_3169_3() } resource existingStg 'Microsoft.Storage/storageAccounts@2021-04-01' existing = { - name: newStg.name + name: uniqueString(newStg.name) } resource newStg2 'Microsoft.Storage/storageAccounts@2021-04-01' = { - name: existingStg.name + name: uniqueString(existingStg.name) kind: 'BlobStorage' location: resourceGroup().location sku: { @@ -3110,7 +3110,7 @@ public void Test_Issue_3169_3() } "); result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); - result.Template.Should().HaveValueAtPath("$.resources[?(@.kind == 'BlobStorage')].name", "test"); + result.Template.Should().HaveValueAtPath("$.resources[?(@.kind == 'BlobStorage')].name", "[uniqueString(uniqueString('test'))]"); } /// @@ -6803,4 +6803,147 @@ public void Test_Issue16230() result.Template.Should().NotBeNull(); result.Template.Should().HaveJsonAtPath("$.resources[?(@.name == 'bar')].dependsOn", "[\"identity::federation\"]"); } + + // https://github.com/azure/bicep/issues/1410 + [TestMethod] + public void Mutually_exclusive_but_duplicative_resources_are_permitted() + { + var result = CompilationHelper.Compile(""" + param createMode 'GeoRestore' | 'Replica' = 'GeoRestore' + + resource postgres 'microsoft.dbforpostgresql/servers@2017-12-01' = if (createMode == 'GeoRestore') { + name: 'foo' + location: 'eastus' + properties: { + createMode: 'GeoRestore' + sourceServerId: '' + + } + } + + resource postgres2 'microsoft.dbforpostgresql/servers@2017-12-01' = if (createMode == 'Replica') { + name: 'foo' + location: 'eastus' + properties: { + createMode: 'Replica' + sourceServerId: '' + } + } + """); + + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); + } + + // https://github.com/azure/bicep/issues/1410 + [TestMethod] + public void Resources_with_the_same_name_but_different_types_are_permitted() + { + var result = CompilationHelper.Compile(""" + resource postgres 'microsoft.dbforpostgresql/servers@2017-12-01' = { + name: 'foo' + location: 'eastus' + properties: { + createMode: 'GeoRestore' + sourceServerId: '' + + } + } + + resource postgres2 'microsoft.dbforpostgresql/flexibleServers@2021-06-01' = { + name: 'foo' + location: 'eastus' + properties: { + createMode: 'Replica' + sourceServerResourceId: '' + } + } + """); + + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); + } + + // https://github.com/azure/bicep/issues/1410 + [TestMethod] + public void Resources_with_the_same_name_but_different_scopes_are_permitted() + { + var result = CompilationHelper.Compile(""" + resource postgres 'microsoft.dbforpostgresql/servers@2017-12-01' existing = { + name: 'foo' + scope: resourceGroup('otherRg') + } + + resource postgres2 'microsoft.dbforpostgresql/servers@2017-12-01' = { + name: 'foo' + location: 'eastus' + properties: { + createMode: 'Replica' + sourceServerId: '' + } + } + """); + + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); + } + + // https://github.com/azure/bicep/issues/1410 + [TestMethod] + public void Modules_with_the_same_name_are_not_permitted() + { + var result = CompilationHelper.Compile( + ("main.bicep", """ + module foo1 'empty.bicep' = { + name: 'foo' + } + + module foo2 'empty.bicep' = { + name: 'foo' + } + """), + ("empty.bicep", string.Empty)); + + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] + { + ("BCP122", DiagnosticLevel.Error, "Modules: \"foo1\", \"foo2\" are defined with this same name and this same scope in a file. Rename them or split into different modules."), + ("BCP122", DiagnosticLevel.Error, "Modules: \"foo1\", \"foo2\" are defined with this same name and this same scope in a file. Rename them or split into different modules."), + }); + } + + // https://github.com/azure/bicep/issues/1410 + [TestMethod] + public void Mutually_exclusive_but_duplicative_modules_are_permitted() + { + var result = CompilationHelper.Compile( + ("main.bicep", """ + param condition bool + + module foo1 'empty.bicep' = if (condition) { + name: 'foo' + } + + module foo2 'empty.bicep' = if (!condition) { + name: 'foo' + } + """), + ("empty.bicep", string.Empty)); + } + + // https://github.com/azure/bicep/issues/1410 + [TestMethod] + public void Modules_with_the_same_name_but_different_scopes_are_permitted() + { + var result = CompilationHelper.Compile( + ("main.bicep", """ + module foo1 'empty.bicep' = { + name: 'foo' + } + + module foo2 'empty.bicep' = { + name: 'foo' + scope: resourceGroup('otherRg') + } + """), + ("empty.bicep", string.Empty)); + + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); + } } diff --git a/src/Bicep.Core.IntegrationTests/Scenarios/DiscriminatedObjectsTests.cs b/src/Bicep.Core.IntegrationTests/Scenarios/DiscriminatedObjectsTests.cs index 87f0eeb15f8..3312de89474 100644 --- a/src/Bicep.Core.IntegrationTests/Scenarios/DiscriminatedObjectsTests.cs +++ b/src/Bicep.Core.IntegrationTests/Scenarios/DiscriminatedObjectsTests.cs @@ -101,7 +101,7 @@ public void Test_Issue657_discriminators() // parent-property child resource resource test4 'Rp.A/parent/child@2020-10-01' = { parent: test - name: 'notAValidVal' + name: 'notAValidVal1' properties: { onlyOnEnum: true } @@ -110,13 +110,13 @@ public void Test_Issue657_discriminators() // 'existing' parent-property child resource resource test5 'Rp.A/parent/child@2020-10-01' existing = { parent: test - name: 'notAValidVal' + name: 'notAValidVal2' } ")); failedResult.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { - ("BCP036", DiagnosticLevel.Warning, "The property \"name\" expected a value of type \"'val1' | 'val2'\" but the provided value is of type \"'notAValidVal'\". If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues."), - ("BCP036", DiagnosticLevel.Warning, "The property \"name\" expected a value of type \"'val1' | 'val2'\" but the provided value is of type \"'notAValidVal'\". If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues."), + ("BCP036", DiagnosticLevel.Warning, "The property \"name\" expected a value of type \"'val1' | 'val2'\" but the provided value is of type \"'notAValidVal1'\". If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues."), + ("BCP036", DiagnosticLevel.Warning, "The property \"name\" expected a value of type \"'val1' | 'val2'\" but the provided value is of type \"'notAValidVal2'\". If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues."), }); } @@ -194,7 +194,7 @@ public void Test_Issue657_enum() // parent-property child resource resource test4 'Rp.A/parent/child@2020-10-01' = { parent: test - name: 'notAValidVal' + name: 'notAValidVal1' properties: { onlyOnEnum: true } @@ -203,13 +203,13 @@ public void Test_Issue657_enum() // 'existing' parent-property child resource resource test5 'Rp.A/parent/child@2020-10-01' existing = { parent: test - name: 'notAValidVal' + name: 'notAValidVal2' } ")); failedResult.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { - ("BCP036", DiagnosticLevel.Error, "The property \"name\" expected a value of type \"'val1' | 'val2'\" but the provided value is of type \"'notAValidVal'\"."), - ("BCP036", DiagnosticLevel.Error, "The property \"name\" expected a value of type \"'val1' | 'val2'\" but the provided value is of type \"'notAValidVal'\"."), + ("BCP036", DiagnosticLevel.Error, "The property \"name\" expected a value of type \"'val1' | 'val2'\" but the provided value is of type \"'notAValidVal1'\"."), + ("BCP036", DiagnosticLevel.Error, "The property \"name\" expected a value of type \"'val1' | 'val2'\" but the provided value is of type \"'notAValidVal2'\"."), }); } diff --git a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.bicep b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.bicep index 81133bae774..bab607bbebe 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.bicep @@ -53,7 +53,7 @@ resource resD 'My.Rp/myResourceType/childType@2020-01-01' = { } resource resE 'My.Rp/myResourceType/childType@2020-01-01' = { - name: 'resC/resD' + name: 'resC/resD_2' properties: { resDRef: resD.id } diff --git a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.diagnostics.bicep b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.diagnostics.bicep index 9f6c7d0f474..f49f77c60b8 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.diagnostics.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.diagnostics.bicep @@ -59,8 +59,8 @@ resource resD 'My.Rp/myResourceType/childType@2020-01-01' = { resource resE 'My.Rp/myResourceType/childType@2020-01-01' = { //@[14:57) [BCP081 (Warning)] Resource type "My.Rp/myResourceType/childType@2020-01-01" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'My.Rp/myResourceType/childType@2020-01-01'| - name: 'resC/resD' -//@[08:19) [use-parent-property (Warning)] Resource "resE" has its name formatted as a child of resource "resC". The syntax can be simplified by using the parent property. (bicep core linter https://aka.ms/bicep/linter/use-parent-property) |'resC/resD'| + name: 'resC/resD_2' +//@[08:21) [use-parent-property (Warning)] Resource "resE" has its name formatted as a child of resource "resC". The syntax can be simplified by using the parent property. (bicep core linter https://aka.ms/bicep/linter/use-parent-property) |'resC/resD_2'| properties: { resDRef: resD.id } diff --git a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.formatted.bicep b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.formatted.bicep index e5d995bdf24..e730ac53a12 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.formatted.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.formatted.bicep @@ -52,7 +52,7 @@ resource resD 'My.Rp/myResourceType/childType@2020-01-01' = { } resource resE 'My.Rp/myResourceType/childType@2020-01-01' = { - name: 'resC/resD' + name: 'resC/resD_2' properties: { resDRef: resD.id } diff --git a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.ir.bicep b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.ir.bicep index d28c369048a..301e3831173 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.ir.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.ir.bicep @@ -1,5 +1,5 @@ param deployTimeParam string = 'steve' -//@[00:1098) ProgramExpression +//@[00:1100) ProgramExpression //@[00:0038) ├─DeclaredParameterExpression { Name = deployTimeParam } //@[22:0028) | ├─AmbientTypeReferenceExpression { Name = string } //@[31:0038) | └─StringLiteralExpression { Value = steve } @@ -143,9 +143,9 @@ resource resD 'My.Rp/myResourceType/childType@2020-01-01' = { } resource resE 'My.Rp/myResourceType/childType@2020-01-01' = { -//@[00:0124) ├─DeclaredResourceExpression -//@[60:0124) | ├─ObjectExpression - name: 'resC/resD' +//@[00:0126) ├─DeclaredResourceExpression +//@[60:0126) | ├─ObjectExpression + name: 'resC/resD_2' properties: { //@[02:0040) | | └─ObjectPropertyExpression //@[02:0012) | | ├─StringLiteralExpression { Value = properties } diff --git a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.json b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.json index abf4b436848..36bcd1fa2b4 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.json +++ b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "dev", - "templateHash": "10969660194523330241" + "templateHash": "9865822508247546164" } }, "parameters": { @@ -80,7 +80,7 @@ { "type": "My.Rp/myResourceType/childType", "apiVersion": "2020-01-01", - "name": "resC/resD", + "name": "resC/resD_2", "properties": { "resDRef": "[resourceId('My.Rp/myResourceType/childType', split(format('{0}/resD', 'resC'), '/')[0], split(format('{0}/resD', 'resC'), '/')[1])]" }, diff --git a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.sourcemap.bicep b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.sourcemap.bicep index 2501337786e..3248b8c99ac 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.sourcemap.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.sourcemap.bicep @@ -128,12 +128,12 @@ resource resE 'My.Rp/myResourceType/childType@2020-01-01' = { //@ { //@ "type": "My.Rp/myResourceType/childType", //@ "apiVersion": "2020-01-01", -//@ "name": "resC/resD", +//@ "name": "resC/resD_2", //@ "dependsOn": [ //@ "[resourceId('My.Rp/myResourceType/childType', split(format('{0}/resD', 'resC'), '/')[0], split(format('{0}/resD', 'resC'), '/')[1])]" //@ ] //@ } - name: 'resC/resD' + name: 'resC/resD_2' properties: { //@ "properties": { //@ }, diff --git a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.symbolicnames.json b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.symbolicnames.json index 546da5072cf..df8eb93f54c 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.symbolicnames.json +++ b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.symbolicnames.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "dev", - "templateHash": "13967933445482532999" + "templateHash": "12971250390483085890" } }, "parameters": { @@ -81,7 +81,7 @@ "resE": { "type": "My.Rp/myResourceType/childType", "apiVersion": "2020-01-01", - "name": "resC/resD", + "name": "resC/resD_2", "properties": { "resDRef": "[resourceId('My.Rp/myResourceType/childType', split(format('{0}/resD', 'resC'), '/')[0], split(format('{0}/resD', 'resC'), '/')[1])]" }, diff --git a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.symbols.bicep b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.symbols.bicep index 29674fc42c4..3fa4255e538 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.symbols.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.symbols.bicep @@ -64,8 +64,8 @@ resource resD 'My.Rp/myResourceType/childType@2020-01-01' = { } resource resE 'My.Rp/myResourceType/childType@2020-01-01' = { -//@[9:13) Resource resE. Type: My.Rp/myResourceType/childType@2020-01-01. Declaration start char: 0, length: 124 - name: 'resC/resD' +//@[9:13) Resource resE. Type: My.Rp/myResourceType/childType@2020-01-01. Declaration start char: 0, length: 126 + name: 'resC/resD_2' properties: { resDRef: resD.id } diff --git a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.syntax.bicep b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.syntax.bicep index e3984437429..fb0c8e92cd0 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.syntax.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.syntax.bicep @@ -1,5 +1,5 @@ param deployTimeParam string = 'steve' -//@[00:1098) ProgramSyntax +//@[00:1100) ProgramSyntax //@[00:0038) ├─ParameterDeclarationSyntax //@[00:0005) | ├─Token(Identifier) |param| //@[06:0021) | ├─IdentifierSyntax @@ -392,24 +392,24 @@ resource resD 'My.Rp/myResourceType/childType@2020-01-01' = { //@[01:0003) ├─Token(NewLine) |\n\n| resource resE 'My.Rp/myResourceType/childType@2020-01-01' = { -//@[00:0124) ├─ResourceDeclarationSyntax +//@[00:0126) ├─ResourceDeclarationSyntax //@[00:0008) | ├─Token(Identifier) |resource| //@[09:0013) | ├─IdentifierSyntax //@[09:0013) | | └─Token(Identifier) |resE| //@[14:0057) | ├─StringSyntax //@[14:0057) | | └─Token(StringComplete) |'My.Rp/myResourceType/childType@2020-01-01'| //@[58:0059) | ├─Token(Assignment) |=| -//@[60:0124) | └─ObjectSyntax +//@[60:0126) | └─ObjectSyntax //@[60:0061) | ├─Token(LeftBrace) |{| //@[61:0062) | ├─Token(NewLine) |\n| - name: 'resC/resD' -//@[02:0019) | ├─ObjectPropertySyntax + name: 'resC/resD_2' +//@[02:0021) | ├─ObjectPropertySyntax //@[02:0006) | | ├─IdentifierSyntax //@[02:0006) | | | └─Token(Identifier) |name| //@[06:0007) | | ├─Token(Colon) |:| -//@[08:0019) | | └─StringSyntax -//@[08:0019) | | └─Token(StringComplete) |'resC/resD'| -//@[19:0020) | ├─Token(NewLine) |\n| +//@[08:0021) | | └─StringSyntax +//@[08:0021) | | └─Token(StringComplete) |'resC/resD_2'| +//@[21:0022) | ├─Token(NewLine) |\n| properties: { //@[02:0040) | ├─ObjectPropertySyntax //@[02:0012) | | ├─IdentifierSyntax diff --git a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.tokens.bicep b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.tokens.bicep index ae7f4900c08..5298a303ac7 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.tokens.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Dependencies_LF/main.tokens.bicep @@ -251,11 +251,11 @@ resource resE 'My.Rp/myResourceType/childType@2020-01-01' = { //@[58:59) Assignment |=| //@[60:61) LeftBrace |{| //@[61:62) NewLine |\n| - name: 'resC/resD' + name: 'resC/resD_2' //@[02:06) Identifier |name| //@[06:07) Colon |:| -//@[08:19) StringComplete |'resC/resD'| -//@[19:20) NewLine |\n| +//@[08:21) StringComplete |'resC/resD_2'| +//@[21:22) NewLine |\n| properties: { //@[02:12) Identifier |properties| //@[12:13) Colon |:| diff --git a/src/Bicep.Core.Samples/Files/baselines/InvalidModules_LF/main.diagnostics.bicep b/src/Bicep.Core.Samples/Files/baselines/InvalidModules_LF/main.diagnostics.bicep index dddb242d351..40893ebdb76 100644 --- a/src/Bicep.Core.Samples/Files/baselines/InvalidModules_LF/main.diagnostics.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/InvalidModules_LF/main.diagnostics.bicep @@ -159,7 +159,7 @@ module modANoName './modulea.bicep' = if ({ 'a': b }.a == true) { module modANoInputs './modulea.bicep' = { //@[007:019) [BCP035 (Error)] The specified "module" declaration is missing the following required properties: "params". (bicep https://aka.ms/bicep/core-diagnostics#BCP035) |modANoInputs| name: 'modANoInputs' -//@[008:022) [BCP122 (Error)] Modules: "modANoInputs", "modANoInputsWithCondition", "modAEmptyInputs", "modAEmptyInputsWithCondition" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |'modANoInputs'| +//@[008:022) [BCP122 (Error)] Modules: "modANoInputs", "modANoInputsWithCondition", "modAEmptyInputs" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |'modANoInputs'| // #completionTest(0,1,2) -> moduleATopLevelPropertiesMinusName } @@ -169,14 +169,14 @@ module modANoInputsWithCondition './modulea.bicep' = if (length([ 'foo' ]) == 1) { name: 'modANoInputs' -//@[008:022) [BCP122 (Error)] Modules: "modANoInputs", "modANoInputsWithCondition", "modAEmptyInputs", "modAEmptyInputsWithCondition" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |'modANoInputs'| +//@[008:022) [BCP122 (Error)] Modules: "modANoInputs", "modANoInputsWithCondition", "modAEmptyInputs" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |'modANoInputs'| // #completionTest(0,1,2) -> moduleAWithConditionTopLevelPropertiesMinusName } module modAEmptyInputs './modulea.bicep' = { name: 'modANoInputs' -//@[008:022) [BCP122 (Error)] Modules: "modANoInputs", "modANoInputsWithCondition", "modAEmptyInputs", "modAEmptyInputsWithCondition" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |'modANoInputs'| +//@[008:022) [BCP122 (Error)] Modules: "modANoInputs", "modANoInputsWithCondition", "modAEmptyInputs" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |'modANoInputs'| params: { //@[002:008) [BCP035 (Error)] The specified "object" declaration is missing the following required properties: "arrayParam", "objParam", "stringParamB". (bicep https://aka.ms/bicep/core-diagnostics#BCP035) |params| // #completionTest(0,1,2,3,4) -> moduleAParams @@ -186,7 +186,6 @@ module modAEmptyInputs './modulea.bicep' = { module modAEmptyInputsWithCondition './modulea.bicep' = if (1 + 2 == 2) { name: 'modANoInputs' -//@[008:022) [BCP122 (Error)] Modules: "modANoInputs", "modANoInputsWithCondition", "modAEmptyInputs", "modAEmptyInputsWithCondition" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |'modANoInputs'| params: { //@[002:008) [BCP035 (Error)] The specified "object" declaration is missing the following required properties: "arrayParam", "objParam", "stringParamB". (bicep https://aka.ms/bicep/core-diagnostics#BCP035) |params| // #completionTest(0,1,2,3,4) -> moduleAWithConditionParams @@ -313,11 +312,13 @@ module runtimeValidModule1 'empty.bicep' = { module runtimeInvalidModule1 'empty.bicep' = { name: runtimeValidRes1.location +//@[008:033) [BCP122 (Error)] Modules: "runtimeInvalidModule1", "runtimeInvalidModule2" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |runtimeValidRes1.location| //@[008:033) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "module" type, which requires a value that can be calculated at the start of the deployment. Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeValidRes1.location| } module runtimeInvalidModule2 'empty.bicep' = { name: runtimeValidRes1['location'] +//@[008:036) [BCP122 (Error)] Modules: "runtimeInvalidModule1", "runtimeInvalidModule2" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |runtimeValidRes1['location']| //@[008:036) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "module" type, which requires a value that can be calculated at the start of the deployment. Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeValidRes1['location']| //@[024:036) [prefer-unquoted-property-names (Warning)] Property names that are valid identifiers should be declared without quotation marks and accessed using dot notation. (bicep core linter https://aka.ms/bicep/linter/prefer-unquoted-property-names) |['location']| } @@ -325,17 +326,20 @@ module runtimeInvalidModule2 'empty.bicep' = { module runtimeInvalidModule3 'empty.bicep' = { name: runtimeValidRes1.sku.name //@[008:028) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "module" type, which requires a value that can be calculated at the start of the deployment. Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeValidRes1.sku| +//@[008:033) [BCP122 (Error)] Modules: "runtimeInvalidModule3", "runtimeInvalidModule4", "runtimeInvalidModule5", "runtimeInvalidModule6" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |runtimeValidRes1.sku.name| } module runtimeInvalidModule4 'empty.bicep' = { name: runtimeValidRes1.sku['name'] //@[008:028) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "module" type, which requires a value that can be calculated at the start of the deployment. Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeValidRes1.sku| +//@[008:036) [BCP122 (Error)] Modules: "runtimeInvalidModule3", "runtimeInvalidModule4", "runtimeInvalidModule5", "runtimeInvalidModule6" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |runtimeValidRes1.sku['name']| //@[028:036) [prefer-unquoted-property-names (Warning)] Property names that are valid identifiers should be declared without quotation marks and accessed using dot notation. (bicep core linter https://aka.ms/bicep/linter/prefer-unquoted-property-names) |['name']| } module runtimeInvalidModule5 'empty.bicep' = { name: runtimeValidRes1['sku']['name'] //@[008:031) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "module" type, which requires a value that can be calculated at the start of the deployment. Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeValidRes1['sku']| +//@[008:039) [BCP122 (Error)] Modules: "runtimeInvalidModule3", "runtimeInvalidModule4", "runtimeInvalidModule5", "runtimeInvalidModule6" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |runtimeValidRes1['sku']['name']| //@[024:031) [prefer-unquoted-property-names (Warning)] Property names that are valid identifiers should be declared without quotation marks and accessed using dot notation. (bicep core linter https://aka.ms/bicep/linter/prefer-unquoted-property-names) |['sku']| //@[031:039) [prefer-unquoted-property-names (Warning)] Property names that are valid identifiers should be declared without quotation marks and accessed using dot notation. (bicep core linter https://aka.ms/bicep/linter/prefer-unquoted-property-names) |['name']| } @@ -343,6 +347,7 @@ module runtimeInvalidModule5 'empty.bicep' = { module runtimeInvalidModule6 'empty.bicep' = { name: runtimeValidRes1['sku'].name //@[008:031) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "module" type, which requires a value that can be calculated at the start of the deployment. Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeValidRes1['sku']| +//@[008:036) [BCP122 (Error)] Modules: "runtimeInvalidModule3", "runtimeInvalidModule4", "runtimeInvalidModule5", "runtimeInvalidModule6" are defined with this same name and this same scope in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP122) |runtimeValidRes1['sku'].name| //@[024:031) [prefer-unquoted-property-names (Warning)] Property names that are valid identifiers should be declared without quotation marks and accessed using dot notation. (bicep core linter https://aka.ms/bicep/linter/prefer-unquoted-property-names) |['sku']| } diff --git a/src/Bicep.Core.Samples/Files/baselines/InvalidResources_CRLF/main.diagnostics.bicep b/src/Bicep.Core.Samples/Files/baselines/InvalidResources_CRLF/main.diagnostics.bicep index 7ee456fc232..fb495ccac0c 100644 --- a/src/Bicep.Core.Samples/Files/baselines/InvalidResources_CRLF/main.diagnostics.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/InvalidResources_CRLF/main.diagnostics.bicep @@ -100,7 +100,6 @@ resource foo 'Microsoft.Foo/foos@2020-02-02-alpha'= if { //@[013:050) [BCP081 (Warning)] Resource type "Microsoft.Foo/foos@2020-02-02-alpha" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Foo/foos@2020-02-02-alpha'| //@[055:056) [BCP018 (Error)] Expected the "(" character at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP018) |{| name: 'foo' -//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| } // empty condition @@ -110,7 +109,6 @@ resource foo 'Microsoft.Foo/foos@2020-02-02-alpha'= if () { //@[013:050) [BCP081 (Warning)] Resource type "Microsoft.Foo/foos@2020-02-02-alpha" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Foo/foos@2020-02-02-alpha'| //@[056:056) [BCP243 (Error)] Parentheses must contain exactly one expression. (bicep https://aka.ms/bicep/core-diagnostics#BCP243) || name: 'foo' -//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| } // #completionTest(57, 59) -> symbols @@ -119,7 +117,6 @@ resource foo 'Microsoft.Foo/foos@2020-02-02-alpha'= if ( ) { //@[013:050) [BCP081 (Warning)] Resource type "Microsoft.Foo/foos@2020-02-02-alpha" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Foo/foos@2020-02-02-alpha'| //@[056:056) [BCP243 (Error)] Parentheses must contain exactly one expression. (bicep https://aka.ms/bicep/core-diagnostics#BCP243) || name: 'foo' -//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| } // invalid condition type @@ -128,7 +125,6 @@ resource foo 'Microsoft.Foo/foos@2020-02-02-alpha'= if (123) { //@[013:050) [BCP081 (Warning)] Resource type "Microsoft.Foo/foos@2020-02-02-alpha" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Foo/foos@2020-02-02-alpha'| //@[055:060) [BCP046 (Error)] Expected a value of type "bool". (bicep https://aka.ms/bicep/core-diagnostics#BCP046) |(123)| name: 'foo' -//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| } // runtime functions are no allowed in resource conditions @@ -137,7 +133,6 @@ resource foo 'Microsoft.Foo/foos@2020-02-02-alpha' = if (reference('Micorosft.Ma //@[013:050) [BCP081 (Warning)] Resource type "Microsoft.Foo/foos@2020-02-02-alpha" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Foo/foos@2020-02-02-alpha'| //@[057:066) [BCP066 (Error)] Function "reference" is not valid at this location. It can only be used in resource declarations. (bicep https://aka.ms/bicep/core-diagnostics#BCP066) |reference| name: 'foo' -//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| } resource foo 'Microsoft.Foo/foos@2020-02-02-alpha' = if (listKeys('foo', '2020-05-01').bar == true) { @@ -145,7 +140,6 @@ resource foo 'Microsoft.Foo/foos@2020-02-02-alpha' = if (listKeys('foo', '2020-0 //@[013:050) [BCP081 (Warning)] Resource type "Microsoft.Foo/foos@2020-02-02-alpha" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Foo/foos@2020-02-02-alpha'| //@[057:065) [BCP066 (Error)] Function "listKeys" is not valid at this location. It can only be used in resource declarations. (bicep https://aka.ms/bicep/core-diagnostics#BCP066) |listKeys| name: 'foo' -//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| } // duplicate property at the top level @@ -174,7 +168,7 @@ resource foo 'Microsoft.Foo/foos@2020-02-02-alpha'= { //@[009:012) [BCP028 (Error)] Identifier "foo" is declared multiple times. Remove or rename the duplicates. (bicep https://aka.ms/bicep/core-diagnostics#BCP028) |foo| //@[013:050) [BCP081 (Warning)] Resource type "Microsoft.Foo/foos@2020-02-02-alpha" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Foo/foos@2020-02-02-alpha'| name: 'foo' -//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| +//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| properties: { foo: 'a' //@[004:007) [BCP025 (Error)] The property "foo" is declared multiple times in this object. Remove or rename the duplicate properties. (bicep https://aka.ms/bicep/core-diagnostics#BCP025) |foo| @@ -188,7 +182,7 @@ resource foo 'Microsoft.Foo/foos@2020-02-02-alpha'= { //@[009:012) [BCP028 (Error)] Identifier "foo" is declared multiple times. Remove or rename the duplicates. (bicep https://aka.ms/bicep/core-diagnostics#BCP028) |foo| //@[013:050) [BCP081 (Warning)] Resource type "Microsoft.Foo/foos@2020-02-02-alpha" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Foo/foos@2020-02-02-alpha'| name: 'foo' -//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| +//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| properties: { foo: 'a' //@[004:007) [BCP025 (Error)] The property "foo" is declared multiple times in this object. Remove or rename the duplicate properties. (bicep https://aka.ms/bicep/core-diagnostics#BCP025) |foo| @@ -203,7 +197,7 @@ resource foo 'Microsoft.Foo/foos@2020-02-02-alpha'= { //@[009:012) [BCP028 (Error)] Identifier "foo" is declared multiple times. Remove or rename the duplicates. (bicep https://aka.ms/bicep/core-diagnostics#BCP028) |foo| //@[013:050) [BCP081 (Warning)] Resource type "Microsoft.Foo/foos@2020-02-02-alpha" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Foo/foos@2020-02-02-alpha'| name: 'foo' -//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| +//@[008:013) [BCP121 (Error)] Resources: "foo", "foo", "foo" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'foo'| location: [ //@[012:018) [BCP036 (Warning)] The property "location" expected a value of type "string" but the provided value is of type "". If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues. (bicep https://aka.ms/bicep/core-diagnostics#BCP036) |[\r\n ]| ] @@ -384,11 +378,13 @@ resource runtimeValidRes5 'Microsoft.Advisor/recommendations/suppressions@2020-0 resource runtimeInvalidRes1 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { name: runtimeValidRes1.location +//@[008:033) [BCP121 (Error)] Resources: "runtimeInvalidRes1", "runtimeInvalidRes2", "runtimeInvalidRes8", "runtimeInvalidRes14" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |runtimeValidRes1.location| //@[008:033) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "Microsoft.Advisor/recommendations/suppressions" type, which requires a value that can be calculated at the start of the deployment. Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeValidRes1.location| } resource runtimeInvalidRes2 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { name: runtimeValidRes1['location'] +//@[008:036) [BCP121 (Error)] Resources: "runtimeInvalidRes1", "runtimeInvalidRes2", "runtimeInvalidRes8", "runtimeInvalidRes14" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |runtimeValidRes1['location']| //@[008:036) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "Microsoft.Advisor/recommendations/suppressions" type, which requires a value that can be calculated at the start of the deployment. Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeValidRes1['location']| //@[024:036) [prefer-unquoted-property-names (Warning)] Property names that are valid identifiers should be declared without quotation marks and accessed using dot notation. (bicep core linter https://aka.ms/bicep/linter/prefer-unquoted-property-names) |['location']| } @@ -426,11 +422,13 @@ resource runtimeInvalidRes6 'Microsoft.Advisor/recommendations/suppressions@2020 resource runtimeInvalidRes7 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { name: runtimeValidRes2.properties.azCliVersion //@[008:035) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "Microsoft.Advisor/recommendations/suppressions" type, which requires a value that can be calculated at the start of the deployment. Properties of runtimeValidRes2 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeValidRes2.properties| +//@[008:048) [BCP121 (Error)] Resources: "runtimeInvalidRes7", "runtimeInvalidRes15", "runtimeInvalidRes16" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |runtimeValidRes2.properties.azCliVersion| } var magicString1 = 'location' resource runtimeInvalidRes8 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { name: runtimeValidRes2['${magicString1}'] +//@[008:043) [BCP121 (Error)] Resources: "runtimeInvalidRes1", "runtimeInvalidRes2", "runtimeInvalidRes8", "runtimeInvalidRes14" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |runtimeValidRes2['${magicString1}']| //@[008:043) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "Microsoft.Advisor/recommendations/suppressions" type, which requires a value that can be calculated at the start of the deployment. Properties of runtimeValidRes2 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeValidRes2['${magicString1}']| } @@ -499,22 +497,26 @@ var runtimeValid = { resource runtimeInvalidRes14 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { name: runtimeInvalid.foo1 //@[008:022) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "Microsoft.Advisor/recommendations/suppressions" type, which requires a value that can be calculated at the start of the deployment. You are referencing a variable which cannot be calculated at the start ("runtimeInvalid" -> "runtimefoo1" -> "runtimeValidRes1"). Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeInvalid| +//@[008:027) [BCP121 (Error)] Resources: "runtimeInvalidRes1", "runtimeInvalidRes2", "runtimeInvalidRes8", "runtimeInvalidRes14" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |runtimeInvalid.foo1| } resource runtimeInvalidRes15 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { name: runtimeInvalid.foo2 //@[008:022) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "Microsoft.Advisor/recommendations/suppressions" type, which requires a value that can be calculated at the start of the deployment. You are referencing a variable which cannot be calculated at the start ("runtimeInvalid" -> "runtimefoo1" -> "runtimeValidRes1"). Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeInvalid| +//@[008:027) [BCP121 (Error)] Resources: "runtimeInvalidRes7", "runtimeInvalidRes15", "runtimeInvalidRes16" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |runtimeInvalid.foo2| } resource runtimeInvalidRes16 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { name: runtimeInvalid.foo3.properties.azCliVersion //@[008:022) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "Microsoft.Advisor/recommendations/suppressions" type, which requires a value that can be calculated at the start of the deployment. You are referencing a variable which cannot be calculated at the start ("runtimeInvalid" -> "runtimefoo1" -> "runtimeValidRes1"). Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeInvalid| +//@[008:051) [BCP121 (Error)] Resources: "runtimeInvalidRes7", "runtimeInvalidRes15", "runtimeInvalidRes16" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |runtimeInvalid.foo3.properties.azCliVersion| } // Note: This is actually a runtime valid value. However, other properties of the variable cannot be resolved, so we block this. resource runtimeInvalidRes17 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { name: runtimeInvalid.foo4 //@[008:022) [BCP120 (Error)] This expression is being used in an assignment to the "name" property of the "Microsoft.Advisor/recommendations/suppressions" type, which requires a value that can be calculated at the start of the deployment. You are referencing a variable which cannot be calculated at the start ("runtimeInvalid" -> "runtimefoo1" -> "runtimeValidRes1"). Properties of runtimeValidRes1 which can be calculated at the start include "apiVersion", "id", "name", "type". (bicep https://aka.ms/bicep/core-diagnostics#BCP120) |runtimeInvalid| +//@[008:027) [BCP121 (Error)] Resources: "runtimeInvalidRes17", "runtimeValidRes6" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |runtimeInvalid.foo4| } resource runtimeInvalidRes18 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { @@ -529,6 +531,7 @@ resource runtimeInvalidRes18 'Microsoft.Advisor/recommendations/suppressions@202 resource runtimeValidRes6 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { name: runtimeValid.foo1 +//@[008:025) [BCP121 (Error)] Resources: "runtimeInvalidRes17", "runtimeValidRes6" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |runtimeValid.foo1| } resource runtimeValidRes7 'Microsoft.Advisor/recommendations/suppressions@2020-01-01' = { @@ -1091,7 +1094,7 @@ Nested discriminator missing key */ resource nestedDiscriminatorMissingKey 'Microsoft.DocumentDB/databaseAccounts@2020-06-01-preview' = { name: 'test' -//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_if", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| +//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| location: 'l' properties: { //@[014:051) [BCP078 (Warning)] The property "createMode" requires a value of type "'Default' | 'Restore'", but none was supplied. (bicep https://aka.ms/bicep/core-diagnostics#BCP078) |{\r\n //createMode: 'Default'\r\n\r\n }| @@ -1117,7 +1120,6 @@ Nested discriminator missing key (conditional) */ resource nestedDiscriminatorMissingKey_if 'Microsoft.DocumentDB/databaseAccounts@2020-06-01-preview' = if(bool(1)) { name: 'test' -//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_if", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| location: 'l' properties: { //@[014:051) [BCP078 (Warning)] The property "createMode" requires a value of type "'Default' | 'Restore'", but none was supplied. (bicep https://aka.ms/bicep/core-diagnostics#BCP078) |{\r\n //createMode: 'Default'\r\n\r\n }| @@ -1144,7 +1146,7 @@ Nested discriminator missing key (loop) resource nestedDiscriminatorMissingKey_for 'Microsoft.DocumentDB/databaseAccounts@2020-06-01-preview' = [for thing in []: { //@[009:042) [BCP179 (Warning)] Unique resource or deployment name is required when looping. The loop item variable "thing" must be referenced in at least one of the value expressions of the following properties: "name" (bicep https://aka.ms/bicep/core-diagnostics#BCP179) |nestedDiscriminatorMissingKey_for| name: 'test' -//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_if", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| +//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| location: 'l' properties: { //@[014:051) [BCP078 (Warning)] The property "createMode" requires a value of type "'Default' | 'Restore'", but none was supplied. (bicep https://aka.ms/bicep/core-diagnostics#BCP078) |{\r\n //createMode: 'Default'\r\n\r\n }| @@ -1172,7 +1174,7 @@ Nested discriminator missing key (filtered loop) resource nestedDiscriminatorMissingKey_for_if 'Microsoft.DocumentDB/databaseAccounts@2020-06-01-preview' = [for thing in []: if(true) { //@[009:045) [BCP179 (Warning)] Unique resource or deployment name is required when looping. The loop item variable "thing" must be referenced in at least one of the value expressions of the following properties: "name" (bicep https://aka.ms/bicep/core-diagnostics#BCP179) |nestedDiscriminatorMissingKey_for_if| name: 'test' -//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_if", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| +//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| location: 'l' properties: { //@[014:051) [BCP078 (Warning)] The property "createMode" requires a value of type "'Default' | 'Restore'", but none was supplied. (bicep https://aka.ms/bicep/core-diagnostics#BCP078) |{\r\n //createMode: 'Default'\r\n\r\n }| @@ -1199,7 +1201,7 @@ Nested discriminator */ resource nestedDiscriminator 'Microsoft.DocumentDB/databaseAccounts@2020-06-01-preview' = { name: 'test' -//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_if", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| +//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| location: 'l' properties: { //@[002:012) [BCP035 (Warning)] The specified "object" declaration is missing the following required properties: "databaseAccountOfferType", "locations". If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues. (bicep https://aka.ms/bicep/core-diagnostics#BCP035) |properties| @@ -1236,7 +1238,7 @@ Nested discriminator (conditional) */ resource nestedDiscriminator_if 'Microsoft.DocumentDB/databaseAccounts@2020-06-01-preview' = if(true) { name: 'test' -//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_if", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| +//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| location: 'l' properties: { //@[002:012) [BCP035 (Warning)] The specified "object" declaration is missing the following required properties: "databaseAccountOfferType", "locations". If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues. (bicep https://aka.ms/bicep/core-diagnostics#BCP035) |properties| @@ -1275,7 +1277,7 @@ Nested discriminator (loop) resource nestedDiscriminator_for 'Microsoft.DocumentDB/databaseAccounts@2020-06-01-preview' = [for thing in []: { //@[009:032) [BCP179 (Warning)] Unique resource or deployment name is required when looping. The loop item variable "thing" must be referenced in at least one of the value expressions of the following properties: "name" (bicep https://aka.ms/bicep/core-diagnostics#BCP179) |nestedDiscriminator_for| name: 'test' -//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_if", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| +//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| location: 'l' properties: { //@[002:012) [BCP035 (Warning)] The specified "object" declaration is missing the following required properties: "databaseAccountOfferType", "locations". If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues. (bicep https://aka.ms/bicep/core-diagnostics#BCP035) |properties| @@ -1314,7 +1316,7 @@ Nested discriminator (filtered loop) resource nestedDiscriminator_for_if 'Microsoft.DocumentDB/databaseAccounts@2020-06-01-preview' = [for thing in []: if(true) { //@[009:035) [BCP179 (Warning)] Unique resource or deployment name is required when looping. The loop item variable "thing" must be referenced in at least one of the value expressions of the following properties: "name" (bicep https://aka.ms/bicep/core-diagnostics#BCP179) |nestedDiscriminator_for_if| name: 'test' -//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_if", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| +//@[008:014) [BCP121 (Error)] Resources: "nestedDiscriminatorMissingKey", "nestedDiscriminatorMissingKey_for", "nestedDiscriminatorMissingKey_for_if", "nestedDiscriminator", "nestedDiscriminator_if", "nestedDiscriminator_for", "nestedDiscriminator_for_if" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'test'| location: 'l' properties: { //@[002:012) [BCP035 (Warning)] The specified "object" declaration is missing the following required properties: "databaseAccountOfferType", "locations". If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues. (bicep https://aka.ms/bicep/core-diagnostics#BCP035) |properties| @@ -1954,6 +1956,7 @@ resource p7_res2 'Microsoft.Rp1/resource1/child2@2020-06-01' = { parent: p7_res1 name: 'res1/res2' //@[008:019) [BCP170 (Error)] Expected resource name to not contain any "/" characters. Child resources with a parent resource reference (via the parent property or via nesting) must not contain a fully-qualified name. (bicep https://aka.ms/bicep/core-diagnostics#BCP170) |'res1/res2'| +//@[008:019) [BCP121 (Error)] Resources: "p7_res2", "p7_res3" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'res1/res2'| } resource p7_res3 'Microsoft.Rp1/resource1/child2@2020-06-01' = { @@ -1961,6 +1964,7 @@ resource p7_res3 'Microsoft.Rp1/resource1/child2@2020-06-01' = { parent: p7_res1 name: '${p7_res1.name}/res2' //@[008:030) [BCP170 (Error)] Expected resource name to not contain any "/" characters. Child resources with a parent resource reference (via the parent property or via nesting) must not contain a fully-qualified name. (bicep https://aka.ms/bicep/core-diagnostics#BCP170) |'${p7_res1.name}/res2'| +//@[008:030) [BCP121 (Error)] Resources: "p7_res2", "p7_res3" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |'${p7_res1.name}/res2'| } // top-level resource with too many '/' characters diff --git a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.bicep b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.bicep index 4c4c4a4a143..d5213983822 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.bicep @@ -164,11 +164,11 @@ resource resourceA 'My.Rp/typeA@2020-01-01' = { } resource resourceB 'My.Rp/typeA/typeB@2020-01-01' = { - name: '${resourceA.name}/myName' + name: '${resourceA.name}/resourceB' } resource resourceC 'My.Rp/typeA/typeB@2020-01-01' = { - name: '${resourceA.name}/myName' + name: '${resourceA.name}/resourceC' properties: { aId: resourceA.id aType: resourceA.type @@ -439,7 +439,7 @@ output p1_subnet1id string = p1_subnet1.id // parent property with extension resource resource p2_res1 'Microsoft.Rp1/resource1@2020-06-01' = { - name: 'res1' + name: 'p2res1' } resource p2_res1child 'Microsoft.Rp1/resource1/child1@2020-06-01' = { @@ -464,7 +464,7 @@ output p2_res2childid string = p2_res2child.id // parent property with 'existing' resource resource p3_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { - name: 'res1' + name: 'p3res1' } resource p3_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' = { @@ -480,7 +480,7 @@ output p3_res1childid string = p3_child1.id // parent & child with 'existing' resource p4_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { scope: tenant() - name: 'res1' + name: 'p4res1' } resource p4_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' existing = { diff --git a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.diagnostics.bicep b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.diagnostics.bicep index eb306605c8c..194416f7ff1 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.diagnostics.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.diagnostics.bicep @@ -173,14 +173,14 @@ resource resourceA 'My.Rp/typeA@2020-01-01' = { resource resourceB 'My.Rp/typeA/typeB@2020-01-01' = { //@[19:49) [BCP081 (Warning)] Resource type "My.Rp/typeA/typeB@2020-01-01" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'My.Rp/typeA/typeB@2020-01-01'| - name: '${resourceA.name}/myName' -//@[08:34) [use-parent-property (Warning)] Resource "resourceB" has its name formatted as a child of resource "resourceA". The syntax can be simplified by using the parent property. (bicep core linter https://aka.ms/bicep/linter/use-parent-property) |'${resourceA.name}/myName'| + name: '${resourceA.name}/resourceB' +//@[08:37) [use-parent-property (Warning)] Resource "resourceB" has its name formatted as a child of resource "resourceA". The syntax can be simplified by using the parent property. (bicep core linter https://aka.ms/bicep/linter/use-parent-property) |'${resourceA.name}/resourceB'| } resource resourceC 'My.Rp/typeA/typeB@2020-01-01' = { //@[19:49) [BCP081 (Warning)] Resource type "My.Rp/typeA/typeB@2020-01-01" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'My.Rp/typeA/typeB@2020-01-01'| - name: '${resourceA.name}/myName' -//@[08:34) [use-parent-property (Warning)] Resource "resourceC" has its name formatted as a child of resource "resourceA". The syntax can be simplified by using the parent property. (bicep core linter https://aka.ms/bicep/linter/use-parent-property) |'${resourceA.name}/myName'| + name: '${resourceA.name}/resourceC' +//@[08:37) [use-parent-property (Warning)] Resource "resourceC" has its name formatted as a child of resource "resourceA". The syntax can be simplified by using the parent property. (bicep core linter https://aka.ms/bicep/linter/use-parent-property) |'${resourceA.name}/resourceC'| properties: { aId: resourceA.id aType: resourceA.type @@ -465,7 +465,7 @@ output p1_subnet1id string = p1_subnet1.id // parent property with extension resource resource p2_res1 'Microsoft.Rp1/resource1@2020-06-01' = { //@[17:53) [BCP081 (Warning)] Resource type "Microsoft.Rp1/resource1@2020-06-01" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Rp1/resource1@2020-06-01'| - name: 'res1' + name: 'p2res1' } resource p2_res1child 'Microsoft.Rp1/resource1/child1@2020-06-01' = { @@ -494,7 +494,7 @@ output p2_res2childid string = p2_res2child.id // parent property with 'existing' resource resource p3_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { //@[17:53) [BCP081 (Warning)] Resource type "Microsoft.Rp1/resource1@2020-06-01" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Rp1/resource1@2020-06-01'| - name: 'res1' + name: 'p3res1' } resource p3_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' = { @@ -512,7 +512,7 @@ output p3_res1childid string = p3_child1.id resource p4_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { //@[17:53) [BCP081 (Warning)] Resource type "Microsoft.Rp1/resource1@2020-06-01" does not have types available. Bicep is unable to validate resource properties prior to deployment, but this will not block the resource from being deployed. (bicep https://aka.ms/bicep/core-diagnostics#BCP081) |'Microsoft.Rp1/resource1@2020-06-01'| scope: tenant() - name: 'res1' + name: 'p4res1' } resource p4_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' existing = { diff --git a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.formatted.bicep b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.formatted.bicep index ea51d9c8b04..b0c0dd3ecb1 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.formatted.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.formatted.bicep @@ -164,11 +164,11 @@ resource resourceA 'My.Rp/typeA@2020-01-01' = { } resource resourceB 'My.Rp/typeA/typeB@2020-01-01' = { - name: '${resourceA.name}/myName' + name: '${resourceA.name}/resourceB' } resource resourceC 'My.Rp/typeA/typeB@2020-01-01' = { - name: '${resourceA.name}/myName' + name: '${resourceA.name}/resourceC' properties: { aId: resourceA.id aType: resourceA.type @@ -463,7 +463,7 @@ output p1_subnet1id string = p1_subnet1.id // parent property with extension resource resource p2_res1 'Microsoft.Rp1/resource1@2020-06-01' = { - name: 'res1' + name: 'p2res1' } resource p2_res1child 'Microsoft.Rp1/resource1/child1@2020-06-01' = { @@ -488,7 +488,7 @@ output p2_res2childid string = p2_res2child.id // parent property with 'existing' resource resource p3_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { - name: 'res1' + name: 'p3res1' } resource p3_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' = { @@ -504,7 +504,7 @@ output p3_res1childid string = p3_child1.id // parent & child with 'existing' resource p4_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { scope: tenant() - name: 'res1' + name: 'p4res1' } resource p4_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' existing = { diff --git a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.ir.bicep b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.ir.bicep index 08de05f1153..74d191a7b49 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.ir.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.ir.bicep @@ -1,5 +1,5 @@ -//@[000:14055) ProgramExpression +//@[000:14067) ProgramExpression //@[000:00000) | └─ResourceDependencyExpression [UNPARENTED] //@[000:00000) | └─ResourceReferenceExpression [UNPARENTED] //@[000:00000) | └─ResourceDependencyExpression [UNPARENTED] @@ -490,15 +490,15 @@ resource resourceA 'My.Rp/typeA@2020-01-01' = { } resource resourceB 'My.Rp/typeA/typeB@2020-01-01' = { -//@[000:00092) ├─DeclaredResourceExpression -//@[052:00092) | ├─ObjectExpression - name: '${resourceA.name}/myName' +//@[000:00095) ├─DeclaredResourceExpression +//@[052:00095) | ├─ObjectExpression + name: '${resourceA.name}/resourceB' } resource resourceC 'My.Rp/typeA/typeB@2020-01-01' = { -//@[000:00269) ├─DeclaredResourceExpression -//@[052:00269) | ├─ObjectExpression - name: '${resourceA.name}/myName' +//@[000:00272) ├─DeclaredResourceExpression +//@[052:00272) | ├─ObjectExpression + name: '${resourceA.name}/resourceC' properties: { //@[002:00175) | | └─ObjectPropertyExpression //@[002:00012) | | ├─StringLiteralExpression { Value = properties } @@ -1215,9 +1215,9 @@ output p1_subnet1id string = p1_subnet1.id // parent property with extension resource resource p2_res1 'Microsoft.Rp1/resource1@2020-06-01' = { -//@[000:00076) ├─DeclaredResourceExpression -//@[056:00076) | └─ObjectExpression - name: 'res1' +//@[000:00078) ├─DeclaredResourceExpression +//@[056:00078) | └─ObjectExpression + name: 'p2res1' } resource p2_res1child 'Microsoft.Rp1/resource1/child1@2020-06-01' = { @@ -1266,9 +1266,9 @@ output p2_res2childid string = p2_res2child.id // parent property with 'existing' resource resource p3_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { -//@[000:00085) ├─DeclaredResourceExpression -//@[065:00085) | └─ObjectExpression - name: 'res1' +//@[000:00087) ├─DeclaredResourceExpression +//@[065:00087) | └─ObjectExpression + name: 'p3res1' } resource p3_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' = { @@ -1303,10 +1303,10 @@ output p3_res1childid string = p3_child1.id // parent & child with 'existing' resource p4_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { -//@[000:00104) ├─DeclaredResourceExpression -//@[065:00104) | └─ObjectExpression +//@[000:00106) ├─DeclaredResourceExpression +//@[065:00106) | └─ObjectExpression scope: tenant() - name: 'res1' + name: 'p4res1' } resource p4_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' existing = { diff --git a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.json b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.json index a2862a5a01c..9640b8fd1f5 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.json +++ b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "dev", - "templateHash": "10727609760574024345" + "templateHash": "3313850547374953435" } }, "parameters": { @@ -37,7 +37,7 @@ "_siteApiVersion": "2019-08-01", "_siteType": "Microsoft.Web/sites", "resourceCRef": { - "id": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]" + "id": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceC', 'resourceA'), '/')[0], split(format('{0}/resourceC', 'resourceA'), '/')[1])]" }, "setResourceCRef": true, "myInterpKey": "abc", @@ -246,7 +246,7 @@ { "type": "My.Rp/typeA/typeB", "apiVersion": "2020-01-01", - "name": "[format('{0}/myName', 'resourceA')]", + "name": "[format('{0}/resourceB', 'resourceA')]", "dependsOn": [ "[resourceId('My.Rp/typeA', 'resourceA')]" ] @@ -254,17 +254,17 @@ { "type": "My.Rp/typeA/typeB", "apiVersion": "2020-01-01", - "name": "[format('{0}/myName', 'resourceA')]", + "name": "[format('{0}/resourceC', 'resourceA')]", "properties": { "aId": "[resourceId('My.Rp/typeA', 'resourceA')]", "aType": "My.Rp/typeA", "aName": "resourceA", "aApiVersion": "2020-01-01", - "bProperties": "[reference(resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1]), '2020-01-01')]" + "bProperties": "[reference(resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceB', 'resourceA'), '/')[0], split(format('{0}/resourceB', 'resourceA'), '/')[1]), '2020-01-01')]" }, "dependsOn": [ "[resourceId('My.Rp/typeA', 'resourceA')]", - "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]" + "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceB', 'resourceA'), '/')[0], split(format('{0}/resourceB', 'resourceA'), '/')[1])]" ] }, { @@ -274,9 +274,9 @@ "properties": { "runtime": [ { - "bId": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]", + "bId": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceB', 'resourceA'), '/')[0], split(format('{0}/resourceB', 'resourceA'), '/')[1])]", "bType": "My.Rp/typeA/typeB", - "bName": "[format('{0}/myName', 'resourceA')]", + "bName": "[format('{0}/resourceB', 'resourceA')]", "bApiVersion": "2020-01-01", "aKind": "[reference(resourceId('My.Rp/typeA', 'resourceA'), '2020-01-01', 'full').kind]" } @@ -285,8 +285,8 @@ }, "dependsOn": [ "[resourceId('My.Rp/typeA', 'resourceA')]", - "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]", - "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]" + "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceB', 'resourceA'), '/')[0], split(format('{0}/resourceB', 'resourceA'), '/')[1])]", + "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceC', 'resourceA'), '/')[0], split(format('{0}/resourceC', 'resourceA'), '/')[1])]" ] }, { @@ -595,38 +595,38 @@ { "type": "Microsoft.Rp1/resource1", "apiVersion": "2020-06-01", - "name": "res1" + "name": "p2res1" }, { "type": "Microsoft.Rp1/resource1/child1", "apiVersion": "2020-06-01", - "name": "[format('{0}/{1}', 'res1', 'child1')]", + "name": "[format('{0}/{1}', 'p2res1', 'child1')]", "dependsOn": [ - "[resourceId('Microsoft.Rp1/resource1', 'res1')]" + "[resourceId('Microsoft.Rp1/resource1', 'p2res1')]" ] }, { "type": "Microsoft.Rp2/resource2", "apiVersion": "2020-06-01", - "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'res1', 'child1')]", + "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'p2res1', 'child1')]", "name": "res2", "dependsOn": [ - "[resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1')]" + "[resourceId('Microsoft.Rp1/resource1/child1', 'p2res1', 'child1')]" ] }, { "type": "Microsoft.Rp2/resource2/child2", "apiVersion": "2020-06-01", - "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'res1', 'child1')]", + "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'p2res1', 'child1')]", "name": "[format('{0}/{1}', 'res2', 'child2')]", "dependsOn": [ - "[extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), 'Microsoft.Rp2/resource2', 'res2')]" + "[extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'p2res1', 'child1'), 'Microsoft.Rp2/resource2', 'res2')]" ] }, { "type": "Microsoft.Rp1/resource1/child1", "apiVersion": "2020-06-01", - "name": "[format('{0}/{1}', 'res1', 'child1')]" + "name": "[format('{0}/{1}', 'p3res1', 'child1')]" }, { "type": "Microsoft.Sql/servers", @@ -668,7 +668,7 @@ }, "p2_res2childprop": { "type": "string", - "value": "[reference(extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), 'Microsoft.Rp2/resource2/child2', 'res2', 'child2'), '2020-06-01').someProp]" + "value": "[reference(extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'p2res1', 'child1'), 'Microsoft.Rp2/resource2/child2', 'res2', 'child2'), '2020-06-01').someProp]" }, "p2_res2childname": { "type": "string", @@ -680,11 +680,11 @@ }, "p2_res2childid": { "type": "string", - "value": "[extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), 'Microsoft.Rp2/resource2/child2', 'res2', 'child2')]" + "value": "[extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'p2res1', 'child1'), 'Microsoft.Rp2/resource2/child2', 'res2', 'child2')]" }, "p3_res1childprop": { "type": "string", - "value": "[reference(resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), '2020-06-01').someProp]" + "value": "[reference(resourceId('Microsoft.Rp1/resource1/child1', 'p3res1', 'child1'), '2020-06-01').someProp]" }, "p3_res1childname": { "type": "string", @@ -696,11 +696,11 @@ }, "p3_res1childid": { "type": "string", - "value": "[resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1')]" + "value": "[resourceId('Microsoft.Rp1/resource1/child1', 'p3res1', 'child1')]" }, "p4_res1childprop": { "type": "string", - "value": "[reference(tenantResourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), '2020-06-01').someProp]" + "value": "[reference(tenantResourceId('Microsoft.Rp1/resource1/child1', 'p4res1', 'child1'), '2020-06-01').someProp]" }, "p4_res1childname": { "type": "string", @@ -712,7 +712,7 @@ }, "p4_res1childid": { "type": "string", - "value": "[tenantResourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1')]" + "value": "[tenantResourceId('Microsoft.Rp1/resource1/child1', 'p4res1', 'child1')]" }, "nameof_sqlServer": { "type": "string", diff --git a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.sourcemap.bicep b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.sourcemap.bicep index 3b05da1eefd..b54c47256f9 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.sourcemap.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.sourcemap.bicep @@ -345,25 +345,25 @@ resource resourceB 'My.Rp/typeA/typeB@2020-01-01' = { //@ { //@ "type": "My.Rp/typeA/typeB", //@ "apiVersion": "2020-01-01", -//@ "name": "[format('{0}/myName', 'resourceA')]", +//@ "name": "[format('{0}/resourceB', 'resourceA')]", //@ "dependsOn": [ //@ "[resourceId('My.Rp/typeA', 'resourceA')]" //@ ] //@ }, - name: '${resourceA.name}/myName' + name: '${resourceA.name}/resourceB' } resource resourceC 'My.Rp/typeA/typeB@2020-01-01' = { //@ { //@ "type": "My.Rp/typeA/typeB", //@ "apiVersion": "2020-01-01", -//@ "name": "[format('{0}/myName', 'resourceA')]", +//@ "name": "[format('{0}/resourceC', 'resourceA')]", //@ "dependsOn": [ //@ "[resourceId('My.Rp/typeA', 'resourceA')]", -//@ "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]" +//@ "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceB', 'resourceA'), '/')[0], split(format('{0}/resourceB', 'resourceA'), '/')[1])]" //@ ] //@ }, - name: '${resourceA.name}/myName' + name: '${resourceA.name}/resourceC' properties: { //@ "properties": { //@ }, @@ -376,7 +376,7 @@ resource resourceC 'My.Rp/typeA/typeB@2020-01-01' = { aApiVersion: resourceA.apiVersion //@ "aApiVersion": "2020-01-01", bProperties: resourceB.properties -//@ "bProperties": "[reference(resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1]), '2020-01-01')]" +//@ "bProperties": "[reference(resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceB', 'resourceA'), '/')[0], split(format('{0}/resourceB', 'resourceA'), '/')[1]), '2020-01-01')]" } } @@ -384,11 +384,11 @@ var varARuntime = { //@ { //@ } bId: resourceB.id -//@ "bId": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]", +//@ "bId": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceB', 'resourceA'), '/')[0], split(format('{0}/resourceB', 'resourceA'), '/')[1])]", bType: resourceB.type //@ "bType": "My.Rp/typeA/typeB", bName: resourceB.name -//@ "bName": "[format('{0}/myName', 'resourceA')]", +//@ "bName": "[format('{0}/resourceB', 'resourceA')]", bApiVersion: resourceB.apiVersion //@ "bApiVersion": "2020-01-01", aKind: resourceA.kind @@ -405,7 +405,7 @@ var resourceCRef = { //@ "resourceCRef": { //@ }, id: resourceC.id -//@ "id": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]" +//@ "id": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceC', 'resourceA'), '/')[0], split(format('{0}/resourceC', 'resourceA'), '/')[1])]" } var setResourceCRef = true //@ "setResourceCRef": true, @@ -417,8 +417,8 @@ resource resourceD 'My.Rp/typeD@2020-01-01' = { //@ "name": "constant", //@ "dependsOn": [ //@ "[resourceId('My.Rp/typeA', 'resourceA')]", -//@ "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]", -//@ "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]" +//@ "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceB', 'resourceA'), '/')[0], split(format('{0}/resourceB', 'resourceA'), '/')[1])]", +//@ "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceC', 'resourceA'), '/')[0], split(format('{0}/resourceC', 'resourceA'), '/')[1])]" //@ ] //@ }, name: 'constant' @@ -1006,18 +1006,18 @@ resource p2_res1 'Microsoft.Rp1/resource1@2020-06-01' = { //@ { //@ "type": "Microsoft.Rp1/resource1", //@ "apiVersion": "2020-06-01", -//@ "name": "res1" +//@ "name": "p2res1" //@ }, - name: 'res1' + name: 'p2res1' } resource p2_res1child 'Microsoft.Rp1/resource1/child1@2020-06-01' = { //@ { //@ "type": "Microsoft.Rp1/resource1/child1", //@ "apiVersion": "2020-06-01", -//@ "name": "[format('{0}/{1}', 'res1', 'child1')]", +//@ "name": "[format('{0}/{1}', 'p2res1', 'child1')]", //@ "dependsOn": [ -//@ "[resourceId('Microsoft.Rp1/resource1', 'res1')]" +//@ "[resourceId('Microsoft.Rp1/resource1', 'p2res1')]" //@ ] //@ }, parent: p2_res1 @@ -1028,10 +1028,10 @@ resource p2_res2 'Microsoft.Rp2/resource2@2020-06-01' = { //@ { //@ "type": "Microsoft.Rp2/resource2", //@ "apiVersion": "2020-06-01", -//@ "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'res1', 'child1')]", +//@ "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'p2res1', 'child1')]", //@ "name": "res2", //@ "dependsOn": [ -//@ "[resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1')]" +//@ "[resourceId('Microsoft.Rp1/resource1/child1', 'p2res1', 'child1')]" //@ ] //@ }, scope: p2_res1child @@ -1042,10 +1042,10 @@ resource p2_res2child 'Microsoft.Rp2/resource2/child2@2020-06-01' = { //@ { //@ "type": "Microsoft.Rp2/resource2/child2", //@ "apiVersion": "2020-06-01", -//@ "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'res1', 'child1')]", +//@ "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'p2res1', 'child1')]", //@ "name": "[format('{0}/{1}', 'res2', 'child2')]", //@ "dependsOn": [ -//@ "[extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), 'Microsoft.Rp2/resource2', 'res2')]" +//@ "[extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'p2res1', 'child1'), 'Microsoft.Rp2/resource2', 'res2')]" //@ ] //@ }, parent: p2_res2 @@ -1055,7 +1055,7 @@ resource p2_res2child 'Microsoft.Rp2/resource2/child2@2020-06-01' = { output p2_res2childprop string = p2_res2child.properties.someProp //@ "p2_res2childprop": { //@ "type": "string", -//@ "value": "[reference(extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), 'Microsoft.Rp2/resource2/child2', 'res2', 'child2'), '2020-06-01').someProp]" +//@ "value": "[reference(extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'p2res1', 'child1'), 'Microsoft.Rp2/resource2/child2', 'res2', 'child2'), '2020-06-01').someProp]" //@ }, output p2_res2childname string = p2_res2child.name //@ "p2_res2childname": { @@ -1070,19 +1070,19 @@ output p2_res2childtype string = p2_res2child.type output p2_res2childid string = p2_res2child.id //@ "p2_res2childid": { //@ "type": "string", -//@ "value": "[extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), 'Microsoft.Rp2/resource2/child2', 'res2', 'child2')]" +//@ "value": "[extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'p2res1', 'child1'), 'Microsoft.Rp2/resource2/child2', 'res2', 'child2')]" //@ }, // parent property with 'existing' resource resource p3_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { - name: 'res1' + name: 'p3res1' } resource p3_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' = { //@ { //@ "type": "Microsoft.Rp1/resource1/child1", //@ "apiVersion": "2020-06-01", -//@ "name": "[format('{0}/{1}', 'res1', 'child1')]" +//@ "name": "[format('{0}/{1}', 'p3res1', 'child1')]" //@ }, parent: p3_res1 name: 'child1' @@ -1091,7 +1091,7 @@ resource p3_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' = { output p3_res1childprop string = p3_child1.properties.someProp //@ "p3_res1childprop": { //@ "type": "string", -//@ "value": "[reference(resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), '2020-06-01').someProp]" +//@ "value": "[reference(resourceId('Microsoft.Rp1/resource1/child1', 'p3res1', 'child1'), '2020-06-01').someProp]" //@ }, output p3_res1childname string = p3_child1.name //@ "p3_res1childname": { @@ -1106,13 +1106,13 @@ output p3_res1childtype string = p3_child1.type output p3_res1childid string = p3_child1.id //@ "p3_res1childid": { //@ "type": "string", -//@ "value": "[resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1')]" +//@ "value": "[resourceId('Microsoft.Rp1/resource1/child1', 'p3res1', 'child1')]" //@ }, // parent & child with 'existing' resource p4_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { scope: tenant() - name: 'res1' + name: 'p4res1' } resource p4_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' existing = { @@ -1123,7 +1123,7 @@ resource p4_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' existing = { output p4_res1childprop string = p4_child1.properties.someProp //@ "p4_res1childprop": { //@ "type": "string", -//@ "value": "[reference(tenantResourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), '2020-06-01').someProp]" +//@ "value": "[reference(tenantResourceId('Microsoft.Rp1/resource1/child1', 'p4res1', 'child1'), '2020-06-01').someProp]" //@ }, output p4_res1childname string = p4_child1.name //@ "p4_res1childname": { @@ -1138,7 +1138,7 @@ output p4_res1childtype string = p4_child1.type output p4_res1childid string = p4_child1.id //@ "p4_res1childid": { //@ "type": "string", -//@ "value": "[tenantResourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1')]" +//@ "value": "[tenantResourceId('Microsoft.Rp1/resource1/child1', 'p4res1', 'child1')]" //@ }, // parent & nested child with decorators https://github.com/Azure/bicep/issues/10970 diff --git a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.symbolicnames.json b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.symbolicnames.json index f3e808faf7f..09ef4e11064 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.symbolicnames.json +++ b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.symbolicnames.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "dev", - "templateHash": "17920750879435313448" + "templateHash": "5552023285963513625" } }, "parameters": { @@ -38,7 +38,7 @@ "_siteApiVersion": "2019-08-01", "_siteType": "Microsoft.Web/sites", "resourceCRef": { - "id": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]" + "id": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceC', 'resourceA'), '/')[0], split(format('{0}/resourceC', 'resourceA'), '/')[1])]" }, "setResourceCRef": true, "myInterpKey": "abc", @@ -256,7 +256,7 @@ "resourceB": { "type": "My.Rp/typeA/typeB", "apiVersion": "2020-01-01", - "name": "[format('{0}/myName', 'resourceA')]", + "name": "[format('{0}/resourceB', 'resourceA')]", "dependsOn": [ "resourceA" ] @@ -264,7 +264,7 @@ "resourceC": { "type": "My.Rp/typeA/typeB", "apiVersion": "2020-01-01", - "name": "[format('{0}/myName', 'resourceA')]", + "name": "[format('{0}/resourceC', 'resourceA')]", "properties": { "aId": "[resourceId('My.Rp/typeA', 'resourceA')]", "aType": "My.Rp/typeA", @@ -284,9 +284,9 @@ "properties": { "runtime": [ { - "bId": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/myName', 'resourceA'), '/')[0], split(format('{0}/myName', 'resourceA'), '/')[1])]", + "bId": "[resourceId('My.Rp/typeA/typeB', split(format('{0}/resourceB', 'resourceA'), '/')[0], split(format('{0}/resourceB', 'resourceA'), '/')[1])]", "bType": "My.Rp/typeA/typeB", - "bName": "[format('{0}/myName', 'resourceA')]", + "bName": "[format('{0}/resourceB', 'resourceA')]", "bApiVersion": "2020-01-01", "aKind": "[reference('resourceA', '2020-01-01', 'full').kind]" } @@ -628,12 +628,12 @@ "p2_res1": { "type": "Microsoft.Rp1/resource1", "apiVersion": "2020-06-01", - "name": "res1" + "name": "p2res1" }, "p2_res1child": { "type": "Microsoft.Rp1/resource1/child1", "apiVersion": "2020-06-01", - "name": "[format('{0}/{1}', 'res1', 'child1')]", + "name": "[format('{0}/{1}', 'p2res1', 'child1')]", "dependsOn": [ "p2_res1" ] @@ -641,7 +641,7 @@ "p2_res2": { "type": "Microsoft.Rp2/resource2", "apiVersion": "2020-06-01", - "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'res1', 'child1')]", + "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'p2res1', 'child1')]", "name": "res2", "dependsOn": [ "p2_res1child" @@ -650,7 +650,7 @@ "p2_res2child": { "type": "Microsoft.Rp2/resource2/child2", "apiVersion": "2020-06-01", - "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'res1', 'child1')]", + "scope": "[format('Microsoft.Rp1/resource1/{0}/child1/{1}', 'p2res1', 'child1')]", "name": "[format('{0}/{1}', 'res2', 'child2')]", "dependsOn": [ "p2_res2" @@ -660,26 +660,26 @@ "existing": true, "type": "Microsoft.Rp1/resource1", "apiVersion": "2020-06-01", - "name": "res1" + "name": "p3res1" }, "p3_child1": { "type": "Microsoft.Rp1/resource1/child1", "apiVersion": "2020-06-01", - "name": "[format('{0}/{1}', 'res1', 'child1')]" + "name": "[format('{0}/{1}', 'p3res1', 'child1')]" }, "p4_res1": { "existing": true, "type": "Microsoft.Rp1/resource1", "apiVersion": "2020-06-01", "scope": "/", - "name": "res1" + "name": "p4res1" }, "p4_child1": { "existing": true, "type": "Microsoft.Rp1/resource1/child1", "apiVersion": "2020-06-01", "scope": "/", - "name": "[format('{0}/{1}', 'res1', 'child1')]" + "name": "[format('{0}/{1}', 'p4res1', 'child1')]" }, "sqlServer": { "type": "Microsoft.Sql/servers", @@ -733,7 +733,7 @@ }, "p2_res2childid": { "type": "string", - "value": "[extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1'), 'Microsoft.Rp2/resource2/child2', 'res2', 'child2')]" + "value": "[extensionResourceId(resourceId('Microsoft.Rp1/resource1/child1', 'p2res1', 'child1'), 'Microsoft.Rp2/resource2/child2', 'res2', 'child2')]" }, "p3_res1childprop": { "type": "string", @@ -749,7 +749,7 @@ }, "p3_res1childid": { "type": "string", - "value": "[resourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1')]" + "value": "[resourceId('Microsoft.Rp1/resource1/child1', 'p3res1', 'child1')]" }, "p4_res1childprop": { "type": "string", @@ -765,7 +765,7 @@ }, "p4_res1childid": { "type": "string", - "value": "[tenantResourceId('Microsoft.Rp1/resource1/child1', 'res1', 'child1')]" + "value": "[tenantResourceId('Microsoft.Rp1/resource1/child1', 'p4res1', 'child1')]" }, "nameof_sqlServer": { "type": "string", diff --git a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.symbols.bicep b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.symbols.bicep index 6e82b72d318..9a848d41cb7 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.symbols.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.symbols.bicep @@ -187,13 +187,13 @@ resource resourceA 'My.Rp/typeA@2020-01-01' = { } resource resourceB 'My.Rp/typeA/typeB@2020-01-01' = { -//@[09:018) Resource resourceB. Type: My.Rp/typeA/typeB@2020-01-01. Declaration start char: 0, length: 92 - name: '${resourceA.name}/myName' +//@[09:018) Resource resourceB. Type: My.Rp/typeA/typeB@2020-01-01. Declaration start char: 0, length: 95 + name: '${resourceA.name}/resourceB' } resource resourceC 'My.Rp/typeA/typeB@2020-01-01' = { -//@[09:018) Resource resourceC. Type: My.Rp/typeA/typeB@2020-01-01. Declaration start char: 0, length: 269 - name: '${resourceA.name}/myName' +//@[09:018) Resource resourceC. Type: My.Rp/typeA/typeB@2020-01-01. Declaration start char: 0, length: 272 + name: '${resourceA.name}/resourceC' properties: { aId: resourceA.id aType: resourceA.type @@ -516,8 +516,8 @@ output p1_subnet1id string = p1_subnet1.id // parent property with extension resource resource p2_res1 'Microsoft.Rp1/resource1@2020-06-01' = { -//@[09:016) Resource p2_res1. Type: Microsoft.Rp1/resource1@2020-06-01. Declaration start char: 0, length: 76 - name: 'res1' +//@[09:016) Resource p2_res1. Type: Microsoft.Rp1/resource1@2020-06-01. Declaration start char: 0, length: 78 + name: 'p2res1' } resource p2_res1child 'Microsoft.Rp1/resource1/child1@2020-06-01' = { @@ -549,8 +549,8 @@ output p2_res2childid string = p2_res2child.id // parent property with 'existing' resource resource p3_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { -//@[09:016) Resource p3_res1. Type: Microsoft.Rp1/resource1@2020-06-01. Declaration start char: 0, length: 85 - name: 'res1' +//@[09:016) Resource p3_res1. Type: Microsoft.Rp1/resource1@2020-06-01. Declaration start char: 0, length: 87 + name: 'p3res1' } resource p3_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' = { @@ -570,9 +570,9 @@ output p3_res1childid string = p3_child1.id // parent & child with 'existing' resource p4_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { -//@[09:016) Resource p4_res1. Type: Microsoft.Rp1/resource1@2020-06-01. Declaration start char: 0, length: 104 +//@[09:016) Resource p4_res1. Type: Microsoft.Rp1/resource1@2020-06-01. Declaration start char: 0, length: 106 scope: tenant() - name: 'res1' + name: 'p4res1' } resource p4_child1 'Microsoft.Rp1/resource1/child1@2020-06-01' existing = { diff --git a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.syntax.bicep b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.syntax.bicep index ea7498e2697..51f00cbf1fa 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.syntax.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.syntax.bicep @@ -1,5 +1,5 @@ -//@[000:14055) ProgramSyntax +//@[000:14067) ProgramSyntax //@[000:00002) ├─Token(NewLine) |\r\n| @sys.description('this is basicStorage') //@[000:00225) ├─ResourceDeclarationSyntax @@ -1180,22 +1180,22 @@ resource resourceA 'My.Rp/typeA@2020-01-01' = { //@[001:00005) ├─Token(NewLine) |\r\n\r\n| resource resourceB 'My.Rp/typeA/typeB@2020-01-01' = { -//@[000:00092) ├─ResourceDeclarationSyntax +//@[000:00095) ├─ResourceDeclarationSyntax //@[000:00008) | ├─Token(Identifier) |resource| //@[009:00018) | ├─IdentifierSyntax //@[009:00018) | | └─Token(Identifier) |resourceB| //@[019:00049) | ├─StringSyntax //@[019:00049) | | └─Token(StringComplete) |'My.Rp/typeA/typeB@2020-01-01'| //@[050:00051) | ├─Token(Assignment) |=| -//@[052:00092) | └─ObjectSyntax +//@[052:00095) | └─ObjectSyntax //@[052:00053) | ├─Token(LeftBrace) |{| //@[053:00055) | ├─Token(NewLine) |\r\n| - name: '${resourceA.name}/myName' -//@[002:00034) | ├─ObjectPropertySyntax + name: '${resourceA.name}/resourceB' +//@[002:00037) | ├─ObjectPropertySyntax //@[002:00006) | | ├─IdentifierSyntax //@[002:00006) | | | └─Token(Identifier) |name| //@[006:00007) | | ├─Token(Colon) |:| -//@[008:00034) | | └─StringSyntax +//@[008:00037) | | └─StringSyntax //@[008:00011) | | ├─Token(StringLeftPiece) |'${| //@[011:00025) | | ├─PropertyAccessSyntax //@[011:00020) | | | ├─VariableAccessSyntax @@ -1204,29 +1204,29 @@ resource resourceB 'My.Rp/typeA/typeB@2020-01-01' = { //@[020:00021) | | | ├─Token(Dot) |.| //@[021:00025) | | | └─IdentifierSyntax //@[021:00025) | | | └─Token(Identifier) |name| -//@[025:00034) | | └─Token(StringRightPiece) |}/myName'| -//@[034:00036) | ├─Token(NewLine) |\r\n| +//@[025:00037) | | └─Token(StringRightPiece) |}/resourceB'| +//@[037:00039) | ├─Token(NewLine) |\r\n| } //@[000:00001) | └─Token(RightBrace) |}| //@[001:00005) ├─Token(NewLine) |\r\n\r\n| resource resourceC 'My.Rp/typeA/typeB@2020-01-01' = { -//@[000:00269) ├─ResourceDeclarationSyntax +//@[000:00272) ├─ResourceDeclarationSyntax //@[000:00008) | ├─Token(Identifier) |resource| //@[009:00018) | ├─IdentifierSyntax //@[009:00018) | | └─Token(Identifier) |resourceC| //@[019:00049) | ├─StringSyntax //@[019:00049) | | └─Token(StringComplete) |'My.Rp/typeA/typeB@2020-01-01'| //@[050:00051) | ├─Token(Assignment) |=| -//@[052:00269) | └─ObjectSyntax +//@[052:00272) | └─ObjectSyntax //@[052:00053) | ├─Token(LeftBrace) |{| //@[053:00055) | ├─Token(NewLine) |\r\n| - name: '${resourceA.name}/myName' -//@[002:00034) | ├─ObjectPropertySyntax + name: '${resourceA.name}/resourceC' +//@[002:00037) | ├─ObjectPropertySyntax //@[002:00006) | | ├─IdentifierSyntax //@[002:00006) | | | └─Token(Identifier) |name| //@[006:00007) | | ├─Token(Colon) |:| -//@[008:00034) | | └─StringSyntax +//@[008:00037) | | └─StringSyntax //@[008:00011) | | ├─Token(StringLeftPiece) |'${| //@[011:00025) | | ├─PropertyAccessSyntax //@[011:00020) | | | ├─VariableAccessSyntax @@ -1235,8 +1235,8 @@ resource resourceC 'My.Rp/typeA/typeB@2020-01-01' = { //@[020:00021) | | | ├─Token(Dot) |.| //@[021:00025) | | | └─IdentifierSyntax //@[021:00025) | | | └─Token(Identifier) |name| -//@[025:00034) | | └─Token(StringRightPiece) |}/myName'| -//@[034:00036) | ├─Token(NewLine) |\r\n| +//@[025:00037) | | └─Token(StringRightPiece) |}/resourceC'| +//@[037:00039) | ├─Token(NewLine) |\r\n| properties: { //@[002:00175) | ├─ObjectPropertySyntax //@[002:00012) | | ├─IdentifierSyntax @@ -3436,24 +3436,24 @@ output p1_subnet1id string = p1_subnet1.id // parent property with extension resource //@[042:00044) ├─Token(NewLine) |\r\n| resource p2_res1 'Microsoft.Rp1/resource1@2020-06-01' = { -//@[000:00076) ├─ResourceDeclarationSyntax +//@[000:00078) ├─ResourceDeclarationSyntax //@[000:00008) | ├─Token(Identifier) |resource| //@[009:00016) | ├─IdentifierSyntax //@[009:00016) | | └─Token(Identifier) |p2_res1| //@[017:00053) | ├─StringSyntax //@[017:00053) | | └─Token(StringComplete) |'Microsoft.Rp1/resource1@2020-06-01'| //@[054:00055) | ├─Token(Assignment) |=| -//@[056:00076) | └─ObjectSyntax +//@[056:00078) | └─ObjectSyntax //@[056:00057) | ├─Token(LeftBrace) |{| //@[057:00059) | ├─Token(NewLine) |\r\n| - name: 'res1' -//@[002:00014) | ├─ObjectPropertySyntax + name: 'p2res1' +//@[002:00016) | ├─ObjectPropertySyntax //@[002:00006) | | ├─IdentifierSyntax //@[002:00006) | | | └─Token(Identifier) |name| //@[006:00007) | | ├─Token(Colon) |:| -//@[008:00014) | | └─StringSyntax -//@[008:00014) | | └─Token(StringComplete) |'res1'| -//@[014:00016) | ├─Token(NewLine) |\r\n| +//@[008:00016) | | └─StringSyntax +//@[008:00016) | | └─Token(StringComplete) |'p2res1'| +//@[016:00018) | ├─Token(NewLine) |\r\n| } //@[000:00001) | └─Token(RightBrace) |}| //@[001:00005) ├─Token(NewLine) |\r\n\r\n| @@ -3630,7 +3630,7 @@ output p2_res2childid string = p2_res2child.id // parent property with 'existing' resource //@[043:00045) ├─Token(NewLine) |\r\n| resource p3_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { -//@[000:00085) ├─ResourceDeclarationSyntax +//@[000:00087) ├─ResourceDeclarationSyntax //@[000:00008) | ├─Token(Identifier) |resource| //@[009:00016) | ├─IdentifierSyntax //@[009:00016) | | └─Token(Identifier) |p3_res1| @@ -3638,17 +3638,17 @@ resource p3_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { //@[017:00053) | | └─Token(StringComplete) |'Microsoft.Rp1/resource1@2020-06-01'| //@[054:00062) | ├─Token(Identifier) |existing| //@[063:00064) | ├─Token(Assignment) |=| -//@[065:00085) | └─ObjectSyntax +//@[065:00087) | └─ObjectSyntax //@[065:00066) | ├─Token(LeftBrace) |{| //@[066:00068) | ├─Token(NewLine) |\r\n| - name: 'res1' -//@[002:00014) | ├─ObjectPropertySyntax + name: 'p3res1' +//@[002:00016) | ├─ObjectPropertySyntax //@[002:00006) | | ├─IdentifierSyntax //@[002:00006) | | | └─Token(Identifier) |name| //@[006:00007) | | ├─Token(Colon) |:| -//@[008:00014) | | └─StringSyntax -//@[008:00014) | | └─Token(StringComplete) |'res1'| -//@[014:00016) | ├─Token(NewLine) |\r\n| +//@[008:00016) | | └─StringSyntax +//@[008:00016) | | └─Token(StringComplete) |'p3res1'| +//@[016:00018) | ├─Token(NewLine) |\r\n| } //@[000:00001) | └─Token(RightBrace) |}| //@[001:00005) ├─Token(NewLine) |\r\n\r\n| @@ -3761,7 +3761,7 @@ output p3_res1childid string = p3_child1.id // parent & child with 'existing' //@[033:00035) ├─Token(NewLine) |\r\n| resource p4_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { -//@[000:00104) ├─ResourceDeclarationSyntax +//@[000:00106) ├─ResourceDeclarationSyntax //@[000:00008) | ├─Token(Identifier) |resource| //@[009:00016) | ├─IdentifierSyntax //@[009:00016) | | └─Token(Identifier) |p4_res1| @@ -3769,7 +3769,7 @@ resource p4_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { //@[017:00053) | | └─Token(StringComplete) |'Microsoft.Rp1/resource1@2020-06-01'| //@[054:00062) | ├─Token(Identifier) |existing| //@[063:00064) | ├─Token(Assignment) |=| -//@[065:00104) | └─ObjectSyntax +//@[065:00106) | └─ObjectSyntax //@[065:00066) | ├─Token(LeftBrace) |{| //@[066:00068) | ├─Token(NewLine) |\r\n| scope: tenant() @@ -3783,14 +3783,14 @@ resource p4_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { //@[015:00016) | | ├─Token(LeftParen) |(| //@[016:00017) | | └─Token(RightParen) |)| //@[017:00019) | ├─Token(NewLine) |\r\n| - name: 'res1' -//@[002:00014) | ├─ObjectPropertySyntax + name: 'p4res1' +//@[002:00016) | ├─ObjectPropertySyntax //@[002:00006) | | ├─IdentifierSyntax //@[002:00006) | | | └─Token(Identifier) |name| //@[006:00007) | | ├─Token(Colon) |:| -//@[008:00014) | | └─StringSyntax -//@[008:00014) | | └─Token(StringComplete) |'res1'| -//@[014:00016) | ├─Token(NewLine) |\r\n| +//@[008:00016) | | └─StringSyntax +//@[008:00016) | | └─Token(StringComplete) |'p4res1'| +//@[016:00018) | ├─Token(NewLine) |\r\n| } //@[000:00001) | └─Token(RightBrace) |}| //@[001:00005) ├─Token(NewLine) |\r\n\r\n| diff --git a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.tokens.bicep b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.tokens.bicep index a399dbac9cb..2dbcc9f2410 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.tokens.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Resources_CRLF/main.tokens.bicep @@ -762,15 +762,15 @@ resource resourceB 'My.Rp/typeA/typeB@2020-01-01' = { //@[050:051) Assignment |=| //@[052:053) LeftBrace |{| //@[053:055) NewLine |\r\n| - name: '${resourceA.name}/myName' + name: '${resourceA.name}/resourceB' //@[002:006) Identifier |name| //@[006:007) Colon |:| //@[008:011) StringLeftPiece |'${| //@[011:020) Identifier |resourceA| //@[020:021) Dot |.| //@[021:025) Identifier |name| -//@[025:034) StringRightPiece |}/myName'| -//@[034:036) NewLine |\r\n| +//@[025:037) StringRightPiece |}/resourceB'| +//@[037:039) NewLine |\r\n| } //@[000:001) RightBrace |}| //@[001:005) NewLine |\r\n\r\n| @@ -782,15 +782,15 @@ resource resourceC 'My.Rp/typeA/typeB@2020-01-01' = { //@[050:051) Assignment |=| //@[052:053) LeftBrace |{| //@[053:055) NewLine |\r\n| - name: '${resourceA.name}/myName' + name: '${resourceA.name}/resourceC' //@[002:006) Identifier |name| //@[006:007) Colon |:| //@[008:011) StringLeftPiece |'${| //@[011:020) Identifier |resourceA| //@[020:021) Dot |.| //@[021:025) Identifier |name| -//@[025:034) StringRightPiece |}/myName'| -//@[034:036) NewLine |\r\n| +//@[025:037) StringRightPiece |}/resourceC'| +//@[037:039) NewLine |\r\n| properties: { //@[002:012) Identifier |properties| //@[012:013) Colon |:| @@ -2194,11 +2194,11 @@ resource p2_res1 'Microsoft.Rp1/resource1@2020-06-01' = { //@[054:055) Assignment |=| //@[056:057) LeftBrace |{| //@[057:059) NewLine |\r\n| - name: 'res1' + name: 'p2res1' //@[002:006) Identifier |name| //@[006:007) Colon |:| -//@[008:014) StringComplete |'res1'| -//@[014:016) NewLine |\r\n| +//@[008:016) StringComplete |'p2res1'| +//@[016:018) NewLine |\r\n| } //@[000:001) RightBrace |}| //@[001:005) NewLine |\r\n\r\n| @@ -2315,11 +2315,11 @@ resource p3_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { //@[063:064) Assignment |=| //@[065:066) LeftBrace |{| //@[066:068) NewLine |\r\n| - name: 'res1' + name: 'p3res1' //@[002:006) Identifier |name| //@[006:007) Colon |:| -//@[008:014) StringComplete |'res1'| -//@[014:016) NewLine |\r\n| +//@[008:016) StringComplete |'p3res1'| +//@[016:018) NewLine |\r\n| } //@[000:001) RightBrace |}| //@[001:005) NewLine |\r\n\r\n| @@ -2401,11 +2401,11 @@ resource p4_res1 'Microsoft.Rp1/resource1@2020-06-01' existing = { //@[015:016) LeftParen |(| //@[016:017) RightParen |)| //@[017:019) NewLine |\r\n| - name: 'res1' + name: 'p4res1' //@[002:006) Identifier |name| //@[006:007) Colon |:| -//@[008:014) StringComplete |'res1'| -//@[014:016) NewLine |\r\n| +//@[008:016) StringComplete |'p4res1'| +//@[016:018) NewLine |\r\n| } //@[000:001) RightBrace |}| //@[001:005) NewLine |\r\n\r\n| diff --git a/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/UseResourceIdFunctionsRuleTests.cs b/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/UseResourceIdFunctionsRuleTests.cs index b616d398d5d..15fa8b78fe6 100644 --- a/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/UseResourceIdFunctionsRuleTests.cs +++ b/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/UseResourceIdFunctionsRuleTests.cs @@ -476,6 +476,8 @@ param nodefault string ", new string[] { + "[8:21] Resources: \"certificateOrderName\", \"certificateOrderName2\" are defined with this same name in a file. Rename them or split into different modules.", + "[17:21] Resources: \"certificateOrderName\", \"certificateOrderName2\" are defined with this same name in a file. Rename them or split into different modules.", $"[20:17] If property \"keyVaultShouldFailId\" represents a resource ID, it must use a symbolic resource reference, be a parameter or start with one of these functions: {allowedFunctions}. Found nonconforming expression at keyVaultShouldFailId -> existingKeyVaultId", }, DisplayName = "pass/IDs-In-KeyVault.json")] diff --git a/src/Bicep.Core/Emit/EmitLimitationCalculator.cs b/src/Bicep.Core/Emit/EmitLimitationCalculator.cs index e152c48331e..509adb6a566 100644 --- a/src/Bicep.Core/Emit/EmitLimitationCalculator.cs +++ b/src/Bicep.Core/Emit/EmitLimitationCalculator.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Bicep.Core.DataFlow; using Bicep.Core.Diagnostics; using Bicep.Core.Extensions; @@ -70,90 +71,184 @@ private static void DetectDuplicateNames(SemanticModel semanticModel, IDiagnosti // This method only checks, if in one deployment we do not have 2 or more resources with this same name in one deployment to avoid template validation error // This will not check resource constraints such as necessity of having unique virtual network names within resource group - var duplicateResources = GetResourceDefinitions(semanticModel, resourceScopeData) - .GroupBy(x => x, ResourceDefinition.EqualityComparer) + var duplicateResources = semanticModel.DeclaredResources + .GroupBy(x => x, new DeclaredResourceIdComparer(semanticModel, resourceScopeData)) .Where(group => group.Count() > 1); foreach (var duplicatedResourceGroup in duplicateResources) { - var duplicatedResourceNames = duplicatedResourceGroup.Select(x => x.ResourceName).ToArray(); foreach (var duplicatedResource in duplicatedResourceGroup) { - diagnosticWriter.Write(duplicatedResource.ResourceNamePropertyValue, x => x.ResourceMultipleDeclarations(duplicatedResourceNames)); + diagnosticWriter.Write(duplicatedResource.NameSyntax, x => x.ResourceMultipleDeclarations(duplicatedResourceGroup.Select(r => r.Symbol.Name))); } } - var duplicateModules = GetModuleDefinitions(semanticModel, moduleScopeData) - .GroupBy(x => x, ModuleDefinition.EqualityComparer) + var duplicateModules = semanticModel.Root.ModuleDeclarations + .GroupBy(x => x, new ModuleIdComparer(semanticModel, moduleScopeData)) .Where(group => group.Count() > 1); foreach (var duplicatedModuleGroup in duplicateModules) { - var duplicatedModuleNames = duplicatedModuleGroup.Select(x => x.ModuleName).ToArray(); foreach (var duplicatedModule in duplicatedModuleGroup) { - diagnosticWriter.Write(duplicatedModule.ModulePropertyNameValue, x => x.ModuleMultipleDeclarations(duplicatedModuleNames)); + diagnosticWriter.Write( + duplicatedModule.TryGetBodyPropertyValue(LanguageConstants.ModuleNamePropertyName) ?? duplicatedModule.DeclaringModule.Name, + x => x.ModuleMultipleDeclarations(duplicatedModuleGroup.Select(m => m.Name))); } } } - private static IEnumerable GetModuleDefinitions(SemanticModel semanticModel, ImmutableDictionary moduleScopeData) + private class DeclaredResourceIdComparer : IEqualityComparer { - foreach (var module in semanticModel.Root.ModuleDeclarations) + private readonly SemanticModel model; + private readonly ImmutableDictionary resourceScopeData; + private readonly Dictionary> resourceNameSegments = new(); + + internal DeclaredResourceIdComparer( + SemanticModel model, + ImmutableDictionary resourceScopeData) { - if (!moduleScopeData.TryGetValue(module, out var scopeData)) - { - //module has invalid scope provided, ignoring from duplicate check - continue; - } - if (module.TryGetBodyPropertyValue(LanguageConstants.ModuleNamePropertyName) is not StringSyntax propertyNameValue) + this.model = model; + this.resourceScopeData = resourceScopeData; + } + + public bool Equals(DeclaredResourceMetadata? x, DeclaredResourceMetadata? y) + { + if (x is null && y is null) + { + return true; + } + + return + // extensibility resources do not have an ARM ID + x?.IsAzResource is true && + y?.IsAzResource is true && + // ARM resource ID uniqueness is only enforced on resources with a `true` condition + (x.Symbol.DeclaringResource.TryGetCondition() is not { } xCondition || + model.GetTypeInfo(xCondition) is BooleanLiteralType { Value: true }) && + (y.Symbol.DeclaringResource.TryGetCondition() is not { } yCondition || + model.GetTypeInfo(yCondition) is BooleanLiteralType { Value: true }) && + // To have the same ID, resource must have: + // the same type + LanguageConstants.ResourceTypeComparer.Equals(x.TypeReference.FormatType(), y.TypeReference.FormatType()) && + // the same scope + resourceScopeData.TryGetValue(x, out var xScopeData) && + resourceScopeData.TryGetValue(y, out var yScopeData) && + xScopeData.Equals(yScopeData) && + // and the same name + resourceNameSegments.GetOrAdd(x, NameSegmentsFor) + .SequenceEqual(resourceNameSegments.GetOrAdd(y, NameSegmentsFor)); + } + + public int GetHashCode([DisallowNull] DeclaredResourceMetadata obj) + { + var baseHash = obj.TypeReference.FormatType().GetHashCode(); + + foreach (var nameSegment in resourceNameSegments.GetOrAdd(obj, NameSegmentsFor)) { - //currently limiting check to 'name' property values that are strings, although it can be references or other syntaxes - continue; + baseHash = HashCode.Combine(baseHash, nameSegment); } - var propertyScopeValue = (module.TryGetBodyPropertyValue(LanguageConstants.ResourceScopePropertyName) as FunctionCallSyntax)?.Arguments.Select(x => x.Expression as StringSyntax).ToImmutableArray(); - - yield return new ModuleDefinition(module.Name, scopeData.RequestedScope, propertyScopeValue, propertyNameValue); + return baseHash; } + + private ImmutableArray NameSegmentsFor(DeclaredResourceMetadata resource) + => model.ResourceAncestors.GetAncestors(resource) + .Reverse() + .SelectMany(r => r.IndexExpression switch + { + SyntaxBase idx when model.GetTypeInfo(idx) is IntegerLiteralType literalIndex + => new[] { NameSegmentFor(r.Resource), new LiteralIdSegment(literalIndex.Value.ToString()) }, + SyntaxBase idx => new[] { NameSegmentFor(r.Resource), new NonLiteralIdSegment(idx) }, + _ => NameSegmentFor(r.Resource).AsEnumerable(), + }) + .Append(NameSegmentFor(resource)) + .ToImmutableArray(); + + private IArmIdSegment NameSegmentFor(DeclaredResourceMetadata resource) + => IArmIdSegment.For(resource.TryGetNameSyntax(), model) switch + { + IArmIdSegment nonNull => nonNull, + _ => new NonLiteralIdSegment(resource.Symbol.DeclaringResource.Name), + }; } - private static IEnumerable GetResourceDefinitions(SemanticModel semanticModel, ImmutableDictionary resourceScopeData) + private interface IArmIdSegment { - foreach (var resource in semanticModel.DeclaredResources) + [return: NotNullIfNotNull(nameof(syntax))] + static IArmIdSegment? For(SyntaxBase? syntax, SemanticModel model) => syntax switch { - if (resource.IsExistingResource) - { - // 'existing' resources are not being deployed so duplicates are allowed - continue; - } + SyntaxBase nonNull when model.GetTypeInfo(nonNull) is StringLiteralType literalSegment + => new LiteralIdSegment(literalSegment.RawStringValue), + SyntaxBase nonNull => new NonLiteralIdSegment(nonNull), + _ => null, + }; + } - if (!resource.IsAzResource) - { - // comparison checks currently blocked for non-ARM resources - continue; - } + private record LiteralIdSegment(string Name) : IArmIdSegment; - if (resource.TryGetNameSyntax() is not { } resourceName || - resourceName is not StringSyntax resourceNameString) - { - // the resource doesn't have a name set, or it's not a string and thus difficult to analyze - continue; - } + private record NonLiteralIdSegment(SyntaxBase NameSyntax) : IArmIdSegment; - // Determine the scope - this is either something like a resource group/subscription or another resource - ResourceMetadata? resourceScope; - if (resourceScopeData.TryGetValue(resource, out var scopeData) && scopeData.ResourceScope is { } scopeMetadata) - { - resourceScope = scopeMetadata; - } - else + // Using a class instead of a record here so that reference equality will be used for missing segments + private class MissingIdSegment() : IArmIdSegment { } + + private class ModuleIdComparer : IEqualityComparer + { + private readonly SemanticModel model; + private readonly ImmutableDictionary moduleScopeData; + private readonly Dictionary moduleScopingSegments = new(); + + public ModuleIdComparer( + SemanticModel model, + ImmutableDictionary moduleScopeData) + { + this.model = model; + this.moduleScopeData = moduleScopeData; + } + + public bool Equals(ModuleSymbol? x, ModuleSymbol? y) + { + if (x is null && y is null) + { + return true; + } + + // if a module declaration omits a name, it is either using the optional module names feature + // (in which case its name will be unique) or already has an error-level diagnostic + return x?.TryGetBodyPropertyValue(LanguageConstants.ModuleNamePropertyName) is { } xName && + y?.TryGetBodyPropertyValue(LanguageConstants.ModuleNamePropertyName) is { } yName && + // ARM resource ID uniqueness is only enforced on resources with a `true` condition + (x.DeclaringModule.TryGetCondition() is not { } xCondition || + model.GetTypeInfo(xCondition) is BooleanLiteralType { Value: true }) && + (y.DeclaringModule.TryGetCondition() is not { } yCondition || + model.GetTypeInfo(yCondition) is BooleanLiteralType { Value: true }) && + // To have the same ID, modules must have the same scope + moduleScopingSegments.GetOrAdd(x, ScopingSegmentsFor) + .Equals(moduleScopingSegments.GetOrAdd(y, ScopingSegmentsFor)) && + // and the same name + IArmIdSegment.For(xName, model).Equals(IArmIdSegment.For(yName, model)); + } + + public int GetHashCode([DisallowNull] ModuleSymbol obj) + => IArmIdSegment.For(obj.TryGetBodyPropertyValue(LanguageConstants.ModuleNamePropertyName), model)?.GetHashCode() ?? 0; + + private ModuleScopingSegments ScopingSegmentsFor(ModuleSymbol m) + { + if (!moduleScopeData.TryGetValue(m, out var scopeData)) { - resourceScope = semanticModel.ResourceAncestors.GetAncestors(resource).LastOrDefault()?.Resource; + return new(new MissingIdSegment(), new MissingIdSegment(), new MissingIdSegment()); } - yield return new ResourceDefinition(resource.Symbol.Name, resourceScope, resource.TypeReference.FormatType(), resourceNameString); + return new( + IArmIdSegment.For(scopeData.ManagementGroupNameProperty, model), + IArmIdSegment.For(scopeData.SubscriptionIdProperty, model), + IArmIdSegment.For(scopeData.ResourceGroupProperty, model)); } + + private record ModuleScopingSegments( + IArmIdSegment? ManagementGroupName, + IArmIdSegment? SubscriptionId, + IArmIdSegment? ResourceGroupName); } private static void DetectIncorrectlyFormattedNames(SemanticModel semanticModel, IDiagnosticWriter diagnosticWriter) diff --git a/src/Bicep.Core/Extensions/DictionaryExtensions.cs b/src/Bicep.Core/Extensions/DictionaryExtensions.cs index 267a4e5f301..77a90784e66 100644 --- a/src/Bicep.Core/Extensions/DictionaryExtensions.cs +++ b/src/Bicep.Core/Extensions/DictionaryExtensions.cs @@ -9,6 +9,24 @@ public static class DictionaryExtensions source.TryGetValue(key, out TValue? value); return value; } + + /// + /// NOT thread safe! + /// If you need thread safety, use a . + /// + public static TValue GetOrAdd( + this IDictionary source, + TKey key, + Func valueFactory) + { + if (!source.TryGetValue(key, out var value)) + { + value = valueFactory(key); + source.Add(key, value); + } + + return value; + } } } diff --git a/src/Bicep.Core/Syntax/ModuleDeclarationSyntax.cs b/src/Bicep.Core/Syntax/ModuleDeclarationSyntax.cs index 30673f6c42e..b34c7a76f0d 100644 --- a/src/Bicep.Core/Syntax/ModuleDeclarationSyntax.cs +++ b/src/Bicep.Core/Syntax/ModuleDeclarationSyntax.cs @@ -69,7 +69,15 @@ public ModuleDeclarationSyntax(IEnumerable leadingNodes, Token keywo public ObjectSyntax GetBody() => this.TryGetBody() ?? throw new InvalidOperationException($"A valid module body is not available on this module due to errors. Use {nameof(TryGetBody)}() instead."); - public bool HasCondition() => this.Value is IfConditionSyntax or ForSyntax { Body: IfConditionSyntax }; + public bool HasCondition() => TryGetCondition() is not null; + + public SyntaxBase? TryGetCondition() => Value switch + { + IfConditionSyntax ifCondition => ifCondition.ConditionExpression, + ForSyntax { Body: IfConditionSyntax ifCondition } => ifCondition.ConditionExpression, + _ => null, + }; + public ArtifactType GetArtifactType() => ArtifactType.Module; } diff --git a/src/Bicep.Core/Syntax/ResourceDeclarationSyntax.cs b/src/Bicep.Core/Syntax/ResourceDeclarationSyntax.cs index 09b0bc7595e..1e708627440 100644 --- a/src/Bicep.Core/Syntax/ResourceDeclarationSyntax.cs +++ b/src/Bicep.Core/Syntax/ResourceDeclarationSyntax.cs @@ -74,7 +74,14 @@ public ResourceDeclarationSyntax(IEnumerable leadingNodes, Token key public ObjectSyntax GetBody() => this.TryGetBody() ?? throw new InvalidOperationException($"A valid resource body is not available on this module due to errors. Use {nameof(TryGetBody)}() instead."); - public bool HasCondition() => this.Value is IfConditionSyntax or ForSyntax { Body: IfConditionSyntax }; + public bool HasCondition() => TryGetCondition() is not null; + + public SyntaxBase? TryGetCondition() => Value switch + { + IfConditionSyntax ifCondition => ifCondition.ConditionExpression, + ForSyntax { Body: IfConditionSyntax ifCondition } => ifCondition.ConditionExpression, + _ => null, + }; public bool IsCollection() => this.Value is ForSyntax; } diff --git a/src/Bicep.Core/Utils/ModuleDefinition.cs b/src/Bicep.Core/Utils/ModuleDefinition.cs deleted file mode 100644 index d41436b2194..00000000000 --- a/src/Bicep.Core/Utils/ModuleDefinition.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -using System.Collections.Immutable; -using Bicep.Core.Syntax; -using Bicep.Core.TypeSystem; - -namespace Bicep.Core.Utils -{ - internal class ModuleDefinition - { - public string ModuleName { get; } - public ResourceScope ModulePropertyScopeType { get; } - public IReadOnlyCollection? ModulePropertyScopeValue { get; } - public StringSyntax ModulePropertyNameValue { get; } - - public ModuleDefinition(string moduleName, ResourceScope modulePropertyScopeType, ImmutableArray? modulePropertyScopeValue, StringSyntax modulePropertyNameValue) - { - ModuleName = moduleName; - ModulePropertyScopeType = modulePropertyScopeType; - ModulePropertyScopeValue = modulePropertyScopeValue; - ModulePropertyNameValue = modulePropertyNameValue; - } - - public static readonly IEqualityComparer EqualityComparer = new ModuleComparer(); - - private class ModuleComparer : IEqualityComparer - { - - public bool Equals(ModuleDefinition? x, ModuleDefinition? y) - { - if (x is null || y is null) - { - return false; - } - - if (x.ModulePropertyScopeType != y.ModulePropertyScopeType) - { - return false; - } - - var xpnv = x.ModulePropertyNameValue.TryGetLiteralValue(); - var ypnv = y.ModulePropertyNameValue.TryGetLiteralValue(); - - if (xpnv is null || ypnv is null || !string.Equals(xpnv, ypnv, StringComparison.InvariantCultureIgnoreCase)) - { - //no point in checking scope at least one of them is interpolated or their literal names differ - return false; - } - - if ((x.ModulePropertyScopeValue is null || x.ModulePropertyScopeValue.Count == 0) && (y.ModulePropertyScopeValue is null || y.ModulePropertyScopeValue.Count == 0)) - { - // this case indicates that modules are being deployed to scope without name specified (e.g. subscription(), resourceGroup(), etc.) - // and as we checked before that names are equal, we need to return true. - return true; - } - - - //null values indicates that module used is parent scope - //as we checked case, when we have both modules in parent scope, we can safely return false when null is found - //this might still lead to situation, when we define scope which in real deployment is same as parent scope, but this cannot be forseen - //(it'll be a runtime error, while we check only for compilation errors) - return x.ModulePropertyScopeValue is not null && y.ModulePropertyScopeValue is not null - && Enumerable.SequenceEqual(x.ModulePropertyScopeValue, y.ModulePropertyScopeValue, StringSyntaxComparerInstance); - - } - - public int GetHashCode(ModuleDefinition obj) - { - var hc = new HashCode(); - hc.Add(obj.ModulePropertyScopeType); - foreach (var x in obj.ModulePropertyScopeValue ?? Enumerable.Empty()) - { - hc.Add(x, StringSyntaxComparerInstance); - } - hc.Add(obj.ModulePropertyNameValue?.TryGetLiteralValue(), StringComparer.InvariantCultureIgnoreCase); - return hc.ToHashCode(); - } - - private static readonly StringSyntaxComparer StringSyntaxComparerInstance = new(); - - private class StringSyntaxComparer : IEqualityComparer - { - public bool Equals(StringSyntax? x, StringSyntax? y) - { - var xv = x?.TryGetLiteralValue(); - var yv = y?.TryGetLiteralValue(); - //null values indicates value is interpolated or was not a string (i.e. reference). - //since at this point we check only for literal matching, we do comparison only if both are not nulls (plain strings) - return xv is not null && yv is not null && string.Equals(xv, yv, StringComparison.InvariantCultureIgnoreCase); - - } - - public int GetHashCode(StringSyntax? obj) - { - return StringComparer.InvariantCultureIgnoreCase.GetHashCode(obj?.TryGetLiteralValue() ?? string.Empty); - } - } - } - } -} diff --git a/src/Bicep.Core/Utils/ResourceDefinition.cs b/src/Bicep.Core/Utils/ResourceDefinition.cs deleted file mode 100644 index abdab71b22b..00000000000 --- a/src/Bicep.Core/Utils/ResourceDefinition.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -using Bicep.Core.Semantics.Metadata; -using Bicep.Core.Syntax; - -namespace Bicep.Core.Utils -{ - internal class ResourceDefinition - { - public string ResourceName { get; } - public ResourceMetadata? ResourceScope { get; } - public string FullyQualifiedResourceType { get; } - public StringSyntax ResourceNamePropertyValue { get; } - - public ResourceDefinition(string resourceName, ResourceMetadata? resourceScope, string fullyQualifiedResourceType, StringSyntax resourceNamePropertyValue) - { - ResourceName = resourceName; - ResourceScope = resourceScope; - FullyQualifiedResourceType = fullyQualifiedResourceType; - ResourceNamePropertyValue = resourceNamePropertyValue; - } - - - public static readonly IEqualityComparer EqualityComparer = new ResourceComparer(); - // comparers below are very simple now, however in future it might be used to do more exact comparison on property value to include interpolations - // also, we expect StringSyntax as values it can be other types as well (function calls, variable accesses, etc.) - private class ResourceComparer : IEqualityComparer - { - - public bool Equals(ResourceDefinition? x, ResourceDefinition? y) - { - if (x is null || y is null) - { - return false; - } - - if (!string.Equals(x.FullyQualifiedResourceType, y.FullyQualifiedResourceType, StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - if (x.ResourceScope != y.ResourceScope) - { - return false; - } - - var xv = x.ResourceNamePropertyValue.TryGetLiteralValue(); - var yv = y.ResourceNamePropertyValue.TryGetLiteralValue(); - - //if literal value is null, we assume resources are not equal, as this indicates that interpolated value is used - //and as for now we're unable to determine if they will have equal values or not. - return xv is not null && yv is not null && string.Equals(xv, yv, StringComparison.OrdinalIgnoreCase); - } - - public int GetHashCode(ResourceDefinition obj) - { - var hc = new HashCode(); - hc.Add(obj.FullyQualifiedResourceType, StringComparer.OrdinalIgnoreCase); - hc.Add(obj.ResourceScope); - hc.Add(obj.ResourceNamePropertyValue.TryGetLiteralValue(), StringComparer.OrdinalIgnoreCase); - return hc.ToHashCode(); - } - } - } -} diff --git a/src/Bicep.Decompiler.IntegrationTests/Files/Working/naming001-simple/main.bicep b/src/Bicep.Decompiler.IntegrationTests/Files/Working/naming001-simple/main.bicep index 0de42c145a8..428edf048fa 100644 --- a/src/Bicep.Decompiler.IntegrationTests/Files/Working/naming001-simple/main.bicep +++ b/src/Bicep.Decompiler.IntegrationTests/Files/Working/naming001-simple/main.bicep @@ -8,6 +8,7 @@ var virtualMachineName3 = 'VM-MultiNic' resource virtualMachine 'Microsoft.Compute/virtualMachines@2020-06-01' = { name: virtualMachineName +//@[8:26) [BCP121 (Error)] Resources: "virtualMachine", "virtualMachineRename", "virtualMachine3" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |virtualMachineName| location: location } @@ -23,11 +24,13 @@ resource Name 'Microsoft.Compute/virtualMachines@2020-06-01' = { resource virtualMachineRename 'Microsoft.Compute/virtualMachines@2020-06-01' = { name: virtualMachineRename_var +//@[8:32) [BCP121 (Error)] Resources: "virtualMachine", "virtualMachineRename", "virtualMachine3" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |virtualMachineRename_var| location: location } resource virtualMachine3 'Microsoft.Compute/virtualMachines@2020-06-01' = { name: virtualMachineName3 +//@[8:27) [BCP121 (Error)] Resources: "virtualMachine", "virtualMachineRename", "virtualMachine3" are defined with this same name in a file. Rename them or split into different modules. (bicep https://aka.ms/bicep/core-diagnostics#BCP121) |virtualMachineName3| location: location }