VIM 中编辑 Javascript 保存时使用 ESLint 进行语法检查

更新日期: 2022-05-27 阅读次数: 269 字数: 1210 分类: Vim

为何迫切需要语法检查

昨天再次因为一个语法错误,交流浪费了不少时间。本以为是小改动,改完没看就发给别人了,没想到还是出错了。

对于需要编译的语言还好,编译时可以过滤掉语法错误。

但是对于 js 这种动态语言,特别是单文件,没有打包需求的情况下。 极易写出有语法错误的代码。之前是使用 gulp 插件实现的 js 语法检查

对于写 tampermonkey 这种单文件的小功能,我只能在 VIM 里进行配置了。

全局安装 ESLint

sudo npm install eslint --global

(不推荐) VIM Syntastic 配置

Syntastic 是 VIM 的一个语法检查插件。支持通过多种其他工具组合对多种语言进行语法检查。我发现之前的 golang 语法检测也是基于 Syntastic 的。

Plugin 'vim-syntastic/syntastic'

" ... 其他配置

let g:syntastic_javascript_checkers=['eslint']

" Syntastic has numerous options that can be configured, 
" and the defaults are not particularly well suitable for new users.
" 不添加下面的配置,无法看到错误提示
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*

let g:syntastic_always_populate_loc_list = 1
let g:syntastic_auto_loc_list = 1
let g:syntastic_check_on_open = 1
let g:syntastic_check_on_wq = 0

安装

:PluginInstall

(推荐) VIM ALE 配置

syntastic 有一个严重的问题,其是阻塞的。在打开大的文件时,会有明显的卡顿现象。 例如,antd pro 的一个 ts 文件,打开用了 10 秒。在其执行完之前,啥也干不了。这非常的不友好。

找了一个替代品 ALE,充分利用了 NeoVim 及 Vim8 的异步特性,体验好太多。

ALE (Asynchronous Lint Engine) is a plugin providing linting (syntax checking and semantic errors) in NeoVim 0.2.0+ and Vim 8 while you edit your text files, and acts as a Vim Language Server Protocol client.

Plugin 'dense-analysis/ale'

" ALE plugin
let g:ale_fixers = {
\   '*': ['remove_trailing_lines', 'trim_whitespace'],
\   'javascript': ['eslint'],
\}

" show errors in location list
let g:ale_open_list = 1
" Show 5 lines of errors (default: 10)
let g:ale_list_window_size = 5
" Set this variable to 1 to fix files when you save them.
let g:ale_fix_on_save = 1
let g:ale_lint_on_text_changed = 'never'
let g:ale_lint_on_insert_leave = 0

https://github.com/dense-analysis/ale

ESLint 配置文件

个人 home 目录新建一个配置文件 ~/.eslintrc.js

module.exports = {
    "env": {
        "browser"      : true,
        "es6"          : true,
        "greasemonkey" : true,
        "jquery"       : true,
        "node"         : true,
    },
    "extends": "eslint:recommended",
    "rules": {
        // enable additional rules
        "linebreak-style": ["error", "unix"],
    },
    "parserOptions": {
        // Required for certain syntax usages
        "ecmaVersion": 2020
    },
}

配置文件的规范可以参考这里:

https://eslint.org/docs/user-guide/configuring/configuration-files

至此,就配置好了。

打开之前写的 js 文件,一堆错误,惨不忍睹。。。

Parsing error: Unexpected token

在语法检查时,发现诡异的错误。例如这行:

let coursesCount = courses.length;

提示错误内容:

sunzhongwei.com.user.js|315 col 7 error| Parsing error: Unexpected token coursesCount

修复方法,增加配置

"parserOptions": {
    // Required for certain syntax usages
    "ecmaVersion": 2020
},

"window" is not defined

由于是给 tampermonkey 开发插件,即 js 文件是运行在浏览器中的,所以 window 对象就被当成了未定义。

两种修复方法:

"globals": {
    "document": true,
    "window": true
}

或:

"env": {
    "browser": true,
},

第二种做法更简洁直观,而第一种做法则可以处理更多场景,例如 tampermonkey 里的各种全局变量。 但实际上 eslint 还内置了 greasemonkey, jquery 这些 env 非常贴心。

'module' is not defined

"env": {
    "node": true
},

不设置 eslint 配置文件的报错信息

打开 VIM 编辑一个 js 文件,故意写一行语法错误的代码。 在保存时,并没有看到对应的语法错误提示。

为了排查,我在命令行里手动运行了一下 eslint,果然报错:

$ eslint sunzhongwei.com.user.js

Oops! Something went wrong! :(

ESLint: 8.16.0

ESLint couldn't find a configuration file. To set up a configuration file for this project, please run:

    npm init @eslint/config

ESLint looked for configuration files in /mnt/d/work/sunzhongwei.com/src/ and its ancestors. If it found none, it then looked in your home directory.

If you think you already have a configuration file or if you need more help, please stop by the ESLint chat room: https://eslint.org/chat/help

看起来是没有对 eslint 进行配置导致的。

其他的语法检查方案

  • CI: 多人合作时,这个更靠谱一点
  • VSCode: 其 snippet 语法太恶心,无法继承我的 VIM 财产;再就是 IDE 里写代码没有感觉

TODO

  • [X] 开发环境自动部署配置
  • [X] 是否有快捷键自动跳到下一行错误: :lnext, :lprevious。如果要快速重复 lnext,可以用 @@

快速重复上个命令

The last command entered with ':' can be repeated with @: and further repeats can be done with @@

lnext 与 lprevious

l 前缀代表 location。

VIM location list 与 quickfix list 的区别:

  • The location list is local to the current window so you can have as many location lists as windows.
  • The quickfix list is global so you can't have more than one available at a time.

参考

  • https://remarkablemark.org/blog/2016/09/28/vim-syntastic-eslint/

tags: Javascript 语法检查工具

爱评论不评论