diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt index 3781e47968b..2656b51b9e4 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt @@ -369,7 +369,7 @@ private class LibrarySourceScope(project: Project, private val library: Library) } //TODO: (module refactoring) android sdk has modified scope -private class SdkScope(project: Project, private val sdk: Sdk) : +private class SdkScope(project: Project, val sdk: Sdk) : LibraryScopeBase(project, sdk.rootProvider.getFiles(OrderRootType.CLASSES), arrayOf()) { override fun equals(other: Any?) = other is SdkScope && sdk == other.sdk diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt index 5feb15d4a7d..b566a7c1f49 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.script.KotlinScriptDefinition +import java.io.File import kotlin.script.experimental.dependencies.ScriptDependencies class ScriptModuleSearchScope(val scriptFile: VirtualFile, baseScope: GlobalSearchScope) : DelegatingGlobalSearchScope(baseScope) { @@ -61,8 +62,9 @@ fun findJdk(dependencies: ScriptDependencies?, project: Project): Sdk? { null } - return allJdks.find { javaHome != null && it.homePath == javaHome } ?: ProjectRootManager.getInstance(project).projectSdk - ?: allJdks.firstOrNull() + return allJdks.find { javaHome != null && File(it.homePath).canonicalPath == javaHome } + ?: ProjectRootManager.getInstance(project).projectSdk + ?: allJdks.firstOrNull() } sealed class ScriptDependenciesInfo(val project: Project) : IdeaModuleInfo, BinaryModuleInfo { diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDefinitionsManager.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDefinitionsManager.kt index a725792f003..4ab94e5f9fd 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDefinitionsManager.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDefinitionsManager.kt @@ -24,6 +24,11 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.JavaSdk import com.intellij.openapi.projectRoots.ProjectJdkTable import com.intellij.openapi.projectRoots.ex.PathUtilEx +import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.vfs.VfsUtil +import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.kotlin.idea.caches.project.SdkInfo +import org.jetbrains.kotlin.idea.caches.project.getScriptRelatedModuleInfo import org.jetbrains.kotlin.script.KotlinScriptDefinition import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate import org.jetbrains.kotlin.script.ScriptDefinitionProvider @@ -223,7 +228,9 @@ class BundledKotlinScriptDependenciesResolver(private val project: Project) : De scriptContents: ScriptContents, environment: Environment ): DependenciesResolver.ResolveResult { - val javaHome = getScriptSDK(project) + val virtualFile = scriptContents.file?.let { VfsUtil.findFileByIoFile(it, true) } + + val javaHome = getScriptSDK(project, virtualFile) val dependencies = ScriptDependencies( javaHome = javaHome?.let(::File), classpath = with(PathUtil.kotlinPathsForIdeaPlugin) { @@ -237,8 +244,18 @@ class BundledKotlinScriptDependenciesResolver(private val project: Project) : De return dependencies.asSuccess() } - private fun getScriptSDK(project: Project): String? { - val jdk = ProjectJdkTable.getInstance().allJdks.firstOrNull { sdk -> sdk.sdkType is JavaSdk } ?: PathUtilEx.getAnyJdk(project) + private fun getScriptSDK(project: Project, virtualFile: VirtualFile?): String? { + if (virtualFile != null) { + val dependentModuleSourceInfo = getScriptRelatedModuleInfo(project, virtualFile) + val sdk = dependentModuleSourceInfo?.dependencies()?.filterIsInstance()?.singleOrNull()?.sdk + if (sdk != null) { + return sdk.homePath + } + } + + val jdk = ProjectRootManager.getInstance(project).projectSdk + ?: ProjectJdkTable.getInstance().allJdks.firstOrNull { sdk -> sdk.sdkType is JavaSdk } + ?: PathUtilEx.getAnyJdk(project) return jdk?.homePath } } diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt index 5877302fb59..24bc81b16fc 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfoTest.kt @@ -18,20 +18,29 @@ package org.jetbrains.kotlin.idea.caches.resolve import com.intellij.openapi.module.Module import com.intellij.openapi.module.StdModuleTypes +import com.intellij.openapi.projectRoots.ProjectJdkTable import com.intellij.openapi.roots.DependencyScope +import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ModuleRootModificationUtil +import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess import com.intellij.testFramework.ModuleTestCase +import com.intellij.testFramework.PlatformTestCase import com.intellij.testFramework.PsiTestUtil import com.intellij.testFramework.UsefulTestCase import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.idea.caches.project.* import org.jetbrains.kotlin.idea.framework.CommonLibraryKind import org.jetbrains.kotlin.idea.framework.JSLibraryKind +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.* +import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.test.util.addDependency import org.jetbrains.kotlin.test.util.jarRoot import org.jetbrains.kotlin.test.util.projectLibrary +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance import org.junit.Assert class IdeaModuleInfoTest : ModuleTestCase() { @@ -319,12 +328,108 @@ class IdeaModuleInfoTest : ModuleTestCase() { stdlibJs.classes.assertAdditionalLibraryDependencies(stdlibCommon.classes) } + fun testScriptDependenciesForModule() { + val a = module("a") + val b = module("b") + + with(createFileInModule(a, "script.kts").moduleInfo) { + dependencies().contains(a.production) + dependencies().contains(a.test) + !dependencies().contains(b.production) + dependencies().firstIsInstance() + } + } + + override fun setUp() { + super.setUp() + VfsRootAccess.allowRootAccess("C:/Work/Projects/kotlin/") + } + + fun testScriptDependenciesForProject() { + val a = module("a") + + val script = createFileInProject("script.kts").moduleInfo + + !script.dependencies().contains(a.production) + !script.dependencies().contains(a.test) + + script.dependencies().firstIsInstance() + } + + fun testSdkForScript() { + runWriteAction { + ProjectJdkTable.getInstance().addJdk(mockJdk6()) + ProjectJdkTable.getInstance().addJdk(mockJdk9()) + } + + with(createFileInProject("script.kts").moduleInfo) { + dependencies().filterIsInstance().single { it.sdk == mockJdk6() } + } + } + + fun testSdkForScriptProjectSdk() { + runWriteAction { + ProjectJdkTable.getInstance().addJdk(mockJdk6()) + ProjectJdkTable.getInstance().addJdk(mockJdk9()) + + ProjectRootManager.getInstance(project).projectSdk = mockJdk9() + } + + with(createFileInProject("script.kts").moduleInfo) { + dependencies().filterIsInstance().single { it.sdk == mockJdk9() } + } + } + + fun testSdkForScriptModuleSdk() { + val a = module("a") + + runWriteAction { + ProjectJdkTable.getInstance().addJdk(mockJdk6()) + ProjectJdkTable.getInstance().addJdk(mockJdk9()) + + ProjectRootManager.getInstance(project).projectSdk = mockJdk6() + with(ModuleRootManager.getInstance(a).modifiableModel) { + sdk = mockJdk9() + commit() + } + } + + with(createFileInModule(a, "script.kts").moduleInfo) { + dependencies().filterIsInstance().first { it.sdk == mockJdk9() } + } + } + + private fun createFileInModule(module: Module, fileName: String, inTests: Boolean = false): VirtualFile { + val fileToCopyIO = createTempFile(fileName, "") + + for (contentEntry in ModuleRootManager.getInstance(module).contentEntries) { + for (sourceFolder in contentEntry.sourceFolders) { + if (((!inTests && !sourceFolder.isTestSource) || (inTests && sourceFolder.isTestSource)) && sourceFolder.file != null) { + return runWriteAction { + PlatformTestCase.getVirtualFile(fileToCopyIO).copy(this, sourceFolder.file!!, fileName) + } + } + } + } + + error("Couldn't find source folder in ${module.name}") + } + + private fun createFileInProject(fileName: String): VirtualFile { + return runWriteAction { + PlatformTestCase.getVirtualFile(createTempFile(fileName, "")).copy(this, project.baseDir, fileName) + } + } + private fun Module.addDependency( other: Module, dependencyScope: DependencyScope = DependencyScope.COMPILE, exported: Boolean = false ) = ModuleRootModificationUtil.addDependency(this, other, dependencyScope, exported) + private val VirtualFile.moduleInfo: IdeaModuleInfo + get() = getModuleInfoByVirtualFile(project, this)!! + private val Module.production: ModuleProductionSourceInfo get() = productionSourceInfo()!! @@ -361,13 +466,23 @@ class IdeaModuleInfoTest : ModuleTestCase() { UsefulTestCase.assertSameElements(this.getDependentModules(), expected.toList()) } - private fun stdlibCommon(): Library = projectLibrary("kotlin-stdlib-common", - ForTestCompileRuntime.stdlibCommonForTests().jarRoot, - kind = CommonLibraryKind) + private fun stdlibCommon(): Library = projectLibrary( + "kotlin-stdlib-common", + ForTestCompileRuntime.stdlibCommonForTests().jarRoot, + kind = CommonLibraryKind + ) private fun stdlibJvm(): Library = projectLibrary("kotlin-stdlib", ForTestCompileRuntime.runtimeJarForTests().jarRoot) - private fun stdlibJs(): Library = projectLibrary("kotlin-stdlib-js", - ForTestCompileRuntime.runtimeJarForTests().jarRoot, - kind = JSLibraryKind) + private fun stdlibJs(): Library = projectLibrary( + "kotlin-stdlib-js", + ForTestCompileRuntime.runtimeJarForTests().jarRoot, + kind = JSLibraryKind + ) + + override fun tearDown() { + clearSdkTable(testRootDisposable) + + super.tearDown() + } }