Skip to content
Open
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
1 change: 1 addition & 0 deletions .biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"!**/undefined",
"!**/benchmark/target",
"!**/benches",
"!!**/e2e-tests",
"!!**/target",
"!!.cargo"
]
Expand Down
25 changes: 25 additions & 0 deletions .changeset/blue-parts-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
"@biomejs/biome": patch
---

Fixed [#8233](https://github.com/biomejs/biome/issues/8233), where Biome CLI in
stdin mode didn't work correctly when handling files in projects with nested
configurations. For example, with the following structure,
`--stdin-file-path=subdirectory/...` would not use the nested configuration in
`subdirectory/biome.json`:

```
├── biome.json
└── subdirectory
├── biome.json
└── lib.js
```

```shell
biome format --write --stdin-file-path=subdirectory/lib.js < subdirectory/lib.js
```

Now, the nested configuration is correctly picked up and applied.

In addition, Biome now shows a warning if `--stdin-file-path` is provided but
that path is ignored and therefore not formatted or fixed.
4 changes: 1 addition & 3 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,7 @@ jobs:
- name: Build Biome debug binary
run: cargo build --bin biome
- name: Run tests
run: |
cd e2e-tests
sh test-all.sh
run: ./e2e-tests/test-all.sh

documentation:
name: Documentation
Expand Down
4 changes: 4 additions & 0 deletions crates/biome_cli/src/runner/impls/process_file/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ impl ProcessFile for FormatProcessFile {

if file_features.is_ignored() {
console.append(markup! {{content}});
// Write error last because files may generally be long
console.error(markup! {
<Warn>"The content was not formatted because the path `"{biome_path.as_str()}"` is ignored."</Warn>
});
return Ok(());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ impl ProcessFile for LintAssistProcessFile {

if file_features.is_ignored() {
console.append(markup! {{content}});
// Write error last because files may generally be long
console.error(markup! {
<Warn>"The content was not fixed because the path `"{biome_path.as_str()}"` is ignored."</Warn>
});
return Ok(());
}

Expand Down
5 changes: 4 additions & 1 deletion crates/biome_cli/src/runner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,10 @@ pub(crate) trait CommandRunner {
} = configured_workspace;

if let Some(stdin) = self.get_stdin(console, execution.as_ref())? {
let biome_path = BiomePath::new(stdin.as_path());
// Biome path must starts_with(the project directory), which will have been
// joined to workdir. Otherwise we won't find nested settings.
let working_dir = fs.working_directory().unwrap_or_default();
let biome_path = BiomePath::new(working_dir.join(stdin.as_path()));
if biome_path.extension().is_none() {
console.error(markup! {
{PrintDiagnostic::simple(&CliDiagnostic::from(StdinDiagnostic::new_no_extension()))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ function f() {var x=1; return{x}} class Foo {}
```block
function f() {var x=1; return{x}} class Foo {}
```

```block
The content was not fixed because the path `mock.cc` is ignored.
```
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ function f() {return{}}
```block
function f() {return{}}
```

```block
The content was not formatted because the path `mock.cc` is ignored.
```
2 changes: 1 addition & 1 deletion e2e-tests/relative-path-ignore-file/biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"root": false,
"root": true,
"files": {
"includes": ["**", "!file.js"]
},
Expand Down
2 changes: 1 addition & 1 deletion e2e-tests/relative-path/biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"root": false,
"root": true,
"files": {
"includes": ["**"]
},
Expand Down
5 changes: 5 additions & 0 deletions e2e-tests/stdin-nested-config/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let x = 5;

function indent() {
return x;
}
5 changes: 5 additions & 0 deletions e2e-tests/stdin-nested-config/app.js.formatted
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let x = 5;

function indent() {
return x;
}
16 changes: 16 additions & 0 deletions e2e-tests/stdin-nested-config/biome.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"root": true,
"vcs": {
"enabled": false
},
"files": {
"ignoreUnknown": false,
// Include .js recursively, but not .ts
"includes": ["**/biome.jsonc", "**/*.js"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 4
}
}
1 change: 1 addition & 0 deletions e2e-tests/stdin-nested-config/donotformat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
let x = 10;
12 changes: 12 additions & 0 deletions e2e-tests/stdin-nested-config/subdirectory/biome.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"root": false,
"extends": "//",
"files": {
// This should be relative to the location of this config file, so we should not touch root/donotformat.ts
"includes": ["*.ts"]
},
"formatter": {
"indentStyle": "space",
"indentWidth": 2
}
}
5 changes: 5 additions & 0 deletions e2e-tests/stdin-nested-config/subdirectory/lib.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let y = 65;

function indent() {
return y;
}
5 changes: 5 additions & 0 deletions e2e-tests/stdin-nested-config/subdirectory/lib.js.formatted
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let y = 65;

function indent() {
return y;
}
5 changes: 5 additions & 0 deletions e2e-tests/stdin-nested-config/subdirectory/typed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let y = 65;

function indent() {
return y;
}
5 changes: 5 additions & 0 deletions e2e-tests/stdin-nested-config/subdirectory/typed.ts.formatted
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let y = 65;

function indent() {
return y;
}
28 changes: 28 additions & 0 deletions e2e-tests/stdin-nested-config/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -euo pipefail

TEMP=$(mktemp)
trap 'rm -f $TEMP' EXIT

biome() {
cargo run --bin biome -- "$@"
}

STATUS=0
diff_stdin_filepath() {
biome format --stdin-file-path="$1" < "$1" > "$TEMP"
if ! git diff --no-index "$1.formatted" "$TEMP"; then
STATUS=1
fi
}

diff_stdin_filepath app.js
diff_stdin_filepath subdirectory/lib.js
diff_stdin_filepath subdirectory/typed.ts

biome format --stdin-file-path="donotformat.ts" < "donotformat.ts" > "$TEMP"
if ! git diff --no-index "donotformat.ts" "$TEMP"; then
STATUS=1
fi

exit $STATUS
32 changes: 28 additions & 4 deletions e2e-tests/test-all.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
#!/bin/sh
#!/usr/bin/env bash

# Usage:
# ./test-all.sh
# ./test-all.sh stdin # to filter tests by name

set -eu

# Change to the script's directory
cd "$(dirname "$0")"

# Glob matcher
if [[ -z "${1:-}" ]]; then FILTER="*"; else FILTER="*$1*"; fi

redecho() {
echo -e "\033[1;31m$1\033[0m"
}

bail() {
redecho "Error: $1"
exit 1
}

for x in *; do
if test -d "$x"; then
# shellcheck disable=SC2053 # intentional glob match against $FILTER
if [[ "$x" != $FILTER ]]; then
echo "Skipping $x"
continue
fi
echo "Testing $x..."
cd "$x"
sh test.sh
cd ..
pushd "$x" > /dev/null
bash test.sh || bail "Test failed: $x. To re-run: $0 $x"
popd > /dev/null
fi
done
Loading