CodeBlanks Logo Icon CodeBlanks

Meydan okuma 4: Mini plugin

Uzman seviyenin tamamını yoklayan bir görev çözersin.

Mini plugin

Bu son meydan okuma uzman seviyenin tamamını yoklar. Bir lint plugin iskeleti yaz, getSemanticDiagnostics'i sar, mock dil servisi ile test et. Ardından any türü bulan özel bir diagnostic üreticisi ekle. ts.Diagnostic, ts.forEachChild ve ts.isVariableDeclaration birlikte kullanacaksın.

Uygulama Plugin iskeleti

Bir plugin fonksiyonu yaz: ts.server.PluginCreateInfo alır, ts.LanguageService döndürür. info.languageService'ten ls al, getSemanticDiagnostics'i sar ve ls'nin diagnostics'ini olduğu gibi döndür. Mock dil servisi 2 diagnostic döndürsün. Plugin'i çağır ve diagnostic sayısını yazdır.

Başlangıç kodu

index.ts
import * as ts from "typescript";

// Bir plugin fonksiyonu yaz:
// - PluginCreateInfo alır, LanguageService döndürür
// - info'daki dil servisini al
// - Diagnostic metodunu sar ve ls'nin diagnostics'ini döndür
// Mock dil servisi 2 diagnostic döndürsün
// Plugin'i çağır ve diagnostic sayısını yazdır

// kodunu buraya yaz

Örnek çözüm

index.ts
import ts from "typescript";

function createPlugin(info: ts.server.PluginCreateInfo): ts.LanguageService {
  const ls = info.languageService;
  return {
    ...ls,
    getSemanticDiagnostics: function(fileName: string) {
      return ls.getSemanticDiagnostics(fileName);
    },
  };
}

const fakeLs = {
  getSemanticDiagnostics: function(_fileName: string): ts.Diagnostic[] {
    return [
      { category: ts.DiagnosticCategory.Error, code: 1, messageText: "a", file: undefined, start: 0, length: 1 } as ts.Diagnostic,
      { category: ts.DiagnosticCategory.Warning, code: 2, messageText: "b", file: undefined, start: 0, length: 1 } as ts.Diagnostic,
    ];
  },
} 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);

Beklenen çıktı

2

Uygulama any türlerini işaretle

Bir plugin yaz: getSemanticDiagnostics'i sar. SourceFile'ı ls.getProgram().getSourceFile(fileName) ile al. AST'yı gez: tür eklemesi any olan VariableDeclaration düğümleri için bir ts.Diagnostic üret (category: Warning, messageText: "Avoid any"). prior ve extras'ı birleştir. Test: kaynak let a: any = 1; let b: number = 2;; toplam diagnostic sayısını yazdır.

Başlangıç kodu

index.ts
import * as ts from "typescript";

// Bir plugin yaz: Diagnostic metodunu sar
// - SourceFile'ı al
// - AST'yı gez: any türü olan VariableDeclaration bul
// - Her biri için bir Diagnostic üret (Warning kategorisi)
// - prior ve extras'ı birleştir
// Test: kaynak "let a: any = 1; let b: number = 2;"
// Toplam diagnostic sayısını yazdır

// kodunu buraya yaz

Örnek çözüm

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 && node.type.kind === ts.SyntaxKind.AnyKeyword) {
          extras.push({
            file: sf,
            start: node.getStart(sf),
            length: node.getWidth(sf),
            category: ts.DiagnosticCategory.Warning,
            code: 9001,
            messageText: "Avoid any",
          });
        }
        ts.forEachChild(node, visit);
      }
      visit(sf);
      return [...prior, ...extras];
    },
  };
}

const sf = ts.createSourceFile("app.ts", "let a: any = 1; let b: 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);

Beklenen çıktı

1

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Bir plugin diagnostic üretmek için hangi metodu sarar?

  • getCompilerDiagnostics
  • getSyntacticDiagnostics
  • getSemanticDiagnostics Doğru cevap
  • getSuggestionDiagnostics

Açıklama: Bir lint plugin getSemanticDiagnostics'i sarar ve özel diagnostic ekler. getSyntacticDiagnostics, getSuggestionDiagnostics ve getCompilerDiagnostics plugin kalıbında kullanılmaz.

2 Mesaj metnini al

Soru
console.log((diags[0] as ts.Diagnostic).____);
Cevap
console.log((diags[0] as ts.Diagnostic).messageText);

Açıklama: ts.Diagnostic.messageText mesaj metnini taşır; message, text ve description Diagnostic üzerinde özellik değildir.

3 Plugin parçaları

Kavram Anlamı
PluginCreateInfo Plugin girdisi
info.languageService Mevcut dil servisi
ts.Diagnostic Hata/uyarı nesnesi
ts.forEachChild AST'yı gezer

Uzman bölümündeki tüm dersler