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 4d3c2dd1982..ecf006455eb 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 @@ -44,11 +44,13 @@ data class ScriptModuleInfo( override fun dependencies(): List { return arrayListOf(this).apply { val scriptDependentModules = ScriptAdditionalIdeaDependenciesProvider.getRelatedModules(scriptFile, project) - if (scriptDependentModules.isNotEmpty()) { - scriptDependentModules.mapNotNull { it.productionSourceInfo() ?: it.testSourceInfo() }.forEach { - this@apply.add(it) - this@apply.addAll(it.dependencies()) - } + scriptDependentModules.forEach { + addAll(it.correspondingModuleInfos()) + } + + val scriptDependentLibraries = ScriptAdditionalIdeaDependenciesProvider.getRelatedLibraries(scriptFile, project) + scriptDependentLibraries.forEach { + addAll(createLibraryInfo(project, it)) } val dependenciesInfo = ScriptDependenciesInfo.ForFile(project, scriptFile, scriptDefinition) diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptAdditionalIdeaDependenciesProvider.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptAdditionalIdeaDependenciesProvider.kt index 9b078aa902f..be31fe371b3 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptAdditionalIdeaDependenciesProvider.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptAdditionalIdeaDependenciesProvider.kt @@ -9,10 +9,12 @@ import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.VirtualFile abstract class ScriptAdditionalIdeaDependenciesProvider { abstract fun getRelatedModules(file: VirtualFile, project: Project): List + abstract fun getRelatedLibraries(file: VirtualFile, project: Project): List companion object { private val EP_NAME: ExtensionPointName = @@ -23,5 +25,11 @@ abstract class ScriptAdditionalIdeaDependenciesProvider { .filterIsInstance() .flatMap { it.getRelatedModules(file, project) } } + + fun getRelatedLibraries(file: VirtualFile, project: Project): List { + return Extensions.getArea(project).getExtensionPoint(EP_NAME).extensions + .filterIsInstance() + .flatMap { it.getRelatedLibraries(file, project) } + } } } \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/core/script/GradleScriptAdditionalIdeaDependenciesProvider.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/core/script/GradleScriptAdditionalIdeaDependenciesProvider.kt index bae8f7fad47..75ac27792b5 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/core/script/GradleScriptAdditionalIdeaDependenciesProvider.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/core/script/GradleScriptAdditionalIdeaDependenciesProvider.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.idea.core.script.dependencies.ScriptAdditionalIdeaDependenciesProvider import org.jetbrains.plugins.gradle.settings.GradleProjectSettings @@ -32,4 +33,8 @@ class GradleScriptAdditionalIdeaDependenciesProvider : ScriptAdditionalIdeaDepen } } } + + override fun getRelatedLibraries(file: VirtualFile, project: Project): List { + return emptyList() + } } \ No newline at end of file diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/ScratchAdditionalIdeaDependenciesProvider.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/ScratchAdditionalIdeaDependenciesProvider.kt index a0ebaa24cf2..2676ccb9d64 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/ScratchAdditionalIdeaDependenciesProvider.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/ScratchAdditionalIdeaDependenciesProvider.kt @@ -9,18 +9,50 @@ import com.intellij.ide.scratch.ScratchFileService import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.* +import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.idea.core.script.dependencies.ScriptAdditionalIdeaDependenciesProvider import org.jetbrains.kotlin.idea.core.script.scriptRelatedModuleName +import org.jetbrains.kotlin.utils.addIfNotNull class ScratchAdditionalIdeaDependenciesProvider : ScriptAdditionalIdeaDependenciesProvider() { + override fun getRelatedModules(file: VirtualFile, project: Project): List { - if (ScratchFileService.isInScratchRoot(file)) { - val scratchModule = file.scriptRelatedModuleName?.let { ModuleManager.getInstance(project).findModuleByName(it) } - if (scratchModule != null) { - return listOf(scratchModule) + if (!ScratchFileService.isInScratchRoot(file)) return emptyList() + + val scratchModule = file.scriptRelatedModuleName?.let { + ModuleManager.getInstance(project).findModuleByName(it) + } ?: return emptyList() + + val modules = linkedSetOf(scratchModule) + moduleDependencyEnumerator(scratchModule).withoutLibraries().forEach { orderEntry -> + when (orderEntry) { + is ModuleSourceOrderEntry -> modules.add(orderEntry.getOwnerModule()) + is ModuleOrderEntry -> modules.addIfNotNull(orderEntry.module) + } + true + } + return modules.toList() + } + + override fun getRelatedLibraries(file: VirtualFile, project: Project): List { + if (!ScratchFileService.isInScratchRoot(file)) return emptyList() + + val result = linkedSetOf() + getRelatedModules(file, project).forEach { + moduleDependencyEnumerator(it).withoutDepModules().forEach { orderEntry -> + if (orderEntry is LibraryOrderEntry) { + result.addIfNotNull(orderEntry.library) + } + true } } - return emptyList() + return result.toList() + } + + private fun moduleDependencyEnumerator(it: Module): OrderEnumerator { + return ModuleRootManager.getInstance(it).orderEntries() + .compileOnly().withoutSdk().recursively().exportedOnly() } } \ No newline at end of file diff --git a/idea/testData/scratch/libraryDepWithKotlinTest.comp.after b/idea/testData/scratch/libraryDepWithKotlinTest.comp.after new file mode 100644 index 00000000000..1dccf80eb6d --- /dev/null +++ b/idea/testData/scratch/libraryDepWithKotlinTest.comp.after @@ -0,0 +1,2 @@ +val a: Int? = 1 // RESULT: val a: Int? +kotlin.test.assertNotNull(1) // RESULT: 1 \ No newline at end of file diff --git a/idea/testData/scratch/libraryDepWithKotlinTest.kts b/idea/testData/scratch/libraryDepWithKotlinTest.kts new file mode 100644 index 00000000000..766071b1ec6 --- /dev/null +++ b/idea/testData/scratch/libraryDepWithKotlinTest.kts @@ -0,0 +1,2 @@ +val a: Int? = 1 +kotlin.test.assertNotNull(1) \ No newline at end of file diff --git a/idea/testData/scratch/libraryDepWithKotlinTest.repl.after b/idea/testData/scratch/libraryDepWithKotlinTest.repl.after new file mode 100644 index 00000000000..ce401f63778 --- /dev/null +++ b/idea/testData/scratch/libraryDepWithKotlinTest.repl.after @@ -0,0 +1,2 @@ +val a: Int? = 1 +kotlin.test.assertNotNull(1) // RESULT: res1: kotlin.Int = 1 \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/scratch/AbstractScratchRunActionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/scratch/AbstractScratchRunActionTest.kt index 9e03e25946b..37ff0053449 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/scratch/AbstractScratchRunActionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/scratch/AbstractScratchRunActionTest.kt @@ -12,7 +12,6 @@ import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.roots.CompilerModuleExtension import com.intellij.openapi.roots.ModuleRootModificationUtil import com.intellij.openapi.util.io.FileUtil -import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess import com.intellij.psi.PsiDocumentManager @@ -22,6 +21,7 @@ import com.intellij.testFramework.MapDataContext import com.intellij.testFramework.PsiTestUtil import com.intellij.testFramework.TestActionEvent import com.intellij.util.ui.UIUtil +import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingUtil @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.MockLibraryUtil +import org.jetbrains.kotlin.utils.PathUtil import org.junit.Assert import java.io.File import java.util.* @@ -171,11 +172,12 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() { override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory() - override fun getProjectDescriptor(): com.intellij.testFramework.LightProjectDescriptor { - val testName = StringUtil.toLowerCase(getTestName(false)) + override fun getProjectDescriptor(): com.intellij.testFramework.LightProjectDescriptor { + val testName = getTestName(false) return when { - testName.endsWith("NoRuntime") -> KotlinLightProjectDescriptor.INSTANCE + testName.endsWith("WithKotlinTest") -> INSTANCE_WITH_KOTLIN_TEST + testName.endsWith("NoRuntime") -> INSTANCE_WITHOUT_RUNTIME else -> KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK } } @@ -197,4 +199,19 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() { runWriteAction { file.delete(this) } } } + + companion object { + private val INSTANCE_WITH_KOTLIN_TEST = object : KotlinWithJdkAndRuntimeLightProjectDescriptor( + arrayListOf( + ForTestCompileRuntime.runtimeJarForTests(), + PathUtil.kotlinPathsForDistDirectory.kotlinTestPath + ) + ) { + override fun getSdk() = PluginTestCaseBase.fullJdk() + } + + private val INSTANCE_WITHOUT_RUNTIME = object : KotlinLightProjectDescriptor() { + override fun getSdk() = PluginTestCaseBase.fullJdk() + } + } } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java index 465d93860f0..64dceccbb3a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java @@ -46,6 +46,11 @@ public class ScratchRunActionTestGenerated extends AbstractScratchRunActionTest runTest("idea/testData/scratch/klass.kts"); } + @TestMetadata("libraryDepWithKotlinTest.kts") + public void testLibraryDepWithKotlinTest() throws Exception { + runTest("idea/testData/scratch/libraryDepWithKotlinTest.kts"); + } + @TestMetadata("simple.kts") public void testSimple() throws Exception { runTest("idea/testData/scratch/simple.kts"); @@ -129,6 +134,11 @@ public class ScratchRunActionTestGenerated extends AbstractScratchRunActionTest runTest("idea/testData/scratch/klass.kts"); } + @TestMetadata("libraryDepWithKotlinTest.kts") + public void testLibraryDepWithKotlinTest() throws Exception { + runTest("idea/testData/scratch/libraryDepWithKotlinTest.kts"); + } + @TestMetadata("simple.kts") public void testSimple() throws Exception { runTest("idea/testData/scratch/simple.kts");