New J2K: Add debug tree visitor and some tree elements

This commit is contained in:
Simon Ogorodnik
2017-10-13 02:34:12 +03:00
committed by Ilya Kirillov
parent 3ff0287c9f
commit 4f7c46741e
14 changed files with 267 additions and 55 deletions
@@ -18,21 +18,48 @@ package org.jetbrains.kotlin.j2k
import com.intellij.lang.java.JavaLanguage
import com.intellij.psi.*
import org.jetbrains.kotlin.j2k.tree.JKClass
import org.jetbrains.kotlin.j2k.tree.JKElement
import org.jetbrains.kotlin.j2k.tree.JKExpression
import org.jetbrains.kotlin.j2k.tree.impl.JKClassImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKElementBase
import org.jetbrains.kotlin.j2k.tree.impl.JKJavaFieldImpl
import com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class JavaToJKTreeBuilder {
private class ExpressionTreeVisitor : JavaElementVisitor() {
override fun visitElement(element: PsiElement) {
element.acceptChildren(this)
private var resultExpression: JKExpression? = null
override fun visitLiteralExpression(expression: PsiLiteralExpression?) {
if (expression is PsiLiteralExpressionImpl) {
when (expression.literalElementType) {
JavaTokenType.STRING_LITERAL ->
resultExpression = JKJavaStringLiteralExpressionImpl(expression.innerText!!)
}
}
}
fun extractExpression(): JKExpression? = object : JKElementBase(), JKExpression {}
fun result(): JKExpression = resultExpression!!
}
private object ModifierMapper {
fun PsiModifierList?.toJK(): JKModifierList {
val modifierList = JKModifierListImpl()
if (this == null) return modifierList
PsiModifier.MODIFIERS
.filter { hasExplicitModifier(it) }
.mapTo(modifierList.modifiers) { modifierToJK(it) }
return modifierList
}
fun modifierToJK(name: String): JKModifier = when (name) {
PsiModifier.PUBLIC -> JKJavaAccessModifierImpl(JKJavaAccessModifier.AccessModifierType.PUBLIC)
PsiModifier.PRIVATE -> JKJavaAccessModifierImpl(JKJavaAccessModifier.AccessModifierType.PRIVATE)
PsiModifier.PROTECTED -> JKJavaAccessModifierImpl(JKJavaAccessModifier.AccessModifierType.PROTECTED)
else -> TODO("Not yet supported")
}
}
private class ElementVisitor : JavaElementVisitor() {
@@ -44,23 +71,39 @@ class JavaToJKTreeBuilder {
var currentClass: JKClass? = null
override fun visitClass(aClass: PsiClass) {
currentClass = JKClassImpl()
val name = JKNameIdentifierImpl(aClass.name!!)
val modifierList = with(ModifierMapper) {
aClass.modifierList.toJK()
}
currentClass = JKClassImpl(modifierList, name)
super.visitClass(aClass)
}
override fun visitField(field: PsiField) {
val initializer = ExpressionTreeVisitor().also { field.initializer?.accept(it) }.extractExpression()
val initializer = field.initializer?.buildTreeForExpression()
currentClass!!.declarations += JKJavaFieldImpl(field.name!!, initializer)
val type = JKJavaTypeIdentifierImpl(field.type.canonicalText)
val name = JKNameIdentifierImpl(field.name!!)
currentClass!!.declarations += JKJavaFieldImpl(type, name, initializer)
super.visitField(field)
}
}
fun buildTree(psi: PsiElement): JKElement? {
assert(psi.language.`is`(JavaLanguage.INSTANCE)) { "Unable to build JK Tree using Java Visitor for language ${psi.language}" }
val elementVisitor = ElementVisitor()
psi.accept(elementVisitor)
return elementVisitor.currentClass
}
}
companion object {
private fun PsiExpression.buildTreeForExpression(): JKExpression =
JavaToJKTreeBuilder.ExpressionTreeVisitor().apply { accept(this) }.result()
}
}
@@ -20,10 +20,8 @@ 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.tree.JKClass
import org.jetbrains.kotlin.j2k.tree.JKElement
import org.jetbrains.kotlin.j2k.tree.JKJavaField
import org.jetbrains.kotlin.j2k.tree.JKJavaKtVisitorVoid
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.utils.Printer
class NewJavaToKotlinConverter(
private val project: Project,
@@ -38,26 +36,13 @@ class NewJavaToKotlinConverter(
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(tree.prettyDebugPrintTree())
appendln()
}
}
println(result)
return result
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.tree
import org.jetbrains.kotlin.utils.Printer
private class DebugTreePrinter : JKJavaKtVisitorVoid {
internal val stringBuilder = StringBuilder()
private val printer = Printer(stringBuilder)
override fun visitElement(element: JKElement) {
printer.println(element.classNameWithoutJK(), " [")
printer.indented {
element.acceptChildren(this, null)
}
printer.println("]")
}
}
private fun Any.classNameWithoutJK(): String = this.javaClass.simpleName.removePrefix("JK")
private inline fun Printer.indented(block: () -> Unit) {
this.pushIndent()
block()
this.popIndent()
}
fun JKElement.prettyDebugPrintTree(): String
= DebugTreePrinter().apply { accept(this, null) }.stringBuilder.toString()
@@ -4,4 +4,9 @@ interface JKJavaVisitor<R, D> : JKVisitor<R, D> {
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)
fun visitJavaAssignmentExpression(javaAssignmentExpression: JKJavaAssignmentExpression, data: D): R = visitExpression(javaAssignmentExpression, data)
fun visitJavaCall(javaCall: JKJavaCall, data: D): R = visitCall(javaCall, data)
fun visitJavaTypeIdentifier(javaTypeIdentifier: JKJavaTypeIdentifier, data: D): R = visitTypeIdentifier(javaTypeIdentifier, data)
fun visitJavaStringLiteralExpression(javaStringLiteralExpression: JKJavaStringLiteralExpression, data: D): R = visitLiteralExpression(javaStringLiteralExpression, data)
fun visitJavaAccessModifier(javaAccessModifier: JKJavaAccessModifier, data: D): R = visitAccessModifier(javaAccessModifier, data)
}
@@ -7,4 +7,14 @@ interface JKJavaVisitorVoid : JKJavaVisitor<Unit, Nothing?>, JKVisitorVoid {
override fun visitJavaMethod(javaMethod: JKJavaMethod, data: Nothing?) = visitJavaMethod(javaMethod)
fun visitJavaForLoop(javaForLoop: JKJavaForLoop) = visitLoop(javaForLoop, null)
override fun visitJavaForLoop(javaForLoop: JKJavaForLoop, data: Nothing?) = visitJavaForLoop(javaForLoop)
fun visitJavaAssignmentExpression(javaAssignmentExpression: JKJavaAssignmentExpression) = visitExpression(javaAssignmentExpression, null)
override fun visitJavaAssignmentExpression(javaAssignmentExpression: JKJavaAssignmentExpression, data: Nothing?) = visitJavaAssignmentExpression(javaAssignmentExpression)
fun visitJavaCall(javaCall: JKJavaCall) = visitCall(javaCall, null)
override fun visitJavaCall(javaCall: JKJavaCall, data: Nothing?) = visitJavaCall(javaCall)
fun visitJavaTypeIdentifier(javaTypeIdentifier: JKJavaTypeIdentifier) = visitTypeIdentifier(javaTypeIdentifier, null)
override fun visitJavaTypeIdentifier(javaTypeIdentifier: JKJavaTypeIdentifier, data: Nothing?) = visitJavaTypeIdentifier(javaTypeIdentifier)
fun visitJavaStringLiteralExpression(javaStringLiteralExpression: JKJavaStringLiteralExpression) = visitLiteralExpression(javaStringLiteralExpression, null)
override fun visitJavaStringLiteralExpression(javaStringLiteralExpression: JKJavaStringLiteralExpression, data: Nothing?) = visitJavaStringLiteralExpression(javaStringLiteralExpression)
fun visitJavaAccessModifier(javaAccessModifier: JKJavaAccessModifier) = visitAccessModifier(javaAccessModifier, null)
override fun visitJavaAccessModifier(javaAccessModifier: JKJavaAccessModifier, data: Nothing?) = visitJavaAccessModifier(javaAccessModifier)
}
@@ -4,4 +4,6 @@ interface JKKtVisitor<R, D> : JKVisitor<R, D> {
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)
fun visitKtAssignmentStatement(ktAssignmentStatement: JKKtAssignmentStatement, data: D): R = visitStatement(ktAssignmentStatement, data)
fun visitKtCall(ktCall: JKKtCall, data: D): R = visitCall(ktCall, data)
}
@@ -7,4 +7,8 @@ interface JKKtVisitorVoid : JKKtVisitor<Unit, Nothing?>, JKVisitorVoid {
override fun visitKtConstructor(ktConstructor: JKKtConstructor, data: Nothing?) = visitKtConstructor(ktConstructor)
fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor) = visitKtConstructor(ktPrimaryConstructor, null)
override fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor, data: Nothing?) = visitKtPrimaryConstructor(ktPrimaryConstructor)
fun visitKtAssignmentStatement(ktAssignmentStatement: JKKtAssignmentStatement) = visitStatement(ktAssignmentStatement, null)
override fun visitKtAssignmentStatement(ktAssignmentStatement: JKKtAssignmentStatement, data: Nothing?) = visitKtAssignmentStatement(ktAssignmentStatement)
fun visitKtCall(ktCall: JKKtCall) = visitCall(ktCall, null)
override fun visitKtCall(ktCall: JKKtCall, data: Nothing?) = visitKtCall(ktCall)
}
@@ -3,9 +3,17 @@ package org.jetbrains.kotlin.j2k.tree
interface JKVisitor<R, D> {
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 visitExpression(expression: JKExpression, data: D): R = visitStatement(expression, data)
fun visitLoop(loop: JKLoop, data: D): R = visitStatement(loop, data)
fun visitDeclaration(declaration: JKDeclaration, data: D): R = visitElement(declaration, data)
fun visitBlock(block: JKBlock, data: D): R = visitElement(block, data)
fun visitCall(call: JKCall, data: D): R = visitExpression(call, data)
fun visitIdentifier(identifier: JKIdentifier, data: D): R = visitElement(identifier, data)
fun visitTypeIdentifier(typeIdentifier: JKTypeIdentifier, data: D): R = visitIdentifier(typeIdentifier, data)
fun visitNameIdentifier(nameIdentifier: JKNameIdentifier, data: D): R = visitIdentifier(nameIdentifier, data)
fun visitLiteralExpression(literalExpression: JKLiteralExpression, data: D): R = visitExpression(literalExpression, data)
fun visitModifierList(modifierList: JKModifierList, data: D): R = visitElement(modifierList, data)
fun visitModifier(modifier: JKModifier, data: D): R = visitElement(modifier, data)
fun visitAccessModifier(accessModifier: JKAccessModifier, data: D): R = visitModifier(accessModifier, data)
}
@@ -5,14 +5,30 @@ interface JKVisitorVoid : JKVisitor<Unit, Nothing?> {
override fun visitElement(element: JKElement, data: Nothing?) = visitElement(element)
fun visitClass(klass: JKClass) = visitDeclaration(klass, null)
override fun visitClass(klass: JKClass, data: Nothing?) = visitClass(klass)
fun visitExpression(expression: JKExpression) = visitElement(expression, null)
override fun visitExpression(expression: JKExpression, data: Nothing?) = visitExpression(expression)
fun visitStatement(statement: JKStatement) = visitElement(statement, null)
override fun visitStatement(statement: JKStatement, data: Nothing?) = visitStatement(statement)
fun visitExpression(expression: JKExpression) = visitStatement(expression, null)
override fun visitExpression(expression: JKExpression, data: Nothing?) = visitExpression(expression)
fun visitLoop(loop: JKLoop) = visitStatement(loop, null)
override fun visitLoop(loop: JKLoop, data: Nothing?) = visitLoop(loop)
fun visitDeclaration(declaration: JKDeclaration) = visitElement(declaration, null)
override fun visitDeclaration(declaration: JKDeclaration, data: Nothing?) = visitDeclaration(declaration)
fun visitBlock(block: JKBlock) = visitElement(block, null)
override fun visitBlock(block: JKBlock, data: Nothing?) = visitBlock(block)
fun visitCall(call: JKCall) = visitExpression(call, null)
override fun visitCall(call: JKCall, data: Nothing?) = visitCall(call)
fun visitIdentifier(identifier: JKIdentifier) = visitElement(identifier, null)
override fun visitIdentifier(identifier: JKIdentifier, data: Nothing?) = visitIdentifier(identifier)
fun visitTypeIdentifier(typeIdentifier: JKTypeIdentifier) = visitIdentifier(typeIdentifier, null)
override fun visitTypeIdentifier(typeIdentifier: JKTypeIdentifier, data: Nothing?) = visitTypeIdentifier(typeIdentifier)
fun visitNameIdentifier(nameIdentifier: JKNameIdentifier) = visitIdentifier(nameIdentifier, null)
override fun visitNameIdentifier(nameIdentifier: JKNameIdentifier, data: Nothing?) = visitNameIdentifier(nameIdentifier)
fun visitLiteralExpression(literalExpression: JKLiteralExpression) = visitExpression(literalExpression, null)
override fun visitLiteralExpression(literalExpression: JKLiteralExpression, data: Nothing?) = visitLiteralExpression(literalExpression)
fun visitModifierList(modifierList: JKModifierList) = visitElement(modifierList, null)
override fun visitModifierList(modifierList: JKModifierList, data: Nothing?) = visitModifierList(modifierList)
fun visitModifier(modifier: JKModifier) = visitElement(modifier, null)
override fun visitModifier(modifier: JKModifier, data: Nothing?) = visitModifier(modifier)
fun visitAccessModifier(accessModifier: JKAccessModifier) = visitModifier(accessModifier, null)
override fun visitAccessModifier(accessModifier: JKAccessModifier, data: Nothing?) = visitAccessModifier(accessModifier)
}
@@ -16,12 +16,10 @@
package org.jetbrains.kotlin.j2k.tree.impl
import org.jetbrains.kotlin.j2k.tree.JKExpression
import org.jetbrains.kotlin.j2k.tree.JKJavaField
import org.jetbrains.kotlin.j2k.tree.JKJavaVisitor
import org.jetbrains.kotlin.j2k.tree.JKVisitor
import org.jetbrains.kotlin.j2k.tree.*
class JKJavaFieldImpl(override val name: String,
class JKJavaFieldImpl(override var type: JKTypeIdentifier,
override var name: JKNameIdentifier,
override var initializer: JKExpression?) : JKJavaField, JKElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R {
@@ -34,5 +32,41 @@ class JKJavaFieldImpl(override val name: String,
}
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D)
= initializer?.accept(visitor, data) ?: Unit
= listOfNotNull(type, name, initializer).forEach { it.accept(visitor, data) }
}
class JKJavaTypeIdentifierImpl(override val typeName: String) : JKJavaTypeIdentifier, JKElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R {
return if (visitor is JKJavaVisitor) {
visitor.visitJavaTypeIdentifier(this, data)
}
else {
visitor.visitTypeIdentifier(this, data)
}
}
}
class JKJavaStringLiteralExpressionImpl(override val text: String) : JKJavaStringLiteralExpression, JKElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R {
return if (visitor is JKJavaVisitor) {
visitor.visitJavaStringLiteralExpression(this, data)
}
else {
visitor.visitLiteralExpression(this, data)
}
}
}
class JKJavaAccessModifierImpl(override val type: JKJavaAccessModifier.AccessModifierType) : JKJavaAccessModifier, JKElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R {
return if (visitor is JKJavaVisitor) {
visitor.visitJavaAccessModifier(this, data)
}
else {
visitor.visitAccessModifier(this, data)
}
}
}
@@ -16,10 +16,7 @@
package org.jetbrains.kotlin.j2k.tree.impl
import org.jetbrains.kotlin.j2k.tree.JKClass
import org.jetbrains.kotlin.j2k.tree.JKDeclaration
import org.jetbrains.kotlin.j2k.tree.JKElement
import org.jetbrains.kotlin.j2k.tree.JKVisitor
import org.jetbrains.kotlin.j2k.tree.*
abstract class JKElementBase : JKElement {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitElement(this, data)
@@ -27,12 +24,29 @@ abstract class JKElementBase : JKElement {
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {}
}
class JKClassImpl : JKClass, JKElementBase() {
class JKClassImpl(override var modifierList: JKModifierList, override var name: JKNameIdentifier) : JKClass, JKElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitClass(this, data)
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {
declarations.forEach { it.accept(visitor, data) }
(listOf(modifierList, name) + declarations).forEach { it.accept(visitor, data) }
}
override val declarations = mutableListOf<JKDeclaration>()
}
class JKNameIdentifierImpl(override val name: String) : JKNameIdentifier, JKElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitNameIdentifier(this, data)
}
class JKModifierListImpl : JKModifierList, JKElementBase() {
override val modifiers = mutableListOf<JKModifier>()
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitModifierList(this, data)
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {
modifiers.forEach { it.accept(visitor, data) }
}
}
+23 -2
View File
@@ -17,10 +17,31 @@
package org.jetbrains.kotlin.j2k.tree
interface JKJavaField : JKDeclaration {
val name: String
var type: JKTypeIdentifier
var name: JKNameIdentifier
var initializer: JKExpression?
}
interface JKJavaMethod : JKDeclaration
interface JKJavaForLoop : JKLoop
interface JKJavaForLoop : JKLoop
interface JKJavaAssignmentExpression : JKExpression
interface JKJavaCall : JKCall
interface JKJavaTypeIdentifier : JKTypeIdentifier {
val typeName: String
}
interface JKJavaStringLiteralExpression : JKLiteralExpression {
val text: String
}
interface JKJavaAccessModifier : JKAccessModifier {
val type: AccessModifierType
enum class AccessModifierType {
PUBLIC, PROTECTED, PRIVATE
}
}
+24 -2
View File
@@ -24,15 +24,37 @@ interface JKElement {
}
interface JKClass : JKDeclaration {
var modifierList: JKModifierList
var name: JKNameIdentifier
val declarations: MutableList<JKDeclaration>
}
interface JKExpression : JKElement
interface JKStatement : JKElement
interface JKExpression : JKStatement
interface JKLoop : JKStatement
interface JKDeclaration : JKElement
interface JKBlock : JKElement
interface JKCall : JKExpression
interface JKIdentifier : JKElement
interface JKTypeIdentifier : JKIdentifier
interface JKNameIdentifier : JKIdentifier {
val name: String
}
interface JKLiteralExpression : JKExpression
interface JKModifierList : JKElement {
val modifiers: MutableList<JKModifier>
}
interface JKModifier : JKElement
interface JKAccessModifier : JKModifier
@@ -16,8 +16,12 @@
package org.jetbrains.kotlin.j2k.tree
interface JKKtFun: JKDeclaration
interface JKKtFun : JKDeclaration
interface JKKtConstructor: JKDeclaration
interface JKKtConstructor : JKDeclaration
interface JKKtPrimaryConstructor: JKKtConstructor
interface JKKtPrimaryConstructor : JKKtConstructor
interface JKKtAssignmentStatement : JKStatement
interface JKKtCall : JKCall