仕事で困ったのでIntelliJのプラグインを作る
はじめに
Javaを書いている時に、こんなクラスのインスタンスを生成する必要があるテストを書くことがあった。
@Value
public class Sample {
private final Integer a;
private final String b;
private final SomeClass c;
}
SomeClass
の中にはまたいくつかのオブジェクトが入れ子になっており、このクラスのインスタンスを作るだけでなかなか疲弊してしまう。加えてそれぞれのフィールドに初期値を代入する必要があり、テストに関係ない(オブジェクトさえあればテストができる)どうでもいい初期値を型ごとに考えていた。チームメンバーからも同様の悩みが挙がっていたため、今回はIntention Action
を利用したIntelliJのプラグインでどうにかしてみることにした。
正直なところ詳しいところは公式リファレンスに全部載っているため、それを読めばいいんだと思う。あくまでこれはやってみた記事。
Intention Actionsとは
IntelliJのEditor上で呼び出せる便利なアクション。MacのショートカットはOption(⌥)+Enter。WindowsだとAlt+Enterだと思う。
詳しい情報は公式Helpにある。
プラグイン作成
めざしたもの
クラスのフィールドに型ごとの初期値を入れたインスタンス生成の記述をクリップボードにコピーしてくれるようなプラグイン。
例えば
@Value
public class Sample {
private final Integer a;
private final String b;
private final SomeClass c;
}
のクラスで実行したら
new Sample(0, "", new SomeClass())
とテキトー初期化インスタンスをクリップボードにコピーする。
つくったもの
GitHubに上げた。色々修正するところはある。
アクション
実行したいアクションを「〜Action」という名前でJavaで作成。
public class CopyAction extends PsiElementBaseIntentionAction {
private static final String NEW_LINE;
private static final Map<String, String> initialValueLUT = new HashMap<>();
static {
initialValueLUT.put("boolean", "false");
initialValueLUT.put("Boolean", "false");
initialValueLUT.put("int", "0");
initialValueLUT.put("byte", "(byte)0");
initialValueLUT.put("Byte", "(byte)0");
initialValueLUT.put("Integer", "0");
initialValueLUT.put("String", "\"\"");
initialValueLUT.put("BigDecimal", "new BigDecimal(\"0\")");
initialValueLUT.put("Long", "0L");
initialValueLUT.put("long", "0L");
initialValueLUT.put("short", "(short)0");
initialValueLUT.put("Short", "(short)0");
initialValueLUT.put("Date", "new Date()");
initialValueLUT.put("float", "0.0F");
initialValueLUT.put("Float", "0.0F");
initialValueLUT.put("double", "0.0D");
initialValueLUT.put("Double", "0.0D");
initialValueLUT.put("Character", "\'\'");
initialValueLUT.put("char", "\'\'");
initialValueLUT.put("LocalDateTime", "LocalDateTime.now()");
initialValueLUT.put("LocalDate", "LocalDate.now()");
initialValueLUT.put("List", "[]");
NEW_LINE = System.getProperty("line.separator");
}
@Override
public void invoke(@NotNull Project project, Editor editor,
@NotNull PsiElement element) throws IncorrectOperationException {
if (element.getParent() instanceof PsiClass) {
final PsiClass psiClass = ((PsiClass) element.getParent());
final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
final String clipBoardText = makeText(psiClass.getName(), psiClass.getAllFields());
final StringSelection selection = new StringSelection(clipBoardText);
clipboard.setContents(selection, selection);
}
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor,
@NotNull PsiElement element) {
return true;
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return "";
}
@NotNull
@Override
public String getText() { return "Add Field to ClipBoard";}
private String makeText(final String className, final PsiField[] psiFields) {
String clipBoardText = "new " + className + "(" + NEW_LINE;
clipBoardText += Arrays.stream(psiFields)
.map(p -> "/* " + p.getName() + " */ " + Optional.ofNullable(initialValueLUT
.get(p.getTypeElement().getFirstChild().getFirstChild().getText()))
.orElse("new " + p.getType()
.toString()
.split(":")[1] + "()"))
.collect(
Collectors.joining("," + NEW_LINE));
clipBoardText += ")";
return clipBoardText;
}
}
plugin.xml
今回行いたいアクションはIntention Action
なので、plugin.xml
に実行クラスをIntentionAction
タグで囲って記載する。
<extensions defaultExtensionNs="com.intellij">
<intentionAction>
<className>CopyAction</className>
</intentionAction>
</extensions>
拡張ポイントについてはプラグインの拡張ポイントから探す(IntentionActionsはLangExtentionPoints.xmlの43行目あたり)。
つくったもの
Author And Source
この問題について(仕事で困ったのでIntelliJのプラグインを作る), 我々は、より多くの情報をここで見つけました https://qiita.com/Ikeponias/items/4457f4d644a0b4dac335著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .