有一天上头说要给文件加一个copyright。好👌。
实现这个基本需求的方法有很多。比如在 git hook 中添加。选择Eslint 和 vscode 是因为,方便。可以实现,写代码后保存就出现copyright。而且不用理会什么Git hook 什么周期中,暂存区与工作区中文件的冲突。
本文涉及的内容
- eslint rule 是什么。
- AST 概念
- 如何配置 vscode 已达到引用自定义的rule
原理
vscode 可以暗转 eslint-vscode 插件,配置好 eslint 配置之后,保存vscode就会自己去跑 eslint --fix . 那么我们只要写一个 eslint-rule 去完成检测copyright是否添加,没有的话如何添加就OK了。
eslint-rule 如何写?
eslint-rule: 对源代码进行检测,并提供修复与报错作用的脚本。 (rule要做到这些功能,就必须要对代码进行增删改。自然用最普通的方案就是用AST将源代码最为树形结构的对象。)基本上看ESLINT RULE 文档 是少不了的。
AST 代码抽象树
听起来很牛逼,实际上确实是这样子的。但是最难的如何将源代码转为AST 树的核心思想基本上我们都不需要会(除非你要开发一门新的语言什么的)。我们这里就说下他大概的意思。就想上面说的。我们要做源代码增伤改查。如果我们直接对源代码中的字符串进行操作。那真是令人头大的工作。比如我们分析 var a = 123; 我们要怎么用代码知道这是行赋值语句。变量名是什么等等信息。很显然对正常人来说把它看成字符串来逐行分析是不现实的。而就是有人能做到,提供了库将这样的字符串解析出他原本的代码意义并将其转为以树为结构保存的对象。我们成这类库成为解析器。转后的树对象成为 AST。除了将源代码解析成AST树的技术,其他概念都是纸老虎,千万别被用AST写一个babel plugin这样的话吓到。有了概念小学生都能写
var a = 123 // 源代码
// 下面是用 acoron 解析出来的AST
{
"type": "Program",
"start": 0,
"end": 13,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 13,
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 13,
"id": {
"type": "Identifier",
"start": 4,
"end": 5,
"name": "a"
},
"init": {
"type": "Literal",
"start": 8,
"end": 13,
"value": "123",
"raw": "'123'"
}
}
],
"kind": "var"
}
],
"sourceType": "module"
}
扯远了。对JS AST树的结构感谢区的话我下期再写,记录下几个常见的格式,建立起AST树的模型,已达到能看懂的情况。
自己写的rule代码,🌶🐓
module.exports = {
meta: {
fixable: 'code',
type: 'suggestion',
},
create(context) {
function hasCopyrightComment(comments) {
const firstComment = comments[0] || {}
const commentValue = firstComment.value || ''
const range = firstComment.range
const copyright = commentValue.replace(/^\n|\n$/g, '')
if (copyright === COPYRIGHT && range[0] === 0) {
return true
}
}
return {
Program(node) {
if (hasCopyrightComment(context.getAllComments())) {
return
}
context.report({
message: 'has not copyright',
node,
fix(fixer) {
return fixer.insertTextBeforeRange([0, 0], `/*\n${COPYRIGHT}\n*/\n`)
},
})
},
}
},
}
大概思路,大可完善。但是完善的代码就是从0到1的过程了。
如何应用到开发中(遇到的坑)
eslint 不太建议自己rule放在本地,他希望你写完的rule能共享出来。想要达到vscode报存就应用自己定义的rule需要。
- 在 eslintrc.js 中写入你的rule文件的名。 rules: { rulename: ...}
- 在项目根目录创建.vscode/settings.json
- 在settins.json 中写入 { "eslint.autoFixOnSave": true, "eslint.options": { "rulePaths": ["你的rule文件路径"], }, }
完成。