From a8eef5effcd4c928f53ff0cf4101b55a5d48e289 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Thu, 28 Apr 2016 16:40:09 +0300 Subject: [PATCH] KT-12039 Convert Java to Kotlin -- static imports are imported as Class.CONST (missing .Companion) #KT-12039 Fixed --- .../kotlin/j2k/AnnotationConverter.kt | 6 +- j2k/src/org/jetbrains/kotlin/j2k/Converter.kt | 2 +- .../jetbrains/kotlin/j2k/importConversion.kt | 140 ++++++++++++++---- j2k/testData/KotlinApi.kt | 7 + .../StaticImportAllFromFileFacade.java | 8 + .../StaticImportAllFromFileFacade.kt | 8 + .../StaticImportAllFromObject.java | 7 + .../StaticImportAllFromObject.kt | 8 + .../StaticImportFromCompanionObject.java | 7 + .../StaticImportFromCompanionObject.kt | 7 + .../StaticImportFromCompanionObject2.java | 7 + .../StaticImportFromCompanionObject2.kt | 10 ++ .../StaticImportFromCompanionObject3.java | 7 + .../StaticImportFromCompanionObject3.kt | 7 + .../StaticImportFromFileFacade.java | 11 ++ .../StaticImportFromFileFacade.kt | 10 ++ ...otlinConverterForWebDemoTestGenerated.java | 36 +++++ ...otlinConverterSingleFileTestGenerated.java | 36 +++++ 18 files changed, 289 insertions(+), 35 deletions(-) create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromFileFacade.java create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromFileFacade.kt create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromObject.java create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromObject.kt create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject.java create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject.kt create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject2.java create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject2.kt create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject3.java create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject3.kt create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromFileFacade.java create mode 100644 j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromFileFacade.kt diff --git a/j2k/src/org/jetbrains/kotlin/j2k/AnnotationConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/AnnotationConverter.kt index 9e276eeab07..3b2f0c9bf87 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/AnnotationConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/AnnotationConverter.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.j2k.ast.* import org.jetbrains.kotlin.j2k.ast.Annotation import org.jetbrains.kotlin.load.java.components.JavaAnnotationTargetMapper +import org.jetbrains.kotlin.name.FqName import java.lang.annotation.ElementType import java.lang.annotation.Target @@ -31,8 +32,9 @@ class AnnotationConverter(private val converter: Converter) { + NullableNotNullManager.getInstance(converter.project).nullables + listOf(CommonClassNames.JAVA_LANG_OVERRIDE, ElementType::class.java.name)).toSet() - fun isImportNotRequired(annotationName: String): Boolean { - return annotationName in annotationsToRemove || annotationName == Target::class.java.name + fun isImportNotRequired(fqName: FqName): Boolean { + val nameAsString = fqName.asString() + return nameAsString in annotationsToRemove || nameAsString == Target::class.java.name } fun convertAnnotations(owner: PsiModifierListOwner): Annotations diff --git a/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt b/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt index b29bd9b7235..95ab15aaf45 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt @@ -114,7 +114,7 @@ class Converter private constructor( is PsiStatement -> createDefaultCodeConverter().convertStatement(element) is PsiExpression -> createDefaultCodeConverter().convertExpression(element) is PsiImportList -> convertImportList(element) - is PsiImportStatementBase -> convertImport(element, false) + is PsiImportStatementBase -> convertImport(element, false).singleOrNull() is PsiAnnotation -> annotationConverter.convertAnnotation(element, newLineAfter = false) is PsiPackageStatement -> PackageStatement(quoteKeywords(element.packageName ?: "")).assignPrototype(element) is PsiJavaCodeReferenceElement -> { diff --git a/j2k/src/org/jetbrains/kotlin/j2k/importConversion.kt b/j2k/src/org/jetbrains/kotlin/j2k/importConversion.kt index 580cb998075..dadcd8f7b3f 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/importConversion.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/importConversion.kt @@ -18,60 +18,136 @@ package org.jetbrains.kotlin.j2k import com.intellij.psi.PsiImportList import com.intellij.psi.PsiImportStatementBase +import com.intellij.psi.PsiImportStaticStatement import com.intellij.psi.PsiJavaCodeReferenceElement import org.jetbrains.kotlin.asJava.KtLightClass import org.jetbrains.kotlin.asJava.KtLightClassForFacade +import org.jetbrains.kotlin.asJava.KtLightDeclaration +import org.jetbrains.kotlin.asJava.KtLightMethod import org.jetbrains.kotlin.builtins.DefaultBuiltIns +import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.j2k.ast.Import import org.jetbrains.kotlin.j2k.ast.ImportList import org.jetbrains.kotlin.j2k.ast.assignPrototype import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.platform.JavaToKotlinClassMap +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.renderer.render +import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform +import org.jetbrains.kotlin.utils.singletonOrEmptyList -fun Converter.convertImportList(importList: PsiImportList): ImportList = - ImportList(importList.allImportStatements.mapNotNull { convertImport(it, true) }).assignPrototype(importList) +fun Converter.convertImportList(importList: PsiImportList): ImportList { + val imports = importList.allImportStatements + .flatMap { convertImport(it, true) } + .distinctBy { it.name } // duplicated imports may appear + return ImportList(imports).assignPrototype(importList) +} -fun Converter.convertImport(anImport: PsiImportStatementBase, filter: Boolean): Import? { - fun doConvert(): Import? { - val reference = anImport.importReference ?: return null - val qualifiedName = quoteKeywords(reference.qualifiedName!!) - if (anImport.isOnDemand) { - return Import(qualifiedName + ".*") +fun Converter.convertImport(anImport: PsiImportStatementBase, filter: Boolean): List { + fun doConvert(): List { + val reference = anImport.importReference ?: return emptyList() + val fqName = FqName(reference.qualifiedName!!) + val onDemand = anImport.isOnDemand + return if (filter) { + filterImport(fqName, reference, onDemand, anImport is PsiImportStaticStatement) + .map { Import(it) } } else { - return if (filter) { - val filteredName = filterImport(qualifiedName, reference) - if (filteredName != null) Import(filteredName) else null + listOf(Import(renderImportName(fqName, onDemand))) + } + } + + return doConvert().map { it.assignPrototype(anImport) } +} + +private fun Converter.filterImport(fqName: FqName, ref: PsiJavaCodeReferenceElement, isOnDemand: Boolean, isImportStatic: Boolean): List { + if (!isOnDemand) { + if (annotationConverter.isImportNotRequired(fqName)) return emptyList() + + // If imported class has a kotlin analog, drop the import + if (!JavaToKotlinClassMap.INSTANCE.mapPlatformClass(fqName, DefaultBuiltIns.Instance).isEmpty()) return emptyList() + } + + //TODO: how to detect compiled Kotlin here? + val target = ref.resolve() + if (isImportStatic) { + if (isOnDemand) { + when (target) { + is KtLightClassForFacade -> return listOf(target.getFqName().parent().render() + ".*") + + is KtLightClass -> { + val kotlinOrigin = target.kotlinOrigin + val importFromObject = when (kotlinOrigin) { + is KtObjectDeclaration -> kotlinOrigin + is KtClass -> kotlinOrigin.getCompanionObjects().singleOrNull() + else -> null + } + if (importFromObject != null) { + val objectFqName = importFromObject.fqName + if (objectFqName != null) { + // cannot import on demand from object, generate imports for all members + return importFromObject.declarations + .mapNotNull { + val descriptor = services.resolverForConverter.resolveToDescriptor(it) ?: return@mapNotNull null + if (descriptor.hasJvmStaticAnnotation() || descriptor is PropertyDescriptor && descriptor.isConst) + descriptor.name + else + null + } + .distinct() + .map { objectFqName.child(it).render() } + } + } + } } - else { - Import(qualifiedName) + } + else { + if (target is KtLightDeclaration<*, *>) { + val kotlinOrigin = target.kotlinOrigin + + val nameToImport = if (target is KtLightMethod && kotlinOrigin is KtProperty) + kotlinOrigin.nameAsName + else + fqName.shortName() + + if (nameToImport != null) { + val originParent = kotlinOrigin?.parent + when (originParent) { + is KtFile -> { // import of function or property accessor from file facade + return listOf(originParent.packageFqName.child(nameToImport).render()) + } + + is KtClassBody -> { + val parentClass = originParent.parent as KtClassOrObject + if (parentClass is KtObjectDeclaration && parentClass.isCompanion()) { + return parentClass.getFqName()?.child(nameToImport)?.render().singletonOrEmptyList() + } + } + } + } + } + } + } + else { + when (target) { + is KtLightClassForFacade -> return listOf(target.getFqName().parent().render() + ".*") + + is KtLightClass -> { + if (!isOnDemand) { + if (isFacadeClassFromLibrary(target)) return emptyList() + + if (isImportedByDefault(target)) return emptyList() + } } } } - return doConvert()?.assignPrototype(anImport) + return listOf(renderImportName(fqName, isOnDemand)) } -private fun Converter.filterImport(name: String, ref: PsiJavaCodeReferenceElement): String? { - if (annotationConverter.isImportNotRequired(name)) return null - - // If imported class has a kotlin analog, drop the import - if (!JavaToKotlinClassMap.INSTANCE.mapPlatformClass(FqName(name), DefaultBuiltIns.Instance).isEmpty()) return null - - val target = ref.resolve() - if (target is KtLightClassForFacade) { - return target.getFqName().parent().render() + ".*" - } - else if (target is KtLightClass) { - if (isFacadeClassFromLibrary(target)) return null - - if (isImportedByDefault(target)) return null - } - - return name -} +private fun renderImportName(fqName: FqName, isOnDemand: Boolean) + = if (isOnDemand) fqName.render() + ".*" else fqName.render() private val DEFAULT_IMPORTS_SET: Set = JvmPlatform.defaultModuleParameters.defaultImports .filter { it.isAllUnder } diff --git a/j2k/testData/KotlinApi.kt b/j2k/testData/KotlinApi.kt index cfa7c84b178..d7e40cd3f6d 100644 --- a/j2k/testData/KotlinApi.kt +++ b/j2k/testData/KotlinApi.kt @@ -9,14 +9,19 @@ public open class KotlinClass(public var field: Int) { fun get(i: Int) = 0 companion object { + @JvmStatic public fun staticFun(p: Int): Int = p + @JvmStatic public var staticVar: Int = 1 + @JvmStatic public var staticProperty: Int get() = 1 set(value) {} public fun nullableStaticFun(p: Int?): Int? = p public var nullableStaticVar: Int? = 1 + + const val CONST = 0 } } @@ -43,7 +48,9 @@ public var String.extensionProperty: Int set(value) {} public object KotlinObject { + @JvmStatic public fun foo(): Int = 1 + @JvmStatic public var property1: Int = 1 public var property2: Int get() = 1 diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromFileFacade.java b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromFileFacade.java new file mode 100644 index 00000000000..5804702254e --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromFileFacade.java @@ -0,0 +1,8 @@ +import static kotlinApi.KotlinApiKt.*; + +class C { + int foo() { + setExtensionProperty("a", 1); + return getExtensionProperty("b"); + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromFileFacade.kt b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromFileFacade.kt new file mode 100644 index 00000000000..8eb5e6f27dc --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromFileFacade.kt @@ -0,0 +1,8 @@ +import kotlinApi.* + +internal class C { + fun foo(): Int { + "a".extensionProperty = 1 + return "b".extensionProperty + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromObject.java b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromObject.java new file mode 100644 index 00000000000..ca878c92248 --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromObject.java @@ -0,0 +1,7 @@ +import static kotlinApi.KotlinObject.*; + +class C { + int bar() { + return foo(); + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromObject.kt b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromObject.kt new file mode 100644 index 00000000000..d2402330e0f --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromObject.kt @@ -0,0 +1,8 @@ +import kotlinApi.KotlinObject.foo +import kotlinApi.KotlinObject.property1 + +internal class C { + fun bar(): Int { + return foo() + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject.java b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject.java new file mode 100644 index 00000000000..8f5d14ee213 --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject.java @@ -0,0 +1,7 @@ +import static kotlinApi.KotlinClass.CONST; + +public class C { + void bar() { + System.out.println(CONST); + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject.kt b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject.kt new file mode 100644 index 00000000000..16bc97807cd --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject.kt @@ -0,0 +1,7 @@ +import kotlinApi.KotlinClass.Companion.CONST + +class C { + internal fun bar() { + println(CONST) + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject2.java b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject2.java new file mode 100644 index 00000000000..25e9f20d4dd --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject2.java @@ -0,0 +1,7 @@ +import static kotlinApi.KotlinClass.*; + +public class C { + void bar() { + System.out.println(CONST); + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject2.kt b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject2.kt new file mode 100644 index 00000000000..493d680ca87 --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject2.kt @@ -0,0 +1,10 @@ +import kotlinApi.KotlinClass.Companion.staticFun +import kotlinApi.KotlinClass.Companion.staticVar +import kotlinApi.KotlinClass.Companion.staticProperty +import kotlinApi.KotlinClass.Companion.CONST + +class C { + internal fun bar() { + println(CONST) + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject3.java b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject3.java new file mode 100644 index 00000000000..16dc407a88e --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject3.java @@ -0,0 +1,7 @@ +import static kotlinApi.KotlinClass.getStaticProperty; + +class C { + int foo() { + return getStaticProperty(); + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject3.kt b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject3.kt new file mode 100644 index 00000000000..e8e87c016a0 --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject3.kt @@ -0,0 +1,7 @@ +import kotlinApi.KotlinClass.Companion.staticProperty + +internal class C { + fun foo(): Int { + return staticProperty + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromFileFacade.java b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromFileFacade.java new file mode 100644 index 00000000000..ca0b4c7e0d9 --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromFileFacade.java @@ -0,0 +1,11 @@ +import static kotlinApi.KotlinApiKt.extensionFunction; +import static kotlinApi.KotlinApiKt.getExtensionProperty; +import static kotlinApi.KotlinApiKt.setExtensionProperty; + +class C { + int foo() { + extensionFunction(1) + setExtensionProperty("a", 1); + return getExtensionProperty("b"); + } +} diff --git a/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromFileFacade.kt b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromFileFacade.kt new file mode 100644 index 00000000000..d604a577cfe --- /dev/null +++ b/j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromFileFacade.kt @@ -0,0 +1,10 @@ +import kotlinApi.extensionFunction +import kotlinApi.extensionProperty + +internal class C { + fun foo(): Int { + 1.extensionFunction() + "a".extensionProperty = 1 + return "b".extensionProperty + } +} diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index afe4acc6ff8..2c137769a76 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -3033,6 +3033,42 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/Property2.java"); doTest(fileName); } + + @TestMetadata("StaticImportAllFromFileFacade.java") + public void testStaticImportAllFromFileFacade() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromFileFacade.java"); + doTest(fileName); + } + + @TestMetadata("StaticImportAllFromObject.java") + public void testStaticImportAllFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromObject.java"); + doTest(fileName); + } + + @TestMetadata("StaticImportFromCompanionObject.java") + public void testStaticImportFromCompanionObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject.java"); + doTest(fileName); + } + + @TestMetadata("StaticImportFromCompanionObject2.java") + public void testStaticImportFromCompanionObject2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject2.java"); + doTest(fileName); + } + + @TestMetadata("StaticImportFromCompanionObject3.java") + public void testStaticImportFromCompanionObject3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject3.java"); + doTest(fileName); + } + + @TestMetadata("StaticImportFromFileFacade.java") + public void testStaticImportFromFileFacade() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromFileFacade.java"); + doTest(fileName); + } } @TestMetadata("j2k/testData/fileOrElement/labelStatement") diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index 7cf0d6da45d..f0028db8905 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -3033,6 +3033,42 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/Property2.java"); doTest(fileName); } + + @TestMetadata("StaticImportAllFromFileFacade.java") + public void testStaticImportAllFromFileFacade() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromFileFacade.java"); + doTest(fileName); + } + + @TestMetadata("StaticImportAllFromObject.java") + public void testStaticImportAllFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportAllFromObject.java"); + doTest(fileName); + } + + @TestMetadata("StaticImportFromCompanionObject.java") + public void testStaticImportFromCompanionObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject.java"); + doTest(fileName); + } + + @TestMetadata("StaticImportFromCompanionObject2.java") + public void testStaticImportFromCompanionObject2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject2.java"); + doTest(fileName); + } + + @TestMetadata("StaticImportFromCompanionObject3.java") + public void testStaticImportFromCompanionObject3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromCompanionObject3.java"); + doTest(fileName); + } + + @TestMetadata("StaticImportFromFileFacade.java") + public void testStaticImportFromFileFacade() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/kotlinApiAccess/StaticImportFromFileFacade.java"); + doTest(fileName); + } } @TestMetadata("j2k/testData/fileOrElement/labelStatement")