Split JvmDependenciesIndex to several files, move to 'index' package

This commit is contained in:
Alexander Udalov
2016-10-17 11:35:43 +03:00
parent cdf6567375
commit 76523cc175
8 changed files with 156 additions and 108 deletions
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.cli.jvm.compiler
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClassFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.utils.addToStdlib.check
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.cli.jvm.compiler
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinder
import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinderFactory
@@ -26,6 +26,8 @@ import com.intellij.psi.PsiManager
import com.intellij.psi.PsiPackage
import com.intellij.psi.impl.file.PsiPackageImpl
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
@@ -74,6 +74,10 @@ import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
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.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
@@ -148,7 +152,7 @@ class KotlinCoreEnvironment private constructor(
val initialRoots = configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS).classpathRoots()
// REPL and kapt2 update classpath dynamically
val indexFactory = JvmUpdatableDependenciesIndexFactory()
val indexFactory = JvmUpdateableDependenciesIndexFactory()
rootsIndex = indexFactory.makeIndexFor(initialRoots)
updateClasspathFromRootsIndex(rootsIndex)
@@ -0,0 +1,72 @@
/*
* Copyright 2010-2016 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.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
class JvmDependenciesDynamicCompoundIndex() : JvmDependenciesIndex {
private val indices = arrayListOf<JvmDependenciesIndex>()
private val lock = ReentrantReadWriteLock()
fun addIndex(index: JvmDependenciesIndex) {
lock.write {
indices.add(index)
}
}
fun addNewIndexForRoots(roots: Iterable<JavaRoot>): JvmDependenciesIndex? =
lock.read {
val alreadyIndexed = indexedRoots.toHashSet()
val newRoots = roots.filter { !alreadyIndexed.contains(it) }
if (newRoots.isEmpty()) null
else {
val index = JvmDependenciesIndexImpl(newRoots)
addIndex(index)
index
}
}
override val indexedRoots: Sequence<JavaRoot> get() = indices.asSequence().flatMap { it.indexedRoots }
override fun <T : Any> findClass(
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType>,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
): T? =
lock.read {
indices.asSequence().mapNotNull { it.findClass(classId, acceptedRootTypes, findClassGivenDirectory) }.firstOrNull()
}
override fun traverseDirectoriesInPackage(
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType>,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
) {
lock.read {
indices.forEach { it.traverseDirectoriesInPackage(packageFqName, acceptedRootTypes, continueSearch) }
}
}
override fun collectKnownClassNamesInPackage(packageFqName: FqName): Set<String> = lock.read {
indices.flatMapTo(hashSetOf()) { it.collectKnownClassNamesInPackage(packageFqName) }
}
}
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2016 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.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import java.util.*
interface JvmDependenciesIndex {
val indexedRoots: Sequence<JavaRoot>
fun <T : Any> findClass(
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType> = JavaRoot.SourceAndBinary,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
): T?
fun traverseDirectoriesInPackage(
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType> = JavaRoot.SourceAndBinary,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
)
fun collectKnownClassNamesInPackage(
packageFqName: FqName
): Set<String>
}
data class JavaRoot(val file: VirtualFile, val type: RootType, val prefixFqName: FqName? = null) {
enum class RootType {
SOURCE,
BINARY
}
companion object RootTypes {
val OnlyBinary: Set<RootType> = EnumSet.of(RootType.BINARY)
val SourceAndBinary: Set<RootType> = EnumSet.of(RootType.BINARY, RootType.SOURCE)
}
}
interface JvmDependenciesIndexFactory<out T : JvmDependenciesIndex> {
fun makeIndexFor(roots: List<JavaRoot>): T
}
class JvmUpdateableDependenciesIndexFactory : JvmDependenciesIndexFactory<JvmDependenciesDynamicCompoundIndex> {
override fun makeIndexFor(roots: List<JavaRoot>) = JvmDependenciesDynamicCompoundIndex().apply {
addIndex(JvmDependenciesIndexImpl(roots))
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 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.
@@ -14,69 +14,18 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.jvm.compiler
package org.jetbrains.kotlin.cli.jvm.index
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.containers.IntArrayList
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import java.util.*
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
data class JavaRoot(val file: VirtualFile, val type: JavaRoot.RootType, val prefixFqName: FqName? = null) {
enum class RootType {
SOURCE,
BINARY
}
companion object RootTypes {
val OnlyBinary: Set<RootType> = EnumSet.of(RootType.BINARY)
val SourceAndBinary: Set<RootType> = EnumSet.of(RootType.BINARY, RootType.SOURCE)
}
}
interface JvmDependenciesIndex {
val indexedRoots: Sequence<JavaRoot>
fun <T : Any> findClass(
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType> = JavaRoot.SourceAndBinary,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
): T?
fun traverseDirectoriesInPackage(
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType> = JavaRoot.SourceAndBinary,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
)
fun collectKnownClassNamesInPackage(
packageFqName: FqName
): Set<String>
}
interface JvmDependenciesIndexFactory<out T : JvmDependenciesIndex> {
fun makeIndexFor(roots: List<JavaRoot>): T
}
class JvmStaticDependenciesIndexFactory : JvmDependenciesIndexFactory<JvmDependenciesIndex> {
override fun makeIndexFor(roots: List<JavaRoot>) = JvmDependenciesIndexImpl(roots)
}
class JvmUpdatableDependenciesIndexFactory : JvmDependenciesIndexFactory<JvmDependenciesDynamicCompoundIndex> {
override fun makeIndexFor(roots: List<JavaRoot>) = JvmDependenciesDynamicCompoundIndex().apply {
addIndex(JvmDependenciesIndexImpl(roots))
}
}
// speeds up finding files/classes in classpath/java source roots
// NOT THREADSAFE, needs to be adapted/removed if we want compiler to be multithreaded
// the main idea of this class is for each package to store roots which contains it to avoid excessive file system traversal
class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
//these fields are computed based on _roots passed to constructor which are filled in later
private val roots: List<JavaRoot> by lazy { _roots.toList() }
@@ -139,7 +88,7 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
override fun collectKnownClassNamesInPackage(
packageFqName: FqName
): Set<String> {
var result = hashSetOf<String>()
val result = hashSetOf<String>()
traverseDirectoriesInPackage(packageFqName, continueSearch = {
dir, rootType ->
@@ -322,57 +271,8 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
object NotFound : SearchResult
}
}
class JvmDependenciesDynamicCompoundIndex() : JvmDependenciesIndex {
private val indices = arrayListOf<JvmDependenciesIndex>()
private val lock = ReentrantReadWriteLock()
fun addIndex(index: JvmDependenciesIndex) {
lock.write {
indices.add(index)
}
}
fun addNewIndexForRoots(roots: Iterable<JavaRoot>): JvmDependenciesIndex? =
lock.read {
val alreadyIndexed = indexedRoots.toHashSet()
val newRoots = roots.filter { !alreadyIndexed.contains(it) }
if (newRoots.isEmpty()) null
else {
val index = JvmDependenciesIndexImpl(newRoots)
addIndex(index)
index
}
}
override val indexedRoots: Sequence<JavaRoot> get() = indices.asSequence().flatMap { it.indexedRoots }
override fun <T : Any> findClass(
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType>,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
): T? =
lock.read {
indices.asSequence().mapNotNull { it.findClass(classId, acceptedRootTypes, findClassGivenDirectory) }.firstOrNull()
}
override fun traverseDirectoriesInPackage(
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType>,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
) {
lock.read {
indices.forEach { it.traverseDirectoriesInPackage(packageFqName, acceptedRootTypes, continueSearch) }
}
}
override fun collectKnownClassNamesInPackage(packageFqName: FqName): Set<String> = lock.read {
indices.flatMapTo(hashSetOf()) { it.collectKnownClassNamesInPackage(packageFqName) }
private companion object {
fun IntArrayList.lastOrNull() = if (isEmpty) null else get(size() - 1)
}
}
private fun IntArrayList.lastOrNull() = if (isEmpty) null else get(size() - 1)
private val IntArrayList.indices: IntRange get() = 0..(size() - 1)
@@ -20,8 +20,12 @@ import com.intellij.openapi.components.ServiceManager
import com.intellij.psi.search.GlobalSearchScope
import junit.framework.TestCase
import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.cli.jvm.compiler.*
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCliJavaFileManagerImpl
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.load.kotlin.JvmVirtualFileFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -31,7 +35,6 @@ import org.jetbrains.kotlin.test.KotlinTestWithEnvironment
import org.jetbrains.kotlin.test.TestJdkKind
import java.io.File
class KotlinCliJavaFileManagerTest : KotlinTestWithEnvironment() {
private var javaFilesDir: File? = null