Moonpick est un linter alternatif pour Moonscript. Bien que moonscript soit livré avec un linter intégré, il est actuellement limité dans ce qu'il peut détecter. Le linter intégré détectera par exemple les variables inutilisées, mais uniquement pour un sous-ensemble de toutes les déclarations inutilisées possibles. Il ne détectera pas les variables d'importation inutilisées, les variables de décomposition, les fonctions inutilisées, etc. Moonpick est né dans le but de détecter ce qui précède et bien plus encore.
Moonpick peut être installé via Luarocks :
$ luarocks install moonpick
Il peut ensuite être exécuté depuis la ligne de commande :
$ moonpick < path-to-file >
La sortie imite fidèlement la sortie du linter intégré de Moonscript.
Il est également facilement intégré dans une application autonome car sa seule dépendance est moonscript. Consultez la section API pour plus d’informations sur la façon de l’exécuter par programme.
Moonpick détecte les variables inutilisées sous toutes leurs formes, qu'elles soient explicitement utilisées comme variables via des affectations ou implicitement créées dans le cadre d'une instruction import
, d'une instruction de décomposition de table, etc.
Moonpick peut également détecter et se plaindre des paramètres de fonction déclarés mais inutilisés. Ceci n'est pas activé par défaut, car il est très courant d'avoir des paramètres inutilisés. Par exemple, une fonction peut suivre une API externe et vouloir quand même indiquer les paramètres disponibles même si tous ne sont pas utilisés. Pour activer cela, définissez l'option de configuration report_params
sur true
.
Moonpick est livré avec une configuration par défaut qui met en liste blanche tout paramètre commençant par un « _ », offrant ainsi un moyen de conserver les aspects documentaires d'une fonction tout en satisfaisant le linter.
Les variables de boucle inutilisées sont détectées. Il est possible de désactiver complètement cela dans la configuration, ou de fournir une liste blanche explicite uniquement pour les variables de boucle. Moonpick est livré avec une configuration par défaut qui met en liste blanche les arguments « i » et « j », ou toute variable commençant par un « _ ».
Semblable au linter intégré, Moonpick détecte les références non définies.
L'observation d'une déclaration se produit chaque fois qu'une déclaration masque une déclaration antérieure portant le même nom. Considérez le code suivant :
my_mod = require ' my_mod '
-- [.. more code in between.. ]
for my_mod in get_modules ( ' foo ' )
my_mod . bar!
Bien qu'il soit assez clair dans l'exemple ci-dessus que le my_mod
déclaré dans la boucle est différent du niveau supérieur my_mod
, cela peut rapidement devenir moins clair si davantage de code est inséré entre la déclaration for et une utilisation ultérieure. A ce stade, le code devient ambigu. L'observation de la déclaration y contribue en garantissant que chaque variable est définie au plus une fois, de manière sans ambiguïté.
La détection peut être complètement désactivée en définissant la variable de configuration report_shadowing
sur false, et la liste blanche peut être configurée en spécifiant une liste de configuration whitelist_shadowing
.
Notez que pour les versions de Moonscript antérieures à 0.5, ce type d'observations réutiliserait simplement la déclaration précédente, conduisant à des bogues facilement négligés et déroutants.
La réaffectation d'une variable précédemment définie contenant une valeur de fonction est rarement souhaitée et est souvent le résultat de l'oubli d'une déclaration antérieure.
-- 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
Cela peut entraîner des problèmes de débogage difficiles, en particulier si la réaffectation est effectuée uniquement dans un chemin de code qui n'est pas toujours utilisé.
La détection peut être complètement désactivée en définissant la variable de configuration report_fndef_reassignments
sur false, et la liste blanche peut être configurée en spécifiant une liste de configuration whitelist_fndef_reassignments
.
La réaffectation d'une variable de niveau supérieur à partir d'une fonction ou d'une méthode peut parfois être la cause de bugs non évidents et insaisissables, par exemple :
module = require ' lib.module '
-- [..] much further down
get_foo = ( y ) ->
module = y match ( ' %w+ ' ) lower! -- mistakenly reusing the `module` var
return " #{module}_bar "
Si get_foo
ci-dessus n'est appelé que sous condition, cela pourrait faire passer de graves bugs inaperçus.
Contrairement aux autres détections, cette détection n'est pas activée par défaut. La détection peut être activée en définissant la variable de configuration report_top_level_reassignments
sur true, et la liste blanche peut être configurée en spécifiant une liste de configuration whitelist_top_level_reassignments
. Il est cependant fortement recommandé de l'activer.
La raison pour laquelle cela n'est pas activé par défaut est qu'il n'est pas rare d'avoir du code légitime qui manipule des variables de niveau supérieur à partir de sous-fonctions ou de méthodes. Afin d'éviter les plaintes du linter, il faudrait alors soit configurer la liste blanche, soit adopter un style de codage différent dans lequel les variables de niveau supérieur ne sont pas réaffectées (par exemple en utilisant une table pour conserver l'état du module à la place).
Moonpick prend en charge un super ensemble du même fichier de configuration et du même format que le linter intégré.
Il fournit des options de configuration supplémentaires en ajoutant la prise en charge de la configuration du peluchage des paramètres de fonction et des variables de boucle, et autorise également les modèles Lua dans toutes les listes blanches. Les fichiers de configuration Linter peuvent être écrits en Lua ou Moonscript ( lint_config.lua
et lint_config.moon
respectivement).
Voir l'exemple ci-dessous (lint_config.moon, utilisant la syntaxe 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
}
Un élément de la liste blanche est traité comme un modèle s’il contient autre chose que des caractères alphanumériques.
local moonpick = require ( ' moonpick ' )
Lint le code donné dans code
, renvoyant un tableau des inspections de peluchage. config
est la configuration de linting à utiliser pour le fichier et peut contenir des versions plates des éléments généralement trouvés dans un fichier de configuration ( whitelist_globals
, whitelist_params
, whitelist_loop_variables
, whitelist_unused
, report_params
, report_loop_variables
).
Exemple de table de configuration (syntaxe Lua) :
local moonpick = require ( ' moonpick ' )
local code = ' a = 2 '
moonpick . lint ( code , {
whitelist_globals = { ' foo ' , ' bar ' , }
whitelist_params = { ' ^_+ ' , ' other_+ ' }
})
Le tableau des inspections renvoyé ressemblerait à ceci pour l'exemple ci-dessus :
{
{
line = 1 ,
pos = 1 ,
msg = ' declared but unused - `a` ' ,
code = ' a = 2 '
}
}
Lints le file
donné, renvoyant un tableau des inspections de peluchage. opts
peut actuellement contenir une valeur, lint_config
, qui spécifie le fichier de configuration à partir duquel charger la configuration.
local moonpick_config = require ( ' moonpick.config ' )
Renvoie le chemin du fichier de configuration pertinent pour path
, ou nil
si aucun n'a été trouvé.
Charge la configuration du linting pour le file
file à partir du fichier de configuration donné par config_path
. La configuration renvoyée sera un tableau d'options de configuration aplaties pour file
.
Renvoie une instance d'évaluateur pour les options de linting données (par exemple, telles que renvoyées par load_config_from
). L'instance d'évaluateur fournit les fonctions suivantes (notez qu'il s'agit de fonctions qui doivent être invoquées à l'aide de l'opérateur point ordinaire .
) :
allow_global_access
, allow_unused_param
, allow_unused_loop_variable
, allow_unused
, allow_fndef_reassignment
, allow_top_level_reassignment
.
Tous prennent comme premier argument un symbole (sous forme de chaîne) et renvoient true
ou false
selon que le symbole passe ou non le peluchage.
Notez que Moonpick est plutôt jeune à ce stade, et bien qu'il ait été exécuté avec succès sur des bases de code plus grandes, il peut très bien produire des faux positifs et des rapports incorrects. Si vous rencontrez ce problème, veuillez ouvrir un problème avec un exemple de code illustrant le comportement incorrect.
Copyright 2016-2017 Nils Nordman
Moonpick est publié sous licence MIT (voir le fichier LICENSE pour plus de détails).
Les tests nécessitent busted
pour s'exécuter, ainsi que le module pl
(Penlight - luarock install penlight
). Exécutez simplement busted
dans le répertoire racine du projet.
Exécutez avec un LUA_PATH spécifié pointant vers le répertoire src
local. En supposant un emplacement de paiement de ~/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