New J2K: Implement basic output generation

This commit is contained in:
Simon Ogorodnik
2017-10-12 02:33:54 +03:00
committed by Ilya Kirillov
parent 5fd3a78dbe
commit 66d6ac745f
16 changed files with 85 additions and 106 deletions
+13 -10
View File
@@ -40,14 +40,16 @@ val JK_JAVA_FILE = File(JK_ROOT, "j.kt")
val JK_COMMON_FILE = File(JK_ROOT, "jk.kt")
val interfaceRegex = "interface (JK[a-zA-Z]+)".toRegex()
val interfaceRegex = "interface (JK[a-zA-Z]+)\\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 { interfaceRegex.findAll(it) }
.map { match -> match.groupValues[1] }
.map { match -> InterfaceData(match.groupValues[1], match.groupValues.getOrNull(2)) }
.toList()
@@ -56,7 +58,7 @@ fun String.safeVarName() = when (this) {
else -> this
}
fun genVisitors(interfaceNames: List<String>, visitorName: String, extends: String = "") {
fun genVisitors(interfaceData: List<InterfaceData>, visitorName: String, extends: String = "") {
val outFile = File(JK_ROOT, "$visitorName.kt")
@@ -65,30 +67,33 @@ fun genVisitors(interfaceNames: List<String>, visitorName: String, extends: Stri
appendln()
val extends = if (extends.isNotBlank()) ": $extends<R, D>" else ""
appendln("interface $visitorName<R, D> $extends {")
interfaceNames.joinTo(this, separator = "\n") { name ->
interfaceData.joinTo(this, separator = "\n") { (name, ext) ->
val nameWithoutPrefix = name.removePrefix("JK")
val argName = nameWithoutPrefix.decapitalize().safeVarName()
val generifyCall = if (name != "JKElement") "= visit${ext!!.removePrefix("JK")}($argName, data)" else ""
"""
| fun visit$nameWithoutPrefix(${nameWithoutPrefix.decapitalize().safeVarName()}: $name, data: D): R
| fun visit$nameWithoutPrefix($argName: $name, data: D): R $generifyCall
""".trimMargin()
}
appendln()
appendln("}")
})
val outVoidFile = File(JK_ROOT, "${visitorName}Void.kt")
outVoidFile.writeText(buildString {
appendln("package org.jetbrains.kotlin.j2k.tree")
appendln()
val extends = if (extends.isNotBlank()) ", ${extends}Void" else ""
appendln("interface ${visitorName}Void : $visitorName<Unit, Nothing?>$extends {")
interfaceNames.joinTo(this, separator = "\n") { name ->
interfaceData.joinTo(this, separator = "\n") { (name, ext) ->
val nameWithoutPrefix = name.removePrefix("JK")
val argName = nameWithoutPrefix.decapitalize().safeVarName()
val arg = "$argName: $name"
val generifyCall = if (name != "JKElement") "= visit${ext!!.removePrefix("JK")}($argName, null)" else ""
"""
| fun visit$nameWithoutPrefix($arg)
| fun visit$nameWithoutPrefix($arg) $generifyCall
| override fun visit$nameWithoutPrefix($arg, data: Nothing?) = visit$nameWithoutPrefix($argName)
""".trimMargin()
}
@@ -101,11 +106,9 @@ fun genVisitors(interfaceNames: List<String>, visitorName: String, extends: Stri
genVisitors(JK_COMMON_FILE.interfaceNames(), "JKVisitor")
genVisitors(JK_JAVA_FILE.interfaceNames(), "JKJavaVisitor", "JKVisitor")
genVisitors(JK_KT_FILE.interfaceNames(), "JKKtVisitor", "JKVisitor")
genVisitors(JK_JAVA_FILE.interfaceNames() + JK_KT_FILE.interfaceNames(), "JKJavaKtVisitor", "JKVisitor")
/* JKKtVisitor<R,D> : JKVisitor<R,D> + Void
JKJavaVisitor<R,D> : JKVisitor<R,D> + Void
JKJavaKtVisitor<R, D> : JKVisitor<R,D> + Void
*/
//val visitNames =
@@ -28,10 +28,12 @@ import org.jetbrains.kotlin.j2k.tree.impl.JKJavaFieldImpl
class JavaToJKTreeBuilder {
private class ElementVisitor : JavaElementVisitor() {
override fun visitElement(element: PsiElement) {
element.acceptChildren(this)
}
var currentClass: JKClass? = null
override fun visitClass(aClass: PsiClass) {
@@ -40,7 +42,7 @@ class JavaToJKTreeBuilder {
}
override fun visitField(field: PsiField) {
currentClass!!.declarations.add(JKJavaFieldImpl(field.name!!))
currentClass!!.declarations += JKJavaFieldImpl(field.name!!)
super.visitField(field)
}
}
@@ -20,17 +20,44 @@ import com.intellij.openapi.progress.EmptyProgressIndicator
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiJavaFile
import org.jetbrains.kotlin.j2k.ConverterSettings
import org.jetbrains.kotlin.j2k.tree.JKClass
import org.jetbrains.kotlin.j2k.tree.JKElement
import org.jetbrains.kotlin.j2k.tree.JKJavaField
import org.jetbrains.kotlin.j2k.tree.JKJavaKtVisitorVoid
class NewJavaToKotlinConverter(
private val project: Project,
private val settings: ConverterSettings
) {
fun filesToKotlin(files: List<PsiJavaFile>, progressIndicator: ProgressIndicator = EmptyProgressIndicator()): Nothing {
fun filesToKotlin(files: List<PsiJavaFile>, progressIndicator: ProgressIndicator = EmptyProgressIndicator()): String {
val treeBuilder = JavaToJKTreeBuilder()
val fileTrees = files.map(treeBuilder::buildTree)
TODO("Output generation")
val result = buildString {
for (tree in fileTrees.filterNotNull()) {
appendln()
tree.accept(object : JKJavaKtVisitorVoid {
override fun visitElement(element: JKElement) {
element.acceptChildren(this, null)
}
override fun visitClass(klass: JKClass) {
appendln("class")
super.visitClass(klass)
}
override fun visitJavaField(javaField: JKJavaField, data: Nothing?) {
appendln("java field ${javaField.name}")
super.visitJavaField(javaField, data)
}
}, null)
appendln()
}
}
return result
}
}
@@ -1,12 +1,3 @@
package org.jetbrains.kotlin.j2k.tree
interface JKJavaKtVisitor<R, D> : JKVisitor<R, D> {
fun visitJavaElement(javaElement: JKJavaElement, data: D): R
fun visitJavaField(javaField: JKJavaField, data: D): R
fun visitJavaMethod(javaMethod: JKJavaMethod, data: D): R
fun visitJavaForLoop(javaForLoop: JKJavaForLoop, data: D): R
fun visitKtElement(ktElement: JKKtElement, data: D): R
fun visitKtFun(ktFun: JKKtFun, data: D): R
fun visitKtConstructor(ktConstructor: JKKtConstructor, data: D): R
fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor, data: D): R
}
interface JKJavaKtVisitor<R, D> : JKJavaVisitor<R, D>, JKKtVisitor<R, D>
@@ -1,20 +1,3 @@
package org.jetbrains.kotlin.j2k.tree
interface JKJavaKtVisitorVoid : JKJavaKtVisitor<Unit, Nothing?>, JKVisitorVoid {
fun visitJavaElement(javaElement: JKJavaElement)
override fun visitJavaElement(javaElement: JKJavaElement, data: Nothing?) = visitJavaElement(javaElement)
fun visitJavaField(javaField: JKJavaField)
override fun visitJavaField(javaField: JKJavaField, data: Nothing?) = visitJavaField(javaField)
fun visitJavaMethod(javaMethod: JKJavaMethod)
override fun visitJavaMethod(javaMethod: JKJavaMethod, data: Nothing?) = visitJavaMethod(javaMethod)
fun visitJavaForLoop(javaForLoop: JKJavaForLoop)
override fun visitJavaForLoop(javaForLoop: JKJavaForLoop, data: Nothing?) = visitJavaForLoop(javaForLoop)
fun visitKtElement(ktElement: JKKtElement)
override fun visitKtElement(ktElement: JKKtElement, data: Nothing?) = visitKtElement(ktElement)
fun visitKtFun(ktFun: JKKtFun)
override fun visitKtFun(ktFun: JKKtFun, data: Nothing?) = visitKtFun(ktFun)
fun visitKtConstructor(ktConstructor: JKKtConstructor)
override fun visitKtConstructor(ktConstructor: JKKtConstructor, data: Nothing?) = visitKtConstructor(ktConstructor)
fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor)
override fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor, data: Nothing?) = visitKtPrimaryConstructor(ktPrimaryConstructor)
}
interface JKJavaKtVisitorVoid : JKJavaKtVisitor<Unit, Nothing?>, JKJavaVisitorVoid, JKKtVisitorVoid
@@ -1,8 +1,7 @@
package org.jetbrains.kotlin.j2k.tree
interface JKJavaVisitor<R, D> : JKVisitor<R, D> {
fun visitJavaElement(javaElement: JKJavaElement, data: D): R
fun visitJavaField(javaField: JKJavaField, data: D): R
fun visitJavaMethod(javaMethod: JKJavaMethod, data: D): R
fun visitJavaForLoop(javaForLoop: JKJavaForLoop, data: D): R
fun visitJavaField(javaField: JKJavaField, data: D): R = visitDeclaration(javaField, data)
fun visitJavaMethod(javaMethod: JKJavaMethod, data: D): R = visitDeclaration(javaMethod, data)
fun visitJavaForLoop(javaForLoop: JKJavaForLoop, data: D): R = visitLoop(javaForLoop, data)
}
@@ -1,12 +1,10 @@
package org.jetbrains.kotlin.j2k.tree
interface JKJavaVisitorVoid : JKJavaVisitor<Unit, Nothing?>, JKVisitorVoid {
fun visitJavaElement(javaElement: JKJavaElement)
override fun visitJavaElement(javaElement: JKJavaElement, data: Nothing?) = visitJavaElement(javaElement)
fun visitJavaField(javaField: JKJavaField)
fun visitJavaField(javaField: JKJavaField) = visitDeclaration(javaField, null)
override fun visitJavaField(javaField: JKJavaField, data: Nothing?) = visitJavaField(javaField)
fun visitJavaMethod(javaMethod: JKJavaMethod)
fun visitJavaMethod(javaMethod: JKJavaMethod) = visitDeclaration(javaMethod, null)
override fun visitJavaMethod(javaMethod: JKJavaMethod, data: Nothing?) = visitJavaMethod(javaMethod)
fun visitJavaForLoop(javaForLoop: JKJavaForLoop)
fun visitJavaForLoop(javaForLoop: JKJavaForLoop) = visitLoop(javaForLoop, null)
override fun visitJavaForLoop(javaForLoop: JKJavaForLoop, data: Nothing?) = visitJavaForLoop(javaForLoop)
}
@@ -1,8 +1,7 @@
package org.jetbrains.kotlin.j2k.tree
interface JKKtVisitor<R, D> : JKVisitor<R, D> {
fun visitKtElement(ktElement: JKKtElement, data: D): R
fun visitKtFun(ktFun: JKKtFun, data: D): R
fun visitKtConstructor(ktConstructor: JKKtConstructor, data: D): R
fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor, data: D): R
fun visitKtFun(ktFun: JKKtFun, data: D): R = visitDeclaration(ktFun, data)
fun visitKtConstructor(ktConstructor: JKKtConstructor, data: D): R = visitDeclaration(ktConstructor, data)
fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor, data: D): R = visitKtConstructor(ktPrimaryConstructor, data)
}
@@ -1,12 +1,10 @@
package org.jetbrains.kotlin.j2k.tree
interface JKKtVisitorVoid : JKKtVisitor<Unit, Nothing?>, JKVisitorVoid {
fun visitKtElement(ktElement: JKKtElement)
override fun visitKtElement(ktElement: JKKtElement, data: Nothing?) = visitKtElement(ktElement)
fun visitKtFun(ktFun: JKKtFun)
fun visitKtFun(ktFun: JKKtFun) = visitDeclaration(ktFun, null)
override fun visitKtFun(ktFun: JKKtFun, data: Nothing?) = visitKtFun(ktFun)
fun visitKtConstructor(ktConstructor: JKKtConstructor)
fun visitKtConstructor(ktConstructor: JKKtConstructor) = visitDeclaration(ktConstructor, null)
override fun visitKtConstructor(ktConstructor: JKKtConstructor, data: Nothing?) = visitKtConstructor(ktConstructor)
fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor)
fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor) = visitKtConstructor(ktPrimaryConstructor, null)
override fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor, data: Nothing?) = visitKtPrimaryConstructor(ktPrimaryConstructor)
}
@@ -1,11 +1,10 @@
package org.jetbrains.kotlin.j2k.tree
interface JKVisitor<R, D> {
fun visitElement(element: JKElement, data: D): R
fun visitClass(klass: JKClass, data: D): R
fun visitMember(member: JKMember, data: D): R
fun visitExpression(expression: JKExpression, data: D): R
fun visitStatement(statement: JKStatement, data: D): R
fun visitLoop(loop: JKLoop, data: D): R
fun visitDeclaration(declaration: JKDeclaration, data: D): R
fun visitElement(element: JKElement, data: D): R
fun visitClass(klass: JKClass, data: D): R = visitDeclaration(klass, data)
fun visitExpression(expression: JKExpression, data: D): R = visitElement(expression, data)
fun visitStatement(statement: JKStatement, data: D): R = visitElement(statement, data)
fun visitLoop(loop: JKLoop, data: D): R = visitStatement(loop, data)
fun visitDeclaration(declaration: JKDeclaration, data: D): R = visitElement(declaration, data)
}
@@ -1,18 +1,16 @@
package org.jetbrains.kotlin.j2k.tree
interface JKVisitorVoid : JKVisitor<Unit, Nothing?> {
fun visitElement(element: JKElement)
fun visitElement(element: JKElement)
override fun visitElement(element: JKElement, data: Nothing?) = visitElement(element)
fun visitClass(klass: JKClass)
fun visitClass(klass: JKClass) = visitDeclaration(klass, null)
override fun visitClass(klass: JKClass, data: Nothing?) = visitClass(klass)
fun visitMember(member: JKMember)
override fun visitMember(member: JKMember, data: Nothing?) = visitMember(member)
fun visitExpression(expression: JKExpression)
fun visitExpression(expression: JKExpression) = visitElement(expression, null)
override fun visitExpression(expression: JKExpression, data: Nothing?) = visitExpression(expression)
fun visitStatement(statement: JKStatement)
fun visitStatement(statement: JKStatement) = visitElement(statement, null)
override fun visitStatement(statement: JKStatement, data: Nothing?) = visitStatement(statement)
fun visitLoop(loop: JKLoop)
fun visitLoop(loop: JKLoop) = visitStatement(loop, null)
override fun visitLoop(loop: JKLoop, data: Nothing?) = visitLoop(loop)
fun visitDeclaration(declaration: JKDeclaration)
fun visitDeclaration(declaration: JKDeclaration) = visitElement(declaration, null)
override fun visitDeclaration(declaration: JKDeclaration, data: Nothing?) = visitDeclaration(declaration)
}
@@ -16,26 +16,12 @@
package org.jetbrains.kotlin.j2k.tree.impl
import org.jetbrains.kotlin.j2k.tree.JKJavaElement
import org.jetbrains.kotlin.j2k.tree.JKJavaField
import org.jetbrains.kotlin.j2k.tree.JKJavaVisitor
import org.jetbrains.kotlin.j2k.tree.JKVisitor
abstract class JKJavaElementBase : JKJavaElement {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R {
return if (visitor is JKJavaVisitor) {
visitor.visitJavaElement(this, data)
}
else {
visitor.visitElement(this, data)
}
}
class JKJavaFieldImpl(override val name: String) : JKJavaField, JKElementBase() {
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {}
}
class JKJavaFieldImpl(val name: String) : JKJavaField, JKJavaElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R {
return if (visitor is JKJavaVisitor) {
visitor.visitJavaField(this, data)
@@ -16,10 +16,10 @@
package org.jetbrains.kotlin.j2k.tree
interface JKJavaElement : JKElement
interface JKJavaField : JKDeclaration {
val name: String
}
interface JKJavaField : JKJavaElement, JKDeclaration, JKMember
interface JKJavaMethod : JKDeclaration
interface JKJavaMethod : JKJavaElement, JKDeclaration, JKMember
interface JKJavaForLoop : JKJavaElement, JKLoop
interface JKJavaForLoop : JKLoop
@@ -23,12 +23,10 @@ interface JKElement {
fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D)
}
interface JKClass : JKElement {
interface JKClass : JKDeclaration {
val declarations: MutableList<JKDeclaration>
}
interface JKMember : JKElement
interface JKExpression : JKElement
interface JKStatement : JKElement
@@ -16,10 +16,8 @@
package org.jetbrains.kotlin.j2k.tree
interface JKKtElement: JKElement
interface JKKtFun: JKDeclaration
interface JKKtFun: JKKtElement, JKDeclaration
interface JKKtConstructor: JKDeclaration
interface JKKtConstructor: JKKtElement, JKDeclaration
interface JKKtPrimaryConstructor: JKKtElement, JKKtConstructor
interface JKKtPrimaryConstructor: JKKtConstructor
@@ -22,6 +22,6 @@ abstract class AbstractNewJavaToKotlinConverterSingleFileTest : AbstractJavaToKo
override fun fileToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val file = createJavaFile(text)
NewJavaToKotlinConverter(project, settings).filesToKotlin(listOf(file))
return NewJavaToKotlinConverter(project, settings).filesToKotlin(listOf(file))
}
}