Add support for @argsfile
Summary:
added a new argument type with the format @[filename].
If supplied, ktfmt arguments will be extracted from file.
Reviewed By: cgrushko
Differential Revision: D34612728
fbshipit-source-id: 46cb237b12fd929719fcab7c05a5f42ec7d398fa
diff --git a/core/src/main/java/com/facebook/ktfmt/cli/Main.kt b/core/src/main/java/com/facebook/ktfmt/cli/Main.kt
index f71cd4c..4c965bb 100644
--- a/core/src/main/java/com/facebook/ktfmt/cli/Main.kt
+++ b/core/src/main/java/com/facebook/ktfmt/cli/Main.kt
@@ -65,12 +65,13 @@
}
}
- private val parsedArgs: ParsedArgs = ParsedArgs.parseOptions(err, args)
+ private val parsedArgs: ParsedArgs = ParsedArgs.processArgs(err, args)
fun run(): Int {
if (parsedArgs.fileNames.isEmpty()) {
err.println(
"Usage: ktfmt [--dropbox-style | --google-style | --kotlinlang-style] [--dry-run] [--set-exit-if-changed] File1.kt File2.kt ...")
+ err.println("Or: ktfmt @file")
return 1
}
diff --git a/core/src/main/java/com/facebook/ktfmt/cli/ParsedArgs.kt b/core/src/main/java/com/facebook/ktfmt/cli/ParsedArgs.kt
index bb959c8..503cb89 100644
--- a/core/src/main/java/com/facebook/ktfmt/cli/ParsedArgs.kt
+++ b/core/src/main/java/com/facebook/ktfmt/cli/ParsedArgs.kt
@@ -18,6 +18,7 @@
import com.facebook.ktfmt.format.Formatter
import com.facebook.ktfmt.format.FormattingOptions
+import java.io.File
import java.io.PrintStream
/** ParsedArgs holds the arguments passed to ktfmt on the command-line, after parsing. */
@@ -34,6 +35,15 @@
val setExitIfChanged: Boolean,
) {
companion object {
+
+ fun processArgs(err: PrintStream, args: Array<String>): ParsedArgs {
+ if (args.size == 1 && args[0].startsWith("@")) {
+ return parseOptions(err, File(args[0].substring(1)).readLines().toTypedArray())
+ } else {
+ return parseOptions(err, args)
+ }
+ }
+
/** parseOptions parses command-line arguments passed to ktfmt. */
fun parseOptions(err: PrintStream, args: Array<String>): ParsedArgs {
val fileNames = mutableListOf<String>()
@@ -49,6 +59,7 @@
arg == "--dry-run" || arg == "-n" -> dryRun = true
arg == "--set-exit-if-changed" -> setExitIfChanged = true
arg.startsWith("--") -> err.println("Unexpected option: $arg")
+ arg.startsWith("@") -> err.println("Unexpected option: $arg")
else -> fileNames.add(arg)
}
}
diff --git a/core/src/test/java/com/facebook/ktfmt/cli/ParsedArgsTest.kt b/core/src/test/java/com/facebook/ktfmt/cli/ParsedArgsTest.kt
index 75df85a..63d4c2f 100644
--- a/core/src/test/java/com/facebook/ktfmt/cli/ParsedArgsTest.kt
+++ b/core/src/test/java/com/facebook/ktfmt/cli/ParsedArgsTest.kt
@@ -20,7 +20,10 @@
import com.facebook.ktfmt.format.FormattingOptions
import com.google.common.truth.Truth.assertThat
import java.io.ByteArrayOutputStream
+import java.io.FileNotFoundException
import java.io.PrintStream
+import junit.framework.Assert.fail
+import org.junit.After
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -29,6 +32,13 @@
@RunWith(JUnit4::class)
class ParsedArgsTest {
+ private val root = createTempDir()
+
+ @After
+ fun tearDown() {
+ root.deleteRecursively()
+ }
+
@Test
fun `files to format are returned and unknown flags are reported`() {
val out = ByteArrayOutputStream()
@@ -40,6 +50,16 @@
}
@Test
+ fun `files to format are returned and flags starting with @ are reported`() {
+ val out = ByteArrayOutputStream()
+
+ val (fileNames, _) = ParsedArgs.parseOptions(PrintStream(out), arrayOf("foo.kt", "@unknown"))
+
+ assertThat(fileNames).containsExactly("foo.kt")
+ assertThat(out.toString()).isEqualTo("Unexpected option: @unknown\n")
+ }
+
+ @Test
fun `parseOptions uses default values when args are empty`() {
val out = ByteArrayOutputStream()
@@ -107,4 +127,30 @@
assertThat(parsed.setExitIfChanged).isTrue()
}
+
+ @Test
+ fun `processArgs use the @file option with non existing file`() {
+ val out = ByteArrayOutputStream()
+
+ try {
+ ParsedArgs.processArgs(PrintStream(out), arrayOf("@non-existing-file"))
+ fail("expected an exception of type FileNotFoundException but nothing was thrown")
+ } catch (e: FileNotFoundException) {
+ assertThat(e.message).contains("non-existing-file (No such file or directory)")
+ }
+ }
+
+ @Test
+ fun `processArgs use the @file option with file containing arguments`() {
+ val out = ByteArrayOutputStream()
+ val file = root.resolve("existing-file")
+ file.writeText("--google-style\n--dry-run\n--set-exit-if-changed\nFile1.kt\nFile2.kt\n")
+
+ val parsed = ParsedArgs.processArgs(PrintStream(out), arrayOf("@" + file.absolutePath))
+
+ assertThat(parsed.formattingOptions).isEqualTo(Formatter.GOOGLE_FORMAT)
+ assertThat(parsed.dryRun).isTrue()
+ assertThat(parsed.setExitIfChanged).isTrue()
+ assertThat(parsed.fileNames).containsExactlyElementsIn(listOf("File1.kt", "File2.kt"))
+ }
}