Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CLI option --stdin-path to provide a virtual file location for stdin #2836

Merged
merged 5 commits into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions documentation/snapshot/docs/install/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,14 @@ ktlint --stdin -F
```

!!! tip "Suppress logging and error output"
Logging output printed to `stdout` can be suppressed by setting `--log-level=none` (see [logging](#logging)).
Output printed to `stderr` can be suppressed in different ways. To ignore all error output, add `2> /dev/null` to the end of the command line. Otherwise, specify a [reporter](#violation-reporting) to write the error output to a file.
Logging output printed to `stdout` can be suppressed by setting `--log-level=none` (see [logging](#logging)).
Output printed to `stderr` can be suppressed in different ways. To ignore all error output, add `2> /dev/null` to the end of the command line. Otherwise, specify a [reporter](#violation-reporting) to write the error output to a file.

If input from `stdin` represents the contents of a file, the file path can be supplied with `stdin-path`. This path is made available for rules to use, the `--format` option will not modify this file.

```shell title="file path from stdin-path"
ktlint --stdin --stdin-path /path/to/file/Foo.kt
```

### Git hooks

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ internal class KtlintCommandLine : CliktCommand(name = "ktlint") {
help = "Read file from stdin",
).flag()

private val stdinPath: String? by
option(
"--stdin-path",
help = "Virtual file location for stdin. When combined with option '--format' the actual file will not be overwritten",
)

private val patternsFromStdin: String? by
option(
"--patterns-from-stdin",
Expand Down Expand Up @@ -263,7 +269,7 @@ internal class KtlintCommandLine : CliktCommand(name = "ktlint") {
val editorConfigOverride =
EditorConfigOverride
.EMPTY_EDITOR_CONFIG_OVERRIDE
.applyIf(stdin) {
.applyIf(stdin && stdinPath.isNullOrBlank()) {
logger.debug {
"Add editor config override to disable 'filename' rule which can not be used in combination with reading from " +
"<stdin>"
Expand Down Expand Up @@ -427,11 +433,17 @@ internal class KtlintCommandLine : CliktCommand(name = "ktlint") {
ktLintRuleEngine: KtLintRuleEngine,
reporter: ReporterV2,
) {
val code =
stdinPath
?.expandTildeToFullPath()
?.let { path -> Paths.get(path) }
?.let { Code.fromStdin(it) }
?: Code.fromStdin()
report(
KtLintRuleEngine.STDIN_FILE,
process(
ktLintRuleEngine = ktLintRuleEngine,
code = Code.fromStdin(),
code = code,
baselineLintErrors = emptyList(),
),
reporter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,21 @@ class SimpleCLITest {
}
}

@Test
fun `Issue 1123 - Enable filename rule when --stdin and --stdin-path is used`(
@TempDir
tempDir: Path,
) {
CommandLineTestRunner(tempDir)
.run(
testProjectName = "too-many-empty-lines",
arguments = listOf("--stdin", "--stdin-path", "/foo/Foo.kt"),
stdin = ByteArrayInputStream("fun foo() = 42".toByteArray()),
) {
assertThat(normalOutput).doesNotContainLineMatching(Regex(".*ktlint_standard_filename: disabled.*"))
}
}

@Test
fun `Issue 1832 - Given stdin input containing Kotlin Script resulting in a KtLintParseException when linted as Kotlin code then process the input as Kotlin Script`(
@TempDir
Expand Down
1 change: 1 addition & 0 deletions ktlint-rule-engine/api/ktlint-rule-engine.api
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public final class com/pinterest/ktlint/rule/engine/api/Code$Companion {
public final fun fromSnippetWithPath (Ljava/lang/String;Ljava/nio/file/Path;)Lcom/pinterest/ktlint/rule/engine/api/Code;
public static synthetic fun fromSnippetWithPath$default (Lcom/pinterest/ktlint/rule/engine/api/Code$Companion;Ljava/lang/String;Ljava/nio/file/Path;ILjava/lang/Object;)Lcom/pinterest/ktlint/rule/engine/api/Code;
public final fun fromStdin ()Lcom/pinterest/ktlint/rule/engine/api/Code;
public final fun fromStdin (Ljava/nio/file/Path;)Lcom/pinterest/ktlint/rule/engine/api/Code;
}

public final class com/pinterest/ktlint/rule/engine/api/EditorConfigDefaults {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ public class Code private constructor(
) {
public fun fileNameOrStdin(): String =
if (isStdIn) {
STDIN_FILE
fileName ?: STDIN_FILE
} else {
fileName.orEmpty()
}

public fun filePathOrStdin(): String =
if (isStdIn) {
STDIN_FILE
filePath?.pathString ?: STDIN_FILE
} else {
filePath?.pathString.orEmpty()
}
Expand Down Expand Up @@ -115,6 +115,13 @@ public class Code private constructor(
* filesystem are ignored as the snippet is not associated with a file path. Use [Code.fromFile] for scanning a file while at the
* same time respecting the '.editorconfig' files on the path to the file.
*/
public fun fromStdin(): Code = fromSnippet(String(System.`in`.readBytes()))
public fun fromStdin(): Code = fromSnippetWithPath(String(System.`in`.readBytes()))

/**
* Create [Code] by reading the snippet from 'stdin'. The code snippet is associated with the given path. The actual file does not
* need to exist, neither do the contents of the actual file have to match with the content specified via 'stdin'. The
* '.editorconfig' files on the [virtualPath] are respected.
*/
public fun fromStdin(virtualPath: Path): Code = fromSnippetWithPath(String(System.`in`.readBytes()), virtualPath = virtualPath)
}
}