New J2K: WIP: Introduce symbols instead of references

This commit is contained in:
Simon Ogorodnik
2018-05-16 01:00:03 +03:00
committed by Ilya Kirillov
parent 4b3fdbcb0b
commit edd23c7a83
10 changed files with 141 additions and 176 deletions
@@ -23,41 +23,10 @@ import com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl
import com.intellij.psi.impl.source.tree.java.PsiNewExpressionImpl
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.multiverse.JKMDeclarationList
import org.jetbrains.kotlin.j2k.tree.multiverse.JKMultiverseClass
import org.jetbrains.kotlin.j2k.tree.multiverse.ReferenceTargetProvider
import org.jetbrains.kotlin.j2k.tree.impl.*
class JavaToJKTreeBuilder : ReferenceTargetProvider {
override fun resolveClassReference(clazz: PsiClass): JKClass {
val name = clazz.qualifiedName ?: TODO()
return universe[name] ?: multiverse[name] ?: run {
val clazz = JKMultiverseClass(JKNameIdentifierImpl(name), JKMDeclarationList(emptyList()), JKClass.ClassKind.CLASS, JKModifierListImpl())
multiverse[name] = clazz
clazz
}
}
override fun resolveClassReference(identifier: String): JKClass {
return universe[identifier] ?: multiverse[identifier] ?: run {
val clazz =
JKMultiverseClass(JKNameIdentifierImpl(identifier), JKMDeclarationList(emptyList()), JKClass.ClassKind.CLASS, JKModifierListImpl())
multiverse[identifier] = clazz
clazz
}
}
override fun putUniverseClass(clazz: JKClass) {
universe[clazz.name.name] = clazz
}
override fun putMultiverseClass(clazz: JKMultiverseClass) {
multiverse[clazz.name.name] = clazz
}
private val universe = mutableMapOf<String, JKClass>()
private val multiverse = mutableMapOf<String, JKMultiverseClass>()
class JavaToJKTreeBuilder {
private val expressionTreeMapper = ExpressionTreeMapper()
@@ -65,6 +34,18 @@ class JavaToJKTreeBuilder : ReferenceTargetProvider {
private val modifierMapper = ModifierMapper()
val symbols = mutableMapOf<PsiElement, JKBindableSymbol<*>>()
fun bindSymbol(psi: PsiElement, element: JKElement) {
provideSymbol(psi).bind(element)
}
fun <T : JKElement> provideSymbol(psi: PsiElement): JKBindableSymbol<T> {
return symbols.getOrPut(psi) {
DelayedPsiSymbol<T>(psi)
} as JKBindableSymbol<T>
}
private inner class ExpressionTreeMapper {
fun PsiExpression.toJK(): JKExpression {
when (this) {
@@ -98,8 +79,17 @@ class JavaToJKTreeBuilder : ReferenceTargetProvider {
is PsiParenthesizedExpression -> {
return toJK()
}
is PsiAssignmentExpression -> {
return toJK()
}
else -> {
throw RuntimeException("Not supported: ${this::class}")
}
}
throw RuntimeException("Not supported")
}
fun PsiAssignmentExpression.toJK(): JKJavaAssignmentExpression {
return JKJavaAssignmentExpressionImpl(lExpression.toJK(), rExpression?.toJK() ?: TODO())
}
fun PsiBinaryExpression.toJK(): JKExpression {
@@ -137,7 +127,7 @@ class JavaToJKTreeBuilder : ReferenceTargetProvider {
fun PsiMethodCallExpression.toJK(): JKExpression {
val method = methodExpression as PsiReferenceExpressionImpl
val identifier = method.resolve().convertReference()
val identifier = JKMethodReferenceImpl({ method.reference?.resolve() })
val call = JKJavaMethodCallExpressionImpl(identifier as JKMethodReference, argumentList.toJK())
return if (method.findChildByRole(ChildRole.DOT) != null) {
JKQualifiedExpressionImpl((method.qualifier as PsiExpression).toJK(), JKJavaQualifierImpl.DOT, call)
@@ -148,8 +138,7 @@ class JavaToJKTreeBuilder : ReferenceTargetProvider {
fun PsiReferenceExpression.toJK(): JKExpression {
val impl = this as PsiReferenceExpressionImpl
val identifier = impl.resolve().convertReference() as JKFieldReference
val access = JKJavaFieldAccessExpressionImpl(identifier)
val access = JKJavaFieldAccessExpressionImpl(JKFieldReferenceImpl({ impl.resolve() }))
return if (impl.findChildByRole(ChildRole.DOT) != null) {
JKQualifiedExpressionImpl((impl.qualifier as PsiExpression).toJK(), JKJavaQualifierImpl.DOT, access)
} else {
@@ -180,7 +169,7 @@ class JavaToJKTreeBuilder : ReferenceTargetProvider {
return JKJavaNewEmptyArrayImpl(dimensions.map { it?.toJK() })
}
}
return JKJavaNewExpressionImpl(classReference?.resolve().convertReference() as JKClassReference, argumentList.toJK())
return JKJavaNewExpressionImpl(provideSymbol(constructorFakeReference.resolve()!!), argumentList.toJK())
}
fun PsiArrayAccessExpression.toJK(): JKExpression {
@@ -199,39 +188,9 @@ class JavaToJKTreeBuilder : ReferenceTargetProvider {
return JKExpressionListImpl(this?.expressions?.map { it.toJK() } ?: emptyList())
}
fun PsiElement?.convertReference(): JKReference = when (this) {
is PsiMethod -> convertMethodReference()
is PsiField -> convertFieldReference()
is PsiClass -> convertClassReference()
else -> throw Exception("Invalid PSI")
}
fun PsiMethod.convertMethodReference(): JKMethodReference {
val clazz = this@JavaToJKTreeBuilder.resolveClassReference(containingClass ?: TODO())
return JKMethodReferenceImpl(
this@JavaToJKTreeBuilder.resolveMethodReference(clazz, this),
if (clazz is JKMultiverseClass) JKReference.JKReferenceType.U2M else JKReference.JKReferenceType.U2U
)
}
fun PsiField.convertFieldReference(): JKFieldReference {
val clazz = this@JavaToJKTreeBuilder.resolveClassReference(containingClass ?: TODO())
return JKFieldReferenceImpl(
this@JavaToJKTreeBuilder.resolveFieldReference(clazz, this),
if (clazz is JKMultiverseClass) JKReference.JKReferenceType.U2M else JKReference.JKReferenceType.U2U
)
}
fun PsiClass.convertClassReference(): JKClassReference {
val clazz = this@JavaToJKTreeBuilder.resolveClassReference(this)
return JKClassReferenceImpl(
clazz, if (clazz is JKMultiverseClass) JKReference.JKReferenceType.U2M else JKReference.JKReferenceType.U2U
)
}
fun PsiType.toJK(): JKType {
return when (this) {
is PsiClassType -> JKClassTypeImpl(resolve()!!.convertClassReference(), parameters.map { it.toJK() })
is PsiClassType -> JKClassTypeImpl(resolve()?.let { provideSymbol<JKClass>(it) }, parameters.map { it.toJK() })
is PsiArrayType -> JKJavaArrayTypeImpl(componentType.toJK())
is PsiPrimitiveType -> when (presentableText) {
"int" -> JKJavaPrimitiveTypeImpl.INT
@@ -254,25 +213,39 @@ class JavaToJKTreeBuilder : ReferenceTargetProvider {
else -> JKClass.ClassKind.CLASS
}
val psi = this
return JKClassImpl(with(modifierMapper) { modifierList.toJK() }, JKNameIdentifierImpl(name!!), classKind).apply {
declarationList.apply {
return JKClassImpl(
with(modifierMapper) { modifierList.toJK() },
JKNameIdentifierImpl(name!!),
classKind
).also {
it.declarationList.apply {
declarations = psi.children.mapNotNull {
ElementVisitor(this@DeclarationMapper).apply { it.accept(this) }.resultElement as? JKUniverseDeclaration
}
}
bindSymbol(this, it)
}
}
fun PsiField.toJK(): JKJavaField {
return JKJavaFieldImpl(with(modifierMapper) { modifierList.toJK() }, with(expressionTreeMapper) { type.toJK() },
JKNameIdentifierImpl(this.name), with(expressionTreeMapper) { initializer?.toJK() } ?: TODO())
return JKJavaFieldImpl(
with(modifierMapper) { modifierList.toJK() },
with(expressionTreeMapper) { type.toJK() },
JKNameIdentifierImpl(this.name),
with(expressionTreeMapper) { initializer?.toJK() } ?: TODO()
).also {
bindSymbol(this, it)
}
}
fun PsiMethod.toJK(): JKJavaMethod {
return JKJavaMethodImpl(
with(modifierMapper) { modifierList.toJK() }, JKNameIdentifierImpl(name),
parameterList.parameters.map { it -> it.toJK() }, body?.toJK() ?: TODO()
)
).also {
bindSymbol(this, it)
}
}
fun PsiMember.toJK(): JKDeclaration? = when (this) {
@@ -293,6 +266,9 @@ class JavaToJKTreeBuilder : ReferenceTargetProvider {
if (this is PsiExpressionStatement) {
return JKExpressionStatementImpl(with(expressionTreeMapper) { expression.toJK() })
}
if (this is PsiReturnStatement) {
return JKReturnStatementImpl(with(expressionTreeMapper) { returnValue?.toJK() ?: TODO() })
}
TODO()
}
}
@@ -44,7 +44,7 @@ class NewCodeBuilder {
override fun visitUniverseClass(universeClass: JKUniverseClass, data: Unit) {
printer.print(classKindString(universeClass.classKind))
builder.append(" ")
printer.print(universeClass.name.name)
printer.print(universeClass.name.value)
if (universeClass.declarationList.declarations.isNotEmpty()) {
printer.println("{")
printer.pushIndent()
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.j2k.tree
import org.jetbrains.kotlin.j2k.tree.impl.JKBindableSymbol
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitorVoid
import org.jetbrains.kotlin.utils.Printer
@@ -73,26 +74,17 @@ private class DebugTreePrinter : JKVisitorVoid {
printer.println("]")
}
override fun visitMethodReference(methodReference: JKMethodReference) {
printer.println(methodReference.classNameWithoutJK())
printer.println(methodReference.target.parent.let { (it as? JKClass)?.name?.name ?: "null" }, "@", methodReference.target.name.name)
}
override fun visitFieldReference(fieldReference: JKFieldReference) {
printer.println(fieldReference.classNameWithoutJK())
printer.println(fieldReference.target.parent.let { (it as? JKClass)?.name?.name ?: "null" }, "@", fieldReference.target.name.name)
}
override fun visitClassReference(classReference: JKClassReference) {
printer.println(classReference.classNameWithoutJK())
printer.println(classReference.target.name.name)
}
override fun visitType(type: JKType) {
printer.println(type.classNameWithoutJK(), " \"")
printer.indented {
if (type is JKClassType)
printer.println(type.classReference.target.name.name)
if (type is JKClassType) {
if ((type.classReference as? JKBindableSymbol)?.isBound == true) {
printer.println(type.classReference?.element?.name?.value)
} else {
printer.println("Unbound")
}
}
}
printer.println("\"")
}
@@ -96,13 +96,12 @@ class JKJavaFieldAccessExpressionImpl(override var identifier: JKFieldReference)
}
class JKJavaNewExpressionImpl(
override var identifier: JKClassReference, override var arguments: JKExpressionList
) : JKJavaNewExpression, JKElementBase() {
override val constructorSymbol: JKSymbol<JKMethod>,
arguments: JKExpressionList
) : JKJavaNewExpression, JKBranchElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaNewExpression(this, data)
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {
identifier.accept(visitor, data)
}
override var arguments by child(arguments)
}
class JKJavaNewEmptyArrayImpl(override var initializer: List<JKLiteralExpression?>) : JKJavaNewEmptyArray, JKElementBase() {
@@ -139,4 +138,18 @@ class JKJavaArrayTypeImpl(override val type: JKType) : JKJavaArrayType, JKElemen
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {
}
}
class JKReturnStatementImpl(expression: JKExpression) : JKBranchElementBase(), JKReturnStatement {
// TODO accept
override val expression by child(expression)
}
class JKJavaAssignmentExpressionImpl(
lExpression: JKExpression,
rExpression: JKExpression/*,
TODO operation:? */
) : JKBranchElementBase(), JKJavaAssignmentExpression {
override var lExpression: JKExpression by child(lExpression)
override var rExpression: JKExpression by child(rExpression)
}
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.j2k.tree.impl
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.JKReference.JKReferenceType
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor
import com.intellij.psi.PsiElement
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
@@ -72,6 +72,7 @@ abstract class JKBranchElementBase : JKElementBase(), JKMutableBranchElement {
protected var childNum = 0
protected fun <T : JKTreeElement, U : T> child(v: U): ReadWriteProperty<JKMutableBranchElement, T> {
children.add(childNum, v)
return JKChild(childNum++)
}
@@ -89,6 +90,10 @@ abstract class JKElementListBase: JKElementBase(), JKMutableBranchElement {
children.addAll(v)
return JKListChild()
}
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {
children.forEach { it.accept(visitor, data) }
}
}
class JKUDeclarationListImpl : JKElementListBase(), JKUDeclarationList {
@@ -110,7 +115,7 @@ class JKClassImpl(modifierList: JKModifierList, name: JKNameIdentifier, override
}
class JKNameIdentifierImpl(override val name: String) : JKNameIdentifier, JKElementBase() {}
class JKNameIdentifierImpl(override val value: String) : JKNameIdentifier, JKElementBase() {}
class JKModifierListImpl(modifiers: List<JKModifier> = emptyList()) : JKModifierList, JKElementListBase() {
override var modifiers: List<JKModifier> by children(modifiers)
@@ -192,7 +197,7 @@ class JKTypeCastExpressionImpl(override var expression: JKExpression, override v
}
class JKClassTypeImpl(
override val classReference: JKClassReference,
override val classReference: JKSymbol<JKClass>?,
override val parameters: List<JKType>,
override val nullability: Nullability = Nullability.Default
) : JKClassType, JKElementBase() {
@@ -204,28 +209,21 @@ class JKClassTypeImpl(
}
}
class JKFieldReferenceImpl(override val target: JKField, override val referenceType: JKReferenceType) : JKFieldReference, JKElementBase() {
abstract class JKReferenceBase<T : JKReferenceTarget>(val resolve: () -> PsiElement?) : JKElementBase(), JKReference {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitReference(this, data)
override var target: T? = null
}
class JKFieldReferenceImpl(resolve: () -> PsiElement?) : JKFieldReference, JKReferenceBase<JKField>(resolve) {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitFieldReference(this, data)
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {
}
}
class JKClassReferenceImpl(override val target: JKClass, override val referenceType: JKReferenceType) : JKClassReference,
JKElementBase() {
class JKClassReferenceImpl(resolve: () -> PsiElement?) : JKClassReference, JKReferenceBase<JKClass>(resolve) {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitClassReference(this, data)
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {
}
}
class JKMethodReferenceImpl(override val target: JKMethod, override val referenceType: JKReferenceType) : JKMethodReference,
JKElementBase() {
class JKMethodReferenceImpl(resolve: () -> PsiElement?) : JKMethodReference, JKReferenceBase<JKMethod>(resolve) {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitMethodReference(this, data)
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.j2k.tree.impl
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.j2k.tree.JKElement
import org.jetbrains.kotlin.j2k.tree.JKSymbol
abstract class JKBindableSymbol<E : JKElement> : JKSymbol<E> {
final override lateinit var element: E
private set
val isBound get() = ::element.isInitialized
fun bind(new: E) {
element = new
}
}
class DelayedPsiSymbol<E : JKElement>(val psi: PsiElement) : JKBindableSymbol<E>()
+10 -3
View File
@@ -26,7 +26,10 @@ interface JKJavaMethod : JKUniverseDeclaration, JKMethod {
interface JKJavaForLoop : JKLoop
interface JKJavaAssignmentExpression : JKExpression
interface JKJavaAssignmentExpression : JKExpression {
var lExpression: JKExpression
var rExpression: JKExpression
}
interface JKJavaPrimitiveType : JKType {
val name: String
@@ -41,7 +44,7 @@ interface JKJavaMethodCallExpression : JKMethodCallExpression
interface JKJavaFieldAccessExpression : JKFieldAccessExpression
interface JKJavaNewExpression : JKExpression {
val identifier: JKClassReference
val constructorSymbol: JKSymbol<JKMethod>
val arguments: JKExpressionList
}
@@ -69,4 +72,8 @@ interface JKJavaNewArray : JKExpression {
val initializer: List<JKExpression>
}
interface JKJavaLiteralExpression : JKLiteralExpression
interface JKJavaLiteralExpression : JKLiteralExpression
interface JKReturnStatement : JKStatement {
val expression: JKExpression
}
+7 -11
View File
@@ -50,30 +50,26 @@ interface JKAccessModifier : JKModifier
interface JKModalityModifier : JKModifier
interface JKReference : JKTreeElement {
val target: JKReferenceTarget
val referenceType: JKReferenceType
enum class JKReferenceType {
U2U, U2M, M2U
}
val target: JKReferenceTarget?
val isBound get() = target != null
}
interface JKMethodReference : JKReference {
override val target: JKMethod
override val target: JKMethod?
}
interface JKFieldReference : JKReference {
override val target: JKField
override val target: JKField?
}
interface JKClassReference : JKReference {
override val target: JKClass
override val target: JKClass?
}
interface JKType : JKTreeElement
interface JKClassType : JKType {
val classReference: JKClassReference
val classReference: JKSymbol<JKClass>?
val nullability: Nullability
val parameters: List<JKType>
}
@@ -89,7 +85,7 @@ interface JKBlock : JKTreeElement {
interface JKIdentifier : JKTreeElement
interface JKNameIdentifier : JKIdentifier {
val name: String
val value: String
}
interface JKExpression : JKTreeElement
@@ -57,4 +57,8 @@ interface JKMethod : JKDeclaration, JKModifierListOwner {
interface JKField : JKDeclaration, JKModifierListOwner {
val type: JKType
val name: JKNameIdentifier
}
}
interface JKSymbol<E : JKElement> {
val element: E
}
@@ -1,45 +0,0 @@
/*
* Copyright 2010-2018 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.multiverse
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiField
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.j2k.tree.JKClass
import org.jetbrains.kotlin.j2k.tree.JKField
import org.jetbrains.kotlin.j2k.tree.JKJavaField
import org.jetbrains.kotlin.j2k.tree.JKMethod
import org.jetbrains.kotlin.j2k.tree.impl.JKNameIdentifierImpl
import org.jetbrains.kotlin.utils.addToStdlib.cast
interface ReferenceTargetProvider {
fun resolveClassReference(identifier: String): JKClass
fun resolveClassReference(clazz: PsiClass): JKClass
fun putUniverseClass(clazz: JKClass)
fun putMultiverseClass(clazz: JKMultiverseClass)
fun resolveMethodReference(clazz: JKClass, method: PsiMethod): JKMethod {
return clazz.declarations.asSequence().filter { it is JKMethod && it.name.name == method.name }.firstOrNull() as JKMethod?
?: JKMultiverseMethod(JKNameIdentifierImpl(method.name)).also { clazz.cast<JKMultiverseClass>().declarations += it }
}
fun resolveFieldReference(clazz: JKClass, field: PsiField): JKField {
return clazz.declarationList.declarations.asSequence().filter { it is JKJavaField && it.name.name == field.name }.firstOrNull() as JKField?
?: JKMultiverseField(JKNameIdentifierImpl(field.name)).also {
clazz.cast<JKMultiverseClass>().declarationList.declarations += it
}
}
}