Skip to content

Commit 6a57053

Browse files
authored
Add an explicit any type (#17848)
Resolves #13399 This PR adds a new ambient type symbol (`any`) to take advantage of `"type"` constraints being made optional in ARM's **w34** release. Anywhere type syntax is expected, users can now supply `any`: ```bicep param foo any output bar any = foo func cowSay(toSay any) string => 'The cow says, "${toSay}"' ``` `any` is incompatible with the `@secure()` decorator. ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/Azure/bicep/pull/17848)
1 parent 5292db2 commit 6a57053

File tree

38 files changed

+472
-160
lines changed

38 files changed

+472
-160
lines changed

src/Bicep.Core.IntegrationTests/ScenarioTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ param l
8383
("BCP028", DiagnosticLevel.Error, "Identifier \"l\" is declared multiple times. Remove or rename the duplicates."),
8484
("BCP079", DiagnosticLevel.Error, "This expression is referencing its own declaration, which is not allowed."),
8585
("BCP028", DiagnosticLevel.Error, "Identifier \"l\" is declared multiple times. Remove or rename the duplicates."),
86-
("BCP279", DiagnosticLevel.Error, "Expected a type at this location. Please specify a valid type expression or one of the following types: \"array\", \"bool\", \"int\", \"object\", \"string\"."),
86+
("BCP279", DiagnosticLevel.Error, "Expected a type at this location. Please specify a valid type expression or one of the following types: \"any\", \"array\", \"bool\", \"int\", \"object\", \"string\"."),
8787
});
8888
}
8989

@@ -792,7 +792,7 @@ public void Test_Issue1599()
792792
result.Template.Should().NotHaveValue();
793793
result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[]
794794
{
795-
("BCP279", DiagnosticLevel.Error, "Expected a type at this location. Please specify a valid type expression or one of the following types: \"array\", \"bool\", \"int\", \"object\", \"string\"."),
795+
("BCP279", DiagnosticLevel.Error, "Expected a type at this location. Please specify a valid type expression or one of the following types: \"any\", \"array\", \"bool\", \"int\", \"object\", \"string\"."),
796796
});
797797
}
798798

@@ -5776,8 +5776,8 @@ public void Test_Issue12908()
57765776

57775777
result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[]
57785778
{
5779-
("BCP308", DiagnosticLevel.Error, """The decorator "secure" may not be used on statements whose declared type is a reference to a user-defined type."""),
5780-
("BCP308", DiagnosticLevel.Error, """The decorator "secure" may not be used on statements whose declared type is a reference to a user-defined type."""),
5779+
("BCP439", DiagnosticLevel.Error, """The @secure() decorator can only be used on statements whose type clause is "string,", "object", or a literal type."""),
5780+
("BCP439", DiagnosticLevel.Error, """The @secure() decorator can only be used on statements whose type clause is "string,", "object", or a literal type."""),
57815781
});
57825782
}
57835783

src/Bicep.Core.IntegrationTests/TypedVariableTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public void Invalid_type_reference_raises_an_error()
7777
);
7878

7979
result.ExcludingLinterDiagnostics().Should().HaveDiagnostics([
80-
("BCP302", DiagnosticLevel.Error, """The name "invalid" is not a valid type. Please specify one of the following types: "array", "bool", "int", "object", "resourceInput", "resourceOutput", "string"."""),
80+
("BCP302", DiagnosticLevel.Error, """The name "invalid" is not a valid type. Please specify one of the following types: "any", "array", "bool", "int", "object", "resourceInput", "resourceOutput", "string"."""),
8181
]);
8282
}
8383

