はじめに
Eclipseの万能ナイフ、クイックフィックス(Ctrl+1)に相当する機能が "Show Intention Actions" です。Windows、Linuxは「Alt+Enter」、Macは「option+Enter」にキーが割り当てられています。扱いが特別なのかメニューバーのどこにもありません(「Preferences / Keymap」でも「Other」カテゴリに属してます)。
「Android Studio、これだけ覚えとけば何とかなる3大機能」が第11回で説明した2つのコード補完(BasicとSmart)と、今回紹介する"Show Intention Actions"です。
インテンション&インスペクション
"Show Intention Actions" と言うように、この機能はコードに対する「気づき」を与えます。反応できる場所にはよくある「電球アイコン」が表示されるので、どこで使って良いか悩むことはそうないと思います。
Android Studioの(隠れた?)目玉機能のひとつにコード検査(インスペクション)機能があります。これは平たく言うと、FindBugsとCheckstyleを足して2で割って4096倍したような機能なのですが、これも"Show Intention Actions"の修正候補に出てきます。
インテンションとインスペクションは一見似たような機能なのですが、意味合いは異なり、その設定箇所も違う場所にあります。
- インテンション
-
- コードに対する気づきを指摘する
- 今のままでも問題ないが、より良くできる提案をする
- 提案に対するアクションがあり、実行するとコードを修正する
- 「Preferences / Intentions」で設定
- インスペクション
-
- コードの問題点を指摘する
- 一部の指摘には、インテンションのような解決へのアクションがあるが、基本的に利用者が考えて問題を解決する
- 「Preferences / Inspections」で設定
傾向としては、候補リストの上の方にはインスペクションが並び、続いてインテンションが並びます。
区切り線と項目の左に並ぶアイコンである程度区別ができますが、インスペクションでも電球アイコン()ではなく、ペンアイコン()になる場合もあるので、結局のところは馴れるしかありません。なお、インスペクションの説明はかなりの分量を要するので次回に繰り越します。
インテンション
インテンションは「こういう書き方もできるけどどう?」といった提案を行う機能です。その提案に乗るのであれば、その項目を選択して決定します(Enterキー)。提案に乗るつもりもないし、いちいちうるさいなと思う場合は、リストのサブメニュー(右カーソル(→)キーで表示)にある「Disabled ~」で無効化できます。
インテンションの設定は「Preferences / Intentions」にあり、無効化した項目は、ここから有効化できます。
「Preferences / Intentions」のリストを見るとわかりますが、非常に多くのインテンションが用意されています。インテンションそれぞれには必ず実施前(Before)と実施後(After)の効果が定義されています。インテンションの解説(Description)は英語ですが、この実施前・後のサンプル表示で、だいたいどんなことをするのかイメージできると思います。
「Preferences / Intentions」は「IDE Settings」に属するため、インテンションの設定は、プロジェクトごとに設定するのでは無くAndroid Studio固有の設定となります。以前に説明したカラースキーマやキーマップ、次回に説明するインスペクションなどは、任意の組み合わせをいくつかのまとまりで管理できるのに対して、インテンションは1種類の組み合わせしか持つ事ができません(先ほどの設定画面をみると分かりますが「スキーマ」や「プロファイル」を定義する場所がないです)。
ちなみに、独自のインテンションを作る機能はありません。それをするにはAndroid Studioのプラグインとして作成しなければなりません。
おすすめ(おもしろ)インテンション
インテンションの説明もすべて英語なのですが、それぞれの項目に効果(実行前と実行後のコード例)が示してあるので、使い方に悩むことはないと思います。数もそれほど多くはありませんが、一応すべてのカテゴリの紹介をしておきます。
- Android
- Androidに関するインテンションです。あとで説明しますが、項目は1つしかありません。
- Annotations
- アノテーションに関するインテンションです。通常のJava開発でもあまりお世話になったことはありません。Android開発なら、なおさら用が無いかもしれませんね。
- Boolean
- 論理式に関するインテンションです。論理式をよりシンプルにしたり、if文に変換したりと、ちょっとした気晴らしになります。気分によっては鬱陶しい機能でもあります。
- Comments
- コメントに関するインテンションです。ちょっとだけユニークなものがありますので、あとで紹介します。
- Conditional Operator
- 三項演算子に関するインテンションです。筆者は三項演算子が大好きなので、ここのインテンションにはしばしばお世話になってます。
- Control flow
- 条件文や繰り返しなどの制御構造に関するインテンションです。条件式を反転したり、if文をswitch文に変換したりなど、地味に便利なものが多いです。
- Declaration
- 宣言に関するインテンションです。カテゴリ単体ではもっとも項目が多いです。一部の項目について後で紹介します。
- Groovy
- Groovyに関するインテンションです。さらにサブカテゴリ(Closures, Comments, Control Flow, Declaration, Expression conversions, Groovy-style, Other)を持ちます。ただ、Android StudioのGroovyサポートはGradleのためで、Groovy単独の開発ができるかというと眉唾な感じがします。
- I18N
- 国際化(Internationalization)に関するインテンションです。サポートしているのはJavaの国際化機構です。Android開発の国際化機構でも役に立つのかどうかは疑問が残ります。
- Imports
- import文に関するインテンションです。import文の最適化などについては、コードスタイルを紹介するときに、まとめて説明する予定です。
- JUnit
- JUnitに関するインテンションです。
- Language Injection
- 「Language Injection」に関するインテンションです。詳細については後で説明します。
- Modifiers
- 修飾子に関するインテンションです。
public
をprivate
にしたりしますが、まあ、使いませんね……。
- Numbers
- 数字に関するインテンションです。こちらも後で説明します。
- Other
- 「その他」のインテンションです。「その他」というか「変な」項目が多いです。いくつかは後で紹介しますが、どんなものがあるかは一度目を通しておくと良いです。
- Refactorings
- リファクタリングに関するインテンションです。このカテゴリができたおかげて(リファクタリングメニューを使わず)Eclipseのクイックフィックス風な事ができるようになったのですが、実は2つしか項目はありません。残念な事に一番需要がありそうな「Renameリファクタリング」が含まれていません。
- Shift Operation
- シフト演算子に関するインテンションです。筆者は三項演算子は好きですが、シフト演算子は好きでは無いので、このカテゴリはOFFにしています。というのは冗談ですが、かけ算とシフト演算子を相互変換する機能です。正直、オススメしません。
- Strings
- 文字列に関するインテンションです。
- XML
- XMLに関するインテンションです。
インテンションにあまり面白いものは無いのですが、筆者の独断でいくつか紹介します。『』内はインテンションのリストのカテゴリと項目を表します。
『Android / Extract string resource』
いくら筆者がAndroid開発したことが無いとは言え「Android Studioの紹介記事でAnrdoid系の機能の説明をしないのはマズイなぁ」と思って調べてみましたが、Android系のインテンションは、これ1つしかありませんでした。
要するに文字列を外部リソース化します。図5のように、ソースコード上にハードコードしている文字列を R.java
に置き換えます。
『Comments / Move Comment to Separate Line』
行末にある行コメントを1行上に移動する単純なインテンションです。個人的には、この逆のインテンションもあるとうれしいのですが、そっちは存在しません。
『JUnit / Convert JUnit3 Test Case to JUnit4』
JUnit3形式のテストコードをJUnit4形式に変換します。
IntelliJで普通のJava開発しているときは大変重宝しているのですが、Android開発だと出番がないかも知れませんね。
『Language Injection』
まずは「Language Injection」について説明します。これはJavaなどのソースコード中の文字列や特定のメソッドの引数の値に対して「他の言語」を指定する事ができる機能です。たとえば、
- この文字列はHTMLとして解釈して欲しい
- この引数の値は正規表現として解釈して欲しい
といった指定を行うことで、その対象が指定した言語でシンタックスハイライトを行ったり、その言語の構文チェックやキーワードの補完が有効になります。
数多くの言語をサポートしているIntelliJ IDEA Ultimate Edtionでは、異彩を放つ変態機能なのですが、対応言語が少ないAndroid Studioではどうなんでしょうね。
使い方というか設定方法ですが、何かしらの文字列上で"Show Intention Actions"を実行すると候補リストに「Inject Language」という項目があります。それを実行すると 図7 のような「どの言語と見なすのか?」を指定する候補が出てきます。
この一覧を見る限りだとAndroid Studioで役に立ちそうなLanguage Injectionは「HTML」と「RegExp(正規表現)」くらいでは無いでしょうか? ちなみに「Java」はJava以外のソースコード(HTMLやXMLなど)中の文字列に対して行うと、その部分だけがJava言語として扱われます。
この機能、もともとは1つのリソースに複数の言語が混在しがちなWeb系で効果を発揮するのですが、Android開発では案外用途が無いのかも知れませんね。
「Inject Language」でLanguage Intentionが設定済みになると、その文字列の"Show Intention Actions"に次の2つの項目が追加されます。
「Un-inject Language」は設定したLanguage Injectionを解除します。もう1つの「Edit xxxx Fragment」がユニークで、実行すると対象文字列(フラグメント)のみを抽出したエディタが開き、Language Injectionした言語として編集できます。当然、編集した結果はもとの文字列に反映されます(図10)。
ただこれ、ちょっとした欠点がありまして、フラグメントの編集で改行を入力しても、きちんと元の文字列に反映されるのですが、フラグメントエディタを抜けると、元の文字列のLanguage Injection設定が解除されてしまいます。そのため、再度「Inject Language」で設定する必要があります。
また欲張り過ぎなんですが、StringBuffer.append()
やStringBuilder.append()
に対しては「Edit xxxx Fragment」は有効になりません(項目は登場しますが、期待した結果にならない)。それでもLanguage Injectionは効いているようなので、頑張ってるなぁと感心します。
Language Injectionは、とてもユニークな機能なのですが、Android Studioのサポート言語が少ないため魅力が半減しているのが残念でなりません(SQLやCSS, JavaScriptが使えると俄然威力を発揮します)。
『Declaration / Check RegExp』
Language Injectionで「RegExp(正規表現)」に設定した文字列に対して正規表現が正しいかどうかを試すことができます。実際に動いているものを見た方がわかりやすいでしょう(図15)。
この"Check RegExp"のポップアップはESCキーを押すと消せます。
『Other / Add Clarifying Parentheses』
計算式をわかりやすくするためにカッコを付け加えます。たとえば、図16のようなことをします。
演算子の優先度を知っていれば無用な事なのですが、カッコひとつでわかりやすくなるなら、わかりやすいに越した事は無いですよね。
さらに次のインテンション項目を用いると、定数値を計算して結果を展開します(図17)。
- 『Other / Compute Constant Value』
- 『Other / Compute Constant Value Subexpression』
ちょっとした電卓代わりに使えるので割りと重宝しています。似たようなインテンションに『Numbers / Convert to ~』というのがあります。こちらは数値を16進数や8進数表記に変換するインテンションです(図18)。
『Strings / Copy String Concatenation Text to the Clipboard』
それほど頻繁に使うインテンションではありませんが、図のようなプラス(+)演算子で結合した文字列をひとまとめにしてクリップボードにコピーします。
途中に定数があればそれを展開した値が、変数の場合は「?」に置き換えてコピーされます。残念な事にStringBufiler.append()
やStringBuffer.append()
では使用できません。
コード生成系
これは、おもしろ系というよりネタバレ系ですね。"Show Intentions Action"でテストクラスやサブクラス、ローカル変数を生成できるのは、これらのインテンションのおかげです。
- 『Declaration / Create Test』
- 『Declaration / Implement Abstract Class or Interface』
- 『Refactoring / Introduce local variable』
これらも含めたいろいろなクラスやメソッドの作り方については、この連載の第15回あたりで説明する予定です。
Java7、Java8対応系
通常のJava開発だとココロときめくこれらのインテンションもAndroid Studioでは無用の長物になっています。埋もれさせておくには惜しいので、一応紹介しておきます。
- 『Declaration / Expand lambda expression body to code block』
- 『Declaration / Infer lambda parameter type』
- 型推論で省略したラムダ式のパラメタの型宣言を推測します。
- 『Declaration / Make method default』
- 『Declaration / Remove redundant types』
- ラムダ式から冗長な型宣言を削除します。"Infer lambda parameter type"の真逆のことをします。
- 『Declaration / Replace Diamond with Explicit Type Arguments』
- ダイヤモンド演算子をJava6の型パラメタに戻します。
- 『Declaration / Replace lambda with anonymous class』
- 『Declaration / Replace method reference with lambda』
- 『Declaration / Surround with try-with-resources block』
AutoCloseable
型の変数を try-with-resourcesブロックで囲みます。
Android Studioのプロジェクトは、Project Structureで言語レベルが1.6に設定してあるので、これらの項目が有効になっていても、実際にインテンションとして登場することはありません。
もし、Android StudioからIntelliJに興味を持たれて、通常のJava開発でIntelliJを使うような事があれば、このインテンションのことを思い出してあげてください。
次回の予告
今回説明しきれなかったインスペクションについて説明します。