diff --git a/src/Bicep.Core.IntegrationTests/UserDefinedTypeTests.cs b/src/Bicep.Core.IntegrationTests/UserDefinedTypeTests.cs index c15cec3098e..eeacb524381 100644 --- a/src/Bicep.Core.IntegrationTests/UserDefinedTypeTests.cs +++ b/src/Bicep.Core.IntegrationTests/UserDefinedTypeTests.cs @@ -108,6 +108,7 @@ public void Masked_types_still_accessible_via_qualified_reference() "); result.Should().HaveDiagnostics(new[] { + ("no-unused-types", DiagnosticLevel.Warning, "Type \"string\" is declared but never used."), ("no-unused-params", DiagnosticLevel.Warning, "Parameter \"stringParam\" is declared but never used."), }); } @@ -153,8 +154,10 @@ param intParam constrainedInt result.Should().HaveDiagnostics(new[] { ("BCP308", DiagnosticLevel.Error, "The decorator \"minLength\" may not be used on statements whose declared type is a reference to a user-defined type."), ("BCP308", DiagnosticLevel.Error, "The decorator \"maxLength\" may not be used on statements whose declared type is a reference to a user-defined type."), + ("no-unused-types", DiagnosticLevel.Warning, "Type \"constrainedStringAlias\" is declared but never used."), ("BCP308", DiagnosticLevel.Error, "The decorator \"minValue\" may not be used on statements whose declared type is a reference to a user-defined type."), ("BCP308", DiagnosticLevel.Error, "The decorator \"maxValue\" may not be used on statements whose declared type is a reference to a user-defined type."), + ("no-unused-types", DiagnosticLevel.Warning, "Type \"constrainedIntAlias\" is declared but never used."), ("BCP308", DiagnosticLevel.Error, "The decorator \"minLength\" may not be used on statements whose declared type is a reference to a user-defined type."), ("BCP308", DiagnosticLevel.Error, "The decorator \"maxLength\" may not be used on statements whose declared type is a reference to a user-defined type."), ("BCP308", DiagnosticLevel.Error, "The decorator \"secure\" may not be used on statements whose declared type is a reference to a user-defined type."), @@ -529,7 +532,7 @@ param constrainedString string? param sealedObject {}? "); - result.Should().NotHaveAnyDiagnostics(); + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); } [TestMethod] @@ -746,7 +749,7 @@ public void Union_types_with_single_normalized_member_compile_without_error() type union = 'a' | 'a' """); - result.Should().NotHaveAnyDiagnostics(); + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); result.Template.Should().NotBeNull(); result.Template!.Should().HaveValueAtPath("definitions.union", JToken.Parse(""" @@ -765,7 +768,7 @@ public void Nullable_union_types_do_not_include_null_in_allowed_values_constrain type unionWithOneMember = null | 'a' """); - result.Should().NotHaveAnyDiagnostics(); + result.ExcludingLinterDiagnostics().Should().NotHaveAnyDiagnostics(); result.Template.Should().NotBeNull(); result.Template!.Should().HaveValueAtPath("definitions.union", JToken.Parse(""" @@ -1201,7 +1204,7 @@ public void Invalid_type_property_access_raises_diagnostic(string accessExpressi type test2 = {{accessExpression}} """); - result.Should().HaveDiagnostics(new[] + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { (expectedErrorCode, DiagnosticLevel.Error, expectedErrorMessage), }); @@ -1308,7 +1311,7 @@ public void Invalid_type_index_access_raises_diagnostic(string accessExpression, type test2 = {{accessExpression}} """); - result.Should().HaveDiagnostics(new[] + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { (expectedErrorCode, DiagnosticLevel.Error, expectedErrorMessage), }); @@ -1377,7 +1380,7 @@ public void Invalid_additional_properties_access_raises_diagnostic(string access type test2 = {{accessExpression}} """); - result.Should().HaveDiagnostics(new[] + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { (expectedErrorCode, DiagnosticLevel.Error, expectedErrorMessage), }); @@ -1487,7 +1490,7 @@ public void Invalid_type_items_access_raises_diagnostic(string accessExpression, type test2 = {{accessExpression}} """); - result.Should().HaveDiagnostics(new[] + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[] { (expectedErrorCode, DiagnosticLevel.Error, expectedErrorMessage), }); @@ -1654,7 +1657,7 @@ public void Parameterized_types_should_require_parameterization() new ServiceBuilder().WithFeatureOverrides(new(TestContext)), """type t = resourceInput"""); - result.Should().HaveDiagnostics([ + result.ExcludingLinterDiagnostics().Should().HaveDiagnostics([ ("BCP384", DiagnosticLevel.Error, """The "resourceInput" type requires 1 argument(s)."""), ]); } diff --git a/src/Bicep.Core.Samples/Files/baselines/Imports_LF/main.diagnostics.bicep b/src/Bicep.Core.Samples/Files/baselines/Imports_LF/main.diagnostics.bicep index f0d0a34cc0a..394ce1e6032 100644 --- a/src/Bicep.Core.Samples/Files/baselines/Imports_LF/main.diagnostics.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/Imports_LF/main.diagnostics.bicep @@ -12,6 +12,7 @@ var aliasedBar = mod2.foo //@[04:14) [no-unused-vars (Warning)] Variable "aliasedBar" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-vars) |aliasedBar| type fizzes = fizz[] +//@[05:11) [no-unused-types (Warning)] Type "fizzes" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |fizzes| param fizzParam mod2.fizz //@[06:15) [no-unused-params (Warning)] Parameter "fizzParam" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-params) |fizzParam| diff --git a/src/Bicep.Core.Samples/Files/baselines/InvalidResourceDerivedTypes_LF/main.diagnostics.bicep b/src/Bicep.Core.Samples/Files/baselines/InvalidResourceDerivedTypes_LF/main.diagnostics.bicep index 24ebfd68975..c462c5cf0d6 100644 --- a/src/Bicep.Core.Samples/Files/baselines/InvalidResourceDerivedTypes_LF/main.diagnostics.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/InvalidResourceDerivedTypes_LF/main.diagnostics.bicep @@ -1,45 +1,60 @@ type invalid1 = resourceInput +//@[005:013) [no-unused-types (Warning)] Type "invalid1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid1| //@[016:029) [BCP384 (Error)] The "resourceInput" type requires 1 argument(s). (bicep https://aka.ms/bicep/core-diagnostics#BCP384) |resourceInput| type invalid2 = resourceInput<> +//@[005:013) [no-unused-types (Warning)] Type "invalid2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid2| //@[029:031) [BCP071 (Error)] Expected 1 argument, but got 0. (bicep https://aka.ms/bicep/core-diagnostics#BCP071) |<>| type invalid3 = resourceInput<'abc', 'def'> +//@[005:013) [no-unused-types (Warning)] Type "invalid3" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid3| //@[029:043) [BCP071 (Error)] Expected 1 argument, but got 2. (bicep https://aka.ms/bicep/core-diagnostics#BCP071) |<'abc', 'def'>| type invalid4 = resourceInput +//@[005:013) [no-unused-types (Warning)] Type "invalid4" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid4| //@[030:035) [BCP070 (Error)] Argument of type "{ bar: Astronomer.Astro/organizations }" is not assignable to parameter of type "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP070) |hello| type invalid5 = resourceInput<'Microsoft.Storage/storageAccounts'> +//@[005:013) [no-unused-types (Warning)] Type "invalid5" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid5| //@[030:065) [BCP029 (Error)] The resource type is not valid. Specify a valid resource type of format "@". (bicep https://aka.ms/bicep/core-diagnostics#BCP029) |'Microsoft.Storage/storageAccounts'| type invalid6 = resourceInput<'Microsoft.Storage/storageAccounts@'> +//@[005:013) [no-unused-types (Warning)] Type "invalid6" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid6| //@[030:066) [BCP029 (Error)] The resource type is not valid. Specify a valid resource type of format "@". (bicep https://aka.ms/bicep/core-diagnostics#BCP029) |'Microsoft.Storage/storageAccounts@'| type invalid7 = resourceInput<'Microsoft.Storage/storageAccounts@hello'> +//@[005:013) [no-unused-types (Warning)] Type "invalid7" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid7| //@[030:071) [BCP029 (Error)] The resource type is not valid. Specify a valid resource type of format "@". (bicep https://aka.ms/bicep/core-diagnostics#BCP029) |'Microsoft.Storage/storageAccounts@hello'| type invalid8 = resourceInput<'notARealNamespace:Microsoft.Storage/storageAccounts@2022-09-01'> +//@[005:013) [no-unused-types (Warning)] Type "invalid8" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid8| //@[030:094) [BCP208 (Error)] The specified namespace "notARealNamespace" is not recognized. Specify a resource reference using one of the following namespaces: "az", "sys". (bicep https://aka.ms/bicep/core-diagnostics#BCP208) |'notARealNamespace:Microsoft.Storage/storageAccounts@2022-09-01'| type invalid9 = resourceInput<':Microsoft.Storage/storageAccounts@2022-09-01'> +//@[005:013) [no-unused-types (Warning)] Type "invalid9" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid9| //@[030:077) [BCP029 (Error)] The resource type is not valid. Specify a valid resource type of format "@". (bicep https://aka.ms/bicep/core-diagnostics#BCP029) |':Microsoft.Storage/storageAccounts@2022-09-01'| type invalid10 = resourceInput<'abc' 'def'> +//@[005:014) [no-unused-types (Warning)] Type "invalid10" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid10| //@[030:043) [BCP071 (Error)] Expected 1 argument, but got 2. (bicep https://aka.ms/bicep/core-diagnostics#BCP071) |<'abc' 'def'>| //@[037:037) [BCP236 (Error)] Expected a new line or comma character at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP236) || type invalid11 = resourceInput<123> +//@[005:014) [no-unused-types (Warning)] Type "invalid11" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid11| //@[031:034) [BCP070 (Error)] Argument of type "123" is not assignable to parameter of type "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP070) |123| type invalid12 = resourceInput +//@[005:014) [no-unused-types (Warning)] Type "invalid12" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalid12| //@[030:047) [BCP071 (Error)] Expected 1 argument, but got 2. (bicep https://aka.ms/bicep/core-diagnostics#BCP071) || //@[044:044) [BCP236 (Error)] Expected a new line or comma character at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP236) || //@[045:045) [BCP243 (Error)] Parentheses must contain exactly one expression. (bicep https://aka.ms/bicep/core-diagnostics#BCP243) || type thisIsWeird = resourceInput\n>| */'Astronomer.Astro/organizations@2023-08-01-preview' /// > > type interpolated = resourceInput<'Microsoft.${'Storage'}/storageAccounts@2022-09-01'> +//@[005:017) [no-unused-types (Warning)] Type "interpolated" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |interpolated| //@[034:085) [BCP032 (Error)] The value must be a compile-time constant. (bicep https://aka.ms/bicep/core-diagnostics#BCP032) |'Microsoft.${'Storage'}/storageAccounts@2022-09-01'| @sealed() //@[000:009) [BCP386 (Error)] The decorator "sealed" may not be used on statements whose declared type is a reference to a resource-derived type. (bicep https://aka.ms/bicep/core-diagnostics#BCP386) |@sealed()| type shouldNotBeSealable = resourceInput<'Microsoft.Storage/storageAccounts@2022-09-01'> +//@[005:024) [no-unused-types (Warning)] Type "shouldNotBeSealable" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |shouldNotBeSealable| //@[027:088) [BCP394 (Error)] Resource-derived type expressions must dereference a property within the resource body. Using the entire resource body type is not permitted. (bicep https://aka.ms/bicep/core-diagnostics#BCP394) |resourceInput<'Microsoft.Storage/storageAccounts@2022-09-01'>| type hello = { @@ -50,14 +65,19 @@ type hello = { } type typoInPropertyName = resourceInput<'Microsoft.Storage/storageAccounts@2023-01-01'>.nom +//@[005:023) [no-unused-types (Warning)] Type "typoInPropertyName" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |typoInPropertyName| //@[088:091) [BCP053 (Error)] The type "Microsoft.Storage/storageAccounts" does not contain property "nom". Available properties include "apiVersion", "asserts", "dependsOn", "eTag", "extendedLocation", "id", "identity", "kind", "location", "managedBy", "managedByExtended", "name", "plan", "properties", "scale", "sku", "tags", "type", "zones". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |nom| type typoInPropertyName2 = resourceInput<'Microsoft.KeyVault/vaults@2022-07-01'>.properties.accessPolicies[*].tenatId +//@[005:024) [no-unused-types (Warning)] Type "typoInPropertyName2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |typoInPropertyName2| //@[110:117) [BCP083 (Error)] The type "AccessPolicyEntry" does not contain property "tenatId". Did you mean "tenantId"? (bicep https://aka.ms/bicep/core-diagnostics#BCP083) |tenatId| type typoInPropertyName3 = resourceInput<'Microsoft.KeyVault/vaults@2022-07-01'>.properties[*].accessPolicies.tenantId +//@[005:024) [no-unused-types (Warning)] Type "typoInPropertyName3" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |typoInPropertyName3| //@[091:094) [BCP390 (Error)] The array item type access operator ('[*]') can only be used with typed arrays. (bicep https://aka.ms/bicep/core-diagnostics#BCP390) |[*]| type typoInPropertyName4 = resourceInput<'Microsoft.Web/customApis@2016-06-01'>.properties.connectionParameters.*.tyype +//@[005:024) [no-unused-types (Warning)] Type "typoInPropertyName4" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |typoInPropertyName4| //@[114:119) [BCP083 (Error)] The type "ConnectionParameter" does not contain property "tyype". Did you mean "type"? (bicep https://aka.ms/bicep/core-diagnostics#BCP083) |tyype| type typoInPropertyName5 = resourceInput<'Microsoft.Web/customApis@2016-06-01'>.properties.*.connectionParameters.type +//@[005:024) [no-unused-types (Warning)] Type "typoInPropertyName5" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |typoInPropertyName5| //@[091:092) [BCP389 (Error)] The type "CustomApiPropertiesDefinition" does not declare an additional properties type. (bicep https://aka.ms/bicep/core-diagnostics#BCP389) |*| module mod 'modules/mod.json' = { diff --git a/src/Bicep.Core.Samples/Files/baselines/InvalidTypeDeclarations_LF/main.diagnostics.bicep b/src/Bicep.Core.Samples/Files/baselines/InvalidTypeDeclarations_LF/main.diagnostics.bicep index e715f0d8ee5..8be283141b4 100644 --- a/src/Bicep.Core.Samples/Files/baselines/InvalidTypeDeclarations_LF/main.diagnostics.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/InvalidTypeDeclarations_LF/main.diagnostics.bicep @@ -4,22 +4,27 @@ type 44 //@[07:007) [BCP018 (Error)] Expected the "=" character at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP018) || type noAssignment +//@[05:017) [no-unused-types (Warning)] Type "noAssignment" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |noAssignment| //@[17:017) [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) || //@[17:017) [BCP018 (Error)] Expected the "=" character at this location. (bicep https://aka.ms/bicep/core-diagnostics#BCP018) || type incompleteAssignment = +//@[05:025) [no-unused-types (Warning)] Type "incompleteAssignment" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |incompleteAssignment| //@[27:027) [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) || type resource = bool //@[05:013) [BCP301 (Error)] The type name "resource" is reserved and may not be attached to a user-defined type. (bicep https://aka.ms/bicep/core-diagnostics#BCP301) |resource| +//@[05:013) [no-unused-types (Warning)] Type "resource" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |resource| @sealed() //@[00:009) [BCP124 (Error)] The decorator "sealed" can only be attached to targets of type "object", but the target has type "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP124) |@sealed()| type sealedString = string +//@[05:017) [no-unused-types (Warning)] Type "sealedString" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |sealedString| @sealed() //@[00:009) [BCP316 (Error)] The "sealed" decorator may not be used on object types with an explicit additional properties type declaration. (bicep https://aka.ms/bicep/core-diagnostics#BCP316) |@sealed()| type sealedDictionary = { +//@[05:021) [no-unused-types (Warning)] Type "sealedDictionary" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |sealedDictionary| *: string } @@ -29,24 +34,30 @@ type disallowedUnion = 'foo'|21 type validStringLiteralUnion = 'foo'|'bar'|'baz' type validUnionInvalidAddition = validStringLiteralUnion|10 +//@[05:030) [no-unused-types (Warning)] Type "validUnionInvalidAddition" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |validUnionInvalidAddition| //@[33:059) [BCP294 (Error)] Type unions must be reducible to a single ARM type (such as 'string', 'int', or 'bool'). (bicep https://aka.ms/bicep/core-diagnostics#BCP294) |validStringLiteralUnion|10| type invalidUnionInvalidAddition = disallowedUnion|true +//@[05:032) [no-unused-types (Warning)] Type "invalidUnionInvalidAddition" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalidUnionInvalidAddition| //@[35:055) [BCP294 (Error)] Type unions must be reducible to a single ARM type (such as 'string', 'int', or 'bool'). (bicep https://aka.ms/bicep/core-diagnostics#BCP294) |disallowedUnion|true| type nullLiteral = null +//@[05:016) [no-unused-types (Warning)] Type "nullLiteral" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |nullLiteral| //@[19:023) [BCP289 (Error)] The type definition is not valid. (bicep https://aka.ms/bicep/core-diagnostics#BCP289) |null| type unionOfNulls = null|null +//@[05:017) [no-unused-types (Warning)] Type "unionOfNulls" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |unionOfNulls| //@[20:029) [BCP294 (Error)] Type unions must be reducible to a single ARM type (such as 'string', 'int', or 'bool'). (bicep https://aka.ms/bicep/core-diagnostics#BCP294) |null|null| @minLength(3) //@[00:013) [BCP124 (Error)] The decorator "minLength" can only be attached to targets of type "array | string", but the target has type "int". (bicep https://aka.ms/bicep/core-diagnostics#BCP124) |@minLength(3)| type lengthConstrainedInt = int +//@[05:025) [no-unused-types (Warning)] Type "lengthConstrainedInt" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |lengthConstrainedInt| @minValue(3) //@[00:012) [BCP124 (Error)] The decorator "minValue" can only be attached to targets of type "int", but the target has type "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP124) |@minValue(3)| type valueConstrainedString = string +//@[05:027) [no-unused-types (Warning)] Type "valueConstrainedString" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |valueConstrainedString| type tautology = tautology //@[05:014) [BCP298 (Error)] This type definition includes itself as required component, which creates a constraint that cannot be fulfilled. (bicep https://aka.ms/bicep/core-diagnostics#BCP298) |tautology| @@ -74,6 +85,7 @@ type cycleBack = cycleRoot //@[05:014) [BCP299 (Error)] This type definition includes itself as a required component via a cycle ("cycleBack" -> "cycleRoot" -> "connector"). (bicep https://aka.ms/bicep/core-diagnostics#BCP299) |cycleBack| type objectWithInvalidPropertyDecorators = { +//@[05:040) [no-unused-types (Warning)] Type "objectWithInvalidPropertyDecorators" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |objectWithInvalidPropertyDecorators| @sealed() //@[02:011) [BCP124 (Error)] The decorator "sealed" can only be attached to targets of type "object", but the target has type "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP124) |@sealed()| fooProp: string @@ -92,6 +104,7 @@ type objectWithInvalidRecursion = { } type arrayWithInvalidMember = objectWithInvalidRecursion[] +//@[05:027) [no-unused-types (Warning)] Type "arrayWithInvalidMember" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |arrayWithInvalidMember| @sealed() //@[00:009) [BCP124 (Error)] The decorator "sealed" can only be attached to targets of type "object", but the target has type "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP124) |@sealed()| @@ -147,64 +160,79 @@ type typeG = { } type primitiveUnion = | bool | bool +//@[05:019) [no-unused-types (Warning)] Type "primitiveUnion" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |primitiveUnion| //@[24:028) [BCP293 (Error)] All members of a union type declaration must be literal values. (bicep https://aka.ms/bicep/core-diagnostics#BCP293) |bool| //@[31:035) [BCP293 (Error)] All members of a union type declaration must be literal values. (bicep https://aka.ms/bicep/core-diagnostics#BCP293) |bool| type objectUnion = typeA | typeB +//@[05:016) [no-unused-types (Warning)] Type "objectUnion" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |objectUnion| //@[19:024) [BCP293 (Error)] All members of a union type declaration must be literal values. (bicep https://aka.ms/bicep/core-diagnostics#BCP293) |typeA| //@[27:032) [BCP293 (Error)] All members of a union type declaration must be literal values. (bicep https://aka.ms/bicep/core-diagnostics#BCP293) |typeB| @discriminator() //@[14:016) [BCP071 (Error)] Expected 1 argument, but got 0. (bicep https://aka.ms/bicep/core-diagnostics#BCP071) |()| type noDiscriminatorParam = typeA | typeB +//@[05:025) [no-unused-types (Warning)] Type "noDiscriminatorParam" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |noDiscriminatorParam| @discriminator(true) //@[15:019) [BCP070 (Error)] Argument of type "true" is not assignable to parameter of type "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP070) |true| type wrongDiscriminatorParamType = typeA | typeB +//@[05:032) [no-unused-types (Warning)] Type "wrongDiscriminatorParamType" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |wrongDiscriminatorParamType| @discriminator('nonexistent') type discriminatorPropertyNotExistAtAll = typeA | typeB +//@[05:039) [no-unused-types (Warning)] Type "discriminatorPropertyNotExistAtAll" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorPropertyNotExistAtAll| //@[42:047) [BCP364 (Error)] The property "nonexistent" must be a required string literal on all union member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP364) |typeA| //@[50:055) [BCP364 (Error)] The property "nonexistent" must be a required string literal on all union member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP364) |typeB| @discriminator('nonexistent') //@[00:029) [BCP366 (Error)] The discriminator property name must be "nonexistent" on all union member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP366) |@discriminator('nonexistent')| type discriminatorPropertyMismatch = unionAB +//@[05:034) [no-unused-types (Warning)] Type "discriminatorPropertyMismatch" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorPropertyMismatch| @discriminator('type') type discriminatorPropertyNotExistOnAtLeastOne = typeA | { value: bool } +//@[05:046) [no-unused-types (Warning)] Type "discriminatorPropertyNotExistOnAtLeastOne" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorPropertyNotExistOnAtLeastOne| //@[57:072) [BCP364 (Error)] The property "type" must be a required string literal on all union member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP364) |{ value: bool }| @discriminator('type') //@[00:022) [BCP363 (Error)] The "discriminator" decorator can only be applied to object-only union types with unique member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP363) |@discriminator('type')| type discriminatorWithOnlyOneMember = typeA +//@[05:035) [no-unused-types (Warning)] Type "discriminatorWithOnlyOneMember" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorWithOnlyOneMember| @discriminator('type') type discriminatorPropertyNotRequiredStringLiteral1 = typeA | typeF +//@[05:051) [no-unused-types (Warning)] Type "discriminatorPropertyNotRequiredStringLiteral1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorPropertyNotRequiredStringLiteral1| //@[62:067) [BCP364 (Error)] The property "type" must be a required string literal on all union member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP364) |typeF| @discriminator('type') type discriminatorPropertyNotRequiredStringLiteral2 = typeA | typeG +//@[05:051) [no-unused-types (Warning)] Type "discriminatorPropertyNotRequiredStringLiteral2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorPropertyNotRequiredStringLiteral2| //@[62:067) [BCP364 (Error)] The property "type" must be a required string literal on all union member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP364) |typeG| @discriminator('type') type discriminatorDuplicatedMember1 = typeA | typeA +//@[05:035) [no-unused-types (Warning)] Type "discriminatorDuplicatedMember1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorDuplicatedMember1| @discriminator('type') type discriminatorDuplicatedMember2 = typeA | { type: 'a', config: object } +//@[05:035) [no-unused-types (Warning)] Type "discriminatorDuplicatedMember2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorDuplicatedMember2| //@[46:075) [BCP365 (Error)] The value "'a'" for discriminator property "type" is duplicated across multiple union member types. The value must be unique across all union member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP365) |{ type: 'a', config: object }| //@[67:073) [use-user-defined-types (Warning)] Use user-defined types instead of 'object' or 'array'. (bicep core linter https://aka.ms/bicep/linter-diagnostics#use-user-defined-types) |object| @discriminator('type') type discriminatorOnlyOneNonNullMember1 = typeA | null +//@[05:039) [no-unused-types (Warning)] Type "discriminatorOnlyOneNonNullMember1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorOnlyOneNonNullMember1| //@[50:054) [BCP286 (Error)] This union member is invalid because it cannot be assigned to the 'object' type. (bicep https://aka.ms/bicep/core-diagnostics#BCP286) |null| @discriminator('type') //@[00:022) [BCP363 (Error)] The "discriminator" decorator can only be applied to object-only union types with unique member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP363) |@discriminator('type')| type discriminatorOnlyOneNonNullMember2 = (typeA)? +//@[05:039) [no-unused-types (Warning)] Type "discriminatorOnlyOneNonNullMember2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorOnlyOneNonNullMember2| @discriminator('type') type discriminatorMemberHasAdditionalProperties = typeA | typeE +//@[05:047) [no-unused-types (Warning)] Type "discriminatorMemberHasAdditionalProperties" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorMemberHasAdditionalProperties| @discriminator('type') type discriminatorSelfCycle1 = typeA | discriminatorSelfCycle1 @@ -245,11 +273,13 @@ type discriminatorInnerSelfCycle2 = typeA | discriminatorInnerSelfCycle2Helper //@[00:022) [BCP363 (Error)] The "discriminator" decorator can only be applied to object-only union types with unique member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP363) |@discriminator('type')| //@[00:022) [BCP124 (Error)] The decorator "discriminator" can only be attached to targets of type "object", but the target has type "[typeA, typeB]". (bicep https://aka.ms/bicep/core-diagnostics#BCP124) |@discriminator('type')| type discriminatorTupleBadType1 = [typeA, typeB] +//@[05:031) [no-unused-types (Warning)] Type "discriminatorTupleBadType1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorTupleBadType1| @discriminator('type') //@[00:022) [BCP363 (Error)] The "discriminator" decorator can only be applied to object-only union types with unique member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP363) |@discriminator('type')| //@[00:022) [BCP124 (Error)] The decorator "discriminator" can only be attached to targets of type "object", but the target has type "[typeA | typeB]". (bicep https://aka.ms/bicep/core-diagnostics#BCP124) |@discriminator('type')| type discriminatorTupleBadType2 = [typeA | typeB] +//@[05:031) [no-unused-types (Warning)] Type "discriminatorTupleBadType2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorTupleBadType2| //@[35:040) [BCP293 (Error)] All members of a union type declaration must be literal values. (bicep https://aka.ms/bicep/core-diagnostics#BCP293) |typeA| //@[43:048) [BCP293 (Error)] All members of a union type declaration must be literal values. (bicep https://aka.ms/bicep/core-diagnostics#BCP293) |typeB| @@ -257,23 +287,27 @@ type discriminatorTupleBadType2 = [typeA | typeB] //@[00:022) [BCP363 (Error)] The "discriminator" decorator can only be applied to object-only union types with unique member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP363) |@discriminator('type')| //@[00:022) [BCP124 (Error)] The decorator "discriminator" can only be attached to targets of type "object", but the target has type "[typeA | typeB, typeC | typeD]". (bicep https://aka.ms/bicep/core-diagnostics#BCP124) |@discriminator('type')| type discriminatorTupleBadType3 = [typeA | typeB, typeC | typeD] +//@[05:031) [no-unused-types (Warning)] Type "discriminatorTupleBadType3" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorTupleBadType3| //@[35:040) [BCP293 (Error)] All members of a union type declaration must be literal values. (bicep https://aka.ms/bicep/core-diagnostics#BCP293) |typeA| //@[43:048) [BCP293 (Error)] All members of a union type declaration must be literal values. (bicep https://aka.ms/bicep/core-diagnostics#BCP293) |typeB| //@[50:055) [BCP293 (Error)] All members of a union type declaration must be literal values. (bicep https://aka.ms/bicep/core-diagnostics#BCP293) |typeC| //@[58:063) [BCP293 (Error)] All members of a union type declaration must be literal values. (bicep https://aka.ms/bicep/core-diagnostics#BCP293) |typeD| type discriminatorInlineAdditionalPropsBadType1 = { +//@[05:047) [no-unused-types (Warning)] Type "discriminatorInlineAdditionalPropsBadType1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorInlineAdditionalPropsBadType1| @discriminator('type') //@[02:024) [BCP363 (Error)] The "discriminator" decorator can only be applied to object-only union types with unique member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP363) |@discriminator('type')| *: typeA } type discriminatorInlineAdditionalPropsBadType2 = { +//@[05:047) [no-unused-types (Warning)] Type "discriminatorInlineAdditionalPropsBadType2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorInlineAdditionalPropsBadType2| @discriminator('type') *: typeA | typeA } type discriminatorInlineAdditionalPropsBadType3 = { +//@[05:047) [no-unused-types (Warning)] Type "discriminatorInlineAdditionalPropsBadType3" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorInlineAdditionalPropsBadType3| @discriminator('type') //@[02:024) [BCP363 (Error)] The "discriminator" decorator can only be applied to object-only union types with unique member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP363) |@discriminator('type')| //@[02:024) [BCP124 (Error)] The decorator "discriminator" can only be attached to targets of type "object", but the target has type "string". (bicep https://aka.ms/bicep/core-diagnostics#BCP124) |@discriminator('type')| @@ -282,10 +316,12 @@ type discriminatorInlineAdditionalPropsBadType3 = { @discriminator('type') type discriminatedUnionDuplicateMemberInsensitive = { type: 'a', value: string } | { type: 'A', value: int } +//@[05:049) [no-unused-types (Warning)] Type "discriminatedUnionDuplicateMemberInsensitive" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatedUnionDuplicateMemberInsensitive| //@[83:108) [BCP365 (Error)] The value "'A'" for discriminator property "type" is duplicated across multiple union member types. The value must be unique across all union member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP365) |{ type: 'A', value: int }| @discriminator('TYPE') type discriminatedUnionCaseSensitiveDiscriminator = { type: 'a', value: string } | { type: 'b', value: int } +//@[05:049) [no-unused-types (Warning)] Type "discriminatedUnionCaseSensitiveDiscriminator" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatedUnionCaseSensitiveDiscriminator| //@[52:080) [BCP364 (Error)] The property "TYPE" must be a required string literal on all union member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP364) |{ type: 'a', value: string }| //@[83:108) [BCP364 (Error)] The property "TYPE" must be a required string literal on all union member types. (bicep https://aka.ms/bicep/core-diagnostics#BCP364) |{ type: 'b', value: int }| @@ -312,11 +348,13 @@ output discriminatorOutputBadType2 object = { prop: 'value' } type strings = string[] type invalidTupleAccess = strings[0] +//@[05:023) [no-unused-types (Warning)] Type "invalidTupleAccess" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalidTupleAccess| //@[34:035) [BCP388 (Error)] Cannot access elements of type "string[]" by index. An tuple type is required. (bicep https://aka.ms/bicep/core-diagnostics#BCP388) |0| type stringTuple = [string, string] type invalidItemTypeAccess = stringTuple[*] +//@[05:026) [no-unused-types (Warning)] Type "invalidItemTypeAccess" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalidItemTypeAccess| //@[40:043) [BCP390 (Error)] The array item type access operator ('[*]') can only be used with typed arrays. (bicep https://aka.ms/bicep/core-diagnostics#BCP390) |[*]| type anObject = { @@ -324,6 +362,7 @@ type anObject = { } type invalidAdditionalPropertiesAccess = anObject.* +//@[05:038) [no-unused-types (Warning)] Type "invalidAdditionalPropertiesAccess" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalidAdditionalPropertiesAccess| //@[50:051) [BCP389 (Error)] The type "{ property: string }" does not declare an additional properties type. (bicep https://aka.ms/bicep/core-diagnostics#BCP389) |*| type stringDict = { @@ -331,5 +370,6 @@ type stringDict = { } type invalidPropertyAccess = stringDict.property +//@[05:026) [no-unused-types (Warning)] Type "invalidPropertyAccess" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |invalidPropertyAccess| //@[40:048) [BCP052 (Error)] The type "{ *: string }" does not contain property "property". (bicep https://aka.ms/bicep/core-diagnostics#BCP052) |property| diff --git a/src/Bicep.Core.Samples/Files/baselines/ResourceDerivedTypes_LF/main.diagnostics.bicep b/src/Bicep.Core.Samples/Files/baselines/ResourceDerivedTypes_LF/main.diagnostics.bicep index 5b61dafe65a..ebc26228c87 100644 --- a/src/Bicep.Core.Samples/Files/baselines/ResourceDerivedTypes_LF/main.diagnostics.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/ResourceDerivedTypes_LF/main.diagnostics.bicep @@ -1,6 +1,8 @@ type foo = resourceInput<'Microsoft.Storage/storageAccounts@2023-01-01'>.name +//@[5:08) [no-unused-types (Warning)] Type "foo" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |foo| type test = { +//@[5:09) [no-unused-types (Warning)] Type "test" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |test| resA: resourceInput<'Microsoft.Storage/storageAccounts@2023-01-01'>.name resB: sys.resourceInput<'Microsoft.Storage/storageAccounts@2022-09-01'>.name resC: sys.array @@ -8,6 +10,7 @@ type test = { } type strangeFormatting = { +//@[5:22) [no-unused-types (Warning)] Type "strangeFormatting" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |strangeFormatting| test: resourceInput< 'Astronomer.Astro/organizations@2023-08-01-preview' @@ -19,13 +22,14 @@ type strangeFormatting = { @description('I love space(s)') type test2 = resourceInput< +//@[5:10) [no-unused-types (Warning)] Type "test2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |test2| 'Astronomer.Astro/organizations@2023-08-01-preview' >.name param bar resourceInput<'Microsoft.Resources/tags@2022-09-01'>.properties = { -//@[6:9) [no-unused-params (Warning)] Parameter "bar" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-params) |bar| +//@[6:09) [no-unused-params (Warning)] Parameter "bar" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-params) |bar| tags: { fizz: 'buzz' snap: 'crackle' @@ -35,6 +39,9 @@ param bar resourceInput<'Microsoft.Resources/tags@2022-09-01'>.properties = { output baz resourceInput<'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31'>.name = 'myId' type storageAccountName = resourceInput<'Microsoft.Storage/storageAccounts@2023-01-01'>.name +//@[5:23) [no-unused-types (Warning)] Type "storageAccountName" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |storageAccountName| type accessPolicy = resourceInput<'Microsoft.KeyVault/vaults@2022-07-01'>.properties.accessPolicies[*] +//@[5:17) [no-unused-types (Warning)] Type "accessPolicy" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |accessPolicy| type tag = resourceInput<'Microsoft.Resources/tags@2022-09-01'>.properties.tags.* +//@[5:08) [no-unused-types (Warning)] Type "tag" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |tag| diff --git a/src/Bicep.Core.Samples/Files/baselines/TypeDeclarations_LF/main.diagnostics.bicep b/src/Bicep.Core.Samples/Files/baselines/TypeDeclarations_LF/main.diagnostics.bicep index 60e01192a01..df8be895e5a 100644 --- a/src/Bicep.Core.Samples/Files/baselines/TypeDeclarations_LF/main.diagnostics.bicep +++ b/src/Bicep.Core.Samples/Files/baselines/TypeDeclarations_LF/main.diagnostics.bicep @@ -21,6 +21,7 @@ type foo = { } type fooProperty = foo.objectProp.intProp +//@[05:16) [no-unused-types (Warning)] Type "fooProperty" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |fooProperty| @minLength(3) @description('An array of array of arrays of arrays of ints') @@ -32,14 +33,18 @@ type fooProperty = foo.objectProp.intProp type bar = int[][][][] type barElement = bar[*] +//@[05:15) [no-unused-types (Warning)] Type "barElement" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |barElement| type aUnion = 'snap'|'crackle'|'pop' type singleMemberUnion = | 'alone' +//@[05:22) [no-unused-types (Warning)] Type "singleMemberUnion" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |singleMemberUnion| type expandedUnion = aUnion|'fizz'|'buzz'|'pop' +//@[05:18) [no-unused-types (Warning)] Type "expandedUnion" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |expandedUnion| type tupleUnion = ['foo', 'bar', 'baz'] +//@[05:15) [no-unused-types (Warning)] Type "tupleUnion" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |tupleUnion| |['fizz', 'buzz'] |['snap', 'crackle', 'pop'] @@ -74,16 +79,19 @@ type tuple = [ ] type tupleSecondItem = tuple[1] +//@[05:20) [no-unused-types (Warning)] Type "tupleSecondItem" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |tupleSecondItem| type stringStringDictionary = { *: string } type stringStringDictionaryValue = stringStringDictionary.* +//@[05:32) [no-unused-types (Warning)] Type "stringStringDictionaryValue" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |stringStringDictionaryValue| @minValue(1) @maxValue(10) type constrainedInt = int +//@[05:19) [no-unused-types (Warning)] Type "constrainedInt" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |constrainedInt| param mightIncludeNull ({key: 'value'} | null)[] @@ -102,8 +110,10 @@ output maybeNull string? = maybeNull type nullable = string? type nonNullable = nullable! +//@[05:16) [no-unused-types (Warning)] Type "nonNullable" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |nonNullable| type withOptionalAnyProp = { +//@[05:24) [no-unused-types (Warning)] Type "withOptionalAnyProp" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |withOptionalAnyProp| requiredProp: string @description('An optional any-typed property') optionalAny: any? @@ -127,6 +137,7 @@ type typeC = { } type typeD = { +//@[05:10) [no-unused-types (Warning)] Type "typeD" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |typeD| type: 'd' value: object //@[09:15) [use-user-defined-types (Warning)] Use user-defined types instead of 'object' or 'array'. (bicep core linter https://aka.ms/bicep/linter-diagnostics#use-user-defined-types) |object| @@ -153,25 +164,30 @@ type discriminatedUnion3 = discriminatedUnion1 | discriminatedUnion2 | { type: ' @discriminator('type') type discriminatedUnion4 = discriminatedUnion1 | (discriminatedUnion2 | typeE) +//@[05:24) [no-unused-types (Warning)] Type "discriminatedUnion4" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatedUnion4| @discriminator('type') type discriminatedUnion5 = (typeA | typeB)? @discriminator('type') type discriminatedUnion6 = (typeA | typeB)! +//@[05:24) [no-unused-types (Warning)] Type "discriminatedUnion6" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatedUnion6| type inlineDiscriminatedUnion1 = { +//@[05:30) [no-unused-types (Warning)] Type "inlineDiscriminatedUnion1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |inlineDiscriminatedUnion1| @discriminator('type') prop: typeA | typeC } type inlineDiscriminatedUnion2 = { +//@[05:30) [no-unused-types (Warning)] Type "inlineDiscriminatedUnion2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |inlineDiscriminatedUnion2| @discriminator('type') prop: { type: 'a', value: bool } | typeB } @discriminator('type') type inlineDiscriminatedUnion3 = { +//@[05:30) [no-unused-types (Warning)] Type "inlineDiscriminatedUnion3" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |inlineDiscriminatedUnion3| type: 'a' @discriminator('type') prop: { type: 'a', value: bool } | typeB @@ -182,27 +198,32 @@ type inlineDiscriminatedUnion3 = { } type inlineDiscriminatedUnion4 = { +//@[05:30) [no-unused-types (Warning)] Type "inlineDiscriminatedUnion4" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |inlineDiscriminatedUnion4| @discriminator('type') prop: (typeA | typeC)? } type discriminatorUnionAsPropertyType = { +//@[05:37) [no-unused-types (Warning)] Type "discriminatorUnionAsPropertyType" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorUnionAsPropertyType| prop1: discriminatedUnion1 prop2: discriminatedUnion3 } type discriminatedUnionInlineAdditionalProps1 = { +//@[05:45) [no-unused-types (Warning)] Type "discriminatedUnionInlineAdditionalProps1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatedUnionInlineAdditionalProps1| @discriminator('type') *: typeA | typeB } type discriminatedUnionInlineAdditionalProps2 = { +//@[05:45) [no-unused-types (Warning)] Type "discriminatedUnionInlineAdditionalProps2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatedUnionInlineAdditionalProps2| @discriminator('type') *: (typeA | typeB)? } @discriminator('type') type discriminatorMemberHasAdditionalProperties1 = typeA | typeF | { type: 'g', *: int } +//@[05:48) [no-unused-types (Warning)] Type "discriminatorMemberHasAdditionalProperties1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatorMemberHasAdditionalProperties1| @discriminator('type') type discriminatorInnerSelfOptionalCycle1 = typeA | { @@ -217,17 +238,20 @@ type discriminatedUnionMemberOptionalCycle1 = { } type discriminatedUnionMemberOptionalCycle2 = { +//@[05:43) [no-unused-types (Warning)] Type "discriminatedUnionMemberOptionalCycle2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatedUnionMemberOptionalCycle2| type: 'b' @discriminator('type') *: typeA | discriminatedUnionMemberOptionalCycle1 } type discriminatedUnionTuple1 = [ +//@[05:29) [no-unused-types (Warning)] Type "discriminatedUnionTuple1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatedUnionTuple1| discriminatedUnion1 string ] type discriminatedUnionInlineTuple1 = [ +//@[05:35) [no-unused-types (Warning)] Type "discriminatedUnionInlineTuple1" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |discriminatedUnionInlineTuple1| @discriminator('type') typeA | typeB | { type: 'c', value: object } //@[38:44) [use-user-defined-types (Warning)] Use user-defined types instead of 'object' or 'array'. (bicep core linter https://aka.ms/bicep/linter-diagnostics#use-user-defined-types) |object| diff --git a/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/NoUnusedTypesRuleTests.cs b/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/NoUnusedTypesRuleTests.cs new file mode 100644 index 00000000000..c73030b084a --- /dev/null +++ b/src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/NoUnusedTypesRuleTests.cs @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Bicep.Core.Analyzers.Linter.Rules; +using Bicep.Core.UnitTests.Assertions; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Bicep.Core.UnitTests.Diagnostics.LinterRuleTests +{ + [TestClass] + public class NoUnusedTypesRuleTests : LinterRuleTestsBase + { + [TestMethod] + public void TypeNameInFormattedMessage() + { + var ruleToTest = new NoUnusedTypesRule(); + ruleToTest.GetMessage(nameof(ruleToTest)).Should().Be($"Type \"{nameof(ruleToTest)}\" is declared but never used."); + } + + private void CompileAndTest(string text, params string[] unusedTypes) + { + CompileAndTest(text, new(OnCompileErrors.IncludeErrors), unusedTypes); + } + + private void CompileAndTest(string text, Options options, params string[] unusedTypes) + { + AssertLinterRuleDiagnostics(NoUnusedTypesRule.Code, text, diags => + { + if (unusedTypes.Any()) + { + var rule = new NoUnusedTypesRule(); + string[] expectedMessages = unusedTypes.Select(p => rule.GetMessage(p)).ToArray(); + diags.Select(e => e.Message).Should().ContainInOrder(expectedMessages); + } + else + { + diags.Should().BeEmpty(); + } + }, + options); + } + + [DataRow(@" + type unusedType = string + type usedType = int + param foo usedType + output bar usedType = foo + ", + "unusedType")] + [DataRow(@" + type type1 = string + type type2 = int + type type3 = bool + ", + "type1", "type2", "type3")] + [DataRow(@" + type usedType = string + param foo usedType + output bar usedType = foo + ")] + [DataRow(@" + type baseType = string + type derivedType = baseType + param foo derivedType + output bar derivedType = foo + ")] + [DataTestMethod] + public void TestRule(string text, params string[] unusedTypes) + { + CompileAndTest(text, unusedTypes); + } + + [TestMethod] + public void Exported_types_are_not_reported_as_unused() + { + CompileAndTest(""" + @export() + type foo = string + """, + new Options(OnCompileErrors.IncludeErrors)); + } + + [DataRow(@" + // Syntax errors + type = + type a + ", + "a")] + [DataTestMethod] + public void SyntaxErrors(string text, params string[] unusedTypes) + { + CompileAndTest(text, new(OnCompileErrors.Ignore), unusedTypes); + } + + [DataRow(@"type")] // Don't show as unused - no type name + [DataRow(@"type // whoops")] // Don't show as unused - no type name + [DataTestMethod] + public void Errors(string text, params string[] unusedTypes) + { + CompileAndTest(text, new(OnCompileErrors.Ignore), unusedTypes); + } + + [TestMethod] + public void Codefix_removes_unused_type() => AssertCodeFix( + NoUnusedTypesRule.Code, + "Remove unused type unusedType", + """ + type unus|edType = string + """, + ""); + + [TestMethod] + public void Codefix_removes_only_the_unused_type() => AssertCodeFix( + NoUnusedTypesRule.Code, + "Remove unused type unusedType", + """ + type unus|edType = string + type usedType = int + param foo usedType + output bar usedType = foo + """, + """ + type usedType = int + param foo usedType + output bar usedType = foo + """); + } +} diff --git a/src/Bicep.Core/Analyzers/Linter/Rules/NoUnusedTypesRule.cs b/src/Bicep.Core/Analyzers/Linter/Rules/NoUnusedTypesRule.cs new file mode 100644 index 00000000000..1f796028591 --- /dev/null +++ b/src/Bicep.Core/Analyzers/Linter/Rules/NoUnusedTypesRule.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Bicep.Core.Diagnostics; +using Bicep.Core.Semantics; +using Bicep.Core.Syntax; + +namespace Bicep.Core.Analyzers.Linter.Rules +{ + public sealed class NoUnusedTypesRule : NoUnusedRuleBase + { + public new const string Code = "no-unused-types"; + + public NoUnusedTypesRule() : base( + code: Code, + description: CoreResources.UnusedTypeRuleDescription, + diagnosticStyling: DiagnosticStyling.ShowCodeAsUnused) + { } + + public override string FormatMessage(params object[] values) + => string.Format(CoreResources.UnusedTypeRuleMessageFormat, values); + + public override IEnumerable AnalyzeInternal(SemanticModel model, DiagnosticLevel diagnosticLevel) + { + var invertedBindings = model.Binder.Bindings.ToLookup(kvp => kvp.Value, kvp => kvp.Key); + + var unreferencedTypes = model.Root.TypeDeclarations + // exported types may be referenced by other files that this single-file analysis can't see + .Where(sym => !IsExported(model, sym.DeclaringType)) + .Where(sym => sym.NameSource.IsValid) + // a declaration always binds to itself, so a type is unused unless something else references it + .Where(sym => !invertedBindings[sym].Any(x => x != sym.DeclaringSyntax)); + + foreach (var sym in unreferencedTypes) + { + yield return CreateRemoveUnusedDiagnosticForSpan( + diagnosticLevel, sym.Name, sym.NameSource.Span, sym.DeclaringSyntax, model.SourceFile.ProgramSyntax); + } + } + + protected override string GetCodeFixDescription(string name) => $"Remove unused type {name}"; + } +} diff --git a/src/Bicep.Core/CoreResources.Designer.cs b/src/Bicep.Core/CoreResources.Designer.cs index 320f14eaef7..a990fcca3d4 100644 --- a/src/Bicep.Core/CoreResources.Designer.cs +++ b/src/Bicep.Core/CoreResources.Designer.cs @@ -923,6 +923,24 @@ internal static string UnusedVariableRuleMessageFormat { return ResourceManager.GetString("UnusedVariableRuleMessageFormat", resourceCulture); } } + + /// + /// Looks up a localized string similar to All declared types must be used.. + /// + internal static string UnusedTypeRuleDescription { + get { + return ResourceManager.GetString("UnusedTypeRuleDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type "{0}" is declared but never used.. + /// + internal static string UnusedTypeRuleMessageFormat { + get { + return ResourceManager.GetString("UnusedTypeRuleMessageFormat", resourceCulture); + } + } /// /// Looks up a localized string similar to Use parent property. diff --git a/src/Bicep.Core/CoreResources.resx b/src/Bicep.Core/CoreResources.resx index 03f39b56a7c..10e552f7fbb 100644 --- a/src/Bicep.Core/CoreResources.resx +++ b/src/Bicep.Core/CoreResources.resx @@ -284,6 +284,13 @@ Variable "{0}" is declared but never used. {0} is the variable name + + All declared types must be used. + + + Type "{0}" is declared but never used. + {0} is the type name + Use protectedSettings for commandToExecute secrets diff --git a/src/Bicep.LangServer.IntegrationTests/TypeStringifierTests.cs b/src/Bicep.LangServer.IntegrationTests/TypeStringifierTests.cs index dbe74f583a3..834355164d0 100644 --- a/src/Bicep.LangServer.IntegrationTests/TypeStringifierTests.cs +++ b/src/Bicep.LangServer.IntegrationTests/TypeStringifierTests.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Bicep.Core.Configuration; using Bicep.Core.Extensions; using Bicep.Core.Parsing; using Bicep.Core.PrettyPrintV2; @@ -1056,7 +1057,11 @@ public void NegatedTypes(string typeDeclaration, string expectedLooseSyntax, str private static CompilationResult Compile(string source) { - var services = new ServiceBuilder().WithFeatureOverrides(new(ResourceTypedParamsAndOutputsEnabled: true)); + var services = new ServiceBuilder() + .WithFeatureOverrides(new(ResourceTypedParamsAndOutputsEnabled: true)) + // These tests compile standalone type declarations that are intentionally never referenced, + // so suppress the no-unused-types linter rule to keep the "no diagnostics" assertions valid. + .WithConfigurationPatch(c => c.WithAnalyzersDisabled("no-unused-types")); return CompilationHelper.Compile(services, source); } diff --git a/src/vscode-bicep/schemas/bicepconfig.schema.json b/src/vscode-bicep/schemas/bicepconfig.schema.json index af1492c80a5..0f0a042d412 100644 --- a/src/vscode-bicep/schemas/bicepconfig.schema.json +++ b/src/vscode-bicep/schemas/bicepconfig.schema.json @@ -635,6 +635,16 @@ } ] }, + "no-unused-types": { + "allOf": [ + { + "description": "All declared types must be used. Defaults to 'Warning'. See https://aka.ms/bicep/linter-diagnostics#no-unused-types" + }, + { + "$ref": "#/definitions/rule-def-level-warning" + } + ] + }, "no-unused-vars": { "allOf": [ {