package org.jetbrains.dokka import com.intellij.openapi.Disposable import com.intellij.openapi.components.BaseComponent import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.projectRoots.SdkAdditionalData import com.intellij.openapi.projectRoots.SdkModificator import com.intellij.openapi.projectRoots.SdkTypeId import com.intellij.openapi.roots.* import com.intellij.openapi.roots.impl.ProjectOrderEnumerator import com.intellij.openapi.util.Condition import com.intellij.openapi.util.Key import com.intellij.openapi.util.UserDataHolderBase import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.messages.MessageBus import org.jetbrains.jps.model.module.JpsModuleSourceRootType import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot import org.jetbrains.kotlin.config.ContentRoot import org.jetbrains.kotlin.config.KotlinSourceRoot import org.picocontainer.PicoContainer import java.io.File /** * Workaround for the lack of ability to create a ProjectFileIndex implementation using only * classes from projectModel-{api,impl}. */ class CoreProjectFileIndex(val project: Project, contentRoots: List) : ProjectFileIndex, ModuleFileIndex { val sourceRoots = contentRoots.filter { it !is JvmClasspathRoot } val classpathRoots = contentRoots.filterIsInstance() val module: Module = object : UserDataHolderBase(), Module { override fun isDisposed(): Boolean { throw UnsupportedOperationException() } override fun getOptionValue(p0: String): String? { throw UnsupportedOperationException() } override fun clearOption(p0: String) { throw UnsupportedOperationException() } override fun getName(): String = "" override fun getModuleWithLibrariesScope(): GlobalSearchScope { throw UnsupportedOperationException() } override fun getModuleWithDependentsScope(): GlobalSearchScope { throw UnsupportedOperationException() } override fun getModuleContentScope(): GlobalSearchScope { throw UnsupportedOperationException() } override fun isLoaded(): Boolean { throw UnsupportedOperationException() } override fun setOption(p0: String, p1: String) { throw UnsupportedOperationException() } override fun getModuleWithDependenciesScope(): GlobalSearchScope { throw UnsupportedOperationException() } override fun getModuleWithDependenciesAndLibrariesScope(p0: Boolean): GlobalSearchScope { throw UnsupportedOperationException() } override fun getProject(): Project = project override fun getModuleContentWithDependenciesScope(): GlobalSearchScope { throw UnsupportedOperationException() } override fun getModuleFilePath(): String { throw UnsupportedOperationException() } override fun getModuleTestsWithDependentsScope(): GlobalSearchScope { throw UnsupportedOperationException() } override fun getModuleScope(): GlobalSearchScope { throw UnsupportedOperationException() } override fun getModuleScope(p0: Boolean): GlobalSearchScope { throw UnsupportedOperationException() } override fun getModuleRuntimeScope(p0: Boolean): GlobalSearchScope { throw UnsupportedOperationException() } override fun getModuleFile(): VirtualFile? { throw UnsupportedOperationException() } override fun getExtensions(p0: ExtensionPointName): Array { throw UnsupportedOperationException() } override fun getComponent(p0: String): BaseComponent? { throw UnsupportedOperationException() } override fun getComponent(p0: Class, p1: T): T { throw UnsupportedOperationException() } override fun getComponent(interfaceClass: Class): T? { if (interfaceClass == ModuleRootManager::class.java) { return moduleRootManager as T } throw UnsupportedOperationException() } override fun getDisposed(): Condition<*> { throw UnsupportedOperationException() } override fun getComponents(p0: Class): Array { throw UnsupportedOperationException() } override fun getPicoContainer(): PicoContainer { throw UnsupportedOperationException() } override fun hasComponent(p0: Class<*>): Boolean { throw UnsupportedOperationException() } override fun getMessageBus(): MessageBus { throw UnsupportedOperationException() } override fun dispose() { throw UnsupportedOperationException() } } private val sdk: Sdk = object : Sdk, RootProvider { override fun getFiles(rootType: OrderRootType): Array = classpathRoots .map { StandardFileSystems.local().findFileByPath(it.file.path) } .filterNotNull() .toTypedArray() override fun addRootSetChangedListener(p0: RootProvider.RootSetChangedListener) { throw UnsupportedOperationException() } override fun addRootSetChangedListener(p0: RootProvider.RootSetChangedListener, p1: Disposable) { throw UnsupportedOperationException() } override fun getUrls(p0: OrderRootType): Array { throw UnsupportedOperationException() } override fun removeRootSetChangedListener(p0: RootProvider.RootSetChangedListener) { throw UnsupportedOperationException() } override fun getSdkModificator(): SdkModificator { throw UnsupportedOperationException() } override fun getName(): String = "" override fun getRootProvider(): RootProvider = this override fun getHomePath(): String? { throw UnsupportedOperationException() } override fun getVersionString(): String? { throw UnsupportedOperationException() } override fun getSdkAdditionalData(): SdkAdditionalData? { throw UnsupportedOperationException() } override fun clone(): Any { throw UnsupportedOperationException() } override fun getSdkType(): SdkTypeId { throw UnsupportedOperationException() } override fun getHomeDirectory(): VirtualFile? { throw UnsupportedOperationException() } override fun getUserData(p0: Key): T? { throw UnsupportedOperationException() } override fun putUserData(p0: Key, p1: T?) { throw UnsupportedOperationException() } } private val moduleSourceOrderEntry = object : ModuleSourceOrderEntry { override fun getFiles(p0: OrderRootType?): Array { throw UnsupportedOperationException() } override fun getPresentableName(): String { throw UnsupportedOperationException() } override fun getUrls(p0: OrderRootType?): Array { throw UnsupportedOperationException() } override fun getOwnerModule(): Module = module override fun accept(p0: RootPolicy?, p1: R?): R { throw UnsupportedOperationException() } override fun isValid(): Boolean { throw UnsupportedOperationException() } override fun compareTo(other: OrderEntry?): Int { throw UnsupportedOperationException() } override fun getRootModel(): ModuleRootModel = moduleRootManager override fun isSynthetic(): Boolean { throw UnsupportedOperationException() } } private val sdkOrderEntry = object : JdkOrderEntry { override fun getJdkName(): String? { throw UnsupportedOperationException() } override fun getJdk(): Sdk = sdk override fun getFiles(p0: OrderRootType?): Array { throw UnsupportedOperationException() } override fun getPresentableName(): String { throw UnsupportedOperationException() } override fun getUrls(p0: OrderRootType?): Array { throw UnsupportedOperationException() } override fun getOwnerModule(): Module { throw UnsupportedOperationException() } override fun accept(p0: RootPolicy?, p1: R?): R { throw UnsupportedOperationException() } override fun isValid(): Boolean { throw UnsupportedOperationException() } override fun getRootFiles(p0: OrderRootType?): Array? { throw UnsupportedOperationException() } override fun getRootUrls(p0: OrderRootType?): Array? { throw UnsupportedOperationException() } override fun compareTo(other: OrderEntry?): Int { throw UnsupportedOperationException() } override fun isSynthetic(): Boolean { throw UnsupportedOperationException() } } inner class MyModuleRootManager : ModuleRootManager() { override fun getExcludeRoots(): Array { throw UnsupportedOperationException() } override fun getContentEntries(): Array { throw UnsupportedOperationException() } override fun getExcludeRootUrls(): Array { throw UnsupportedOperationException() } override fun processOrder(p0: RootPolicy?, p1: R): R { throw UnsupportedOperationException() } override fun getSourceRoots(p0: Boolean): Array { throw UnsupportedOperationException() } override fun getSourceRoots(): Array { throw UnsupportedOperationException() } override fun getSourceRoots(p0: JpsModuleSourceRootType<*>): MutableList { throw UnsupportedOperationException() } override fun getSourceRoots(p0: MutableSet>): MutableList { throw UnsupportedOperationException() } override fun getContentRoots(): Array { throw UnsupportedOperationException() } override fun orderEntries(): OrderEnumerator = ProjectOrderEnumerator(project, null).using(object : RootModelProvider { override fun getModules(): Array = arrayOf(module) override fun getRootModel(p0: Module): ModuleRootModel = this@MyModuleRootManager }) override fun getModuleExtension(p0: Class?): T { throw UnsupportedOperationException() } override fun getDependencyModuleNames(): Array { throw UnsupportedOperationException() } override fun getModule(): Module = module override fun isSdkInherited(): Boolean { throw UnsupportedOperationException() } override fun getOrderEntries(): Array = arrayOf(moduleSourceOrderEntry, sdkOrderEntry) override fun getSourceRootUrls(): Array { throw UnsupportedOperationException() } override fun getSourceRootUrls(p0: Boolean): Array { throw UnsupportedOperationException() } override fun getSdk(): Sdk? { throw UnsupportedOperationException() } override fun getContentRootUrls(): Array { throw UnsupportedOperationException() } override fun getModuleDependencies(): Array { throw UnsupportedOperationException() } override fun getModuleDependencies(p0: Boolean): Array { throw UnsupportedOperationException() } override fun getModifiableModel(): ModifiableRootModel { throw UnsupportedOperationException() } override fun isDependsOn(p0: Module?): Boolean { throw UnsupportedOperationException() } override fun getFileIndex(): ModuleFileIndex { return this@CoreProjectFileIndex } override fun getDependencies(): Array { throw UnsupportedOperationException() } override fun getDependencies(p0: Boolean): Array { throw UnsupportedOperationException() } } val moduleRootManager = MyModuleRootManager() override fun getContentRootForFile(p0: VirtualFile): VirtualFile? { throw UnsupportedOperationException() } override fun getContentRootForFile(p0: VirtualFile, p1: Boolean): VirtualFile? { throw UnsupportedOperationException() } override fun getPackageNameByDirectory(p0: VirtualFile): String? { throw UnsupportedOperationException() } override fun isInLibrarySource(file: VirtualFile): Boolean = false override fun getClassRootForFile(file: VirtualFile): VirtualFile? = classpathRoots.firstOrNull { it.contains(file) }?.let { StandardFileSystems.local().findFileByPath(it.file.path) } override fun getOrderEntriesForFile(file: VirtualFile): List = if (classpathRoots.contains(file)) listOf(sdkOrderEntry) else emptyList() override fun isInLibraryClasses(file: VirtualFile): Boolean = classpathRoots.contains(file) override fun isExcluded(p0: VirtualFile): Boolean { throw UnsupportedOperationException() } override fun getSourceRootForFile(p0: VirtualFile): VirtualFile? { throw UnsupportedOperationException() } override fun isUnderIgnored(p0: VirtualFile): Boolean { throw UnsupportedOperationException() } override fun isLibraryClassFile(p0: VirtualFile): Boolean { throw UnsupportedOperationException() } override fun getModuleForFile(file: VirtualFile): Module? = if (sourceRoots.contains(file)) module else null private fun List.contains(file: VirtualFile): Boolean = any { it.contains(file) } override fun getModuleForFile(p0: VirtualFile, p1: Boolean): Module? { throw UnsupportedOperationException() } override fun isInSource(p0: VirtualFile): Boolean { throw UnsupportedOperationException() } override fun isIgnored(p0: VirtualFile): Boolean { throw UnsupportedOperationException() } override fun isContentSourceFile(p0: VirtualFile): Boolean { throw UnsupportedOperationException() } override fun isInSourceContent(file: VirtualFile): Boolean = sourceRoots.contains(file) override fun iterateContent(p0: ContentIterator): Boolean { throw UnsupportedOperationException() } override fun isInContent(p0: VirtualFile): Boolean { throw UnsupportedOperationException() } override fun iterateContentUnderDirectory(p0: VirtualFile, p1: ContentIterator): Boolean { throw UnsupportedOperationException() } override fun isInTestSourceContent(file: VirtualFile): Boolean = false override fun isUnderSourceRootOfType(p0: VirtualFile, p1: MutableSet>): Boolean { throw UnsupportedOperationException() } override fun getOrderEntryForFile(p0: VirtualFile): OrderEntry? { throw UnsupportedOperationException() } } class CoreProjectRootManager(val projectFileIndex: CoreProjectFileIndex) : ProjectRootManager() { override fun orderEntries(): OrderEnumerator { throw UnsupportedOperationException() } override fun orderEntries(p0: MutableCollection): OrderEnumerator { throw UnsupportedOperationException() } override fun getContentRootsFromAllModules(): Array? { throw UnsupportedOperationException() } override fun setProjectSdk(p0: Sdk?) { throw UnsupportedOperationException() } override fun setProjectSdkName(p0: String?) { throw UnsupportedOperationException() } override fun getModuleSourceRoots(p0: MutableSet>): MutableList { throw UnsupportedOperationException() } override fun getContentSourceRoots(): Array { throw UnsupportedOperationException() } override fun getFileIndex(): ProjectFileIndex = projectFileIndex override fun getProjectSdkName(): String? { throw UnsupportedOperationException() } override fun getProjectSdk(): Sdk? { throw UnsupportedOperationException() } override fun getContentRoots(): Array { throw UnsupportedOperationException() } override fun getContentRootUrls(): MutableList { throw UnsupportedOperationException() } } fun ContentRoot.contains(file: VirtualFile) = when (this) { is JvmContentRoot -> { val path = if (file.fileSystem.protocol == StandardFileSystems.JAR_PROTOCOL) StandardFileSystems.getVirtualFileForJar(file)?.path ?: file.path else file.path File(path).startsWith(this.file.absoluteFile) } is KotlinSourceRoot -> File(file.path).startsWith(File(this.path).absoluteFile) else -> false }