我有一個(gè)用例,我想替換變數(shù)函數(shù)調(diào)用,特別是 foo.value.toString()
來(lái)使用輔助函數(shù) getStringValue(foo)
。如果我找到它,我可以使用修復(fù)程式替換 CallExpression
節(jié)點(diǎn)上的文本,因此我的規(guī)則修復(fù)程式目前如下所示:
fixer => fixer.replaceText(node, `getStringValue(${identifierNode.getText()})`);
以這種方式自動(dòng)修復(fù)此錯(cuò)誤的問(wèn)題是 getStringValue
可能已匯入到檔案中,也可能尚未匯入到檔案中。我希望這個(gè)修復(fù)程式具有以下行為:
據(jù)我從文件中了解到,沒(méi)有簡(jiǎn)單的方法可以使用 fixer
或 context
物件來(lái)存取根 ESTree 節(jié)點(diǎn)。最接近的是 SourceCode.getText()
,這意味著我必須解析原始文字才能解析導(dǎo)入 - 我寧願(yuàn)直接與整個(gè) AST 互動(dòng)。執(zhí)行此自動(dòng)導(dǎo)入過(guò)程的最佳方法是什麼?
如果您想在這裡稍微不安全,您可以假設(shè)使用者沒(méi)有在其文件中本地重新定義getStringValue
函數(shù)(如果您擁有此規(guī)則所適用的程式碼庫(kù),通常是一個(gè)安全的假設(shè))。
在這種情況下,最好的方法是使用選擇器來(lái)檢查導(dǎo)入,例如:
module.exports = { create(context) { let hasImport = false; let lastImport = null; return { ImportDeclaration(node) { lastImport = node; if (isImportICareAbout(node)) { hasImport = true; } }, "My Selector For Other Linting Logic"(node) { // ... context.report({ messageId: "myReport", fix(fixer) { const fixes = [ fixer.replaceText(node, `getStringValue(${identifierNode.name})`), ]; if (!hasImport) { const newImport = 'import { getStringValue } from "module";'; if (lastImport) { // insert after the last import decl fixes.push(fixer.insertTextBefore(lastImport, newImport)); } else { // insert at the start of the file fixes.push(fixer.insertTextAfterRange([0, 0], newImport)); } } return fixes; }, }); }, }; }, };
事實(shí)證明,有一個(gè)簡(jiǎn)單的方法可以從 context
物件中提取 AST 根節(jié)點(diǎn)。它位於 context.getSourceCode().ast
。我用以下邏輯重寫了我的修復(fù):
fixer => { fixer.replaceText(node, `getStringValue(${identifierNode.getText()})`); const body = context.getSourceCode().ast; const importDeclarations = body.filter(statement => statement.type === AST_NODE_TYPES.ImportDeclaration); ... // Check if the declaration has the import and add the appropriate imports if necessary }