microsoft / microsoft/typespec
Linter silently drops diagnostics on library templates instantiated by the user project
- Dominant language
- Java
- Stars
- 5.9k
- Forks
- 394
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 104
Description
### Describe the bug
Linter rules cannot report on library types that only exist because the **user project instantiated a library template**. The diagnostic is created, then silently thrown away.
`createLinterRuleContext.reportDiagnostic` filters on the target's *primary* source location ([`core/linter.ts`](https://github.com/microsoft/typespec/blob/main/packages/compiler/src/core/linter.ts)):
```ts
const context = getLocationContext(program, diagnostic.target);
// Only report diagnostic in the user project.
if (context.type === "project") {
diagnosticCollector.add(diagnostic);
}
```
For a template instantiation, `getLocationContext` → `getSourceLocation` resolves to the template *declaration*, which lives in the library. The template instantiation trace (`getDiagnosticTemplateInstantitationTrace`) that points back at the user's file is never consulted.
The coarse filter is intentional — users shouldn't be blamed for library-internal code. But a template the user instantiated is not library-internal: the type only exists because of the arguments *they* passed, so the diagnostic is actionable.
It's also inconsistent. A plain (non-linter) diagnostic on the exact same target renders fine, with the trace pointing at the user's own line — only linter diagnostics vanish.
### Reproduction
A library declaring `model Wrapper { value: T }` and a rule reporting on properties typed `uuid`:
```tsp
// user project
model Direct { id: uuid; } // ✅ reported
model Instantiated { wrapped: Wrapper; } // ❌ silently dropped
```
Dumping what the linter sees for the two properties the rule fires on:
```
Direct.id: locationContext=project hasTemplateMapper=false -> KEPT
Wrapper.value: locationContext=library hasTemplateMapper=true -> DROPPED
```
Reporting the very same targets as ordinary diagnostics shows the information needed to surface it at the usage site already exists:
```
../lib/lib/main.tsp:14:3 - warning repro-lib/raw-uuid: uuid usage is not recommended.
> 14 | value: T;
main.tsp:21:12 - occurred while instantiating template
> 21 | wrapped: Wrapper;
```
### Real-world impact
Hit while adding an ARM `no-uuid` rule in Azure/typespec-azure#5336: `ResourceNameParameter<..., NameType = Azure.Core.uuid>.name` is generated from a library template, so the rule can never fire on it. In the migration corpus that's 9 UUID resource-name declarations across 6 projects — a permanent blind spot unless rules work around the compiler with bespoke HTTP-projection logic ([discussion](https://github.com/Azure/typespec-azure/pull/5336#discussion_r3931935676)).
### Expected behavior
A linter diagnostic whose target's instantiation trace reaches the user project should be reported, rendered with the instantiation trace — same as plain diagnostics already do.
Narrower follow-up to #1997, which covers the general "show library diagnostics at point of usage" problem.
### Checklist
- [x] Follow our [Code of Conduct](https://github.com/microsoft/typespec/blob/main/CODE_OF_CONDUCT.md)
- [x] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
Contributor guide
Assessment
This issue has not been assessed yet.