2024.10.10
将来は卵1パックの価格が2倍に? 多くの日本人が知らない世界の新潮流、「動物福祉」とは
kotlinでもJavaでも検出できるCustom Lintの作り方(全1記事)
リンクをコピー
記事をブックマーク
釘宮慎之介氏:はい、よろしくお願いします。「kotlinでもJavaでも検出できるCustom Lintの作り方」というタイトルで発表します。自己紹介なんですが、釘宮と申します。Androidエンジニアで、DMM.comというところで働いています。
さっそくアジェンダですが「kotlinを使ったAndroidプロジェクトでlintをかける時にどうしたらいいんだっけ?」という話と、「Custom Lintを作るにはどうしたらいいんだっけ?」という話をします。その後に、「じゃあ実際にandroidのlintでCustom Lintを作ってみましょう。」「(作ったandroid-lintのCustom Lintを)テストしてみましょう。使ってみましょう」という流れで話していきます。
kotlinを使ったAndroidプロジェクトでlintをかけるには、以前までは主に2つの方法しかありませんでした。それが「Ktlint」と「detekt」という方法です。
android-gralde-plugin 3.1.0ぐらいから、androidのlintでもkotlinのlintをかけることができるようになりました。android-lintのいいところは、公式が作っているという点、標準のlintのタスクでちゃんとlintしてくれるという点です。あと、後述するんですけど、Custom Lintを作る際に、型情報を使ったlintとかも作れるという点と、加えてkotlinだけじゃなくて、Javaもそのままlintのチェックをかけることができるという点があります。
(Ktlint、detekt、android-lintには)それぞれいいところがあります。所感でいうと、Ktlintとdetektはそんなに大差はなく、どっちかというとStyle寄りで、インデントのサイズとかそこらへんを見てくれるのかなというところがあります。
ただ、Ktlintはルールの一部無視ができないというか、やればできるんですけど、けっこう難しかったりします。なので、僕自身はKtlintを使ってるんですけど、もしかしたらdetektのほうが使いやすいかもしれないです。
androidのlintに関しては、Styleもロジックも確認はできるんですけど、標準のlintのタスクでインデントのサイズとかを見てくれないようなので、そこがちょっと弱いのかなと思っています。
どれを使えばいいのかっていう主観なんですけど、androidのlintを外すことはできないので、Styleとかを見たいのであれば、androidのlintに加えてKtlintやdetektを併用するのがいいのかなと考えています。
Custom Lintの作り方なんですけど、これはKtlint、detekt、androidのlintの場合も一緒で、まずはASTを知らなければ作れません。(スライドを指して)このように、コードはツリーの構造で、コンパイラやIDEとかを解釈します。
例えば、「引数が複数あったら絶対改行してね」みたいなCustom Lintを作りたいとします。上がNGで、下がOKの場合、こういうlintを作りたいっていう時です。
NGの時もOKの時も、PSI、ASTのツリーはこのようになります。
(一部省略しているのでスライド上では)一番上に、ARGUMENTのLISTというノードがあり、その下にARGUMENTである1、カンマ、スペース、2があるというツリーになります。
さっきのOKの時、つまりちゃんと改行されてる時は、この3つ目のスペース、WHITE SPACEに改行コードが含まれていて。
NGの時には改行コードが含まれてません。
なので、Custom Lintを作りたい時は、こういうことを確認します。このようにツリーの構造になっていて、加えて3つ目のWHITE SPACEのところには改行コードがちゃんと含まれてるかという確認をして、逆に入ってない時はNGを出すというようにやります。
それで、「なんとなくわかったけど、まぁツリーがどうなってるかわかんないっすよね」と思うと思いますが、大丈夫です。僕もわかんないんです(笑)。これに関しては、「PsiViewer」というプラグインが用意されています。どういうものかというと、左側にコードを表示して、右側にツリー構造がどうなってるのかを表示してくれるプラグインなので、これを使ってにらめっこしながら作るといいんじゃないかなと思います。
次に、androidのlintでCustom Lintを作ってみます。例えば、RxJavaを使っているとして、Disposableを適切に処理してないでそのままにしている場合は警告を出すというCustom Lintを作ります。
手順は5つです。まずプロジェクトを作る。次にDetectorを作って、Issueを作って、Registryを作る。最後にこのRegistryを登録するという手順です。
プロジェクトを作るところについては、いつも通り作ればいいんですが、「googlesamples」というgithubがあって、そこにテンプレートみたいなものがあるので、それを持ってくるとか、ならうのがいいと思います。
Detectorを作るところについては、(スライドを指して)完成形がこんなコードになります。
まず、Detectorというものをextendして、UastScannerというものをimplementします。Uastというのは、Unified ASTの略です。
その次に、createUastHandlerというものをオーバーライドします。つまり実際は何をやるかというと、UIElementHandlerというものを実装することになります。
このUIElementHandlerは、ツリーの上から順にスキャンしていってくれて、その各種ノードが見つかった時に、各種のvisitメソッドを呼びます。このvisitメソッドをオーバーライドして使うようになります。
今回はPsiViewerを見ると、DOT_QUALIFIED_EXPRESSIONというものが来た時に確認するだけで済みそうなので、それに対応するvisitメソッドをオーバーライドするようにします。
visit対象のノードクラスで、さっきのDOT_QUALIFIED_EXPRESSIONというもののクラス情報を、上のgetApplicableUastTypesというところに返してあげるようにします。これはお約束になっていて、これをしないとvisitメソッドをオーバーライドしても呼ばれないということがあるのでやります。
実際のvisitメソッドの中身は、こうなっています。
これ、ソースって見れますかね? 大丈夫かな。この中身は何かというと、親がBLOCKになっている時にメソッドチェーンの最後がsubscribeというものになっています。そのsubscribeのメソッドの返り値がDisposableになっている時にレポートする、となっています。
1つ(話を)戻すと、このDisposableの型が返ってくる情報がKtlintやdetektだと取れなくて、androidのlintでできる点がメリットだと思っています。
加えて、kotlinの場合以外に、Javaの場合も書くようにします。UastScannerはkotlinとJavaと区別なくvisitしてくれるんですけど、kotlinとJavaの時でPSIの型が違うので、別途こちらもPsiViewerとにらめっこしながら作ることになります。
Detectorができたら、Issueというものを作っていきます。このIssueの中には、ID情報や説明とかが入っています。
その後に、作ったIssueをRegistryというところに登録して。
このRegistryをbuild.gradleに記述すればCustom Lintは完成です。
作ったCustom Lintをテストしていきます。テストメソッドの書き方はこのようになっています。
対象のコードを文字列で用意します。これは長くなることが多いので、ファイル読み込みにするのがいいと思います。用意したら、それをkotlinファイルとして渡す、つまりkotlinメソッドを呼んで文字列を渡します。そして、lintにかけたらエラー文言が出てくるので、適切なエラー文言になっているかをexpectメソッドで確認します。Javaの時はこの2箇所をJavaに変えればOKです。
作ったCustom Lintの使い方です。これは簡単で、同一プロジェクトにCustom Lintのモジュールがある場合は、dependenciesにlintChecks projectのモジュール名を入れればOKです。他のプロジェクトとかでも同じCustom Lintを使いたい時には、JARにしてあげて、そのJARのパスをlintChecksで渡してあげればOKです。ここまでできれば無事動くことが確認できました。
まとめです。kotlinでlintをかける方法は3つあるっていうことを説明しました。kotlinでもdetektでもandroid-lintの場合でも、Custom Lintを作る際はASTを知らなければいけませんということを説明しました。最後にCustom Lintの作り方を説明しました。ご静聴ありがとうございました。
(会場拍手)
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.12
自分の人生にプラスに働く「イライラ」は才能 自分の強みや才能につながる“良いイライラ”を見分けるポイント
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.11
気づいたら借金、倒産して身ぐるみを剥がされる経営者 起業に「立派な動機」を求められる恐ろしさ
2024.11.11
「退職代行」を使われた管理職の本音と葛藤 メディアで話題、利用者が右肩上がり…企業が置かれている現状とは
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.12
先週まで元気だったのに、突然辞める「びっくり退職」 退職代行サービスの影響も?上司と部下の“すれ違い”が起きる原因
2024.11.14
よってたかってハイリスクのビジネスモデルに仕立て上げるステークホルダー 「社会的理由」が求められる時代の起業戦略