From b3dc0d4affea31b7c2d0cee573312af463244adf Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Wed, 28 Nov 2018 16:08:43 +0300 Subject: [PATCH] New J2K: Add package & imports declarations to JKFile, simplify JKFile constructing --- .../kotlin/j2k/JavaToJKTreeBuilder.kt | 69 ++++++++----------- .../jetbrains/kotlin/j2k/NewCodeBuilder.kt | 58 +++++----------- .../org/jetbrains/kotlin/j2k/tree/impl/jk.kt | 18 ++++- .../org/jetbrains/kotlin/j2k/tree/jk.kt | 6 ++ .../kotlin/j2k/tree/visitors/JKVisitor.kt | 1 + .../kotlin/j2k/tree/visitors/JKVisitorVoid.kt | 2 + 6 files changed, 71 insertions(+), 83 deletions(-) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt index 2444a5acc8f..6319a5bed31 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.j2k -import com.intellij.lang.java.JavaLanguage import com.intellij.psi.* import com.intellij.psi.JavaTokenType.SUPER_KEYWORD import com.intellij.psi.JavaTokenType.THIS_KEYWORD @@ -35,6 +34,24 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) { private val declarationMapper = DeclarationMapper(expressionTreeMapper) + private fun PsiJavaFile.toJK(): JKFile = + JKFileImpl( + packageStatement?.toJK() ?: JKPackageDeclarationImpl(JKNameIdentifierImpl("")), + importList?.importStatements?.map { it.toJK() }.orEmpty(), + with(declarationMapper) { classes.map { it.toJK() } } + ) + + private fun PsiPackageStatement.toJK(): JKPackageDeclaration = + JKPackageDeclarationImpl(JKNameIdentifierImpl(packageName)) + + private fun PsiImportStatement.toJK() = + JKImportStatementImpl( + JKNameIdentifierImpl( + text.substringAfter("import").substringBeforeLast(";").trim() + ) + ) + + private inner class ExpressionTreeMapper { fun PsiExpression?.toJK(): JKExpression { return when (this) { @@ -251,9 +268,6 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) { JKTypeParameterImpl(JKNameIdentifierImpl(name!!), extendsListTypes.map { JKTypeElementImpl(it.toJK(symbolProvider, Nullability.NotNull)) }) - fun PsiPackageStatement.toJK(): JKPackageDeclaration = - JKPackageDeclarationImpl(JKNameIdentifierImpl(packageName)) - fun PsiClass.toJK(): JKClass { val classKind: JKClass.ClassKind = when { isAnnotationType -> JKClass.ClassKind.ANNOTATION @@ -285,7 +299,13 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) { fun PsiClass.createClassBody() = JKClassBodyImpl( children.mapNotNull { - ElementVisitor().apply { it.accept(this) }.resultElement as? JKDeclaration + when (it) { + is PsiEnumConstant -> it.toJK() + is PsiClass -> it.toJK() + is PsiMethod -> it.toJK() + is PsiField -> it.toJK() + else -> null + } } ) @@ -512,42 +532,11 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) { }.last() - private inner class ElementVisitor : JavaElementVisitor() { - - var resultElement: JKTreeElement? = null - - override fun visitClass(aClass: PsiClass) { - resultElement = with(declarationMapper) { aClass.toJK() } + fun buildTree(psi: PsiElement): JKTreeElement? = + when (psi) { + is PsiJavaFile -> psi.toJK() + else -> error("Cannot convert non-java file") } - override fun visitPackageStatement(statement: PsiPackageStatement) { - resultElement = with(declarationMapper) { statement.toJK() } - } - override fun visitField(field: PsiField) { - resultElement = with(declarationMapper) { field.toJK() } - } - - override fun visitEnumConstant(enumConstant: PsiEnumConstant) { - resultElement = with(declarationMapper) { enumConstant.toJK() } - } - - override fun visitMethod(method: PsiMethod) { - resultElement = with(declarationMapper) { method.toJK() } - } - - override fun visitFile(file: PsiFile) { - resultElement = JKFileImpl().apply { - declarationList += file.children.mapNotNull { ElementVisitor().apply { it.accept(this) }.resultElement as? JKDeclaration } - } - } - } - - - fun buildTree(psi: PsiElement): JKTreeElement? { - 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.resultElement - } } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt index c5a928d11be..dc3a1a488bc 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt @@ -119,27 +119,32 @@ class NewCodeBuilder { } override fun visitFile(file: JKFile) { - file.declarationList.find { it is JKPackageDeclaration }?.accept(this) - val collectImportsVisitor = CollectImportsVisitor() - file.accept(collectImportsVisitor) - collectImportsVisitor.collectedFqNames.forEach { - printer.printlnWithNoIndent("import ", it.asString()) - } - file.declarationList.forEach { - if (it !is JKPackageDeclaration) it.accept(this) + if (file.packageDeclaration.packageName.value.isNotEmpty()) { + file.packageDeclaration.accept(this) } + file.importList.forEach { it.accept(this) } + file.declarationList.forEach { it.accept(this) } } + private fun String.escapedAsQualifiedName(): String = + split('.') + .map { it.escaped() } + .joinToString(".") { it } + override fun visitPackageDeclaration(packageDeclaration: JKPackageDeclaration) { printer.printWithNoIndent("package ") val packageNameEscaped = - packageDeclaration.packageName.value - .split('.') - .map { it.escaped() } - .joinToString(".") { it } + packageDeclaration.packageName.value.escapedAsQualifiedName() printer.printlnWithNoIndent(packageNameEscaped) } + override fun visitImportStatement(importStatement: JKImportStatement) { + printer.printWithNoIndent("import ") + val importNameEscaped = + importStatement.name.value.escapedAsQualifiedName() + printer.printlnWithNoIndent(importNameEscaped) + } + override fun visitBreakStatement(breakStatement: JKBreakStatement) { printer.printWithNoIndent("break") } @@ -782,35 +787,6 @@ class NewCodeBuilder { ROUND("(", ")"), SQUARE("[", "]"), CURVED("{", "}"), CURVED_MULTILINE("{\n", "}\n"), INLINE_COMMENT("/*", "*/"), ANGLE("<", ">") } - private class CollectImportsVisitor : JKVisitorVoid { - val collectedFqNames: MutableList = mutableListOf() - override fun visitTreeElement(treeElement: JKTreeElement) { - treeElement.acceptChildren(this) - } - - override fun visitJavaNewExpression(javaNewExpression: JKJavaNewExpression) { - collectedFqNames.add(FqName(javaNewExpression.classSymbol.fqName!!)) - javaNewExpression.acceptChildren(this) - } - -// override fun visitTypeElement(typeElement: JKTypeElement, data: Nothing?) { -// val classType = typeElement.type as? JKClassType ?: return -// collectedFqNames.add(FqName(classType.classReference.fqName!!)) -// } - - override fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression) { - val type = classLiteralExpression.classType.type - if (type is JKClassType) { - val fqName = type.classReference.fqName!! - val isDefaultImport = fqName.split('.').let { - it.size == 2 && it.first() == "kotlin" - } - if (!isDefaultImport) { - collectedFqNames.add(FqName(fqName)) - } - } - } - } fun printCodeOut(root: JKTreeElement): String { Visitor().also { root.accept(it) } 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 7151c17c7be..ad6f7a5f0d9 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt @@ -31,10 +31,18 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtNamedFunction -class JKFileImpl : JKFile, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() { + +class JKFileImpl( + packageDeclaration: JKPackageDeclaration, + importList: List, + declarationList: List +) : JKFile, JKBranchElementBase(), + PsiOwner by PsiOwnerImpl() { override fun accept(visitor: JKVisitor, data: D): R = visitor.visitFile(this, data) - override var declarationList by children() + override var packageDeclaration: JKPackageDeclaration by child(packageDeclaration) + override var importList: List by children(importList) + override var declarationList by children(declarationList) } class JKClassImpl( @@ -506,4 +514,10 @@ class JKClassLiteralExpressionImpl( override val classType: JKTypeElement by child(classType) override fun accept(visitor: JKVisitor, data: D): R = visitor.visitClassLiteralExpression(this, data) +} + +class JKImportStatementImpl(name: JKNameIdentifier) : JKImportStatement, JKBranchElementBase() { + override val name: JKNameIdentifier by child(name) + + override fun accept(visitor: JKVisitor, data: D): R = visitor.visitImportStatement(this, data) } \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt index 15c06eadd62..10cbee5af23 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt @@ -40,7 +40,13 @@ interface PsiOwner { interface JKDeclaration : JKTreeElement +interface JKImportStatement : JKTreeElement { + val name: JKNameIdentifier +} + interface JKFile : JKTreeElement, JKBranchElement { + var packageDeclaration: JKPackageDeclaration + var importList: List var declarationList: List } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt index 4ed6d1bf96d..ed1124be63b 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt @@ -5,6 +5,7 @@ import org.jetbrains.kotlin.j2k.tree.* interface JKVisitor { fun visitTreeElement(treeElement: JKTreeElement, data: D): R fun visitDeclaration(declaration: JKDeclaration, data: D): R = visitTreeElement(declaration, data) + fun visitImportStatement(importStatement: JKImportStatement, data: D): R = visitTreeElement(importStatement, data) fun visitFile(file: JKFile, data: D): R = visitTreeElement(file, data) fun visitClass(klass: JKClass, data: D): R = visitDeclaration(klass, data) fun visitInheritanceInfo(inheritanceInfo: JKInheritanceInfo, data: D): R = visitTreeElement(inheritanceInfo, data) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt index 282bb8ad62d..f15aa498b9c 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt @@ -7,6 +7,8 @@ interface JKVisitorVoid : JKVisitor { override fun visitTreeElement(treeElement: JKTreeElement, data: Nothing?) = visitTreeElement(treeElement) fun visitDeclaration(declaration: JKDeclaration) = visitTreeElement(declaration, null) override fun visitDeclaration(declaration: JKDeclaration, data: Nothing?) = visitDeclaration(declaration) + fun visitImportStatement(importStatement: JKImportStatement) = visitTreeElement(importStatement, null) + override fun visitImportStatement(importStatement: JKImportStatement, data: Nothing?) = visitImportStatement(importStatement) fun visitFile(file: JKFile) = visitTreeElement(file, null) override fun visitFile(file: JKFile, data: Nothing?) = visitFile(file) fun visitClass(klass: JKClass) = visitDeclaration(klass, null)