CodeBlanks Logo Icon CodeBlanks

Diagnostic production

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

index.ts
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 yaz

Sample solution

index.ts
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

Question
extras.push({
  file: sf,
  start: node.getStart(sf),
  length: node.getWidth(sf),
  category: ts.DiagnosticCategory.____,
  code: 9001,
  messageText: "Missing type annotation",
});
Answer
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

All lessons in Expert