Moonpick — альтернативный линтер для Moonscript. Хотя Moonscript поставляется со встроенным линтером, в настоящее время его возможности обнаружения ограничены. Например, встроенный линтер обнаружит неиспользуемые переменные, но только для подмножества всех возможных неиспользуемых объявлений. Он не обнаружит неиспользуемые переменные импорта, переменные декомпозиции, неиспользуемые функции и т. д. Moonpick был создан в попытке обнаружить вышеперечисленное и многое другое.
Moonpick можно установить через Luarocks:
$ luarocks install moonpick
Затем его можно запустить из командной строки:
$ moonpick < path-to-file >
Вывод очень похож на вывод встроенного линтера Moonscript.
Его также легко объединить в отдельное приложение, поскольку его единственной зависимостью является Moonscript. Дополнительную информацию о том, как запустить его программно, см. в разделе API.
Moonpick обнаруживает неиспользуемые переменные во всех их формах, независимо от того, используются ли они в качестве переменных явно посредством присвоений или неявно создаются как часть оператора import
, оператора декомпозиции таблицы и т. д.
Moonpick также может обнаруживать объявленные, но неиспользуемые параметры функции и жаловаться на них. По умолчанию это не включено, так как очень часто встречаются неиспользуемые параметры. Например, функция может следовать внешнему API и по-прежнему хочет указывать доступные параметры, даже если не все из них используются. Чтобы включить это, установите для параметра конфигурации report_params
значение true
.
Moonpick поставляется с конфигурацией по умолчанию, которая заносит в белый список любой параметр, начинающийся с «_», обеспечивая возможность сохранить документацию для функции и при этом доставить удовольствие линтеру.
Обнаружены неиспользуемые переменные цикла. Это можно полностью отключить в конфигурации или предоставить явный белый список только для переменных цикла. Moonpick поставляется с конфигурацией по умолчанию, в которой внесены в белый список аргументы «i» и «j» или любая переменная, начинающаяся с «_».
Подобно встроенному линтеру 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
.
Обратите внимание, что для версий Moonscript до 0.5 такого рода затенения на самом деле просто повторно используют предыдущее объявление, что приводит к легко упускаемым из виду и запутанным ошибкам.
Переназначение ранее определенной переменной, содержащей значение функции, требуется редко и часто является результатом забвения предыдущего объявления.
-- 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
. Однако настоятельно рекомендуется включить это.
Причина, по которой это не включено по умолчанию, заключается в том, что нередко имеется легитимный код, который манипулирует переменными верхнего уровня из подфункций или методов. Чтобы избежать жалоб со стороны линтера, нужно либо настроить белый список, либо принять другой стиль кодирования, при котором переменные верхнего уровня не переназначаются (например, используя вместо этого таблицу для хранения состояния модуля).
Moonpick поддерживает набор того же файла конфигурации и формата, что и встроенный линтер.
Он предоставляет дополнительные возможности конфигурации, добавляя поддержку настройки проверки параметров функции и переменных цикла, а также допускает использование шаблонов Lua во всех белых списках. Файлы конфигурации ЛИНТЕРА могут быть написаны либо на 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
, возвращая таблицу проверок линтинга. config
— это конфигурация проверки, используемая для файла, и может содержать плоские версии элементов, обычно встречающихся в файле конфигурации ( 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
, возвращая таблицу проверок проверки. opts
в настоящее время может содержать одно значение, lint_config
, которое указывает файл конфигурации, из которого загружается конфигурация.
local moonpick_config = require ( ' moonpick.config ' )
Возвращает путь к соответствующему файлу конфигурации для path
или nil
, если он не найден.
Загружает конфигурацию проверки для file
file из файла конфигурации, указанного в config_path
. Возвращенная конфигурация будет представлять собой таблицу параметров конфигурации file
.
Возвращает экземпляр оценщика для заданных параметров проверки (например, возвращаемый load_config_from
). Экземпляр оценщика предоставляет следующие функции (обратите внимание, что это функции, вызываемые с помощью обычного оператора точки .
):
allow_global_access
, allow_unused_param
, allow_unused_loop_variable
, allow_unused
, allow_fndef_reassignment
, allow_top_level_reassignment
.
Все они принимают в качестве первого аргумента символ (в виде строки) и возвращают true
или false
в зависимости от того, прошел ли символ проверку или нет.
Обратите внимание, что Moonpick довольно молод на данном этапе, и хотя он успешно работает на более крупных базах кода, он вполне может давать ложные срабатывания и неверные отчеты. Если вы столкнулись с этим, откройте проблему с примером кода, который иллюстрирует неправильное поведение.
Copyright 2016-2017 Нильс Нордман
Moonpick выпускается под лицензией MIT (полную информацию см. в файле LICENSE).
Для запуска тестов требуется busted
, а также модуль pl
(Penlight — luarock install penlight
). Просто запустите busted
в корневом каталоге проекта.
Выполнить с указанным LUA_PATH, указывающим на локальный каталог src
. Предполагая, что касса находится в ~/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