Search code examples
intellij-plugin

Extending code completion to support internal orm


As said in the tittle, i need to extend code completion to support a internal ORM.

It's something like ActiveRecords. Ex.:

@TableName("ONE_MODEL")
public class OneModel extends BaseModel {

}

...
OneModel oneModel = OneModel.getById(1);
Object value = oneModel.get("COLUMN_NAME");
...

So, when using smart completion when caret between quotation marks inside de .get method, for example, i need to show parameters options based on the table columns.

Something like that it's possible to be made with Intellij Plugins?

I was reading about CompletionContributor, but can't find anything about the possibility to identify the class whose method is being called, it's super class, and it's annotations values.


Solution

  • CompletionContributor is the way to go. This example is taken from the official SDK docs:

    public class SimpleCompletionContributor extends CompletionContributor {
      public SimpleCompletionContributor() {
        extend(CompletionType.BASIC,
               PlatformPatterns.psiElement(SimpleTypes.VALUE).withLanguage(SimpleLanguage.INSTANCE),
               new CompletionProvider<CompletionParameters>() {
                 public void addCompletions(@NotNull CompletionParameters parameters,
                                            ProcessingContext context,
                                            @NotNull CompletionResultSet resultSet) {
                   resultSet.addElement(LookupElementBuilder.create("Hello"));
                 }
               }
        );
      }
    }
    

    The second parameter of extend allows you to trigger your provider on a specific kind of PSI element. In your case, you could target something like PlatformPatterns.psiElement(JavaElementType.LITERAL_EXPRESSION), then in your CompletionProvider you can check for the exact element with parameters.getPosition() and see if it's a PsiLiteral representing a String.

    Using the PSI API, you can then discover what's around this literal, like classes if the containing file is a PsiClassOwner, or with PsiTreeUtil.getParentOfType() etc.

    In your specific example, you could check if the string literal is part of a PsiMethodCallExpression.

    To easily understand how the PSI tree is built, I highly suggest you open Tools > View PSI Structure... and paste a sample of what you want to detect:

    enter image description here