Implement API to get source roots of script dependencies in KotlinScriptConfigurationManager and KotlinScriptConfigurationManager

This commit is contained in:
Pavel V. Talanov
2016-06-16 18:51:19 +03:00
parent ae61767bc7
commit 1da3efea81
2 changed files with 31 additions and 3 deletions
@@ -126,6 +126,10 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
cache.values.flatMap { it.classpath } cache.values.flatMap { it.classpath }
}.distinct() }.distinct()
fun getKnownSourceRoots(): List<File> = cacheLock.read {
cache.values.flatMap { it.sources }
}.distinct()
fun <TF> getCombinedClasspathFor(files: Iterable<TF>): List<File> = fun <TF> getCombinedClasspathFor(files: Iterable<TF>): List<File> =
getExternalImports(files) getExternalImports(files)
.flatMap { it.classpath } .flatMap { it.classpath }
@@ -58,11 +58,12 @@ class KotlinScriptConfigurationManager(
project.messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, object : BulkFileListener.Adapter() { project.messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, object : BulkFileListener.Adapter() {
override fun after(events: List<VFileEvent>) { override fun after(events: List<VFileEvent>) {
val isChanged = scriptExternalImportsProvider?.updateExternalImportsCache( events.mapNotNull { it.file })?.any() ?: false val isChanged = scriptExternalImportsProvider?.updateExternalImportsCache(events.mapNotNull { it.file })?.any() ?: false
if (isChanged) { if (isChanged) {
// TODO: consider more fine-grained update // TODO: consider more fine-grained update
cacheLock.write { cacheLock.write {
allScriptsClasspathCache = null allScriptsClasspathCache = null
allLibrarySourcesCache = null
} }
notifyRootsChanged() notifyRootsChanged()
} }
@@ -71,6 +72,7 @@ class KotlinScriptConfigurationManager(
} }
private var allScriptsClasspathCache: List<VirtualFile>? = null private var allScriptsClasspathCache: List<VirtualFile>? = null
private var allLibrarySourcesCache: List<VirtualFile>? = null
private val cacheLock = ReentrantReadWriteLock() private val cacheLock = ReentrantReadWriteLock()
private fun notifyRootsChanged() { private fun notifyRootsChanged() {
@@ -99,15 +101,37 @@ class KotlinScriptConfigurationManager(
return allScriptsClasspathCache ?: emptyList() return allScriptsClasspathCache ?: emptyList()
} }
fun getAllLibrarySources(): List<VirtualFile> = cacheLock.read {
if (allLibrarySourcesCache == null) {
dumbService.runWhenSmart {
cacheLock.write {
allLibrarySourcesCache =
(scriptExternalImportsProvider?.getKnownSourceRoots() ?: emptyList())
.distinct()
.mapNotNull { it.classpathEntryToVfs() }
}
notifyRootsChanged()
}
}
return allLibrarySourcesCache ?: emptyList()
}
private fun File.classpathEntryToVfs(): VirtualFile = private fun File.classpathEntryToVfs(): VirtualFile =
if (isDirectory) if (isDirectory)
StandardFileSystems.local()?.findFileByPath(this.canonicalPath) ?: throw FileNotFoundException("Classpath entry points to a non-existent location: ${this}") StandardFileSystems.local()?.findFileByPath(this.canonicalPath) ?: throw FileNotFoundException("Classpath entry points to a non-existent location: ${this}")
else else
StandardFileSystems.jar()?.findFileByPath(this.canonicalPath + URLUtil.JAR_SEPARATOR) ?: throw FileNotFoundException("Classpath entry points to a file that is not a JAR archive: ${this}") StandardFileSystems.jar()?.findFileByPath(this.canonicalPath + URLUtil.JAR_SEPARATOR) ?: throw FileNotFoundException("Classpath entry points to a file that is not a JAR archive: ${this}")
fun getAllScriptsClasspathScope(): GlobalSearchScope? { fun getAllScriptsClasspathScope(): GlobalSearchScope {
return getAllScriptsClasspath().let { cp -> return getAllScriptsClasspath().let { cp ->
if (cp.isEmpty()) null if (cp.isEmpty()) GlobalSearchScope.EMPTY_SCOPE
else GlobalSearchScope.union(cp.map { FileLibraryScope(project, it) }.toTypedArray())
}
}
fun getAllLibrarySourcesScope(): GlobalSearchScope {
return getAllLibrarySources().let { cp ->
if (cp.isEmpty()) GlobalSearchScope.EMPTY_SCOPE
else GlobalSearchScope.union(cp.map { FileLibraryScope(project, it) }.toTypedArray()) else GlobalSearchScope.union(cp.map { FileLibraryScope(project, it) }.toTypedArray())
} }
} }