diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt index 74a0c2ed9ae..ab0014b7fcd 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt @@ -54,11 +54,16 @@ data class ArgumentParseErrors( var argumentWithoutValue: String? = null, - val argfileErrors: MutableList = SmartList() + val argfileErrors: MutableList = SmartList() ) // Parses arguments into the passed [result] object. Errors related to the parsing will be collected into [CommonToolArguments.errors]. fun parseCommandLineArguments(args: List, result: A) { + val preprocessed = preprocessCommandLineArguments(args, result.errors) + parsePreprocessedCommandLineArguments(preprocessed, result) +} + +private fun parsePreprocessedCommandLineArguments(args: List, result: A) { data class ArgumentField(val property: KMutableProperty1, val argument: Argument) @Suppress("UNCHECKED_CAST") diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/preprocessCommandLineArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/preprocessCommandLineArguments.kt index ff2461517f2..4fc96e713b5 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/preprocessCommandLineArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/preprocessCommandLineArguments.kt @@ -5,39 +5,42 @@ package org.jetbrains.kotlin.cli.common.arguments -import java.io.* -import java.nio.charset.StandardCharsets +import java.io.File +import java.io.FileNotFoundException +import java.io.IOException +import java.io.Reader -private val experimentalArgfileArgument = "-Xargfile" -private val QUOTATION_MARK = '"' -private val BACKSLASH = '\\' -private val WHITESPACE = ' ' -private val NEWLINE = '\n' +private const val EXPERIMENTAL_ARGFILE_ARGUMENT = "-Xargfile" + +private const val QUOTATION_MARK = '"' +private const val BACKSLASH = '\\' +private const val WHITESPACE = ' ' +private const val NEWLINE = '\n' /** * Performs initial preprocessing of arguments, passed to the compiler. * This is done prior to *any* arguments parsing, and result of preprocessing * will be used instead of actual passed arguments. */ -fun preprocessCommandLineArguments(args: List, result: A): List = +internal fun preprocessCommandLineArguments(args: List, errors: ArgumentParseErrors): List = args.flatMap { if (it.isArgumentForArgfile) - File(it.argfilePath).expand(result) + File(it.argfilePath).expand(errors) else listOf(it) } -private fun File.expand(result: A): List { +private fun File.expand(errors: ArgumentParseErrors): List { return try { bufferedReader(Charsets.UTF_8).use { generateSequence { it.parseNextArgument() }.toList() } } catch (e: FileNotFoundException) { // Process FNFE separately to render absolutePath in error message - result.errors.argfileErrors += "Argfile not found: $absolutePath" + errors.argfileErrors += "Argfile not found: $absolutePath" emptyList() } catch (e: IOException) { - result.errors.argfileErrors += "Error while reading argfile: $e" + errors.argfileErrors += "Error while reading argfile: $e" emptyList() } } @@ -69,9 +72,9 @@ private fun Reader.consumeRestOfEscapedSequence(sb: StringBuilder) { } private val String.argfilePath: String - get() = removePrefix("$experimentalArgfileArgument=") + get() = removePrefix("$EXPERIMENTAL_ARGFILE_ARGUMENT=") // Note that currently we use only experimental syntax for passing argfiles // In 1.3 we can support also javac-like syntax `@argfile` private val String.isArgumentForArgfile: Boolean - get() = startsWith("$experimentalArgfileArgument=") + get() = startsWith("$EXPERIMENTAL_ARGFILE_ARGUMENT=") diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt index afcafe97e32..786de45824a 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt @@ -41,8 +41,7 @@ abstract class CLITool { args: Array ): ExitCode { val arguments = createArguments() - val preprocessedArguments = preprocessCommandLineArguments(args.asList(), arguments) - parseCommandLineArguments(preprocessedArguments, arguments) + parseCommandLineArguments(args.asList(), arguments) val collector = PrintingMessageCollector(errStream, messageRenderer, arguments.verbose) try { @@ -106,8 +105,7 @@ abstract class CLITool { // Used in kotlin-maven-plugin (KotlinCompileMojoBase) and in kotlin-gradle-plugin (KotlinJvmOptionsImpl, KotlinJsOptionsImpl) fun parseArguments(args: Array, arguments: A) { - val preprocessed = preprocessCommandLineArguments(args.asList(), arguments) - parseCommandLineArguments(preprocessed, arguments) + parseCommandLineArguments(args.asList(), arguments) val message = validateArguments(arguments.errors) if (message != null) { throw IllegalArgumentException(message) diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/cli/AbstractCliTest.java b/compiler/tests-common/tests/org/jetbrains/kotlin/cli/AbstractCliTest.java index f9101a3097c..b0457c29d92 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/cli/AbstractCliTest.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/cli/AbstractCliTest.java @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.cli; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.io.FileUtilKt; import com.intellij.openapi.util.text.StringUtil; import kotlin.Pair; import kotlin.collections.CollectionsKt; @@ -31,7 +30,6 @@ import org.jetbrains.kotlin.cli.js.K2JSCompiler; import org.jetbrains.kotlin.cli.js.dce.K2JSDce; import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler; import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler; -import org.jetbrains.kotlin.codegen.TestUtilsKt; import org.jetbrains.kotlin.config.KotlinCompilerVersion; import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion; import org.jetbrains.kotlin.test.CompilerTestUtil; @@ -44,14 +42,14 @@ import org.jetbrains.kotlin.utils.StringsKt; import org.junit.Assert; import java.io.File; -import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; public abstract class AbstractCliTest extends TestCaseWithTmpdir { private static final String TESTDATA_DIR = "$TESTDATA_DIR$"; + private static final String EXPERIMENTAL_ARGFILE_ARGUMENT_PREFIX = "-Xargfile="; + public static Pair executeCompilerGrabOutput(@NotNull CLITool compiler, @NotNull List args) { StringBuilder output = new StringBuilder(); @@ -202,21 +200,17 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir { String argWithTestPathsReplaced = replaceTestPaths(argWithColonsReplaced, testDataDir, tempDir); - if (isArgfileArgument(arg)) { + if (arg.startsWith(EXPERIMENTAL_ARGFILE_ARGUMENT_PREFIX)) { return mockArgfile(argWithTestPathsReplaced, testDataDir, tempDir); - } else { + } + else { return argWithTestPathsReplaced; } } - private static boolean isArgfileArgument(@NotNull String arg) { - return arg.startsWith("-Xargfile="); - } - // Create new temp. argfile with all test paths replaced and return argfile-argument pointing to that file private static String mockArgfile(@NotNull String argfileArgument, @NotNull String testDataDir, @NotNull String tempDir) { - int firstIndexOfArgfilePath = "-Xargfile=".length(); - String argfilePath = argfileArgument.substring(firstIndexOfArgfilePath); + String argfilePath = kotlin.text.StringsKt.substringAfter(argfileArgument, EXPERIMENTAL_ARGFILE_ARGUMENT_PREFIX, argfileArgument); File argfile = new File(argfilePath); if (argfile.exists()) { @@ -224,7 +218,7 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir { String oldArgfileContent = FilesKt.readText(argfile, Charsets.UTF_8); String newArgfileContent = replaceTestPaths(oldArgfileContent, testDataDir, tempDir); FilesKt.writeText(mockArgfile, newArgfileContent, Charsets.UTF_8); - return "-Xargfile=" + mockArgfile.getAbsolutePath(); + return EXPERIMENTAL_ARGFILE_ARGUMENT_PREFIX + mockArgfile.getAbsolutePath(); } else { return argfileArgument; }