Skip to content
Closed
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
5 changes: 5 additions & 0 deletions .changeset/fix-stdin-file-path-includes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@biomejs/biome": patch
---

Fix `--stdin-file-path` being blocked by `includes` configuration. Stdin input now bypasses all path-based ignore checks (`files.includes`, `formatter.includes`, VCS ignore). The path is only used for language detection, since stdin content is explicitly provided by the user.
1 change: 1 addition & 0 deletions crates/biome_cli/src/execute/process_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ pub(crate) fn process_file(ctx: &TraversalOptions, biome_path: &BiomePath) -> Fi
project_key: ctx.project_key,
path: biome_path.clone(),
features: ctx.execution.to_feature(),
is_stdin: false,
})
.with_file_path_and_code_and_tags(
biome_path.to_string(),
Expand Down
2 changes: 2 additions & 0 deletions crates/biome_cli/src/execute/std_in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub(crate) fn run<'a>(
project_key,
path: biome_path.clone(),
features: FeaturesBuilder::new().with_formatter().build(),
is_stdin: true,
})?;

if file_features.is_ignored() {
Expand Down Expand Up @@ -126,6 +127,7 @@ pub(crate) fn run<'a>(
.with_assist()
.with_formatter()
.build(),
is_stdin: true,
})?;

if file_features.is_ignored() {
Expand Down
1 change: 1 addition & 0 deletions crates/biome_cli/src/execute/traverse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ impl TraversalContext for TraversalOptions<'_, '_> {
project_key: self.project_key,
path: biome_path.clone(),
features: self.execution.to_feature(),
is_stdin: false,
});

let can_read = DocumentFileSource::can_read(biome_path);
Expand Down
46 changes: 46 additions & 0 deletions crates/biome_cli/tests/commands/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,52 @@ fn format_stdin_does_not_error_with_ignore_unknown_file_extensions() {
));
}

#[test]
fn format_stdin_ignores_includes_pattern() {
let fs = MemoryFileSystem::default();
let mut console = BufferConsole::default();

// Set up a config with includes that doesn't match our stdin path
fs.insert(
Utf8Path::new("biome.json").into(),
r#"{ "formatter": { "includes": ["apps/**"] } }"#.as_bytes(),
);

// stdin path is "mock.js" which doesn't match "apps/**"
// But stdin should bypass includes check
console
.in_buffer
.push("function f() {return{}}".to_string());

let (fs, result) = run_cli(
fs,
&mut console,
Args::from(["format", "--stdin-file-path", "mock.js"].as_slice()),
);

assert!(result.is_ok(), "run_cli returned {result:?}");

let message = console
.out_buffer
.first()
.expect("Console should have written a message");

let content = markup_to_string(markup! {
{message.content}
});

// Verify the content was formatted despite not matching includes pattern
assert_eq!(content, "function f() {\n\treturn {};\n}\n");

assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"format_stdin_ignores_includes_pattern",
fs,
console,
result,
));
}

#[test]
fn does_not_format_if_disabled() {
let fs = MemoryFileSystem::default();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: redactor(content)
---
## `biome.json`

```json
{ "formatter": { "includes": ["apps/**"] } }
```

# Input messages

```block
function f() {return{}}
```

# Emitted Messages

```block
function f() {
return {};
}

```
1 change: 1 addition & 0 deletions crates/biome_formatter_test/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ impl<'a> SpecTestFile<'a> {
project_key,
path: input_file.clone(),
features: FeaturesBuilder::new().with_formatter().build(),
is_stdin: false,
})
.unwrap();

Expand Down
2 changes: 2 additions & 0 deletions crates/biome_lsp/src/handlers/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub(crate) fn code_actions(
project_key: doc.project_key,
path: path.clone(),
features,
is_stdin: false,
})?;

if !file_features.supports_lint() && !file_features.supports_assist() {
Expand Down Expand Up @@ -315,6 +316,7 @@ fn fix_all(
.with_linter()
.with_assist()
.build(),
is_stdin: false,
})?;
let should_format = file_features.supports_format();

Expand Down
3 changes: 3 additions & 0 deletions crates/biome_lsp/src/handlers/formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub(crate) fn format(
project_key: doc.project_key,
path: path.clone(),
features,
is_stdin: false,
})?;
if !file_features.supports_format() {
return notify_user(file_features, path);
Expand Down Expand Up @@ -107,6 +108,7 @@ pub(crate) fn format_range(
project_key: doc.project_key,
path: path.clone(),
features,
is_stdin: false,
})?;
if !file_features.supports_format() {
return notify_user(file_features, path);
Expand Down Expand Up @@ -199,6 +201,7 @@ pub(crate) fn format_on_type(
project_key: doc.project_key,
path: path.clone(),
features,
is_stdin: false,
})?;
if !file_features.supports_format() {
return notify_user(file_features, path);
Expand Down
1 change: 1 addition & 0 deletions crates/biome_lsp/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ impl Session {
project_key: doc.project_key,
features: FeaturesBuilder::new().with_linter().with_assist().build(),
path: biome_path.clone(),
is_stdin: false,
})?;

if !file_features.supports_lint() && !file_features.supports_assist() {
Expand Down
12 changes: 10 additions & 2 deletions crates/biome_service/src/projects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ impl Projects {
is_ignored_by_top_level_config || is_ignored_by_features
}

#[expect(clippy::too_many_arguments)]
#[inline(always)]
pub fn get_file_features(
&self,
Expand All @@ -207,6 +208,7 @@ impl Projects {
features: FeatureName,
language: DocumentFileSource,
capabilities: &Capabilities,
is_stdin: bool,
) -> Result<FileFeaturesResult, WorkspaceError> {
let data = self.0.pin();
let project_data = data
Expand All @@ -231,9 +233,15 @@ impl Projects {
.is_some_and(|dir_path| dir_path == project_data.path)
{
// Never ignore Biome's top-level config file
} else if self.is_ignored(fs, project_key, path, features, IgnoreKind::Ancestors) {
} else if !is_stdin
&& self.is_ignored(fs, project_key, path, features, IgnoreKind::Ancestors)
{
// Skip ignore checks for stdin - the path is only used for language detection,
// not for path matching. Stdin content is explicitly provided, so VCS ignore
// and includes patterns should not apply.
file_features.set_ignored_for_all_features();
} else {
} else if !is_stdin {
// Skip feature-specific includes check for stdin.
for feature in features.iter() {
if project_data
.root_settings
Expand Down
5 changes: 5 additions & 0 deletions crates/biome_service/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ pub struct SupportsFeatureParams {
pub project_key: ProjectKey,
pub path: BiomePath,
pub features: FeatureName,
/// When true, skip ignore and `includes` pattern checks. Used for stdin
/// input where the path is only used for language detection. Stdin content
/// is explicitly provided, so VCS ignore and includes patterns should not apply.
#[serde(default)]
pub is_stdin: bool,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, Default)]
Expand Down
1 change: 1 addition & 0 deletions crates/biome_service/src/workspace/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,7 @@ impl Workspace for WorkspaceServer {
params.features,
language,
&capabilities,
params.is_stdin,
)
}

Expand Down
6 changes: 6 additions & 0 deletions packages/@biomejs/backend-jsonrpc/src/workspace.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.