Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
19 changes: 19 additions & 0 deletions .changeset/wet-results-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
"@biomejs/biome": minor
---

Added new capabilities to the CLI arguments `--skip` and `--only`, available to the `biome lint` command.

`--skip` and `--only` can now accept domain names; when provided, Biome will run or skip all the rules that belong to a certain domain.

For example, the following command will only run the rules that belong to the [next](https://biomejs.dev/linter/domains/#next) domain:

```shell
biome lint --only=next
```

Another example, the following command will skip the rules that belong to the [project](https://biomejs.dev/linter/domains/#project) domain:

```shell
biome lint --skip=project
```
33 changes: 33 additions & 0 deletions crates/biome_analyze/src/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use biome_rowan::{AstNode, BatchMutation, BatchMutationExt, Language, TextRange}
use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::str::FromStr;

#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
Expand Down Expand Up @@ -512,6 +513,38 @@ impl RuleDomain {
Self::Tailwind => &[],
}
}

pub const fn as_str(&self) -> &'static str {
match self {
Self::React => "react",
Self::Test => "test",
Self::Solid => "solid",
Self::Next => "next",
Self::Qwik => "qwik",
Self::Vue => "vue",
Self::Project => "project",
Self::Tailwind => "tailwind",
}
}
}

impl FromStr for RuleDomain {
type Err = &'static str;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"react" => Ok(Self::React),
"test" => Ok(Self::Test),
"solid" => Ok(Self::Solid),
"next" => Ok(Self::Next),
"qwik" => Ok(Self::Qwik),
"vue" => Ok(Self::Vue),
"project" => Ok(Self::Project),
"tailwind" => Ok(Self::Tailwind),

_ => Err("Invalid rule domain"),
}
}
}

