Introduce experimental -Xuse-javac compilation mode

In this mode, javac AST and Symbol files are used during
Kotlin compilation instead of PSI / binary stuff.
Later, they are reused for Java file compilation.
javac in this mode is integrated into kotlinc.
This commit is contained in:
baratynskiy
2017-04-05 13:11:26 +03:00
committed by Mikhail Glukhikh
parent c9a04fe1e2
commit 5eea3b6569
217 changed files with 6537 additions and 565 deletions
@@ -16,36 +16,61 @@
package org.jetbrains.kotlin.jvm.compiler
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.renderer.AnnotationArgumentsRenderingPolicy
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
import org.jetbrains.kotlin.renderer.*
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils.*
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.validateAndCompareDescriptorWithFile
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.junit.Assert
import java.io.File
import java.io.IOException
import java.lang.annotation.Retention
import org.jetbrains.kotlin.test.KotlinTestUtils.*
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.validateAndCompareDescriptorWithFile
abstract class AbstractCompileJavaAgainstKotlinTest : TestCaseWithTmpdir() {
@Throws(IOException::class)
protected fun doTest(ktFilePath: String) {
protected fun doTestWithJavac(ktFilePath: String) {
doTest(ktFilePath, true)
}
@Throws(IOException::class)
protected fun doTestWithoutJavac(ktFilePath: String) {
doTest(ktFilePath, false)
}
@Throws(IOException::class)
protected fun doTest(ktFilePath: String, useJavac: Boolean) {
Assert.assertTrue(ktFilePath.endsWith(".kt"))
val ktFile = File(ktFilePath)
val javaFile = File(ktFilePath.replaceFirst("\\.kt$".toRegex(), ".java"))
val javaErrorFile = File(ktFilePath.replaceFirst("\\.kt$".toRegex(), ".javaerr.txt"))
val out = File(tmpdir, "out")
val compiledSuccessfully = compileKotlinWithJava(listOf(javaFile), listOf(ktFile),
out, testRootDisposable, javaErrorFile)
val compiledSuccessfully = if (useJavac) {
compileKotlinWithJava(listOf(javaFile),
listOf(ktFile),
out, testRootDisposable)
} else {
KotlinTestUtils.compileKotlinWithJava(listOf(javaFile),
listOf(ktFile),
out, testRootDisposable, javaErrorFile)
}
if (!compiledSuccessfully) return
val environment = KotlinCoreEnvironment.createForTests(
@@ -56,12 +81,35 @@ abstract class AbstractCompileJavaAgainstKotlinTest : TestCaseWithTmpdir() {
val analysisResult = JvmResolveUtil.analyze(environment)
val packageView = analysisResult.moduleDescriptor.getPackage(LoadDescriptorUtil.TEST_PACKAGE_FQNAME)
assertFalse("Nothing found in package " + LoadDescriptorUtil.TEST_PACKAGE_FQNAME, packageView.isEmpty())
assertFalse("Nothing found in package ${LoadDescriptorUtil.TEST_PACKAGE_FQNAME}", packageView.isEmpty())
val expectedFile = File(ktFilePath.replaceFirst("\\.kt$".toRegex(), ".txt"))
validateAndCompareDescriptorWithFile(packageView, CONFIGURATION, expectedFile)
}
@Throws(IOException::class)
fun compileKotlinWithJava(
javaFiles: List<File>,
ktFiles: List<File>,
outDir: File,
disposable: Disposable
): Boolean {
val environment = createEnvironmentWithMockJdkAndIdeaAnnotations(disposable)
environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, true)
environment.configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, outDir)
environment.configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
environment.registerJavac(javaFiles, kotlinFiles = listOf(KotlinTestUtils.loadJetFile(environment.project, ktFiles.first())))
if (!ktFiles.isEmpty()) {
LoadDescriptorUtil.compileKotlinToDirAndGetModule(ktFiles, outDir, environment)
}
else {
val mkdirs = outDir.mkdirs()
assert(mkdirs) { "Not created: $outDir" }
}
return JavacWrapper.getInstance(environment.project).use { it.compile() }
}
companion object {
// Do not render parameter names because there are test cases where classes inherit from JDK collections,
// and some versions of JDK have debug information in the class files (including parameter names), and some don't
@@ -0,0 +1,108 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jvm.compiler
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.renderer.*
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
import org.jetbrains.kotlin.test.TestJdkKind
import org.junit.Assert
import java.io.File
import java.io.IOException
import java.lang.annotation.Retention
import org.jetbrains.kotlin.test.KotlinTestUtils.*
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.validateAndCompareDescriptorWithFile
abstract class AbstractCompileKotlinAgainstJavaTest : TestCaseWithTmpdir() {
@Throws(IOException::class)
protected fun doTest(ktFilePath: String) {
Assert.assertTrue(ktFilePath.endsWith(".kt"))
val ktFile = File(ktFilePath)
val javaFile = File(ktFilePath.replaceFirst("\\.kt$".toRegex(), ".java"))
val out = File(tmpdir, "out")
val compiledSuccessfully = compileKotlinWithJava(listOf(javaFile),
listOf(ktFile),
out, testRootDisposable)
if (!compiledSuccessfully) return
val environment = KotlinCoreEnvironment.createForTests(
testRootDisposable,
newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK, getAnnotationsJar(), out),
EnvironmentConfigFiles.JVM_CONFIG_FILES
)
environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, true)
environment.configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, out)
environment.registerJavac(emptyList<File>())
val analysisResult = JvmResolveUtil.analyze(environment)
val packageView = analysisResult.moduleDescriptor.getPackage(LoadDescriptorUtil.TEST_PACKAGE_FQNAME)
assertFalse("Nothing found in package ${LoadDescriptorUtil.TEST_PACKAGE_FQNAME}", packageView.isEmpty())
val expectedFile = File(ktFilePath.replaceFirst("\\.kt$".toRegex(), ".txt"))
validateAndCompareDescriptorWithFile(packageView, CONFIGURATION, expectedFile)
}
@Throws(IOException::class)
fun compileKotlinWithJava(
javaFiles: List<File>,
ktFiles: List<File>,
outDir: File,
disposable: Disposable
): Boolean {
val environment = createEnvironmentWithMockJdkAndIdeaAnnotations(disposable)
environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, true)
environment.configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, outDir)
environment.registerJavac(javaFiles, kotlinFiles = listOf(KotlinTestUtils.loadJetFile(environment.project, ktFiles.first())))
if (!ktFiles.isEmpty()) {
LoadDescriptorUtil.compileKotlinToDirAndGetModule(ktFiles, outDir, environment)
}
else {
val mkdirs = outDir.mkdirs()
assert(mkdirs) { "Not created: $outDir" }
}
return JavacWrapper.getInstance(environment.project).use { it.compile() }
}
companion object {
// Do not render parameter names because there are test cases where classes inherit from JDK collections,
// and some versions of JDK have debug information in the class files (including parameter names), and some don't
private val CONFIGURATION = AbstractLoadJavaTest.COMPARATOR_CONFIGURATION.withRenderer(
DescriptorRenderer.withOptions {
withDefinedIn = false
parameterNameRenderingPolicy = ParameterNameRenderingPolicy.NONE
verbose = true
annotationArgumentsRenderingPolicy = AnnotationArgumentsRenderingPolicy.UNLESS_EMPTY
excludedAnnotationClasses = setOf(FqName(Retention::class.java.name))
modifiers = DescriptorRendererModifier.ALL
}
)
}
}
@@ -0,0 +1,350 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jvm.compiler;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/compileKotlinAgainstJava")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class CompileKotlinAgainstJavaTestGenerated extends AbstractCompileKotlinAgainstJavaTest {
@TestMetadata("AbstractClass.kt")
public void testAbstractClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/AbstractClass.kt");
doTest(fileName);
}
@TestMetadata("AbstractEnum.kt")
public void testAbstractEnum() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/AbstractEnum.kt");
doTest(fileName);
}
public void testAllFilesPresentInCompileKotlinAgainstJava() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/compileKotlinAgainstJava"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("AnnotationWithArguments.kt")
public void testAnnotationWithArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/AnnotationWithArguments.kt");
doTest(fileName);
}
@TestMetadata("AnnotationWithField.kt")
public void testAnnotationWithField() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/AnnotationWithField.kt");
doTest(fileName);
}
@TestMetadata("AsteriskInImport.kt")
public void testAsteriskInImport() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/AsteriskInImport.kt");
doTest(fileName);
}
@TestMetadata("CheckKotlinStub.kt")
public void testCheckKotlinStub() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/CheckKotlinStub.kt");
doTest(fileName);
}
@TestMetadata("CheckNotNull.kt")
public void testCheckNotNull() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/CheckNotNull.kt");
doTest(fileName);
}
@TestMetadata("Class.kt")
public void testClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/Class.kt");
doTest(fileName);
}
@TestMetadata("ClassWithNestedEnum.kt")
public void testClassWithNestedEnum() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ClassWithNestedEnum.kt");
doTest(fileName);
}
@TestMetadata("ClassWithTypeParameter.kt")
public void testClassWithTypeParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ClassWithTypeParameter.kt");
doTest(fileName);
}
@TestMetadata("CyclicDependencies.kt")
public void testCyclicDependencies() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/CyclicDependencies.kt");
doTest(fileName);
}
@TestMetadata("DefaultModifier.kt")
public void testDefaultModifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/DefaultModifier.kt");
doTest(fileName);
}
@TestMetadata("EnclosingClassInner.kt")
public void testEnclosingClassInner() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/EnclosingClassInner.kt");
doTest(fileName);
}
@TestMetadata("Enum.kt")
public void testEnum() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/Enum.kt");
doTest(fileName);
}
@TestMetadata("EnumName.kt")
public void testEnumName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/EnumName.kt");
doTest(fileName);
}
@TestMetadata("Inheritance.kt")
public void testInheritance() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/Inheritance.kt");
doTest(fileName);
}
@TestMetadata("InheritedInner.kt")
public void testInheritedInner() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/InheritedInner.kt");
doTest(fileName);
}
@TestMetadata("InnerCanonicalName.kt")
public void testInnerCanonicalName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/InnerCanonicalName.kt");
doTest(fileName);
}
@TestMetadata("InnerClass.kt")
public void testInnerClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/InnerClass.kt");
doTest(fileName);
}
@TestMetadata("InnerClassFromAsteriskImport.kt")
public void testInnerClassFromAsteriskImport() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/InnerClassFromAsteriskImport.kt");
doTest(fileName);
}
@TestMetadata("InnerClassFromImport.kt")
public void testInnerClassFromImport() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/InnerClassFromImport.kt");
doTest(fileName);
}
@TestMetadata("Interface.kt")
public void testInterface() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/Interface.kt");
doTest(fileName);
}
@TestMetadata("InterfaceField.kt")
public void testInterfaceField() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/InterfaceField.kt");
doTest(fileName);
}
@TestMetadata("InterfaceMemberClass.kt")
public void testInterfaceMemberClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/InterfaceMemberClass.kt");
doTest(fileName);
}
@TestMetadata("InterfaceWithDefault.kt")
public void testInterfaceWithDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/InterfaceWithDefault.kt");
doTest(fileName);
}
@TestMetadata("ListImpl.kt")
public void testListImpl() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ListImpl.kt");
doTest(fileName);
}
@TestMetadata("MapExample.kt")
public void testMapExample() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/MapExample.kt");
doTest(fileName);
}
@TestMetadata("Method.kt")
public void testMethod() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/Method.kt");
doTest(fileName);
}
@TestMetadata("MethodWithArgument.kt")
public void testMethodWithArgument() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/MethodWithArgument.kt");
doTest(fileName);
}
@TestMetadata("MethodWithSeveralTypeParameters.kt")
public void testMethodWithSeveralTypeParameters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/MethodWithSeveralTypeParameters.kt");
doTest(fileName);
}
@TestMetadata("MethodWithTypeParameter.kt")
public void testMethodWithTypeParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/MethodWithTypeParameter.kt");
doTest(fileName);
}
@TestMetadata("MethodWithWildcard.kt")
public void testMethodWithWildcard() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/MethodWithWildcard.kt");
doTest(fileName);
}
@TestMetadata("Nesting.kt")
public void testNesting() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/Nesting.kt");
doTest(fileName);
}
@TestMetadata("RawReturnType.kt")
public void testRawReturnType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/RawReturnType.kt");
doTest(fileName);
}
@TestMetadata("ReturnEnum.kt")
public void testReturnEnum() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ReturnEnum.kt");
doTest(fileName);
}
@TestMetadata("ReturnInnerClass.kt")
public void testReturnInnerClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ReturnInnerClass.kt");
doTest(fileName);
}
@TestMetadata("ReturnInnerInInner.kt")
public void testReturnInnerInInner() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ReturnInnerInInner.kt");
doTest(fileName);
}
@TestMetadata("ReturnInnerInner.kt")
public void testReturnInnerInner() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ReturnInnerInner.kt");
doTest(fileName);
}
@TestMetadata("ReturnNested.kt")
public void testReturnNested() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ReturnNested.kt");
doTest(fileName);
}
@TestMetadata("ReturnNestedFQ.kt")
public void testReturnNestedFQ() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ReturnNestedFQ.kt");
doTest(fileName);
}
@TestMetadata("ReturnType.kt")
public void testReturnType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ReturnType.kt");
doTest(fileName);
}
@TestMetadata("ReturnTypeResolution.kt")
public void testReturnTypeResolution() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/ReturnTypeResolution.kt");
doTest(fileName);
}
@TestMetadata("SeveralInnerClasses.kt")
public void testSeveralInnerClasses() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/SeveralInnerClasses.kt");
doTest(fileName);
}
@TestMetadata("SimpleAnnotation.kt")
public void testSimpleAnnotation() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/SimpleAnnotation.kt");
doTest(fileName);
}
@TestMetadata("SimpleWildcard.kt")
public void testSimpleWildcard() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/SimpleWildcard.kt");
doTest(fileName);
}
@TestMetadata("Singleton.kt")
public void testSingleton() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/Singleton.kt");
doTest(fileName);
}
@TestMetadata("StaticNestedClass.kt")
public void testStaticNestedClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/StaticNestedClass.kt");
doTest(fileName);
}
@TestMetadata("TypeArgumentInSuperType.kt")
public void testTypeArgumentInSuperType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/TypeArgumentInSuperType.kt");
doTest(fileName);
}
@TestMetadata("TypeParameter.kt")
public void testTypeParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/TypeParameter.kt");
doTest(fileName);
}
@TestMetadata("UseKotlinInner.kt")
public void testUseKotlinInner() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/UseKotlinInner.kt");
doTest(fileName);
}
@TestMetadata("UseKtClass.kt")
public void testUseKtClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/UseKtClass.kt");
doTest(fileName);
}
@TestMetadata("Vararg.kt")
public void testVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstJava/Vararg.kt");
doTest(fileName);
}
}
@@ -0,0 +1,101 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jvm.compiler
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.javac.components.JavacBasedClassFinder
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.KotlinTestWithEnvironmentManagement
import org.jetbrains.kotlin.test.TestJdkKind
import java.io.File
import kotlin.test.assertNotNull
import kotlin.test.assertNull
class KotlinJavacBasedClassFinderTest : KotlinTestWithEnvironmentManagement() {
fun testAbsentClass() {
val tmpdir = KotlinTestUtils.tmpDirForTest(this)
val environment = createEnvironment(tmpdir)
val project = environment.project
val classFinder = createClassFinder(project)
val className = "test.A.B.D"
val found = classFinder.findClass(ClassId.topLevel(FqName(className)))
assertNull(found, "Class is expected to be null, there should be no exceptions too.")
}
fun testNestedClass() {
val tmpdir = KotlinTestUtils.tmpDirForTest(this)
KotlinTestUtils.compileKotlinWithJava(
listOf(), listOf(File("compiler/testData/kotlinClassFinder/nestedClass.kt")), tmpdir, testRootDisposable, null
)
val environment = createEnvironment(tmpdir)
val project = environment.project
val classFinder = createClassFinder(project)
val className = "test.A.B.C"
val classId = ClassId(FqName("test"), FqName("A.B.C"), false)
val found = classFinder.findClass(classId)
assertNotNull(found, "Class not found for $className")
val binaryClass = VirtualFileFinder.SERVICE.getInstance(project).findKotlinClass(found!!)
assertNotNull(binaryClass, "No binary class for $className")
assertEquals("test/A.B.C", binaryClass?.classId?.toString())
}
private fun createClassFinder(project: Project) = JavacBasedClassFinder().apply {
this::class.java.superclass.getDeclaredField("project")?.let {
it.isAccessible = true
it.set(this, project)
}
setScope(GlobalSearchScope.allScope(project))
val javacField = this::class.java.getDeclaredField("javac")
javacField.isAccessible = true
javacField.set(this, JavacWrapper.getInstance(project))
val javaSearchScopeField = this::class.java.superclass.getDeclaredField("javaSearchScope")
javaSearchScopeField.isAccessible = true
javaSearchScopeField.set(this, GlobalSearchScope.allScope(project))
}
private fun createEnvironment(tmpdir: File?, files: List<File> = emptyList()): KotlinCoreEnvironment {
return KotlinCoreEnvironment.createForTests(
testRootDisposable,
KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK, tmpdir),
EnvironmentConfigFiles.JVM_CONFIG_FILES
).apply {
registerJavac(files)
// Activate Kotlin light class finder
JvmResolveUtil.analyze(this)
}
}
}