问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

Eslint的disable、enable的注释配置是怎么实现的

发布网友 发布时间:2天前

我来回答

1个回答

热心网友 时间:2024-10-21 16:20

不知道大家有没有用过ESLint的注释的配置方式:

/*eslint-disableno-alert,no-console*/alert('foo');console.log('bar');/*eslint-enableno-alert,no-console*///eslint-disable-next-linealert('foo');

eslint支持eslint-disable、eslint-enable、eslint-disable-next-line等指定某个rule是否生效的行内配置,叫做inlineconfig。

webpack中也有这种配置方式,可以在动态引入一个模块的时候配置代码分割的方式,叫做magiccomment。

import(/*webpackChunkName:"my-chunk-name"*//*webpackMode:"lazy"*//*webpackExports:["default","named"]*/'mole');

类似的,terser也有这种机制,叫做annotation,可以指定某个api是否是纯的,纯函数的话如果没用到可以直接删除。

vara=/*#__PURE__*/React.createElement("div",null);

可以看到,很多库都用到了这种通过注释来配置的方式,不管是叫annotation也好、magiccomment也好,或者inlineconfig也好,都指的同一个东西。

既然是这么常见的配置方式,那么他们是怎么实现的呢?

注释中配置的实现原理

我们拿eslint的inlineconfig的实现来看一下。

eslint会把源码parse成AST,然后对把AST传入一系列rule来做检查,检查结果会用formatter格式化后输出。

注释的配置是在哪一步生效的呢?

我简化了一下源码,是这样的:

