From 6f8049ffd3eb8b41230d130488b693a4e73f8921 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 25 May 2023 17:20:31 +0200 Subject: [PATCH] CLI: support -language-version option in cli runner --- .../src/org/jetbrains/kotlin/runner/Main.kt | 146 +++++++++--------- .../kotlin/cli/LauncherScriptTest.kt | 12 ++ 2 files changed, 88 insertions(+), 70 deletions(-) diff --git a/compiler/cli/cli-runner/src/org/jetbrains/kotlin/runner/Main.kt b/compiler/cli/cli-runner/src/org/jetbrains/kotlin/runner/Main.kt index c0410260e75..c15b35a99ef 100644 --- a/compiler/cli/cli-runner/src/org/jetbrains/kotlin/runner/Main.kt +++ b/compiler/cli/cli-runner/src/org/jetbrains/kotlin/runner/Main.kt @@ -82,83 +82,89 @@ object Main { arguments.addAll(args.copyOfRange(i+1, args.size)) } - if ("-help" == arg || "-h" == arg) { - printUsageAndExit() - } - else if ("-version" == arg) { - printVersionAndExit() - } - else if ("-classpath" == arg || "-cp" == arg) { - for (path in next().split(File.pathSeparator).filter(String::isNotEmpty)) { - classpath.addPath(path) + when { + "-help" == arg || "-h" == arg -> { + printUsageAndExit() } - } - else if ("-compiler-path" == arg) { - for (path in next().split(File.pathSeparator).filter(String::isNotEmpty)) { - compilerClasspath.addPath(path) + "-version" == arg -> { + printVersionAndExit() } - } - else if ("-howtorun" == arg) { - if (howtorun != HowToRun.GUESS) { - throw RunnerException("-howtorun is already set to ${howtorun.argName}") + "-classpath" == arg || "-cp" == arg -> { + for (path in next().split(File.pathSeparator).filter(String::isNotEmpty)) { + classpath.addPath(path) + } } - val howToRunArg = next() - if (howToRunArg.startsWith(".")) { - howtorun = HowToRun.SCRIPT - compilerArguments.add("-Xdefault-script-extension=$howToRunArg") - } else { - howtorun = HowToRun.fromArg(howToRunArg) - ?: throw RunnerException("invalid argument to the option -howtorun $howToRunArg, valid arguments are: ${HowToRun.validValues}") + "-compiler-path" == arg -> { + for (path in next().split(File.pathSeparator).filter(String::isNotEmpty)) { + compilerClasspath.addPath(path) + } } - } - else if ("-expression" == arg || "-e" == arg) { - if (howtorun != HowToRun.GUESS && howtorun != HowToRun.SCRIPT) { - throw RunnerException("expression evaluation is not compatible with -howtorun argument ${howtorun.argName}") + "-howtorun" == arg -> { + if (howtorun != HowToRun.GUESS) { + throw RunnerException("-howtorun is already set to ${howtorun.argName}") + } + val howToRunArg = next() + if (howToRunArg.startsWith(".")) { + howtorun = HowToRun.SCRIPT + compilerArguments.add("-Xdefault-script-extension=$howToRunArg") + } else { + howtorun = HowToRun.fromArg(howToRunArg) + ?: throw RunnerException("invalid argument to the option -howtorun $howToRunArg, valid arguments are: ${HowToRun.validValues}") + } } - setRunner(ExpressionRunner(next())) - restAsArguments() - break - } - else if ("-no-stdlib" == arg) { - noStdLib = true - compilerArguments.add(arg) - } - else if ("-no-reflect" == arg) { - noReflect = true - compilerArguments.add(arg) - } - else if (arg.startsWith("-X")) { - compilerArguments.add(arg) - } - else if (arg.startsWith("-")) { - throw RunnerException("unknown option: $arg") - } - else if (howtorun == HowToRun.JAR || (howtorun == HowToRun.GUESS && arg.endsWith(".jar"))) { - setRunner(JarRunner(arg)) - restAsArguments() - break - } - else if (howtorun == HowToRun.SCRIPT || (howtorun == HowToRun.GUESS && arg.endsWith(".kts"))) { - setRunner(ScriptRunner(arg)) - restAsArguments() - break - } - else { - val workingDir = File(".") - val classFile = File(arg) + "-expression" == arg || "-e" == arg -> { + if (howtorun != HowToRun.GUESS && howtorun != HowToRun.SCRIPT) { + throw RunnerException("expression evaluation is not compatible with -howtorun argument ${howtorun.argName}") + } + setRunner(ExpressionRunner(next())) + restAsArguments() + break + } + "-no-stdlib" == arg -> { + noStdLib = true + compilerArguments.add(arg) + } + "-no-reflect" == arg -> { + noReflect = true + compilerArguments.add(arg) + } + arg.startsWith("-X") -> { + compilerArguments.add(arg) + } + "-language-version" == arg -> { + compilerArguments.add(arg) + compilerArguments.add(next()) + } + arg.startsWith("-") -> { + throw RunnerException("unknown option: $arg") + } + howtorun == HowToRun.JAR || howtorun == HowToRun.GUESS && arg.endsWith(".jar") -> { + setRunner(JarRunner(arg)) + restAsArguments() + break + } + howtorun == HowToRun.SCRIPT || howtorun == HowToRun.GUESS && arg.endsWith(".kts") -> { + setRunner(ScriptRunner(arg)) + restAsArguments() + break + } + else -> { + val workingDir = File(".") + val classFile = File(arg) - // Allow running class files with '.class' extension. - // In order to infer its fully qualified name, it should be located in the current working directory or a subdirectory of it - val className = - if (arg.endsWith(".class") && classFile.exists() && classFile.canonicalPath.contains(workingDir.canonicalPath)) { - classFile.canonicalFile.toRelativeString(workingDir.canonicalFile) - .removeSuffix(".class") - .replace(File.separatorChar, '.') - } else arg + // Allow running class files with '.class' extension. + // In order to infer its fully qualified name, it should be located in the current working directory or a subdirectory of it + val className = + if (arg.endsWith(".class") && classFile.exists() && classFile.canonicalPath.contains(workingDir.canonicalPath)) { + classFile.canonicalFile.toRelativeString(workingDir.canonicalFile) + .removeSuffix(".class") + .replace(File.separatorChar, '.') + } else arg - setRunner(MainClassRunner(className)) - restAsArguments() - break + setRunner(MainClassRunner(className)) + restAsArguments() + break + } } i++ } diff --git a/compiler/tests/org/jetbrains/kotlin/cli/LauncherScriptTest.kt b/compiler/tests/org/jetbrains/kotlin/cli/LauncherScriptTest.kt index 8800ebfe27f..327c1463f76 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/LauncherScriptTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/cli/LauncherScriptTest.kt @@ -192,6 +192,18 @@ class LauncherScriptTest : TestCaseWithTmpdir() { ) } + fun testRunnerExpressionLanguageVersion20() { + runProcess( + "kotlin", + "-language-version", "2.0", "-e", + "println(args.joinToString())", + "-a", + "b", + expectedStdout = "-a, b\n", + expectedStderr = "warning: language version 2.0 is experimental, there are no backwards compatibility guarantees for new language and library features\n" + ) + } + fun testCommandlineProcessing() { runProcess( "kotlin",