Tracey Yoshima

02/07/2023, 11:49 PM
Hi! I’m curious if there is a Kotlin compiler configuration that preserves some of the structure in a PSI in the FIR or a means to visit the PSI and associate the PSI to the FIR:
In a code snippet like:
import java.util.Random
fun method(min: Int, max: Int) : Int {
    return Random().nextInt((max - min) + 1)
The PSI for the nextInt function call is
=> on the Left-hand side:
. Parenthesized expressions in source code may be unnecessarily wrapped at times, like
(((max)) - ((min)))
. And I’d like to preserve the source code formatting, but the FIR removes the parentheses and only represents the function calls.


02/08/2023, 10:06 AM
No, there isn't PSI is an CST (concrete syntax tree) which preserves original structure of code FIR is an AST (abstract syntax/semantics tree), which represents meaning of code. And the same FIR tree may be built from a number of different PSI trees There is no need for compiler to fully know original syntax structure. Source elements in each FIR node is enough for compiler needs (diagnostics reporting and line mapping collecting)
What exactly you are trying to achieve?

Tracey Yoshima

02/08/2023, 6:24 PM
Ah, okay — that’s fair. I’ve been translating the FIR to an OpenRewrite Kotlin v0.x LST, essentially a combination of the CST and AST with additional information like the language version, stats on the formatting, built-tool info, etc. The work is to enable automated code remediation that leverages accurate type attribution while preserving the project’s original stylistic formatting. The remediations may include unifying code style, implementing language best practices, migrating from one language version to another, or updating APIs from other projects. I want to preserve the original source code so that a single unit of work (what we call a recipe) does not result in unexpected results (even if the results are technically correct). In the arbitrary example
, excluding the parentheses does not cause any changes to the code, but something like
(max - min) * 2
without the parens
max - min * 2
would. So, I’ve handled the parenthesis surrounding binary expressions in code, but I was hoping for a means to use the existing FIR or PSI. If a new version of
or a Kotlin plugin is released that includes API changes, a
declarative recipe
will enable users to adopt the new version quickly.