组织需要并将它们移到文档Top

我正在组织代码在一个应用程序。 require声明是不组织的,所以我使这个codemod对它们进行sorting并将它们添加到页面顶部。

codemod工作 ,几乎完美。 我有些疑惑:

  • 这是一个好方法,还是有一个更正确的方式来使用API​​?
  • 我怎么能保持sourceStart (所有要求)和其他源代码之间的空行?
  • 在ES6import中可以使用类似的方法吗? (即用jscodeshift对它们进行sorting)

我的初始代码:

 var path = require('path'); var stylus = require('stylus'); var express = require('express'); var router = express.Router(); var async = require('async'); let restOfCode = 'foo'; 

我的codemod:

 let requires = j(file.source).find(j.CallExpression, { "callee": { "name": "require" } }).closest(j.VariableDeclarator); let sortedNames = requires.__paths.map(node => node.node.id.name).sort(sort); // ["async", "express", "path", "stylus"] let sortedRequires = []; requires.forEach(r => { let index = sortedNames.indexOf(r.node.id.name); sortedRequires[index] = j(r).closest(j.VariableDeclaration).__paths[0]; // <- feels like a hack }); let sourceStart = j(sortedRequires).toSource(); let sourceRest = j(file.source).find(j.CallExpression, { "callee": { "name": "require" } }).closest(j.VariableDeclaration) .replaceWith((vD, i) => { // return nothing, it will be replaced on top of document }) .toSource(); return sourceStart.concat(sourceRest).join('\n'); // is there a better way than [].concat(string).join(newLine) ? 

结果我得到了:

 var async = require('async'); var express = require('express'); var path = require('path'); var stylus = require('stylus'); var router = express.Router(); // <- I would expect a empty line before this one let restOfCode = 'foo'; 

这是一个好方法,还是有更正确的方式来使用API​​?

你不应该直接访问__paths 。 如果您需要访问所有的NodePath,则可以使用.paths()方法。 如果要访问AST节点,请使用.nodes()

例如,映射只是

 let sortedNames = requires.nodes()(node => node.id.name).sort(sort); 

我怎么能保持sourceStart (所有要求)和其他源代码之间的空行?

没有一个好的方法来做到这一点。 看到这个相关的重铸问题 。 希望有一天CST会变得更容易。

在ES6import中可以使用类似的方法吗? (即用jscodeshift对它们进行sorting)

当然。


FWIW,这是我的版本(基于你的第一个版本):

 export default function transformer(file, api) { const j = api.jscodeshift; const sort = (a, b) => a.declarations[0].id.name.localeCompare( b.declarations[0].id.name ); const root = j(file.source); const requires = root .find(j.CallExpression, {"callee": {"name": "require"}}) .closest(j.VariableDeclaration); const sortedRequires = requires.nodes().sort(sort); requires.remove(); return root .find(j.Statement) .at(0) .insertBefore(sortedRequires) .toSource(); }; } 

https://astexplorer.net/#/i8v3GBENZ7