Skip to content

Commit

Permalink
refactor(analyzer): use enumflags2 (#3230)
Browse files Browse the repository at this point in the history
  • Loading branch information
ematipico authored Jun 18, 2024
1 parent f8786aa commit 42bc279
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 57 deletions.
3 changes: 1 addition & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion crates/biome_analyze/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ biome_deserialize = { workspace = true, optional = true }
biome_deserialize_macros = { workspace = true, optional = true }
biome_diagnostics = { workspace = true }
biome_rowan = { workspace = true }
bitflags = { workspace = true }
enumflags2 = { workspace = true }
rustc-hash = { workspace = true }
schemars = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"], optional = true }
Expand Down
106 changes: 87 additions & 19 deletions crates/biome_analyze/src/categories.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use enumflags2::{bitflags, BitFlags};
use std::borrow::Cow;

use bitflags::bitflags;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[cfg_attr(
feature = "serde",
Expand Down Expand Up @@ -172,13 +171,38 @@ pub enum SourceActionKind {
Other(Cow<'static, str>),
}

bitflags! {
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct RuleCategories: u8 {
const SYNTAX = 1 << RuleCategory::Syntax as u8;
const LINT = 1 << RuleCategory::Lint as u8;
const ACTION = 1 << RuleCategory::Action as u8;
const TRANSFORMATION = 1 << RuleCategory::Transformation as u8;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[bitflags]
#[repr(u8)]
pub(crate) enum Categories {
Syntax = 1 << RuleCategory::Syntax as u8,
Lint = 1 << RuleCategory::Lint as u8,
Action = 1 << RuleCategory::Action as u8,
Transformation = 1 << RuleCategory::Transformation as u8,
}

#[derive(Debug, Copy, Clone)]
/// The categories supported by the analyzer.
///
/// The default implementation of this type returns an instance with all the categories.
///
/// Use [RuleCategoriesBuilder] to generate the categories you want to query.
pub struct RuleCategories(BitFlags<Categories>);

impl RuleCategories {
pub fn empty() -> Self {
let empty: BitFlags<Categories> = BitFlags::empty();
Self(empty)
}

pub fn all() -> Self {
let empty: BitFlags<Categories> = BitFlags::all();
Self(empty)
}

/// Checks whether the current categories contain a specific [RuleCategories]
pub fn contains(&self, other: impl Into<RuleCategories>) -> bool {
self.0.contains(other.into().0)
}
}

Expand All @@ -190,17 +214,19 @@ impl Default for RuleCategories {

impl RuleCategories {
pub fn is_syntax(&self) -> bool {
*self == RuleCategories::SYNTAX
self.0.contains(Categories::Syntax)
}
}

impl From<RuleCategory> for RuleCategories {
fn from(input: RuleCategory) -> Self {
match input {
RuleCategory::Syntax => RuleCategories::SYNTAX,
RuleCategory::Lint => RuleCategories::LINT,
RuleCategory::Action => RuleCategories::ACTION,
RuleCategory::Transformation => RuleCategories::TRANSFORMATION,
RuleCategory::Syntax => RuleCategories(BitFlags::from_flag(Categories::Syntax)),
RuleCategory::Lint => RuleCategories(BitFlags::from_flag(Categories::Lint)),
RuleCategory::Action => RuleCategories(BitFlags::from_flag(Categories::Action)),
RuleCategory::Transformation => {
RuleCategories(BitFlags::from_flag(Categories::Transformation))
}
}
}
}
Expand All @@ -213,19 +239,19 @@ impl serde::Serialize for RuleCategories {
{
let mut flags = Vec::new();

if self.contains(Self::SYNTAX) {
if self.0.contains(Categories::Syntax) {
flags.push(RuleCategory::Syntax);
}

if self.contains(Self::LINT) {
if self.0.contains(Categories::Lint) {
flags.push(RuleCategory::Lint);
}

if self.contains(Self::ACTION) {
if self.0.contains(Categories::Action) {
flags.push(RuleCategory::Action);
}

if self.contains(Self::TRANSFORMATION) {
if self.0.contains(Categories::Transformation) {
flags.push(RuleCategory::Transformation);
}

Expand Down Expand Up @@ -258,7 +284,7 @@ impl<'de> serde::Deserialize<'de> for RuleCategories {
let mut result = RuleCategories::empty();

while let Some(item) = seq.next_element::<RuleCategory>()? {
result |= RuleCategories::from(item);
result.0 |= RuleCategories::from(item).0;
}

Ok(result)
Expand All @@ -279,3 +305,45 @@ impl schemars::JsonSchema for RuleCategories {
<Vec<RuleCategory>>::json_schema(gen)
}
}

#[derive(Debug, Default)]
/// A convenient type create a [RuleCategories] type
///
/// ```
/// use biome_analyze::{RuleCategoriesBuilder, RuleCategory};
/// let mut categories = RuleCategoriesBuilder::default().with_syntax().with_lint().build();
///
/// assert!(categories.contains(RuleCategory::Lint));
/// assert!(categories.contains(RuleCategory::Syntax));
/// assert!(!categories.contains(RuleCategory::Action));
/// assert!(!categories.contains(RuleCategory::Transformation));
/// ```
pub struct RuleCategoriesBuilder {
flags: BitFlags<Categories>,
}

impl RuleCategoriesBuilder {
pub fn with_syntax(mut self) -> Self {
self.flags.insert(Categories::Syntax);
self
}

pub fn with_lint(mut self) -> Self {
self.flags.insert(Categories::Lint);
self
}

pub fn with_action(mut self) -> Self {
self.flags.insert(Categories::Action);
self
}

pub fn with_transformation(mut self) -> Self {
self.flags.insert(Categories::Transformation);
self
}

pub fn build(self) -> RuleCategories {
RuleCategories(self.flags)
}
}
5 changes: 3 additions & 2 deletions crates/biome_analyze/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ mod visitor;
pub use biome_diagnostics::category_concat;

pub use crate::categories::{
ActionCategory, RefactorKind, RuleCategories, RuleCategory, SourceActionKind,
ActionCategory, RefactorKind, RuleCategories, RuleCategoriesBuilder, RuleCategory,
SourceActionKind,
};
pub use crate::diagnostics::AnalyzerDiagnostic;
pub use crate::diagnostics::SuppressionDiagnostic;
Expand Down Expand Up @@ -885,7 +886,7 @@ impl<'analysis> AnalysisFilter<'analysis> {

/// Return `true` if the category `C` matches this filter
pub fn match_category<C: GroupCategory>(&self) -> bool {
self.categories.contains(C::CATEGORY.into())
self.categories.contains(C::CATEGORY)
}

/// Return `true` if the group `G` matches this filter
Expand Down
4 changes: 2 additions & 2 deletions crates/biome_cli/src/execute/process_file/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use crate::execute::process_file::{
DiffKind, FileResult, FileStatus, Message, SharedTraversalOptions,
};
use crate::execute::TraversalMode;
use biome_analyze::RuleCategoriesBuilder;
use biome_diagnostics::{category, Diagnostic, DiagnosticExt, Error, Severity};
use biome_service::file_handlers::{AstroFileHandler, SvelteFileHandler, VueFileHandler};
use biome_service::workspace::RuleCategories;
use std::path::Path;
use std::sync::atomic::Ordering;
use tracing::debug;
Expand All @@ -27,7 +27,7 @@ pub(crate) fn format_with_guard<'ctx>(
let diagnostics_result = workspace_file
.guard()
.pull_diagnostics(
RuleCategories::SYNTAX,
RuleCategoriesBuilder::default().with_syntax().build(),
max_diagnostics.into(),
Vec::new(),
Vec::new(),
Expand Down
7 changes: 5 additions & 2 deletions crates/biome_cli/src/execute/process_file/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use crate::execute::diagnostics::ResultExt;
use crate::execute::process_file::workspace_file::WorkspaceFile;
use crate::execute::process_file::{FileResult, FileStatus, Message, SharedTraversalOptions};
use crate::TraversalMode;
use biome_analyze::RuleCategoriesBuilder;
use biome_diagnostics::{category, Error};
use biome_service::file_handlers::{AstroFileHandler, SvelteFileHandler, VueFileHandler};
use biome_service::workspace::RuleCategories;
use std::path::Path;
use std::sync::atomic::Ordering;

Expand Down Expand Up @@ -66,7 +66,10 @@ pub(crate) fn lint_with_guard<'ctx>(
let pull_diagnostics_result = workspace_file
.guard()
.pull_diagnostics(
RuleCategories::LINT | RuleCategories::SYNTAX,
RuleCategoriesBuilder::default()
.with_syntax()
.with_lint()
.build(),
max_diagnostics.into(),
only,
skip,
Expand Down
9 changes: 6 additions & 3 deletions crates/biome_cli/src/execute/std_in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
use crate::execute::diagnostics::{ContentDiffAdvice, FormatDiffDiagnostic};
use crate::execute::Execution;
use crate::{CliDiagnostic, CliSession, TraversalMode};
use biome_analyze::RuleCategoriesBuilder;
use biome_console::{markup, ConsoleExt};
use biome_diagnostics::PrintDiagnostic;
use biome_diagnostics::{Diagnostic, DiagnosticExt, Error};
use biome_fs::BiomePath;
use biome_service::file_handlers::{AstroFileHandler, SvelteFileHandler, VueFileHandler};
use biome_service::workspace::{
ChangeFileParams, DropPatternParams, FeaturesBuilder, FixFileParams, FormatFileParams,
OpenFileParams, OrganizeImportsParams, PullDiagnosticsParams, RuleCategories,
SupportsFeatureParams,
OpenFileParams, OrganizeImportsParams, PullDiagnosticsParams, SupportsFeatureParams,
};
use biome_service::WorkspaceError;
use std::borrow::Cow;
Expand Down Expand Up @@ -163,7 +163,10 @@ pub(crate) fn run<'a>(
};
if !mode.is_check_apply_unsafe() {
let result = workspace.pull_diagnostics(PullDiagnosticsParams {
categories: RuleCategories::LINT | RuleCategories::SYNTAX,
categories: RuleCategoriesBuilder::default()
.with_lint()
.with_syntax()
.build(),
path: biome_path.clone(),
max_diagnostics: mode.max_diagnostics.into(),
only,
Expand Down
1 change: 0 additions & 1 deletion crates/biome_grit_parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ biome_grit_factory = { workspace = true }
biome_grit_syntax = { workspace = true }
biome_parser = { workspace = true }
biome_rowan = { workspace = true }
bitflags = { workspace = true }
schemars = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
Expand Down
4 changes: 2 additions & 2 deletions crates/biome_js_analyze/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ impl Error for RuleError {}
#[cfg(test)]
mod tests {
use biome_analyze::options::RuleOptions;
use biome_analyze::{AnalyzerOptions, Never, RuleCategories, RuleFilter, RuleKey};
use biome_analyze::{AnalyzerOptions, Never, RuleCategoriesBuilder, RuleFilter, RuleKey};
use biome_console::fmt::{Formatter, Termcolor};
use biome_console::{markup, Markup};
use biome_diagnostics::category;
Expand Down Expand Up @@ -451,7 +451,7 @@ mod tests {
);

let filter = AnalysisFilter {
categories: RuleCategories::SYNTAX,
categories: RuleCategoriesBuilder::default().with_syntax().build(),
..AnalysisFilter::default()
};

Expand Down
6 changes: 4 additions & 2 deletions crates/biome_js_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub(crate) type JsBatchMutation = BatchMutation<JsLanguage>;

#[cfg(test)]
mod tests {
use biome_analyze::{AnalyzerOptions, Never, RuleCategories, RuleFilter};
use biome_analyze::{AnalyzerOptions, Never, RuleCategoriesBuilder, RuleFilter};
use biome_js_parser::{parse, JsParserOptions};
use biome_js_syntax::JsFileSource;
use std::slice;
Expand All @@ -140,7 +140,9 @@ mod tests {
transform(
&parsed.tree(),
AnalysisFilter {
categories: RuleCategories::TRANSFORMATION,
categories: RuleCategoriesBuilder::default()
.with_transformation()
.build(),
enabled_rules: Some(slice::from_ref(&rule_filter)),
..AnalysisFilter::default()
},
Expand Down
10 changes: 5 additions & 5 deletions crates/biome_lsp/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::extension_settings::ExtensionSettings;
use crate::extension_settings::CONFIGURATION_SECTION;
use crate::utils;
use anyhow::Result;
use biome_analyze::RuleCategories;
use biome_analyze::RuleCategoriesBuilder;
use biome_configuration::ConfigurationPathHint;
use biome_console::markup;
use biome_diagnostics::PrintDescription;
Expand Down Expand Up @@ -316,18 +316,18 @@ impl Session {
})?;

let diagnostics: Vec<Diagnostic> = {
let mut categories = RuleCategories::SYNTAX;
let mut categories = RuleCategoriesBuilder::default().with_syntax();
if self.configuration_status().is_loaded() {
if file_features.supports_lint() {
categories |= RuleCategories::LINT
categories = categories.with_lint();
}
if file_features.supports_organize_imports() {
categories |= RuleCategories::ACTION
categories = categories.with_action();
}
}
let result = self.workspace.pull_diagnostics(PullDiagnosticsParams {
path: biome_path.clone(),
categories,
categories: categories.build(),
max_diagnostics: u64::MAX,
only: Vec::new(),
skip: Vec::new(),
Expand Down
10 changes: 6 additions & 4 deletions crates/biome_service/src/file_handlers/css.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use crate::workspace::{
use crate::WorkspaceError;
use biome_analyze::options::PreferredQuote;
use biome_analyze::{
AnalysisFilter, AnalyzerConfiguration, AnalyzerOptions, ControlFlow, Never, RuleCategories,
AnalysisFilter, AnalyzerConfiguration, AnalyzerOptions, ControlFlow, Never,
RuleCategoriesBuilder, RuleCategory,
};
use biome_css_analyze::analyze;
use biome_css_formatter::context::CssFormatOptions;
Expand Down Expand Up @@ -386,7 +387,7 @@ fn lint(params: LintParams) -> LintResults {
// - it is a syntax-only analyzer pass, or
// - if a single rule is run.
let ignores_suppression_comment =
!filter.categories.contains(RuleCategories::LINT) || has_only_filter;
!filter.categories.contains(RuleCategory::Lint) || has_only_filter;

let mut diagnostic_count = diagnostics.len() as u32;
let mut errors = diagnostics
Expand Down Expand Up @@ -488,10 +489,11 @@ pub(crate) fn code_actions(params: CodeActionsParams) -> PullActionsResult {

let mut filter = AnalysisFilter::from_enabled_rules(filter.as_slice());

filter.categories = RuleCategories::SYNTAX | RuleCategories::LINT;
let mut categories = RuleCategoriesBuilder::default().with_syntax().with_lint();
if settings.organize_imports.enabled {
filter.categories |= RuleCategories::ACTION;
categories = categories.with_action();
}
filter.categories = categories.build();
filter.range = Some(range);

let analyzer_options = workspace.analyzer_options::<CssLanguage>(path, &language);
Expand Down
Loading

0 comments on commit 42bc279

Please sign in to comment.