src/Bicep.Core.IntegrationTests/UserDefinedTypeTests.cs

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ param intParam constrainedInt
155155
("BCP308", DiagnosticLevel.Error, "The decorator \"maxValue\" may not be used on statements whose declared type is a reference to a user-defined type."),
156156
("BCP308", DiagnosticLevel.Error, "The decorator \"minLength\" may not be used on statements whose declared type is a reference to a user-defined type."),
157157
("BCP308", DiagnosticLevel.Error, "The decorator \"maxLength\" may not be used on statements whose declared type is a reference to a user-defined type."),
158-
("BCP308", DiagnosticLevel.Error, "The decorator \"secure\" may not be used on statements whose declared type is a reference to a user-defined type."),
158+
("BCP439", DiagnosticLevel.Error, "The @secure() decorator can only be used on statements whose type clause is \"string,\", \"object\", or a literal type."),
159159
("BCP308", DiagnosticLevel.Error, "The decorator \"allowed\" may not be used on statements whose declared type is a reference to a user-defined type."),
160160
("no-unused-params", DiagnosticLevel.Warning, "Parameter \"stringParam\" is declared but never used."),
161161
("BCP308", DiagnosticLevel.Error, "The decorator \"minValue\" may not be used on statements whose declared type is a reference to a user-defined type."),
@@ -1730,11 +1730,10 @@ param siteProperties resourceInput<'Microsoft.Web/sites@2022-09-01'>.properties
17301730
properties: siteProperties
17311731
}
17321732
1733-
@secure()
17341733
output siteProperties resourceOutput<'Microsoft.Web/sites@2022-09-01'>.properties = appService.properties
17351734
""");
17361735

1737-
result.Should().NotHaveAnyDiagnostics();
1736+
result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics();
17381737
}
17391738

17401739
[TestMethod]
@@ -1779,26 +1778,28 @@ public void Parameterized_type_recursion_raises_diagnostic(string template)
17791778

17801779
// https://www.github.com/Azure/bicep/issues/15277
17811780
[DataTestMethod]
1782-
[DataRow("type resourceDerived = resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings")]
1783-
[DataRow("param resourceDerived resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings")]
1784-
[DataRow("output resourceDerived resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings = 'foo'")]
1785-
[DataRow("type t = { property: resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings }")]
1786-
[DataRow("type t = { *: resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings }")]
1787-
[DataRow("type t = [ resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings ]")]
1788-
[DataRow("type t = resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings[]")]
1789-
[DataRow("func f() resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings => 'foo'")]
1790-
[DataRow("func f(p resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings) string => 'foo'")]
1791-
public void Type_expressions_that_will_become_ARM_schema_nodes_are_checked_for_ARM_type_system_compatibility_prior_to_compilation(string template)
1781+
[DataRow("type resourceDerived = resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings", "$.definitions.resourceDerived")]
1782+
[DataRow("param resourceDerived resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings", "$.parameters.resourceDerived")]
1783+
[DataRow("output resourceDerived resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings = 'foo'", "$.outputs.resourceDerived")]
1784+
[DataRow("type t = { property: resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings }", "$.definitions.t.properties.property")]
1785+
[DataRow("type t = { *: resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings }", "$.definitions.t.additionalProperties")]
1786+
[DataRow("type t = [ resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings ]", "$.definitions.t.prefixItems[0]")]
1787+
[DataRow("type t = resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings[]", "$.definitions.t.items")]
1788+
[DataRow("func f() resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings => 'foo'", "$.functions[0].members.f.output")]
1789+
[DataRow("func f(p resourceInput<'Microsoft.Compute/virtualMachines/extensions@2019-12-01'>.properties.settings) string => 'foo'", "$.functions[0].members.f.parameters[0]")]
1790+
public void Type_expressions_that_will_become_ARM_schema_nodes_allow_types_that_do_not_fit_into_an_arm_primitive_type_category(
1791+
string template,
1792+
string pathToAnyTypeNode)
17921793
{
17931794
var result = CompilationHelper.Compile(
17941795
new ServiceBuilder().WithFeatureOverrides(new(TestContext)),
17951796
template);
17961797

1797-
result.Template.Should().BeNull();
1798-
result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[]
1799-
{
1800-
("BCP411", DiagnosticLevel.Error, """The type "any" cannot be used in a type assignment because it does not fit within one of ARM's primitive type categories (string, int, bool, array, object). If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues."""),
1801-
});
1798+
result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics();
1799+
result.Template.Should().NotBeNull();
1800+
var typeNode = result.Template!.SelectToken(pathToAnyTypeNode);
1801+
typeNode.Should().BeOfType<JObject>();
1802+
typeNode!.SelectToken("$.type").Should().BeNull();
18021803
}
18031804

