PSI and AST/UAST

699 views
Skip to first unread message

João Cruz

unread,
Feb 26, 2021, 1:58:06 PM2/26/21
to lint-dev
Hello again,

Could someone help me understanding the relation between PSI and AST/UAST?

As far as I understood from talks, AST was the first generated tree from Java files, but it could only access to top-level code elements such as class, methods, fields, etc. Then PSI came into the picture giving the power to check more low-level elements, such as whitespaces.

In my understanding either 
- PSI extends AST
- Is a whole different tree similar to AST but with even more types of nodes.

Now UAST comes into place and I saw in the documentation (https://javadoc.io/doc/com.android.tools.lint/lint-api/latest/com/android/tools/lint/detector/api/Detector.UastScanner.html) a mention saying "UAST augments PSI" and also "UAST is used for the inside of methods (e.g. method bodies), and things like field initializers. PSI continues to be used at the outer level". This got me really confused. UAST replaced AST, but PSI still is the structure accessing low level nodes, how is UAST augmenting it and how is UAST the one looking for the more low level elements?

I might be confusing a few things, please can someone clarify?

Cheers,
João


Tor Norbye

unread,
Feb 26, 2021, 4:11:19 PM2/26/21
to João Cruz, lint-dev
AST just means "abstract syntax tree".

Both PSI and UAST provide AST representations of a source file.
And both of them provide a whole view of the file (e.g. if it contains a class, both will have a class -- PsiClass or UClass respectively).
However, the PSI hierarchy is language specific; the AST for Java looks one way, and the AST for Kotlin looks completely different (different classes involved etc). That means if you want to write a lint check for both Java and Kotlin, you'd basically need to implement the logic twice.

UAST basically can let you target both without worrying about the individual ASTs. It is backed by PSI; the parsers will construct PSI (java psi and kotlin psi), and UAST is constructed from that.

The reason PSI is still relevant is that when you analyze UAST and "resolve" a reference, you get back a PsiElement, not a UElement. That's because (for example) you might be referring to compiled code in a jar file -- which doesn't have a UAST representation.

-- Tor



--
You received this message because you are subscribed to the Google Groups "lint-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lint-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lint-dev/464badc8-5867-42af-a461-6c3fbd6b42bfn%40googlegroups.com.

João Cruz

unread,
Mar 1, 2021, 10:08:10 AM3/1/21
to lint-dev
Nicely put! Now it's clear for me!

Thank you very much for the detailed explanation, Tor!

Cheers,
João

Reply all
Reply to author
Forward
0 new messages