Skip to content

Report linter diagnostics on library template members the user gave a type to - #11862

Draft
Timothee Guerin (timotheeguerin) wants to merge 5 commits into
microsoft:mainfrom
timotheeguerin:linter-template-instantiation
Draft

Report linter diagnostics on library template members the user gave a type to#11862
Timothee Guerin (timotheeguerin) wants to merge 5 commits into
microsoft:mainfrom
timotheeguerin:linter-template-instantiation

Conversation

@timotheeguerin

@timotheeguerin Timothee Guerin (timotheeguerin) commented Sep 4, 2026

Copy link
Copy Markdown
Member

A linter rule can never report on a type that exists only because the user instantiated a library template. reportDiagnostic keeps a diagnostic only when its target resolves to the project, and an instantiated member's source location is the template declaration inside the library, so the diagnostic is dropped without a trace.

That hides real problems. Given ARM's

model ResourceNameParameter<Resource, ..., Type extends string = string> {
  name: Type;
}

a rule that objects to Type being a uuid cannot say so about

model Employee is TrackedResource<EmployeeProperties> {
  ...ResourceNameParameter<Employee, Type = Azure.Core.uuid>;
}

even though the uuid is the user's own choice, written in their own file. This was found on Azure/typespec-azure#5336, where it silenced 9 declarations across 6 projects. A plain (non-linter) diagnostic on the exact same target renders fine, complete with an instantiation trace, so the two kinds of diagnostic disagree about the same code.

Now a library-declared member is reported when both of the following hold, and the diagnostic is moved onto the argument in the user's own file:

  • it was declared as a template parameter the user supplied an argument for. name: Type qualifies, so the type really is the one they passed. value: T[] in Page<T> does not: the array is the library's own declaration, and a complaint about it is the library's to fix whichever item type is passed.
  • the argument is a type they cannot edit, such as a library scalar or unknown. When they pass one of their own declarations, anything wrong with it is reportable on that declaration, where they can see it in context, so the instantiation adds nothing.

Together these keep the diagnostic pointed at a line the reader can act on. Measured against azure-rest-api-specs, this reports the cases the rules were written to catch — ArmResponse<unknown>, ArmResponse<NetworkTrace[]> — without reporting members whose problem lies in a model the author already owns.

#suppress now walks the template instantiation trace too, so the diagnostic can be suppressed where the user instantiates the template, which is the only place they can write a directive.

Fixes #11861

Known follow-up

documentation-required reports on a type whose documentation was blanked with @@doc(X, ""), and points at the type rather than at the augmentation that blanked it. The rule knows it is about @doc and can point at the responsible node; the linter cannot guess which decorator a rule cares about. Tracked in Azure/typespec-azure#5445.

@microsoft-github-policy-service microsoft-github-policy-service Bot added compiler:core Issues for @typespec/compiler meta:website TypeSpec.io updates labels Sep 4, 2026
@pkg-pr-new

pkg-pr-new Bot commented Sep 4, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/compiler@11862

commit: fc614e4

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @typespec/compiler
Show changes

@typespec/compiler - fix ✏️

Report linter diagnostics on library template members the user gave a type to,> ,> A rule reporting on a member declared inside a library template — for example the value property of Wrapper<T> when the project writes Wrapper<uuid> — was silently dropped, because the member's source location resolves to the template declaration in the library. That member only has the type it has because of the argument the user passed, so it is now reported, on the argument in the user's own file.,> ,> Only a member declared as the parameter, such as value: T, counts. A member the parameter merely appears inside, such as value: T[], is still left alone: the array is the library's own declaration, so a diagnostic about it is the library's to fix no matter which item type the user passed.,> ,> The argument must also be a type the user cannot edit, such as a library scalar or unknown. When they pass one of their own declarations, anything wrong with it is reportable on that declaration, where they can see it in context, so the instantiated member has nothing to add.

@typespec/compiler - fix ✏️

Suppress a diagnostic reported inside a template where the template was instantiated,> ,> tsp,> model Widget {,> #suppress "some-rule" "Not applicable here",> page: Page<WidgetItem>;,> },> ,> ,> Previously the #suppress directive was only looked up on the target and its parents, so a diagnostic coming from a template declaration could not be suppressed from the code that instantiated it.

@azure-sdk-automation

azure-sdk-automation Bot commented Sep 4, 2026

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

@timotheeguerin Timothee Guerin (timotheeguerin) added the int:azure-specs Run integration tests against azure-rest-api-specs label Sep 4, 2026
Narrow the fix so a library-declared member is reported only when its declared
type depends on a template parameter the user passed an argument for, and
retarget the diagnostic to that argument node in the user's project.
@timotheeguerin Timothee Guerin (timotheeguerin) changed the title Report linter diagnostics on library templates instantiated by the user project Report linter diagnostics on library template members whose type the user supplied Sep 4, 2026
A member the parameter merely appears inside, such as `value: T[]` in
`Page<T>`, is the library's own declaration: a diagnostic about it is the
library's to fix no matter which item type the user passed. Reported against
azure-rest-api-specs this removes the `missing-x-ms-identifiers` findings on
`Page<X>` while keeping `no-unknown` on `ArmResponse<unknown>` and
`missing-x-ms-identifiers` where the user passed the array itself.
@timotheeguerin Timothee Guerin (timotheeguerin) changed the title Report linter diagnostics on library template members whose type the user supplied Report linter diagnostics on library template members the user gave a type to Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compiler:core Issues for @typespec/compiler int:azure-specs Run integration tests against azure-rest-api-specs meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linter silently drops diagnostics on library templates instantiated by the user project

1 participant