diff --git a/build-common/test/org/jetbrains/kotlin/incremental/testingUtils/classFilesComparison.kt b/build-common/test/org/jetbrains/kotlin/incremental/testingUtils/classFilesComparison.kt index 922f9d0dfe4..8591dd23d1e 100644 --- a/build-common/test/org/jetbrains/kotlin/incremental/testingUtils/classFilesComparison.kt +++ b/build-common/test/org/jetbrains/kotlin/incremental/testingUtils/classFilesComparison.kt @@ -205,7 +205,7 @@ private fun kjsmToString(kjsmFile: File): String { } private fun sourceMapFileToString(sourceMapFile: File, generatedJsFile: File): String { - val sourceMapParseResult = SourceMapParser.parse(StringReader(sourceMapFile.readText())) + val sourceMapParseResult = SourceMapParser.parse(sourceMapFile.readText()) return when (sourceMapParseResult) { is SourceMapSuccess -> { val bytesOut = ByteArrayOutputStream() diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/dce/K2JSDce.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/dce/K2JSDce.kt index 5f2c50869e7..0a44a8e85e5 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/dce/K2JSDce.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/dce/K2JSDce.kt @@ -122,7 +122,7 @@ class K2JSDce : CLITool() { private fun mapSourcePaths(inputFile: File, targetFile: File): Boolean { val json = try { - InputStreamReader(FileInputStream(inputFile), "UTF-8").use { parseJson(it) } + parseJson(inputFile) } catch (e: JsonSyntaxException) { return false } diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/internal/JSStdlibLinker.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/internal/JSStdlibLinker.kt index efb4d2c1df5..c9cfdd23a6c 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/internal/JSStdlibLinker.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/internal/JSStdlibLinker.kt @@ -52,7 +52,7 @@ private fun mergeStdlibParts(outputFile: File, wrapperFile: File, baseDir: File, val sourceMapFile = File(file.parent, file.name + ".map") if (sourceMapFile.exists()) { - val sourceMapParse = sourceMapFile.reader().use { SourceMapParser.parse(it) } + val sourceMapParse = SourceMapParser.parse(sourceMapFile) when (sourceMapParse) { is SourceMapError -> { System.err.println("Error parsing source map file $sourceMapFile: ${sourceMapParse.message}") @@ -82,7 +82,7 @@ private fun mergeStdlibParts(outputFile: File, wrapperFile: File, baseDir: File, outputFile.writeText(programText + "\n//# sourceMappingURL=${sourceMapFile.name}\n") - val sourceMapJson = StringReader(sourceMapContent).use { parseJson(it) } + val sourceMapJson = parseJson(sourceMapContent) val sources = (sourceMapJson as JsonObject).properties["sources"] as JsonArray sourceMapJson.properties["sourcesContent"] = JsonArray(*sources.elements.map { sourcePath -> diff --git a/js/js.dce/src/org/jetbrains/kotlin/js/dce/DeadCodeElimination.kt b/js/js.dce/src/org/jetbrains/kotlin/js/dce/DeadCodeElimination.kt index 136c629f011..3e1c56a526d 100644 --- a/js/js.dce/src/org/jetbrains/kotlin/js/dce/DeadCodeElimination.kt +++ b/js/js.dce/src/org/jetbrains/kotlin/js/dce/DeadCodeElimination.kt @@ -89,8 +89,7 @@ class DeadCodeElimination(private val logConsumer: (DCELogLevel, String) -> Unit return@map block } val sourceMapParse = file.sourceMapResource - ?.let { InputStreamReader(it.reader(), "UTF-8") } - ?.use { SourceMapParser.parse(it) } + ?.let { SourceMapParser.parse(InputStreamReader(it.reader(), "UTF-8").readText()) } when (sourceMapParse) { is SourceMapError -> { logConsumer( diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt index 83686c88714..c4f830c159b 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt @@ -114,7 +114,7 @@ class FunctionReader( } val sourceMap = sourceMapContent?.let { - val sourceMapResult = SourceMapParser.parse(StringReader(it)) + val sourceMapResult = SourceMapParser.parse(it) when (sourceMapResult) { is SourceMapSuccess -> sourceMapResult.value is SourceMapError -> { diff --git a/js/js.parser/src/org/jetbrains/kotlin/js/parser/sourcemaps/JSON.kt b/js/js.parser/src/org/jetbrains/kotlin/js/parser/sourcemaps/JSON.kt index 441fc8197b9..e6c73422e4e 100644 --- a/js/js.parser/src/org/jetbrains/kotlin/js/parser/sourcemaps/JSON.kt +++ b/js/js.parser/src/org/jetbrains/kotlin/js/parser/sourcemaps/JSON.kt @@ -16,10 +16,7 @@ package org.jetbrains.kotlin.js.parser.sourcemaps -import java.io.Reader -import java.io.StringReader -import java.io.StringWriter -import java.io.Writer +import java.io.* sealed class JsonNode { abstract fun write(writer: Writer) @@ -120,8 +117,7 @@ data class JsonNumber(val value: Double) : JsonNode() { override fun write(writer: Writer) { if (value.toLong().toDouble() == value) { writer.append(value.toLong().toString()) - } - else { + } else { writer.append(value.toString()) } } @@ -130,14 +126,15 @@ data class JsonNumber(val value: Double) : JsonNode() { } class JsonSyntaxException(val offset: Int, val line: Int, val column: Int, val text: String) : - RuntimeException("JSON syntax error at ${line + 1}, ${column + 1}: $text") + RuntimeException("JSON syntax error at ${line + 1}, ${column + 1}: $text") -fun parseJson(reader: Reader): JsonNode = JsonParser(reader).parse() +fun parseJson(file: File): JsonNode = parseJson(file.readText(Charsets.UTF_8)) -fun parseJson(text: String): JsonNode = parseJson(StringReader(text)) +fun parseJson(text: String): JsonNode = JsonParser(text).parse() -private class JsonParser(val reader: Reader) { - private var charCode = reader.read() +private class JsonParser(val content: String) { + private var index = 0 + private var charCode = content.getOrNull(index++)?.toInt() ?: -1 private var offset = 0 private var line = 0 private var col = 0 @@ -165,13 +162,27 @@ private class JsonParser(val reader: Reader) { '['.toInt() -> parseArray() '{'.toInt() -> parseObject() '"'.toInt() -> JsonString(parseString()) - 'n'.toInt() -> { expectString("null"); JsonNull } - 'f'.toInt() -> { expectString("false"); JsonBoolean.FALSE } - 't'.toInt() -> { expectString("true"); JsonBoolean.TRUE } - in '0'.toInt()..'9'.toInt() -> JsonNumber(parseNumber()) - '-'.toInt() -> { advance(); JsonNumber(-parseNumber()) + 'n'.toInt() -> { + expectString("null") + JsonNull + } + 'f'.toInt() -> { + expectString("false") + JsonBoolean.FALSE + } + 't'.toInt() -> { + expectString("true") + JsonBoolean.TRUE + } + '-'.toInt() -> { + advance() + JsonNumber(-parseNumber()) + } + else -> if (charCode in '0'.toInt()..'9'.toInt()) { + JsonNumber(parseNumber()) + } else { + error("Unexpected char") } - else -> error("Unexpected char") } } @@ -183,8 +194,7 @@ private class JsonParser(val reader: Reader) { if (charCode == ']'.toInt()) { advance() break - } - else { + } else { if (result.elements.isNotEmpty()) { expectCharAndAdvance(',') } @@ -202,8 +212,7 @@ private class JsonParser(val reader: Reader) { if (charCode == '}'.toInt()) { advance() break - } - else { + } else { if (result.properties.isNotEmpty()) { expectCharAndAdvance(',') } @@ -356,7 +365,7 @@ private class JsonParser(val reader: Reader) { wasCR = false } } - charCode = reader.read() + charCode = content.getOrNull(index++)?.toInt() ?: -1 offset++ } diff --git a/js/js.parser/src/org/jetbrains/kotlin/js/parser/sourcemaps/SourceMapParser.kt b/js/js.parser/src/org/jetbrains/kotlin/js/parser/sourcemaps/SourceMapParser.kt index 56102ae8254..ac602ba3271 100644 --- a/js/js.parser/src/org/jetbrains/kotlin/js/parser/sourcemaps/SourceMapParser.kt +++ b/js/js.parser/src/org/jetbrains/kotlin/js/parser/sourcemaps/SourceMapParser.kt @@ -16,20 +16,29 @@ package org.jetbrains.kotlin.js.parser.sourcemaps +import java.io.File import java.io.IOException -import java.io.Reader import java.io.StringReader object SourceMapParser { @Throws(IOException::class) - fun parse(reader: Reader): SourceMapParseResult { + fun parse(file: File): SourceMapParseResult { + return parse(file.readText(Charsets.UTF_8)) + } + + @Throws(IOException::class) + fun parse(content: String): SourceMapParseResult { val jsonObject = try { - parseJson(reader) + parseJson(content) } catch (e: JsonSyntaxException) { return SourceMapError(e.message ?: "parse error") } + return parse(jsonObject) + } + @Throws(IOException::class) + private fun parse(jsonObject: JsonNode): SourceMapParseResult { if (jsonObject !is JsonObject) return SourceMapError("Top-level object expected") val version = jsonObject.properties["version"] ?: return SourceMapError("Version not defined") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt index b43e58086ad..585b1baef21 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt @@ -420,8 +420,8 @@ abstract class BasicBoxTest( val recompiledSourceMap = removeRecompiledSuffix( FileUtil.loadFile(File(recompiledOutputFile.parentFile, recompiledOutputFile.name + ".map"))) if (originalSourceMap != recompiledSourceMap) { - val originalSourceMapParse = SourceMapParser.parse(StringReader(originalSourceMap)) - val recompiledSourceMapParse = SourceMapParser.parse(StringReader(recompiledSourceMap)) + val originalSourceMapParse = SourceMapParser.parse(originalSourceMap) + val recompiledSourceMapParse = SourceMapParser.parse(recompiledSourceMap) if (originalSourceMapParse is SourceMapSuccess && recompiledSourceMapParse is SourceMapSuccess) { assertEquals("Source map file changed after recompilation", originalSourceMapParse.toDebugString(), @@ -570,7 +570,7 @@ abstract class BasicBoxTest( val parsedProgram = JsProgram() parsedProgram.globalBlock.statements += parse(code, ThrowExceptionOnErrorReporter, parsedProgram.scope, outputFile.path).orEmpty() removeLocationFromBlocks(parsedProgram) - val sourceMapParseResult = SourceMapParser.parse(StringReader(generatedSourceMap)) + val sourceMapParseResult = SourceMapParser.parse(generatedSourceMap) val sourceMap = when (sourceMapParseResult) { is SourceMapSuccess -> sourceMapParseResult.value is SourceMapError -> error("Could not parse source map: ${sourceMapParseResult.message}")