New J2K: Collect imports to ImportStorage, not to JKFle

This commit is contained in:
Ilya Kirillov
2019-03-26 22:36:16 +03:00
committed by Ilya Kirillov
parent 9d9c9f40db
commit 9fb6cfc26e
5 changed files with 87 additions and 133 deletions
@@ -78,10 +78,11 @@ object ConversionsRunner {
//Kotlin --> Kotlin conversions
+InnerClassConversion()
+FilterImportsConversion()
+StaticsToCompanionExtractConversion()
+InterfaceWithFieldConversion()
+ClassToObjectPromotionConversion(context)
+ImportStatementConversion()
+CollectImportsConversion(context)
+SortClassMembersConversion()
}
@@ -5,14 +5,28 @@
package org.jetbrains.kotlin.nj2k
import org.jetbrains.kotlin.load.java.NULLABILITY_ANNOTATIONS
import org.jetbrains.kotlin.name.FqName
class ImportStorage {
private val imports = mutableSetOf<FqName>()
fun addImport(import: FqName) {
imports += import
if (isImportNeeded(import)) {
imports += import
}
}
fun getImports(): Set<FqName> = imports
companion object {
fun isImportNeeded(fqName: FqName): Boolean {
if (fqName in NULLABILITY_ANNOTATIONS) return false
return true
}
inline fun isImportNeeded(fqName: String): Boolean =
isImportNeeded(FqName(fqName))
}
}
@@ -0,0 +1,46 @@
/*
* 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.
*/
/*
* 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.nj2k.conversions
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.nj2k.ConversionContext
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.JKSymbol
import org.jetbrains.kotlin.nj2k.tree.impl.fqNameToImport
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class CollectImportsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
when (element) {
is JKClassAccessExpression -> addSymbol(element.identifier)
is JKFieldAccessExpression -> addSymbol(element.identifier)
is JKMethodCallExpression -> addSymbol(element.identifier)
is JKAnnotation -> addSymbol(element.classSymbol)
is JKJavaNewExpression -> addSymbol(element.classSymbol)
is JKInheritanceInfo -> {
element.implements
}
is JKTypeElement -> {
element.type.safeAs<JKClassType>()?.also {
addSymbol(it.classReference)
}
}
}
return recurse(element)
}
private fun addSymbol(symbol: JKSymbol) {
symbol.fqNameToImport()?.also { fqName ->
context.importStorage.addImport(FqName(fqName))
}
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2019 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.nj2k.conversions
import org.jetbrains.kotlin.nj2k.ImportStorage
import org.jetbrains.kotlin.nj2k.tree.JKFile
import org.jetbrains.kotlin.nj2k.tree.JKTreeElement
class FilterImportsConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element is JKFile) {
for (import in element.importList) {
if (!ImportStorage.isImportNeeded(import.name.value)) {
element.importList -= import
}
}
}
return recurse(element)
}
}
@@ -1,131 +0,0 @@
/*
* 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.
*/
/*
* 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.nj2k.conversions
import com.intellij.psi.CommonClassNames
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.JKImportStatementImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKNameIdentifierImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKSymbol
import org.jetbrains.kotlin.nj2k.tree.impl.fqNameToImport
import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitorVoid
class ImportStatementConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKFile) return recurse(element)
for (import in element.declarationList.collectImports()) {
if (!element.importList.containsImport(import)) {
element.importList += JKImportStatementImpl(JKNameIdentifierImpl(import))
}
}
return recurse(element)
}
private val importExceptionList =
listOf(
CommonClassNames.JAVA_UTIL_ARRAY_LIST,
CommonClassNames.JAVA_UTIL_LIST,
CommonClassNames.JAVA_UTIL_HASH_SET,
CommonClassNames.JAVA_UTIL_HASH_MAP,
CommonClassNames.JAVA_UTIL_COLLECTION,
CommonClassNames.JAVA_UTIL_ITERATOR,
"java.util.LinkedHashMap",
"java.util.LinkedHashSet"
)
private fun List<JKImportStatement>.containsImport(import: String) =
asSequence()
.map { it.name.value }
.any {
it == import ||
it.endsWith("*") && import.substringBeforeLast(".") == it.substringBeforeLast(".*")
}
private fun List<JKDeclaration>.collectImports(): List<String> {
val collectImportsVisitor = CollectImportsVisitor()
forEach {
it.accept(collectImportsVisitor)
}
return collectImportsVisitor.collectedFqNames
}
private class CollectImportsVisitor : JKVisitorVoid {
private val unfilteredCollectedFqNames = mutableSetOf<String>()
private val defaultImports =
listOf(
"kotlin",
"kotlin.annotation",
"kotlin.collections",
"kotlin.comparisons",
"kotlin.io",
"kotlin.ranges",
"kotlin.sequences",
"kotlin.text",
"java.lang",
"kotlin.jvm"
)
val collectedFqNames
get() = unfilteredCollectedFqNames.filter {
it.substringBeforeLast(".") !in defaultImports && it.contains(".")
}
private fun addSymbol(symbol: JKSymbol) {
symbol.fqNameToImport()?.also { fqName ->
unfilteredCollectedFqNames += fqName
}
}
override fun visitTreeElement(treeElement: JKTreeElement) {
treeElement.acceptChildren(this)
}
override fun visitClassAccessExpression(classAccessExpression: JKClassAccessExpression) {
addSymbol(classAccessExpression.identifier)
}
override fun visitJavaNewExpression(javaNewExpression: JKJavaNewExpression) {
addSymbol(javaNewExpression.classSymbol)
javaNewExpression.acceptChildren(this)
}
override fun visitTypeElement(typeElement: JKTypeElement) {
val classType = typeElement.type as? JKClassType ?: return
addSymbol(classType.classReference)
}
override fun visitFieldAccessExpression(fieldAccessExpression: JKFieldAccessExpression) {
addSymbol(fieldAccessExpression.identifier)
}
override fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression) {
addSymbol(methodCallExpression.identifier)
methodCallExpression.acceptChildren(this)
}
override fun visitAnnotation(annotation: JKAnnotation) {
addSymbol(annotation.classSymbol)
annotation.acceptChildren(this)
}
override fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression) {
val type = classLiteralExpression.classType.type
if (type is JKClassType) {
addSymbol(type.classReference)
}
classLiteralExpression.acceptChildren(this)
}
}
}