Impossible to run applications with long command lines on windows
^KT-29352 Fixed
This commit is contained in:
@@ -344,6 +344,7 @@ public class KotlinRunConfiguration extends JetRunConfiguration {
|
|||||||
JavaParametersUtil.configureModule(module, params, classPathType, jreHome);
|
JavaParametersUtil.configureModule(module, params, classPathType, jreHome);
|
||||||
setupJavaParameters(params);
|
setupJavaParameters(params);
|
||||||
|
|
||||||
|
params.setShortenCommandLine(null, module.getProject());
|
||||||
params.setMainClass(myConfiguration.getRunClass());
|
params.setMainClass(myConfiguration.getRunClass());
|
||||||
setupModulePath(params, module);
|
setupModulePath(params, module);
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class KotlinConsoleKeeper(val project: Project) {
|
|||||||
if (module != null) {
|
if (module != null) {
|
||||||
val classPath = JavaParametersBuilder.getModuleDependencies(module)
|
val classPath = JavaParametersBuilder.getModuleDependencies(module)
|
||||||
if (classPath.isNotEmpty()) {
|
if (classPath.isNotEmpty()) {
|
||||||
|
javaParameters.setUseDynamicParameters(javaParameters.isDynamicClasspath)
|
||||||
javaParameters.programParametersList.add("-cp")
|
javaParameters.programParametersList.add("-cp")
|
||||||
javaParameters.programParametersList.add(
|
javaParameters.programParametersList.add(
|
||||||
classPath.joinToString(File.pathSeparator)
|
classPath.joinToString(File.pathSeparator)
|
||||||
|
|||||||
@@ -5,11 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.util
|
package org.jetbrains.kotlin.idea.util
|
||||||
|
|
||||||
|
import com.intellij.execution.ShortenCommandLine
|
||||||
import com.intellij.execution.configurations.JavaParameters
|
import com.intellij.execution.configurations.JavaParameters
|
||||||
import com.intellij.openapi.compiler.ex.CompilerPathsEx
|
import com.intellij.openapi.compiler.ex.CompilerPathsEx
|
||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.projectRoots.JavaSdkType
|
import com.intellij.openapi.projectRoots.JavaSdkType
|
||||||
|
import com.intellij.openapi.projectRoots.JdkUtil
|
||||||
import com.intellij.openapi.projectRoots.Sdk
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
import com.intellij.openapi.projectRoots.SimpleJavaSdkType
|
import com.intellij.openapi.projectRoots.SimpleJavaSdkType
|
||||||
import com.intellij.openapi.roots.ModuleRootManager
|
import com.intellij.openapi.roots.ModuleRootManager
|
||||||
@@ -29,9 +31,20 @@ class JavaParametersBuilder(private val project: Project) {
|
|||||||
if (jdk == null && setDefaultSdk) {
|
if (jdk == null && setDefaultSdk) {
|
||||||
this.jdk = SimpleJavaSdkType().createJdk("tmp", SystemProperties.getJavaHome())
|
this.jdk = SimpleJavaSdkType().createJdk("tmp", SystemProperties.getJavaHome())
|
||||||
}
|
}
|
||||||
|
this.setShortenCommandLine(getDefaultShortenCommandLineMethod(jdk?.homePath), project)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is partially copied from IDEA sources but doesn't check presence of dynamic.classpath property
|
||||||
|
* because we want to shorten command line for scratches and repl anyway
|
||||||
|
* @see [com.intellij.execution.ShortenCommandLine.getDefaultMethod]
|
||||||
|
*/
|
||||||
|
private fun getDefaultShortenCommandLineMethod(rootPath: String?): ShortenCommandLine {
|
||||||
|
if (rootPath != null && JdkUtil.isModularRuntime(rootPath)) return ShortenCommandLine.ARGS_FILE
|
||||||
|
return if (JdkUtil.useClasspathJar()) ShortenCommandLine.MANIFEST else ShortenCommandLine.CLASSPATH_FILE
|
||||||
|
}
|
||||||
|
|
||||||
fun withMainClassName(name: String?): JavaParametersBuilder {
|
fun withMainClassName(name: String?): JavaParametersBuilder {
|
||||||
mainClassName = name
|
mainClassName = name
|
||||||
return this
|
return this
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package some.test
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -6,10 +6,12 @@
|
|||||||
package org.jetbrains.kotlin.idea.repl
|
package org.jetbrains.kotlin.idea.repl
|
||||||
|
|
||||||
import com.intellij.execution.console.LanguageConsoleImpl
|
import com.intellij.execution.console.LanguageConsoleImpl
|
||||||
|
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||||
import com.intellij.testFramework.PlatformTestCase
|
import com.intellij.testFramework.PlatformTestCase
|
||||||
import com.intellij.util.ui.UIUtil
|
import com.intellij.util.ui.UIUtil
|
||||||
import org.jetbrains.kotlin.console.KotlinConsoleKeeper
|
import org.jetbrains.kotlin.console.KotlinConsoleKeeper
|
||||||
import org.jetbrains.kotlin.console.KotlinConsoleRunner
|
import org.jetbrains.kotlin.console.KotlinConsoleRunner
|
||||||
|
import org.jetbrains.kotlin.idea.run.createLibraryWithLongPaths
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.reflect.KMutableProperty0
|
import kotlin.reflect.KMutableProperty0
|
||||||
@@ -82,6 +84,16 @@ class IdeReplExecutionTest : PlatformTestCase() {
|
|||||||
assertFalse(consoleRunner.processHandler.isProcessTerminated, "Process accidentally terminated")
|
assertFalse(consoleRunner.processHandler.isProcessTerminated, "Process accidentally terminated")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testLongCommandLine() {
|
||||||
|
ModuleRootModificationUtil.addDependency(module, createLibraryWithLongPaths(project))
|
||||||
|
|
||||||
|
consoleRunner.dispose()
|
||||||
|
consoleRunner = KotlinConsoleKeeper.getInstance(project).run(module)!!
|
||||||
|
|
||||||
|
testRunPossibility()
|
||||||
|
}
|
||||||
|
|
||||||
@Test fun testOnePlusOne() = testSimpleCommand("1 + 1", "2")
|
@Test fun testOnePlusOne() = testSimpleCommand("1 + 1", "2")
|
||||||
@Test fun testPrintlnText() = "Hello, console world!".let { testSimpleCommand("println(\"$it\")", it) }
|
@Test fun testPrintlnText() = "Hello, console world!".let { testSimpleCommand("println(\"$it\")", it) }
|
||||||
@Test fun testDivisionByZeroException() = testSimpleCommand("1 / 0", "java.lang.ArithmeticException: / by zero")
|
@Test fun testDivisionByZeroException() = testSimpleCommand("1 / 0", "java.lang.ArithmeticException: / by zero")
|
||||||
|
|||||||
@@ -133,6 +133,20 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
|
|||||||
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(moduleWithDependencySrcDir))
|
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(moduleWithDependencySrcDir))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testLongCommandLine() {
|
||||||
|
val myModule = configureModule(moduleDirPath("module"), getTestProject().baseDir).module
|
||||||
|
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(module, addJdk(testRootDisposable, ::mockJdk))
|
||||||
|
|
||||||
|
ModuleRootModificationUtil.addDependency(myModule, createLibraryWithLongPaths(project))
|
||||||
|
|
||||||
|
val kotlinRunConfiguration = createConfigurationFromMain("some.test.main")
|
||||||
|
kotlinRunConfiguration.setModule(myModule)
|
||||||
|
|
||||||
|
val javaParameters = getJavaRunParameters(kotlinRunConfiguration)
|
||||||
|
val commandLine = javaParameters.toCommandLine().commandLineString
|
||||||
|
Assert.assertTrue(commandLine.length < javaParameters.classPath.pathList.joinToString().length)
|
||||||
|
}
|
||||||
|
|
||||||
fun testClassesAndObjects() {
|
fun testClassesAndObjects() {
|
||||||
doTest(ConfigLibraryUtil::configureKotlinRuntimeAndSdk)
|
doTest(ConfigLibraryUtil::configureKotlinRuntimeAndSdk)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,6 +134,20 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
|
|||||||
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(moduleWithDependencySrcDir))
|
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(moduleWithDependencySrcDir))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testLongCommandLine() {
|
||||||
|
val myModule = configureModule(moduleDirPath("module"), getTestProject().baseDir).module
|
||||||
|
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(module, addJdk(testRootDisposable, ::mockJdk))
|
||||||
|
|
||||||
|
ModuleRootModificationUtil.addDependency(myModule, createLibraryWithLongPaths(project))
|
||||||
|
|
||||||
|
val kotlinRunConfiguration = createConfigurationFromMain("some.test.main")
|
||||||
|
kotlinRunConfiguration.setModule(myModule)
|
||||||
|
|
||||||
|
val javaParameters = getJavaRunParameters(kotlinRunConfiguration)
|
||||||
|
val commandLine = javaParameters.toCommandLine().commandLineString
|
||||||
|
Assert.assertTrue(commandLine.length < javaParameters.classPath.pathList.joinToString().length)
|
||||||
|
}
|
||||||
|
|
||||||
fun testClassesAndObjects() {
|
fun testClassesAndObjects() {
|
||||||
doTest(ConfigLibraryUtil::configureKotlinRuntimeAndSdk)
|
doTest(ConfigLibraryUtil::configureKotlinRuntimeAndSdk)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,16 @@ import com.intellij.execution.configurations.RunProfile
|
|||||||
import com.intellij.execution.executors.DefaultRunExecutor
|
import com.intellij.execution.executors.DefaultRunExecutor
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
import com.intellij.execution.runners.ExecutionEnvironment
|
||||||
import com.intellij.execution.runners.ExecutionEnvironmentBuilder
|
import com.intellij.execution.runners.ExecutionEnvironmentBuilder
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.roots.OrderRootType
|
||||||
|
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable
|
||||||
|
import com.intellij.openapi.roots.libraries.Library
|
||||||
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.intellij.openapi.vfs.LocalFileSystem
|
||||||
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.testFramework.MapDataContext
|
import com.intellij.testFramework.MapDataContext
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
|
|
||||||
fun getJavaRunParameters(configuration: RunConfiguration): JavaParameters {
|
fun getJavaRunParameters(configuration: RunConfiguration): JavaParameters {
|
||||||
@@ -42,6 +50,31 @@ fun createConfigurationFromElement(element: PsiElement, save: Boolean = false):
|
|||||||
return runnerAndConfigurationSettings!!.configuration
|
return runnerAndConfigurationSettings!!.configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createLibraryWithLongPaths(project: Project): Library {
|
||||||
|
val maxCommandlineLengthWindows = 24500
|
||||||
|
val maxFilenameLengthWindows = 245
|
||||||
|
|
||||||
|
return runWriteAction {
|
||||||
|
val modifiableModel = ProjectLibraryTable.getInstance(project).modifiableModel
|
||||||
|
val library = try {
|
||||||
|
modifiableModel.createLibrary("LibraryWithLongPaths", null)
|
||||||
|
} finally {
|
||||||
|
modifiableModel.commit()
|
||||||
|
}
|
||||||
|
with(library.modifiableModel) {
|
||||||
|
for (i in 0..maxCommandlineLengthWindows / maxFilenameLengthWindows) {
|
||||||
|
val tmpFile = VirtualFileManager.constructUrl(
|
||||||
|
LocalFileSystem.getInstance().protocol,
|
||||||
|
FileUtil.createTempFile("file$i", "a".repeat(maxFilenameLengthWindows)).path
|
||||||
|
)
|
||||||
|
addRoot(tmpFile, OrderRootType.CLASSES)
|
||||||
|
}
|
||||||
|
commit()
|
||||||
|
}
|
||||||
|
return@runWriteAction library
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private object MockExecutor : DefaultRunExecutor() {
|
private object MockExecutor : DefaultRunExecutor() {
|
||||||
override fun getId() = DefaultRunExecutor.EXECUTOR_ID
|
override fun getId() = DefaultRunExecutor.EXECUTOR_ID
|
||||||
|
|||||||
@@ -88,15 +88,7 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
|
|||||||
val sourceFile = File(testDataPath, fileName)
|
val sourceFile = File(testDataPath, fileName)
|
||||||
val fileText = sourceFile.readText()
|
val fileText = sourceFile.readText()
|
||||||
|
|
||||||
val scratchFile = ScratchRootType.getInstance().createScratchFile(
|
val scratchFile = createScratchFile(sourceFile.name, fileText)
|
||||||
project,
|
|
||||||
sourceFile.name,
|
|
||||||
KotlinLanguage.INSTANCE,
|
|
||||||
fileText,
|
|
||||||
ScratchFileService.Option.create_if_missing
|
|
||||||
) ?: error("Couldn't create scratch file ${sourceFile.path}")
|
|
||||||
|
|
||||||
myFixture.openFileInEditor(scratchFile)
|
|
||||||
|
|
||||||
ScriptDependenciesManager.updateScriptDependenciesSynchronously(scratchFile, project)
|
ScriptDependenciesManager.updateScriptDependenciesSynchronously(scratchFile, project)
|
||||||
|
|
||||||
@@ -115,16 +107,6 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
|
|||||||
|
|
||||||
launchScratch(scratchFile)
|
launchScratch(scratchFile)
|
||||||
|
|
||||||
UIUtil.dispatchAllInvocationEvents()
|
|
||||||
|
|
||||||
val start = System.currentTimeMillis()
|
|
||||||
// wait until output is displayed in editor or for 1 minute
|
|
||||||
while (ScratchCompilationSupport.isAnyInProgress() && (System.currentTimeMillis() - start) < 60000) {
|
|
||||||
Thread.sleep(100)
|
|
||||||
}
|
|
||||||
|
|
||||||
UIUtil.dispatchAllInvocationEvents()
|
|
||||||
|
|
||||||
val doc = PsiDocumentManager.getInstance(project).getDocument(psiFile) ?: error("Document for ${psiFile.name} is null")
|
val doc = PsiDocumentManager.getInstance(project).getDocument(psiFile) ?: error("Document for ${psiFile.name} is null")
|
||||||
|
|
||||||
val actualOutput = StringBuilder(psiFile.text)
|
val actualOutput = StringBuilder(psiFile.text)
|
||||||
@@ -152,13 +134,36 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
|
|||||||
KotlinTestUtils.assertEqualsToFile(expectedFile, actualOutput.toString())
|
KotlinTestUtils.assertEqualsToFile(expectedFile, actualOutput.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun launchScratch(scratchFile: VirtualFile) {
|
protected fun createScratchFile(name: String, text: String): VirtualFile {
|
||||||
|
val scratchFile = ScratchRootType.getInstance().createScratchFile(
|
||||||
|
project,
|
||||||
|
name,
|
||||||
|
KotlinLanguage.INSTANCE,
|
||||||
|
text,
|
||||||
|
ScratchFileService.Option.create_if_missing
|
||||||
|
) ?: error("Couldn't create scratch file")
|
||||||
|
|
||||||
|
myFixture.openFileInEditor(scratchFile)
|
||||||
|
return scratchFile
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun launchScratch(scratchFile: VirtualFile) {
|
||||||
val action = RunScratchAction()
|
val action = RunScratchAction()
|
||||||
val e = getActionEvent(scratchFile, action)
|
val e = getActionEvent(scratchFile, action)
|
||||||
|
|
||||||
action.beforeActionPerformedUpdate(e)
|
action.beforeActionPerformedUpdate(e)
|
||||||
Assert.assertTrue(e.presentation.isEnabled && e.presentation.isVisible)
|
Assert.assertTrue(e.presentation.isEnabled && e.presentation.isVisible)
|
||||||
action.actionPerformed(e)
|
action.actionPerformed(e)
|
||||||
|
|
||||||
|
UIUtil.dispatchAllInvocationEvents()
|
||||||
|
|
||||||
|
val start = System.currentTimeMillis()
|
||||||
|
// wait until output is displayed in editor or for 1 minute
|
||||||
|
while (ScratchCompilationSupport.isAnyInProgress() && (System.currentTimeMillis() - start) < 60000) {
|
||||||
|
Thread.sleep(100)
|
||||||
|
}
|
||||||
|
|
||||||
|
UIUtil.dispatchAllInvocationEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getActionEvent(virtualFile: VirtualFile, action: AnAction): TestActionEvent {
|
private fun getActionEvent(virtualFile: VirtualFile, action: AnAction): TestActionEvent {
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.scratch
|
||||||
|
|
||||||
|
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||||
|
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable
|
||||||
|
import com.intellij.openapi.roots.libraries.Library
|
||||||
|
import org.jetbrains.kotlin.idea.run.createLibraryWithLongPaths
|
||||||
|
import org.jetbrains.kotlin.idea.scratch.output.InlayScratchFileRenderer
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
|
||||||
|
class CustomScratchRunActionTest : AbstractScratchRunActionTest() {
|
||||||
|
|
||||||
|
fun testLongCommandLineWithRepl() {
|
||||||
|
assertEquals("RESULT: res0: kotlin.Int = 1", getOutput(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLongCommandLine() {
|
||||||
|
assertEquals("RESULT: 1", getOutput(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getOutput(isRepl: Boolean): String {
|
||||||
|
val fileText = "1"
|
||||||
|
val scratchFile = createScratchFile("scratch_1.kts", fileText)
|
||||||
|
|
||||||
|
val (editor, scratchPanel) = getEditorWithScratchPanel(myManager, scratchFile) ?: error("Couldn't find scratch panel")
|
||||||
|
scratchPanel.scratchFile.saveOptions {
|
||||||
|
copy(isRepl = isRepl, isInteractiveMode = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
scratchPanel.setModule(myFixture.module)
|
||||||
|
|
||||||
|
launchScratch(scratchFile)
|
||||||
|
|
||||||
|
return editor.editor.inlayModel.getInlineElementsInRange(0, fileText.length)
|
||||||
|
.map { it.renderer }
|
||||||
|
.filterIsInstance<InlayScratchFileRenderer>()
|
||||||
|
.joinToString().trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val library: Library by lazy {
|
||||||
|
createLibraryWithLongPaths(project)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setUp() {
|
||||||
|
super.setUp()
|
||||||
|
|
||||||
|
ModuleRootModificationUtil.addDependency(myFixture.module, library)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tearDown() {
|
||||||
|
removeLibraryWithLongPaths()
|
||||||
|
|
||||||
|
super.tearDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeLibraryWithLongPaths() {
|
||||||
|
runWriteAction {
|
||||||
|
val modifiableModel = ProjectLibraryTable.getInstance(project).modifiableModel
|
||||||
|
try {
|
||||||
|
modifiableModel.removeLibrary(library)
|
||||||
|
} finally {
|
||||||
|
modifiableModel.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,9 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.scratch
|
package org.jetbrains.kotlin.idea.scratch
|
||||||
|
|
||||||
import com.intellij.ide.scratch.ScratchFileService
|
|
||||||
import com.intellij.ide.scratch.ScratchRootType
|
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
|
||||||
import org.jetbrains.kotlin.idea.scratch.ui.ScratchTopPanel
|
import org.jetbrains.kotlin.idea.scratch.ui.ScratchTopPanel
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import javax.swing.JCheckBox
|
import javax.swing.JCheckBox
|
||||||
@@ -17,18 +14,7 @@ import kotlin.reflect.full.declaredMemberProperties
|
|||||||
class ScratchOptionsSaveTest : AbstractScratchRunActionTest() {
|
class ScratchOptionsSaveTest : AbstractScratchRunActionTest() {
|
||||||
|
|
||||||
fun testOptionsSaveOnClosingFile() {
|
fun testOptionsSaveOnClosingFile() {
|
||||||
val fileText = "val a = 1"
|
val scratchFile = createScratchFile("scratch_1.kts", "val a = 1")
|
||||||
|
|
||||||
val scratchFile = ScratchRootType.getInstance().createScratchFile(
|
|
||||||
project,
|
|
||||||
"scratch_1.kts",
|
|
||||||
KotlinLanguage.INSTANCE,
|
|
||||||
fileText,
|
|
||||||
ScratchFileService.Option.create_if_missing
|
|
||||||
) ?: error("Couldn't create scratch file")
|
|
||||||
|
|
||||||
myManager.openFile(scratchFile, true)
|
|
||||||
|
|
||||||
val (_, scratchPanelBeforeClosingFile) = getEditorWithScratchPanel(myManager, scratchFile) ?: error("Couldn't find scratch panel")
|
val (_, scratchPanelBeforeClosingFile) = getEditorWithScratchPanel(myManager, scratchFile) ?: error("Couldn't find scratch panel")
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(
|
||||||
|
|||||||
Reference in New Issue
Block a user