in src/Bicep.Core.IntegrationTests/Scenarios/NullabilityTests.cs [38:212]
private static IEnumerable<object[]> GetTemplatesWithSingleUnexpectedlyNullableValue()
{
static object[] Case(string templateWithNullablyTypedValue, string templateWithNonNullAssertion, TypeSymbol expectedType, TypeSymbol actualType) =>
[
templateWithNullablyTypedValue,
templateWithNonNullAssertion,
expectedType,
actualType,
];
return new[]
{
// nullably typed property assignment
Case(
@"
param input string
resource sa 'Microsoft.Storage/storageAccounts@2022-09-01' existing = {
name: last(filter(split(input, '/'), x => true))
}
",
@"
param input string
resource sa 'Microsoft.Storage/storageAccounts@2022-09-01' existing = {
name: last(filter(split(input, '/'), x => true))!
}
",
LanguageConstants.String,
TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.String)
),
// nullably typed function argument
Case(
@"
param input string
output out string = uniqueString(last(filter(split(input, '/'), x => true)))
",
@"
param input string
output out string = uniqueString(last(filter(split(input, '/'), x => true))!)
",
LanguageConstants.String,
TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.String)
),
// nullably typed output value
Case(
@"
param csv string
output firstPrefix string = first(filter(split(csv, ','), x => true))
",
@"
param csv string
output firstPrefix string = first(filter(split(csv, ','), x => true))!
",
LanguageConstants.String,
TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.String)
),
// nullably typed ternary condition
Case(
@"
param input array
var nullableAtIndex = [for i in input: i != null]
output eitherFooOrBar string = first(nullableAtIndex) ? 'foo' : 'bar'
",
@"
param input array
var nullableAtIndex = [for i in input: i != null]
output eitherFooOrBar string = first(nullableAtIndex) ! ? 'foo' : 'bar'
",
LanguageConstants.Bool,
TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.Bool)
),
// nullably typed if condition
Case(
@"
param input array
var nullableAtIndex = [for i in input: i != null]
resource sa 'Microsoft.Storage/storageAccounts@2022-09-01' existing = if (first(nullableAtIndex)) {
name: 'storageacct'
}
",
@"
param input array
var nullableAtIndex = [for i in input: i != null]
resource sa 'Microsoft.Storage/storageAccounts@2022-09-01' existing = if (first(nullableAtIndex)!) {
name: 'storageacct'
}
",
LanguageConstants.Bool,
TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.Bool)
),
// nullably typed array indices
Case(
@"
param input array
output something string = input[first(filter(range(0, length(input)), x => true))]
",
@"
param input array
output something string = input[first(filter(range(0, length(input)), x => true))!]
",
LanguageConstants.Int,
TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.Int)
),
// nullably typed object indices
Case(
@"
param input object
param csv string
output something string = input[first(filter(split(csv, ','), x => true))]
",
@"
param input object
param csv string
output something string = input[first(filter(split(csv, ','), x => true))!]
",
LanguageConstants.String,
TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.String)
),
// nullably typed list comprehension target
Case(
@"
param input array
var arrayOfArrays = [for i in input: range(0, 10)]
var arrayOfOneBuzz = [for i in first(arrayOfArrays): 'buzz']
",
@"
param input array
var arrayOfArrays = [for i in input: range(0, 10)]
var arrayOfOneBuzz = [for i in first(arrayOfArrays)!: 'buzz']
",
LanguageConstants.Array,
TypeHelper.CreateTypeUnion(LanguageConstants.Null, new TypedArrayType(TypeFactory.CreateIntegerType(0, 10), default))
),
// nullably typed parameter defaults
Case(
@"
param csv string
param anotherParam string = first(filter(split(csv, ','), x => true))
",
@"
param csv string
param anotherParam string = first(filter(split(csv, ','), x => true))!
",
LanguageConstants.String,
TypeHelper.CreateTypeUnion(LanguageConstants.Null, LanguageConstants.String)
),
};
}