Diagnostic production
- TypeScript course
- Expert
- Lesson 28/35
- 5 min
Add a custom diagnostic producer.
Diagnostic structure
A ts.Diagnostic object carries file, start, length, category, code and messageText fields. When a rule violation is found in the plugin, you produce a diagnostic with these fields.
const diag: ts.Diagnostic = {
file: sf,
start: node.getStart(sf),
length: node.getWidth(sf),
category: ts.DiagnosticCategory.Warning,
code: 9001,
messageText: "Missing type annotation",
};Producing diagnostics
To produce diagnostics inside the plugin you push ts.Diagnostic objects into an extras array. Then you merge them with ls's prior diagnostics and return.
const extras: ts.Diagnostic[] = [];
extras.push({
file: sf,
start: node.getStart(sf),
length: node.getWidth(sf),
category: ts.DiagnosticCategory.Warning,
code: 9001,
messageText: "Missing type annotation",
});
return [...prior, ...extras];Practice Add a custom diagnostic
Write a plugin that wraps getSemanticDiagnostics. First take ls's diagnostics (prior). Get the SourceFile via ls.getProgram().getSourceFile(fileName). Walk the AST: for each VariableDeclaration without a type annotation, produce a ts.Diagnostic (category: Warning). Merge prior and extras. Test: source let x = 1; let y: number = 2;; print the total diagnostic count.
Starter code
import * as ts from "typescript";
// Bir plugin yaz: Semantic diagnostics metodunu sar
// - Önce ls'nin diagnostics'ini al (prior)
// - SourceFile'ı ls.getProgram().getSourceFile ile al
// - AST'yı gez: tür eklemesi olmayan VariableDeclaration bul
// - Her biri için bir Diagnostic üret (category: Warning)
// - prior ve extras'ı birleştir
// Test yaz ve toplam diagnostic sayısını yazdır.
// kodunu buraya yazSample solution
import ts from "typescript";
function createPlugin(info: ts.server.PluginCreateInfo): ts.LanguageService {
const ls = info.languageService;
return {
...ls,
getSemanticDiagnostics: function(fileName: string) {
const prior = ls.getSemanticDiagnostics(fileName);
const sf = ls.getProgram().getSourceFile(fileName);
if (!sf) return prior;
const extras: ts.Diagnostic[] = [];
function visit(node: ts.Node) {
if (ts.isVariableDeclaration(node) && !node.type) {
extras.push({
file: sf,
start: node.getStart(sf),
length: node.getWidth(sf),
category: ts.DiagnosticCategory.Warning,
code: 9001,
messageText: "Missing type annotation",
});
}
ts.forEachChild(node, visit);
}
visit(sf);
return [...prior, ...extras];
},
};
}
const sf = ts.createSourceFile("app.ts", "let x = 1; let y: number = 2;", ts.ScriptTarget.Latest, true);
const fakeLs = {
getSemanticDiagnostics: function() { return [] as ts.Diagnostic[]; },
getProgram: function() { return { getSourceFile: function(n: string) { return n === "app.ts" ? sf : undefined; } } as unknown as ts.Program; },
} as unknown as ts.LanguageService;
const info = { languageService: fakeLs, config: {} } as unknown as ts.server.PluginCreateInfo;
const plugin = createPlugin(info);
const diags = plugin.getSemanticDiagnostics("app.ts");
console.log(diags.length);Expected output
1
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What does ts.DiagnosticCategory.Warning mean?
- A compiler error
- A suggestion
- An informational message
- A warning, does not stop compilation Correct answer
Explanation: The Warning category issues a warning but does not stop compilation; Error stops it, Suggestion is a proposal, and Message is informational.
2 Create a diagnostic
extras.push({
file: sf,
start: node.getStart(sf),
length: node.getWidth(sf),
category: ts.DiagnosticCategory.____,
code: 9001,
messageText: "Missing type annotation",
});
extras.push({
file: sf,
start: node.getStart(sf),
length: node.getWidth(sf),
category: ts.DiagnosticCategory.Warning,
code: 9001,
messageText: "Missing type annotation",
});
Explanation: The Warning category issues a warning; Error stops compilation, and Info and Fatal do not exist on DiagnosticCategory.
3 Diagnostic parts
| Term | Meaning |
|---|---|
file |
Carries the source file |
start |
Start offset |
category |
Severity |
messageText |
Message text |