Generic AST parsing library for kotlin multiplatform

Related tags

kotlin ast multiplatform
Overview

License Release

kotlinx.ast

kotlinx.ast is a generic AST (Abstract Syntax Tree) parsing library, Kotlin is currently the only supported language. The library is designed that other languages can be easily added. kotlinx.ast does not use the Kotlin Compiler for parsing, it is using ANTLR (the Kotlin variant: https://github.com/Strumenta/antlr-kotlin) using the official Kotlin Grammar (https://kotlinlang.org/docs/reference/grammar.html).

One Component is Klass, a collection of language independent data classes used to represent and easily access the AST.

Status

The Project is in an early stage, but it is already possible to parse Kotlin code. Bug Reports, Feature Requests and Pull Requests are very welcome.

kotlinx.ast is a multiplatform project, but currently, JVM is the only supported target. Support for JS and native is planned.

antlr-java, antlr-optimized and antlr-kotlin are supported on the JVM. Multiplatform support (Kotlin Native and Kotlin JavaScript) for antlr-kotlin is planned. Because antlr-java and antlr-optimized are JVM-only, support for other platforms is not possible.

Prior art

kastree is using the kotlin compiler for parsing, it can only parse kotlin files. JS and native support is not possible. 'kastree` is currently not under active development.

Example

This Kotlin Code:

@Annotation1("abc")
// line comment between annotations
@Annotation2("\${123}")
fun parse() {}

will be parsed as:

PackageHeader()
importList
KlassDeclaration(fun parse)
  KlassAnnotation(Annotation1)
    KlassArgument()
      KlassString
        "abc"
  KlassAnnotation(Annotation2)
    KlassArgument()
      KlassString
        Escape("\$")
        "{123}"

There are more examples in directory testdata.

  • Files named "*.kt.txt" contains the kotlin source to parse
  • Files named "*.raw.txt" contains the parsed raw kotlin AST as defined by the official Kotlin Grammar
  • Files named "*.summary.txt" contains the AST summary

Open Tasks

There are some parts missing, for example the importList is not converted into an easy-to-use data class

Overview

Currently, there are some libraries that are part of kotlinx.ast:

  • kotlinx.ast:common contains the code that can later be reused by other grammar parsers
  • kotlinx.ast:common-test contains the dependencies to test frameworks, used by kotlinx.ast unit tests
  • kotlinx.ast:parser-antlr-java contains the shared code required to parse grammars using the official antlr4 JVM implementation.
  • kotlinx.ast:parser-antlr-kotlin contains the shared code required to parse grammars using antlr-kotlin
  • kotlinx.ast:parser-antlr-optimized contains the shared code required to parse grammars using the optimized fork of antlr.
  • kotlinx.ast:grammar-kotlin-parser-common contains the shared code required to parse kotlin source
  • kotlinx.ast:grammar-kotlin-parser-antlr-java provides a kotlin ast parsed using antlr-java
  • kotlinx.ast:grammar-kotlin-parser-antlr-kotlin provides a kotlin ast parsed using antlr-kotlin
  • kotlinx.ast:grammar-kotlin-parser-test contains the test data used by the kotlin parsers
  • kotlinx.ast:grammar-antlr4-parser-common contains the shared code required to parse antlr4 grammar files
  • kotlinx.ast:grammar-antlr4-parser-antlr-java provides an antlr4 grammar ast parser using antlr-java
  • kotlinx.ast:grammar-antlr4-parser-test contains the test data used by the antlr4 grammar parsers

External Dependencies

antlr-kotlin

  • ${Versions.antlrKotlinGroup}:antlr-kotlin-runtime:${Versions.antlrKotlin} is required at runtime to be able to parse kotlin code into an AST when using kotlinx.ast:grammar-kotlin-parser-antlr-kotlin.

antlr-java

  • org.antlr:antlr4:${Versions.antlrJava} is required at runtime to be able to parse kotlin code into an AST when using kotlinx.ast:grammar-kotlin-parser-antlr-java.

antlr-optimized

  • com.tunnelvisionlabs:antlr4:${Versions.antlrOptimized} is required at runtime to be able to parse kotlin code into an AST when using kotlinx.ast:grammar-kotlin-parser-antlr-optimized. NOTE: antlr-optimized is a drop-in replacement of antlr-java. Both jars provide the same API, namely the package org.antlr.v4, so you can't use both at the same time. kotlinx.ast:parser-antlr-optimized depends on kotlinx.ast:parser-antlr-java, both provide the same kotlinx.ast API. The difference is that parser-antlr-optimized will exclude the dependency to org.antlr:antlr4 and instead include com.tunnelvisionlabs:antlr4. The generated code of these two libraries is not equal, therefore two different grammar modules are required:
  • kotlinx.ast:parser-antlr-java
  • kotlinx.ast:parser-antlr-optimized (the generated code is linked, for the case that you want to compare it)

(Versions can be found here: Versions.kt)

How to use kotlinx.ast

There is a small example to get started:

Using with Gradle

kotlinx.ast is accessible on Maven & Gradle through Jitpack. In jitpack basically you can use every commit or tag as a version number. You can find recent versions on the Jitpack page for kotlinx.ast.

You have to add this line to settings.gradle.kts: (otherwise, the jars are not resolved):

// Enables KotlinMultiplatform publication and resolving (in dependencies)
enableFeaturePreview("GRADLE_METADATA")

You have to add Jitpack to build.gradle.kts:

repositories {
  maven("https://jitpack.io")
}

Add the dependency to kotlinx.ast into your project:

kotlin {
    jvm()

    sourceSets {
        val commonMain by getting {
            dependencies {
                // please look at https://jitpack.io/#drieks/antlr-kotlin to find the latest version
                api("com.github.kotlinx.ast:grammar-kotlin-parser-antlr-kotlin:0123456789")
            }
        }
    }
}

If you don't use kotlin-multiplatform add this line:

// please look at https://jitpack.io/#drieks/antlr-kotlin to find the latest version
implementation("com.github.kotlinx.ast:grammar-kotlin-parser-antlr-kotlin:0123456789")

Or, if you prefer to use the antlr-java parser (JVM only):

// please look at https://jitpack.io/#drieks/antlr-kotlin to find the latest version
implementation("com.github.kotlinx.ast:grammar-kotlin-parser-antlr-java:0123456789")

The latest version can be be seen in the Jitpack-Badge at the top of this page.

Issues
  • How to get the entire AST instead of just the summary?

    How to get the entire AST instead of just the summary?

    Hi!

    The title says it basically. How do you get the entire AST, with DefaultAstNodes converted to the Klass Data classes, from a kotlinfile. In the example the following function is invoked:

    kotlinFile.summary()
    

    This function does not include the body of a function for example. I tried to create my own function:

    kotlinFile.complete()
    
    private val completeTreeMap: TreeMap = DefaultTreeMap(
        annotationsMapper,
        declarationsMapper,
        expressionsMapper.flattenNames("functionDeclaration"),
        globalsMapper,
        kotlinDefaultMapper,
        modifierMapper,
        stringMapper,
        typesMapper
    )
    
    fun List<Ast>.complete(): AstResult<List<Ast>> {
        return completeTreeMap.treeMap(this)
    }
    
    fun Ast.complete(): AstResult<List<Ast>> {
        return listOf(this).complete()
    }
    

    I tried to change the Mappers in the DefaultTreeMap, but couldn't get a configuration to be able to visit the statements in the body of functions.

    Hopefully this is enough information to be able to resolve my problem.

    Thanks in advance!

    opened by ToineHulshof 10
  • java.lang.ArrayIndexOutOfBoundsException during parsing

    java.lang.ArrayIndexOutOfBoundsException during parsing

    Hi! I tried to parse a very simple file: class Sample (private val propertyA: String)

    using the code from example

    fun main() {
        val source = AstSource.File(
            "src/jvmMain/kotlin/sample/Sample.kt"
        )
        val kotlinFile = KotlinGrammarAntlrKotlinParser.parseKotlinFile(source)
        kotlinFile.summary()
            .onSuccess { astList ->
                astList.forEach(Ast::print)
            }.onFailure { errors ->
                errors.forEach(::println)
            }
    }
    

    And got such error

    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 170
    	at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinAstParserImpl.toAstTerminal(AntlrKotlinAstParserImpl.kt:27)
    	at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinAstParserImpl.parse(AntlrKotlinAstParserImpl.kt:82)
    	at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinAstParserImpl.parse(AntlrKotlinAstParserImpl.kt:75)
    	at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinAstParserImplKt.antlrKotlinParser(AntlrKotlinAstParserImpl.kt:138)
    	at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinAstParserImplKt.antlrKotlinParser(AntlrKotlinAstParserImpl.kt:98)
    	at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinParser.parse(AntlrKotlinParser.kt:20)
    	at kotlinx.ast.grammar.kotlin.common.KotlinGrammarParser$DefaultImpls.parseKotlinFile(KotlinGrammarParser.kt:9)
    	at kotlinx.ast.grammar.kotlin.target.antlr.kotlin.KotlinGrammarAntlrKotlinParser.parseKotlinFile(KotlinGrammarAntlrKotlinParser.kt:10)
    	at sample.MainKt.main(Main.kt:14)
    	at sample.MainKt.main(Main.kt)
    
    opened by VitaSokolova 9
  • Function with generic parameter with optional breaks the parsing

    Function with generic parameter with optional breaks the parsing

    Example below will crash when calling summary() i.e. KotlinAstParser.parseKotlinFile(source).summary() throws java.lang.UnsupportedOperationException: Empty collection can't be reduced..

    Parsing the code below, with the String? in a generic, leads to a new structure and summary() does not work anymore.

    package com.example.test
    
    class TestClass {
        fun function(record: Map<String?, String>) {
        }
    }
    
    opened by martinflorek 7
  • ParseCancellationException - string interpolated functions

    ParseCancellationException - string interpolated functions

    Hi, I'm not sure that is it ast library issue but I've got following file:

    package com.example.app.ui
    
    internal class FeatureFragment :
        BaseFragment<FeatureViewModel, FeatureFragmentBinding>() {
    
        private fun handleViewStateChanges(viewState: FeatureViewModel.ViewState): Unit =
            with(
                requireBinding
            ) {
                dateRangePropertyView.text =
                    "${monthDayYearDateFormat.format(viewState.dateRange.startDate)} - ${
                        monthDayYearDateFormat.format(viewState.dateRange.endDate)
                    }"
            }
    }
    

    I'm testing the file as usual:

    kotlinFile.summary(attachRawAst = false)
        .onSuccess { astList ->
            astList.forEach(Ast::print)
        }.onFailure { errors ->
            errors.forEach(::println)
        }
    

    and parser throws an exception:

    Exception in thread "main" org.antlr.v4.kotlinruntime.misc.ParseCancellationException at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinErrorListener.syntaxError(AntlrKotlinErrorListener.kt:17) at org.antlr.v4.kotlinruntime.ProxyErrorListener.syntaxError(ProxyErrorListener.kt:34) at org.antlr.v4.kotlinruntime.Parser.notifyErrorListeners(Parser.kt:564) at org.antlr.v4.kotlinruntime.DefaultErrorStrategy.reportUnwantedToken(DefaultErrorStrategy.kt:376) at org.antlr.v4.kotlinruntime.DefaultErrorStrategy.sync(DefaultErrorStrategy.kt:271) at kotlinx.ast.grammar.kotlin.target.antlr.kotlin.generated.KotlinParser.kotlinFile(KotlinParser.kt:1108) at kotlinx.ast.grammar.kotlin.target.antlr.kotlin.KotlinGrammarAntlrKotlinParserExtractor$extractor$1.invoke(KotlinGrammarAntlrKotlinParserAstParserType.kt:18) at kotlinx.ast.grammar.kotlin.target.antlr.kotlin.KotlinGrammarAntlrKotlinParserExtractor$extractor$1.invoke(KotlinGrammarAntlrKotlinParserAstParserType.kt:9) at kotlinx.ast.common.AstParserExtractor$DefaultImpls.extract(AstParserExtractor.kt:5) at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinParserExtractor$DefaultImpls.extract(AntlrKotlinParserExtractor.kt) at kotlinx.ast.grammar.kotlin.target.antlr.kotlin.KotlinGrammarAntlrKotlinParserExtractor.extract(KotlinGrammarAntlrKotlinParserAstParserType.kt:9) at kotlinx.ast.grammar.kotlin.target.antlr.kotlin.KotlinGrammarAntlrKotlinParserExtractor.extract(KotlinGrammarAntlrKotlinParserAstParserType.kt:9) at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinAstParserImplKt.antlrKotlinParser(AntlrKotlinAstParserImpl.kt:165) at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinAstParserImplKt.antlrKotlinParser(AntlrKotlinAstParserImpl.kt:121) at kotlinx.ast.parser.antlr.kotlin.AntlrKotlinParser.parse(AntlrKotlinParser.kt:20) at kotlinx.ast.grammar.kotlin.common.KotlinGrammarParser$DefaultImpls.parseKotlinFile(KotlinGrammarParser.kt:9) at kotlinx.ast.grammar.kotlin.target.antlr.kotlin.KotlinGrammarAntlrKotlinParser.parseKotlinFile(KotlinGrammarAntlrKotlinParser.kt:10) at org.jetbrains.kotlin.idea.scratch.generated.ScratchFileRunnerGenerated$ScratchFileRunnerGenerated.(tmp.kt:22) at org.jetbrains.kotlin.idea.scratch.generated.ScratchFileRunnerGenerated.main(tmp.kt:33)

    The problem has to be the line break after ${ because, without that lines, the execution goes smooth

                dateRangePropertyView.text =
                    "${monthDayYearDateFormat.format(viewState.dateRange.startDate)} - ${
                        monthDayYearDateFormat.format(viewState.dateRange.endDate)
                    }"
    

    Library version

    com.github.kotlinx.ast:grammar-kotlin-parser-antlr-kotlin-jvm:a96e681f90

    bug feedback 
    opened by arkadiuszpalka 6
  • Constructor parameters and properties defined in constructor

    Constructor parameters and properties defined in constructor

    The parser now handles "escaped" characters inside annotations' values but I have found another missing node.

    The AST does not contain constructor parameters and properties declared in constructor e.g.:

    class TestClass(
        @Value("test value")
        private val propertyA: String
    )
    
    opened by martinflorek 6
  • Nullable types are not parsed correctly

    Nullable types are not parsed correctly

    I'm parsing the following Kotlin code kotlinx.ast and the KotlinGrammarAntlrKotlinParser. But weirdly, I have some nullable types which are not marked as nullable.

    package foo.bar
    class Spam {
        fun doSomething(i: Int, s: String?, l : List<String>) {}
    } 
    

    Here's what I get when printing the AST nodes

    PackageHeader(foo.bar)
    importList
    KlassDeclaration(object Spam)
    PackageHeader(foo.bar)
    importList
    KlassDeclaration(class Spam)
      classBody
        KlassDeclaration(fun doSomething)
          KlassDeclaration(parameter i Int)
          KlassDeclaration(parameter s String)
          KlassDeclaration(parameter l List<String>)
    

    I'm using version c35b50fa44 from JitPack :

    implementation("com.github.kotlinx.ast:grammar-kotlin-parser-antlr-kotlin-jvm:c35b50fa44")
    
    opened by xgouchet 4
  • Unable to use example class, because I am unable to import classes

    Unable to use example class, because I am unable to import classes

    Hi, Please help in what I am doing wrong I am unable to use this AstSource

    Dependencies used -

        implementation 'com.github.drieks.antlr-kotlin:antlr-kotlin-runtime-jvm:b09d76328'
        implementation 'com.github.drieks.antlr-kotlin:antlr-kotlin-runtime:b09d76328'
        api("com.github.kotlinx.ast:grammar-kotlin-parser-antlr-kotlin:b09d76328")
    

    Sample code -

        val source = AstSource.File(
            "grammar-kotlin-parser-antlr-kotlin/src/jvmTest/kotlin/kotlinx/ast/example/ExampleMain.kt"
        )
        val kotlinFile = KotlinGrammarAntlrKotlinParser.parseKotlinFile(source)
        kotlinFile.summary(attachRawAst = false)
            .onSuccess { astList ->
                astList.forEach(Ast::print)
            }.onFailure { errors ->
                errors.forEach(::println)
            }
    }
    

    Error - Unable to import class - AstSource

    opened by rahullohra2903 4
  • Failed to parse typeParameter

    Failed to parse typeParameter

    I noticed that the library has problem to parse generic type with . dot

    File under test:

    class SimpleType<V : BaseType.SubType> {
    
    }
    

    failed to parse typeParameter

    I'm invoking it like at example:

            kotlinFile.summary(attachRawAst = false)
                .onSuccess { astList ->
                    astList.forEach {
                        it.print()
                    }
                }.onFailure { errors ->
                    errors.forEach(::println)
                }
    

    Library version:

    com.github.kotlinx.ast:grammar-kotlin-parser-antlr-kotlin-jvm:75251cf4d8
    
    opened by arkadiuszpalka 3
  • How to recursively print the structure of Ast

    How to recursively print the structure of Ast

    Hi, thanks for the work!

    I am fresh to Kotlin, and I want to convert a Kotlin file to AST.

    Here is my Kotlin file:

    package com.kickstarter.libs.utils
    
    import android.content.Context
    import android.net.Uri
    import androidx.browser.customtabs.CustomTabsIntent
    import androidx.core.content.ContextCompat
    import com.kickstarter.R
    
    object UrlUtils {
    
        private const val KEY_REF = "ref"
    
        fun appendPath(baseUrl: String, path: String): String {
            val uriBuilder = Uri.parse(baseUrl).buildUpon()
            uriBuilder.appendEncodedPath(path)
    
            return uriBuilder.build().toString()
        }
    
        fun appendQueryParameter(baseUrl: String, key: String, value: String): String {
            val uriBuilder = Uri.parse(baseUrl).buildUpon()
            uriBuilder.appendQueryParameter(key, value)
    
            return uriBuilder.build().toString()
        }
    
        fun appendRefTag(baseUrl: String, tag: String): String {
            return appendQueryParameter(baseUrl, KEY_REF, tag)
        }
    
        fun baseCustomTabsIntent(context: Context): CustomTabsIntent {
            val builder = CustomTabsIntent.Builder()
    
            builder.setShowTitle(true)
            builder.setToolbarColor(ContextCompat.getColor(context, R.color.primary))
    
            return builder.build()
        }
    
        fun refTag(url: String): String? {
            return Uri.parse(url).getQueryParameter(KEY_REF)
        }
    }
    
    

    Here is the test code:

    package kotlinx.ast.example
    
    import kotlinx.ast.common.AstSource
    import kotlinx.ast.common.ast.Ast
    import kotlinx.ast.common.print
    import kotlinx.ast.grammar.kotlin.common.summary
    import kotlinx.ast.grammar.kotlin.target.antlr.kotlin.KotlinGrammarAntlrKotlinParser
    
    fun main() {
        val source = AstSource.File(
                "gen.kotlin/src/main/resources/2.kt.txt"
        )
        val kotlinFile = KotlinGrammarAntlrKotlinParser.parseKotlinFile(source)
        kotlinFile.summary(attachRawAst = false)
                .onSuccess { astList ->
                    astList.forEach(Ast::print)
                }.onFailure { errors ->
                    errors.forEach(::println)
                }
    }
    

    And here is the result, which only prints the top-level ones:

    PackageHeader(com.kickstarter.libs.utils)
    importList
      Import(android.content.Context)
      Import(android.net.Uri)
      Import(androidx.browser.customtabs.CustomTabsIntent)
      Import(androidx.core.content.ContextCompat)
      Import(com.kickstarter.R)
    KlassDeclaration(object UrlUtils)
    
    

    However, I found that the children for the top-level object AST is empty, then how to print the whole structure of the file?

    opened by Symbolk 3
  • Found unsupported ast node. Function uses type projection 'out'

    Found unsupported ast node. Function uses type projection 'out'

    Hello :) Here's the file under test:

    package com.example.app.ui
    
    internal class FeatureFragment :
        BaseFragment<FeatureViewModel, FeatureFragmentBinding>() {
    
        override fun provideViewIntents(): List<Observable<out Feature.Intent>> = emptyList()
    
    }
    

    and the parser prints out the following message:

    found unsupported ast node 'DefaultAstNode(description=typeProjectionModifiers, children=[DefaultAstNode(description=typeProjectionModifier, children=[DefaultAstNode(description=varianceModifier, children=[DefaultAstTerminal(description=OUT, text=out, channel=AstChannel(id=0, name=DEFAULT_TOKEN_CHANNEL), attachments=AstAttachments(attachments={[email protected]=   51 [171..174]   [6:47..6:50]}))], attachments=AstAttachments(attachments={[email protected]=      [171..174]   [6:47..6:50]}))], attachments=AstAttachments(attachments={[email protected]=      [171..174]   [6:47..6:50]}))], attachments=AstAttachments(attachments={[email protected]=      [171..174]   [6:47..6:50]}))' in typeProjection!
    

    seems the out makes trouble.

    Library version

    com.github.kotlinx.ast:grammar-kotlin-parser-antlr-kotlin-jvm:bdca0630aa

    bug fixed 
    opened by arkadiuszpalka 2
  • Running at command line or as gradle task

    Running at command line or as gradle task

    Hi, thanks for this tool. This is really a question and not an issue as am not conversant with ASTs. Is this something that can be run from the command line or as gradle task? If possible (gradle better), could you give me some pointers? At the moment am running this as a unit test and printing the output to a file to be checked later. Ideally, I want to create a gradle task pointing to a dir to load all files in there and print this AST output to a file for analysis later on.

    feedback question 
    opened by saintjab 1
  • Source code generation from the AST

    Source code generation from the AST

    I've been working on a meta-programming tool that can process generated code for the Android Room database and transform it to insert profiling statements. Since this generates Java code, I've used JavaParser to read the Java code into an AST, transform it and output the transformed AST as source code (since this is a feature that JavaParser supports) to be used in the final build.

    I also want to add support for SQLDelight. However, that generates Kotlin code, so I need a tool that can not only parse the generated Kotlin code, but lets me modify it and output transformed source code.

    As far as I can tell, kotlinx.ast only supports reading the source code and not generating code from the AST. Would I be correct in that?

    feedback question 
    opened by vinaysshenoy 2
  • Properties from companion object are not parsed as KlassDeclaration instances

    Properties from companion object are not parsed as KlassDeclaration instances

    Given the following code:

    
    class MyClass {
        val myClassProp = "myClassProp"
        companion object {
            const val myCompanionConst = "myCompanionConst"
            val myCompanionProp = "myCompanionProp"
        }
    }
    

    the parser returns myConst and myClassProp as a KlassDeclaration instances, but the myCompanionProp is parsed as a tree of DefaultAstNode/DefaultAstTerminal which are hard to analyze: image

    Is this the expected behavior?

    bug feedback fixed 
    opened by mbolotov 1
  • java.lang.NoClassDefFoundError: Could not initialize class kotlinx.ast.grammar.kotlin.target.antlr.kotlin.KotlinGrammarAntlrKotlinParser

    java.lang.NoClassDefFoundError: Could not initialize class kotlinx.ast.grammar.kotlin.target.antlr.kotlin.KotlinGrammarAntlrKotlinParser

    My project is a Gradle Plugin that parses Kotlin code to generate flat files.

    I am trying to replace kastree with this library, but i encounter the captioned error when I run my plugin in another project. My code works fine within my Gradle plugin project and my tests though. I suppose this is a missing transitive dependency problem, but I can't figure out what is missing exactly.

    In my Gradle plugin project I have the following dep:

    api 'com.github.kotlinx.ast:grammar-kotlin-parser-antlr-kotlin-jvm:a96e681f90'
    

    Note that the Gradle project uses subprojects. The parsing is implemented in one of the subproject, and the Gradle plugin project has an implementation dependency on that subproject. I also tried with an api dependency to no avail.

    Should i add a runtime dependency on the kotlin parser ?

    feedback question 
    opened by gauthier-roebroeck-mox 7
  • Best way to explore AST to search for specific patterns?

    Best way to explore AST to search for specific patterns?

    Hello,

    i am trying to migrate an existing project using kastree to this library.

    I am struggling to retrieve the content of a parameter of an annotation that is on a method of a class.

    I have a Kotlin file that looks like this (excerpt):

    class MyClass {
    
    @KafkaListener(
            id = "\${'$'}{messaging.command.topic.consumer.group.name}",
            clientIdPrefix = "\${'$'}{messaging.command.topic.consumer.group.name}",
            topics = ["direct.topic.name.2", "\${'$'}{messaging.command.topic.name.2}"],
            concurrency = "\${'$'}{messaging.command.topic.listener-count}"
        )
        fun topicTest4MultipleMixedTopics(@Payload entityCommand: EntityCommand<JsonNode>, record: ConsumerRecord<String, Array<Byte>>) {
        }
    }
    

    What's the best way to get the content of the topics argument of the @KafkaListener annotation ?

    So far i came up with this. This gives me the members of the class:

    kotlinFile.summary(attachRawAst = false)
                .onSuccess { ast ->
                    ast
                        .filterIsInstance<KlassDeclaration>() // filter on Classes
                        .flatMap { it.flatten("classBody") } // get the Class body
                        .flatMap { it.children } // get all the declarations within that class (functions etc)
                        .filterIsInstance(KlassDeclaration::class.java) // filter on KlassDeclaration
                        .flatMap { parseTopics2(it) } // parse topics from functions
                }
    

    This tries to parse the function declaration block. I am faced with each node having a single node in its children, over and over, and no good way to get the content of the actual string.

    private fun parseTopics2(func: KlassDeclaration): List<Pair<String, List<Schema>>> {
            func.children
                .asSequence()
                .filterIsInstance<KlassAnnotation>()
                .filter { it.description.contains(annotation) }
                .mapNotNull { it.arguments.firstOrNull { it.identifier.identifier == "topics" } }
                .mapNotNull { it.expressions.firstOrNull() }
                .filter { it.description == "collectionLiteral" }
                .filterIsInstance<DefaultAstNode>()
                .mapNotNull { it.children.getOrNull(1) }
                .toList()
                .flatMap { it.flatten("stringLiteral") }
            return emptyList()
        }
    

    I am also not sure that doing a .filterIsInstance<KlassAnnotation>() is a good way of filtering the AST, surely there is a better way of doing that, no ?

    feedback question 
    opened by gauthier-roebroeck-mox 3
  • Nullable types are not parsed correctly

    Nullable types are not parsed correctly

    package test
    
    class MyObj(val myParam: String?)
    

    The nullable field of the myParam inside the constructor is set to false. I'm using a96e681f90.

    bug feedback fixed 
    opened by fab1an 1
  • How can I get the AST representing statements inside the method?

    How can I get the AST representing statements inside the method?

    When parsing AST, how can I find out on which line a particular Class or Function was declared?

    enhancement good first issue help wanted 
    opened by rajatpundir 4
  • Question: Support for kdoc

    Question: Support for kdoc

    So in the examples and the test cases, it seemed that single line comments are stripped from the AST output. Now I could not find a reference or test case for class or function documentation (kdoc). Will this library parse them into some nodes or will comments be ignored in the output?

    opened by mediavrog 2
  • Official Kotlin library with

    Official Kotlin library with "kotlinx" prefix?

    Is this an official Kotlin library supported by JetBrains? If not, I guess it is not appropriate to use the "kotlinx" prefix in the name. It causes ambiguity.

    opened by ShreckYe 2
  • Parsing large files is too slow

    Parsing large files is too slow

    These files are currently not included in SelfTest.kt because the processing does not finish within a reasonable time:

    • KotlinLexer.kt
    • KotlinParser.kt
    • UnicodeClasses.kt
    bug enhancement 
    opened by drieks 6
