Ajouter une déclaration d'importation si la fonction d'assistance n'est pas déjà importée : solution améliorée avec correctif de règles ESLint personnalisées
P粉312195700
P粉312195700 2024-03-28 09:26:00
0
2
333

J'ai un cas d'utilisation dans lequel je souhaite remplacer les appels de fonctions variables, en particulier le texte sur les nœuds foo.value.toString() 来使用辅助函数 getStringValue(foo) 。如果我找到它,我可以使用修复程序替换 CallExpression, donc mon correctif de règle ressemble actuellement à ceci :

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

Le problème avec la correction automatique de cette erreur de cette façon est que getStringValue peut ou non avoir été importé dans le fichier. Je veux que ce correctif ait le comportement suivant :

  1. Si la fonction est déjà importée dans le fichier, il n'est pas nécessaire de faire autre chose.
  2. Si la fonction n'est pas importée, mais que le module de fichiers qu'elle contient est importé, ajoutez cette fonction aux importations du module.
  3. Si ni la fonction ni le module de fichier qui la contient ne sont importés, importez le module avec la fonction.

D'après ce que j'ai compris de la documentation, il n'y a pas de moyen simple de le faire en utilisant fixercontext 对象访问根 ESTree 节点。最接近的是 SourceCode.getText(), ce qui signifie que je dois analyser le texte source afin d'analyser l'importation - je préfère interagir directement avec l'ensemble de l'AST. Quelle est la meilleure façon d’effectuer ce processus d’importation automatisé ?

P粉312195700
P粉312195700

répondre à tous(2)
P粉596161915

Si vous voulez être légèrement dangereux ici, vous pouvez supposer que l'utilisateur n'a pas redéfini la fonction getStringValue localement dans ses fichiers (généralement une hypothèse sûre si vous possédez une base de code à laquelle cette règle s'applique).

Dans ce cas, le mieux est d'utiliser un sélecteur pour vérifier l'import, par exemple :

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

Il s'avère qu'il existe un moyen simple de le faire à partir de context 对象中提取 AST 根节点。它位于 context.getSourceCode().ast. J'ai réécrit mon correctif avec la logique suivante :

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
}
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal