From 468404c6c3cd92f4fc260112b1934615e74086cf Mon Sep 17 00:00:00 2001 From: Natalia Selezneva Date: Fri, 26 Oct 2018 09:23:05 +0300 Subject: [PATCH] Repl: refactoring, move common parts to utils --- .../kotlin/cli/common/repl/replUtil.kt | 26 +++++++++++++++++++ .../kotlin/cli/jvm/repl/ReplFromTerminal.kt | 4 +-- .../cli/jvm/repl/messages/UnescapeUtils.kt | 25 ------------------ .../jvm/repl/reader/ReplSystemInWrapper.kt | 4 +-- .../writer/IdeSystemOutWrapperReplWriter.kt | 18 +++---------- .../scratch/repl/KtScratchReplExecutor.kt | 17 ++++-------- .../kotlin/console/CommandExecutor.kt | 11 ++------ .../kotlin/console/ReplOutputHandler.kt | 10 +++---- 8 files changed, 44 insertions(+), 71 deletions(-) delete mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/UnescapeUtils.kt diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/replUtil.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/replUtil.kt index 76ba5dbb836..20a9c47eedc 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/replUtil.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/replUtil.kt @@ -17,9 +17,35 @@ package org.jetbrains.kotlin.cli.common.repl import com.google.common.base.Throwables +import com.intellij.openapi.util.text.StringUtil +import com.intellij.util.LineSeparator +import org.jetbrains.kotlin.utils.repl.ReplEscapeType import java.io.File import java.net.URLClassLoader +// using '#' to avoid collisions with xml escaping +private val SOURCE_CHARS: List = listOf("\n", "#") +private val XML_REPLACEMENTS: List = listOf("#n", "#diez") + +private val END_LINE: String = LineSeparator.getSystemLineSeparator().separatorString +private const val XML_PREAMBLE = "" + +fun String.replUnescapeLineBreaks() = StringUtil.replace(this, XML_REPLACEMENTS, SOURCE_CHARS) +fun String.replEscapeLineBreaks() = StringUtil.replace(this, SOURCE_CHARS, XML_REPLACEMENTS) + +fun String.replOutputAsXml(escapeType: ReplEscapeType): String { + val escapedXml = StringUtil.escapeXml(replEscapeLineBreaks()) + return "$XML_PREAMBLE$escapedXml" +} + +fun String.replInputAsXml(): String { + val escapedXml = StringUtil.escapeXml(replEscapeLineBreaks()) + return "$XML_PREAMBLE$escapedXml" +} + +fun String.replAddLineBreak() = this + END_LINE +fun String.replRemoveLineBreaksInTheEnd() = trimEnd(*END_LINE.toCharArray()) + fun makeScriptBaseName(codeLine: ReplCodeLine) = "Line_${codeLine.no}${if (codeLine.generation > REPL_CODE_LINE_FIRST_GEN) "_gen_${codeLine.generation}" else ""}" diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.kt index a5d7eae0008..da64bc42e3d 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.kt @@ -21,10 +21,10 @@ import com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult +import org.jetbrains.kotlin.cli.common.repl.replUnescapeLineBreaks import org.jetbrains.kotlin.cli.jvm.repl.configuration.ConsoleReplConfiguration import org.jetbrains.kotlin.cli.jvm.repl.configuration.IdeReplConfiguration import org.jetbrains.kotlin.cli.jvm.repl.configuration.ReplConfiguration -import org.jetbrains.kotlin.cli.jvm.repl.messages.unescapeLineBreaks import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.KotlinCompilerVersion import java.io.File @@ -96,7 +96,7 @@ class ReplFromTerminal( private fun one(next: WhatNextAfterOneLine): WhatNextAfterOneLine { var line = replConfiguration.commandReader.readLine(next) ?: return WhatNextAfterOneLine.QUIT - line = unescapeLineBreaks(line) + line = line.replUnescapeLineBreaks() if (line.startsWith(":") && (line.length == 1 || line[1] != ':')) { val notQuit = oneCommand(line.substring(1)) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/UnescapeUtils.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/UnescapeUtils.kt deleted file mode 100644 index 89fd1e0020a..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/UnescapeUtils.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 - -import com.intellij.openapi.util.text.StringUtil - -// using '#' to avoid collisions with xml escaping -internal val SOURCE_CHARS: Array = arrayOf("\n", "#") -internal val XML_REPLACEMENTS: Array = arrayOf("#n", "#diez") - -fun unescapeLineBreaks(s: String) = StringUtil.replace(s, XML_REPLACEMENTS, SOURCE_CHARS) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/reader/ReplSystemInWrapper.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/reader/ReplSystemInWrapper.kt index d544e1a94c6..0d990e06089 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/reader/ReplSystemInWrapper.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/reader/ReplSystemInWrapper.kt @@ -16,7 +16,7 @@ package org.jetbrains.kotlin.cli.jvm.repl.reader -import org.jetbrains.kotlin.cli.jvm.repl.messages.unescapeLineBreaks +import org.jetbrains.kotlin.cli.common.repl.replUnescapeLineBreaks import org.jetbrains.kotlin.cli.jvm.repl.writer.ReplWriter import org.w3c.dom.Element import org.xml.sax.InputSource @@ -79,7 +79,7 @@ class ReplSystemInWrapper( val unescapedXml = parseXml(xmlInput) return if (isReplScriptExecuting) - unescapeLineBreaks(unescapedXml) + unescapedXml.replUnescapeLineBreaks() else unescapedXml } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/writer/IdeSystemOutWrapperReplWriter.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/writer/IdeSystemOutWrapperReplWriter.kt index 4290c7c47ad..c1b89c0be14 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/writer/IdeSystemOutWrapperReplWriter.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/writer/IdeSystemOutWrapperReplWriter.kt @@ -16,16 +16,11 @@ package org.jetbrains.kotlin.cli.jvm.repl.writer -import com.intellij.openapi.util.text.StringUtil -import com.intellij.util.LineSeparator -import org.jetbrains.kotlin.cli.jvm.repl.messages.SOURCE_CHARS -import org.jetbrains.kotlin.cli.jvm.repl.messages.XML_REPLACEMENTS +import org.jetbrains.kotlin.cli.common.repl.replAddLineBreak +import org.jetbrains.kotlin.cli.common.repl.replOutputAsXml import org.jetbrains.kotlin.utils.repl.ReplEscapeType -import java.io.PrintStream import org.jetbrains.kotlin.utils.repl.ReplEscapeType.* - -internal val END_LINE: String = LineSeparator.getSystemLineSeparator().separatorString -internal val XML_PREAMBLE = "" +import java.io.PrintStream class IdeSystemOutWrapperReplWriter(standardOut: PrintStream) : PrintStream(standardOut, true), ReplWriter { override fun print(x: Boolean) = printWithEscaping(x.toString()) @@ -42,12 +37,7 @@ class IdeSystemOutWrapperReplWriter(standardOut: PrintStream) : PrintStream(stan } private fun printWithEscaping(text: String, escapeType: ReplEscapeType = USER_OUTPUT) { - super.print("${xmlEscape(text, escapeType)}${END_LINE}") - } - - private fun xmlEscape(s: String, escapeType: ReplEscapeType): String { - val singleLine = StringUtil.replace(s, SOURCE_CHARS, XML_REPLACEMENTS) - return "${XML_PREAMBLE}${StringUtil.escapeXml(singleLine)}" + super.print(text.replOutputAsXml(escapeType).replAddLineBreak()) } override fun printlnWelcomeMessage(x: String) = printlnWithEscaping(x, INITIAL_PROMPT) diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/repl/KtScratchReplExecutor.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/repl/KtScratchReplExecutor.kt index f970d4f6c58..c31ad906c06 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/repl/KtScratchReplExecutor.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/repl/KtScratchReplExecutor.kt @@ -20,10 +20,10 @@ import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.process.OSProcessHandler import com.intellij.execution.process.ProcessOutputTypes import com.intellij.openapi.util.Key -import com.intellij.openapi.util.text.StringUtil +import org.jetbrains.kotlin.cli.common.repl.replInputAsXml +import org.jetbrains.kotlin.cli.common.repl.replRemoveLineBreaksInTheEnd +import org.jetbrains.kotlin.cli.common.repl.replUnescapeLineBreaks import org.jetbrains.kotlin.console.KotlinConsoleKeeper -import org.jetbrains.kotlin.console.SOURCE_CHARS -import org.jetbrains.kotlin.console.XML_REPLACEMENTS import org.jetbrains.kotlin.console.actions.logError import org.jetbrains.kotlin.idea.scratch.* import org.jetbrains.kotlin.idea.scratch.output.ScratchOutput @@ -34,8 +34,6 @@ import java.io.ByteArrayInputStream import java.nio.charset.Charset import javax.xml.parsers.DocumentBuilderFactory -private val XML_PREAMBLE = "" - class KtScratchReplExecutor(file: ScratchFile) : ScratchExecutor(file) { private val history: ReplHistory = ReplHistory() private lateinit var osProcessHandler: OSProcessHandler @@ -63,12 +61,7 @@ class KtScratchReplExecutor(file: ScratchFile) : ScratchExecutor(file) { val processInputOS = osProcessHandler.processInput ?: return logError(this::class.java, "

Broken execute stream

") val charset = osProcessHandler.charset ?: Charsets.UTF_8 - val xmlRes = XML_PREAMBLE + - "" + - StringUtil.escapeXml( - StringUtil.replace(command, SOURCE_CHARS, XML_REPLACEMENTS) - ) + - "" + val xmlRes = command.replInputAsXml() val bytes = ("$xmlRes\n").toByteArray(charset) processInputOS.write(bytes) @@ -130,7 +123,7 @@ class KtScratchReplExecutor(file: ScratchFile) : ScratchExecutor(file) { val root = output.firstChild as Element val outputType = root.getAttribute("type") - val content = StringUtil.replace(root.textContent, XML_REPLACEMENTS, SOURCE_CHARS).trim('\n') + val content = root.textContent.replUnescapeLineBreaks().replRemoveLineBreaksInTheEnd() LOG.printDebugMessage("REPL output: $outputType $content") diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/console/CommandExecutor.kt b/idea/idea-repl/src/org/jetbrains/kotlin/console/CommandExecutor.kt index f87153679ac..e118c79bef0 100644 --- a/idea/idea-repl/src/org/jetbrains/kotlin/console/CommandExecutor.kt +++ b/idea/idea-repl/src/org/jetbrains/kotlin/console/CommandExecutor.kt @@ -18,11 +18,9 @@ package org.jetbrains.kotlin.console import com.intellij.execution.process.BaseOSProcessHandler import com.intellij.openapi.command.WriteCommandAction -import com.intellij.openapi.util.text.StringUtil +import org.jetbrains.kotlin.cli.common.repl.replInputAsXml import org.jetbrains.kotlin.console.actions.logError -private val XML_PREAMBLE = "" - class CommandExecutor(private val runner: KotlinConsoleRunner) { private val commandHistory = runner.commandHistory private val historyUpdater = HistoryUpdater(runner) @@ -50,12 +48,7 @@ class CommandExecutor(private val runner: KotlinConsoleRunner) { val processInputOS = processHandler.processInput ?: return logError(this::class.java, "

