kotlinx / ast

Generic AST parsing library for kotlin multiplatform
Apache License 2.0
317 stars 22 forks source link

How to Visit Each Node of an AST? #48

Closed kevinvandenbreemen closed 2 years ago

kevinvandenbreemen commented 3 years ago

Good morning, I've been playing with your library for a bit to see if I can use it in a project to analyze Kotlin code. I am confused about what / whether there is a relation between the concept of a "summary" (see Summary.kt extension functions a la Ast.summary() function) and that of visiting nodes as one would do in libraries like ParseJava.

Is there a way for me to execute a visitor pattern on the tree generated by the library and say print out the names of all classes in a file or the names of all methods in a class?

drieks commented 3 years ago

Hi @kevinvandenbreemen,

both the "raw ast" (the parsing result) and the "summary ast" are data classes. The base type is {{kotlinx.ast.common.ast.Ast}}, you can recursively process them and check for instances of {{kotlinx.ast.common.ast.AstNode}}, when it is a {{AstNode}} you can use the field {{children}} to process the child nodes.

The difference is that the "raw" ast contains every detail of the source, it is very big and unhandy to process. The "summary" ast is a higher level representation, containing "fun", "val", "class" or "object" for example.

fun process(ast: Ast) {
    when(ast) {
        is KlassDeclaration ->
            // check keyword, is can be for example val, fun, class, object 
            if (ast.keyword == "fun") {
               println("found function ${ast.identifier?.rawName}")
            }
            // each KlassDeclaration can have child nodes
            for(child in ast.children) {
                process(child)
            }

        is AstNode ->
            // handle children of other ast nodes
            for(child in ast.children) {
                process(child)
            }

        else ->
            // unknown leaf ast, ignore..
    }
}

You can see the difference here in the unit test folder: testdata For example Class.kt.txt contains the kotlin code, Class.raw.ast.txt contain the "raw" ast and Class.summary.ast.txt contains the "summary" ast.

kevinvandenbreemen commented 3 years ago

Thank you, this is quite helpful :) and I think I can use it to optimize some of the work I've written so far on my project. Thanks again