ARM Rules, TypeSpec Linting, and Suppression
ARM includes many rules on the structure of resources and the details of resource operations that ensure a consistent user experience when managing services inside Azure. TypeSpec encodes many fo these rules into linting checks that occur on each compilation. If you use an IDE and install the TypeSpec IDE Tools, violations of rules will show up as yellow highlights in your tsp code. If you hover over these, you will get a message indicating the issue and how to fix it in your specification. If you use the typespec command-line, violations of rules will be printed as warnings, with a description and steps to correct the issue, and a pointer to the location in the specification where the violation occurred.
In the sections below, we will discuss these rules, how they work, and, in cases where a violation is a false positive, or has a reason approved by an ARM reviewer, can be suppressed.
ARM RPC Rules
Section titled “ARM RPC Rules”TypeSpec has a set of linting rules that execute whenever the specification is compiled, and in the IDE as you type. Violations are highlighted inline in the spec, or emitted during compilation.
For more information, see ARM RPC rules
Detecting and Suppressing Rule Violations at Design Time
Section titled “Detecting and Suppressing Rule Violations at Design Time”Violations of ARM RPC rules will show up at design time as a yellow highlight over the violating type in TypeSpec, and at compile time as an emitted warning with a specific reference in the specification code (line number, position, pointer).
Here is an example of a linter warning:
Diagnostics were reported during compilation:
C:/typespec-samples/resource-manager/zerotrust/main.tsp:38:3 - warning @azure-tools/typespec-azure-resource-manager/arm-resource-operation-missing-decorator: Resource POST operation must be decorated with @armResourceAction.> 38 | /** Gets the Zero Trust URL for this resource */ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^> 39 | @post | ^^^^^^^> 40 | getZeroTrustUrl(...ResourceInstanceParameters<ZeroTrustResource>): ZeroTrustUrl | ErrorResponse; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Found 1 warning.To suppress the warning, you would use the #suppress directive on the type that violates the rule. The directive takes the fully-qualified name of the rule you are suppressing, and a reason for the suppression.
#suppress "@azure-tools/typespec-azure-resource-manager/arm-resource-operation-missing-decorator" "This is a sample suppression." /** Gets the MAA URL for this resource */ @post getZeroTrustUrl(...ResourceInstanceParameters<ZeroTrustResource>): ZeroTrustUrl | ErrorResponse;Of course, in this case, the best resolution would be to follow the advice in the linting rule, and add the @armResourceAction decorator.
@armResourceAction(ZeroTrustResource) /** Gets the MAA URL for this resource */ @post getZeroTrustUrl(...ResourceInstanceParameters<ZeroTrustResource>): ZeroTrustUrl | ErrorResponse;Evaluating Rule Violations
Section titled “Evaluating Rule Violations”The tables below provide guidance to rule authors and ARM reviewers on how to evaluate violations of TypeSpec ARM rules. Rules are grouped by the library that defines them and listed alphabetically by name. For each rule, the tables give a link to its reference documentation, the corresponding LintDiff rule (if any), and the impact of a violation, including the area it affects.
Rules in @azure-tools/typespec-azure-core
Section titled “Rules in @azure-tools/typespec-azure-core”| Rule | LintDiff | Impact |
|---|---|---|
auth-required | — | API, SDK. None; all ARM APIs allow the same authentication. |
byos | — | API. The API uses file upload and download instead of a storage account. |
casing-style | R3016 (covers the serious violation) | API, SDK. On properties, this produces non-standard casing that impacts usability. On other types, emitters substitute the correct casing for their language. |
composition-over-inheritance | — | SDK. Overuse of inheritance impacts SDK usability. |
documentation-required | *SummaryOrDescription | API, SDK. Results in poor documentation in SDKs and API docs. |
friendly-name | — | API evolution. Names a type for emitters in an unscoped way; @clientName should be used instead. |
key-visibility-required | — | API, SDK. May inaccurately represent the mutability of identity fields. |
known-encoding | R2003 | API, SDK. Impacts API and SDK usability; non-standard formats are transmitted only as the unencoded wire type. |
long-running-polling-operation-required | — | SDK, API. Inapplicable to ARM LROs, but prevents an API from being represented as an LRO. |
no-case-mismatch | — | SDK. Type names that differ only by casing prevent SDK generation. |
no-error-status-codes | NoErrorCodeResponses | API. Using status codes in a non-standard way makes APIs difficult to use. |
no-explicit-routes-resource-ops | — | API. May indicate non-standard resource paths. |
no-fixed-enum-discriminator | — | API. Makes adding a new discriminant value a breaking change. |
no-format | — | SDK, API. May use an invalid format. |
no-generic-numeric | R2003 | SDK. SDKs lose precision or cannot represent the value with a strong numeric type. |
no-header-explode | — | API. Mainly a data-plane concern, but explode should not be allowed for headers. |
no-legacy-usage | — | API, SDK. Uses legacy patterns instead of standard patterns. |
no-multiple-discriminator | — | SDK, API. Multiple discriminators are not supported by SDKs, nor by Swagger without extensions. |
no-nullable | — | API, SDK. This is usually a mistake where the property should be optional. |
no-offsetdatetime | — | SDK, API. Reduces clarity of purpose; a time is best provided in UTC. |
no-openapi | — | API, SDK, Emitters. Introduces OpenAPI changes that are not reflected in other emitters such as SDKs, which can cause SDKs to misrepresent the wire API. |
no-private-usage | — | API, SDK. May cause a spec break in the future. |
no-query-explode | — | API. Mainly a data-plane concern, but explode should not be allowed for query parameters. |
no-rest-library-interfaces | — | SDK, Emitters. If used to describe resource APIs, emitters may not recognize them as such, though this would produce other violations. |
no-route-parameter-name-mismatch | — | SDK. When representing operations over a resource, mismatched parameters can produce strange SDK operation signatures. |
no-rpc-path-params | — | There are no violations in ARM. |
no-string-discriminator | — | SDK. Makes the SDK less usable because discriminant values are unknown. |
no-unknown | — | API, SDK. Allowing any JSON type makes SDKs and APIs unusable without extensive documentation. |
no-unnamed-types | — | SDK, API. Causes the SDK to use an unnamed type. |
operation-missing-api-version | ApiVersionParameterRequired | API, SDK. An unversioned operation cannot evolve. |
request-body-problem | — | API, SDK. A request body that is an array makes API evolution difficult. |
require-versioned | — | SDK, API. Prevents updating the API with new api-versions. |
response-schema-problem | — | API, SDK. May indicate a forgotten response status code. |
spread-discriminated-model | — | SDK. May indicate a mistake, because a discriminator is ineffective when spread. |
no-closed-literal-union, no-enum | — | SDK, API. Prevents adding values to an enum in new api-versions without a breaking change. |
Rules in @azure-tools/typespec-azure-resource-manager
Section titled “Rules in @azure-tools/typespec-azure-resource-manager”| Rule | LintDiff | Impact |
|---|---|---|
arm-common-types-version | — | API, SDK. Indicates that common-types are not used, though this should produce other violations. |
arm-custom-resource-no-key | — | API, SDK. Mainly a correctness issue; the name property should use @key. |
arm-custom-resource-usage-discourage | — | API. The resource does not use ARM common-types. |
arm-delete-operation-response-codes | DeleteResponseCodes | API. RPC violation. |
arm-no-path-casing-conflicts | — | API, SDK. Different-case paths to the same resource can cause ARM manifest failures. |
arm-no-record | AvoidAdditionalProperties | API, SDK. Dictionary types make the API and SDK difficult to use. |
arm-post-operation-response-codes | PostResponseCodes | API. RPC violation. |
arm-put-operation-response-codes | PutResponseCodes | API. RPC violation. |
arm-resource-action-no-segment | PathForResourceAction (partial) | API, SDK. May indicate a violation of the resource action path. |
arm-resource-duplicate-property | R3019 | API. RPC violation. |
arm-resource-interface-requires-decorator | — | No impact beyond what other rules cover. |
arm-resource-invalid-action-verb | — | API, SDK. An improper HTTP verb for a resource action can cause failures in the C# SDK and in emitters that model resource actions, such as service generation and the portal. |
arm-resource-invalid-envelope-property | R3006 | API. RPC violation. |
arm-resource-invalid-version-format | R3012 | API. RPC violation. |
arm-resource-key-invalid-chars | — | SDK. The resource parameter name produces invalid keys in SDKs. |
arm-resource-name-pattern | ResourceNameRestriction | API. RPC violation. |
arm-resource-operation-response | R3007 (the TypeSpec rule also covers list) | API. RPC violation. |
arm-resource-operation | — | SDK, API, Emitters. Missing these decorators can prevent operations from being associated with the correct resource. This breaks the C# SDK and prevents reasoning about and linting resource-based rules, as well as producing correct resource-centric content such as service generation, tests, linting rules, and portal experiences. |
arm-resource-patch | ConsistentPatchProperties | API. RPC violation. |
arm-resource-path-segment-invalid-chars | — | SDK, API. Produces an invalid ARM API and invalid parameter names. |
arm-resource-provisioning-state | ProvisioningStateValidation, ProvisioningStateSpecifiedForLROPut, ProvisioningStateSpecifiedForLROPatch, RpaaS_ResourceProvisioningState | API. RPC / RPaaS violation. |
beyond-nesting-levels | TrackedResourceBeyondsThirdLevel | API. RPC violation. |
empty-updateable-properties | — | API. Covered by patch-specific rules. |
improper-subscription-list-operation | — | API. Likely a modeling error; only subscription-based resources should have list operations. |
lro-location-header | LroLocationHeader | API. RPC violation. |
missing-operations-endpoint | R3023 | API. RPC violation. |
missing-x-ms-identifiers | R4041 (warning) | API. No real impact (an old pattern). |
no-empty-model | R4037 | API, SDK. Accepting any schema makes the API and SDK difficult to use. |
no-override-props | — | SDK, Tooling. Violations can crash the breaking-change tool and are unsupported by most languages. |
no-resource-delete-operation | AllTrackedResourcesMustHaveDelete | API. RPC violation. |
no-response-body | — | API. A non-empty response, usually for a 202. |
patch-envelope | — | API. A Patch operation is missing updatable envelope properties. |
resource-name | — | API, SDK. Invalid characters in a name violate the RPC and create invalid client parameter names, which prevents SDK generation. |
secret-prop | XMSSecretInResponse | API. RPC violation. |
unsupported-type | — | SDK. The data type cannot be modeled in SDKs. |
version-progression | — | API, SDK, Tooling. Out-of-order versions make specs unmaintainable, and versions with matching dates cause SDK problems. |
Rules in @azure-tools/typespec-client-generator-core
Section titled “Rules in @azure-tools/typespec-client-generator-core”| Rule | LintDiff | Impact |
|---|---|---|
property-name-conflict | — | SDK. Not representable in the C# SDK. |
require-client-suffix | — | SDK. Clients do not follow the SDK naming guidelines. |