今回はオートコンプリートプラグイン作成方法について簡単に説明します
基本的な部分はRubyMineやAndroid Studioでも変わらないと思います(試してないです)
今回作成するプラグイン
今回はSample::get()
の引数として渡されるクラス名を補完するプラグインを作成します
/**
* 何か処理する
*
* @param string $className クラス名
*/
public static function get($className)
{
// 何か処理
}
試したバージョン
-
IntelliJ IDEA
- 13.1.2 -
PhpStorm
- 8.0.3 -
IntelliJ Platform Plugin SDK
- IDEA IU-135.690
作成方法
プロジェクトの作成
プラグインプロジェクト(IntelliJ Platform Plugin)を新規作成します
今回はSampleStormという名前にしてます
プロジェクトの設定
以下に従いライブラリ(php-openapi.jar、php.jar)とplugin.xmlを編集(ライブラリの依存関係を記入)をしてください
Project Language Level
デフォルトでPhpStormは6.0で起動する為、7.0以降でビルドされたプラグインをインストールするとエラー(Unsupported major.minor version 51.0
みたいなやつ)になります。
自分しか使わない、環境が固定されている等であれば特に6.0にする必要はないと思いますが、不特定多数に使うような場合は6.0にしておく方がよいかもしれません。
META-INF/plugin.xml
プラグインの情報としてid, name, version, vendorを編集します。
ここの情報を編集しないとプラグインは動作しないので注意してください。
<idea-plugin version="2">
<id>com.samplestorm</id>
<name>SampleStorm</name>
<version>1.0</version>
<vendor email="aaa@example.com" url="http://www.example.com">Example</vendor>
SampleCompletionContributorクラス
ドキュメントによるとオートコンプリートを提供するのに一番簡単な方法はCompletion Contributorを利用する事だそうなのでそれを利用します。
CompletionContributorクラスを継承したSampleCompletionContributorクラスを作成します。
package samplestorm.completion.contributor;
import com.intellij.codeInsight.completion.CompletionContributor;
public class SampleCompletionContributor extends CompletionContributor {
public SampleCompletionContributor() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(PsiElement.class), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters completionParameters,
ProcessingContext processingContext,
@NotNull CompletionResultSet completionResultSet) {
completionResultSet.addElement(LookupElementBuilder.create("Hello"));
}
});
}
}
コンストラクタ内でextendメソッドを利用してSampleCompletionContributorクラスが提供するオートコンプリートを設定します
META-INF/plugin.xml
作成したSimpleCompletionContributorクラスを追加します
言語がPHPの場合に実施するようになります
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<completion.contributor language="PHP" implementationClass="samplestorm.completion.contributor.SampleCompletionContributor"/>
</extensions>
これで一旦デバッグを起動するとHelloという文字列に補完が入るようになります
CompletionContributor.extendメソッド
以下の引数を指定する事でオートコンプリートを設定できます
-
CompletionType
- オートコンプリートのタイプを指定します -
ElementPattern
- オートコンプリートする対象を指定します -
CompletionProvider
- オートコンプリートを提供するクラスを指定します
今回作成するプラグインでは2のElementPatternでSample::get()を対象として、3のCompletionProviderでPHPクラス名を提供するように実装します。
オートコンプリートする対象を指定する
上記サンプルでは最低限の指定しかしていないので別にSample::get()以外(aaa:bbb())でも補完がかかります。
これを修正してSample::get()にだけ補完が入るように修正します。
指定するにはPsi Elementの基本知識を必要になります。
PsiElement
PhpStorm(IntelliJ)ではプロジェクト配下のファイルはPSI(Program Structure Interface) Elementによりツリー上で表現されています
例えば、Sample::get("className")のget("className")だけをすごく簡単に書くと以下のような感じなります(感じなので正確じゃないです)
// ツリーはもっとあると
+ Method reference (get)
+ Class reference (Sample)
+ Parameter list
+ String ("className")
+ PsiElement (")
+ PsiElement (className)
+ PsiElement (")
このようなツリー上の場合にのみ補完が入ると指定する事でSample::get()の時だけ補完が入るようになります。
指定ルールはリーフから書くので今回でいうとPsiElement (className)から指定します ※もっと綺麗な指定方法があると思います、力業ですみません!
- 自分の親(
withParent
)はString
- 1の親は
Paramter List
- 2の親は
Method Reference
- 3はクラスメソッド
- メソッド名はget
- 3の親の名前はSample
指定ルール返すsamplePatternというメソッドを作成します
public static PsiElementPattern.Capture samplePattern() {
return PlatformPatterns.psiElement(PsiElement.class)
.withParent(
PlatformPatterns.psiElement(StringLiteralExpression.class)
.withParent(
PlatformPatterns.psiElement(PhpElementTypes.PARAMETER_LIST)
.withParent(
PlatformPatterns.psiElement(PhpElementTypes.METHOD_REFERENCE)
.referencing(
PhpPatterns.psiElement().withElementType(
PhpElementTypes.CLASS_METHOD
).withName(StandardPatterns.string().oneOf("get"))
.withParent(
PhpPatterns.psiElement().withName("Sample")
)
)
)
)
);
}
extend()を修正してsamplePatternを呼び出すようにします
extend(CompletionType.BASIC, samplePattern(), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters completionParameters,
ProcessingContext processingContext,
@NotNull CompletionResultSet completionResultSet) {
completionResultSet.addElement(LookupElementBuilder.create("Hello"));
}
});
デバッグを起動します
これでSample::get()
では補完が入り、aaa::bbb()
では補完が入らないようになります
補完時にPHPクラスを提供する
CompletionProviderを継承したSampleProviderを作成します
public class SampleProvider<CompletionParameters> extends CompletionProvider {
@Override
protected void addCompletions(@NotNull com.intellij.codeInsight.completion.CompletionParameters completionParameters,
ProcessingContext processingContext,
@NotNull CompletionResultSet completionResultSet) {
completionResultSet.addElement(LookupElementBuilder.create("Hello"));
}
extend()を修正してSampleProviderを指定します
extend(CompletionType.BASIC, samplePattern(), new SampleProvider<CompletionParameters>());
デバッグを起動して補完がうまく動くのを確認します
addCompletions()メソッドの引数で渡されるCompletionResultSetにLookupElmentに補完候補を追加するだけで後はいい感じで動作してくれます
Helloを追加している行をコピーすると他の文字列も補完が入るようになるのが確認できると思います
LookupElement
補完が入った時の1行が1LookupElementのイメージです、CompletionResultSetが全体
今回は既に用意されているものを利用しますが、これも継承する事で独自のものを作れます
アイコンやテキスト、装飾(文字色、Boldとか)を設定できるようになります(時間があったらどこかで書きます)
今回はプロジェクト内のPHPクラスが補完されればいいのでプロジェクト内のPHPファイルを取得して追加していくようにします
プロジェクト内のPHPをインデックス化して検索機能を提供しているクラスPhpIndexが提供されているのでこれを利用します、またLookupElementも既に用意されているPhpLookupElementを利用します
@Override
protected void addCompletions(@NotNull com.intellij.codeInsight.completion.CompletionParameters completionParameters,
ProcessingContext processingContext,
@NotNull CompletionResultSet completionResultSet) {
Project project = completionParameters.getPosition().getContainingFile().getProject();
PhpIndex phpIndex = PhpIndex.getInstance(project);
for (String className : phpIndex.getAllClassNames(completionResultSet.getPrefixMatcher())) {
PhpClass phpClass = phpIndex.getClassByName(className);
if (phpClass != null) {
completionResultSet.addElement(new PhpLookupElement(phpClass));
}
}
}
デバッグでPHPクラスが補完されるか確認してみてください
パッケージ化する
プロジェクトを選択して右メニューから以下を選択するとパッケージ(SampleStorm.jar)が作成できます
これをPhpStormのPluginをディスクからインストールしてみると動くはずです
おまけ
PsiViewer
Psi Elementのツリー上を確認すた為に便利なプラグインがPsiViewerがあります
これを利用してSample::get()
のツリーがどのようになっているを確認します
Links
参考にしたサイトです
- IntelliJ IDEA Plugin Development
- PhpStorm Plugin Development
- PhpStorm: Symfony2 Plugin
- IntelliJ IDEAのプラグインを作ろう!
以上