当前位置:首页 > 通信资讯 > 正文

eslint --fix怎么用(eslint fix自动修复)

eslint --fix怎么用(eslint fix自动修复)

我们知道 eslint 支持 fix,当添加了 --fix 参数部分 rule 可以自动修复问题。

有没有想过,这种功能是怎么实现的?babel 也能转换代码,它和 eslint 生成代码的原理一样么?

babel

babel 分为 parse、transform、generate 3 步。

eslint --fix怎么用(eslint fix自动修复)

在 transform 阶段转换完 AST 代码之后,在 generate 阶段会递归打印 AST 成目标代码。

generate 的原理就是递归根据每个 AST 的信息拼接字符串:

eslint --fix怎么用(eslint fix自动修复)

所以我们在插件里面改动了 AST,最终的代码也会改。

eslint

eslint 的 rule 可以对 AST 进行检查,然后通过 context.report 报错,还可以指定如何修复:

自定义 rule 格式如下:

  1. module.exports={
  2. meta:{
  3. fixable:true
  4. },
  5. create(context){
  6. return{
  7. //指定AST的类型
  8. ObjectExpression(node){
  9. //一系列检查
  10. context.report({
  11. node,
  12. message:'xxx有错误',
  13. loc:node.loc,
  14. *fix(fixer){
  15. yieldfixer.replaceTextRange([rangeStart,rangeEnd],'替换的文本');
  16. }
  17. });
  18. }
  19. };
  20. }
  21. };

其中 fix 选项就是用于问题自动修复的,通过 fixer 的 api。

fixer 有这些 api 可用:

  1. insertTextAfter(nodeOrToken,text);
  2. insertTextAfterRange(range,text);
  3. insertTextBefore(nodeOrToken,text);
  4. insertTextBeforeRange(range,text);
  5. remove(nodeOrToken);
  6. removeRange(range);
  7. replaceText(nodeOrToken,text);
  8. replaceTextRange(range,text);

特别容易记,就是增、删、改 3类,增分为在前面插入和在后面插入,每一类都支持基于 token 来修改 text 或者基于 range(下标范围)。

AST 中每个节点都保留了 range 的信息,也就是在源代码的下标是从哪到哪,这样就可以根据 range 来修改代码,或者根据 AST 查到 range 再去修改代码。

eslint --fix怎么用(eslint fix自动修复)

那知道了对什么 range 做什么操作之后,是怎么自动修改代码的呢?

下面是 eslint 中 fix 代码的源码:

  1. //源码
  2. constoriginalText=sourceCode.text;
  3. //第一个range的开始
  4. conststart=fixes[0].range[0];
  5. //最后一个range的结束
  6. constend=fixes[fixes.length-1].range[1];
  7. //替换的文本
  8. lettext="";
  9. letlastPos=Number.MIN_SAFE_INTEGER;
  10. for(constfixoffixes){
  11. if(fix.range[0]>=0){
  12. //截取range的左边的字符串,从当前range和上一个range的右边位置取大的
  13. text+=originalText.slice(Math.max(0,start,lastPos),fix.range[0]);
  14. }
  15. //拼接上修复的文本
  16. text+=fix.text;
  17. //range右边的位置
  18. lastPos=fix.range[1];
  19. }
  20. //用拼接的字符串替换range内的字符串
  21. text+=originalText.slice(Math.max(0,start,lastPos),end);

其中比较有意思的一个点是当两端 range 有交集的时候:

eslint --fix怎么用(eslint fix自动修复)

每一个 fix 都是对一个线段(range)内文本的修复,当有交集的时候怎么处理,这其实可以作为一个算法题来考核候选人了。

从左到右应用 fix,然后记录当前的 rangeRight,应用下一段的时候就取 rangeLeft 和上一个 rangeRight 的最大值作为 rangeLeft。

把这个问题抽象出来之后还是一个比较有意思的算法题,我觉得用来面试比较不错,而且有真实的应用场景。

聊回正题,fix 功能的实现就是对每段 range 修改的文本进行拼接,然后替换源码字符串就可以了。

总结

babel 和 eslint 都可以修改代码,babel 是操作了 AST,打印代码的时候就会生成不同的代码,而 eslint 则是一部分 rule 支持自动 fix,当开启了 --fix 的时候就会自动修复。

babel 生成代码的原理是递归打印 AST,拼接字符串,所以改了 AST,生成的代码就改了。

eslint 修复代码的逻辑是对某段 range 的文本做替换,之后拼接,这个与 AST 无关,所以 eslint 的 fix 功能是可选的。

比较有意思的是 eslint 的多个 rule 返回的对多段range 的修改如何应用到对代码修改上,当有交集的时候怎么办,我觉得这个问题可以作为算法题来考查面试者了。

原文链接:https://mp.weixin.qq.com/s/4-imp-DKpLz4VaCHiGDUkw

如果您对该产品感兴趣,请填写办理(客服微信:xiaoxiongyidong)

为您推荐:

发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。