Grammar-Kit icon indicating copy to clipboard operation
Grammar-Kit copied to clipboard

Add attribute `mixedAST` to simplify mixed AST+PSI creation

Open vlad20012 opened this issue 2 years ago • 5 comments
trafficstars

We are used to two different kinds of PSI implementations:

  1. ASTDelegatePsiElement
+-----+         +-----+
| PSI | ------> | AST |
+-----+         +-----+
  1. StubBasedPsiElementBase
+-----+         +-----+
| PSI | ------> | AST |
+-----+ \ OR    +-----+
         \
          \     +------+
           \ -> | Stub |
                +------+

But really there is a third option - mix PSI and AST in a single class/object:

+---------+
| PSI/AST |
+---------+

This is useful when a PSI element does not have a stub. In this case, additional AST object is not allocated, so we win in memory consumption, and the tree traversing will be fasted, so we win in CPU as well. A PSI element can be mixed if it implements both ASTNode and PsiElement interfaces. This is already done in the platform class CompositePsiElement.

When extending CompositePsiElement, a psi implementation slightly differs from the one extending ASTDelegatePsiElement. In particular, token accessors use findPsiChildByType instead of findChildByType and different constructor signature is needed:

public Element1Impl(IElementType type) {
  super(type);
}

Grammar-Kit supports mixed AST at the moment, but currently it figures out whether a BNF rule uses mixedAST or not by reading .class file content of its extends attribute and comparing its chain of superclasses with com.intellij.psi.impl.source.tree.CompositePsiElement name (1, 2).

Such approach requires extracting all possible superclasses and mixins of PSI nodes to a separate gradle module in order to compile it prior to Grammar-Kit invocation, which is a quite complex setup.

In this PR I've simplified it by introducing mixedAST attribute. If it is set to true (and the rule does not have a stub), Grammar-Kit will use mixedAST style for generated PSI impls without trying to read any .class files content at runtime. The attribute can be applied to a specific rule or globally (so a rule will be treated as mixedAST unless it has a stub)

vlad20012 avatar Jan 14 '23 15:01 vlad20012

I am looking at solutions to the Grammar-Kit gradle plugin problem and stumbled over this pull request. It seems interesting for other reasons, but mostly for the codegen .class reading issues. I'd love if the GrammarKit team had a look at this and either rejected or accepted it.

lerno avatar May 02 '23 07:05 lerno

What is the status of this PR? Is it being considered?

ice1000 avatar May 14 '24 15:05 ice1000

Current status:

A year ago I and @vlad20012 discussed that a separate mixedAST flag is not needed.

If possible, fast logic must always be used. generate.exact-types attribute can be used to detect the case.

gregsh avatar May 14 '24 19:05 gregsh

Where can I learn more about generate.exact-types?

ice1000 avatar May 15 '24 00:05 ice1000

Did you mean #317? It's also open, hmm

ice1000 avatar May 15 '24 00:05 ice1000