Skip to content

feat: new linter rules to enforce descriptions on types, params, var, type properties and output - #20036

Open
John (johnlokerse) wants to merge 12 commits into
Azure:mainfrom
johnlokerse:johnlokerse/new-linter-rule-param-descriptions
Open

feat: new linter rules to enforce descriptions on types, params, var, type properties and output#20036
John (johnlokerse) wants to merge 12 commits into
Azure:mainfrom
johnlokerse:johnlokerse/new-linter-rule-param-descriptions

Conversation

@johnlokerse

@johnlokerse John (johnlokerse) commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Description

This change adds a new Bicep linter rule called use-parameter-descriptions. Default the rule level is off but when set to error it checks if the parameter has either the @sys.description or @description decorator above a parameter. Additionally, it checks if the description is not empty.

Anthony Martin (@anthony-c-martin) stephaniezyen This implements issue #9453 and #5595.

Example Usage

It works through the bicep linter command or using the VSCode extension:

CleanShot 2026-07-10 at 10 50 14

Checklist

Microsoft Reviewers: Open in CodeFlow

@johnlokerse

Copy link
Copy Markdown
Contributor Author

Documentation is needed for this

@johnlokerse

Copy link
Copy Markdown
Contributor Author

Anthony Martin (@anthony-c-martin) does anyone on the team have time for a review? 😃

@slavizh

Copy link
Copy Markdown
Contributor

John (@johnlokerse) does it works for types as well? Would be very good if it applies to types as well or if there is separate rule for it. There is one exception for types though - discriminator. for the example below it should not apply as the description for foo is where foo is referenced. If there is description directly on the type it does not appear anywhere.