Gradle plugin for simplify Kotlin Multiplatform mobile configurations

Mobile Multiplatform gradle plugin This is a Gradle plugin for simple setup of Kotlin Multiplatform mobile Gradle modules. Setup buildSrc/build.gradle

IceRock Development 59 Jul 5, 2021
A framework for writing composable parsers based on Kotlin Coroutines.

Parsus A framework for writing composable parsers based on Kotlin Coroutines. val booleanGrammar = object : Grammar<BooleanExpression>() { val ws

Aleksei Semin 26 Jul 21, 2021
Dependency Injection library for Kotlin Multiplatform, support iOS and Android

Multiplatform-DI library for Kotlin Multiplatform Lightweight dependency injection framework for Kotlin Multiplatform application Dependency injection

Anna Zharkova 12 Jul 27, 2021
Kotlin Multiplatform Mobile App Template

KMMT : Kotlin Multiplatform Mobile Template Kotlin Multiplatform Mobile Development Simplified KMMT is a KMM based project template designed to simpli

Jitty Andiyan 117 Jul 19, 2021
BuildConfig for Kotlin Multiplatform Project

BuildKonfig BuildConfig for Kotlin Multiplatform Project. It currently supports embedding values from gradle file. Table Of Contents Motivation Usage

Yasuhiro SHIMIZU 187 Jul 28, 2021
DI can be simple. Forget about modules and components. Just use it!

PopKorn - Kotlin Multiplatform DI PopKorn is a simple, powerful and lightweight Kotlin Multiplatform Dependency Injector. It doesn't need any modules

Pau Corbella 109 May 22, 2021
KaMP Kit by Touchlab is a collection of code and tools designed to get your mobile team started quickly with Kotlin Multiplatform.

KaMP Kit Welcome to the KaMP Kit! About Goal The goal of the KaMP Kit is to facilitate your evaluation of Kotlin Multiplatform (aka KMP). It is a coll

Touchlab 1.2k Aug 2, 2021
Kotlin Multiplatform project that gets network data from Food2Fork.ca

Food2Fork Recipe App This is the codebase for a Kotlin Multiplatform Mobile course. [Watch the course](https://codingwithmitch.com/courses/kotlin-mult

Mitch Tabian 181 Jul 24, 2021
A Bluetooth kotlin multiplatform "Cross-Platform" library for iOS and Android

Blue-Falcon A Bluetooth "Cross Platform" Kotlin Multiplatform library for iOS, Android, MacOS, Raspberry Pi and Javascript. Bluetooth in general has t

Andrew Reed 146 Jul 24, 2021
A collection of hand-crafted extensions for your Kotlin projects.

Splitties Splitties is a collection of small Kotlin multiplatform libraries (with Android as first target). These libraries are intended to reduce the

Louis CAD 1.8k Aug 4, 2021
The most essential libraries for Kotlin Multiplatform development

Essenty The most essential libraries for Kotlin Multiplatform development. Supported targets: android jvm js (IR and LEGACY) iosArm64, iosX64 watchosA

Arkadii Ivanov 13 Aug 2, 2021
Design Patterns implemented in Kotlin

Design Patterns In Kotlin ⚠️ New article about testing: Unit Testing with Mockito 2 Project maintained by @dbacinski (Dariusz Baciński) Inspired by De

Dariusz Baciński 4.8k Jul 28, 2021
Opinionated Redux-like implementation backed by Kotlin Coroutines and Kotlin Multiplatform Mobile

CoRed CoRed is Redux-like implementation that maintains the benefits of Redux's core idea without the boilerplate. No more action types, action creato

Kittinun Vantasin 16 Aug 1, 2021
GraphQL based Jetpack Compose and SwiftUI Kotlin Multiplatform sample

GraphQL based Jetpack Compose and SwiftUI Kotlin Multiplatform sample

John O'Reilly 60 Aug 5, 2021