verify(text){//parse源码constast=parse(text);//调用rule,拿到lint的问题constlintingProblems=runRules(ast);//通过AST拿到注释中的配置constcommentDirectives=getDirectiveComments(ast);//根据注释中的配置过滤问题returnapplyDisableDirectives(lintingProblems,commentDirectives);}

可以看到,整体流程是:

把源码parse成AST

调用rule对AST做检查,拿到lint的problems

通过AST拿到注释中的diectives

通过directives过滤problems,就是最终需要报出的问题

也就是说eslint的inlineconfig是在lint完AST,拿到各种problems之后生效的,对problems做一次过滤。

那怎么从AST中取出directives的呢?又是怎么过滤problems的呢?

我们分别看一下。

从AST取出directives的源码简化以后是这样的:

functiongetDirectiveComments(ast){constdirectives=[];ast.comments.forEach(comment=>{constmatch=/^[#@](eslint(?:-env|-enable|-disable(?:(?:-next)?-line)?)?|exported|globals?)(?:\s|$)/u.exec(comment.trim());if(match){constdirectiveText=match[1];...directives.push({type:xxx,line:loc.start.line,column:loc.start.column+1,ruleId});}}returndirectives;}

其实就是对AST中所有的comments的内容做一下正则的匹配,如果是支持的directive,就把它收集起来,并且记录下对应的行列号。

之后就是对problems的过滤了。

简化后的源码是这样的:

functionapplyDisableDirectives(problems,disableDirectives){constfilteredProblems=[];constdisabledRuleMap=newMap();letnextIndex=0;for(constproblemofproblems){//对每一个probelm,都要找到当前被禁用的rulewhile(nextIndex<disableDirectives.length&&compareLocations(disableDirectives[nextIndex],problem)<=0){constdirective=disableDirectives[nextIndex++];switch(directive.type){case"disable":disabledRuleMap.set(directive.ruleId,directive);break;case"enable":disabledRuleMap.delete(directive.ruleId);break;}}//如果problem对应的rule没有被禁用,则返回if(!disabledRuleMap.has(problem.ruleId)){filteredProblems.push(problem);}}returnfilteredProblems;}functioncompareLocations(itemA,itemB){returnitemA.line-itemB.line||itemA.column-itemB.column;}

我们理下思路:

我们要过滤掉problems中被disabled的rule报出的problem,返回过滤后的problems。

可以维护一个disabledRuleMap,表示禁用的rule。

对每一个problem,都根据行列号来从disableDirectives中取出directive的信息,把对应的rule放入disabledRuleMap。

然后看下该problem的rule是否是被禁用了,也就是是否在disabledRuleMap中,如果是,就过滤掉。

这样处理完一遍,返回的problem就是可以报出的了。

这就是eslint的eslint-disable、eslint-enable、eslint-disable-next-line等注释可以配置rule是否生效的原理。

eslint是根据行列号找到对应的comment的,其实很多AST中会记录每个节点关联的comment。

比如babel的AST:

这样可以根据AST来取出注释,之后通过正则来判断是否是directive。

通过行列号来查找comment,通过AST找到关联的comment,这是两种查找注释的方式。

总结

注释中的配置在eslint、webpack、terser等工具中都有应用,分别叫inlineconfig、magiccomment、annotation,但都指的同一个东西。

它们都是找到AST中的comments,通过正则匹配下是否是支持的directive(指令),然后取出对应的信息。

找到directive之后,还要找到directive生效的地方,可以用两种方式来查找:一种是根据行列号的比较,一种是根据关联的AST来查找。

找到directive和对应生效的地方之后,就可以根据directive中的信息做各种处理了。

eslint中是在调用完rule之后,拿到所有的problems,通过行列号匹配directive,根据其中的disabledrule过滤掉一些problem。

注释中的配置是一种比较常见的配置方式,适合一些局部的配置。理解了它们的实现原理,能够让我们更好的掌握这种机制。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
这是什么钞票。 请问这是哪个国家的钞票?价值多少人民币?谢谢 快易典学生平板电脑屏幕碎了怎么办,我在书店买的,可以拿到书店修吗... 沧州龟头周围有一圈小肉粒是什么? 快易典学生电脑的屏幕摔坏了,触屏触不了,可以修吗?如果修的话要多少... 西班牙冷汤和哪些菜品搭配更好喝? 西班牙番茄冷汤提示 我想请问你在秦汉胡同学学古筝...一共需要多少钱啊,包括买古筝的钱 word2010如何查看和编辑文档? 胸罩带子老掉,罩杯边有空 Eslint该如何配置?Eslint使用以及相关配置说明 Eslint 核心概念 &amp; 自定义 plugin 开发 氧气的最终去向为什么是氧化分解有机物呢? ...氧转化成水,有机物转化为二氧化碳吗? 为什么氧的最终去向是分解有机... ...成二氧化碳吗? 2.氧的最终去向为什么是分解有机物呢? 勇者大冒险动漫中男主角安岩的房东叫什么 十万个冷笑话时光鸡是哪一集 办理的移动业务套餐,想问一下这两项优惠到底是指什么,又该怎么用?_百 ... 勇者大冒险神荼的发型是什么发型 安岩是什么电视剧 苹果6S没感觉多卡,就是玩游戏半个小时去了30%左右的电!要不要换华为P... 没有妈妈我也会好快乐作文350 为什么我上传空间相册里的视频不全显示出来,只显示一半? 没有电工证让安监发现了怎么办? 从杭州汽车南站到浙工大屏峰校区应坐几路车 从萧山机场到浙江工业大学屏风校区坐几路公交? 湖北省经济管理干部学院到武昌鸟语林怎么坐车最快 ...3层框架结构的楼,面积大概350平米,需要多少吨钢筋、水泥;造价大概多 ... 浙江衢州姜家山文武校的校长杨海林和浙江向明学校的色狼是一个人吗... ...一辈子不原谅,到死也不原谅,抱着别人说爱我,有老婆不承认,骗我... 2020年中考成绩排名怎么看? 每个学校对不同省的分数线一样吗 吉祥又成功的公司名字2024 吉祥大气公司名字 2024年起个发财的公司名字 企业名有内涵高级大全最新版 2024有高级感的公司名字 PPT演讲中的倒计时怎么做?一分钟搞定 小学四年级数学日记怎么写啊?有谁写过?? 文科532分,肇庆学院录取机会大吗? 我今年理科高考540分 可以报考肇庆学院吗? 广东考生542分有什么本A院校好选择啊~~~ 我这个分数能上广东肇庆学院吗? 我是今年的文科生,考了492分,想报考肇庆学院,有希望吗??? 29岁适合雪花秀哪个系列 29岁,混合性皮肤,眼角有细纹,用雪花秀的什么产品好 我的电脑有一个空文件夹删除不掉,求教高手 血源诅咒圣杯地牢 项目投资来源包括什么 刷全量包是什么意思 《变身!偶像公主》共有几集?在哪可以看到全部? 日本偶像动画片像寻找满月.守护甜心.偶像公主.宣言.天堂.sa...我都...