自定义luacheck校验规则

安装运行环境

安装环境及源码解析,参考:LuaCheck校验原理解析

自定义校验规则

从代码中可以看出,定义一条规则有以下关键点:

  1. 需要定义告警信息:由键值对组成,key为告警编码(不一定为纯数字,只是这里使用的是纯数字),value为告警信息,告警信息中,message_format为消息模板,fields为消息中定义的字段,这两者用于模板文本传参,如果不需要传参,即只需要打印固定信息时,fields可以为空 {} 。此处定义在每个模块的stage.warnings对象中。
  2. 需要在模块中定义stage.run函数并将其return,stage.run函数即为此模块的主函数,在这里执行校验规则,函数接受chstate参数,作为被检查行的上下文对象;
  3. 当需要弹出告警时,需要使用chstate:warn_xx函数推送,可用函数有:
    1. chstate:warn_range(code, range, warning):
      • code为步骤1定义的告警信息对应告警编码,字符串形式,如"541";
      • range为需要提示的代码块,以node节点形式传入;
      • warning为需要覆盖的告警信息,例如,已定义告警信息为 {["541"] = {message_format = "empty do..end block", fields = {}}} ,这里可以通过传参 {["541"] = {message_format = "nothing", fields = {}}} 来将其覆盖。通常不需要传这个参数。
    2. chstate:warn_var(code, var, warning):此处code、warning参数与chstate:warn_range函数一致,var参数顾名思义,传入的是一个变量对象,同样以node节点形式传入;
    3. chstate:warn_value(code, value, warning):此处value为一个被赋值的变量对象,可知其关系为value.var_node 即为这个值对应的变量(ast语法树中节点),value.var_node.node即为对应代码块;
  4. 需要将这个模块添加到stages.lua的执行列表中,即 stages.names ,注意,必须要添加到前置流程之后,即 resolve_locals 之后;
示例:自定义规则模块

接下来实现一条简单自定义规则:代码中不允许出现 HelloLua 字样,规则编码为 700 ;

步骤1:stages下新增模块

src/luacheck/stages/ 下,新建 HelloLua.lua 文件,其内容为:

lua 复制代码
local stage = {}

stage.warnings = {}

function stage.run(chstate)
end

return stage
步骤2:编写规则及其校验方法

修改 HelloLua.lua 文件如下:

lua 复制代码
local stage = {}

stage.warnings = {
  ["700"] = {message_format = "do not show HelloLua", fields = {}},
}

function stage.run(chstate)
   local num_lines = #chstate.line_offsets
   for line_number = 1, num_lines do
      local line_offset = chstate.line_offsets[line_number]
      local line_length = chstate.line_lengths[line_number]
      -- 若检查到此行代码中存在HelloLua,则打印对应告警
      if chstate.source:find("HelloLua", line_offset, true) then
         chstate:warn("700", line_number, line_offset, line_offset + #("HelloLua") - 1)
      end
   end
end

return stage
步骤3:将自定义模块添加到stages.lua中

修改stages.lua中stages.names如下:

lua 复制代码
stages.names = {
   "parse",
   "unwrap_parens",
   "linearize",
   "parse_inline_options",
   "name_functions",
   "resolve_locals",
   "detect_bad_whitespace",
   "detect_cyclomatic_complexity",
   "detect_empty_blocks",
   "detect_empty_statements",
   "detect_globals",
   "detect_reversed_fornum_loops",
   "detect_unbalanced_assignments",
   "detect_uninit_accesses",
   "detect_unreachable_code",
   "detect_unused_fields",
   "detect_unused_locals",
   "HelloLua"
}
-- 添加到末尾

此时该规则已配置完成,接下来是验证其生效;

步骤4:验证

用于测试的lua文件 init.lua 内容如下:

lua 复制代码
local base_dir = vim.env.LUNARVIM_BASE_DIR
  or (function()
    local init_path = debug.getinfo(1, "HelloLua").source -- 此处修改字符串内容,检查是否告警
    return init_path:sub(2):match("(.*[/\\])"):sub(1, -2)
  end)()

if not vim.tbl_contains(vim.opt.rtp:get(), base_dir) then
  vim.opt.rtp:prepend(base_dir)
end

require("lvim.bootstrap"):init(base_dir)

require("lvim.config"):load()

local plugins = require "lvim.plugins"

require("lvim.plugin-loader").load { plugins, lvim.plugins }

require("lvim.core.theme").setup()

local Log = require "lvim.core.log"
Log:debug "Starting LunarVim"

local commands = require "lvim.core.commands"
commands.load(commands.defaults)

执行检查:

bash 复制代码
root@979bc2a8a939:~/test/luacheck-0.23.0# lua -e 'package.path="/root/test/luacheck-0.23.0/src/?.lua;/root/test/luacheck-0.23.0/src/?/init.lua;"..package.path' /root/test/luacheck-0.23.0/bin/luacheck.lua --codes init.lua 
Checking init.lua                                 8 warnings

    init.lua:1:1: (W700) do not show HelloLua
    init.lua:1:18: (W113) accessing undefined variable vim
    init.lua:2:1: (W700) do not show HelloLua
    init.lua:3:1: (W700) do not show HelloLua
    init.lua:7:8: (W113) accessing undefined variable vim
    init.lua:7:25: (W113) accessing undefined variable vim
    init.lua:8:3: (W113) accessing undefined variable vim
    init.lua:17:47: (W113) accessing undefined variable lvim

Total: 8 warnings / 0 errors in 1 file

可见该规则已生效。

此处注意,因为这里使用的是从luacheck源脚本执行,所以所有涉及路径的参数必须指向luacheck所在路径,要根据实际所处位置进行调整,--codes 参数用于显示对应检查规则,也可以在 .luacheckrc 文件中定义 codes = true

相关推荐
晚霞的不甘43 分钟前
Flutter for OpenHarmony 可视化教学:A* 寻路算法的交互式演示
人工智能·算法·flutter·架构·开源·音视频
晚霞的不甘2 小时前
Flutter for OpenHarmony 实现计算几何:Graham Scan 凸包算法的可视化演示
人工智能·算法·flutter·架构·开源·音视频
猫头虎2 小时前
OpenClaw-VSCode:在 VS Code 里玩转 OpenClaw,远程管理+SSH 双剑合璧
ide·vscode·开源·ssh·github·aigc·ai编程
一只大侠的侠2 小时前
Flutter开源鸿蒙跨平台训练营 Day12从零开发通用型登录页面
flutter·开源·harmonyos
wenzhangli72 小时前
OoderAgent 企业版 2.0 发布的意义:一次生态战略的全面升级
人工智能·开源
rainbow68892 小时前
C++开源库dxflib解析DXF文件实战
开发语言·c++·开源
猫头虎2 小时前
基于信创openEuler系统安装部署OpenTeleDB开源数据库的实战教程
数据库·redis·sql·mysql·开源·nosql·database
零一iTEM3 小时前
MAX98357A_音频输出测试
单片机·嵌入式硬件·开源·音视频·硬件工程
猫头虎3 小时前
如何使用Docker部署OpenClaw汉化中文版?
运维·人工智能·docker·容器·langchain·开源·aigc
一只大侠的侠3 小时前
Flutter开源鸿蒙跨平台训练营 Day 15React Native Formik 表单实战
flutter·开源·harmonyos