111 lines
3.7 KiB
Kotlin
111 lines
3.7 KiB
Kotlin
/*
|
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
*/
|
|
|
|
import java.io.File
|
|
|
|
|
|
private val JK_ROOT = File("./nj2k/src/org/jetbrains/kotlin/nj2k/tree")
|
|
|
|
private val JK_OUT_ROOT = File(JK_ROOT, "visitors")
|
|
|
|
private val JK_TREE_FILES = listOf(
|
|
"declarations.kt",
|
|
"elements.kt",
|
|
"expressions.kt",
|
|
"modifiers.kt",
|
|
"statements.kt"
|
|
).map { File(JK_ROOT, it) }
|
|
|
|
|
|
val elementRegex = """(class|object)\s+(JK[\w]+)(\([\w\s:,<>=\(\)\\]+\))?\s*:\s*(JK[a-zA-Z]+)""".toRegex()
|
|
|
|
|
|
data class InterfaceData(val name: String, val extends: String?)
|
|
|
|
fun File.interfaceNames() =
|
|
sequenceOf(this)
|
|
.map { it.readText() }
|
|
.flatMap { elementRegex.findAll(it) }
|
|
.map { match ->
|
|
InterfaceData(
|
|
match.groupValues[2],
|
|
match.groupValues[4].let { if (it == "JKAnnotationMemberValue") "JKTreeElement" else it }
|
|
)
|
|
}.toList()
|
|
|
|
|
|
fun String.safeVarName() = when (this) {
|
|
"class" -> "klass"
|
|
else -> this
|
|
}
|
|
|
|
fun genVisitors(
|
|
interfaceData: List<InterfaceData>,
|
|
visitorName: String
|
|
) {
|
|
val pkg = "package org.jetbrains.kotlin.nj2k.tree.visitors"
|
|
|
|
File(JK_OUT_ROOT, "$visitorName.kt").writeText(buildString {
|
|
appendln(pkg)
|
|
appendln()
|
|
appendln("import org.jetbrains.kotlin.nj2k.tree.*")
|
|
appendln()
|
|
appendln("abstract class $visitorName {")
|
|
interfaceData.joinTo(this, separator = "\n") { (name, ext) ->
|
|
val nameWithoutPrefix = name.removePrefix("JK")
|
|
val argName = nameWithoutPrefix.decapitalize().safeVarName()
|
|
val generifyCall = if (name != "JKTreeElement") "= visit${ext?.removePrefix("JK") ?: error(name)}($argName)" else ""
|
|
val modifier = if (name == "JKTreeElement") "abstract" else "open"
|
|
"""
|
|
| $modifier fun visit$nameWithoutPrefix($argName: $name) $generifyCall
|
|
""".trimMargin()
|
|
}
|
|
appendln()
|
|
appendln("}")
|
|
})
|
|
|
|
|
|
File(JK_OUT_ROOT, "${visitorName}WithCommentsPrinting.kt").writeText(buildString {
|
|
appendln(pkg)
|
|
appendln()
|
|
appendln("import org.jetbrains.kotlin.nj2k.tree.*")
|
|
appendln()
|
|
|
|
appendln("abstract class ${visitorName}WithCommentsPrinting : $visitorName() {")
|
|
appendln(
|
|
"""
|
|
| abstract fun printLeftNonCodeElements(element: JKNonCodeElementsListOwner)
|
|
| abstract fun printRightNonCodeElements(element: JKNonCodeElementsListOwner)
|
|
|
|
|
""".trimMargin()
|
|
)
|
|
|
|
interfaceData.joinTo(this, separator = "\n\n") { (name, ext) ->
|
|
val nameWithoutPrefix = name.removePrefix("JK")
|
|
val argName = nameWithoutPrefix.decapitalize().safeVarName()
|
|
val arg = "$argName: $name"
|
|
val rawVisitSuffix = "Raw"
|
|
val generifyCall = if (name != "JKTreeElement") "= visit${ext!!.removePrefix("JK")}$rawVisitSuffix($argName)" else ""
|
|
val modifier = if (name == "JKTreeElement") "abstract" else "open"
|
|
"""
|
|
| final override fun visit$nameWithoutPrefix($arg) {
|
|
| printLeftNonCodeElements($argName)
|
|
| visit$nameWithoutPrefix$rawVisitSuffix($argName)
|
|
| printRightNonCodeElements($argName)
|
|
| }
|
|
|
|
|
| $modifier fun visit$nameWithoutPrefix$rawVisitSuffix($arg) $generifyCall
|
|
""".trimMargin()
|
|
}
|
|
appendln()
|
|
appendln("}")
|
|
})
|
|
}
|
|
|
|
fun main() {
|
|
genVisitors(JK_TREE_FILES.flatMap { it.interfaceNames() }, "JKVisitor")
|
|
}
|
|
|