18041805
[TestMethod]
@@ -1957,4 +1958,46 @@ param foo bool
19571958
("BCP432", DiagnosticLevel.Error, "This expression is being used in parameter \"predicate\" of the function \"validate\", 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 (\"indirection\" -> \"sa\"). Properties of sa which can be calculated at the start include \"apiVersion\", \"id\", \"name\", \"type\"."),
19581959
]);
19591960
}
1961+
1962+
[TestMethod]
1963+
public void Any_type_can_be_used_wherever_a_type_is_allowed()
1964+
{
1965+
var result = CompilationHelper.Compile("""
1966+
type myAny = any
1967+
type hasAnyProp = {
1968+
property: any
1969+
}
1970+
type dictStringAny = {
1971+
*: any
1972+
}
1973+
type untypedArray = any[]
1974+
type tupleWithAny = [string, bool, any]
1975+
""");
1976+
1977+
result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics();
1978+
result.Template.Should().NotBeNull();
1979+
result.Template.Should().HaveJsonAtPath("$.definitions.myAny", "{}");
1980+
result.Template.Should().HaveJsonAtPath("$.definitions.hasAnyProp.properties.property", "{}");
1981+
result.Template.Should().HaveJsonAtPath("$.definitions.dictStringAny.additionalProperties", "{}");
1982+
result.Template.Should().HaveJsonAtPath("$.definitions.untypedArray.items", "{}");
1983+
result.Template.Should().HaveJsonAtPath("$.definitions.tupleWithAny.prefixItems[2]", "{}");
1984+
}
1985+
1986+
[TestMethod]
1987+
public void Secure_decorator_is_blocked_on_any_and_resource_derived_types()
1988+
{
1989+
var result = CompilationHelper.Compile("""
1990+
@secure()
1991+
type untyped = any
1992+
1993+
@secure()
1994+
type rdt = resourceInput<'Microsoft.Resources/deployments@2022-09-01'>.name
1995+
""");
1996+
1997+
result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(
1998+
[
1999+
("BCP439", DiagnosticLevel.Error, "The @secure() decorator can only be used on statements whose type clause is \"string,\", \"object\", or a literal type."),
2000+
("BCP439", DiagnosticLevel.Error, "The @secure() decorator can only be used on statements whose type clause is \"string,\", \"object\", or a literal type."),
2001+
]);
2002+
}
19602003
}

