From 5bf9db4d168bce506a7baedcffb8b28da1021464 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 19 Jul 2024 10:29:37 +0100 Subject: [PATCH] refactor(core): register syntax rules via visitor --- crates/biome_service/src/file_handlers/css.rs | 9 +- .../src/file_handlers/graphql.rs | 9 +- .../src/file_handlers/javascript.rs | 13 +-- .../biome_service/src/file_handlers/json.rs | 6 +- crates/biome_service/src/file_handlers/mod.rs | 97 ++++++++++++++++++- 5 files changed, 116 insertions(+), 18 deletions(-) diff --git a/crates/biome_service/src/file_handlers/css.rs b/crates/biome_service/src/file_handlers/css.rs index 4a8561e52622..21abbf24c4bd 100644 --- a/crates/biome_service/src/file_handlers/css.rs +++ b/crates/biome_service/src/file_handlers/css.rs @@ -1,6 +1,6 @@ use super::{ is_diagnostic_error, CodeActionsParams, ExtensionHandler, FixAllParams, LintParams, - LintResults, ParseResult, SearchCapabilities, + LintResults, ParseResult, SearchCapabilities, SyntaxVisitor, }; use crate::configuration::to_analyzer_rules; use crate::file_handlers::DebugCapabilities; @@ -31,6 +31,7 @@ use biome_formatter::{ FormatError, IndentStyle, IndentWidth, LineEnding, LineWidth, Printed, QuoteStyle, }; use biome_fs::BiomePath; +use biome_js_analyze::visit_registry; use biome_parser::AnyParse; use biome_rowan::{AstNode, NodeCache}; use biome_rowan::{TextRange, TextSize, TokenAtOffset}; @@ -342,7 +343,7 @@ fn lint(params: LintParams) -> LintResults { let has_only_filter = !params.only.is_empty(); let mut rules = None; - let enabled_rules = if let Some(settings) = params.workspace.settings() { + let mut enabled_rules = if let Some(settings) = params.workspace.settings() { // Compute final rules (taking `overrides` into account) rules = settings.as_rules(params.path.as_path()); @@ -364,6 +365,10 @@ fn lint(params: LintParams) -> LintResults { vec![] }; + let mut syntax_visitor = SyntaxVisitor::default(); + visit_registry(&mut syntax_visitor); + enabled_rules.extend(syntax_visitor.enabled_rules); + let disabled_rules = params .skip .into_iter() diff --git a/crates/biome_service/src/file_handlers/graphql.rs b/crates/biome_service/src/file_handlers/graphql.rs index 358403fff43b..8a01b9fc605b 100644 --- a/crates/biome_service/src/file_handlers/graphql.rs +++ b/crates/biome_service/src/file_handlers/graphql.rs @@ -1,6 +1,6 @@ use super::{ is_diagnostic_error, CodeActionsParams, DocumentFileSource, ExtensionHandler, FixAllParams, - LintParams, LintResults, ParseResult, SearchCapabilities, + LintParams, LintResults, ParseResult, SearchCapabilities, SyntaxVisitor, }; use crate::file_handlers::DebugCapabilities; use crate::file_handlers::{ @@ -29,6 +29,7 @@ use biome_graphql_formatter::context::GraphqlFormatOptions; use biome_graphql_formatter::format_node; use biome_graphql_parser::parse_graphql_with_cache; use biome_graphql_syntax::{GraphqlLanguage, GraphqlRoot, GraphqlSyntaxNode, TextRange, TextSize}; +use biome_js_analyze::visit_registry; use biome_parser::AnyParse; use biome_rowan::{AstNode, NodeCache, TokenAtOffset}; use std::borrow::Cow; @@ -300,7 +301,7 @@ fn lint(params: LintParams) -> LintResults { let has_only_filter = !params.only.is_empty(); let mut rules = None; - let enabled_rules = if let Some(settings) = params.workspace.settings() { + let mut enabled_rules = if let Some(settings) = params.workspace.settings() { // Compute final rules (taking `overrides` into account) rules = settings.as_rules(params.path.as_path()); @@ -328,6 +329,10 @@ fn lint(params: LintParams) -> LintResults { .map(|selector| selector.into()) .collect::>(); + let mut syntax_visitor = SyntaxVisitor::default(); + visit_registry(&mut syntax_visitor); + enabled_rules.extend(syntax_visitor.enabled_rules); + let filter = AnalysisFilter { categories: params.categories, enabled_rules: Some(enabled_rules.as_slice()), diff --git a/crates/biome_service/src/file_handlers/javascript.rs b/crates/biome_service/src/file_handlers/javascript.rs index fbf78334023e..740b6712c19a 100644 --- a/crates/biome_service/src/file_handlers/javascript.rs +++ b/crates/biome_service/src/file_handlers/javascript.rs @@ -1,7 +1,7 @@ use super::{ search, AnalyzerCapabilities, CodeActionsParams, DebugCapabilities, ExtensionHandler, FormatterCapabilities, LintParams, LintResults, ParseResult, ParserCapabilities, - SearchCapabilities, + SearchCapabilities, SyntaxVisitor, }; use crate::configuration::to_analyzer_rules; use crate::diagnostics::extension_error; @@ -446,13 +446,10 @@ pub(crate) fn lint(params: LintParams) -> LintResults { if organize_imports_enabled && !params.categories.is_syntax() { rule_filter_list.push(RuleFilter::Rule("correctness", "organizeImports")); } - rule_filter_list.push(RuleFilter::Rule( - "correctness", - "noDuplicatePrivateClassMembers", - )); - rule_filter_list.push(RuleFilter::Rule("correctness", "noInitializerWithDefinite")); - rule_filter_list.push(RuleFilter::Rule("correctness", "noSuperWithoutExtends")); - rule_filter_list.push(RuleFilter::Rule("nursery", "noSuperWithoutExtends")); + let mut syntax_visitor = SyntaxVisitor::default(); + visit_registry(&mut syntax_visitor); + rule_filter_list.extend(syntax_visitor.enabled_rules); + rule_filter_list }; let disabled_rules = params diff --git a/crates/biome_service/src/file_handlers/json.rs b/crates/biome_service/src/file_handlers/json.rs index a128476e92da..07bf6afa860e 100644 --- a/crates/biome_service/src/file_handlers/json.rs +++ b/crates/biome_service/src/file_handlers/json.rs @@ -3,6 +3,7 @@ use std::ffi::OsStr; use super::{ CodeActionsParams, DocumentFileSource, ExtensionHandler, ParseResult, SearchCapabilities, + SyntaxVisitor, }; use crate::configuration::to_analyzer_rules; use crate::file_handlers::DebugCapabilities; @@ -345,7 +346,7 @@ fn lint(params: LintParams) -> LintResults { } let has_only_filter = !params.only.is_empty(); - let enabled_rules = if has_only_filter { + let mut enabled_rules = if has_only_filter { params .only .into_iter() @@ -359,6 +360,9 @@ fn lint(params: LintParams) -> LintResults { .into_iter() .collect::>() }; + let mut syntax_visitor = SyntaxVisitor::default(); + biome_js_analyze::visit_registry(&mut syntax_visitor); + enabled_rules.extend(syntax_visitor.enabled_rules); let disabled_rules = params .skip .into_iter() diff --git a/crates/biome_service/src/file_handlers/mod.rs b/crates/biome_service/src/file_handlers/mod.rs index 720fd701aee4..9500d6a8bed2 100644 --- a/crates/biome_service/src/file_handlers/mod.rs +++ b/crates/biome_service/src/file_handlers/mod.rs @@ -14,20 +14,23 @@ use crate::{ workspace::{FixFileResult, GetSyntaxTreeResult, PullActionsResult, RenameResult}, WorkspaceError, }; -use biome_analyze::{AnalyzerDiagnostic, RuleCategories}; +use biome_analyze::{ + AnalyzerDiagnostic, GroupCategory, Queryable, RegistryVisitor, Rule, RuleCategories, + RuleCategory, RuleFilter, RuleGroup, +}; use biome_configuration::linter::RuleSelector; use biome_configuration::Rules; use biome_console::fmt::Formatter; use biome_console::markup; -use biome_css_syntax::CssFileSource; +use biome_css_syntax::{CssFileSource, CssLanguage}; use biome_diagnostics::{Diagnostic, Severity}; use biome_formatter::Printed; use biome_fs::BiomePath; -use biome_graphql_syntax::GraphqlFileSource; +use biome_graphql_syntax::{GraphqlFileSource, GraphqlLanguage}; use biome_grit_patterns::{GritQuery, GritQueryResult, GritTargetFile}; use biome_js_parser::{parse, JsParserOptions}; -use biome_js_syntax::{EmbeddingKind, JsFileSource, Language, TextRange, TextSize}; -use biome_json_syntax::JsonFileSource; +use biome_js_syntax::{EmbeddingKind, JsFileSource, JsLanguage, Language, TextRange, TextSize}; +use biome_json_syntax::{JsonFileSource, JsonLanguage}; use biome_parser::AnyParse; use biome_project::PackageJson; use biome_rowan::{FileSourceError, NodeCache}; @@ -644,6 +647,90 @@ fn test_svelte_script_lang() { ); } +/// Type meant to register all the syntax rules for each language supported by Biome +/// +/// When a new language is introduced, it must be implemented it. Syntax rules aren't negotiable via configuration, so it's safe +/// to pull all of them. +#[derive(Default, Debug)] +pub(crate) struct SyntaxVisitor<'a> { + pub(crate) enabled_rules: Vec>, +} + +impl<'a> RegistryVisitor for SyntaxVisitor<'a> { + fn record_category>(&mut self) { + if C::CATEGORY == RuleCategory::Syntax { + C::record_groups(self) + } + } + + fn record_rule(&mut self) + where + R: Rule> + 'static, + { + self.enabled_rules.push(RuleFilter::Rule( + ::NAME, + R::METADATA.name, + )) + } +} + +impl<'a> RegistryVisitor for SyntaxVisitor<'a> { + fn record_category>(&mut self) { + if C::CATEGORY == RuleCategory::Syntax { + C::record_groups(self) + } + } + + fn record_rule(&mut self) + where + R: Rule> + + 'static, + { + self.enabled_rules.push(RuleFilter::Rule( + ::NAME, + R::METADATA.name, + )) + } +} + +impl<'a> RegistryVisitor for SyntaxVisitor<'a> { + fn record_category>(&mut self) { + if C::CATEGORY == RuleCategory::Syntax { + C::record_groups(self) + } + } + + fn record_rule(&mut self) + where + R: Rule> + + 'static, + { + self.enabled_rules.push(RuleFilter::Rule( + ::NAME, + R::METADATA.name, + )) + } +} + +impl<'a> RegistryVisitor for SyntaxVisitor<'a> { + fn record_category>(&mut self) { + if C::CATEGORY == RuleCategory::Syntax { + C::record_groups(self) + } + } + + fn record_rule(&mut self) + where + R: Rule> + + 'static, + { + self.enabled_rules.push(RuleFilter::Rule( + ::NAME, + R::METADATA.name, + )) + } +} + #[test] fn test_vue_script_lang() { const VUE_JS_SCRIPT_OPENING_TAG: &str = r#"