AssertJ 用の IntelliJ postfix completion plugin を書いた
AssertJ の assertThat() をpostfix completion で入力したいと常々思っていて、誰か書いてくれないかなと思っていたけど誰も書いてくれないし、IntelliJ のプラグインというものを書いてみたかったので書いてみた。
https://github.com/tokuhirom/assertj-postfix-plugin
↑レポジトリはこちら。
IntelliJ のプラグインの情報は少なくて、どうもどこが本家なのかよくわからなかった。 http://www.jetbrains.org/intellij/sdk/docs/index.html たぶんこの辺。だと思う。
とりあえず検索してみたところ IntelliJ IDEAのPostfix補完プラグインを作るという記事が見つかったので、「こりゃあ、真似すれば簡単に実装できそうだなー」と思ったのが運の尽き。
どーも、ここに書いてある情報だけでは実装は無理っぽい。。 なんか実行時例外出るし。。そもそも俺 intellij plugin の書き方が全くわかってないし。。
で、いろいろ調べてみたところ、IntelliJ のプラグインは gradle つかって開発するのが楽っぽい。
gradle-intellij-plugin ってので、簡単にビルドできる。./gradlew runIdea
ってすると、gradle が intellij idea のコミュニティエディションをダウンロードしてきてそれを実行してくれる。
https://github.com/JetBrains/gradle-intellij-plugin
build.gradle は以下の様な感じ。
plugins {
id "org.jetbrains.intellij" version "0.0.32"
}
apply plugin: 'org.jetbrains.intellij'
apply plugin: 'java'
sourceCompatibility = 1.8
intellij {
pluginName 'AssertJ Postfix Plugin'
}
group 'me.geso.assertj_postfix_plugin'
version '0.0.1'
task wrapper(type: Wrapper) {
gradleVersion = '2.6'
}
repositories {
mavenCentral()
}
ディレクトリ構成は以下のようになっている。
src
└── main
├── java
│ └── me
│ └── geso
│ └── assertj_postfix_plugin
│ ├── AssertJPostfixTemplateProvider.java
│ └── AssertJTemplate.java
└── resources
├── META-INF
│ └── plugin.xml
└── postfixTemplates
└── AssertJTemplate
├── after.java.template
├── before.java.template
└── description.html
src/main/resources/postfixTemplates/ 以下にテンプレートのデータが入っている。これは実際になにかの役に立つわけではないが、入れておかないと例外があがって死ぬ。各テンプレートごとに after.java.template, before.java.template, description.html の3つのファイルが必要だ。
これらのテンプレートは、以下のような場所に表示される。表示されるだけなので、動作には関係ない。
META-INF/plugin.xml がプラグインのメタデータ。プラグインのIDやらなんやらの基本的な設定がここに書いてある。
codeInsight.template.postfixTemplateProvider のあたりが重要で、テンプレートプロバイダを設定している。あとは他のプラグインでも一緒。
<idea-plugin version="2">
<id>me.geso.assertj_postfix_plugin</id>
<name>AssertJ Postfix Completion Plugin</name>
<version>0.0.1</version>
<vendor email="tokuhirom+intellij@gmail.com" url="http://64p.org">tokuhirom</vendor>
<description><![CDATA[
This plugin adds postfix completion template for assertj.
]]></description>
<change-notes><![CDATA[
<ul>
<li>0.0.1 - The first release.
</ul>
]]>
</change-notes>
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
<idea-version since-build="141.0"/>
<extensions defaultExtensionNs="com.intellij">
<codeInsight.template.postfixTemplateProvider language="JAVA"
implementationClass="me.geso.assertj_postfix_plugin.AssertJPostfixTemplateProvider"/>
</extensions>
<actions>
</actions>
</idea-plugin>
で、テンプレートの入り口は以下のとおり。テンプレートのセットを作って返しているだけ。
package me.geso.assertj_postfix_plugin;
import java.util.HashSet;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import com.intellij.codeInsight.template.postfix.templates.JavaPostfixTemplateProvider;
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
public class AssertJPostfixTemplateProvider extends JavaPostfixTemplateProvider {
private final HashSet<PostfixTemplate> templates;
public AssertJPostfixTemplateProvider() {
templates = new HashSet<>();
templates.add(new AssertJTemplate());
}
@NotNull
@Override
public Set<PostfixTemplate> getTemplates() {
return templates;
}
}
テンプレートの実装、以下の様な感じになる。StringBasedPostfixTemplate ってやつを継承することにより、なんかそれっぽいテンプレートを書くだけでよいという感じになっている。
package me.geso.assertj_postfix_plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.Template.Property;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInsight.template.postfix.templates.StringBasedPostfixTemplate;
import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils;
import com.intellij.psi.PsiElement;
public class AssertJTemplate extends StringBasedPostfixTemplate {
public AssertJTemplate() {
super("assertThat", "assertThat(expr);",
JavaPostfixTemplatesUtils.selectorAllExpressionsWithCurrentOffset(JavaPostfixTemplatesUtils.IS_NON_VOID));
}
@Override
public Template createTemplate(TemplateManager templateManager, String s) {
Template template = super.createTemplate(templateManager, s);
template.setValue(Property.USE_STATIC_IMPORT_IF_POSSIBLE, true);
return template;
}
@Nullable
@Override
public String getTemplateString(@NotNull PsiElement psiElement) {
return "org.assertj.core.api.Assertions.assertThat($expr$);$END$";
}
}
デバッガで実行すれば、プラグインが読み込まれた状態の IDEA が起動するので、動作を確認すればOK。普通の java アプリと同様に、デバッガでステップ実行とかもできる。便利。
出来上がったら、 https://plugins.jetbrains.com/ で publish すれば OK.
./gradlew publishPlugin
やらでアップロードできるが、とりあえずは普通に ./gradlew buildPlugin
して、form からアップロードした。plugin.xml が含まれてないと言われてアップロード失敗したので、./gradlew jar
した jar をアップした。二回目からは publishPlugin でやれる。と思う。
そういうわけで、アップしてみてある。ご利用ください。と言いたいところだけど、まだ承認待なのでした。 https://plugins.jetbrains.com/plugin/8093?pr=
Published: 2015-12-19(Sat) 10:14