フューチャー2アドベントカレンダー4日目です。
3日目は@tutuzさんのTransit Gatewayを導入するときに気をつけたいポイント4選、5日目は@KhdbbleさんのEbitenでImage操作 ~キャラクターを動かす~です。
typoとは
各単語に対してのスペルミスやタイプミスのことで、語源は「typographical error(タイポグラフィカル エラー)」だそうです。QiitaとQitaと書いちゃうとか、人によってはAWSのLambdaをlambdaと書くとダメだよねといった大文字小文字の表現についてもtypoに含める人がいると感じます。
Spell Checkerについて
人間である以上はミスタイピング・ミススペルが絶対発生しますよね。どんなに気をつけたとしても一定の割合で出てしまうと思います。
自分1人のプロジェクトであればよいですが、レビュアーや他のメンバーがコードを読むとときにtypoに気がついて指摘したり直したりすると大変なので、古来からスペルチェッカ というツールが作られたりしました。
VSCodeであれば、Code Spell Checker を導入すると便利そうです。存在しないと思われる単語を入力すると、リアルタイムで検証してくれるため人間とツールのダブルチェックでミスが減らせそうです。
JetBrainのSpell Checker
私はGolandやIntelliJなどJetBrain製のIDEを利用することが多いです。JetBrain製のIDEは(おそらく標準で)スペルチェックが機能として持っていて、他のエディタで書かれたコードを落としてくると、けっこうな割合でtypoに気がついて便利だなって思うことが多いです。
機能としては次のリンクの感じで、デフォルトのバンドルされた辞書での検証もできますし、波線になった単語をシームレスに追加登録して、以後検証されなくなることもでき重宝します。
https://pleiades.io/help/go/spellchecking.html
もっと気軽にJetBrainのtypoチェックを使いたい
個人的にはお値段以上の価値がありますがGolandは有償ですし、VSCodeファンなメンバーも多いため全員にJetBrain製のIDEを入れてもらうのは難しそうです。
また、自分がコードレビュー時にいちいちGolandなどのIDEにPJをImportするのも面倒なので、気軽にCLIでチェックできたらなと思っていました。IntelliJやGolandなど(おそらく他のプロダクトも)は、コマンドラインからのIntelliJ IDEA機能の操作 にあるように、 Windowsであれば C:\Program Files\JetBrains\GoLand 2019.3\bin
などにPathを通すと bat コマンド経由でGolandの機能が叩けます。もちろんMacでも可能です。
Spell Checker(typoチェック)には コマンドラインからのコードインスペクションの起動
を利用します。
インスペクションとは、コードなどの妥当性を検証する意味です。Golandであればtypoチェック以外にも、どこからも呼び出されていない関数が無いかチェックなど様々なチェックも同時に行っています。
インスペクションコマンドの起動
本家のドキュメントに詳細が書いていますが、以下のようなコマンドです。
inspect project-path inspection-path output-path [-vX] [-d subdirectory-path]
project-path
はチェックしたいフォルダです。カレントディレクトリ以外は絶対パスを指定する必要があります。 inspection-path
は見慣れないですが JetBrain製IDEユーザであれば .idea/inspectionProfiles
がデフォルトで作成されますが、それと同様のファイルの出力場所を指定します。output-pathは検証結果で、全てXMLで出力されます。
実際にとある開発中の小さなWebAPIのプロジェクトをインスペクトしてみます。
cd %GOPATH%/src/github.com/<Your Orgzanition>/<Your Project>
inspect ./ .idea/inspectionProfiles ./output
すると、いくつかのXMLの結果ファイルが出力されます。
Annotator.xml
BashUnresolvedVariable.xml
GoBinaryAndUnaryExpressionTypesCompatibility.xml
GoDuplicateCase.xml
GoExportedFuncWithUnexportedType.xml
GoInvalidCompositeLiteral.xml
GoRedundantImportAlias.xml
GoTypesCompatibility.xml
GoUnresolvedReference.xml
GoUnusedConst.xml
GoUnusedExportedFunction.xml
GoUnusedParameter.xml
JsonStandardCompliance.xml
SpellCheckingInspection.xml
このうち、今回利用したいのは SpellCheckingInspection.xml
です。名前がそのままでわかりやすいですね。
結果をいくつか抜粋してみると、、
<problem>
<file>file://$USER_HOME$/Go/src/github.com/Your-Organization/Your-Project/handler/my_handler.go</file>
<line>39</line>
<module>Your-Project</module>
<entry_point TYPE="file" FQNAME="file://$USER_HOME$/Go/src/github.com/Your-Organization/Your-Project/handler/my_handler.go" />
<problem_class severity="TYPO" attribute_key="TYPO">Typo</problem_class>
<description>Typo: In word 'errror'</description>
<highlighted_element>errror</highlighted_element>
<offset>44</offset>
<length>6</length>
</problem>
<problem>
<file>file://$USER_HOME$/Go/src/github.com/Your-Organization/Your-Project/docs/my_datamodel.md</file>
<line>7</line>
<module>Your-Project</module>
<entry_point TYPE="file" FQNAME="file://$USER_HOME$/Go/src/github.com/Your-Organization/Your-Project/docs/my_datamodel.md" />
<problem_class severity="TYPO" attribute_key="TYPO">Typo</problem_class>
<description>Typo: In word 'Surces'</description>
<highlighted_element>Surces</highlighted_element>
<offset>56</offset>
<length>6</length>
</problem>
などがツラツラ出力されています。
1つ目は、おそらく error
と書くべきところが errror
とtypoしています。errrorがerrorだよとか思いますね。なんだか目が痛くなりますね。
2つ目は、コードではなくMarkdownですが、単語だけだとわけが分からなかったので元のファイルを見て文脈から察すると、Sources
と書きたかったのが Surces
とtypoしたようです。
このようにして、CLI経由でtypoを検出することができました。
単語を辞書に登録する
このままでも一応はtypoチェックとして機能はしますが、実際の開発フローに組み込むには乗り越えるまだまだ工夫が必要です。
今回でいうと、Surces
といった単語が今回の業務ドメインで用いる場合、typoとして検知したくないでしょう。その場合は辞書登録すれば検知対象外となります。
辞書登録の方法は、 inspection-path
直下に dictionaries
というフォルダを置き、そこに単語登録用のXMLを配備します。今回は dictionaries/cli.xml
というファイル名にしました。
<component name="ProjectDictionaryState">
<dictionary name="cli">
<words>
<w>Surces</w>
</words>
</dictionary>
</component>
辞書ファイルを配備し、もう一度 inspect ./ .idea/inspectionProfiles ./output
コマンドを叩きます。そうすると、Surces
は無視されるようになります。
$ grep Surces SpellCheckingInspection.xml | wc -l
0
単語リストメンテナンスの運用フローは検討する必要がありそうですが、最低限の回避はできそうです。
対象からgo.sumを除外する
PJルートを指定すると、go.sumなどチェックしなくても良いファイルが大量にtypoチェックで検知されます。typoというよりはGitHubのユーザIDだったりするのですが、存在しない単語なので大量に検知されます。
-d subdirectory-path
で検査対象のディレクトリを指定することはできても、スキップ指定するオプションは存在しないようです。そのため、-dで個別に検査対象のディレクトリを指定するか、出力されたファイルに対して自前で除外する必要があります。個別にディレクトリ指定はさすがに大変なのと実行時間がかさむので、出力ファイルからあるディレクトリやファイルの結果を無視する方が筋が良さそうです。
inspectコマンドはドキュメントには記載されていませんが、--format json
でJSONレイアウトで出力もできます。
inspect . .idea/inspectionProfiles ./output -format json
出力された SpellCheckingInspection.json
に対して、 jq
で指定された拡張子(今回だと.goと.md)だけに絞り込みます。 jq*の
select` 機能についてはこちら の記事が参考になりました。
cat SpellCheckingInspection.json | jq -r '.problems[] | select(.file | test("(.*.go$|.*.md$)"))'
これでgo.sumなど気にしなくても良いファイルを除外することができました。
いくつか繋ぎ込みが必要そうですが、GitHub ActionなどCI組み込みも見えてくると思います。その場合はライセンスが問題になってくるので、同時に複数のマシンで起動しないようにするか、専用のライセンスを購入するかなどよく確認しましょう。
まとめ
- typoはSpell Checkツールでなるべくツール側で検知させると幸せになれる
- JetBrain製のSpell CheckerはCLIからも利用できる
- 辞書登録も可能で簡単に使えるが、対象ファイルの指定はひと手間必要