From 00482e3abcef4bd256889986f3508ace96607409 Mon Sep 17 00:00:00 2001 From: Levi Date: Sun, 15 Jan 2023 16:13:41 -0500 Subject: [PATCH 01/12] Handle types in first and last functions --- .../TypeSystem/FunctionResolverTests.cs | 7 ++++-- .../Namespaces/SystemNamespaceType.cs | 24 +++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs index eedfb095189..77d62e0ac72 100644 --- a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs +++ b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs @@ -240,7 +240,7 @@ private static IEnumerable GetLiteralTransformations() _ => throw new NotImplementedException($"Unable to transform {argument} to a literal syntax node.") }; - TypeSymbol ToTypeLiteral(object argument) => argument switch + TypeSymbol ToTypeLiteral(object? argument) => argument switch { string str => new StringLiteralType(str), string[] strArray => new TupleType($"[{string.Join(", ", strArray.Select(str => $"'{str}'"))}]", strArray.Select(str => new StringLiteralType(str)).ToImmutableArray(), default), @@ -248,10 +248,11 @@ private static IEnumerable GetLiteralTransformations() int[] intArray => new TupleType("", intArray.Select(@int => new IntegerLiteralType(@int)).ToImmutableArray(), default), bool boolVal => new BooleanLiteralType(boolVal), bool[] boolArray => new TupleType("", boolArray.Select(@bool => new BooleanLiteralType(@bool)).ToImmutableArray(), default), + null => LanguageConstants.Null, _ => throw new NotImplementedException($"Unable to transform {argument} to a type literal.") }; - object[] CreateRow(object returnedLiteral, string functionName, params object[] argumentLiterals) + object[] CreateRow(object? returnedLiteral, string functionName, params object[] argumentLiterals) { var argumentLiteralSyntaxes = argumentLiterals.Select(ToFunctionArgumentSyntax).ToArray(); var argumentTypeLiterals = argumentLiterals.Select(ToTypeLiteral).ToList(); @@ -298,7 +299,9 @@ object[] CreateRow(object returnedLiteral, string functionName, params object[] CreateRow(new[] { "pop" }, "intersection", new[] { "fizz", "buzz", "pop" }, new[] { "snap", "crackle", "pop" }), CreateRow(new[] { "fizz", "buzz", "pop" }, "union", new[] { "fizz", "buzz" }, new[] { "pop" }), CreateRow("fizz", "first", new[] { new[] { "fizz", "buzz", "pop" } }), + CreateRow(null, "first", new[] { Array.Empty() }), CreateRow("pop", "last", new[] { new[] { "fizz", "buzz", "pop" } }), + CreateRow(null, "last", new[] { Array.Empty() }), CreateRow(0, "indexOf", new[] { "fizz", "buzz", "pop", "fizz" }, "fizz"), CreateRow(3, "lastIndexOf", new[] { "fizz", "buzz", "pop", "fizz" }, "fizz"), CreateRow(1, "min", new[] { 10, 4, 1, 6 }), diff --git a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs index c8557cf40c7..b374c1adfea 100644 --- a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs +++ b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs @@ -6,7 +6,9 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; +using System.Reflection; using System.Text; +using Azure.Deployments.Core.Diagnostics; using Bicep.Core.Diagnostics; using Bicep.Core.Extensions; using Bicep.Core.Features; @@ -281,7 +283,16 @@ private static IEnumerable GetSystemOverloads(IFeatureProvider yield return new FunctionOverloadBuilder("first") // TODO even with non-literal types, some type arithmetic could be performed - .WithReturnResultBuilder(TryDeriveLiteralReturnType("first", LanguageConstants.Any), LanguageConstants.Any) + .WithReturnResultBuilder((binder, fileResolver, diagnostics, arguments, argumentTypes) => + { + return argumentTypes[0] switch + { + TypedArrayType typedArrayType => new(typedArrayType.Item.Type), + TupleType tupleType when tupleType.Items.Length == 0 => new(LanguageConstants.Null), + _ => TryDeriveLiteralReturnType("first", LanguageConstants.Any) + .Invoke(binder, fileResolver, diagnostics, arguments, argumentTypes) + }; + }, TypeHelper.CreateTypeUnion(LanguageConstants.Object, LanguageConstants.Any, LanguageConstants.Null)) .WithGenericDescription(FirstDescription) .WithDescription("Returns the first element of the array.") .WithRequiredParameter("array", LanguageConstants.Array, "The value to retrieve the first element.") @@ -296,7 +307,16 @@ private static IEnumerable GetSystemOverloads(IFeatureProvider yield return new FunctionOverloadBuilder("last") // TODO even with non-literal types, some type arithmetic could be performed - .WithReturnResultBuilder(TryDeriveLiteralReturnType("last", LanguageConstants.Any), LanguageConstants.Any) + .WithReturnResultBuilder((binder, fileResolver, diagnostics, arguments, argumentTypes) => + { + return argumentTypes[0] switch + { + TypedArrayType typedArrayType => new(typedArrayType.Item.Type), + TupleType tupleType when tupleType.Items.Length == 0 => new(LanguageConstants.Null), + _ => TryDeriveLiteralReturnType("last", LanguageConstants.Any) + .Invoke(binder, fileResolver, diagnostics, arguments, argumentTypes) + }; + }, TypeHelper.CreateTypeUnion(LanguageConstants.Object, LanguageConstants.Any, LanguageConstants.Null)) .WithGenericDescription(LastDescription) .WithDescription("Returns the last element of the array.") .WithRequiredParameter("array", LanguageConstants.Array, "The value to retrieve the last element.") From e507f37e80c0c1182265aef3a26dd3d2cfc2416e Mon Sep 17 00:00:00 2001 From: Levi Date: Wed, 18 Jan 2023 16:58:53 -0500 Subject: [PATCH 02/12] Fix return result builder switch --- .../Namespaces/SystemNamespaceType.cs | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs index b374c1adfea..0fe63ea1105 100644 --- a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs +++ b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs @@ -282,17 +282,16 @@ private static IEnumerable GetSystemOverloads(IFeatureProvider .Build(); yield return new FunctionOverloadBuilder("first") - // TODO even with non-literal types, some type arithmetic could be performed .WithReturnResultBuilder((binder, fileResolver, diagnostics, arguments, argumentTypes) => { - return argumentTypes[0] switch + FunctionResult result = new(argumentTypes[0] switch { - TypedArrayType typedArrayType => new(typedArrayType.Item.Type), - TupleType tupleType when tupleType.Items.Length == 0 => new(LanguageConstants.Null), - _ => TryDeriveLiteralReturnType("first", LanguageConstants.Any) - .Invoke(binder, fileResolver, diagnostics, arguments, argumentTypes) - }; - }, TypeHelper.CreateTypeUnion(LanguageConstants.Object, LanguageConstants.Any, LanguageConstants.Null)) + TupleType tupleType => tupleType.Items.FirstOrDefault()?.Type ?? LanguageConstants.Null, + ArrayType arrayType => TypeHelper.CreateTypeUnion(LanguageConstants.Null, arrayType.Item.Type), + _ => throw new InvalidOperationException("Could not determine the return type from the provided input") + }); + return result; + }, LanguageConstants.Any) .WithGenericDescription(FirstDescription) .WithDescription("Returns the first element of the array.") .WithRequiredParameter("array", LanguageConstants.Array, "The value to retrieve the first element.") @@ -306,17 +305,15 @@ private static IEnumerable GetSystemOverloads(IFeatureProvider .Build(); yield return new FunctionOverloadBuilder("last") - // TODO even with non-literal types, some type arithmetic could be performed .WithReturnResultBuilder((binder, fileResolver, diagnostics, arguments, argumentTypes) => { - return argumentTypes[0] switch + return new(argumentTypes[0] switch { - TypedArrayType typedArrayType => new(typedArrayType.Item.Type), - TupleType tupleType when tupleType.Items.Length == 0 => new(LanguageConstants.Null), - _ => TryDeriveLiteralReturnType("last", LanguageConstants.Any) - .Invoke(binder, fileResolver, diagnostics, arguments, argumentTypes) - }; - }, TypeHelper.CreateTypeUnion(LanguageConstants.Object, LanguageConstants.Any, LanguageConstants.Null)) + TupleType tupleType => tupleType.Items.LastOrDefault()?.Type ?? LanguageConstants.Null, + ArrayType arrayType => TypeHelper.CreateTypeUnion(LanguageConstants.Null, arrayType.Item.Type), + _ => throw new InvalidOperationException("Could not determine the return type from the provided input") + }); + }, LanguageConstants.Any) .WithGenericDescription(LastDescription) .WithDescription("Returns the last element of the array.") .WithRequiredParameter("array", LanguageConstants.Array, "The value to retrieve the last element.") From b7bf8715b9548ae64ece96a1700adf8dba3b1ec1 Mon Sep 17 00:00:00 2001 From: Levi Date: Wed, 18 Jan 2023 20:03:39 -0500 Subject: [PATCH 03/12] Add tests --- .../TypeSystem/FunctionResolverTests.cs | 54 +++++++++++++++++++ .../Namespaces/SystemNamespaceType.cs | 3 +- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs index 77d62e0ac72..04575c1fee1 100644 --- a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs +++ b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs @@ -146,6 +146,20 @@ public void ShouldNotFlatten(TypeSymbol typeToFlatten, params string[] diagnosti .Should().HaveDiagnostics(diagnosticMessages.Select(message => ("BCP309", DiagnosticLevel.Error, message))); } + [DataTestMethod] + [DynamicData(nameof(GetFirstTestCases), DynamicDataSourceType.Method)] + public void FirstReturnsCorrectTypeForNonLiterals(TypeSymbol inputArrayType, TypeSymbol expected) + { + TypeValidator.AreTypesAssignable(EvaluateFunction("first", new List { inputArrayType }, new[] { new FunctionArgumentSyntax(TestSyntaxFactory.CreateArray(Enumerable.Empty())) }).Type, expected).Should().BeTrue(); + } + + [DataTestMethod] + [DynamicData(nameof(GetLastTestCases), DynamicDataSourceType.Method)] + public void LastReturnsCorrectTypeForNonLiterals(TypeSymbol inputArrayType, TypeSymbol expected) + { + TypeValidator.AreTypesAssignable(EvaluateFunction("last", new List { inputArrayType }, new[] { new FunctionArgumentSyntax(TestSyntaxFactory.CreateArray(Enumerable.Empty())) }).Type, expected).Should().BeTrue(); + } + private FunctionResult EvaluateFunction(string functionName, IList argumentTypes, FunctionArgumentSyntax[] arguments) { var matches = GetMatches(functionName, argumentTypes, out _, out _); @@ -227,6 +241,44 @@ private static IEnumerable GetFlattenNegativeTestCases() => new[] }, }; + private static IEnumerable GetFirstTestCases() => new[] + { + // first(resourceGroup[]) -> resourceGroup + new object[] { + new TypedArrayType(LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup), default), + TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup)) + }, + // first([resourceGroup, subscription]) => resourceGroup + new object[] { + new TupleType("[resourceGroup, subscription]", + ImmutableArray.Create( + LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup), + LanguageConstants.CreateResourceScopeReference(ResourceScope.Subscription) + ), + default), + LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup) + } + }; + + private static IEnumerable GetLastTestCases() => new[] + { + // first(resourceGroup[]) -> resourceGroup + new object[] { + new TypedArrayType(LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup), default), + TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup)) + }, + // first([resourceGroup, subscription]) => subscription + new object[] { + new TupleType("[resourceGroup, subscription]", + ImmutableArray.Create( + LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup), + LanguageConstants.CreateResourceScopeReference(ResourceScope.Subscription) + ), + default), + LanguageConstants.CreateResourceScopeReference(ResourceScope.Subscription) + } + }; + private static IEnumerable GetLiteralTransformations() { FunctionArgumentSyntax ToFunctionArgumentSyntax(object argument) => argument switch @@ -299,8 +351,10 @@ object[] CreateRow(object? returnedLiteral, string functionName, params object[] CreateRow(new[] { "pop" }, "intersection", new[] { "fizz", "buzz", "pop" }, new[] { "snap", "crackle", "pop" }), CreateRow(new[] { "fizz", "buzz", "pop" }, "union", new[] { "fizz", "buzz" }, new[] { "pop" }), CreateRow("fizz", "first", new[] { new[] { "fizz", "buzz", "pop" } }), + CreateRow(3, "first", new[] { new object[] { 3, "buzz", true } }), CreateRow(null, "first", new[] { Array.Empty() }), CreateRow("pop", "last", new[] { new[] { "fizz", "buzz", "pop" } }), + CreateRow(true, "last", new[] { new object[] { 3, "buzz", true } }), CreateRow(null, "last", new[] { Array.Empty() }), CreateRow(0, "indexOf", new[] { "fizz", "buzz", "pop", "fizz" }, "fizz"), CreateRow(3, "lastIndexOf", new[] { "fizz", "buzz", "pop", "fizz" }, "fizz"), diff --git a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs index 0fe63ea1105..c1ae1e3a531 100644 --- a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs +++ b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs @@ -284,13 +284,12 @@ private static IEnumerable GetSystemOverloads(IFeatureProvider yield return new FunctionOverloadBuilder("first") .WithReturnResultBuilder((binder, fileResolver, diagnostics, arguments, argumentTypes) => { - FunctionResult result = new(argumentTypes[0] switch + return new(argumentTypes[0] switch { TupleType tupleType => tupleType.Items.FirstOrDefault()?.Type ?? LanguageConstants.Null, ArrayType arrayType => TypeHelper.CreateTypeUnion(LanguageConstants.Null, arrayType.Item.Type), _ => throw new InvalidOperationException("Could not determine the return type from the provided input") }); - return result; }, LanguageConstants.Any) .WithGenericDescription(FirstDescription) .WithDescription("Returns the first element of the array.") From 98d1ec5099b4c0622c7dd4f9afefdb406d09967b Mon Sep 17 00:00:00 2001 From: Levi Date: Wed, 18 Jan 2023 20:21:03 -0500 Subject: [PATCH 04/12] Fix failing tests --- .../TypeSystem/FunctionResolverTests.cs | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs index 04575c1fee1..8de428142b5 100644 --- a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs +++ b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs @@ -148,14 +148,14 @@ public void ShouldNotFlatten(TypeSymbol typeToFlatten, params string[] diagnosti [DataTestMethod] [DynamicData(nameof(GetFirstTestCases), DynamicDataSourceType.Method)] - public void FirstReturnsCorrectTypeForNonLiterals(TypeSymbol inputArrayType, TypeSymbol expected) + public void FirstReturnsCorrectType(TypeSymbol inputArrayType, TypeSymbol expected) { TypeValidator.AreTypesAssignable(EvaluateFunction("first", new List { inputArrayType }, new[] { new FunctionArgumentSyntax(TestSyntaxFactory.CreateArray(Enumerable.Empty())) }).Type, expected).Should().BeTrue(); } [DataTestMethod] [DynamicData(nameof(GetLastTestCases), DynamicDataSourceType.Method)] - public void LastReturnsCorrectTypeForNonLiterals(TypeSymbol inputArrayType, TypeSymbol expected) + public void LastReturnsCorrectType(TypeSymbol inputArrayType, TypeSymbol expected) { TypeValidator.AreTypesAssignable(EvaluateFunction("last", new List { inputArrayType }, new[] { new FunctionArgumentSyntax(TestSyntaxFactory.CreateArray(Enumerable.Empty())) }).Type, expected).Should().BeTrue(); } @@ -248,6 +248,16 @@ private static IEnumerable GetFirstTestCases() => new[] new TypedArrayType(LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup), default), TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup)) }, + // first(['test', 3]) -> 'test' + new object[] { + new TupleType("['test', 3]", + ImmutableArray.Create( + new StringLiteralType("test"), + new IntegerLiteralType(3) + ), + default), + new StringLiteralType("test") + }, // first([resourceGroup, subscription]) => resourceGroup new object[] { new TupleType("[resourceGroup, subscription]", @@ -267,6 +277,16 @@ private static IEnumerable GetLastTestCases() => new[] new TypedArrayType(LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup), default), TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup)) }, + // first(['test', 3]) -> 3 + new object[] { + new TupleType("['test', 3]", + ImmutableArray.Create( + new StringLiteralType("test"), + new IntegerLiteralType(3) + ), + default), + new IntegerLiteralType(3) + }, // first([resourceGroup, subscription]) => subscription new object[] { new TupleType("[resourceGroup, subscription]", @@ -351,10 +371,8 @@ object[] CreateRow(object? returnedLiteral, string functionName, params object[] CreateRow(new[] { "pop" }, "intersection", new[] { "fizz", "buzz", "pop" }, new[] { "snap", "crackle", "pop" }), CreateRow(new[] { "fizz", "buzz", "pop" }, "union", new[] { "fizz", "buzz" }, new[] { "pop" }), CreateRow("fizz", "first", new[] { new[] { "fizz", "buzz", "pop" } }), - CreateRow(3, "first", new[] { new object[] { 3, "buzz", true } }), CreateRow(null, "first", new[] { Array.Empty() }), CreateRow("pop", "last", new[] { new[] { "fizz", "buzz", "pop" } }), - CreateRow(true, "last", new[] { new object[] { 3, "buzz", true } }), CreateRow(null, "last", new[] { Array.Empty() }), CreateRow(0, "indexOf", new[] { "fizz", "buzz", "pop", "fizz" }, "fizz"), CreateRow(3, "lastIndexOf", new[] { "fizz", "buzz", "pop", "fizz" }, "fizz"), From f6dcca0d2bef51d01a496093cf25c320087817c4 Mon Sep 17 00:00:00 2001 From: Levi Date: Wed, 18 Jan 2023 20:22:48 -0500 Subject: [PATCH 05/12] just some comment fix --- .../TypeSystem/FunctionResolverTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs index 8de428142b5..282047d898a 100644 --- a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs +++ b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs @@ -272,12 +272,12 @@ private static IEnumerable GetFirstTestCases() => new[] private static IEnumerable GetLastTestCases() => new[] { - // first(resourceGroup[]) -> resourceGroup + // last(resourceGroup[]) -> resourceGroup new object[] { new TypedArrayType(LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup), default), TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.CreateResourceScopeReference(ResourceScope.ResourceGroup)) }, - // first(['test', 3]) -> 3 + // last(['test', 3]) -> 3 new object[] { new TupleType("['test', 3]", ImmutableArray.Create( @@ -287,7 +287,7 @@ private static IEnumerable GetLastTestCases() => new[] default), new IntegerLiteralType(3) }, - // first([resourceGroup, subscription]) => subscription + // last([resourceGroup, subscription]) => subscription new object[] { new TupleType("[resourceGroup, subscription]", ImmutableArray.Create( From 8931e952638bc4381a14d33634009a12574cdde3 Mon Sep 17 00:00:00 2001 From: Levi Date: Wed, 18 Jan 2023 20:25:58 -0500 Subject: [PATCH 06/12] remove unused imports --- src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs index c1ae1e3a531..5723cbf1516 100644 --- a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs +++ b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs @@ -6,9 +6,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; -using System.Reflection; using System.Text; -using Azure.Deployments.Core.Diagnostics; using Bicep.Core.Diagnostics; using Bicep.Core.Extensions; using Bicep.Core.Features; From 0dc9663fda567d91e7a63c70b9b243efc37d6e9e Mon Sep 17 00:00:00 2001 From: Levi Date: Fri, 20 Jan 2023 23:04:54 -0500 Subject: [PATCH 07/12] Fix tests --- src/Bicep.Core.IntegrationTests/Scenarios/ScopeTests.cs | 2 +- .../Files/user_submitted/201/cloud-shell-vnet/main.bicep | 2 +- .../Files/user_submitted/201/private-aks-cluster/aks.bicep | 2 +- .../user_submitted/201/private-aks-cluster/jumpbox.bicep | 4 ++-- .../201/vm-windows-with-custom-script-extension/main.bicep | 2 +- .../modules/managedDisks-customimagevm.bicep | 2 +- .../modules/managedDisks-customvhdvm.bicep | 2 +- .../wvd-create-hostpool/modules/managedDisks-galleryvm.bicep | 2 +- .../modules/unmanagedDisks-customvhdvm.bicep | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Bicep.Core.IntegrationTests/Scenarios/ScopeTests.cs b/src/Bicep.Core.IntegrationTests/Scenarios/ScopeTests.cs index d3e73ff3dba..16d62e409f7 100644 --- a/src/Bicep.Core.IntegrationTests/Scenarios/ScopeTests.cs +++ b/src/Bicep.Core.IntegrationTests/Scenarios/ScopeTests.cs @@ -187,7 +187,7 @@ param postgreSqlServerId string ] resource postgreSQL 'Microsoft.DBForPostgreSQL/servers@2017-12-01' existing = { - name: last(split(postgreSqlServerId, '/')) + name: last(split(postgreSqlServerId, '/'))! resource database 'databases' = [for (item, index) in PSQL_DATABASES: { name: item.database.name properties: { diff --git a/src/Bicep.Core.Samples/Files/user_submitted/201/cloud-shell-vnet/main.bicep b/src/Bicep.Core.Samples/Files/user_submitted/201/cloud-shell-vnet/main.bicep index 85a893c1e5a..2331285f5a0 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/201/cloud-shell-vnet/main.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/201/cloud-shell-vnet/main.bicep @@ -241,7 +241,7 @@ resource privateDnsZoneARecord 'Microsoft.Network/privateDnsZones/A@2020-01-01' ttl: 3600 aRecords: [ { - ipv4Address: first(first(privateEndpoint.properties.customDnsConfigs).ipAddresses) + ipv4Address: first(first(privateEndpoint.properties.customDnsConfigs)!.ipAddresses)! } ] } diff --git a/src/Bicep.Core.Samples/Files/user_submitted/201/private-aks-cluster/aks.bicep b/src/Bicep.Core.Samples/Files/user_submitted/201/private-aks-cluster/aks.bicep index d53b0ea298c..a8280a3f45c 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/201/private-aks-cluster/aks.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/201/private-aks-cluster/aks.bicep @@ -157,7 +157,7 @@ var aadProfileConfiguration = { tenantID: aadProfileTenantId } -var virtualNetworkName = last(split(virtualNetworkId, '/')) +var virtualNetworkName = last(split(virtualNetworkId, '/'))! resource virtualNetwork 'Microsoft.Network/virtualNetworks@2020-08-01' existing = { name: virtualNetworkName diff --git a/src/Bicep.Core.Samples/Files/user_submitted/201/private-aks-cluster/jumpbox.bicep b/src/Bicep.Core.Samples/Files/user_submitted/201/private-aks-cluster/jumpbox.bicep index 55f83b2437b..c1ff8410d69 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/201/private-aks-cluster/jumpbox.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/201/private-aks-cluster/jumpbox.bicep @@ -81,8 +81,8 @@ var linuxConfiguration = { provisionVMAgent: true } -var virtualNetworkName = last(split(virtualNetworkId, '/')) -var logAnalyticsWorkspaceName = last(split(logAnalyticsWorkspaceId, '/')) +var virtualNetworkName = last(split(virtualNetworkId, '/'))! +var logAnalyticsWorkspaceName = last(split(logAnalyticsWorkspaceId, '/'))! resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-10-01' existing = { name: logAnalyticsWorkspaceName diff --git a/src/Bicep.Core.Samples/Files/user_submitted/201/vm-windows-with-custom-script-extension/main.bicep b/src/Bicep.Core.Samples/Files/user_submitted/201/vm-windows-with-custom-script-extension/main.bicep index 30052b75ccb..dc3faad84d8 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/201/vm-windows-with-custom-script-extension/main.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/201/vm-windows-with-custom-script-extension/main.bicep @@ -250,7 +250,7 @@ var virtualMachineExtensionCustomScript = { fileUris: [ virtualMachineExtensionCustomScriptUri ] - commandToExecute: 'powershell -ExecutionPolicy Unrestricted -File ./${last(split(virtualMachineExtensionCustomScriptUri, '/'))}' + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -File ./${last(split(virtualMachineExtensionCustomScriptUri, '/'))!}' } resource vmext 'Microsoft.Compute/virtualMachines/extensions@2020-06-01' = { diff --git a/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-customimagevm.bicep b/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-customimagevm.bicep index 315afcc9d00..355c039d706 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-customimagevm.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-customimagevm.bicep @@ -125,7 +125,7 @@ param aadJoin bool = false param intune bool = false var emptyArray = [] -var domain_var = ((domain == '') ? last(split(administratorAccountUsername, '@')) : domain) +var domain_var = ((domain == '') ? last(split(administratorAccountUsername, '@'))! : domain) var storageAccountType = rdshVMDiskType var newNsgName = '${rdshPrefix}nsg-${guidValue}' var nsgId = (createNetworkSecurityGroup ? resourceId('Microsoft.Network/networkSecurityGroups', newNsgName) : networkSecurityGroupId) diff --git a/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-customvhdvm.bicep b/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-customvhdvm.bicep index 39fbdf05d80..e4d6d7b2b40 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-customvhdvm.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-customvhdvm.bicep @@ -125,7 +125,7 @@ param aadJoin bool = false param intune bool = false var emptyArray = [] -var domain_var = ((domain == '') ? last(split(administratorAccountUsername, '@')) : domain) +var domain_var = ((domain == '') ? last(split(administratorAccountUsername, '@'))! : domain) var storageAccountType = rdshVMDiskType var imageName_var = '${rdshPrefix}image' var newNsgName = '${rdshPrefix}nsg-${guidValue}' diff --git a/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-galleryvm.bicep b/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-galleryvm.bicep index 4f8a8de8112..596edee4d8a 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-galleryvm.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/managedDisks-galleryvm.bicep @@ -125,7 +125,7 @@ param aadJoin bool = false param intune bool = false var emptyArray = [] -var domain_var = ((domain == '') ? last(split(administratorAccountUsername, '@')) : domain) +var domain_var = ((domain == '') ? last(split(administratorAccountUsername, '@'))! : domain) var storageAccountType = rdshVMDiskType var newNsgName = '${rdshPrefix}nsg-${guidValue}' var nsgId = (createNetworkSecurityGroup ? resourceId('Microsoft.Network/networkSecurityGroups', newNsgName) : networkSecurityGroupId) diff --git a/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/unmanagedDisks-customvhdvm.bicep b/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/unmanagedDisks-customvhdvm.bicep index 60eebb1ce69..5918386853b 100644 --- a/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/unmanagedDisks-customvhdvm.bicep +++ b/src/Bicep.Core.Samples/Files/user_submitted/201/wvd-create-hostpool/modules/unmanagedDisks-customvhdvm.bicep @@ -125,7 +125,7 @@ param aadJoin bool = false param intune bool = false var emptyArray = [] -var domain_var = ((domain == '') ? last(split(administratorAccountUsername, '@')) : domain) +var domain_var = ((domain == '') ? last(split(administratorAccountUsername, '@'))! : domain) var storageAccountName = split(split(vmImageVhdUri, '/')[2], '.')[0] var storageaccount = concat(resourceId(storageAccountResourceGroupName, 'Microsoft.Storage/storageAccounts', storageAccountName)) var newNsgName = '${rdshPrefix}nsg-${guidValue}' From b000e4fa9db33174bf9f36ff364cde97782e2873 Mon Sep 17 00:00:00 2001 From: Levi Date: Sat, 21 Jan 2023 10:58:49 -0500 Subject: [PATCH 08/12] Fix switch statement default to return any type --- src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs index 5723cbf1516..ea90c1a9347 100644 --- a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs +++ b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs @@ -286,7 +286,7 @@ private static IEnumerable GetSystemOverloads(IFeatureProvider { TupleType tupleType => tupleType.Items.FirstOrDefault()?.Type ?? LanguageConstants.Null, ArrayType arrayType => TypeHelper.CreateTypeUnion(LanguageConstants.Null, arrayType.Item.Type), - _ => throw new InvalidOperationException("Could not determine the return type from the provided input") + _ => LanguageConstants.Any }); }, LanguageConstants.Any) .WithGenericDescription(FirstDescription) @@ -308,7 +308,7 @@ private static IEnumerable GetSystemOverloads(IFeatureProvider { TupleType tupleType => tupleType.Items.LastOrDefault()?.Type ?? LanguageConstants.Null, ArrayType arrayType => TypeHelper.CreateTypeUnion(LanguageConstants.Null, arrayType.Item.Type), - _ => throw new InvalidOperationException("Could not determine the return type from the provided input") + _ => LanguageConstants.Any }); }, LanguageConstants.Any) .WithGenericDescription(LastDescription) From ee8bcac42ac99fa94df69279b195a7db9311a1d1 Mon Sep 17 00:00:00 2001 From: Levi Date: Sun, 15 Jan 2023 16:13:41 -0500 Subject: [PATCH 09/12] Handle types in first and last functions --- src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs index ea90c1a9347..c903e017eb6 100644 --- a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs +++ b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs @@ -6,7 +6,9 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; +using System.Reflection; using System.Text; +using Azure.Deployments.Core.Diagnostics; using Bicep.Core.Diagnostics; using Bicep.Core.Extensions; using Bicep.Core.Features; From 4cc72a83125eb91da71fefd58b22cb1f4d6ec373 Mon Sep 17 00:00:00 2001 From: Levi Date: Wed, 18 Jan 2023 20:03:39 -0500 Subject: [PATCH 10/12] Add tests --- src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs index 282047d898a..5029cedcae4 100644 --- a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs +++ b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs @@ -371,8 +371,10 @@ object[] CreateRow(object? returnedLiteral, string functionName, params object[] CreateRow(new[] { "pop" }, "intersection", new[] { "fizz", "buzz", "pop" }, new[] { "snap", "crackle", "pop" }), CreateRow(new[] { "fizz", "buzz", "pop" }, "union", new[] { "fizz", "buzz" }, new[] { "pop" }), CreateRow("fizz", "first", new[] { new[] { "fizz", "buzz", "pop" } }), + CreateRow(3, "first", new[] { new object[] { 3, "buzz", true } }), CreateRow(null, "first", new[] { Array.Empty() }), CreateRow("pop", "last", new[] { new[] { "fizz", "buzz", "pop" } }), + CreateRow(true, "last", new[] { new object[] { 3, "buzz", true } }), CreateRow(null, "last", new[] { Array.Empty() }), CreateRow(0, "indexOf", new[] { "fizz", "buzz", "pop", "fizz" }, "fizz"), CreateRow(3, "lastIndexOf", new[] { "fizz", "buzz", "pop", "fizz" }, "fizz"), From 7fb4fe90aa868b9ce0104348c1fcc1530715afaf Mon Sep 17 00:00:00 2001 From: Levi Date: Wed, 18 Jan 2023 20:21:03 -0500 Subject: [PATCH 11/12] Fix failing tests --- src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs index 5029cedcae4..282047d898a 100644 --- a/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs +++ b/src/Bicep.Core.UnitTests/TypeSystem/FunctionResolverTests.cs @@ -371,10 +371,8 @@ object[] CreateRow(object? returnedLiteral, string functionName, params object[] CreateRow(new[] { "pop" }, "intersection", new[] { "fizz", "buzz", "pop" }, new[] { "snap", "crackle", "pop" }), CreateRow(new[] { "fizz", "buzz", "pop" }, "union", new[] { "fizz", "buzz" }, new[] { "pop" }), CreateRow("fizz", "first", new[] { new[] { "fizz", "buzz", "pop" } }), - CreateRow(3, "first", new[] { new object[] { 3, "buzz", true } }), CreateRow(null, "first", new[] { Array.Empty() }), CreateRow("pop", "last", new[] { new[] { "fizz", "buzz", "pop" } }), - CreateRow(true, "last", new[] { new object[] { 3, "buzz", true } }), CreateRow(null, "last", new[] { Array.Empty() }), CreateRow(0, "indexOf", new[] { "fizz", "buzz", "pop", "fizz" }, "fizz"), CreateRow(3, "lastIndexOf", new[] { "fizz", "buzz", "pop", "fizz" }, "fizz"), From 018b408c7309fe8b326946385688f5a8d1becc8f Mon Sep 17 00:00:00 2001 From: Levi Date: Wed, 18 Jan 2023 20:25:58 -0500 Subject: [PATCH 12/12] remove unused imports --- src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs index c903e017eb6..ea90c1a9347 100644 --- a/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs +++ b/src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs @@ -6,9 +6,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; -using System.Reflection; using System.Text; -using Azure.Deployments.Core.Diagnostics; using Bicep.Core.Diagnostics; using Bicep.Core.Extensions; using Bicep.Core.Features;