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 cc99e9177d5..9f7266a724f 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 @@ -317,8 +317,14 @@ object KotlinToJVMBytecodeCompiler { catch (e: java.lang.NoSuchMethodException) { for (ctor in scriptClass.kotlin.constructors) { val (ctorArgs, scriptArgsLeft) = ctor.parameters.fold(Pair(emptyList(), scriptArgs), ::foldingFunc) - if (ctorArgs.size == ctor.parameters.size && (scriptArgsLeft == null || scriptArgsLeft.isEmpty())) - return ctor.call(*ctorArgs.toTypedArray()) + if (ctorArgs.size <= ctor.parameters.size && (scriptArgsLeft == null || scriptArgsLeft.isEmpty())) { + val argsMap = ctorArgs.zip(ctor.parameters) { a, p -> Pair(p, a) }.toMap() + try { + return ctor.callBy(argsMap) + } + catch (e: Exception) { // TODO: find the exact exception type thrown then callBy fails + } + } } } return null diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinConfigurableScriptDefinition.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinConfigurableScriptDefinition.kt index a650ec68500..78afdc62a2d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinConfigurableScriptDefinition.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinConfigurableScriptDefinition.kt @@ -92,7 +92,7 @@ private fun tryFindKotlinPathsForScriptClasspathEnvVars(project: Project): Kotli .map { it() } .firstOrNull { it.runtimePath.exists() } -private fun generateKotlinScriptClasspathEnvVarsFromPaths(project: Project, paths: KotlinPaths?): Map> = +fun generateKotlinScriptClasspathEnvVarsFromPaths(project: Project, paths: KotlinPaths?): Map> = mapOf("kotlin-runtime" to (paths?.run { listOf(runtimePath.canonicalPath) } ?: emptyList()), "kotlin-reflect" to (paths?.run { listOf(reflectPath.canonicalPath) } ?: emptyList()), "project-root" to listOf(project.basePath ?: "."), diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt index cec3971b4c8..0c8e8e0db2c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt @@ -65,7 +65,9 @@ class KotlinScriptDefinitionProvider { } fun removeScriptDefinition(scriptDefinition: KotlinScriptDefinition) { - definitions.remove(scriptDefinition) + definitionsLock.write { + definitions.remove(scriptDefinition) + } } companion object { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfos.kt index ce490d023fb..121240dbacd 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfos.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfos.kt @@ -290,40 +290,40 @@ internal object NotUnderContentRootModuleInfo : IdeaModuleInfo { override fun dependencies(): List = listOf(this) } -class CustomizedScriptModuleSearchScope(val scriptFile: VirtualFile, baseScope: GlobalSearchScope) : DelegatingGlobalSearchScope(baseScope) { - override fun equals(other: Any?) = other is CustomizedScriptModuleSearchScope && scriptFile == other.scriptFile && super.equals(other) +class ScriptModuleSearchScope(val scriptFile: VirtualFile, baseScope: GlobalSearchScope) : DelegatingGlobalSearchScope(baseScope) { + override fun equals(other: Any?) = other is ScriptModuleSearchScope && scriptFile == other.scriptFile && super.equals(other) override fun hashCode() = scriptFile.hashCode() * 73 * super.hashCode() } -internal data class CustomizedScriptModuleInfo(val project: Project, val module: Module?, val virtualFile: VirtualFile, - val scriptDefinition: KotlinScriptDefinition, - val scriptExtraImports: List) : IdeaModuleInfo { +internal data class ScriptModuleInfo(val project: Project, val module: Module?, val scriptFile: VirtualFile, + val scriptDefinition: KotlinScriptDefinition, + val scriptExtraImports: List) : IdeaModuleInfo { override val moduleOrigin: ModuleOrigin get() = ModuleOrigin.OTHER override val name: Name = Name.special("<$SCRIPT_NAME_PREFIX${scriptDefinition.name}>") - override fun contentScope(): CustomizedScriptModuleSearchScope { + override fun contentScope(): ScriptModuleSearchScope { val dependenciesRoots = dependenciesRoots() - return CustomizedScriptModuleSearchScope( - virtualFile, + return ScriptModuleSearchScope( + scriptFile, if (dependenciesRoots.isEmpty()) GlobalSearchScope.EMPTY_SCOPE else GlobalSearchScope.union(dependenciesRoots.map { FileLibraryScope(project, it) }.toTypedArray())) } private fun dependenciesRoots(): List { // TODO: find out whether it should be cashed (some changes listener should be implemented for the cached roots) - val virtualFileManager = VirtualFileManager.getInstance() val jarfs = StandardFileSystems.jar() return (scriptDefinition.getScriptDependenciesClasspath() + scriptExtraImports.flatMap { it.classpath }) .map { File(it).canonicalFile } .distinct() - .map { + .mapNotNull { + // TODO: ensure that the entries are checked elsewhere, so diagnostics is delivered to a user if files are not correctly specified if (it.isFile) - jarfs.findFileByPath(it.absolutePath + URLUtil.JAR_SEPARATOR) ?: throw FileNotFoundException("Classpath entry points to a file that is not a JAR archive: ${it.canonicalPath}") + jarfs.findFileByPath(it.absolutePath + URLUtil.JAR_SEPARATOR) ?: null // diag: Classpath entry points to a file that is not a JAR archive else - virtualFileManager.findFileByUrl("file://${it.absolutePath}") ?: throw FileNotFoundException("Classpath entry points to a non-existent location: ${it.canonicalPath}") + StandardFileSystems.local().findFileByPath(it.absolutePath) ?: null // diag: Classpath entry points to a non-existent location } } @@ -337,7 +337,6 @@ internal data class CustomizedScriptModuleInfo(val project: Project, val module: } class FileLibraryScope(project: Project, private val libraryRoot: VirtualFile) : GlobalSearchScope(project) { - val cachedEntries : MutableSet = hashSetOf() override fun contains(file: VirtualFile): Boolean = VfsUtilCore.isAncestor(libraryRoot, file, false) @@ -353,53 +352,6 @@ class FileLibraryScope(project: Project, private val libraryRoot: VirtualFile) : override fun hashCode() = libraryRoot.hashCode() } -private data class FakeFileLibrary(val libraryRoot: VirtualFile) : Library { - override fun getFiles(rootType: OrderRootType): Array = arrayOf(libraryRoot) - - override fun getUrls(rootType: OrderRootType): Array = arrayOf(libraryRoot.url) - - override fun getName(): String? = libraryRoot.name - - override fun getModifiableModel(): Library.ModifiableModel { throw UnsupportedOperationException() } - - override fun getTable(): LibraryTable? = null - - override fun getRootProvider(): RootProvider { throw UnsupportedOperationException() } - - override fun isJarDirectory(url: String): Boolean { throw UnsupportedOperationException() } - - override fun isJarDirectory(url: String, rootType: OrderRootType): Boolean { throw UnsupportedOperationException() } - - override fun isValid(url: String, rootType: OrderRootType): Boolean { throw UnsupportedOperationException() } - - override fun readExternal(element: Element?) { throw UnsupportedOperationException() } - - override fun writeExternal(element: Element?) { throw UnsupportedOperationException() } - - override fun dispose() { } -} - -private class FileLibraryModuleInfo(project: Project, val libraryRoot: VirtualFile) : LibraryInfo(project, FakeFileLibrary(libraryRoot)) { - - override val moduleOrigin: ModuleOrigin - get() = ModuleOrigin.OTHER - - override val name: Name = Name.special("<$LIBRARY_NAME_PREFIX${libraryRoot.nameWithoutExtension}>") - - override fun contentScope() = FileLibraryScope(project, libraryRoot) - - override fun dependencies(): List = emptyList() - - override fun toString() = "FileLibraryModuleInfo(root=${libraryRoot.name})" - - override fun equals(other: Any?): Boolean { - if (this === other) return true - return (other is FileLibraryModuleInfo && libraryRoot == other.libraryRoot) - } - - override fun hashCode(): Int = 47 * libraryRoot.hashCode() -} - private class LibraryWithoutSourceScope(project: Project, private val library: Library) : LibraryScopeBase(project, library.getFiles(OrderRootType.CLASSES), arrayOf()) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt index 52e9b446c4a..4263b83dd53 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt @@ -121,52 +121,46 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } val dependenciesForSyntheticFileCache = listOf(PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, filesModificationTracker) val debugName = "completion/highlighting in $syntheticFileModule for files ${files.joinToString { it.name }} for platform $targetPlatform" + + fun makeGlobalResolveSessionProvider(reuseDataFrom: ProjectResolutionFacade? = null, + moduleFilter: (IdeaModuleInfo) -> Boolean = { true } + ): CachedValueProvider.Result { + return globalResolveSessionProvider( + debugName, + project, + targetPlatform, + sdk, + commonGlobalContext = globalContext, + syntheticFiles = files, + reuseDataFrom = reuseDataFrom, + moduleFilter = moduleFilter, + dependencies = dependenciesForSyntheticFileCache + ) + } + return when { syntheticFileModule is ModuleSourceInfo -> { val dependentModules = syntheticFileModule.getDependentModules() ProjectResolutionFacade(project, globalContext.storageManager) { - globalResolveSessionProvider( - debugName, - project, - targetPlatform, - sdk, - commonGlobalContext = globalContext, - syntheticFiles = files, + makeGlobalResolveSessionProvider( reuseDataFrom = globalFacade(targetPlatform, sdk), - moduleFilter = { it in dependentModules }, - dependencies = dependenciesForSyntheticFileCache - ) + moduleFilter = { it in dependentModules }) } } - syntheticFileModule is CustomizedScriptModuleInfo -> { + syntheticFileModule is ScriptModuleInfo -> { ProjectResolutionFacade(project, globalContext.storageManager) { - globalResolveSessionProvider( - debugName, - project, - targetPlatform, - sdk, - commonGlobalContext = globalContext, - syntheticFiles = files, - reuseDataFrom = librariesFacade(targetPlatform, sdk), - moduleFilter = { true }, - dependencies = dependenciesForSyntheticFileCache + makeGlobalResolveSessionProvider( + reuseDataFrom = librariesFacade(targetPlatform, sdk) ) } } syntheticFileModule is LibrarySourceInfo || syntheticFileModule is NotUnderContentRootModuleInfo -> { ProjectResolutionFacade(project, globalContext.storageManager) { - globalResolveSessionProvider( - debugName, - project, - targetPlatform, - sdk, - commonGlobalContext = globalContext, - syntheticFiles = files, + makeGlobalResolveSessionProvider( reuseDataFrom = librariesFacade(targetPlatform, sdk), - moduleFilter = { it == syntheticFileModule }, - dependencies = dependenciesForSyntheticFileCache + moduleFilter = { it == syntheticFileModule } ) } } @@ -177,16 +171,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { // (file under both classes and sources root) LOG.warn("Creating cache with synthetic files ($files) in classes of library $syntheticFileModule") ProjectResolutionFacade(project, globalContext.storageManager) { - globalResolveSessionProvider( - debugName, - project, - targetPlatform, - sdk, - commonGlobalContext = globalContext, - syntheticFiles = files, - moduleFilter = { true }, - dependencies = dependenciesForSyntheticFileCache - ) + makeGlobalResolveSessionProvider() } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/getModuleInfo.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/getModuleInfo.kt index 9bdcbb3d44d..7708109aa50 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/getModuleInfo.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/getModuleInfo.kt @@ -125,7 +125,7 @@ private fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFil val scriptDefinition = getScriptDefinition(virtualFile, project) if (scriptDefinition != null) - return CustomizedScriptModuleInfo(project, module, virtualFile, scriptDefinition, getScriptExtraImports(virtualFile, project)) + return ScriptModuleInfo(project, module, virtualFile, scriptDefinition, getScriptExtraImports(virtualFile, project)) return NotUnderContentRootModuleInfo } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/scopeUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/scopeUtils.kt index 5bf4dfdfa78..944c4f0baa3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/scopeUtils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/scopeUtils.kt @@ -32,7 +32,7 @@ fun getResolveScope(file: KtFile): GlobalSearchScope { return when (file.getModuleInfo()) { is ModuleSourceInfo -> KotlinSourceFilterScope.sourceAndClassFiles(file.resolveScope, file.project) - is CustomizedScriptModuleInfo -> file.getModuleInfo().contentScope() + is ScriptModuleInfo -> file.getModuleInfo().contentScope() else -> GlobalSearchScope.EMPTY_SCOPE } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptConfigurationManager.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptConfigurationManager.kt index 4e3854910fc..2a64690d0b9 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptConfigurationManager.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptConfigurationManager.kt @@ -30,6 +30,7 @@ import com.intellij.util.indexing.IndexableSetContributor import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.idea.caches.resolve.FileLibraryScope import org.jetbrains.kotlin.script.* +import org.jetbrains.kotlin.utils.PathUtil import java.io.File import java.io.FileNotFoundException import java.lang.ref.WeakReference @@ -44,7 +45,7 @@ class KotlinScriptConfigurationManager(project: Project, private val kotlinScriptDependenciesIndexableSetContributor: KotlinScriptDependenciesIndexableSetContributor? ) : AbstractProjectComponent(project) { - private val kotlinEnvVars: Map> by lazy { generateKotlinScriptClasspathEnvVars(myProject) } + private val kotlinEnvVars: Map> by lazy { generateKotlinScriptClasspathEnvVarsFromPaths(myProject, PathUtil.getKotlinPathsForIdeaPlugin()) } init { reloadScriptDefinitions() @@ -57,7 +58,7 @@ class KotlinScriptConfigurationManager(project: Project, override fun after(events: List) { val changedExtraImportConfigs = ArrayList() var anyScriptDefinitionChanged = false - events.filter { it is VFileEvent }.forEach { + events.forEach { it.file?.let { if (isScriptDefinitionConfigFile(it)) { anyScriptDefinitionChanged = true @@ -155,10 +156,8 @@ class KotlinScriptConfigurationManager(project: Project, class KotlinScriptDependenciesIndexableSetContributor : IndexableSetContributor() { - override fun getAdditionalProjectRootsToIndex(project: Project): Set { - return super.getAdditionalProjectRootsToIndex(project) + - KotlinScriptConfigurationManager.getInstance(project).getAllScriptsClasspath() - } + override fun getAdditionalProjectRootsToIndex(project: Project): Set = + KotlinScriptConfigurationManager.getInstance(project).getAllScriptsClasspath().toSet() override fun getAdditionalRootsToIndex(): Set = emptySet() } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptDependenciesClassFinder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptDependenciesClassFinder.kt index 4c0b101099d..55ae925cbf1 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptDependenciesClassFinder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptDependenciesClassFinder.kt @@ -25,11 +25,10 @@ import com.intellij.psi.PsiClass import com.intellij.psi.search.EverythingGlobalScope import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.containers.ConcurrentFactoryMap -import org.jetbrains.kotlin.idea.caches.resolve.CustomizedScriptModuleSearchScope +import org.jetbrains.kotlin.idea.caches.resolve.ScriptModuleSearchScope import org.jetbrains.kotlin.load.java.JavaClassFinderImpl import org.jetbrains.kotlin.resolve.jvm.KotlinSafeClassFinder -@Suppress("unused") // project extension class KotlinScriptDependenciesClassFinder(project: Project, private val kotlinScriptConfigurationManager: KotlinScriptConfigurationManager ) : NonClasspathClassFinder(project), KotlinSafeClassFinder { @@ -46,8 +45,8 @@ class KotlinScriptDependenciesClassFinder(project: Project, override fun calcClassRoots(): List = kotlinScriptConfigurationManager.getAllScriptsClasspath() override fun getCache(scope: GlobalSearchScope?): PackageDirectoryCache = - (scope as? CustomizedScriptModuleSearchScope ?: - (scope as? JavaClassFinderImpl.DelegatingGlobalSearchScopeWithBaseAccess)?.base as? CustomizedScriptModuleSearchScope + (scope as? ScriptModuleSearchScope ?: + (scope as? JavaClassFinderImpl.FilterOutKotlinSourceFilesScope)?.base as? ScriptModuleSearchScope )?.let { myCaches.get(it.scriptFile) } ?: super.getCache(scope) @@ -60,8 +59,8 @@ class KotlinScriptDependenciesClassFinder(project: Project, override fun findClass(qualifiedName: String, scope: GlobalSearchScope): PsiClass? = super.findClass(qualifiedName, scope)?.let { aClass -> when { - scope is CustomizedScriptModuleSearchScope || - (scope as? JavaClassFinderImpl.DelegatingGlobalSearchScopeWithBaseAccess)?.base is CustomizedScriptModuleSearchScope || + scope is ScriptModuleSearchScope || + (scope as? JavaClassFinderImpl.FilterOutKotlinSourceFilesScope)?.base is ScriptModuleSearchScope || scope is EverythingGlobalScope || aClass.containingFile?.virtualFile.let { file -> file != null &&