From 671aed252df7b49dd6a96bc637874baa59381dc8 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 27 Apr 2017 19:51:30 +0300 Subject: [PATCH] Support single Java source files in kotlinc arguments E.g. "kotlinc foo.kt test/Bar.java" will compile foo.kt, and declarations from Bar.java will be accessible to Kotlin code in foo.kt. The change in AbstractTopLevelMembersInvocationTest is needed because an incorrect configuration was created in that test where a library jar was also a Java source root (the compiler is never configured this way in production), which led to an exception in JavaCoreProjectEnvironment#addSourcesToClasspath #KT-17697 Fixed --- .../jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt | 10 +- .../compiler/KotlinCliJavaFileManagerImpl.kt | 30 +++-- .../cli/jvm/compiler/KotlinCoreEnvironment.kt | 35 +++--- .../compiler/KotlinToJVMBytecodeCompiler.kt | 2 +- .../cli/jvm/index/SingleJavaFileRootsIndex.kt | 115 ++++++++++++++++++ .../testData/cli/jvm/singleJavaFileRoots.args | 11 ++ .../testData/cli/jvm/singleJavaFileRoots.out | 13 ++ .../singleJavaFileRoots/DefaultPackage.java | 1 + .../cli/jvm/singleJavaFileRoots/lib/A.java | 5 + .../cli/jvm/singleJavaFileRoots/lib/B.java | 5 + .../cli/jvm/singleJavaFileRoots/lib/C.java | 5 + .../lib/classKinds/AnnotationClass.java | 5 + .../lib/classKinds/ClassClass.java | 3 + .../lib/classKinds/EnumClass.java | 3 + .../lib/classKinds/InterfaceClass.java | 3 + .../lib/ext/SeveralClasses.java | 6 + .../cli/jvm/singleJavaFileRoots/test.kt | 21 ++++ ...AbstractTopLevelMembersInvocationTest.java | 2 +- .../kotlin/cli/CliTestGenerated.java | 6 + .../cli/jvm/KotlinCliJavaFileManagerTest.kt | 2 + 20 files changed, 252 insertions(+), 31 deletions(-) create mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/index/SingleJavaFileRootsIndex.kt create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots.args create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots.out create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots/DefaultPackage.java create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots/lib/A.java create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots/lib/B.java create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots/lib/C.java create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/AnnotationClass.java create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/ClassClass.java create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/EnumClass.java create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/InterfaceClass.java create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots/lib/ext/SeveralClasses.java create mode 100644 compiler/testData/cli/jvm/singleJavaFileRoots/test.kt diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt index 710882db0ec..40c0ed01649 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.cli.jvm +import com.intellij.ide.highlighter.JavaFileType import com.intellij.openapi.Disposable import org.jetbrains.kotlin.cli.common.CLICompiler import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys @@ -94,11 +95,16 @@ class K2JVMCompiler : CLICompiler() { } else if (arguments.module == null) { for (arg in arguments.freeArgs) { - configuration.addKotlinSourceRoot(arg) val file = File(arg) - if (file.isDirectory) { + if (file.extension == JavaFileType.DEFAULT_EXTENSION) { configuration.addJavaSourceRoot(file) } + else { + configuration.addKotlinSourceRoot(arg) + if (file.isDirectory) { + configuration.addJavaSourceRoot(file) + } + } } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt index 159d45b03fc..ced18ed184f 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt @@ -26,6 +26,7 @@ import com.intellij.psi.search.GlobalSearchScope import gnu.trove.THashMap import org.jetbrains.kotlin.cli.jvm.index.JavaRoot import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex +import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser @@ -36,21 +37,23 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager import org.jetbrains.kotlin.util.PerformanceCounter +import org.jetbrains.kotlin.utils.addIfNotNull import java.util.* -import kotlin.properties.Delegates // TODO: do not inherit from CoreJavaFileManager to avoid accidental usage of its methods which do not use caches/indices // Currently, the only relevant usage of this class as CoreJavaFileManager is at CoreJavaDirectoryService.getPackage, // which is indirectly invoked from PsiPackage.getSubPackages class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager { private val perfCounter = PerformanceCounter.create("Find Java class") - private var index: JvmDependenciesIndex by Delegates.notNull() + private lateinit var index: JvmDependenciesIndex + private lateinit var singleJavaFileRootsIndex: SingleJavaFileRootsIndex private val topLevelClassesCache: MutableMap = THashMap() private val allScope = GlobalSearchScope.allScope(myPsiManager.project) private var useFastClassFilesReading = false - fun initialize(packagesCache: JvmDependenciesIndex, useFastClassFilesReading: Boolean) { - this.index = packagesCache + fun initialize(index: JvmDependenciesIndex, singleJavaFileRootsIndex: SingleJavaFileRootsIndex, useFastClassFilesReading: Boolean) { + this.index = index + this.singleJavaFileRootsIndex = singleJavaFileRootsIndex this.useFastClassFilesReading = useFastClassFilesReading } @@ -64,6 +67,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ index.findClass(classId) { dir, type -> findVirtualFileGivenPackage(dir, relativeClassName, type) } + ?: singleJavaFileRootsIndex.findJavaSourceClass(classId) }?.takeIf { it in searchScope } } @@ -153,6 +157,13 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ // traverse all true } + + result.addIfNotNull( + singleJavaFileRootsIndex.findJavaSourceClass(classId) + ?.takeIf { it in scope } + ?.findPsiClassInVirtualFile(relativeClassName) + ) + if (result.isNotEmpty()) { return@time result.toTypedArray() } @@ -169,10 +180,10 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ //abort on first found false } - if (found) { - return PsiPackageImpl(myPsiManager, packageName) + if (!found) { + found = singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName).isNotEmpty() } - return null + return if (found) PsiPackageImpl(myPsiManager, packageName) else null } private fun findVirtualFileGivenPackage( @@ -216,6 +227,11 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ true }) + for (classId in singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName)) { + assert(!classId.isNestedClass) { "ClassId of a single .java source class should not be nested: $classId" } + result.add(classId.shortClassName.asString()) + } + return result } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index f48824fd12a..6b5168b89da 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -72,10 +72,7 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* import org.jetbrains.kotlin.cli.common.toBooleanLenient import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker import org.jetbrains.kotlin.cli.jvm.config.* -import org.jetbrains.kotlin.cli.jvm.index.JavaRoot -import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesDynamicCompoundIndex -import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex -import org.jetbrains.kotlin.cli.jvm.index.JvmUpdateableDependenciesIndexFactory +import org.jetbrains.kotlin.cli.jvm.index.* import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem import org.jetbrains.kotlin.cli.jvm.modules.JavaModuleInfo import org.jetbrains.kotlin.cli.jvm.modules.ModuleGraph @@ -207,11 +204,16 @@ class KotlinCoreEnvironment private constructor( // REPL and kapt2 update classpath dynamically val indexFactory = JvmUpdateableDependenciesIndexFactory() - rootsIndex = indexFactory.makeIndexFor(initialRoots) + val (roots, singleJavaFileRoots) = + initialRoots.partition { (file) -> file.isDirectory || file.extension != JavaFileType.DEFAULT_EXTENSION } + rootsIndex = indexFactory.makeIndexFor(roots) updateClasspathFromRootsIndex(rootsIndex) - (ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl) - .initialize(rootsIndex, configuration.getBoolean(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING)) + (ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize( + rootsIndex, + SingleJavaFileRootsIndex(singleJavaFileRoots), + configuration.getBoolean(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING) + ) val finderFactory = CliVirtualFileFinderFactory(rootsIndex) project.registerService(MetadataFinderFactory::class.java, finderFactory) @@ -230,7 +232,7 @@ class KotlinCoreEnvironment private constructor( private val allJavaFiles: List get() = configuration.javaSourceRoots - .mapNotNull(this::findLocalDirectory) + .mapNotNull(this::findLocalFile) .flatMap { it.javaFiles } .map { File(it.canonicalPath) } @@ -337,13 +339,9 @@ class KotlinCoreEnvironment private constructor( fun tryUpdateClasspath(files: Iterable): List? = updateClasspath(files.map(::JvmClasspathRoot)) fun contentRootToVirtualFile(root: JvmContentRoot): VirtualFile? { - when (root) { - is JvmClasspathRoot -> { - return if (root.file.isFile) findJarRoot(root) else findLocalDirectory(root) - } - is JavaSourceRoot -> { - return if (root.file.isDirectory) findLocalDirectory(root) else null - } + return when (root) { + is JvmClasspathRoot -> if (root.file.isFile) findJarRoot(root) else findLocalFile(root) + is JavaSourceRoot -> findLocalFile(root) else -> throw IllegalStateException("Unexpected root: $root") } } @@ -352,9 +350,9 @@ class KotlinCoreEnvironment private constructor( fun findJarFile(path: String) = applicationEnvironment.jarFileSystem.findFileByPath(path) - private fun findLocalDirectory(root: JvmContentRoot): VirtualFile? { + private fun findLocalFile(root: JvmContentRoot): VirtualFile? { val path = root.file - val localFile = findLocalDirectory(path.absolutePath) + val localFile = findLocalFile(path.absolutePath) if (localFile == null) { report(STRONG_WARNING, "Classpath entry points to a non-existent location: $path") return null @@ -362,9 +360,6 @@ class KotlinCoreEnvironment private constructor( return localFile } - internal fun findLocalDirectory(absolutePath: String): VirtualFile? = - applicationEnvironment.localFileSystem.findFileByPath(absolutePath) - private fun findJarRoot(root: JvmClasspathRoot): VirtualFile? = applicationEnvironment.jarFileSystem.findFileByPath("${root.file}${URLUtil.JAR_SEPARATOR}") diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index 774b13c36ea..892cd4340dd 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -362,7 +362,7 @@ object KotlinToJVMBytecodeCompiler { override fun analyze(): AnalysisResult { val project = environment.project val moduleOutputs = environment.configuration.get(JVMConfigurationKeys.MODULES)?.mapNotNull { module -> - environment.findLocalDirectory(module.getOutputDirectory()) + environment.findLocalFile(module.getOutputDirectory()) }.orEmpty() val sourcesOnly = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, environment.getSourceFiles()) // To support partial and incremental compilation, we add the scope which contains binaries from output directories diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/index/SingleJavaFileRootsIndex.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/index/SingleJavaFileRootsIndex.kt new file mode 100644 index 00000000000..eabe94f992d --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/index/SingleJavaFileRootsIndex.kt @@ -0,0 +1,115 @@ +/* + * 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.cli.jvm.index + +import com.intellij.lang.java.lexer.JavaLexer +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.pom.java.LanguageLevel +import com.intellij.psi.impl.source.tree.ElementType +import com.intellij.psi.tree.IElementType +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +class SingleJavaFileRootsIndex(private val roots: List) { + init { + for ((file) in roots) { + assert(!file.isDirectory) { "Should not be a directory: $file" } + } + } + + private val classIdsInRoots = ArrayList>(roots.size) + + fun findJavaSourceClass(classId: ClassId): VirtualFile? = + roots.indices + .find { index -> classId in getClassIdsForRootAt(index) } + ?.let { index -> roots[index].file } + + fun findJavaSourceClasses(packageFqName: FqName): List = + roots.indices.flatMap(this::getClassIdsForRootAt).filter { root -> root.packageFqName == packageFqName } + + private fun getClassIdsForRootAt(index: Int): List { + for (i in classIdsInRoots.size..index) { + classIdsInRoots.add(JavaSourceClassIdReader(roots[i].file).readClassIds()) + } + return classIdsInRoots[index] + } + + /** + * Given a .java file, [readClassIds] uses lexer to determine which classes are declared in that file + */ + private class JavaSourceClassIdReader(file: VirtualFile) { + private val lexer = JavaLexer(LanguageLevel.JDK_1_9).apply { + start(String(file.contentsToByteArray())) + } + private var braceBalance = 0 + + private fun at(type: IElementType): Boolean = lexer.tokenType == type + + private fun end(): Boolean = lexer.tokenType == null + + private fun advance() { + when { + at(ElementType.LBRACE) -> braceBalance++ + at(ElementType.RBRACE) -> braceBalance-- + } + lexer.advance() + } + + private fun tokenText(): String = lexer.tokenText + + private fun atClass(): Boolean = + braceBalance == 0 && lexer.tokenType in CLASS_KEYWORDS + + fun readClassIds(): List { + var packageFqName = FqName.ROOT + while (!end() && !at(ElementType.PACKAGE_KEYWORD) && !atClass()) { + advance() + } + if (at(ElementType.PACKAGE_KEYWORD)) { + val packageName = StringBuilder() + while (!end() && !at(ElementType.SEMICOLON)) { + if (at(ElementType.IDENTIFIER) || at(ElementType.DOT)) { + packageName.append(tokenText()) + } + advance() + } + packageFqName = FqName(packageName.toString()) + } + + val result = ArrayList(1) + + while (true) { + while (!end() && !atClass()) { + advance() + } + if (end()) break + while (!end() && !at(ElementType.IDENTIFIER)) { + advance() + } + if (end()) break + result.add(ClassId(packageFqName, Name.identifier(tokenText()))) + } + + return result + } + + companion object { + private val CLASS_KEYWORDS = setOf(ElementType.CLASS_KEYWORD, ElementType.INTERFACE_KEYWORD, ElementType.ENUM_KEYWORD) + } + } +} diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots.args b/compiler/testData/cli/jvm/singleJavaFileRoots.args new file mode 100644 index 00000000000..42a0b8907b3 --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots.args @@ -0,0 +1,11 @@ +$TESTDATA_DIR$/singleJavaFileRoots/test.kt +$TESTDATA_DIR$/singleJavaFileRoots/DefaultPackage.java +$TESTDATA_DIR$/singleJavaFileRoots/lib/A.java +$TESTDATA_DIR$/singleJavaFileRoots/lib/B.java +$TESTDATA_DIR$/singleJavaFileRoots/lib/ext/SeveralClasses.java +$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/ClassClass.java +$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/InterfaceClass.java +$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/EnumClass.java +$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/AnnotationClass.java +-d +$TEMP_DIR$ diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots.out b/compiler/testData/cli/jvm/singleJavaFileRoots.out new file mode 100644 index 00000000000..876eb60bcb6 --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots.out @@ -0,0 +1,13 @@ +compiler/testData/cli/jvm/singleJavaFileRoots/test.kt:7:9: error: cannot access class 'C'. Check your module classpath for missing or conflicting dependencies + B().c() + ^ +compiler/testData/cli/jvm/singleJavaFileRoots/test.kt:8:5: error: unresolved reference: C + C().a() + ^ +compiler/testData/cli/jvm/singleJavaFileRoots/test.kt:12:5: error: cannot access '': it is public/*package*/ in 'PackageLocal1' + PackageLocal1() + ^ +compiler/testData/cli/jvm/singleJavaFileRoots/test.kt:13:5: error: cannot access '': it is public/*package*/ in 'PackageLocal2' + PackageLocal2() + ^ +COMPILATION_ERROR diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots/DefaultPackage.java b/compiler/testData/cli/jvm/singleJavaFileRoots/DefaultPackage.java new file mode 100644 index 00000000000..b7e7c026f5a --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots/DefaultPackage.java @@ -0,0 +1 @@ +public class DefaultPackage {} diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots/lib/A.java b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/A.java new file mode 100644 index 00000000000..33c4cd108fd --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/A.java @@ -0,0 +1,5 @@ +package lib; + +public class A { + public B b() {} +} diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots/lib/B.java b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/B.java new file mode 100644 index 00000000000..87dab9b0c0d --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/B.java @@ -0,0 +1,5 @@ +package lib; + +public class B { + public C c() {} +} diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots/lib/C.java b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/C.java new file mode 100644 index 00000000000..31b5697c367 --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/C.java @@ -0,0 +1,5 @@ +package lib; + +public class C { + public A a() {} +} diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/AnnotationClass.java b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/AnnotationClass.java new file mode 100644 index 00000000000..a2d7c307d1a --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/AnnotationClass.java @@ -0,0 +1,5 @@ +package lib.classKinds; + +public @interface AnnotationClass { + EnumClass value(); +} diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/ClassClass.java b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/ClassClass.java new file mode 100644 index 00000000000..115f7877bc1 --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/ClassClass.java @@ -0,0 +1,3 @@ +package lib.classKinds; + +public class ClassClass {} diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/EnumClass.java b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/EnumClass.java new file mode 100644 index 00000000000..3d77b213b96 --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/EnumClass.java @@ -0,0 +1,3 @@ +package lib.classKinds; + +public enum EnumClass { ENTRY } diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/InterfaceClass.java b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/InterfaceClass.java new file mode 100644 index 00000000000..dcc8bf71cf8 --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/classKinds/InterfaceClass.java @@ -0,0 +1,3 @@ +package lib.classKinds; + +public interface InterfaceClass {} diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots/lib/ext/SeveralClasses.java b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/ext/SeveralClasses.java new file mode 100644 index 00000000000..235dbbbeac2 --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots/lib/ext/SeveralClasses.java @@ -0,0 +1,6 @@ +package lib. /* comment */ ext; + +class +PackageLocal1 {} + +class /* comment */ PackageLocal2 {} diff --git a/compiler/testData/cli/jvm/singleJavaFileRoots/test.kt b/compiler/testData/cli/jvm/singleJavaFileRoots/test.kt new file mode 100644 index 00000000000..7264419ce10 --- /dev/null +++ b/compiler/testData/cli/jvm/singleJavaFileRoots/test.kt @@ -0,0 +1,21 @@ +import lib.* +import lib.ext.* +import lib.classKinds.* + +fun main(args: Array) { + A().b() + B().c() + C().a() + + DefaultPackage() + + PackageLocal1() + PackageLocal2() +} + +@AnnotationClass(EnumClass.ENTRY) +fun classKinds( + c: ClassClass, + i: InterfaceClass, + e: EnumClass +) {} diff --git a/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractTopLevelMembersInvocationTest.java b/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractTopLevelMembersInvocationTest.java index 69e4bc61932..cee30507bbf 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractTopLevelMembersInvocationTest.java +++ b/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractTopLevelMembersInvocationTest.java @@ -61,7 +61,7 @@ public abstract class AbstractTopLevelMembersInvocationTest extends AbstractByte getTestRootDisposable(), KotlinTestUtils.newConfiguration( ConfigurationKind.JDK_ONLY, TestJdkKind.MOCK_JDK, - CollectionsKt.plus(classPath, KotlinTestUtils.getAnnotationsJar()), classPath + CollectionsKt.plus(classPath, KotlinTestUtils.getAnnotationsJar()), Collections.emptyList() ), EnvironmentConfigFiles.JVM_CONFIG_FILES); diff --git a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java index 3466e261314..cf55f24f422 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -332,6 +332,12 @@ public class CliTestGenerated extends AbstractCliTest { doJvmTest(fileName); } + @TestMetadata("singleJavaFileRoots.args") + public void testSingleJavaFileRoots() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/singleJavaFileRoots.args"); + doJvmTest(fileName); + } + @TestMetadata("suppressAllWarningsJvm.args") public void testSuppressAllWarningsJvm() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/suppressAllWarningsJvm.args"); diff --git a/compiler/tests/org/jetbrains/kotlin/cli/jvm/KotlinCliJavaFileManagerTest.kt b/compiler/tests/org/jetbrains/kotlin/cli/jvm/KotlinCliJavaFileManagerTest.kt index bd24d467c10..2865ec5b50e 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/jvm/KotlinCliJavaFileManagerTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/cli/jvm/KotlinCliJavaFileManagerTest.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.cli.jvm.index.JavaRoot import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndexImpl +import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder import org.jetbrains.kotlin.name.ClassId @@ -202,6 +203,7 @@ class KotlinCliJavaFileManagerTest : KotlinTestWithEnvironment() { val root = environment.contentRootToVirtualFile(JavaSourceRoot(javaFilesDir!!, null))!! coreJavaFileManager.initialize( JvmDependenciesIndexImpl(listOf(JavaRoot(root, JavaRoot.RootType.SOURCE))), + SingleJavaFileRootsIndex(emptyList()), useFastClassFilesReading = true )