TypeScript
Code fix
Code fix sağlayıcısını yazarsın.
CodeFixAction yapısı
Bir ts.CodeFixAction nesnesi fixName (fix kimliği), description (kullanıcı açıklaması) ve changes (dosya değişiklikleri) alanlarını taşır. changes bir FileTextChanges[]'dir; her eleman bir dosya için textChanges dizisi içerir.
const fix: ts.CodeFixAction = {
fixName: "add-any",
description: "Add type annotation",
changes: [{
fileName,
textChanges: [
{ span: { start, length: 0 }, newText: ": any" }
],
}],
};
getCodeFixesAtPosition
Dil servisinde code fix sağlayan metod getCodeFixesAtPosition'dır. Dosya adı, pozisyon aralığı ve hata kodları alır, CodeFixAction[] döndürür. Plugin içinde bu metodu sarıp ek fix'ler üretirsin.
getCodeFixesAtPosition: function(fileName, start, end) {
const prior = ls.getCodeFixesAtPosition(fileName, start, end);
// ek fixes üret
return [...prior, ...fixes];
};
Uygulama Code fix sağla
Bir plugin yaz: getCodeFixesAtPosition'ı sar. Önce ls'nin fixes'ini al (prior). SourceFile'ı al. AST'yı gez: tür eklemesi olmayan VariableDeclaration düğümleri için bir ts.CodeFixAction üret (fixName: "add-any"). textChanges ile değişken adının sonuna : any ekle. prior ve fixes'i birleştir. Test: kaynak let x = 1;; ilk fix'in fixName'ini yazdır.
Örnek çözümü göster
import ts from "typescript";
function createPlugin(info: ts.server.PluginCreateInfo): ts.LanguageService {
const ls = info.languageService;
return {
...ls,
getCodeFixesAtPosition: function(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: ts.FormatCodeSettings, preferences: ts.UserPreferences) {
const prior = ls.getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences);
const sf = ls.getProgram().getSourceFile(fileName);
if (!sf) return prior;
const fixes: ts.CodeFixAction[] = [];
function visit(node: ts.Node) {
if (ts.isVariableDeclaration(node) && !node.type) {
fixes.push({
fixName: "add-any",
description: "Add type annotation",
changes: [{
fileName,
textChanges: [{ span: { start: node.name.getEnd(), length: 0 }, newText: ": any" }],
}],
});
}
ts.forEachChild(node, visit);
}
visit(sf);
return [...prior, ...fixes];
},
};
}
const sf = ts.createSourceFile("app.ts", "let x = 1;", ts.ScriptTarget.Latest, true);
const fakeLs = {
getCodeFixesAtPosition: function() { return [] as ts.CodeFixAction[]; },
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 fixes = plugin.getCodeFixesAtPosition("app.ts", 0, 1, [], {} as ts.FormatCodeSettings, {} as ts.UserPreferences);
console.log(fixes[0].fixName);
Kendini test et
-
Bir CodeFixAction'ın changes alanı ne içerir?
- Tek bir metin değişikliği
- Dosya değişiklikleri (FileTextChanges[])
- Diagnostic listesi
- Kaynak dosya metni
Cevabı göster
Dosya değişiklikleri (FileTextChanges[]) — changes alanı bir FileTextChanges[] taşır; her eleman bir dosya için textChanges dizisi içerir. Tek metin değişikliği, diagnostic listesi veya kaynak dosya metni değildir.
-
Fix adı
fixes.push({
____: "add-any",
description: "Add type annotation",
changes: [{ fileName, textChanges: [{ span: { start: node.name.getEnd(), length: 0 }, newText: ": any" }] }],
});
Cevabı göster
fixes.push({
fixName: "add-any",
description: "Add type annotation",
changes: [{ fileName, textChanges: [{ span: { start: node.name.getEnd(), length: 0 }, newText: ": any" }] }],
});
-
Code fix parçaları
- fixName
- Fix kimliği
- description
- Kullanıcı açıklaması
- changes
- Dosya değişiklikleri
- textChanges
- Metin değişiklikleri
Sıradaki ders: Configuration