[JAVA] I was in trouble at work, so I made a plugin for IntelliJ

Introduction

When I was writing Java, I sometimes wrote a test that needed to instantiate such a class.


@Value
public class Sample {
    private final Integer a;
    private final String b;
    private final SomeClass c;
}

There are also some objects nested inside the SomeClass, and just creating an instance of this class is quite exhausting. In addition, it is necessary to assign an initial value to each field, and I was thinking about an initial value that is not related to the test (it can be tested if there is an object) for each type. Since the same troubles were raised by the team members, I decided to do something with the IntelliJ plug-in using ʻIntention Action` this time. To be honest, the details are all in the Official Reference, so I think you should read it. This is just an article I tried.

What are Intention Actions?

A convenient action that can be called on the IntelliJ Editor. The shortcut for Mac is Option (⌥) + Enter. I think it's Alt + Enter on Windows. More information can be found at Official Help.

Plugin creation

What I aimed for

A plugin that copies the description of instantiation that puts the initial value for each type in the class field to the clipboard. For example


@Value
public class Sample {
    private final Integer a;
    private final String b;
    private final SomeClass c;
}

If you run it in the class of

new Sample(0, "", new SomeClass())

And copy the texto initialization instance to the clipboard.

What I made

I uploaded it to GitHub. There are various corrections.

action

Create Action you want to execute in Java with the name "~ Action".


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 Since the action you want to perform this time is ʻIntention Action, describe the execution class in plugin.xml by enclosing it in the ʻIntention Action tag.

  <extensions defaultExtensionNs="com.intellij">
    <intentionAction>
      <className>CopyAction</className>
    </intentionAction>
  </extensions>

Search for extension points from Plugin Extension Points (IntentionActions is LangExtentionPoints.xml (Around line 43 of .jetbrains.com/idea-ce/file/idea-ce-4f9b5f89b2a19ce700b1373a465c16b28ed8ad52/platform/platform-resources/src/META-INF/LangExtensionPoints.xml).

What I made

For the time being, I made a plug-in that copies the description of creating an instance to the clipboard while entering the initial value. sample.gif

Recommended Posts

I was in trouble at work, so I made a plugin for IntelliJ
I made a plugin for IntelliJ IDEA
I made a Diff tool for Java files
I made a primality test program in Java
I made a THETA API client that can be used for plug-in development
The training for newcomers was "Make an app!", So I made an app for the time being.
I made a rock-paper-scissors game in Java (CLI)
I made a Ruby extension library in C
I was a little addicted to the S3 Checksum comparison, so I made a note.
I made a Docker image of SDAPS for Japanese
I made a simple calculation problem game in Java
I made a check tool for the release module
I made a method to ask for Premium Friday
I tried installing the Docker Integration plugin in IntelliJ
I made a Restful server and client in Spring.
I made a library for displaying tutorials on Android.
In Ruby code, I was confused for a moment as "Hash-like but parentheses are arrays?"
parquet-tools gives java.lang.ExceptionInInitializerError, so I made it work with java8
I made a plugin to execute jextract with Gradle task
[Beginner] I made a program to sell cakes in Java
I searched for a web framework with Gem in Ruby
A story I was addicted to in Rails validation settings
I was confused because there was a split in the Array
When I made a bar graph with MPAndroidChart, the x-axis label was misaligned for some reason
I made a SPA with Rails + Nuxt.js for half a year of self-study, so please take a look.
I made roulette in Java.
I made a chat app.
[Circle CI] A story I was addicted to at Start Building
I made a command line interface with WinMerge Plugin using JD-Core
I can't create a Java class with a specific name in IntelliJ
I made a reply function for the Rails Tutorial extension (Part 1)
I recently made a js app in the rumored Dart language
I made a question that can be used for a technical interview
I made a method to ask for Premium Friday (Java 8 version)
I made a reply function for the Rails Tutorial extension (Part 5):
"RSpec doesn't work!" The cause was spring, so I investigated it.