...
@discriminator('type)
type foo = foo1 | foo2
...

@johnlokerse

Copy link
Copy Markdown
Contributor Author

John (@johnlokerse) does it works for types as well? Would be very good if it applies to types as well or if there is separate rule for it. There is one exception for types though - discriminator. for the example below it should not apply as the description for foo is where foo is referenced. If there is description directly on the type it does not appear anywhere.

...
@discriminator('type)
type foo = foo1 | foo2
...

Stanislav Zhelyazkov (@slavizh) This can be done. I would do it separately from this linter, though, since not everyone wants to put descriptions on properties in types or on the type itself. The same thing applies to variables and outputs if you ask me.

Or as another option we introduce a configuration to the new use-descriptions linter rule, just like use-recent-api-versions has with the maxAllowedAgeInDays configuration in the bicepconfig.json. Like so:

	"analyzers": {
		"core": {
			"rules": {
				"use-recent-api-versions": {
					"level": "warning",
					"maxAllowedAgeInDays": 500
				},
				"use-descriptions": {
					"level": "error",
					"variables": false,
					"userDefinedTypes": true,
					"parameters": true,
					"outputs": true
				}
			}
		}
	}

@anthony-c-martin

Copy link
Copy Markdown
Member

Or as another option we introduce a configuration to the new use-descriptions linter rule, just like use-recent-api-versions has with the maxAllowedAgeInDays configuration in the bicepconfig.json. Like so:

John (@johnlokerse) - the changes in this PR look good to me, but I think it would be a good idea to close on this discussion first - I wouldn't want to release something and then immediately change it.

@johnlokerse

Copy link
Copy Markdown
Contributor Author

Or as another option we introduce a configuration to the new use-descriptions linter rule, just like use-recent-api-versions has with the maxAllowedAgeInDays configuration in the bicepconfig.json. Like so:

John (@johnlokerse) - the changes in this PR look good to me, but I think it would be a good idea to close on this discussion first - I wouldn't want to release something and then immediately change it.

I agree.

Anthony Martin (@anthony-c-martin) Stanislav Zhelyazkov (@slavizh) What is your take on the proposed configuration in the bicepconfig.json? If you think it's good, I would suggest setting the configurable option (= variables, parameters, udt and output bool toggles) to true if not set in the bicepconfig else use the user-defined value set in the bicepconfig.

@anthony-c-martin

Copy link
Copy Markdown
Member

Anthony Martin (@anthony-c-martin) Stanislav Zhelyazkov (@slavizh) What is your take on the proposed configuration in the bicepconfig.json? If you think it's good, I would suggest setting the configurable option (= variables, parameters, udt and output bool toggles) to true if not set in the bicepconfig else use the user-defined value set in the bicepconfig.

What would the "default" behavior be - just parameters?

Another option to consider for how you express this in config is with an array of enums - e.g.:

"use-descriptions": {
  "level": "error",
  "requireOn": ["parameter", "type", "typeProperty", "output"]
}

@slavizh

Copy link
Copy Markdown
Contributor

Anthony Martin (@anthony-c-martin) looks good to me. For parameters by default the highest could be only warning otherwise it will be a breaking change. I am ok to be a warning instead of off. For the others from my perspective they should be warnings by default but I think that might be too aggressive for many users and I do not know if they will react positively on it. Note that the exception on discriminator type is important as that description does not really appear anywhere when it is standalone type referenced.

@johnlokerse

Copy link
Copy Markdown
Contributor Author

Anthony Martin (@anthony-c-martin) Looks good to me too, and I like the requiredOn property with the array values. However, if we look at the current list of linter rules, this introduces an inconsistency with how the other linter rules work:

CleanShot 2026-07-28 at 16 19 57@2x

If we choose the same approach as the no-unused-* rules, it would be use-description-* instead of configuring it in bicepconfig.json via requiredOn. This would be consistent with the other linter rules. What do you think?

Stanislav Zhelyazkov (@slavizh) I agree on the warning default for parameters, but not for the others. I don’t see many organisations using descriptions for anything besides parameters. I recommend turning these off by default.

@slavizh

Copy link
Copy Markdown
Contributor

John (@johnlokerse) note my suggestion is not based on what is popular but rather what should be the best practice. For example you will see most folks using multiple parameters trying to implement different features for different services that are deployed within the same module instead of trying to group those into a single parameter per resource. Very small example:

param resource1Name string
param resource1Sku string
param resource1MinimumTlsVersion string

param resource2Name string
param resource2MinimumTlsVersion string
param resource2PublicNetworkAccess string

vs.

type resource1Type = {
  name: string
  sku: string
  minimumTlsVersion: string
}

type resource2Type = {
  name: string
  publicNetworkAccess: string
  minimumTlsVersion: string
}
param resource1 resource1Type

param resource2 resource2Type

The latter has a ton of benefits that makes the user experience of modules better. Unfortunately even AVD is implementing that partially. One of the reason for not being widely used is that most folks moved from ARM templates where we did not have such features and everything was flat. Another is that the Portal does not supports such types very well thus the examples created by Microsoft employees also have flat structure. However this is another topic. Overall I think the standard values should represent the desired standard for coding even if it is not what is widely used in order to promote that standard. I also know that some warnings might be annoying in simple scenarios.

@anthony-c-martin

Copy link
Copy Markdown
Member

John (@johnlokerse), I'm happy defaulting to "off" for everything, because of the sheer quantity of .bicep files this would flag if enabled by default.

If we choose the same approach as the no-unused-* rules, it would be use-description-* instead of configuring it in bicepconfig.json via requiredOn. This would be consistent with the other linter rules. What do you think?

Good point! I'm fine either way. I think there's benefit to the ease of enabling/disabling if we create separate linters for each.

@johnlokerse

Copy link
Copy Markdown
Contributor Author

John (@johnlokerse), I'm happy defaulting to "off" for everything, because of the sheer quantity of .bicep files this would flag if enabled by default.

If we choose the same approach as the no-unused-* rules, it would be use-description-* instead of configuring it in bicepconfig.json via requiredOn. This would be consistent with the other linter rules. What do you think?

Good point! I'm fine either way. I think there's benefit to the ease of enabling/disabling if we create separate linters for each.

Anthony Martin (@anthony-c-martin) Okay, so let's keep it consistent with the other linter rules. We default to off, and the following linters will be implemented:

  1. use-description-parameters
  2. use-description-vars
  3. use-description-type
  4. use-description-type-property
  5. use-description-output

Additionally, documentation needs to be created. Will use the same style as this page: https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/linter-rule-no-unused-parameters.

Do I miss anything? If not, I will start building and will update this PR with the new linter rules. 😃

@anthony-c-martin

Copy link
Copy Markdown
Member

John (@johnlokerse), I'm happy defaulting to "off" for everything, because of the sheer quantity of .bicep files this would flag if enabled by default.

If we choose the same approach as the no-unused-* rules, it would be use-description-* instead of configuring it in bicepconfig.json via requiredOn. This would be consistent with the other linter rules. What do you think?

Good point! I'm fine either way. I think there's benefit to the ease of enabling/disabling if we create separate linters for each.

Anthony Martin (@anthony-c-martin) Okay, so let's keep it consistent with the other linter rules. We default to off, and the following linters will be implemented:

  1. use-description-parameters
  2. use-description-vars
  3. use-description-type
  4. use-description-type-property
  5. use-description-output

Additionally, documentation needs to be created. Will use the same style as this page: https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/linter-rule-no-unused-parameters.

Do I miss anything? If not, I will start building and will update this PR with the new linter rules. 😃

Sounds good to me!

@Xelu86

Xelu86 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Hey John (@johnlokerse) & Anthony Martin (@anthony-c-martin), I've started documenting the "use-parameter-descriptions" rule in an internal draft.

I do have a question. In src/Bicep.Core/Analyzers/Linter/Rules/UseParameterDescriptionsRule.cs‎ & src/vscode-bicep/schemas/bicepconfig.schema.json, I see "use-parameter-descriptions" being used. Will this perhaps change to use-description-parameters for consistency in both code and documentation to match the following linters?

use-description-parameters
use-description-vars
use-description-type
use-description-type-property
use-description-output

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good, but note that you have a merge conflict to fix

@johnlokerse John (johnlokerse) changed the title feat: new Bicep linter rule use-parameter-descriptions feat: 5 new linter rules to enforce descriptions on types, params, var, type properties and output Aug 7, 2026
@johnlokerse John (johnlokerse) changed the title feat: 5 new linter rules to enforce descriptions on types, params, var, type properties and output feat: new linter rules to enforce descriptions on types, params, var, type properties and output Aug 7, 2026
@johnlokerse

John (johnlokerse) commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Anthony Martin (@anthony-c-martin) Implemented 5 new linter rules to enforce descriptions. As requested by Stanislav Zhelyazkov (@slavizh) a type decorated with @discriminator is skipped. Default is off and linter names are now use-descriptions-<output/parameters/vars/type/type-property>. See video:

CleanShot.2026-08-07.at.12.57.52.mp4

Xelu86 For the documentation the names will be like this:

    use-description-parameters -> https://aka.ms/bicep/linter-diagnostics#use-description-parameters
    use-description-vars -> https://aka.ms/bicep/linter-diagnostics#use-description-vars
    use-description-output -> https://aka.ms/bicep/linter-diagnostics#use-description-output
    use-description-type -> https://aka.ms/bicep/linter-diagnostics#use-description-type
    use-description-type-property -> https://aka.ms/bicep/linter-diagnostics#use-description-type-property

@johnlokerse

Copy link
Copy Markdown
Contributor Author

The only problem I am seeing is when you right-click on the type property (for example value from the screenshot) and select add @description it adds the description('') to the type instead of the property. Anthony Martin (@anthony-c-martin) Do we want to fix it in this PR or separately?

CleanShot 2026-08-07 at 11 57 23 CleanShot 2026-08-07 at 11 57 39

@anthony-c-martin

Copy link
Copy Markdown
Member

Anthony Martin (Anthony Martin (@anthony-c-martin)) Do we want to fix it in this PR or separately?

I think this is fine to address separtely

@anthony-c-martin

Copy link
Copy Markdown
Member

John (@johnlokerse) - could we rename the linter rules for parity with the no-unused-<x> linter rules? These rules use plural (types rather than type), and refer to the language constructs by their keywords in Bicep (params rather than parameters).

These would be the updated names:

use-description-params
use-description-vars
use-description-types
use-description-type-properties
use-description-outputs

@johnlokerse

Copy link
Copy Markdown
Contributor Author

John (John (@johnlokerse)) - could we rename the linter rules for parity with the no-unused-<x> linter rules? These rules use plural (types rather than type), and refer to the language constructs by their keywords in Bicep (params rather than parameters).

These would be the updated names:

use-description-params
use-description-vars
use-description-types
use-description-type-properties
use-description-outputs

Done!

Xelu86 The linter rules are renamed to what Anthony mentioned

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants