Hi, I'm working on a kotlin compiler plugin. One o...
# compiler
n
Hi, I'm working on a kotlin compiler plugin. One of the tasks of the plugin is to replace certain interfaces with a class. E.g.:
Copy code
inteface Greeting {
  fun greet()
}
Would be transformed into a class replacing the interface:
Copy code
class Greeting {
  fun geet() {
    println("Hello, World!")
  }
}
When trying to figure out whether I can to this and mostly how, I looked at [arrow-meta](https://github.com/arrow-kt/arrow-meta). I see they accomplish replacing/renaming pieces of kotlin code in a
AnalysisHandlerExtension
. They also build their own AST and have their own writer to write the modified tree into a file. So I though instead of relying on arrow-meta I thought I'd use the PSI api to copy, modify and get the text of modified files. However it seems that in the compiler some pieces of PSI is not available. Most importantly when I try to delete and element from the tree I get the following exception:
Copy code
e: java.lang.NullPointerException
        at org.jetbrains.kotlin.com.intellij.psi.impl.source.codeStyle.CodeEditUtil.saveWhitespacesInfo(CodeEditUtil.java:122)
        at org.jetbrains.kotlin.com.intellij.psi.impl.source.codeStyle.CodeEditUtil.removeChildren(CodeEditUtil.java:134)
        at org.jetbrains.kotlin.com.intellij.psi.impl.source.codeStyle.CodeEditUtil.removeChild(CodeEditUtil.java:49)
        at org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.CompositeElement.deleteChildInternal(CompositeElement.java:451)
        at org.jetbrains.kotlin.com.intellij.extapi.psi.ASTDelegatePsiElement.deleteChildInternal(ASTDelegatePsiElement.java:346)
        at org.jetbrains.kotlin.com.intellij.extapi.psi.ASTDelegatePsiElement.delete(ASTDelegatePsiElement.java:330)
Looking at
CodeEditUtil
I know that the
NullPointerException
is raised in this part
Copy code
public static void saveWhitespacesInfo(ASTNode first) {
  ...
  setOldIndentation((TreeElement)first, IndentHelper.getInstance().getIndent(file, first));
}
Because
IdentnHelper.getInstance()
returns null.
Copy code
public abstract class IndentHelper {
  public static IndentHelper getInstance() {
    return ApplicationManager.getApplication().getService(IndentHelper.class);
  }
  ...
}
And indeed trying to get
IndentHelper
as service returns null in my plugin. So now I'm wondering if it is possible to install an instance if this service out side of the IDE to be able to manipulate PSI in a kotlin compiler plugin. Alternatively I'd be also grateful is someone could provide me with the highlights on an alternative approach to achieve my goal.
d
Hi PSI in kotlin compiler is read-obly by design and there is no builtin solution for such plugins (yet) I think arrow meta is most suitable way to achieve your goal right now
r
@nemi For what is worth we are going to remove in place transformations in Meta now for the issue Dmitriy described. Even when you have your own tree the moment you change the internal document then you leave the IDE out of sync. Imagine you add a new member, then that requires also an IDE plugin because the Kotlin plugin today does not create synth descriptor for the IDE to see the changes. There is also the problem of source locations and line numbers, it’s offsetting the doc and for Meta to fix that would have to further hijack the compiler so it’s not a good path going forward. In your example the Kotlin plugin would still think that is an interface and not a class and would red line use site calls for
Greeting()
with the wrong error messages and potentially wrong suggestions too. We hope that once FIR has some kind of compiler hooks for what metaprogramming looks like, it includes the builtin IDE support so compiler plugin authors are not forced to write and market IDEA plugins to get meta-programming support in Kotlin.
n
Hey @dmitriy.novozhilov , @raulraja! Thanks for your the info (sorry for the late reply, was away for holidays). @raulraja this will break existing code built with arrow-meta right ?(just for clarification) Is there a potential time time frame when such things are going to be possible through built in compiler APIs?
In your example the Kotlin plugin would still think that is an interface and not a class and would red line use site calls for 
Greeting()
  with the wrong error messages and potentially wrong suggestions too.
@raulraja yes this definitely would be a PITA, however in my case it is not an issue, as these classes would never be instantiated directly. And I do not need to reflect the changes in the IDE either 🤔 so what meta is doing right now cloud for my use case
r
We will keep then those around until there is a FIR alternative but not advertise as they are dangerous APIs if that works for you @nemi. FIR is in heavy active dev but no concrete dates afaik
👌 1