src/Bicep.Core.Samples/Files/baselines/Completions/outputTypes.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
[
2+
{
3+
"label": "any",
4+
"kind": "class",
5+
"detail": "any",
6+
"deprecated": false,
7+
"preselect": false,
8+
"sortText": "2_any",
9+
"insertTextFormat": "plainText",
10+
"insertTextMode": "adjustIndentation",
11+
"textEdit": {
12+
"range": {},
13+
"newText": "any"
14+
}
15+
},
216
{
317
"label": "array",
418
"kind": "class",

src/Bicep.Core.Samples/Files/baselines/Completions/paramTypes.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
[
2+
{
3+
"label": "any",
4+
"kind": "class",
5+
"detail": "any",
6+
"deprecated": false,
7+
"preselect": false,
8+
"sortText": "2_any",
9+
"insertTextFormat": "plainText",
10+
"insertTextMode": "adjustIndentation",
11+
"textEdit": {
12+
"range": {},
13+
"newText": "any"
14+
}
15+
},
216
{
317
"label": "array",
418
"kind": "class",

src/Bicep.Core.Samples/Files/baselines/InvalidExpressions_LF/Completions/sysFunctions.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,25 @@
11
[
2+
{
3+
"label": "any",
4+
"kind": "property",
5+
"detail": "any",
6+
"documentation": {
7+
"kind": "markdown",
8+
"value": "Type: `Type<any>` \n"
9+
},
10+
"deprecated": false,
11+
"preselect": false,
12+
"sortText": "2_any",
13+
"insertTextFormat": "plainText",
14+
"insertTextMode": "adjustIndentation",
15+
"textEdit": {
16+
"range": {},
17+
"newText": "any"
18+
},
19+
"commitCharacters": [
20+
"."
21+
]
22+
},
223
{
324
"label": "any",
425
"kind": "function",

src/Bicep.Core.Samples/Files/baselines/InvalidExpressions_LF/main.diagnostics.bicep

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ var invalidPropertyAccessOnAzNamespace = az.az
448448
//@[44:46) [BCP052 (Error)] The type "az" does not contain property "az". (bicep https://aka.ms/bicep/core-diagnostics#BCP052) |az|
449449
var invalidPropertyAccessOnSysNamespace = sys.az
450450
//@[04:39) [no-unused-vars (Warning)] Variable "invalidPropertyAccessOnSysNamespace" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-vars) |invalidPropertyAccessOnSysNamespace|
451-
//@[46:48) [BCP053 (Error)] The type "sys" does not contain property "az". Available properties include "array", "bool", "int", "object", "resourceInput", "resourceOutput", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |az|
451+
//@[46:48) [BCP053 (Error)] The type "sys" does not contain property "az". Available properties include "any", "array", "bool", "int", "object", "resourceInput", "resourceOutput", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |az|
452452
var invalidOperands = 1 + az
453453
//@[04:19) [no-unused-vars (Warning)] Variable "invalidOperands" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-vars) |invalidOperands|
454454
//@[22:28) [BCP045 (Error)] Cannot apply operator "+" to operands of type "1" and "az". (bicep https://aka.ms/bicep/core-diagnostics#BCP045) |1 + az|
@@ -495,12 +495,12 @@ var azFunctions = az.a
495495
// #completionTest(24) -> sysFunctions
496496
var sysFunctions = sys.a
497497
//@[04:16) [no-unused-vars (Warning)] Variable "sysFunctions" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-vars) |sysFunctions|
498-
//@[23:24) [BCP053 (Error)] The type "sys" does not contain property "a". Available properties include "array", "bool", "int", "object", "resourceInput", "resourceOutput", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |a|
498+
//@[23:24) [BCP053 (Error)] The type "sys" does not contain property "a". Available properties include "any", "array", "bool", "int", "object", "resourceInput", "resourceOutput", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |a|
499499

500500
// #completionTest(33) -> sysFunctions
501501
var sysFunctionsInParens = (sys.a)
502502
//@[04:24) [no-unused-vars (Warning)] Variable "sysFunctionsInParens" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-vars) |sysFunctionsInParens|
503-
//@[32:33) [BCP053 (Error)] The type "sys" does not contain property "a". Available properties include "array", "bool", "int", "object", "resourceInput", "resourceOutput", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |a|
503+
//@[32:33) [BCP053 (Error)] The type "sys" does not contain property "a". Available properties include "any", "array", "bool", "int", "object", "resourceInput", "resourceOutput", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |a|
504504

505505
// missing method name
506506
var missingMethodName = az.()

src/Bicep.Core.Samples/Files/baselines/InvalidFunctions_LF/main.diagnostics.bicep

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ func useRuntimeFunction() string => reference('foo').bar
22
//@[36:52) [BCP341 (Error)] This expression is being used inside a function declaration, which requires a value that can be calculated at the start of the deployment. (bicep https://aka.ms/bicep/core-diagnostics#BCP341) |reference('foo')|
33

44
func missingArgType(input) string => input
5-
//@[25:26) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) |)|
5+
//@[25:26) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "any", "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) |)|
66

77
func missingOutputType(input string) => input
8-
//@[37:39) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) |=>|
8+
//@[37:39) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "any", "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) |=>|
99
//@[45:45) [BCP009 (Error)] Expected a literal value, an array, an object, a parenthesized expression, or a function call at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP009) ||
1010
//@[45:45) [BCP018 (Error)] Expected the "=>" character at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP018) ||
1111

@@ -59,23 +59,23 @@ func recursiveB() string => recursiveA()
5959

6060
func onlyComma(,) string => 'foo'
6161
//@[15:15) [BCP015 (Error)] Expected a variable identifier at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP015) ||
62-
//@[15:16) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) |,|
62+
//@[15:16) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "any", "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) |,|
6363
func trailingCommas(a string,,) string => 'foo'
6464
//@[29:29) [BCP015 (Error)] Expected a variable identifier at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP015) ||
65-
//@[29:30) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) |,|
65+
//@[29:30) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "any", "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) |,|
6666
func multiLineOnly(
6767
a string
6868
b string) string => 'foo'
6969
//@[02:03) [BCP018 (Error)] Expected the ")" character at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP018) |b|
7070
//@[27:27) [BCP009 (Error)] Expected a literal value, an array, an object, a parenthesized expression, or a function call at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP009) ||
71-
//@[27:27) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) ||
71+
//@[27:27) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "any", "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) ||
7272
//@[27:27) [BCP018 (Error)] Expected the "=>" character at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP018) ||
7373

7474
func multiLineTrailingCommas(
7575
a string,
7676
,) string => 'foo'
7777
//@[02:02) [BCP015 (Error)] Expected a variable identifier at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP015) ||
78-
//@[02:03) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) |,|
78+
//@[02:03) [BCP279 (Error)] Expected a type at this location. Please specify a valid type expression or one of the following types: "any", "array", "bool", "int", "object", "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP279) |,|
7979

8080
func lineBeforeComma(
8181
a string

0 commit comments

Comments
 (0)