Elm2 アドベントカレンダー 2017 の3日目です。
Elm Analyse は Elm コードの良くない匂いを嗅ぎつけて指摘してくれるツールです。
使い方
npm (または yarn)でインストールします。
npm install -g elm-analyse
プロジェクトのルートディレクトリでコマンドを打つと警告が一覧で出力されます。
elm-analyse
(場合によっては多少待ちます)
チェック事項
以下の項目をチェックします。
CoreArrayUsage
Elm 0.18 の Array にはバグがあるので、今は Skinney/elm-array-exploration を使った方がいい(0.19 でコアにマージされます)。
DebugCrash
Debug.crash
が使われている。
DebugLog
Debug.log
が使われている。
DropConcatOfLists
リストを無駄な結合 [1,2,3] ++ [4,5]
は [1,2,3,4,5]
のようにまとめた方が良い。
DropConsOfItemAndList
リストを無駄な結合 1::[2,3,4]
は [1,2,3,4]
のようにまとめた方が良い。
DuplicateImport
同じモジュールを2回インポートしている。
-- BAD
import Html exposing (text)
import Html exposing (Html)
DuplicateImportedVariable
同じ値を2度インポートしている。
-- BAD
import Html exposing (Html, text, Html)
DuplicateRecordFieldUpdate
レコードの同じフィールドを重複して更新している。
-- BAD
{ person | name = "John", name = "Jane" }
ExposeAll
できる限りモジュールが公開するインターフェイスを絞った方が良い。
-- BAD
module Foo exposing (..)
NoUncurriedPrefix
(++) "Hello " "World"
のように中置演算子を無駄に関数として使わず、素直に "Hello " ++ "World"
とした方が良い。
FunctionInLet
let ~ in
中に関数を宣言する必要はあまりないので、トップレベルに置けるなら置いた方が良い。
-- BAD
foo : Int -> Int
foo x =
let
somethingIShouldDefineOnTopLevel : Int -> Int
somethingIShouldDefineOnTopLevel y =
y + 1
in
somethingIShouldDefineOnTopLevel x
ImportAll
ワイルドカードで import すると他の人が読んだときにどのモジュールの関数かわかりにくくなるので、避けた方がいい。
-- BAD
import Html exposing (..)
LineLengthExceeded
一行の文字数が長すぎる(デフォルトの閾値は 150 文字)
MultiLineRecordFormatting
レコードは複数行で宣言した方が読みやすい。
-- BAD
type alias Person =
{ name : String , age : string , address : Address }
-- GOOD
type alias Person =
{ name : String
, age : string
, address : Address
}
NoTopLevelSignature
トップレベルの関数や値には型をつけた方がいい。
-- BAD
foo =
1
NonStaticRegex
動的に正規表現を作ると実行時エラーを起こす可能性があるため、トップレベルに宣言した方がいい。
-- BAD
foo x =
let
myInvalidRegex = Regex.regex "["
in
(myInvalidRegex, x)
RedefineVariable
同じ変数名で外の変数を上書きしない方が混乱が少ない。
-- BAD
foo : Maybe Int -> Int
foo x =
case x of
Just x ->
x
Nothing ->
1
SingleFieldRecord
1つのフィールドしかないレコードは obsolete (廃れた習慣?)だ。(意図が良くわからないが Haskell でそういう書き方をするから?)
-- BAD
type Model =
Model { input : String }
TriggerWords
TODO
や FIXME
のようなコメントを残したままにしない方が良い(単語は設定で変えられる)。
UnformattedFile
elm-format されていない。
UnnecessaryListConcat
不必要に List.concat
している。単に ++
で繋げた方が良い。
-- BAD
foo : List Int
foo =
List.concat [ [ 1, 2 ,3 ], [ a, b, c] ]
UnnecessaryParens
不必要な括弧は取り除いた方が良い。(それでも括弧が好きな人は Lisp をやろうと書いてある)
-- BAD
someCall =
(foo 1) 2
UnnecessaryPortModule
port module
と不必要に宣言されている。
-- BAD
port module Foo exposing (notAPort)
notAPort : Int
notAPort = 1
UnusedImport
インポートされているが使われていないモジュールがある。
-- BAD
import Unused
UnusedImportAlias
import ... as ...
でエイリアスをつけたモジュール名が使われていない。
module Foo exposing (main)
-- BAD( H が使われていない)
import Html as H exposing (Html, text)
main : Html a
main =
text "Hello"
UnusedImportedVariable
module Foo exposing (thing)
-- BAD ( div が使われていない)
import Html exposing (Html, div, text)
main : Html a
main =
text "Hello World!"
UnusedPatternVariable
パターンマッチで束縛した変数が使われていない。
-- BAD ( age が使われていない)
sayHello {name, age} = "Hello " ++ name
UnusedTopLevel
トップレベルの関数が使われていない。
UnusedTypeAlias
type alias を宣言しているが使われていない。
UnusedVariable
変数が使われていない。
-- BAD
foo : String -> Int
foo x =
1
UseConsOverConcat
[ a ] ++ foo
ではなく a :: foo
と書いた方がいい。
チェック項目の設定
異議あり!という項目が多々あったと思うので、プロジェクトのルートディレクトリに elm-anayse.json
を置いてください。true
のものだけがチェックされます。
{
"checks": {
"DebugCrash": false,
"DebugLog": false,
"DropConcatOfLists": false,
"DropConsOfItemAndList": false,
"DuplicateImport": true,
"DuplicateImportedVariable": true,
"ExposeAll": false,
"ImportAll": false,
"LineLengthExceeded": false,
"MultiLineRecordFormatting": false,
"NoTopLevelSignature": false,
"NoUncurriedPrefix": true,
"NonStaticRegex": true,
"RedefineVariable": false,
"SingleFieldRecord": false,
"UnnecessaryListConcat": false,
"UnnecessaryParens": true,
"UnusedImport": true,
"UnusedImportAlias": true,
"UnusedImportedVariable": true,
"UnusedPatternVariable": false,
"UnusedTopLevel": true,
"UnusedTypeAlias": true,
"UnusedVariable": false,
"UseConsOverConcat": false,
"UnformattedFile": true
},
"TriggerWords": {
"words": ["todo", "fixme"]
}
}
レポートをブラウザで表示
--serve
オプションで結果をブラウザで表示します。
elm-analyse --serve
localhost:3000 にアクセスすると、警告の一覧やモジュールの依存関係が表示されます。
問題のコードの位置を教えてくれるのが嬉しかったりします。
まとめ
チーム開発のときにプロジェクトでルールを決めて使うと、自動でチェックできて便利かもしれませんよ!