Broken process stream

") val charset = (processHandler as? BaseOSProcessHandler)?.charset ?: Charsets.UTF_8 - val xmlRes = XML_PREAMBLE + - "" + - StringUtil.escapeXml( - StringUtil.replace(command, SOURCE_CHARS, XML_REPLACEMENTS) - ) + - "" + val xmlRes = command.replInputAsXml() val bytes = ("$xmlRes\n").toByteArray(charset) processInputOS.write(bytes) diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/console/ReplOutputHandler.kt b/idea/idea-repl/src/org/jetbrains/kotlin/console/ReplOutputHandler.kt index 789558db1d6..57bf22bd59e 100644 --- a/idea/idea-repl/src/org/jetbrains/kotlin/console/ReplOutputHandler.kt +++ b/idea/idea-repl/src/org/jetbrains/kotlin/console/ReplOutputHandler.kt @@ -20,20 +20,16 @@ import com.intellij.execution.process.OSProcessHandler import com.intellij.execution.process.ProcessOutputTypes import com.intellij.openapi.util.Key import com.intellij.openapi.util.TextRange -import com.intellij.openapi.util.text.StringUtil -import org.jetbrains.annotations.NotNull +import org.jetbrains.kotlin.cli.common.repl.replUnescapeLineBreaks import org.jetbrains.kotlin.console.actions.logError import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.utils.repl.ReplEscapeType +import org.jetbrains.kotlin.utils.repl.ReplEscapeType.* import org.w3c.dom.Element import org.xml.sax.InputSource import java.io.ByteArrayInputStream import java.nio.charset.Charset import javax.xml.parsers.DocumentBuilderFactory -import org.jetbrains.kotlin.utils.repl.ReplEscapeType.* - -val XML_REPLACEMENTS: Array = arrayOf("#n", "#diez") -val SOURCE_CHARS: Array = arrayOf("\n", "#") data class SeverityDetails(val severity: Severity, val description: String, val range: TextRange) @@ -79,7 +75,7 @@ class ReplOutputHandler( val root = output.firstChild as Element val outputType = ReplEscapeType.valueOfOrNull(root.getAttribute("type")) - val content = StringUtil.replace(root.textContent, XML_REPLACEMENTS, SOURCE_CHARS) + val content = root.textContent.replUnescapeLineBreaks() when (outputType) { INITIAL_PROMPT -> buildWarningIfNeededBeforeInit(content)