Allow to run scratch without module selected

^KT-23985 Fixed
This commit is contained in:
Natalia Selezneva
2018-12-05 09:39:14 +03:00
parent 8d4ca4d1c5
commit e2b5134048
11 changed files with 68 additions and 30 deletions
@@ -68,7 +68,7 @@ class ScratchFileModuleInfoProvider(val project: Project) : ProjectComponent {
val scratchPanel = getEditorWithScratchPanel(source, file)?.second val scratchPanel = getEditorWithScratchPanel(source, file)?.second
scratchPanel?.addModuleListener { psiFile, module -> scratchPanel?.addModuleListener { psiFile, module ->
psiFile.virtualFile.scriptRelatedModuleName = module.name psiFile.virtualFile.scriptRelatedModuleName = module?.name
// Drop caches for old module // Drop caches for old module
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount() ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
@@ -79,11 +79,6 @@ class ScratchFileModuleInfoProvider(val project: Project) : ProjectComponent {
val module = ktFile.virtualFile.scriptRelatedModuleName?.let { ModuleManager.getInstance(project).findModuleByName(it) } val module = ktFile.virtualFile.scriptRelatedModuleName?.let { ModuleManager.getInstance(project).findModuleByName(it) }
if (module != null) { if (module != null) {
scratchPanel?.setModule(module) scratchPanel?.setModule(module)
} else {
val firstModule = ModuleManager.getInstance(project).modules.firstOrNull()
if (firstModule != null) {
scratchPanel?.setModule(firstModule)
}
} }
} }
} }
@@ -62,11 +62,6 @@ class RunScratchAction : ScratchAction(
val module = scratchPanel.getModule() val module = scratchPanel.getModule()
@Suppress("FoldInitializerAndIfToElvis")
if (module == null) {
return defaultOutputHandler.error(scratchFile, "Module should be selected")
}
val executor = if (isRepl) provider.createReplExecutor(scratchFile) else provider.createCompilingExecutor(scratchFile) val executor = if (isRepl) provider.createReplExecutor(scratchFile) else provider.createCompilingExecutor(scratchFile)
@Suppress("FoldInitializerAndIfToElvis") @Suppress("FoldInitializerAndIfToElvis")
@@ -96,7 +91,7 @@ class RunScratchAction : ScratchAction(
} }
} }
if (!isAutoRun && isMakeBeforeRun) { if (!isAutoRun && module != null && isMakeBeforeRun) {
val project = scratchPanel.scratchFile.project val project = scratchPanel.scratchFile.project
ProjectTaskManager.getInstance(project).build(arrayOf(module)) { result -> ProjectTaskManager.getInstance(project).build(arrayOf(module)) { result ->
if (result.isAborted || result.errors > 0) { if (result.isAborted || result.errors > 0) {
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
import org.jetbrains.kotlin.idea.debugger.DebuggerUtils import org.jetbrains.kotlin.idea.debugger.DebuggerUtils
import org.jetbrains.kotlin.idea.refactoring.getLineNumber import org.jetbrains.kotlin.idea.refactoring.getLineNumber
import org.jetbrains.kotlin.idea.scratch.* import org.jetbrains.kotlin.idea.scratch.*
@@ -63,7 +64,7 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) {
override fun execute() { override fun execute() {
handler.onStart(file) handler.onStart(file)
val module = file.getModule() ?: return errorOccurs("Module should be selected", isFatal = true) val module = file.getModule()
val psiFile = file.getPsiFile() as? KtFile ?: return errorOccurs("Couldn't find KtFile for current editor", isFatal = true) val psiFile = file.getPsiFile() as? KtFile ?: return errorOccurs("Couldn't find KtFile for current editor", isFatal = true)
if (!checkForErrors(psiFile)) return if (!checkForErrors(psiFile)) return
@@ -90,7 +91,7 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) {
) ?: return ) ?: return
try { try {
val commandLine = createCommandLine(module, result.mainClassName, tempDir.path) val commandLine = createCommandLine(psiFile, module, result.mainClassName, tempDir.path)
LOG.printDebugMessage(commandLine.commandLineString) LOG.printDebugMessage(commandLine.commandLineString)
@@ -176,16 +177,22 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) {
return dir return dir
} }
private fun createCommandLine(module: Module, mainClassName: String, tempOutDir: String): GeneralCommandLine { private fun createCommandLine(originalFile: KtFile, module: Module?, mainClassName: String, tempOutDir: String): GeneralCommandLine {
val javaParameters = KotlinConsoleKeeper.createJavaParametersWithSdk(module) val javaParameters = KotlinConsoleKeeper.createJavaParametersWithSdk(module)
javaParameters.mainClass = mainClassName javaParameters.mainClass = mainClassName
val compiledModulePath = CompilerPathsEx.getOutputPaths(arrayOf(module)).toList()
val moduleDependencies = OrderEnumerator.orderEntries(module).recursively().pathsList.pathList
javaParameters.classPath.add(tempOutDir) javaParameters.classPath.add(tempOutDir)
javaParameters.classPath.addAll(compiledModulePath)
javaParameters.classPath.addAll(moduleDependencies) if (module != null) {
val compiledModulePath = CompilerPathsEx.getOutputPaths(arrayOf(module)).toList()
javaParameters.classPath.addAll(compiledModulePath)
val moduleDependencies = OrderEnumerator.orderEntries(module).recursively().pathsList.pathList
javaParameters.classPath.addAll(moduleDependencies)
}
val scriptDependencies = ScriptDependenciesManager.getInstance(originalFile.project).getScriptDependencies(originalFile.virtualFile)
javaParameters.classPath.addAll(scriptDependencies.classpath.map { it.absolutePath })
return javaParameters.toCommandLine() return javaParameters.toCommandLine()
} }
@@ -43,7 +43,7 @@ class KtScratchReplExecutor(file: ScratchFile) : ScratchExecutor(file) {
override fun execute() { override fun execute() {
handler.onStart(file) handler.onStart(file)
val module = file.getModule() ?: return errorOccurs("Module should be selected", isFatal = true) val module = file.getModule()
val cmdLine = KotlinConsoleKeeper.createCommandLine(module) val cmdLine = KotlinConsoleKeeper.createCommandLine(module)
LOG.printDebugMessage("Execute REPL: ${cmdLine.commandLineString}") LOG.printDebugMessage("Execute REPL: ${cmdLine.commandLineString}")
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.scratch.ui
import com.intellij.application.options.ModulesComboBox import com.intellij.application.options.ModulesComboBox
import com.intellij.execution.ui.ConfigurationModuleSelector
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.actionSystem.ActionManager import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.ActionPlaces import com.intellij.openapi.actionSystem.ActionPlaces
@@ -115,11 +116,11 @@ class ScratchTopPanel private constructor(val scratchFile: ScratchFile) : JPanel
moduleChooser.selectedModule = module moduleChooser.selectedModule = module
} }
fun addModuleListener(f: (PsiFile, Module) -> Unit) { fun addModuleListener(f: (PsiFile, Module?) -> Unit) {
moduleChooser.addActionListener { moduleChooser.addActionListener {
val selectedModule = moduleChooser.selectedModule val selectedModule = moduleChooser.selectedModule
val psiFile = scratchFile.getPsiFile() val psiFile = scratchFile.getPsiFile()
if (selectedModule != null && psiFile != null) { if (psiFile != null) {
f(psiFile, selectedModule) f(psiFile, selectedModule)
} }
} }
@@ -162,6 +163,7 @@ class ScratchTopPanel private constructor(val scratchFile: ScratchFile) : JPanel
setModules(ModuleManager.getInstance(project).modules.filter { setModules(ModuleManager.getInstance(project).modules.filter {
it.productionSourceInfo() != null || it.testSourceInfo() != null it.productionSourceInfo() != null || it.testSourceInfo() != null
}) })
allowEmptySelection(ConfigurationModuleSelector.NO_MODULE_TEXT)
} }
} }
} }
@@ -54,7 +54,7 @@ class KotlinConsoleKeeper(val project: Project) {
companion object { companion object {
@JvmStatic fun getInstance(project: Project) = ServiceManager.getService(project, KotlinConsoleKeeper::class.java) @JvmStatic fun getInstance(project: Project) = ServiceManager.getService(project, KotlinConsoleKeeper::class.java)
fun createCommandLine(module: Module): GeneralCommandLine { fun createCommandLine(module: Module?): GeneralCommandLine {
val javaParameters = createJavaParametersWithSdk(module) val javaParameters = createJavaParametersWithSdk(module)
javaParameters.mainClass = "dummy" javaParameters.mainClass = "dummy"
@@ -79,16 +79,18 @@ class KotlinConsoleKeeper(val project: Project) {
paramList.add("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler") paramList.add("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler")
addPathToCompiledOutput(paramList, module) if (module != null) {
addPathToCompiledOutput(paramList, module)
}
return commandLine return commandLine
} }
fun createJavaParametersWithSdk(module: Module): JavaParameters { fun createJavaParametersWithSdk(module: Module?): JavaParameters {
val params = JavaParameters() val params = JavaParameters()
params.charset = null params.charset = null
val sdk = ModuleRootManager.getInstance(module).sdk val sdk = module?.let { ModuleRootManager.getInstance(module).sdk }
if (sdk != null && sdk.sdkType is JavaSdkType && File(sdk.homePath).exists()) { if (sdk != null && sdk.sdkType is JavaSdkType && File(sdk.homePath).exists()) {
params.jdk = sdk params.jdk = sdk
} }
+3
View File
@@ -0,0 +1,3 @@
arrayListOf(1, 2).size // RESULT: 2
//NO_MODULE
+3
View File
@@ -0,0 +1,3 @@
arrayListOf(1, 2).size
//NO_MODULE
+3
View File
@@ -0,0 +1,3 @@
arrayListOf(1, 2).size // RESULT: res0: kotlin.Int = 2
//NO_MODULE
@@ -12,6 +12,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.roots.CompilerModuleExtension import com.intellij.openapi.roots.CompilerModuleExtension
import com.intellij.openapi.roots.ModuleRootModificationUtil import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.util.io.FileUtil 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.VirtualFile
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiDocumentManager
@@ -27,9 +28,11 @@ import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingUtil
import org.jetbrains.kotlin.idea.scratch.actions.RunScratchAction import org.jetbrains.kotlin.idea.scratch.actions.RunScratchAction
import org.jetbrains.kotlin.idea.scratch.actions.ScratchCompilationSupport import org.jetbrains.kotlin.idea.scratch.actions.ScratchCompilationSupport
import org.jetbrains.kotlin.idea.scratch.output.InlayScratchFileRenderer import org.jetbrains.kotlin.idea.scratch.output.InlayScratchFileRenderer
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.util.application.runWriteAction 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.KotlinTestUtils
import org.jetbrains.kotlin.test.MockLibraryUtil import org.jetbrains.kotlin.test.MockLibraryUtil
import org.junit.Assert import org.junit.Assert
@@ -100,11 +103,15 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
if (!KotlinHighlightingUtil.shouldHighlight(psiFile)) error("Highlighting for scratch file is switched off") if (!KotlinHighlightingUtil.shouldHighlight(psiFile)) error("Highlighting for scratch file is switched off")
val (editor, scratchPanel) = getEditorWithScratchPanel(myManager, scratchFile)?: error("Couldn't find scratch panel") val (editor, scratchPanel) = getEditorWithScratchPanel(myManager, scratchFile) ?: error("Couldn't find scratch panel")
scratchPanel.scratchFile.saveOptions { scratchPanel.scratchFile.saveOptions {
copy(isRepl = isRepl, isInteractiveMode = false) copy(isRepl = isRepl, isInteractiveMode = false)
} }
if (!InTextDirectivesUtils.isDirectiveDefined(fileText, "// NO_MODULE")) {
scratchPanel.setModule(myFixture.module)
}
launchScratch(scratchFile) launchScratch(scratchFile)
UIUtil.dispatchAllInvocationEvents() UIUtil.dispatchAllInvocationEvents()
@@ -128,7 +135,10 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
.filterIsInstance<InlayScratchFileRenderer>() .filterIsInstance<InlayScratchFileRenderer>()
.forEach { .forEach {
val str = it.toString() val str = it.toString()
val offset = doc.getLineEndOffset(line); actualOutput.insert(offset, "${str.takeWhile { it.isWhitespace() }}// ${str.trim()}") val offset = doc.getLineEndOffset(line); actualOutput.insert(
offset,
"${str.takeWhile { it.isWhitespace() }}// ${str.trim()}"
)
} }
} }
@@ -160,7 +170,15 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory() override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory()
override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK
override fun getProjectDescriptor(): com.intellij.testFramework.LightProjectDescriptor {
val testName = StringUtil.toLowerCase(getTestName(false))
return when {
testName.endsWith("NoRuntime") -> KotlinLightProjectDescriptor.INSTANCE
else -> KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK
}
}
override fun setUp() { override fun setUp() {
super.setUp() super.setUp()
@@ -56,6 +56,11 @@ public class ScratchRunActionTestGenerated extends AbstractScratchRunActionTest
runTest("idea/testData/scratch/simpleFun.kts"); runTest("idea/testData/scratch/simpleFun.kts");
} }
@TestMetadata("simpleNoRuntime.kts")
public void testSimpleNoRuntime() throws Exception {
runTest("idea/testData/scratch/simpleNoRuntime.kts");
}
@TestMetadata("spacesAtLineStart.kts") @TestMetadata("spacesAtLineStart.kts")
public void testSpacesAtLineStart() throws Exception { public void testSpacesAtLineStart() throws Exception {
runTest("idea/testData/scratch/spacesAtLineStart.kts"); runTest("idea/testData/scratch/spacesAtLineStart.kts");
@@ -134,6 +139,11 @@ public class ScratchRunActionTestGenerated extends AbstractScratchRunActionTest
runTest("idea/testData/scratch/simpleFun.kts"); runTest("idea/testData/scratch/simpleFun.kts");
} }
@TestMetadata("simpleNoRuntime.kts")
public void testSimpleNoRuntime() throws Exception {
runTest("idea/testData/scratch/simpleNoRuntime.kts");
}
@TestMetadata("spacesAtLineStart.kts") @TestMetadata("spacesAtLineStart.kts")
public void testSpacesAtLineStart() throws Exception { public void testSpacesAtLineStart() throws Exception {
runTest("idea/testData/scratch/spacesAtLineStart.kts"); runTest("idea/testData/scratch/spacesAtLineStart.kts");