From 7cccb9998207943ee82319573edef22a6f6777f3 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 22 May 2018 20:38:03 +0300 Subject: [PATCH] New J2K: WIP: Type mapper --- .../jetbrains/kotlin/j2k/ConversionContext.kt | 16 ++++++ .../jetbrains/kotlin/j2k/ConversionsRunner.kt | 8 +-- .../jetbrains/kotlin/j2k/JKSymbolProvider.kt | 19 +++++++ .../kotlin/j2k/JavaToJKTreeBuilder.kt | 32 +++++++++--- .../kotlin/j2k/NewJavaToKotlinConverter.kt | 8 ++- .../kotlin/j2k/conversions/BaseConversion.kt | 3 +- .../conversions/FieldToPropertyConversion.kt | 3 +- .../conversions/TransformerBasedConversion.kt | 3 +- .../j2k/conversions/TypeMappingConversion.kt | 52 ++++++++++++++++--- .../kotlin/j2k/tree/DebugTreePrinter.kt | 8 +-- .../org/jetbrains/kotlin/j2k/tree/impl/j.kt | 20 +++---- .../org/jetbrains/kotlin/j2k/tree/impl/jk.kt | 10 ++-- .../jetbrains/kotlin/j2k/tree/impl/symbols.kt | 15 ++++-- 13 files changed, 151 insertions(+), 46 deletions(-) create mode 100644 j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionContext.kt create mode 100644 j2k/newSrc/org/jetbrains/kotlin/j2k/JKSymbolProvider.kt diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionContext.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionContext.kt new file mode 100644 index 00000000000..7ef220ae67e --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionContext.kt @@ -0,0 +1,16 @@ +/* + * 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 + +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.j2k.tree.JKElement + +data class ConversionContext( + val symbolProvider: JKSymbolProvider, + val project: Project, + val backAnnotator: (JKElement) -> PsiElement? +) \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt index 202605d0319..fc0ec25d033 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt @@ -18,15 +18,17 @@ package org.jetbrains.kotlin.j2k import org.jetbrains.kotlin.j2k.conversions.FieldToPropertyConversion import org.jetbrains.kotlin.j2k.conversions.JavaMethodToKotlinFunctionConversion +import org.jetbrains.kotlin.j2k.conversions.TypeMappingConversion import org.jetbrains.kotlin.j2k.tree.JKTreeElement object ConversionsRunner { - fun doApply(trees: List) { + fun doApply(trees: List, context: ConversionContext) { trees.forEach { - FieldToPropertyConversion().runConversion(it) - JavaMethodToKotlinFunctionConversion().runConversion(it) + FieldToPropertyConversion().runConversion(it, context) + TypeMappingConversion(context).runConversion(it, context) + JavaMethodToKotlinFunctionConversion().runConversion(it, context) } } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/JKSymbolProvider.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/JKSymbolProvider.kt new file mode 100644 index 00000000000..c3459a68f63 --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/JKSymbolProvider.kt @@ -0,0 +1,19 @@ +/* + * 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 + + +class JKSymbolProvider { +// +// +// fun provideSymbol(clz: PsiClass): JKClassSymbol { +// +// } +// +// fun provideSymbol(clz: KtClassOrObject): JKClassSymbol { +// +// } +} \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt index 8014f3f9439..cd5a00bfc3e 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt @@ -34,6 +34,8 @@ class JavaToJKTreeBuilder { private val modifierMapper = ModifierMapper() + val backAnnotation = mutableMapOf() + val symbols = mutableMapOf() val symbolsByDeclaration = mutableMapOf() @@ -152,11 +154,16 @@ class JavaToJKTreeBuilder { fun PsiReferenceExpression.toJK(): JKExpression { val impl = this as PsiReferenceExpressionImpl + if (impl.resolve() !is PsiField) { + return JKNullLiteral() // TODO !!! + } + val access = JKJavaFieldAccessExpressionImpl(JKMultiverseFieldSymbol(impl.resolve() as PsiField)) - return if (impl.findChildByRole(ChildRole.DOT) != null) { - JKQualifiedExpressionImpl((impl.qualifier as PsiExpression).toJK(), JKJavaQualifierImpl.DOT, access) - } else { - access + return when { + impl.findChildByRole(ChildRole.DOT) != null && + (impl.qualifierExpression as? PsiReferenceExpression)?.resolve() !is PsiClass -> + JKQualifiedExpressionImpl((impl.qualifier as PsiExpression).toJK(), JKJavaQualifierImpl.DOT, access) + else -> access } } @@ -191,7 +198,7 @@ class JavaToJKTreeBuilder { } fun PsiTypeCastExpression.toJK(): JKExpression { - return JKTypeCastExpressionImpl(operand?.toJK() ?: TODO(), castType?.type?.toJK() ?: TODO()) + return JKTypeCastExpressionImpl(operand?.toJK() ?: TODO(), castType?.toJK() ?: TODO()) } fun PsiParenthesizedExpression.toJK(): JKExpression { @@ -202,9 +209,18 @@ class JavaToJKTreeBuilder { return JKExpressionListImpl(this?.expressions?.map { it.toJK() } ?: emptyList()) } + fun PsiTypeElement.toJK(): JKType { + return type.toJK().also { + backAnnotation[it] = this + } + } + fun PsiType.toJK(): JKType { return when (this) { - is PsiClassType -> JKClassTypeImpl(resolve()?.let { provideSymbol(it) as? JKClassSymbol }!!, parameters.map { it.toJK() }) + is PsiClassType -> JKClassTypeImpl( + resolve()?.let { provideSymbol(it) as? JKClassSymbol }!!, + parameters.map { it.toJK() } + ) is PsiArrayType -> JKJavaArrayTypeImpl(componentType.toJK()) is PsiPrimitiveType -> when (presentableText) { "int" -> JKJavaPrimitiveTypeImpl.INT @@ -238,7 +254,7 @@ class JavaToJKTreeBuilder { fun PsiField.toJK(): JKJavaField { return JKJavaFieldImpl( with(modifierMapper) { modifierList.toJK() }, - with(expressionTreeMapper) { type.toJK() }, + with(expressionTreeMapper) { typeElement?.toJK() } ?: TODO(), JKNameIdentifierImpl(this.name), with(expressionTreeMapper) { initializer?.toJK() } ?: TODO() ).also { @@ -262,7 +278,7 @@ class JavaToJKTreeBuilder { } fun PsiParameter.toJK(): JKValueArgumentImpl { - return JKValueArgumentImpl(with(expressionTreeMapper) { type.toJK() }, name!!) + return JKValueArgumentImpl(with(expressionTreeMapper) { typeElement?.toJK() } ?: TODO(), name!!) } fun PsiCodeBlock.toJK(): JKBlock { diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewJavaToKotlinConverter.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewJavaToKotlinConverter.kt index 5ac3acc7d40..e1e50dd56c1 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewJavaToKotlinConverter.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewJavaToKotlinConverter.kt @@ -42,7 +42,13 @@ class NewJavaToKotlinConverter( println(fileTrees.prettyPrintTrees()) - ConversionsRunner.doApply(fileTrees) + val context = ConversionContext( + JKSymbolProvider(), + project, + { treeBuilder.backAnnotation[it] } + ) + + ConversionsRunner.doApply(fileTrees, context) val resultTree = fileTrees.prettyPrintTrees() diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/BaseConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/BaseConversion.kt index feded069a3a..e7697887878 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/BaseConversion.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/BaseConversion.kt @@ -16,12 +16,13 @@ package org.jetbrains.kotlin.j2k.conversions +import org.jetbrains.kotlin.j2k.ConversionContext import org.jetbrains.kotlin.j2k.tree.JKTreeElement abstract class BaseConversion { /** * @return true if something changed */ - abstract fun runConversion(treeRoot: JKTreeElement): Boolean + abstract fun runConversion(treeRoot: JKTreeElement, context: ConversionContext): Boolean } \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/FieldToPropertyConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/FieldToPropertyConversion.kt index e68caf250d1..08565dd6df1 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/FieldToPropertyConversion.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/FieldToPropertyConversion.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.j2k.conversions +import org.jetbrains.kotlin.j2k.ConversionContext import org.jetbrains.kotlin.j2k.tree.* import org.jetbrains.kotlin.load.java.JvmAbi @@ -16,7 +17,7 @@ class FieldToPropertyConversion : MatchBasedConversion() { var somethingChanged = false - override fun runConversion(treeRoot: JKTreeElement): Boolean { + override fun runConversion(treeRoot: JKTreeElement, context: ConversionContext): Boolean { val root = applyToElement(treeRoot) assert(root === treeRoot) return somethingChanged diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/TransformerBasedConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/TransformerBasedConversion.kt index 799e4f605df..08e6bcaaf36 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/TransformerBasedConversion.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/TransformerBasedConversion.kt @@ -16,13 +16,14 @@ package org.jetbrains.kotlin.j2k.conversions +import org.jetbrains.kotlin.j2k.ConversionContext import org.jetbrains.kotlin.j2k.tree.JKTreeElement import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitorVoid abstract class TransformerBasedConversion : BaseConversion(), JKVisitorVoid { protected var somethingChanged = false - override fun runConversion(treeRoot: JKTreeElement): Boolean { + override fun runConversion(treeRoot: JKTreeElement, context: ConversionContext): Boolean { somethingChanged = false treeRoot.accept(this, null) return somethingChanged diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/TypeMappingConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/TypeMappingConversion.kt index cc5ec04d766..9ae6371b320 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/TypeMappingConversion.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/TypeMappingConversion.kt @@ -5,17 +5,32 @@ package org.jetbrains.kotlin.j2k.conversions +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiReferenceExpression +import org.jetbrains.kotlin.j2k.ConversionContext +import org.jetbrains.kotlin.j2k.ast.Nullability import org.jetbrains.kotlin.j2k.tree.JKClassType import org.jetbrains.kotlin.j2k.tree.JKJavaPrimitiveType import org.jetbrains.kotlin.j2k.tree.JKTreeElement import org.jetbrains.kotlin.j2k.tree.JKType +import org.jetbrains.kotlin.j2k.tree.impl.JKClassSymbol +import org.jetbrains.kotlin.j2k.tree.impl.JKClassTypeImpl +import org.jetbrains.kotlin.j2k.tree.impl.JKMultiverseKtClassSymbol +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.platform.JavaToKotlinClassMap +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.resolve.ImportPath +import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver +import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType -class TypeMappingConversion : MatchBasedConversion() { +class TypeMappingConversion(val context: ConversionContext) : MatchBasedConversion() { override fun onElementChanged(new: JKTreeElement, old: JKTreeElement) { somethingChanged = true } - override fun runConversion(treeRoot: JKTreeElement): Boolean { + override fun runConversion(treeRoot: JKTreeElement, context: ConversionContext): Boolean { val root = applyToElement(treeRoot) assert(root === treeRoot) return somethingChanged @@ -32,14 +47,37 @@ class TypeMappingConversion : MatchBasedConversion() { } } + fun fqNameRef(classId: ClassId, element: PsiElement): PsiReferenceExpression? { + return KtPsiFactory(element) + .createExpressionCodeFragment(classId.asString(), element) + .findChildByClass(PsiReferenceExpression::class.java) + } + + fun classTypeByFqName( + contextElement: PsiElement?, + fqName: ClassId, + parameters: List, + nullability: Nullability = Nullability.Default + ): JKType? { + contextElement ?: return null + val newTarget = fqNameRef(fqName, contextElement)?.resolve() as? KtClassOrObject ?: return null + + val newSymbol = JKMultiverseKtClassSymbol(newTarget) + + return JKClassTypeImpl(newSymbol, parameters, nullability) + } + fun mapClassType(type: JKClassType): JKType { -// if (type.classReference?.target) { -// -// } - return type + val fqNameStr = (type.classReference as? JKClassSymbol)?.fqName ?: return type + + val newFqName = JavaToKotlinClassMap.mapJavaToKotlin(FqName(fqNameStr)) ?: return type + + return classTypeByFqName(context.backAnnotator(type), newFqName, type.parameters, type.nullability) ?: type } fun mapPrimitiveType(type: JKJavaPrimitiveType): JKType { - return type + val fqName = JvmPrimitiveType.get(type.name).primitiveType.typeFqName + + return classTypeByFqName(context.backAnnotator(type), ClassId.topLevel(fqName), emptyList()) ?: type } } \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/DebugTreePrinter.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/DebugTreePrinter.kt index 79cc36f9c42..7d7b7885866 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/DebugTreePrinter.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/DebugTreePrinter.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.j2k.tree +import org.jetbrains.kotlin.j2k.tree.impl.JKClassSymbol import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitorVoid import org.jetbrains.kotlin.utils.Printer @@ -77,12 +78,7 @@ private class DebugTreePrinter : JKVisitorVoid { printer.println(type.classNameWithoutJK(), " \"") printer.indented { if (type is JKClassType) { - /*if ((type.classReference as? JKBindableSymbol)?.isBound == true) { - printer.println(type.classReference?.element?.name?.value) - - } else { - printer.println("Unbound") - }*/ + printer.println((type.classReference as? JKClassSymbol)?.fqName ?: type.classReference?.let { it::class } ?: "Unbound") } } printer.println("\"") diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt index 56890ecdd0c..65fc8bdb72f 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt @@ -20,21 +20,21 @@ import org.jetbrains.kotlin.j2k.tree.* import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor class JKJavaFieldImpl( - override var modifierList: JKModifierList, - override var type: JKType, - override var name: JKNameIdentifier, - override var initializer: JKExpression -) : JKJavaField, JKElementBase() { + modifierList: JKModifierList, + type: JKType, + name: JKNameIdentifier, + initializer: JKExpression +) : JKJavaField, JKBranchElementBase() { override val valid: Boolean get() = true override fun accept(visitor: JKVisitor, data: D): R = visitor.visitJavaField(this, data) - override fun acceptChildren(visitor: JKVisitor, data: D) { - type.accept(visitor, data) - name.accept(visitor, data) - initializer.accept(visitor, data) - } + override var initializer: JKExpression by child(initializer) + override var modifierList: JKModifierList by child(modifierList) + override var name: JKNameIdentifier by child(name) + override var type: JKType by child(type) + } class JKJavaLiteralExpressionImpl( diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt index a418895dabe..c984453b698 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt @@ -204,13 +204,13 @@ class JKTypeCastExpressionImpl(override var expression: JKExpression, override v class JKClassTypeImpl( override val classReference: JKClassSymbol, - override val parameters: List, + parameters: List, override val nullability: Nullability = Nullability.Default -) : JKClassType, JKElementBase() { +) : JKClassType, JKBranchElementBase() { override fun accept(visitor: JKVisitor, data: D): R = visitor.visitClassType(this, data) - override fun acceptChildren(visitor: JKVisitor, data: D) { + override var parameters: List by children(parameters) +} - } -} \ No newline at end of file +class JKNullLiteral : JKExpression, JKElementBase() \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/symbols.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/symbols.kt index 44910d7ca20..d5fc6b5431d 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/symbols.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/symbols.kt @@ -11,6 +11,8 @@ 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.JKMethod +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtClassOrObject interface JKSymbol { val target: Any @@ -18,7 +20,7 @@ interface JKSymbol { } interface JKClassSymbol : JKSymbol { - val fqName: String + val fqName: String? } interface JKMethodSymbol : JKSymbol { @@ -39,8 +41,15 @@ class JKUniverseClassSymbol(override val target: JKClass) : JKClassSymbol { class JKMultiverseClassSymbol(override val target: PsiClass) : JKClassSymbol { override val declaredIn: JKSymbol get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. - override val fqName: String - get() = target.name!! + override val fqName: String? + get() = target.qualifiedName +} + +class JKMultiverseKtClassSymbol(override val target: KtClassOrObject): JKClassSymbol { + override val declaredIn: JKSymbol + get() = TODO("not implemented") + override val fqName: String? + get() = target.fqName?.asString() }