Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core): register syntax rules via visitor #3471

Merged
merged 1 commit into from
Jul 19, 2024
Merged
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
9 changes: 7 additions & 2 deletions crates/biome_service/src/file_handlers/css.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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};
Expand Down Expand Up @@ -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());

Expand All @@ -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()
Expand Down
9 changes: 7 additions & 2 deletions crates/biome_service/src/file_handlers/graphql.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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());

Expand Down Expand Up @@ -328,6 +329,10 @@ fn lint(params: LintParams) -> LintResults {
.map(|selector| selector.into())
.collect::<Vec<_>>();

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()),
Expand Down
13 changes: 5 additions & 8 deletions crates/biome_service/src/file_handlers/javascript.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion crates/biome_service/src/file_handlers/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()
Expand All @@ -359,6 +360,9 @@ fn lint(params: LintParams) -> LintResults {
.into_iter()
.collect::<Vec<_>>()
};
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()
Expand Down
97 changes: 92 additions & 5 deletions crates/biome_service/src/file_handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<RuleFilter<'a>>,
}

impl<'a> RegistryVisitor<JsLanguage> for SyntaxVisitor<'a> {
fn record_category<C: GroupCategory<Language = JsLanguage>>(&mut self) {
if C::CATEGORY == RuleCategory::Syntax {
C::record_groups(self)
}
}

fn record_rule<R>(&mut self)
where
R: Rule<Options: Default, Query: Queryable<Language = JsLanguage, Output: Clone>> + 'static,
{
self.enabled_rules.push(RuleFilter::Rule(
<R::Group as RuleGroup>::NAME,
R::METADATA.name,
))
}
}

impl<'a> RegistryVisitor<JsonLanguage> for SyntaxVisitor<'a> {
fn record_category<C: GroupCategory<Language = JsonLanguage>>(&mut self) {
if C::CATEGORY == RuleCategory::Syntax {
C::record_groups(self)
}
}

fn record_rule<R>(&mut self)
where
R: Rule<Options: Default, Query: Queryable<Language = JsonLanguage, Output: Clone>>
+ 'static,
{
self.enabled_rules.push(RuleFilter::Rule(
<R::Group as RuleGroup>::NAME,
R::METADATA.name,
))
}
}

impl<'a> RegistryVisitor<CssLanguage> for SyntaxVisitor<'a> {
fn record_category<C: GroupCategory<Language = CssLanguage>>(&mut self) {
if C::CATEGORY == RuleCategory::Syntax {
C::record_groups(self)
}
}

fn record_rule<R>(&mut self)
where
R: Rule<Options: Default, Query: Queryable<Language = CssLanguage, Output: Clone>>
+ 'static,
{
self.enabled_rules.push(RuleFilter::Rule(
<R::Group as RuleGroup>::NAME,
R::METADATA.name,
))
}
}

impl<'a> RegistryVisitor<GraphqlLanguage> for SyntaxVisitor<'a> {
fn record_category<C: GroupCategory<Language = GraphqlLanguage>>(&mut self) {
if C::CATEGORY == RuleCategory::Syntax {
C::record_groups(self)
}
}

fn record_rule<R>(&mut self)
where
R: Rule<Options: Default, Query: Queryable<Language = GraphqlLanguage, Output: Clone>>
+ 'static,
{
self.enabled_rules.push(RuleFilter::Rule(
<R::Group as RuleGroup>::NAME,
R::METADATA.name,
))
}
}

#[test]
fn test_vue_script_lang() {
const VUE_JS_SCRIPT_OPENING_TAG: &str = r#"<script>"#;
Expand Down