New J2K: do not find import usages in AST building phase

It is a rather heavy operation and it increases conversion time
Related to #KT-31848
This commit is contained in:
Ilya Kirillov
2019-06-08 20:53:02 +03:00
parent d0e3ab1beb
commit 5f8b5efd66
26 changed files with 62 additions and 40 deletions
@@ -279,5 +279,6 @@ private val processings: List<GeneralPostProcessing> = listOf(
RemoveForExpressionLoopParameterTypeProcessing() RemoveForExpressionLoopParameterTypeProcessing()
), ),
formatCodeProcessing, formatCodeProcessing,
optimizeImportsProcessing optimizeImportsProcessing,
shortenReferencesProcessing
) )
@@ -30,10 +30,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.PsiNewExpressionImpl
import com.intellij.psi.infos.MethodCandidateInfo import com.intellij.psi.infos.MethodCandidateInfo
import com.intellij.psi.javadoc.PsiDocComment import com.intellij.psi.javadoc.PsiDocComment
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.IElementType
import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.caches.lightClasses.KtLightClassForDecompiledDeclaration import org.jetbrains.kotlin.idea.caches.lightClasses.KtLightClassForDecompiledDeclaration
@@ -68,32 +68,12 @@ class JavaToJKTreeBuilder constructor(
private fun PsiJavaFile.toJK(): JKFile = private fun PsiJavaFile.toJK(): JKFile =
JKFileImpl( JKFileImpl(
packageStatement?.toJK() ?: JKPackageDeclarationImpl(JKNameIdentifierImpl("")), packageStatement?.toJK() ?: JKPackageDeclarationImpl(JKNameIdentifierImpl("")),
importList.toJK(filterOutUsedImports = true), importList.toJK(),
with(declarationMapper) { classes.map { it.toJK() } } with(declarationMapper) { classes.map { it.toJK() } }
) )
private fun PsiImportList?.toJK(filterOutUsedImports: Boolean): JKImportList = private fun PsiImportList?.toJK(): JKImportList =
JKImportListImpl( JKImportListImpl(this?.allImportStatements?.mapNotNull { it.toJK() }.orEmpty())
this?.allImportStatements?.let { imports ->
if (filterOutUsedImports) {
imports.filter { import ->
when {
import.isSingleUnusedImport() -> true
import.isOnDemand -> true
else -> false
}
}
} else imports.toList()
}?.mapNotNull { it.toJK() }.orEmpty()
)
private fun PsiImportStatementBase.isSingleUnusedImport(): Boolean {
if (isOnDemand) return false
val target = resolve() ?: return true
val usages = ReferencesSearch.search(target).toList()
return usages.size == 1 && PsiTreeUtil.isAncestor(this, usages.iterator().next().element, true)
}
private fun PsiPackageStatement.toJK(): JKPackageDeclaration = private fun PsiPackageStatement.toJK(): JKPackageDeclaration =
JKPackageDeclarationImpl(JKNameIdentifierImpl(packageName)) JKPackageDeclarationImpl(JKNameIdentifierImpl(packageName))
@@ -106,8 +86,12 @@ class JavaToJKTreeBuilder constructor(
val target = resolve() val target = resolve()
val rawName = (importReference?.canonicalText ?: return null) + if (isOnDemand) ".*" else "" val rawName = (importReference?.canonicalText ?: return null) + if (isOnDemand) ".*" else ""
val name = val name =
if (target is KtLightClassForFacade) target.fqName.parent().asString() + ".*" target.safeAs<KtLightElement<*, *>>()?.kotlinOrigin?.getKotlinFqName()?.asString()
else rawName ?: target.safeAs<KtLightClass>()?.containingFile?.safeAs<KtFile>()?.packageFqName?.asString()?.let { "$it.*" }
?: target.safeAs<KtLightClassForFacade>()?.fqName?.parent()?.asString()?.let { "$it.*" }
?: target.safeAs<KtLightClassForDecompiledDeclaration>()?.fqName?.parent()?.asString()?.let { "$it.*" }
?: rawName
return JKImportStatementImpl(JKNameIdentifierImpl(name)) return JKImportStatementImpl(JKNameIdentifierImpl(name))
.also { .also {
it.assignNonCodeElements(this) it.assignNonCodeElements(this)
@@ -929,7 +913,7 @@ class JavaToJKTreeBuilder constructor(
is PsiField -> with(declarationMapper) { psi.toJK() } is PsiField -> with(declarationMapper) { psi.toJK() }
is PsiMethod -> with(declarationMapper) { psi.toJK() } is PsiMethod -> with(declarationMapper) { psi.toJK() }
is PsiAnnotation -> with(declarationMapper) { psi.toJK() } is PsiAnnotation -> with(declarationMapper) { psi.toJK() }
is PsiImportList -> psi.toJK(filterOutUsedImports = false) is PsiImportList -> psi.toJK()
is PsiImportStatement -> psi.toJK() is PsiImportStatement -> psi.toJK()
is PsiJavaCodeReferenceElement -> is PsiJavaCodeReferenceElement ->
if (psi.parent is PsiReferenceList) { if (psi.parent is PsiReferenceList) {
@@ -1,6 +1,8 @@
// !forceNotNullTypes: false // !forceNotNullTypes: false
// !specifyLocalVariableTypeByDefault: true // !specifyLocalVariableTypeByDefault: true
import java.util.HashSet
internal class Foo { internal class Foo {
fun foo(o: HashSet<*>) { fun foo(o: HashSet<*>) {
val o2: HashSet<*> = o val o2: HashSet<*> = o
@@ -1,3 +1,5 @@
import java.util.HashSet
internal class Foo { internal class Foo {
fun foo(o: HashSet<*>) { fun foo(o: HashSet<*>) {
var foo = 0 var foo = 0
+2
View File
@@ -2,6 +2,8 @@
// ERROR: Type inference failed: Not enough information to infer parameter K in constructor HashMap<K : Any!, V : Any!>(initialCapacity: Int) Please specify it explicitly. // ERROR: Type inference failed: Not enough information to infer parameter K in constructor HashMap<K : Any!, V : Any!>(initialCapacity: Int) Please specify it explicitly.
package demo package demo
import java.util.HashMap
internal class Test { internal class Test {
constructor() {} constructor() {}
constructor(s: String?) {} constructor(s: String?) {}
@@ -1,3 +1,5 @@
import A.Nested
internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)) { internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)) {
internal class Nested(p: Int) { internal class Nested(p: Int) {
companion object { companion object {
@@ -7,5 +9,5 @@ internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)
} }
internal class B { internal class B {
var nested: A.Nested? = null var nested: Nested? = null
} }
@@ -1,5 +1,7 @@
package pack package pack
import pack.A.Nested
internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)) { internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)) {
internal class Nested(p: Int) { internal class Nested(p: Int) {
companion object { companion object {
@@ -9,5 +11,5 @@ internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)
} }
internal class B { internal class B {
var nested: A.Nested? = null var nested: Nested? = null
} }
+2
View File
@@ -1,3 +1,5 @@
import java.util.ArrayList
internal class A { internal class A {
private val list1: ArrayList<String> = ArrayList() private val list1: ArrayList<String> = ArrayList()
private val list2: MutableList<String> = ArrayList() private val list2: MutableList<String> = ArrayList()
+2
View File
@@ -1,3 +1,5 @@
import java.util.ArrayList
internal class C { internal class C {
fun foo1(list: MutableList<String>) { fun foo1(list: MutableList<String>) {
for (i in list.indices) { for (i in list.indices) {
+2
View File
@@ -1,3 +1,5 @@
import java.util.HashMap
internal object Test { internal object Test {
@JvmStatic @JvmStatic
fun main(args: Array<String>) { fun main(args: Array<String>) {
@@ -77,7 +77,7 @@ internal class Java8Class {
} }
fun testGenericFunctions() { fun testGenericFunctions() {
val emptyList: Function0<kotlin.collections.List<String>> = { emptyList() } val emptyList: Function0<List<String>> = { emptyList() }
val list = emptyList.invoke() val list = emptyList.invoke()
list[0] list[0]
} }
+3 -3
View File
@@ -122,10 +122,10 @@ internal class Java8Class {
} }
fun testGenericFunctions() { fun testGenericFunctions() {
val emptyList: JFunction1<kotlin.collections.List<String>> = JFunction1 { emptyList() } val emptyList: JFunction1<List<String>> = JFunction1 { emptyList() }
emptyList.foo() emptyList.foo()
MethodReferenceHelperClass.staticFun1(JFunction1<kotlin.collections.List<String>> { emptyList() }) MethodReferenceHelperClass.staticFun1(JFunction1<List<String>> { emptyList() })
h.memberFun1(JFunction1<kotlin.collections.List<String>> { emptyList() }) h.memberFun1(JFunction1<List<String>> { emptyList() })
} }
fun memberFun(): Int { fun memberFun(): Int {
+2
View File
@@ -1,6 +1,8 @@
// ERROR: The integer literal does not conform to the expected type CapturedType(*) // ERROR: The integer literal does not conform to the expected type CapturedType(*)
// ERROR: The integer literal does not conform to the expected type CapturedType(*) // ERROR: The integer literal does not conform to the expected type CapturedType(*)
// ERROR: Type argument is not within its bounds: should be subtype of 'String?' // ERROR: Type argument is not within its bounds: should be subtype of 'String?'
import java.util.HashMap
internal class G<T : String?>(t: T?) internal class G<T : String?>(t: T?)
class Java { class Java {
internal fun test() { internal fun test() {
+1 -3
View File
@@ -1,5 +1,3 @@
import kotlin.collections.Map.Entry
class A { class A {
internal fun foo(o: Entry<Any?, Any?>?) {} internal fun foo(o: Map.Entry<Any?, Any?>?) {}
} }
@@ -1,7 +1,7 @@
import kotlinApi.KotlinClass import kotlinApi.KotlinClass.Companion.CONST
class C { class C {
internal fun bar() { internal fun bar() {
println(KotlinClass.CONST) println(CONST)
} }
} }
+2
View File
@@ -1,3 +1,5 @@
import java.util.ArrayList
class TestMutableCollection { class TestMutableCollection {
val list: MutableList<String> = ArrayList() val list: MutableList<String> = ArrayList()
@@ -1,3 +1,5 @@
import java.util.ArrayList
internal class User { internal class User {
fun main() { fun main() {
val list: List<String> = ArrayList() val list: List<String> = ArrayList()
@@ -1,5 +1,7 @@
package org.test package org.test
import java.util.ArrayList
internal class Member internal class Member
internal class User { internal class User {
fun main() { fun main() {
+2
View File
@@ -1,5 +1,7 @@
package test package test
import java.util.ArrayList
class Test { class Test {
private var myProp: String? = null private var myProp: String? = null
private var myIntProp: Int? = null private var myIntProp: Int? = null
+1
View File
@@ -1,5 +1,6 @@
import javaApi.JavaClass import javaApi.JavaClass
import kotlinApi.KotlinClass import kotlinApi.KotlinClass
import java.util.HashMap
internal class X { internal class X {
operator fun get(index: Int): Int { operator fun get(index: Int): Int {
@@ -1,3 +1,5 @@
import java.util.HashMap
internal class Test { internal class Test {
fun test(map: HashMap<String, String>) { fun test(map: HashMap<String, String>) {
map.forEach { (key: String, value: String) -> foo(key, value) } map.forEach { (key: String, value: String) -> foo(key, value) }
+2
View File
@@ -1,3 +1,5 @@
import java.util.ArrayList
internal class C<T> { internal class C<T> {
fun foo1(src: Collection<T>) { fun foo1(src: Collection<T>) {
val t = src.iterator().next() val t = src.iterator().next()
+2
View File
@@ -1,5 +1,7 @@
package demo package demo
import java.util.HashMap
internal class Test { internal class Test {
fun main() { fun main() {
val commonMap: HashMap<String, Int> = HashMap() val commonMap: HashMap<String, Int> = HashMap()
+2
View File
@@ -1,5 +1,7 @@
package demo package demo
import java.util.ArrayList
internal class Test { internal class Test {
fun main() { fun main() {
val common: List<String> = ArrayList() val common: List<String> = ArrayList()
@@ -1,5 +1,7 @@
package demo package demo
import java.util.ArrayList
class TestJava { class TestJava {
fun f(result: Function1<String, Unit?>) { fun f(result: Function1<String, Unit?>) {
result.invoke("a") result.invoke("a")
+2
View File
@@ -1,3 +1,5 @@
import java.util.HashMap
internal class A { internal class A {
fun foo() { fun foo() {
val map1: Map<String, Int> = getMap1() val map1: Map<String, Int> = getMap1()