impl RuleMetadata {
Expand Down
6 changes: 3 additions & 3 deletions crates/biome_cli/src/commands/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{FixFileModeOptions, determine_fix_file_mode};
use crate::cli_options::CliOptions;
use crate::commands::{CommandRunner, get_files_to_process_with_cli_options};
use crate::{CliDiagnostic, Execution, TraversalMode};
use biome_configuration::analyzer::RuleSelector;
use biome_configuration::analyzer::AnalyzerSelector;
use biome_configuration::css::CssLinterConfiguration;
use biome_configuration::graphql::GraphqlLinterConfiguration;
use biome_configuration::javascript::JsLinterConfiguration;
Expand All @@ -26,8 +26,8 @@ pub(crate) struct LintCommandPayload {
pub(crate) vcs_configuration: Option<VcsConfiguration>,
pub(crate) files_configuration: Option<FilesConfiguration>,
pub(crate) paths: Vec<OsString>,
pub(crate) only: Vec<RuleSelector>,
pub(crate) skip: Vec<RuleSelector>,
pub(crate) only: Vec<AnalyzerSelector>,
pub(crate) skip: Vec<AnalyzerSelector>,
pub(crate) stdin_file_path: Option<String>,
pub(crate) staged: bool,
pub(crate) changed: bool,
Expand Down
26 changes: 17 additions & 9 deletions crates/biome_cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
setup_cli_subscriber,
};
use biome_configuration::analyzer::assist::AssistEnabled;
use biome_configuration::analyzer::{LinterEnabled, RuleSelector};
use biome_configuration::analyzer::{AnalyzerSelector, LinterEnabled};
use biome_configuration::css::{CssFormatterConfiguration, CssLinterConfiguration};
use biome_configuration::formatter::FormatterEnabled;
use biome_configuration::graphql::{GraphqlFormatterConfiguration, GraphqlLinterConfiguration};
Expand Down Expand Up @@ -233,20 +233,28 @@ pub enum BiomeCommand {
#[bpaf(external, hide_usage)]
cli_options: CliOptions,

/// Run only the given rule or group of rules.
/// Run only the given rule, group of rules or domain.
/// If the severity level of a rule is `off`,
/// then the severity level of the rule is set to `error` if it is a recommended rule or `warn` otherwise.
///
/// Example: `biome lint --only=correctness/noUnusedVariables --only=suspicious`
#[bpaf(long("only"), argument("GROUP|RULE"))]
only: Vec<RuleSelector>,
/// Example:
///
/// ```shell
/// biome lint --only=correctness/noUnusedVariables --only=suspicious --only=test
/// ```
#[bpaf(long("only"), argument("GROUP|RULE|DOMAIN"))]
only: Vec<AnalyzerSelector>,

/// Skip the given rule or group of rules by setting the severity level of the rules to `off`.
/// Skip the given rule, group of rules or domain by setting the severity level of the rules to `off`.
/// This option takes precedence over `--only`.
///
/// Example: `biome lint --skip=correctness/noUnusedVariables --skip=suspicious`
#[bpaf(long("skip"), argument("GROUP|RULE"))]
skip: Vec<RuleSelector>,
/// Example:
///
/// ```shell
/// biome lint --skip=correctness/noUnusedVariables --skip=suspicious --skip=project
/// ```
#[bpaf(long("skip"), argument("GROUP|RULE|DOMAIN"))]
skip: Vec<AnalyzerSelector>,

/// Use this option when you want to format code piped from `stdin`, and print the output to `stdout`.
///
Expand Down
5 changes: 3 additions & 2 deletions crates/biome_cli/src/commands/scan_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,16 @@ pub(crate) fn derive_best_scan_kind(
mod tests {
use super::*;
use crate::{TraversalMode, VcsTargeted};
use biome_configuration::{LinterConfiguration, analyzer::RuleSelector};
use biome_configuration::LinterConfiguration;
use biome_configuration::analyzer::RuleSelector;

#[test]
fn should_return_none_for_lint_command() {
let execution = Execution::new(TraversalMode::Lint {
fix_file_mode: None,
stdin: None,
only: vec![],
skip: vec![RuleSelector::Rule("correctness", "noPrivateImports")],
skip: vec![RuleSelector::Rule("correctness", "noPrivateImports").into()],

vcs_targeted: VcsTargeted::default(),
suppress: false,
Expand Down
6 changes: 3 additions & 3 deletions crates/biome_cli/src/execute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::reporter::terminal::{ConsoleReporter, ConsoleReporterVisitor};
use crate::{
CliDiagnostic, CliSession, DiagnosticsPayload, Reporter, TEMPORARY_INTERNAL_REPORTER_FILE,
};
use biome_configuration::analyzer::RuleSelector;
use biome_configuration::analyzer::AnalyzerSelector;
use biome_console::{ConsoleExt, markup};
use biome_diagnostics::{Category, category};
use biome_diagnostics::{Resource, SerdeJsonError};
Expand Down Expand Up @@ -126,10 +126,10 @@ pub enum TraversalMode {
/// Run only the given rule or group of rules.
/// If the severity level of a rule is `off`,
/// then the severity level of the rule is set to `error` if it is a recommended rule or `warn` otherwise.
only: Vec<RuleSelector>,
only: Vec<AnalyzerSelector>,
/// Skip the given rule or group of rules by setting the severity level of the rules to `off`.
/// This option takes precedence over `--only`.
skip: Vec<RuleSelector>,
skip: Vec<AnalyzerSelector>,
/// A flag to know vcs integrated options such as `--staged` or `--changed` are enabled
vcs_targeted: VcsTargeted,
/// Suppress existing diagnostics with a `// biome-ignore` comment
Expand Down
98 changes: 98 additions & 0 deletions crates/biome_cli/tests/cases/linter_domains.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,3 +355,101 @@ describe("foo", () => {
result,
));
}

#[test]
fn should_enable_domain_via_cli() {
let mut console = BufferConsole::default();
let fs = MemoryFileSystem::default();
let config = Utf8Path::new("biome.json");
fs.insert(
config.into(),
r#"{
"linter": {
"rules": {
"recommended": false
},
"domains": {
"test": "all"
}
}
}
"#
.as_bytes(),
);
let test1 = Utf8Path::new("test1.js");
fs.insert(
test1.into(),
r#"describe.only("bar", () => {});
"#
.as_bytes(),
);

let content = r#"
describe("foo", () => {
beforeEach(() => {});
beforeEach(() => {});
test("bar", () => {
someFn();
});
});
"#;
let test2 = Utf8Path::new("test2.js");
fs.insert(test2.into(), content.as_bytes());

let (fs, result) = run_cli(
fs,
&mut console,
Args::from(["lint", "--only=test", test1.as_str(), test2.as_str()].as_slice()),
);

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

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

#[test]
fn should_disable_domain_via_cli() {
let mut console = BufferConsole::default();
let fs = MemoryFileSystem::default();
let test1 = Utf8Path::new("test1.js");
fs.insert(
test1.into(),
r#"describe.only("bar", () => {});
"#
.as_bytes(),
);

let content = r#"
describe("foo", () => {
beforeEach(() => {});
beforeEach(() => {});
test("bar", () => {
someFn();
});
});
"#;
let test2 = Utf8Path::new("test2.js");
fs.insert(test2.into(), content.as_bytes());

let (fs, result) = run_cli(
fs,
&mut console,
Args::from(["lint", "--skip=test", test1.as_str(), test2.as_str()].as_slice()),
);

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

assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"should_disable_domain_via_cli",
fs,
console,
result,
));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: redactor(content)
---
## `test1.js`

```js
describe.only("bar", () => {});

```

## `test2.js`

```js

describe("foo", () => {
beforeEach(() => {});
beforeEach(() => {});
test("bar", () => {
someFn();
});
});

```

# Emitted Messages

```block
Checked 2 files in <TIME>. No fixes applied.
```
Loading
Loading