Moonpick 是 Moonscript 的替代 linter。虽然 Moonscript 附带了内置的 linter,但目前它可以检测到的内容有限。例如,内置 linter 将检测未使用的变量,但仅针对所有可能未使用的声明的子集。它不会检测未使用的导入变量、分解变量、未使用的函数等。Moonpick 的诞生就是为了尝试检测以上以及更多内容。
Moonpick 可以通过 Luarocks 安装:
$ luarocks install moonpick
然后可以从命令行运行它:
$ moonpick < path-to-file >
输出非常模仿 Moonscript 内置 linter 的输出。
它也可以轻松捆绑到独立应用程序中,因为它唯一的依赖项是 Moonscript。有关如何以编程方式运行它的更多信息,请参阅 API 部分。
Moonpick 检测所有形式的未使用变量,无论它们是通过分配显式用作变量还是作为import
语句、表分解语句等的一部分隐式创建。
Moonpick 还可以检测并抱怨已声明但未使用的函数参数。默认情况下不启用此功能,因为有未使用的参数是很常见的。例如,一个函数可能遵循外部 API,并且仍然想要指示可用的参数,即使并非所有参数都被使用。要启用此功能,请将report_params
配置选项设置为true
。
Moonpick 附带了一个默认配置,该配置会将任何以“_”开头的参数列入白名单,从而提供了一种保留函数的文档方面并仍然满足 linter 要求的方法。
检测到未使用的循环变量。可以在配置中完全禁用此功能,或者仅为循环变量提供显式白名单。 Moonpick 附带一个默认配置,该配置将参数“i”和“j”或任何以“_”开头的变量列入白名单。
与内置 linter Moonpick 类似,它会检测未定义的引用。
每当一个声明遮蔽了较早的同名声明时,就会发生声明遮蔽。考虑以下代码:
my_mod = require ' my_mod '
-- [.. more code in between.. ]
for my_mod in get_modules ( ' foo ' )
my_mod . bar!
虽然在上面的示例中很清楚,循环中声明的my_mod
与顶层my_mod
不同,但如果在 for 声明和以后的使用之间插入更多代码,这一点很快就会变得不太清楚。到那时,代码就变得不明确了。声明遮蔽通过确保每个变量最多以明确的方式定义一次,从而有助于解决此问题。
通过将report_shadowing
配置变量设置为false可以完全关闭检测,并且可以通过指定whitelist_shadowing
配置列表来配置白名单。
请注意,对于早于 0.5 的 Moonscript 版本,此类阴影实际上只会重复使用先前的声明,从而导致容易被忽视和混淆的错误。
很少需要重新分配先前定义的保存函数值的变量,并且通常是由于忘记先前的声明而导致的。
-- with the following declaration and usage
done = ( x ) -> x . foo and x . bar
done ( {} )
-- one might mistakenly reuse the name further down
i = 1
-- [..]
done = i == 10
这可能会导致难以调试的问题,特别是如果重新分配仅在并不总是执行的代码路径中完成的话。
可以通过将report_fndef_reassignments
配置变量设置为false来完全关闭检测,并且可以通过指定whitelist_fndef_reassignments
配置列表来配置白名单。
从函数或方法内重新分配顶级变量有时可能会导致不明显和难以捉摸的错误,例如:
module = require ' lib.module '
-- [..] much further down
get_foo = ( y ) ->
module = y match ( ' %w+ ' ) lower! -- mistakenly reusing the `module` var
return " #{module}_bar "
如果上面的get_foo
仅被有条件地调用,这可能会导致严重的错误被忽视。
与其他检测相比,默认情况下不启用此检测。可以通过将report_top_level_reassignments
配置变量设置为true来打开检测,并且可以通过指定whitelist_top_level_reassignments
配置列表来配置白名单。不过,强烈建议启用此功能。
默认情况下未启用此功能的原因是,从子函数或方法中操作顶级变量的合法代码并不罕见。为了避免 linter 的投诉,要么必须配置白名单,要么需要采用一种不同的编码风格,其中不重新分配顶级变量(例如,使用表来保存模块状态)。
Moonpick 支持一组与内置 linter 相同的配置文件和格式。
它通过添加对配置函数参数和循环变量的 linting 的支持来提供额外的配置选项,并且还允许所有白名单中的 Lua 模式。 Linter 配置文件可以用 Lua 或 Moonscript 编写(分别为lint_config.lua
和lint_config.moon
)。
请参阅以下示例(lint_config.moon,使用 Moonscript 语法):
{
whitelist_globals : {
-- whitelist for all files
[ " . " ] : { ' always_ignore ' } ,
-- whitelist for files matching 'spec'
spec : { ' test_helper ' } ,
}
whitelist_params : {
-- whitelist params for all files
[ " . " ] : { ' my_param ' } ,
-- ignore unused param for files in api
api : { ' extra_info ' } ,
}
whitelist_loop_variables : {
-- always allow loop variables 'i', 'j', 'k', as well as any
-- variable starting with '_' (using a Lua pattern)
[ " . " ] : { ' i ' , ' j ' , ' k ' , ' ^_ ' } ,
}
-- general whitelist for unused variables if desired for
-- some reason
whitelist_unused : {
[ " . " ] : {} ,
}
-- below you'll see the boolean switches controlling the
-- linting, shown with the default value
-- report_loop_variables: true
-- report_params: true
-- report_shadowing: true
-- report_fndef_reassignments: true
-- report_top_level_reassignments: false
}
如果白名单项包含字母数字字符以外的任何内容,则将其视为模式。
local moonpick = require ( ' moonpick ' )
对code
中的给定代码进行 Lint 处理,返回 linting 检查表。 config
是用于文件的 linting 配置,可以包含通常在配置文件中找到的元素的平面版本( whitelist_globals
、 whitelist_params
、 whitelist_loop_variables
、 whitelist_unused
、 report_params
、 report_loop_variables
)。
配置表示例(Lua语法):
local moonpick = require ( ' moonpick ' )
local code = ' a = 2 '
moonpick . lint ( code , {
whitelist_globals = { ' foo ' , ' bar ' , }
whitelist_params = { ' ^_+ ' , ' other_+ ' }
})
对于上面的示例,返回的检查表如下所示:
{
{
line = 1 ,
pos = 1 ,
msg = ' declared but unused - `a` ' ,
code = ' a = 2 '
}
}
对给定file
进行 Lint 处理,返回 linting 检查表。 opts
目前可以包含一个值lint_config
,它指定要从中加载配置的配置文件。
local moonpick_config = require ( ' moonpick.config ' )
返回path
相关配置文件的路径,如果没有找到则返回nil
。
从config_path
给定的配置文件加载文件file
的 linting 配置。返回的配置将是file
的扁平化配置选项表。
返回给定 linting 选项的评估器实例(例如由load_config_from
返回)。求值器实例提供以下函数(请注意,这些是函数,要使用普通的点运算符.
来调用):
allow_global_access
, allow_unused_param
, allow_unused_loop_variable
, allow_unused
, allow_fndef_reassignment
, allow_top_level_reassignment
顶层_级别_重新分配。
所有这些都将符号(作为字符串)作为其第一个参数,并根据符号是否通过 linting 来返回true
或false
。
请注意,Moonpick 在这个阶段还很年轻,虽然它已经在更大的代码库上成功运行,但它很可能会产生误报和不正确的报告。如果您遇到这种情况,请使用说明错误行为的代码示例提出问题。
版权所有 2016-2017 尼尔斯·诺德曼
Moonpick 在 MIT 许可证下发布(有关完整详细信息,请参阅许可证文件)。
测试需要busted
才能运行,以及pl
模块(Penlight - luarock install penlight
)。只需在项目的根目录中busted
即可。
使用指向本地src
目录的指定 LUA_PATH 执行。假设结帐位置为~/code/moonpick
:
LUA_PATH= " $HOME /code/moonpick/src/?.lua; $HOME /code/moonpick/src/?/init.lua; $( lua -e ' print(package.path) ' ) " ~ /code/moonpick/bin/moonpick * .moon