2024.12.10
“放置系”なのにサイバー攻撃を監視・検知、「統合ログ管理ツール」とは 最先端のログ管理体制を実現する方法
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.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
2024.12.09
10点満点中7点の部下に言うべきこと 部下を育成できない上司の特徴トップ5
2024.12.09
国内の有名ホテルでは、マグロ丼がなんと1杯「24,000円」 「良いものをより安く」を追いすぎた日本にとって値上げが重要な理由
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.12.10
職場であえて「不機嫌」を出したほうがいいタイプ NOと言えない人のための人間関係をラクにするヒント
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.06
嫌いな相手の行動が気になって仕方ない… 臨床心理士が教える、人間関係のストレスを軽くする知恵
PR | 2024.11.26
なぜ電話営業はなくならない?その要因は「属人化」 通話内容をデータ化するZoomのクラウドサービス活用術
2024.12.11
大企業への転職前に感じた、「なんか違うかも」の違和感の正体 「親が喜ぶ」「モテそう」ではない、自分の判断基準を持つカギ
PR | 2024.11.22
「闇雲なAI導入」から脱却せよ Zoom・パーソル・THE GUILD幹部が語る、従業員と顧客体験を高めるAI戦略の要諦