From f7e2b8b516c9d12dedff105dc173327357d08905 Mon Sep 17 00:00:00 2001 From: Yahor Berdnikau Date: Thu, 25 May 2023 21:15:08 +0200 Subject: [PATCH] [repo] KGP: drop groovy-all dependency Add ported from Groovy escapeJavaStyleString method into our codebase. --- .../kotlin-gradle-plugin/build.gradle.kts | 1 - .../kotlin/compilerRunner/reportUtils.kt | 63 +++++++++++++++++-- .../EscapeJavaStyleStringTest.kt | 55 ++++++++++++++++ 3 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/compilerRunner/EscapeJavaStyleStringTest.kt diff --git a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts index 98c19ab9b4a..65c7d4c7168 100644 --- a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts @@ -59,7 +59,6 @@ dependencies { commonCompileOnly("com.android.tools.build:gradle-api:4.2.2") commonCompileOnly("com.android.tools.build:builder:4.2.2") commonCompileOnly("com.android.tools.build:builder-model:4.2.2") - commonCompileOnly("org.codehaus.groovy:groovy-all:2.4.12") commonCompileOnly(intellijCore()) commonCompileOnly(commonDependency("org.jetbrains.teamcity:serviceMessages")) commonCompileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.4") diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/reportUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/reportUtils.kt index 2e3ec97ddd7..7a264c2564e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/reportUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/reportUtils.kt @@ -16,10 +16,10 @@ package org.jetbrains.kotlin.compilerRunner -import groovy.json.StringEscapeUtils +import org.gradle.internal.impldep.org.apache.commons.lang.StringEscapeUtils import org.jetbrains.kotlin.cli.common.ExitCode -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.config.KotlinCompilerVersion @@ -34,12 +34,15 @@ import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.FieldVisitor import org.jetbrains.org.objectweb.asm.Opcodes import java.io.File +import java.io.StringWriter import java.nio.file.Files import java.time.LocalDateTime import java.time.format.DateTimeFormatter +import java.util.* import java.util.zip.ZipFile import kotlin.concurrent.thread + internal fun loadCompilerVersion(compilerClasspath: Iterable): String { var result: String? = null @@ -94,7 +97,7 @@ internal fun runToolInSeparateProcess( classpath: Iterable, logger: KotlinLogger, buildDir: File, - jvmArgs: List = emptyList() + jvmArgs: List = emptyList(), ): ExitCode { val javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java" val classpathString = classpath.joinToString(separator = File.pathSeparator) { it.absolutePath } @@ -143,10 +146,60 @@ private fun writeArgumentsToFile(directory: File, argsArray: Array): Fil Files.createTempFile(directory.toPath(), prefix, suffix).toFile() else Files.createTempFile(prefix, suffix).toFile() - compilerOptions.writeText(argsArray.joinToString(" ") { "\"${StringEscapeUtils.escapeJava(it)}\"" }) + compilerOptions.writeText( + argsArray.joinToString(" ") { + "\"${it.escapeJavaStyleString()}\"" + } + ) return compilerOptions } +// Ported method from Groovy: +// https://github.com/apache/groovy/blob/73c0f12ab35427bc3e7fd76929b482df61e1b80d/subprojects/groovy-json/src/main/java/groovy/json/StringEscapeUtils.java#L175 +// Note: using '/f' char produces a compilation error, so removed it +internal fun String.escapeJavaStyleString( + escapeSingleQuote: Boolean = false, + escapeForwardSlash: Boolean = false, +): String { + return buildString { + this@escapeJavaStyleString.forEach { ch -> + when { + ch.toInt() > 0xfff -> append("\\u${ch.hex()}") + ch.toInt() > 0xff -> append("\\u0${ch.hex()}") + ch.toInt() >= 0x7f -> append("\\u00${ch.hex()}") + ch < 32.toChar() -> when (ch) { + '\b' -> append('\\').append('b') + '\n' -> append('\\').append('n') + '\t' -> append('\\').append('t') + '\r' -> append('\\').append('r') + else -> if (ch > 0xf.toChar()) { + append("\\u00${ch.hex()}") + } else { + append("\\u000${ch.hex()}") + } + } + else -> when (ch) { + '\'' -> { + if (escapeSingleQuote) append('\\') + append('\'') + } + '"' -> append('\\').append('"') + '\\' -> append('\\').append('\\') + '/' -> { + if (escapeForwardSlash) append('\\') + append('/') + } + else -> append(ch) + } + } + } + } +} + +private fun Char.hex(): String { + return Integer.toHexString(toInt()).toUpperCase(Locale.ENGLISH) +} + private fun createLoggingMessageCollector(log: KotlinLogger): MessageCollector = object : MessageCollector { private var hasErrors = false private val messageRenderer = MessageRenderer.PLAIN_FULL_PATHS @@ -164,7 +217,7 @@ private fun createLoggingMessageCollector(log: KotlinLogger): MessageCollector = CompilerMessageSeverity.ERROR, CompilerMessageSeverity.STRONG_WARNING, CompilerMessageSeverity.WARNING, - CompilerMessageSeverity.INFO + CompilerMessageSeverity.INFO, -> log.info(locMessage) CompilerMessageSeverity.LOGGING -> log.debug(locMessage) CompilerMessageSeverity.OUTPUT -> { diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/compilerRunner/EscapeJavaStyleStringTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/compilerRunner/EscapeJavaStyleStringTest.kt new file mode 100644 index 00000000000..290b0f6c7e3 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/compilerRunner/EscapeJavaStyleStringTest.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.compilerRunner + +import org.junit.Test +import kotlin.test.DefaultAsserter.assertEquals + +class EscapeJavaStyleStringTest { + + @Test + fun testEscapeJavaStyleString() { + assertEscapeJava("", "", "empty string") + assertEscapeJava("foo", "foo") + assertEscapeJava("\\t", "\t", "tab") + assertEscapeJava("\\\\", "\\", "backslash") + assertEscapeJava("'", "'", "single quote should not be escaped") + assertEscapeJava("\\\\\\b\\t\\r", "\\\b\t\r") + assertEscapeJava("\\u1234", "\u1234") + assertEscapeJava("\\u0234", "\u0234") + assertEscapeJava("\\u00EF", "\u00ef") + assertEscapeJava("\\u0001", "\u0001") + assertEscapeJava( + "\\uABCD", + "\uabcd", + "Should use capitalized Unicode hex" + ) + + assertEscapeJava( + "He didn't say, \\\"stop!\\\"", + "He didn't say, \"stop!\"" + ) + assertEscapeJava( + "This space is non-breaking:" + "\\u00A0", + "This space is non-breaking:\u00a0", + "non-breaking space" + ) + assertEscapeJava( + "\\uABCD\\u1234\\u012C", + "\uABCD\u1234\u012C" + ) + } + + private fun assertEscapeJava( + expected: String, + original: String, + message: String? = null + ) { + val converted: String = original.escapeJavaStyleString() + val assertMessage = "escapeJava(String) failed" + if (message == null) "" else ": $message" + assertEquals(assertMessage, expected, converted) + } +} \ No newline at end of file