From bf6464ddcd31af7f1e246600fc79f882584b0ffd Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Mon, 26 Oct 2015 15:57:37 +0300 Subject: [PATCH] Repl: clearer separation of ide and console logic Fix a bug with redundant new lines printed in console mode --- .../kotlin/cli/jvm/repl/ReplFromTerminal.java | 19 +++++++----- .../jvm/repl/messages/ReplConsoleWriter.kt | 31 +++++++++++++++++++ .../cli/jvm/repl/messages/ReplErrorLogger.kt | 2 +- .../jvm/repl/messages/ReplSystemInWrapper.kt | 2 +- ...apper.kt => ReplSystemOutWrapperForIde.kt} | 27 +++++++--------- .../cli/jvm/repl/messages/ReplWriter.kt | 30 ++++++++++++++++++ 6 files changed, 86 insertions(+), 25 deletions(-) create mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplConsoleWriter.kt rename compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/{ReplSystemOutWrapper.kt => ReplSystemOutWrapperForIde.kt} (66%) create mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplWriter.kt diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.java b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.java index a3dd95ea3e7..58d2f8981d6 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.java @@ -20,10 +20,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.cli.common.KotlinVersion; -import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplErrorLogger; -import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemInWrapper; -import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemOutWrapper; -import org.jetbrains.kotlin.cli.jvm.repl.messages.UnescapeUtilsKt; +import org.jetbrains.kotlin.cli.jvm.repl.messages.*; import org.jetbrains.kotlin.cli.jvm.repl.reader.ConsoleReplCommandReader; import org.jetbrains.kotlin.cli.jvm.repl.reader.IdeReplCommandReader; import org.jetbrains.kotlin.cli.jvm.repl.reader.ReplCommandReader; @@ -43,7 +40,7 @@ public class ReplFromTerminal { private final boolean ideMode; private ReplSystemInWrapper replReader; - private final ReplSystemOutWrapper replWriter; + private final ReplWriter replWriter; private final ReplErrorLogger replErrorLogger; private ReplCommandReader commandReader; @@ -58,8 +55,14 @@ public class ReplFromTerminal { // wrapper for `out` is required to escape every input in [ideMode]; // if [ideMode == false] then just redirects all input to [System.out] // if user calls [System.setOut(...)] then undefined behaviour - replWriter = new ReplSystemOutWrapper(ideMode, System.out); - System.setOut(replWriter); + if (ideMode) { + ReplSystemOutWrapperForIde soutWrapper = new ReplSystemOutWrapperForIde(System.out); + replWriter = soutWrapper; + System.setOut(soutWrapper); + } + else { + replWriter = new ReplConsoleWriter(); + } // wrapper for `in` is required to give user possibility of calling // [readLine] from ide-console repl @@ -216,7 +219,7 @@ public class ReplFromTerminal { return true; } else if (split.size() >= 2 && split.get(0).equals("dump") && split.get(1).equals("bytecode")) { - getReplInterpreter().dumpClasses(new PrintWriter(replWriter)); + getReplInterpreter().dumpClasses(new PrintWriter(System.out)); return true; } else if (split.size() >= 1 && split.get(0).equals("quit")) { diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplConsoleWriter.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplConsoleWriter.kt new file mode 100644 index 00000000000..db1963eb443 --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplConsoleWriter.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.cli.jvm.repl.messages + +class ReplConsoleWriter : ReplWriter { + override fun printlnWelcomeMessage(x: String) = println(x) + override fun printlnHelpMessage(x: String) = println(x) + override fun outputCompileError(x: String) = println(x) + override fun outputCommandResult(x: Any?) = println(x) + override fun outputRuntimeError(x: String) = println(x) + + override fun notifyReadLineStart() {} + override fun notifyReadLineEnd() {} + override fun notifyIncomplete() {} + override fun notifyCommandSuccess() {} + override fun sendInternalErrorReport(x: String) {} +} \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplErrorLogger.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplErrorLogger.kt index 59dd237c49a..ba273693f36 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplErrorLogger.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplErrorLogger.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.utils.rethrow import java.io.PrintWriter import java.io.StringWriter -public class ReplErrorLogger(private val ideMode: Boolean, private val replWriter: ReplSystemOutWrapper) { +public class ReplErrorLogger(private val ideMode: Boolean, private val replWriter: ReplWriter) { fun logException(e: Throwable?) { if (ideMode) { val errorStringWriter = StringWriter() diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemInWrapper.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemInWrapper.kt index b0d33985162..5efd5358e4c 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemInWrapper.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemInWrapper.kt @@ -21,7 +21,7 @@ import java.io.InputStream public class ReplSystemInWrapper( private val stdin: InputStream, - private val replWriter: ReplSystemOutWrapper + private val replWriter: ReplWriter ) : InputStream() { private var isXmlIncomplete = true private var isLastByteProcessed = false diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemOutWrapper.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemOutWrapperForIde.kt similarity index 66% rename from compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemOutWrapper.kt rename to compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemOutWrapperForIde.kt index 8e185f4bc30..b71fb49becf 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemOutWrapper.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemOutWrapperForIde.kt @@ -23,7 +23,7 @@ import java.io.PrintStream val END_LINE: String = LineSeparator.getSystemLineSeparator().separatorString val XML_PREAMBLE = "" -public class ReplSystemOutWrapper(private val ideMode: Boolean, standardOut: PrintStream) : PrintStream(standardOut, true) { +public class ReplSystemOutWrapperForIde(standardOut: PrintStream) : PrintStream(standardOut, true), ReplWriter { private enum class EscapeType { INITIAL_PROMPT, HELP_PROMPT, @@ -50,10 +50,7 @@ public class ReplSystemOutWrapper(private val ideMode: Boolean, standardOut: Pri private fun printlnWithEscaping(text: String, escapeType: EscapeType = EscapeType.USER_OUTPUT) = printWithEscaping("$text\n", escapeType) private fun printWithEscaping(text: String, escapeType: EscapeType = EscapeType.USER_OUTPUT) { - if (ideMode) - super.print("${xmlEscape(text, escapeType)}$END_LINE") - else - super.print(text) + super.print("${xmlEscape(text, escapeType)}$END_LINE") } private fun xmlEscape(s: String, escapeType: EscapeType): String { @@ -61,14 +58,14 @@ public class ReplSystemOutWrapper(private val ideMode: Boolean, standardOut: Pri return "$XML_PREAMBLE${StringUtil.escapeXml(singleLine)}" } - fun printlnWelcomeMessage(x: String) = printlnWithEscaping(x, EscapeType.INITIAL_PROMPT) - fun printlnHelpMessage(x: String) = printlnWithEscaping(x, EscapeType.HELP_PROMPT) - fun outputCommandResult(x: Any?) = printlnWithEscaping(x.toString(), EscapeType.REPL_RESULT) - fun notifyReadLineStart() = printlnWithEscaping("", EscapeType.READLINE_START) - fun notifyReadLineEnd() = printlnWithEscaping("", EscapeType.READLINE_END) - fun notifyCommandSuccess() = printlnWithEscaping("", EscapeType.SUCCESS) - fun notifyIncomplete() = printlnWithEscaping("", EscapeType.REPL_INCOMPLETE) - fun outputCompileError(x: String) = printlnWithEscaping(x, EscapeType.COMPILE_ERROR) - fun outputRuntimeError(x: String) = printlnWithEscaping(x, EscapeType.RUNTIME_ERROR) - fun sendInternalErrorReport(x: String) = printlnWithEscaping(x, EscapeType.INTERNAL_ERROR) + override fun printlnWelcomeMessage(x: String) = printlnWithEscaping(x, EscapeType.INITIAL_PROMPT) + override fun printlnHelpMessage(x: String) = printlnWithEscaping(x, EscapeType.HELP_PROMPT) + override fun outputCommandResult(x: Any?) = printlnWithEscaping(x.toString(), EscapeType.REPL_RESULT) + override fun notifyReadLineStart() = printlnWithEscaping("", EscapeType.READLINE_START) + override fun notifyReadLineEnd() = printlnWithEscaping("", EscapeType.READLINE_END) + override fun notifyCommandSuccess() = printlnWithEscaping("", EscapeType.SUCCESS) + override fun notifyIncomplete() = printlnWithEscaping("", EscapeType.REPL_INCOMPLETE) + override fun outputCompileError(x: String) = printlnWithEscaping(x, EscapeType.COMPILE_ERROR) + override fun outputRuntimeError(x: String) = printlnWithEscaping(x, EscapeType.RUNTIME_ERROR) + override fun sendInternalErrorReport(x: String) = printlnWithEscaping(x, EscapeType.INTERNAL_ERROR) } \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplWriter.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplWriter.kt new file mode 100644 index 00000000000..b5060205613 --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplWriter.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.cli.jvm.repl.messages + +interface ReplWriter { + fun printlnWelcomeMessage(x: String) + fun printlnHelpMessage(x: String) + fun outputCommandResult(x: Any?) + fun notifyReadLineStart() + fun notifyReadLineEnd() + fun notifyIncomplete() + fun notifyCommandSuccess() + fun outputCompileError(x: String) + fun outputRuntimeError(x: String) + fun sendInternalErrorReport(x: String) +} \ No newline at end of file