Android Studio最速入門~効率的にコーディングするための使い方

第14回エディタの[その6]─インスペクション

はじめに

今回は、Android Studioのチップ&デール、インテンション&インスペクションの「インスペクション」について説明します。

インスペクション

いわゆるコード検査なのですが「これがあるからJavaで良いや」と思わせるほど非常に強力な機能です。インテンションと異なり検査することが目的なため、指摘に対して必ず修正候補が出るわけではありません(指摘だけ、というものも結構あります⁠⁠。

インスペクションの設定は「Preferences / Inspections」で行います。インテンションと異なり「Project Settings」に属するため、この設定はプロジェクトごとに変更したり、共有したりすることができます。また、インテンションとは比べものにならないほど検査項目があるので、ある程度のまとまりで検査項目のセットを作っておくことをオススメします。

図1 ⁠Preferences / Inspections」設定画面
図1 「Preferences / Inspections」設定画面

当然のように「どれが検査すべき項目なの?」と行き詰まると思いますが、指摘を受ける都度「これは要る・要らない」と調整していくのが遠回りのようで一番の近道だと思います。

インスペクションの調整は、楽しいことは楽しいのですが、さすがに検査項目が多すぎるため苦痛なのも確かです。しかも、インテンションと異なりコード例もなく、説明文も全部英語なので挫ける要素も満載です。

そこをぐっと乗り越えて、手に馴染んだ検査項目セットができあがると、優秀なナビゲータとペアプロしているような錯覚におちいります(ホントウです⁠⁠。そのあまりの優秀さに「このIDEにはお母さんが入ってる」と言ったIntelliJユーザが居たとか居ないとか。

残念ながらお母さんは居ませんが、小さいおじさんがひっそり潜んでいます。このおじさん、名前をHectorさんと言いまして、常時この人が目を光らせているため、滅多なことではエディタ右上端のインジケーターが緑にならないのです。

図2 Android Studioの右下にいる「Hectorおじさん」
図2 Android Studioの右下にいる「Hectorおじさん」

このHectorおじさんをクリックすると 図3 のようなポップアップが表示され、検査レベル(Highlighting Level)などを設定できます。

図3 検査レベルの変更ポップアップ
図3 検査レベルの変更ポップアップ

この検査レベルなのですが、レベルを下げるにつれHectorおじさんがそっぽを向くという芸の細かさを見せてくれます。

表1 検査レベル(Highlighting Level)とHectorアイコンの関係
Highlighting LevelHector意味
Noneなんのチェックもしません。普通のテキストエディタ並になります。
Syntax文法のチェックだけします。
Inspections文法チェックおよびインスペクションの両方を行います。
Power Save ModePower Save Mode」を有効にした場合。詳しくはコラムを参照してください。

インスペクションの設定

メニューバーの「File → Preferences」からも、ステータスバーに居るHectorおじさんの「Configure Inspections」リンクからも、結局は同じインスペクションの設定画面「Preferences / Inspections」に辿り着きます。ここのプロファイル(Profile)は、カラースキーマやキーマップと異なりプリセットしてある「Default」「Profile Default」の設定内容も変更可能です。

図4 ⁠Preferences / Inspections」設定画面の主な機能ボタン
図4 「Preferences / Inspections」設定画面の主な機能ボタン

「Default」「Project Default」の違いは「Share profile」がONになっているかどうかで、前者は個人向けの設定、後者はプロジェクト共有の設定と理解してください。

より具体的に言うと「Share profile」がOFFのインスペクションの設定は<ANDROID_HOME>/config/inspectionに保存され、ONになっているものは<PROJECT_HOME>/.idea/inspectionProfilesに保存されます。

プロファイルの設定部分のUIもカラースキーマやキーマップとおもむきが異なり、一見すると投げやりっぽい印象を受けるのですが、特に深い意味はなさそうです。

インスペクション項目はひとつひとつ重要度(Severity)を指定でき、モノによっては専用のオプションをもつものもあります。すべてを一読するのは骨が折れる作業ですが、ざっとでも良いので、どんなインスペクション項目があるのか一通り眺めてみることをオススメします。

図5 インスペクション項目ごとに重要度やオプションを指定する
図5 インスペクション項目ごとに重要度やオプションを指定する

すべてのインスペクション項目に共通した設定項目が、重要度の設定です。プリセットで用意されている重要度は以下の6種類です。

表2 重要度の種類と意味
重要度(Severity)意味
Typoスペル間違い(Typo)を指摘します。後述するスペルチェック専用だと思ってください。
Server problemJetBrainsのCIサーバ:TeamCityで指摘された警告です。これを使うことはないと思います。
Weak Warning軽微な警告を指摘するのに用います。
Info情報提供用です。
Warning警告用です。
Errorエラー用です。

プリセットされている重要度のうち「Warinig」「Error」以外はさほど違いはありません。視覚的に注意をひいておきたい項目にそれ相応のレベルを設定すればよいです。通常は「Warning」を設定しておけば良いと思うのですが「警告は鬱陶しいけどOFFにするのも遠慮がある」という項目については「Weak Warning」「Info」に設定しておくとよいです。

一応、デフォルト以外の重要度も追加できるのですが、そこまでするのはやり過ぎかなと思います(筆者もここまで使いこなしていません⁠⁠。

図6 オリジナルの重要度を追加する例
図6 オリジナルの重要度を追加する例

インスペクションもインテンションと同じように候補リストから検査を無効化(Disable inspection)することができます。復活するには「Preferences / Inspections」で該当項目を有効にすればよいのですが、インテンションとは比較ならないほど設定項目が多くあるので、見つけ出せるかどうかが一番の問題になると思います(それを助ける手段も「⁠⁠無効にした項目を)自分が覚えておく」くらいしかありません⁠⁠。

図7 インスペクションの無効化と抑止
図7 インスペクションの無効化と抑止

「Disable inspection」で検査項目自体を無効化する以外に「Suppress ~」を選択すると「そこ」でだけ、その検査を無効化することができます。⁠そこ」の範囲は、どの「Suppress ~」を選んだかによって決まります。

Suppress all inspections for class
「すべての検査」「このクラス」で無効にします。
Suppress for class
「この検査」「このクラス」で無効にします。
Suppress for method
「この検査」「このメソッド」で無効にします。
Suppress for statement
「この検査」「この命令文」で無効にします。
Suppress for statement with comment
「この検査」「この命令文」で無効にします。

実行してみるとわかりますが、それぞれの該当箇所に@SuppressWarningsアノテーションが付与されます(⁠⁠Suppress for statement with comment」は行コメントとして指定します⁠⁠。

図8 ⁠Suppress ~」によるインスペクション項目の抑止の例(クリックすると動きがわかります)
「⁠Suppress ~」によるインスペクション項目の抑止の例` &title=`図8 ⁠Suppress ~」によるインスペクション項目の抑止の例` &width=`400` />

@SuppressWarningsアノテーションはJDK標準のものなのですが、⁠すべての検査を抑止する」場合の@SuppressWarnings("all")ならいざ知らず、個別に検査を抑止する場合はアノテーションの引数に、Android Studioのインスペクション固有の値が設定されるため、あまり気分の良いものではありません。

そんな理由もあって、筆者は「Suppress ~」による検査の抑止はほとんど使った事がありません。

おすすめ(おもしろ)インスペクション

インテンションとは比較ならないほどインスペクションの項目は多岐に渡ります。IntelliJ IDEA 12 Ultimate Edition版ですが、以前に筆者がリストアップしたインスペクションの項目一覧がありますので、参考までにどうぞ(稚拙な日本語訳付きです⁠⁠。

インスペクションの項目には、他の項目とかち合うものもありますので「単にIDEに指摘された」と盲目的にならず、自らの意志で「この項目は必要」⁠この項目は不要」と選別していくことが大事です。実に面倒な作業ですが、そもそもがお節介機能のため、指摘項目を理解した上で使わないと機能の利点を享受するどころか、逆に鬱陶しく目障りな機能になってしまうので通過儀式だと思って辛抱してください。

とはいえ、ただでさえ全部英語でさらに数も多いので、挫けるなというのも無理があります。なので、せめて全てのカテゴリの紹介だけでもしておきます(検査項目のほとんどはJavaに関するものです⁠⁠。

Abstraction issues
抽象化に関する問題を指摘します(クドいのでOFFで良いです⁠⁠。
Android
Androidに関する問題を指摘します。
Android Lint
Android Lintによる警告を指摘します。
Assignment issues
代入に関する問題をしてきます。ほとんど無視して良いですが、ちょっとだけ気になる検査項目があります。
Bitwise operation issues
ビット演算子の問題を指摘します。全部OFFで良いと思います。ビット演算子なんて使いませんよね……。
Class metrics
クラスメトリクスを検査します。残念ながらライン数(LOC)を数える項目はありません。
Class structure
クラス構造に関する問題を指摘します。コーディング規約に応じて、いくつかピックアップするとよいでしょう。
Cloning issues
クローンCloneableに関する問題を指摘します(全てOFFのままで十分だと思います⁠⁠。
Code maturity issues
コードの成熟度に関する問題を指摘します。どうやらデバッグライトを残しているかどうかを検査するようです。
Code style issues
コーディングスタイルに関する問題を指摘します。
Compiler issues
コンパイラに関する問題を指摘します。つまりはjavac相当の指摘をします。
Concurrency annotaion issues
並列処理のアノテーションに関する問題を指摘します。@GuradedByアノテーション等は使ったことが無いので、筆者も実はよくわかっていません。
Control flow issues
制御構文に関する問題を指摘します。
Data flow issues
データフローに関する問題を指摘します。
Declaration redundancy
無駄な宣言をしているかどうかを指摘します。
Dependency issues
依存性に関する問題を指摘します。JDependみたいなものです。
Encapsulation issues
カプセル化に関する問題を指摘します。マジメにやるとキリがないので、全部OFFでも構わないと思います。
Error handling
エラー処理に関する問題を指摘します。
Finalization issues
ファイナライズに関する問題を指摘します。
General
一般的な問題を指摘します。何をもって「一般的」と言っているのかはわかりません……。
Groovy
Groovyに関する問題を指摘します。サブカテゴリにJavaと同じくらいの検査カテゴリが存在します。Android StudioのGroovyサポートがどこまで本気なのかわからないので、しばらくは「Groovyの開発もできる」とは思わないほうが良いと思います。
HTML
HTMLに関する問題を指摘します。
Imports
インポート文に関する問題を指摘します。
Inheritance issues
継承に関する問題です。これもマジメに検査すると疲れる系ですので、ほどほどにしましょう。
Initialization issues
初期化に関する問題を指摘します。
IntelliJ IDEA Platform Inspections
これはIntelliJのプラグインに関する問題を指摘するカテゴリです。Android Studioではプラグイン開発はできないので、このカテゴリ自体が無意味です。
Internationalization issues
国際化(i18n)に関する問題を指摘します。
J2ME issues
J2MEに関する問題を指摘します。これもIntelliJから単純に持ってきた検査項目で、Android Studioでは全くの無意味です。
Java language level issues
Javaの言語レベルに関する問題を指摘します。平たく言うと「Java5以降の構文を使っているかをチェックする」カテゴリです。今となっては古くさい検査なので、すべてOFFで問題ありません。
Java language level migration aids
Java言語のマイグレーション支援を行います。
JavaBeans issues
JavaBeans規約に関する問題を指摘します。
Javadoc issues
Javadocに関する問題を指摘します。
JUnit isseus
JUnitに関する問題を指摘します。JUnit3かJUnit4かによっても検査項目が若干異なります。
Language Injection
Android Studioの「Language Injection機能」に関する問題を指摘します。
Logging issues
ログ出力に関する問題を指摘します。
Maven
Mavenに関する問題を指摘します。Android StudioでMavenはサポートしてるとは言い難いので、これも無視して良い検査項目でしょう。
Memory issues
メモリ管理に関する問題を指摘します。
Method metrics
メソッドのメトリクスを指摘します。クラスメトリクス同様、ライン数を検査する項目はありません。
Modularization issues
モジュール化に関する問題を指摘します。
Naming conventions
命名規則を守っているかどうかを指摘します。
Numeric issues
数値に関する問題を指摘します。
Packaging issues
パッケージングに関する問題を指摘します。
Pattern Validation
先ほどの"Language Injection"同様、Android Studioの「Language Injection機能」に関する問題を指摘します。
Performance issues
パフォーマンスに関する問題を指摘します。
Portability issues
移植性に関する問題を指摘します。
Probable bugs
ありがちなバグを指摘します。
Properties Files
プロパティファイルに関する問題を指摘します。果たしてAndroid開発でJavaのプロパティファイルを使うことがあるんでしょうか?
RELAX NG
RELAX NGに関する問題を指摘します。
Resource management issues
リソース管理に関する問題を指摘します。
Security issues
セキュリティに関する問題を指摘します。
Serialization issues
シリアライズSerializableに関する問題を指摘します。これもマジメにチェックすると骨が折れます。
Spelling
スペルチェックを行います。
Threading issues
スレッドに関する問題を指摘します。
toString() issues
toString()メソッドに関する問題を指摘します。
Verbose or redundant code constructs
冗長かつ無駄なコードを指摘します。
Visibility issues
可視性に関する問題を指摘します。
XML
XMLに関する問題を指摘します。

インスペクションはおもしろい項目が多いのですが、全部紹介するのは骨が折れるので、筆者の独断と偏見でごくごく一部のみをピックアップして紹介します。⁠』内はインスペクションのカテゴリと項目を表します。

スペルチェック

  • Spelling / Typo

すでにAndroid Studioを使い始めている人は、ソースコードに対してスペルチェックを実施していることに気付いているかと思います。その正体がこのインスペクション項目になります。

図12 スペルチェックの指摘例
図12 スペルチェックの指摘例

「スペルチェックはうれしいけれど、正直疎ましい」と思っている人は、この項目をOFFにするか、検査対象を絞り込んでみて下さい。設定画面の「Options」でスペルチェックの範囲を以下の3つを組み合わせて指定できます。

  • 「Process code」… ソースコードを対象
  • 「Process literals」…文字リテラルを対象
  • 「Process comments」…コメントを対象
図13 スペルチェックの範囲の指定の例
図13 スペルチェックの範囲の指定の例

また、スペルチェックの指摘で「Typo: Save 'xxxx' to dictionary」を選択すると、その単語を新たに辞書登録することができます図14⁠。

図14 スペルチェックの指摘から新しい単語を辞書に登録できる
図14 スペルチェックの指摘から新しい単語を辞書に登録できる

登録した単語は「Preferences / Spelling」「Accepted Words」で確認でき、実体は <PROJECT_HOME>/.idea/dictionaries に保存されます図15⁠。

図15 ユーザ定義辞書の保存先
図15 ユーザ定義辞書の保存先

serialVersionUIDの追加

  • Serialization issues / Serializable class without 'serialVersionUID'

Serializableインターフェイスを実装したクラスに対して serialVersionUID を追加します。次回説明する予定のメニューバー「Code → Generate」にあっても良さそうなのですが、serialVersionUIDの生成はインスペクションに含まれています。意外に忘れがちで、知らず知らずのうちに検査項目を無効化して、どこで再設定したら良いのか分からなく機能の筆頭みたいなものです。

あと、このインスペクション項目はクラス名部分で反応します。ここ以外では反応しませんので、この事も心の片隅に留めておいてください図16⁠。

図16 serialVersionUIDの生成
図16 serialVersionUIDの生成

疑わしい名前

  • Naming conventions / Questionable name

foo, bar, booのように意味の無い適当な名前を使っているかどうかを指摘します。この機能をもってして「このIDEにはお母さんが入っている」と言わしめた機能です。

図17 ⁠疑わしい名前」の指摘例
図17 「疑わしい名前」の指摘例

お母さんが入っているは大げさとして、このインスペクション項目の「Options」に検査対象となる語句が定義してあり、これをもって命名規則に感心のないコードをあぶり出します。日本で使う場合はhogeなども追加しておく必要がありますね図18⁠。

図18 ⁠疑わしい名前」の設定画面
図18 「疑わしい名前」の設定画面

Java言語のマイグレーション支援

これはJava language level migration aidsのすべてのインスペクション項目が対象となります。既存のコードをJava7やJava8に書き換えるための支援を行います。IntelliJを使っていると、とても役に立つ機能なのですが、Android開発の場合、インテンションのJava7、Java8対応系と同じく無用の長物だと思います。

ただインテンションと異なり、Java5やJava6対応のものもあるので、いくつかは有効にしておいたほうが良いかと思います。一応、全部紹介しておきます。

Anonymous type can be replaced with lambda
匿名クラスをラムダ式に置き換えます(Java8用⁠⁠。
Anonymous type can be replaced with method reference
匿名クラスをメソッドリファレンス(method references)に置き換えます(Java8用⁠⁠。
Collections.EMPTY_* field access replaceable with 'Collections.empty*()' method call
Collections.EMPTY_*Collections.empty*() に置き換える(Java5以降⁠⁠。
Enumeration can be iteration
Enumration を Iterator に置き換えます(Java2以降⁠⁠。
Explicit type can be replaced with <>
型パラメータをダイヤモンド演算子<>に置き換えます(Java7以降⁠⁠。
'for' loop replaceable with 'for each'
forループを拡張forループ(for each)に置き換えます(Java5以降⁠⁠。
Identical 'catch' branches in 'try' statement
try-catchをマルチキャッチに置き換えます(Java7以降⁠⁠。
'if' replaceable with 'switch'
if文をswitch文に置き換えます(Java7以降⁠⁠。
'indexOf()' expression is replaceable with 'contains()'
String.indexOf()String.contains() に置き換えます(Java5以降⁠⁠。
Lambda can be replaced with method reference
ラムダ式をメソッドリファレンスに置き換えます(Java8用⁠⁠。
Method can be variable arity method
メソッド引数を可変引数に置き換えます(Java5以降⁠⁠。
Possible heap pollution from parameterized vararg type
@SafeVarargsアノテーションできる可変引数を報告します(Java7以降⁠⁠。
Raw use of parameterized class
型パラメータを使えるのに使ってないのを報告します(Java5以降⁠⁠。
'StringBuffer' may be 'StringBuilder'
StringBefferStringBuilder に置き換えます(Java5以降⁠⁠。
'try finally' replaceable with 'try' with resources
try-finaly を try-with-resource に置き換えます(Java7以降⁠⁠。
Unnecessary boxing
無駄なボクシングを指摘します(Java5以降⁠⁠。
Unnecessary unboxing
無駄なアンボクシングを指摘します(Java5以降⁠⁠。
Usages of API documented as @since 1.5 (1.6|1.7)
Java5, 6, 7 で追加されたAPIを使っているかを報告します(Java1.4以下⁠⁠。
'while' loop replaceable with 'for each'
whileループを拡張forループ(for each)に置き換えます(Java5以降⁠⁠。

個人的には『Usages of API documented as @since 1.5 (1.6|1.7)』に大変お世話になっているのですが、まさかAndroid開発でJava1.4とかのレガシーコードを扱う事なんて無いですよね……。

Android / Android Lint

本来なら一番最初に紹介すべきAndroidに関するインスペクション項目です。数えてみたらAndroidは4項目、Android Lintは132項目ありました。どの項目にも固有の設定項目はありませんでした。

Android Lintはその名前からして、Android SDKのlintを指しているのだと思います。すべてを突き合わせしたわけではありませんが、確かに検査項目がAndroid SDKのそれと一致しています。

Javadocに関する問題

これは面白いというより、第12回でインスペクションの時に説明すると宣言したので、それに応えただけです。⁠Javdoc issues』カテゴリにはいくつかの検査項目がありますが「不完全なJavadocを検査する」目的には、

  • Javadoc issues / Declaration has Javadoc problems

を使います。おそらく、この検査項目、1,000以上あるインスペクションの検査項目の中で1、2を争うほど複雑な「Options」を持ちます図19

図19 ⁠Declaration has Javadoc problems」の設定画面
図19 「Declaration has Javadoc problems」の設定画面

Javadocの自動生成はできませんが、この設定を駆使することで不完全なJavadocを洗い出すことができます。相当細かい設定ができますが、筆者は面倒なのでデフォルトのまま使っています。

まとめと次回の予告

Android Studioの元になったIntelliJの目玉機能とも言えるのがこのインテンション&インスペクションです。正直、インスペクションは数が多すぎて辟易しますが、うまいこと使いこなすと、いろいろ親切に教えてくれる優秀なコーチになります。筆者は何度もHectorおじさんの指摘に助けられているので頭が上がりません。取っつきづらい機能でもありますが、使っていく内にコツがわかると思いますので気長につきあってあげてください。

次回はエディタの基本操作として、細かすぎて伝わりづらい便利な機能を紹介します。

おすすめ記事

記事・ニュース一覧