搜尋

首頁  >  問答  >  主體

如果尚未匯入輔助函數,則新增匯入聲明:具有自訂 ESLint 規則修復程式的增強解決方案

我有一個用例,我想替換變數函數調用,特別是 foo.value.toString() 來使用輔助函數 getStringValue(foo) 。如果我找到它,我可以使用修復程式替換 CallExpression 節點上的文本,因此我的規則修復程式目前如下所示:

fixer => fixer.replaceText(node, `getStringValue(${identifierNode.getText()})`);

以這種方式自動修復此錯誤的問題是 getStringValue 可能已匯入到檔案中,也可能尚未匯入到檔案中。我希望這個修復程式具有以下行為:

  1. 如果函數已匯入到檔案中,則無需執行任何其他操作。
  2. 如果函數未導入,但其包含的檔案模組已導入,請將此函數新增至該模組的導入。
  3. 如果函數及其包含的檔案模組均未匯入,則將該模組與該函數一起匯入。

據我從文件中了解到,沒有簡單的方法可以使用 fixercontext 物件來存取根 ESTree 節點。最接近的是 SourceCode.getText(),這意味著我必須解析原始文字才能解析導入 - 我寧願直接與整個 AST 互動。執行此自動導入過程的最佳方法是什麼?

P粉312195700P粉312195700242 天前326

全部回覆(2)我來回復

  • P粉596161915

    P粉5961619152024-03-29 00:56:42

    如果您想在這裡稍微不安全,您可以假設使用者沒有在其文件中本地重新定義getStringValue 函數(如果您擁有此規則所適用的程式碼庫,通常是一個安全的假設)。

    在這種情況下,最好的方法是使用選擇器來檢查導入,例如:

    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;
              },
            });
          },
        };
      },
    };

    回覆
    0
  • P粉098979048

    P粉0989790482024-03-29 00:43:02

    事實證明,有一個簡單的方法可以從 context 物件中提取 AST 根節點。它位於 context.getSourceCode().ast。我用以下邏輯重寫了我的修復:

    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
    }
    

    回覆
    0
  • 取消回覆