Skip to content

Commit

Permalink
feat(cli): add --only and --skip options (#2947)
Browse files Browse the repository at this point in the history
  • Loading branch information
Conaclos committed May 24, 2024
1 parent a49bd8d commit 49f6530
Show file tree
Hide file tree
Showing 43 changed files with 1,063 additions and 1,702 deletions.
37 changes: 17 additions & 20 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,36 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

#### New features

- Add a new option `--rule` to the command `biome lint` ([#58](https://github.com/biomejs/biome/issues/58)).
- Add two new options `--only` and `--skip` to the command `biome lint` ([#58](https://github.com/biomejs/biome/issues/58)).

This new option allows you to execute a single rule or a rule group.
This option is convenient to test a rule or apply the code fixes of a single rule.

For example, you can execute the `style/useNamingConvention` rule on the working directory:
The `--only` option allows you to run a given rule or rule group,
For example, the following command runs only the `style/useNamingConvention` and `style/noInferrableTypes` rules.
If the rule is disabled in the configuration, then its severity level is set to `error` for a recommended rule or `warn` otherwise.

```shell
biome lint --rule=style/useNamingConvention ./
biome lint --only=style/useNamingConvention --only=style/noInferrableTypes
```

If the rule has a code action (autofix), you can use `--apply` to apply the fix:
Passing a group does not change the severity level of the rules in the group.
All the disabled rules in the group will remain disabled.
To ensure that the group is run, the `recommended` field of the group is enabled.
The `nursery` group cannot be passed, as no rules are enabled by default in the nursery group.

The `--skip` option allows you to skip the execution of a given group or a given rule.
For example, the following command skips the `style` group and the `suspicious/noExplicitAny` rule.

```shell
biome lint --rule=style/useNamingConvention --apply ./
biome lint --skip=style --skip=suspicious/noExplicitAny
```

The option takes the rule options in the Biome configuration file into account.
Only, the severity level of the rule is overridden by its default value,
i.e. `error` for a recommended rule or `warn` otherwise.

You can also run a group of rules:
You can also use `--only` and `--skip` together. `--skip` oevrrides `--only`.
The following command executes only the rules from the `style` group, but the `style/useNamingConvention` rule.

```shell
biome lint --rule=suspicious src/main.js
biome lint --only=style --skip=style/useNamingConvention
```

In this case, the severity level of a rule is not overridden.
Thus, the disabled rules stay disabled.
To ensure that the group is run, the `recommended` field of the group is turned on.
The `nursery` group cannot be passed because no rules are enabled in the nursery group by default.

The option is compatible with other options such as `--apply`, `--apply-unsafe` and `--reporter`.
These options are compatible with other options such as `--write` (previously `--apply`), and `--reporter`.

Contributed by @Conaclos

Expand Down
46 changes: 22 additions & 24 deletions crates/biome_analyze/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ where
let line_index = *self.line_index + 1;

// If the last suppression was on the same or previous line, extend its
// range and set of supressed rules with the content for the new suppression
// range and set of suppressed rules with the content for the new suppression
if let Some(last_suppression) = self.line_suppressions.last_mut() {
if last_suppression.line_index == line_index
|| last_suppression.line_index + 1 == line_index
Expand Down Expand Up @@ -767,7 +767,7 @@ pub enum RuleFilter<'a> {
}

impl<'a> RuleFilter<'a> {
// Returns the group name of thie filter.
// Returns the group name of this filter.
pub fn group(self) -> &'a str {
match self {
RuleFilter::Group(group) => group,
Expand Down Expand Up @@ -822,14 +822,23 @@ pub struct AnalysisFilter<'a> {
/// Only allow rules with these categories to emit signals
pub categories: RuleCategories,
/// Only allow rules matching these names to emit signals
/// If `enabled_rules` is set to `None`, then all rules are enabled.
pub enabled_rules: Option<&'a [RuleFilter<'a>]>,
/// Do not allow rules matching these names to emit signals
pub disabled_rules: Option<&'a [RuleFilter<'a>]>,
pub disabled_rules: &'a [RuleFilter<'a>],
/// Only emit signals matching this text range
pub range: Option<TextRange>,
}

impl<'analysis> AnalysisFilter<'analysis> {
/// It creates a new filter with the set of [enabled rules](RuleFilter) passed as argument
pub fn from_enabled_rules(enabled_rules: &'analysis [RuleFilter<'analysis>]) -> Self {
Self {
enabled_rules: Some(enabled_rules),
..AnalysisFilter::default()
}
}

/// Return `true` if the category `C` matches this filter
pub fn match_category<C: GroupCategory>(&self) -> bool {
self.categories.contains(C::CATEGORY.into())
Expand All @@ -841,33 +850,22 @@ impl<'analysis> AnalysisFilter<'analysis> {
&& self.enabled_rules.map_or(true, |enabled_rules| {
enabled_rules.iter().any(|filter| filter.match_group::<G>())
})
&& self.disabled_rules.map_or(true, |disabled_rules| {
!disabled_rules
.iter()
.any(|filter| filter.match_group::<G>())
})
&& !self
.disabled_rules
.iter()
.any(|filter| matches!(filter, RuleFilter::Group(_)) && filter.match_group::<G>())
}

/// Return `true` if the rule `R` matches this filter
pub fn match_rule<R>(&self) -> bool
where
R: Rule,
{
self.match_group::<R::Group>()
pub fn match_rule<R: Rule>(&self) -> bool {
self.match_category::<<R::Group as RuleGroup>::Category>()
&& self.enabled_rules.map_or(true, |enabled_rules| {
enabled_rules.iter().any(|filter| filter.match_rule::<R>())
})
&& self.disabled_rules.map_or(true, |disabled_rules| {
!disabled_rules.iter().any(|filter| filter.match_rule::<R>())
})
}

/// It creates a new filter with the set of [enabled rules](RuleFilter) passed as argument
pub fn from_enabled_rules(enabled_rules: Option<&'analysis [RuleFilter<'analysis>]>) -> Self {
Self {
enabled_rules,
..AnalysisFilter::default()
}
&& !self
.disabled_rules
.iter()
.any(|filter| filter.match_rule::<R>())
}
}

Expand Down
9 changes: 6 additions & 3 deletions crates/biome_cli/src/commands/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ pub(crate) struct LintCommandPayload {
pub(crate) vcs_configuration: Option<PartialVcsConfiguration>,
pub(crate) files_configuration: Option<PartialFilesConfiguration>,
pub(crate) paths: Vec<OsString>,
pub(crate) rule: Option<RuleSelector>,
pub(crate) only: Vec<RuleSelector>,
pub(crate) skip: Vec<RuleSelector>,
pub(crate) stdin_file_path: Option<String>,
pub(crate) staged: bool,
pub(crate) changed: bool,
Expand All @@ -54,7 +55,8 @@ pub(crate) fn lint(session: CliSession, payload: LintCommandPayload) -> Result<(
cli_options,
mut linter_configuration,
mut paths,
rule,
only,
skip,
stdin_file_path,
vcs_configuration,
files_configuration,
Expand Down Expand Up @@ -161,7 +163,8 @@ pub(crate) fn lint(session: CliSession, payload: LintCommandPayload) -> Result<(
Execution::new(TraversalMode::Lint {
fix_file_mode,
stdin,
rule,
only,
skip,
})
.set_report(&cli_options),
session,
Expand Down
23 changes: 12 additions & 11 deletions crates/biome_cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,19 +193,20 @@ pub enum BiomeCommand {
#[bpaf(external, hide_usage)]
cli_options: CliOptions,

/// Run only the given rule or rule group.
/// 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.
///
/// The option overrides the Biome configuration file as follows:
///
/// - When a rule is passed, its severity level is set to `error' if it is a recommended rule, or `warn' otherwise.
///
/// - When a rule group is passed, the `recommended` flag is enabled, but if the `all` flag is enabled.
///
/// Example: `biome lint --rule=correctness/noUnusedVariables`
/// Example: `biome lint --only=correctness/noUnusedVariables --only=suspicious`
#[bpaf(long("only"), argument("GROUP|RULE"))]
only: Vec<RuleSelector>,

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

/// Use this option when you want to format code piped from `stdin`, and print the output to `stdout`.
///
Expand Down
12 changes: 7 additions & 5 deletions crates/biome_cli/src/execute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,13 @@ pub enum TraversalMode {
/// 1. The virtual path to the file
/// 2. The content of the file
stdin: Option<Stdin>,
/// Run only the given rule or rule group.
/// The option overrides the Biome configuration file as follows:
/// - When a rule is passed, its severity level is set to `error' if it is a recommended rule, or `warn' otherwise.
/// - When a rule group is passed, the `recommended` flag is enabled, but if the `all` flag is enabled.
rule: Option<RuleSelector>,
/// 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>,
/// 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>,
},
/// This mode is enabled when running the command `biome ci`
CI {
Expand Down
7 changes: 6 additions & 1 deletion crates/biome_cli/src/execute/process_file/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ pub(crate) fn format_with_guard<'ctx>(
debug!("Pulling diagnostics from parsed file");
let diagnostics_result = workspace_file
.guard()
.pull_diagnostics(RuleCategories::SYNTAX, max_diagnostics.into(), None)
.pull_diagnostics(
RuleCategories::SYNTAX,
max_diagnostics.into(),
Vec::new(),
Vec::new(),
)
.with_file_path_and_code(
workspace_file.path.display().to_string(),
category!("format"),
Expand Down
14 changes: 8 additions & 6 deletions crates/biome_cli/src/execute/process_file/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,19 @@ pub(crate) fn lint_with_guard<'ctx>(
}

let max_diagnostics = ctx.remaining_diagnostics.load(Ordering::Relaxed);
let rule = if let TraversalMode::Lint { rule, .. } = ctx.execution.traversal_mode() {
*rule
} else {
None
};
let (only, skip) =
if let TraversalMode::Lint { only, skip, .. } = ctx.execution.traversal_mode() {
(only.clone(), skip.clone())
} else {
(Vec::new(), Vec::new())
};
let pull_diagnostics_result = workspace_file
.guard()
.pull_diagnostics(
RuleCategories::LINT | RuleCategories::SYNTAX,
max_diagnostics.into(),
rule,
only,
skip,
)
.with_file_path_and_code(
workspace_file.path.display().to_string(),
Expand Down
9 changes: 5 additions & 4 deletions crates/biome_cli/src/execute/std_in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,18 @@ pub(crate) fn run<'a>(
}
}

let rule = if let TraversalMode::Lint { rule, .. } = mode.traversal_mode() {
*rule
let (only, skip) = if let TraversalMode::Lint { only, skip, .. } = mode.traversal_mode() {
(only.clone(), skip.clone())
} else {
None
(Vec::new(), Vec::new())
};
if !mode.is_check_apply_unsafe() {
let result = workspace.pull_diagnostics(PullDiagnosticsParams {
categories: RuleCategories::LINT | RuleCategories::SYNTAX,
path: biome_path.clone(),
max_diagnostics: mode.max_diagnostics.into(),
rule,
only,
skip,
})?;
diagnostics.extend(result.diagnostics);
}
Expand Down
6 changes: 4 additions & 2 deletions crates/biome_cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ impl<'app> CliSession<'app> {
cli_options,
linter_configuration,
paths,
rule,
only,
skip,
stdin_file_path,
vcs_configuration,
files_configuration,
Expand All @@ -145,7 +146,8 @@ impl<'app> CliSession<'app> {
cli_options,
linter_configuration,
paths,
rule,
only,
skip,
stdin_file_path,
vcs_configuration,
files_configuration,
Expand Down
Loading

0 comments on commit 49f6530

Please sign in to comment.