From b4597e02e88a3384841c1665b01cb95f4397bb91 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Mon, 18 Jul 2022 12:37:11 +0100 Subject: [PATCH 1/3] feat(rome_service): auto generate configuration for rules --- CONTRIBUTING.md | 1 + Cargo.lock | 27 ++-- crates/rome_cli/src/traversal.rs | 2 +- crates/rome_cli/tests/configs.rs | 24 +++- crates/rome_cli/tests/main.rs | 27 +++- .../rome_service/src/configuration/linter.rs | 23 ---- .../src/configuration/linter/mod.rs | 42 ++++++ .../src/configuration/linter/rules.rs | 106 +++++++++++++++ crates/rome_service/src/configuration/mod.rs | 5 +- crates/rome_service/src/lib.rs | 2 +- crates/rome_service/src/settings.rs | 23 +++- xtask/codegen/Cargo.toml | 3 + xtask/codegen/src/generate_configuration.rs | 121 ++++++++++++++++++ xtask/codegen/src/main.rs | 9 +- 14 files changed, 370 insertions(+), 45 deletions(-) delete mode 100644 crates/rome_service/src/configuration/linter.rs create mode 100644 crates/rome_service/src/configuration/linter/mod.rs create mode 100644 crates/rome_service/src/configuration/linter/rules.rs create mode 100644 xtask/codegen/src/generate_configuration.rs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5959b575d81..57485bfa948 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,6 +97,7 @@ It's strongly advised to **run this command before committing new changes**. #### `cargo codegen analyzer` This command will detect linter rules declared in the `analyzers` and `assists` directories in `rome_analyze`, regenerate the index modules `analyzers.rs` and `assists.rs` to import these files, and update the registry builder function in `registry.rs` to include all these rules. +It will also regenerate the configuration of the rules. #### `cargo coverage` diff --git a/Cargo.lock b/Cargo.lock index 97e2dd4ca95..f93157362d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1148,11 +1148,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -1856,13 +1856,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.94" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07e33e919ebcd69113d5be0e4d70c5707004ff45188910106854f38b960df4a" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -2207,6 +2207,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +[[package]] +name = "unicode-ident" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" + [[package]] name = "unicode-normalization" version = "0.1.19" @@ -2228,12 +2234,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - [[package]] name = "untrusted" version = "0.7.1" @@ -2504,11 +2504,14 @@ name = "xtask_codegen" version = "0.0.0" dependencies = [ "anyhow", + "case", "filetime", "git2", "pico-args", "proc-macro2", "quote", + "rome_analyze", + "rome_js_analyze", "ungrammar", "ureq", "walkdir", diff --git a/crates/rome_cli/src/traversal.rs b/crates/rome_cli/src/traversal.rs index a7401bd05a4..929070053ef 100644 --- a/crates/rome_cli/src/traversal.rs +++ b/crates/rome_cli/src/traversal.rs @@ -226,7 +226,7 @@ fn print_messages_to_console( } } - if !mode.is_ci() { + if !mode.is_ci() && not_printed_diagnostics > 0 { console.log(markup! { "The number of diagnostics exceeds the number allowed by Rome." "Diagnostics not shown: "{not_printed_diagnostics}"." diff --git a/crates/rome_cli/tests/configs.rs b/crates/rome_cli/tests/configs.rs index b12bbd6d90a..7e17f112b03 100644 --- a/crates/rome_cli/tests/configs.rs +++ b/crates/rome_cli/tests/configs.rs @@ -36,7 +36,14 @@ pub const CONFIG_ALL_FIELDS: &str = r#"{ "lineWidth": 80 }, "linter": { - "enabled": true + "enabled": true, + "globals": ["$"], + "rules": { + "js": { + "noDeadCode": "off", + "useSimplifiedLogicExpression": "warn" + } + } }, "javascript": { "formatter": { @@ -58,3 +65,18 @@ pub const CONFIG_LINTER_DISABLED: &str = r#"{ "enabled": false } }"#; + +pub const CONFIG_LINTER_WRONG_RULE: &str = r#"{ + "root": true, + "linter": { + "enabled": true, + "rules": { + "js": { + "foo_rule": "off" + }, + "jsx": { + "what_the_hell": "off" + } + } + } +}"#; diff --git a/crates/rome_cli/tests/main.rs b/crates/rome_cli/tests/main.rs index ed622e74529..b0f11f822a2 100644 --- a/crates/rome_cli/tests/main.rs +++ b/crates/rome_cli/tests/main.rs @@ -851,7 +851,9 @@ mod init { } mod configuration { - use crate::configs::{CONFIG_ALL_FIELDS, CONFIG_BAD_LINE_WIDTH, CONFIG_ROOT_FALSE}; + use crate::configs::{ + CONFIG_ALL_FIELDS, CONFIG_BAD_LINE_WIDTH, CONFIG_LINTER_WRONG_RULE, CONFIG_ROOT_FALSE, + }; use pico_args::Arguments; use rome_cli::{run_cli, CliSession}; use rome_console::BufferConsole; @@ -929,4 +931,27 @@ mod configuration { _ => panic!("expected an error, but found none"), } } + + #[test] + fn incorrect_rule_name() { + let mut fs = MemoryFileSystem::default(); + + let file_path = Path::new("rome.json"); + fs.insert(file_path.into(), CONFIG_LINTER_WRONG_RULE.as_bytes()); + + let result = run_cli(CliSession { + app: App::with_filesystem_and_console( + DynRef::Borrowed(&mut fs), + DynRef::Owned(Box::new(BufferConsole::default())), + ), + args: Arguments::from_vec(vec![OsString::from("check"), OsString::from("file.js")]), + }); + + match result { + Err(error) => { + assert!(error.to_string().contains("unknown field `foo_rule`"),) + } + _ => panic!("expected an error, but found none"), + } + } } diff --git a/crates/rome_service/src/configuration/linter.rs b/crates/rome_service/src/configuration/linter.rs deleted file mode 100644 index a9eae4d482e..00000000000 --- a/crates/rome_service/src/configuration/linter.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::settings::LinterSettings; -use serde::{Deserialize, Serialize}; - -#[derive(Deserialize, Serialize, Debug, Eq, PartialEq)] -#[serde(rename_all = "camelCase", default)] -pub struct LinterConfiguration { - // if `false`, it disables the feature. `true` by default - pub enabled: bool, -} - -impl Default for LinterConfiguration { - fn default() -> Self { - Self { enabled: true } - } -} - -impl From<&LinterConfiguration> for LinterSettings { - fn from(conf: &LinterConfiguration) -> Self { - Self { - enabled: conf.enabled, - } - } -} diff --git a/crates/rome_service/src/configuration/linter/mod.rs b/crates/rome_service/src/configuration/linter/mod.rs new file mode 100644 index 00000000000..7e7bc736c6b --- /dev/null +++ b/crates/rome_service/src/configuration/linter/mod.rs @@ -0,0 +1,42 @@ +#[rustfmt::skip] +mod rules; + +pub use crate::configuration::linter::rules::Rules; +use crate::settings::LinterSettings; +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Debug, Eq, PartialEq)] +#[serde(rename_all = "camelCase", default)] +pub struct LinterConfiguration { + /// if `false`, it disables the feature. `true` by default + pub enabled: bool, + + /// A list of global bindings that should be ignored by the analyzers + /// + /// If defined here, they should not emit diagnostics. + #[serde(skip_serializing_if = "Option::is_none")] + pub globals: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub rules: Option, +} + +impl Default for LinterConfiguration { + fn default() -> Self { + Self { + enabled: true, + globals: None, + rules: None, + } + } +} + +impl From<&LinterConfiguration> for LinterSettings { + fn from(conf: &LinterConfiguration) -> Self { + Self { + enabled: conf.enabled, + globals: conf.globals.clone(), + rules: conf.rules.clone(), + } + } +} diff --git a/crates/rome_service/src/configuration/linter/rules.rs b/crates/rome_service/src/configuration/linter/rules.rs new file mode 100644 index 00000000000..03a1a2e094c --- /dev/null +++ b/crates/rome_service/src/configuration/linter/rules.rs @@ -0,0 +1,106 @@ +//! Generated file, do not edit by hand, see `xtask/codegen` + +use serde::{Deserialize, Serialize}; +#[derive(Deserialize, Serialize, Debug, Eq, PartialEq, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub enum RuleConfiguration { + Warn, + Error, + Off, +} +impl RuleConfiguration { + pub fn is_err(&self) -> bool { matches!(self, Self::Error) } +} +impl Default for RuleConfiguration { + fn default() -> Self { Self::Error } +} +#[derive(Deserialize, Serialize, Debug, Eq, PartialEq, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct Rules { + #[serde(skip_serializing_if = "Option::is_none")] + pub js: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub jsx: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub regex: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub ts: Option, +} +impl Default for Rules { + fn default() -> Self { + Self { + js: Some(JsRules::default()), + jsx: Some(JsxRules::default()), + regex: Some(RegexRules::default()), + ts: Some(TsRules::default()), + } + } +} +#[derive(Deserialize, Default, Serialize, Debug, Eq, PartialEq, Clone)] +#[serde(rename_all = "camelCase", default, deny_unknown_fields)] +pub struct JsRules { + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_arguments: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_async_promise_executor: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_catch_assign: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_compare_neg_zero: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_dead_code: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_debugger: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_delete: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_double_equals: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_empty_pattern: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_label_var: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_negation_else: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_sparse_array: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_unnecessary_continue: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_unsafe_negation: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_unused_template_literal: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub use_block_statements: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub use_simplified_logic_expression: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub use_single_case_statement: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub use_single_var_declarator: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub use_valid_typeof: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub use_while: RuleConfiguration, +} +#[derive(Deserialize, Default, Serialize, Debug, Eq, PartialEq, Clone)] +#[serde(rename_all = "camelCase", default, deny_unknown_fields)] +pub struct JsxRules { + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_comment_text: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_implicit_boolean: RuleConfiguration, + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub use_self_closing_elements: RuleConfiguration, +} +#[derive(Deserialize, Default, Serialize, Debug, Eq, PartialEq, Clone)] +#[serde(rename_all = "camelCase", default, deny_unknown_fields)] +pub struct RegexRules { + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub no_multiple_spaces_in_regular_expression_literals: RuleConfiguration, +} +#[derive(Deserialize, Default, Serialize, Debug, Eq, PartialEq, Clone)] +#[serde(rename_all = "camelCase", default, deny_unknown_fields)] +pub struct TsRules { + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub use_shorthand_array_type: RuleConfiguration, +} diff --git a/crates/rome_service/src/configuration/mod.rs b/crates/rome_service/src/configuration/mod.rs index f17d6d276dc..3ec1cc64beb 100644 --- a/crates/rome_service/src/configuration/mod.rs +++ b/crates/rome_service/src/configuration/mod.rs @@ -15,10 +15,13 @@ use std::path::PathBuf; mod formatter; mod javascript; -mod linter; +pub mod linter; + +pub use linter::Rules; /// The configuration that is contained inside the file `rome.json` #[derive(Debug, Eq, PartialEq, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] pub struct Configuration { /// One root file should exist. Useful when `extends` comes into play. /// diff --git a/crates/rome_service/src/lib.rs b/crates/rome_service/src/lib.rs index 3b402b35395..22f0ff6e237 100644 --- a/crates/rome_service/src/lib.rs +++ b/crates/rome_service/src/lib.rs @@ -12,7 +12,7 @@ pub mod settings; pub mod workspace; pub use crate::configuration::{ - create_config, load_config, Configuration, ConfigurationError, ConfigurationType, + create_config, load_config, Configuration, ConfigurationError, ConfigurationType, Rules, }; pub use crate::file_handlers::JsFormatSettings; pub use crate::workspace::Workspace; diff --git a/crates/rome_service/src/settings.rs b/crates/rome_service/src/settings.rs index 8f1f3851941..e733b047e57 100644 --- a/crates/rome_service/src/settings.rs +++ b/crates/rome_service/src/settings.rs @@ -1,6 +1,6 @@ use std::sync::{RwLock, RwLockReadGuard}; -use crate::Configuration; +use crate::{Configuration, Rules}; use rome_formatter::{IndentStyle, LineWidth}; use rome_fs::RomePath; use rome_js_syntax::JsLanguage; @@ -19,6 +19,7 @@ pub struct WorkspaceSettings { impl WorkspaceSettings { /// The (configuration)[Configuration] is merged into the workspace pub fn merge_with_configuration(&mut self, configuration: &Configuration) { + // formatter part if let Some(formatter) = &configuration.formatter { self.format = FormatSettings::from(formatter); } @@ -29,6 +30,11 @@ impl WorkspaceSettings { if let Some(formatter) = formatter { self.languages.javascript.format.quote_style = Some(formatter.quote_style); } + + // linter part + if let Some(linter) = &configuration.linter { + self.linter = LinterSettings::from(linter) + } } } @@ -55,16 +61,27 @@ impl Default for FormatSettings { } } -/// Formatter settings for the entire workspace +/// Linter settings for the entire workspace #[derive(Debug)] pub struct LinterSettings { /// Enabled by default pub enabled: bool, + + /// A list of global bindings that should be ignored by the analyzers + /// + /// If defined here, they should not emit diagnostics. + pub globals: Option>, + + pub rules: Option, } impl Default for LinterSettings { fn default() -> Self { - Self { enabled: true } + Self { + enabled: true, + globals: None, + rules: Some(Rules::default()), + } } } diff --git a/xtask/codegen/Cargo.toml b/xtask/codegen/Cargo.toml index b34129c842d..f0a56c5b619 100644 --- a/xtask/codegen/Cargo.toml +++ b/xtask/codegen/Cargo.toml @@ -15,3 +15,6 @@ walkdir = "2.3.2" ureq = "2.4.0" git2 = { version = "0.13.25", default-features = false } filetime = "0.2.15" +rome_analyze = { path = "../../crates/rome_analyze" } +rome_js_analyze = { path = "../../crates/rome_js_analyze" } +case = "1.0.0" diff --git a/xtask/codegen/src/generate_configuration.rs b/xtask/codegen/src/generate_configuration.rs new file mode 100644 index 00000000000..4251aa05a60 --- /dev/null +++ b/xtask/codegen/src/generate_configuration.rs @@ -0,0 +1,121 @@ +use case::CaseExt; +use proc_macro2::{Ident, Span}; +use quote::quote; +use rome_analyze::{AnalysisFilter, RuleCategories}; +use rome_js_analyze::metadata; +use std::collections::BTreeMap; +use xtask::glue::fs2; +use xtask::*; +use xtask_codegen::to_lower_snake_case; + +pub(crate) fn generate_rules_configuration() -> Result<()> { + let config_root = project_root().join("crates/rome_service/src/configuration/linter"); + + let filter = AnalysisFilter { + categories: RuleCategories::LINT, + ..AnalysisFilter::default() + }; + + // Ensure the list of rules is stored alphabetically + let mut groups = BTreeMap::new(); + for meta in metadata(filter) { + groups + .entry(meta.group) + .or_insert_with(BTreeMap::new) + .insert(meta.name, meta.docs); + } + + let mut struct_groups = Vec::new(); + let mut line_groups = Vec::new(); + let mut default_for_groups = Vec::new(); + for (group, rules) in groups { + let mut declarations = Vec::new(); + + for (rule, _) in rules { + let rule = Ident::new(&to_lower_snake_case(rule), Span::call_site()); + let declaration = quote! { + #[serde(skip_serializing_if = "RuleConfiguration::is_err")] + pub #rule: RuleConfiguration + }; + declarations.push(declaration); + } + + let property_group_name = Ident::new(&to_lower_snake_case(group), Span::call_site()); + + let struct_group_name = Ident::new( + &format!("{}Rules", group.to_capitalized()), + Span::call_site(), + ); + + let the_struct = quote! { + + #[derive(Deserialize, Default, Serialize, Debug, Eq, PartialEq, Clone)] + #[serde(rename_all = "camelCase", default, deny_unknown_fields)] + pub struct #struct_group_name { + #( #declarations ),* + } + + }; + + let line = quote! { + #[serde(skip_serializing_if = "Option::is_none")] + pub #property_group_name: Option<#struct_group_name> + }; + + let default = quote! { + #property_group_name: Some(#struct_group_name::default()) + }; + + struct_groups.push(the_struct); + line_groups.push(line); + default_for_groups.push(default); + } + + let groups = quote! { + use serde::{Deserialize, Serialize}; + + #[derive(Deserialize, Serialize, Debug, Eq, PartialEq, Clone)] + #[serde(rename_all = "camelCase", deny_unknown_fields)] + pub enum RuleConfiguration { + Warn, + Error, + Off, + } + + impl RuleConfiguration { + pub fn is_err(&self) -> bool { + matches!(self, Self::Error) + } + } + + impl Default for RuleConfiguration { + fn default() -> Self { + Self::Error + } + } + + #[derive(Deserialize, Serialize, Debug, Eq, PartialEq, Clone)] + #[serde(rename_all = "camelCase", deny_unknown_fields)] + pub struct Rules { + #( #line_groups ),* + } + + impl Default for Rules { + fn default() -> Self { + Self { + #( #default_for_groups ),* + } + } + } + + #( #struct_groups )* + }; + + let ast = groups.to_string(); + + let pretty = xtask::reformat(ast)?; + + fs2::write(config_root.join("rules.rs"), pretty)?; + + Ok(()) +} diff --git a/xtask/codegen/src/main.rs b/xtask/codegen/src/main.rs index bd048e33d8b..bd5894ab437 100644 --- a/xtask/codegen/src/main.rs +++ b/xtask/codegen/src/main.rs @@ -1,6 +1,9 @@ +mod generate_configuration; + use pico_args::Arguments; use xtask::{project_root, pushd, Mode, Result}; +use crate::generate_configuration::generate_rules_configuration; use xtask_codegen::{ generate_analyzer, generate_ast, generate_formatter, generate_parser_tests, generate_tables, }; @@ -34,6 +37,7 @@ fn main() -> Result<()> { } "analyzer" => { generate_analyzer()?; + generate_rules_configuration()?; Ok(()) } _ => { @@ -44,8 +48,9 @@ Run codegen command. USAGE: cargo codegen [option] SUBCOMMANDS: - analyzer Generate factory functions for the analyzer - grammar Transforms js.ungram into AST + analyzer Generate factory functions for the analyzer and the configuration of the analyzers + grammar Transforms ungram files into AST + formatter Generates formatters for each language test Extracts parser inline comments into test files unicode Generates unicode table inside lexer " From 845e2421c2561d59959b209bfec9fa2c8064544d Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Mon, 18 Jul 2022 14:56:48 +0100 Subject: [PATCH 2/3] chore: code review --- .../src/configuration/linter/mod.rs | 24 ++++++++++++++++--- .../src/configuration/linter/rules.rs | 14 +---------- crates/rome_service/src/configuration/mod.rs | 2 +- crates/rome_service/src/lib.rs | 3 ++- crates/rome_service/src/settings.rs | 4 ++-- xtask/codegen/src/generate_configuration.rs | 20 +--------------- 6 files changed, 28 insertions(+), 39 deletions(-) diff --git a/crates/rome_service/src/configuration/linter/mod.rs b/crates/rome_service/src/configuration/linter/mod.rs index 7e7bc736c6b..bf0fce2d724 100644 --- a/crates/rome_service/src/configuration/linter/mod.rs +++ b/crates/rome_service/src/configuration/linter/mod.rs @@ -14,8 +14,8 @@ pub struct LinterConfiguration { /// A list of global bindings that should be ignored by the analyzers /// /// If defined here, they should not emit diagnostics. - #[serde(skip_serializing_if = "Option::is_none")] - pub globals: Option>, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub globals: Vec, #[serde(skip_serializing_if = "Option::is_none")] pub rules: Option, @@ -25,7 +25,7 @@ impl Default for LinterConfiguration { fn default() -> Self { Self { enabled: true, - globals: None, + globals: vec![], rules: None, } } @@ -40,3 +40,21 @@ impl From<&LinterConfiguration> for LinterSettings { } } } + +#[derive(Deserialize, Serialize, Debug, Eq, PartialEq, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub enum RuleConfiguration { + Warn, + Error, + Off, +} +impl RuleConfiguration { + pub fn is_err(&self) -> bool { + matches!(self, Self::Error) + } +} +impl Default for RuleConfiguration { + fn default() -> Self { + Self::Error + } +} diff --git a/crates/rome_service/src/configuration/linter/rules.rs b/crates/rome_service/src/configuration/linter/rules.rs index 03a1a2e094c..d2b12b29910 100644 --- a/crates/rome_service/src/configuration/linter/rules.rs +++ b/crates/rome_service/src/configuration/linter/rules.rs @@ -1,21 +1,9 @@ //! Generated file, do not edit by hand, see `xtask/codegen` +use crate::RuleConfiguration; use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize, Debug, Eq, PartialEq, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] -pub enum RuleConfiguration { - Warn, - Error, - Off, -} -impl RuleConfiguration { - pub fn is_err(&self) -> bool { matches!(self, Self::Error) } -} -impl Default for RuleConfiguration { - fn default() -> Self { Self::Error } -} -#[derive(Deserialize, Serialize, Debug, Eq, PartialEq, Clone)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct Rules { #[serde(skip_serializing_if = "Option::is_none")] pub js: Option, diff --git a/crates/rome_service/src/configuration/mod.rs b/crates/rome_service/src/configuration/mod.rs index 3ec1cc64beb..947ddd4b2c2 100644 --- a/crates/rome_service/src/configuration/mod.rs +++ b/crates/rome_service/src/configuration/mod.rs @@ -17,7 +17,7 @@ mod formatter; mod javascript; pub mod linter; -pub use linter::Rules; +pub use linter::{RuleConfiguration, Rules}; /// The configuration that is contained inside the file `rome.json` #[derive(Debug, Eq, PartialEq, Deserialize, Serialize)] diff --git a/crates/rome_service/src/lib.rs b/crates/rome_service/src/lib.rs index 22f0ff6e237..97daf271b89 100644 --- a/crates/rome_service/src/lib.rs +++ b/crates/rome_service/src/lib.rs @@ -12,7 +12,8 @@ pub mod settings; pub mod workspace; pub use crate::configuration::{ - create_config, load_config, Configuration, ConfigurationError, ConfigurationType, Rules, + create_config, load_config, Configuration, ConfigurationError, ConfigurationType, + RuleConfiguration, Rules, }; pub use crate::file_handlers::JsFormatSettings; pub use crate::workspace::Workspace; diff --git a/crates/rome_service/src/settings.rs b/crates/rome_service/src/settings.rs index e733b047e57..e8fac1f598d 100644 --- a/crates/rome_service/src/settings.rs +++ b/crates/rome_service/src/settings.rs @@ -70,7 +70,7 @@ pub struct LinterSettings { /// A list of global bindings that should be ignored by the analyzers /// /// If defined here, they should not emit diagnostics. - pub globals: Option>, + pub globals: Vec, pub rules: Option, } @@ -79,7 +79,7 @@ impl Default for LinterSettings { fn default() -> Self { Self { enabled: true, - globals: None, + globals: vec![], rules: Some(Rules::default()), } } diff --git a/xtask/codegen/src/generate_configuration.rs b/xtask/codegen/src/generate_configuration.rs index 4251aa05a60..f22776af3a1 100644 --- a/xtask/codegen/src/generate_configuration.rs +++ b/xtask/codegen/src/generate_configuration.rs @@ -73,26 +73,8 @@ pub(crate) fn generate_rules_configuration() -> Result<()> { let groups = quote! { use serde::{Deserialize, Serialize}; + use crate::RuleConfiguration; - #[derive(Deserialize, Serialize, Debug, Eq, PartialEq, Clone)] - #[serde(rename_all = "camelCase", deny_unknown_fields)] - pub enum RuleConfiguration { - Warn, - Error, - Off, - } - - impl RuleConfiguration { - pub fn is_err(&self) -> bool { - matches!(self, Self::Error) - } - } - - impl Default for RuleConfiguration { - fn default() -> Self { - Self::Error - } - } #[derive(Deserialize, Serialize, Debug, Eq, PartialEq, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] From f3ce1bd365fc8f5d15f37da4a28beb1b5f68a7fe Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Mon, 18 Jul 2022 17:21:35 +0100 Subject: [PATCH 3/3] chore: use utility --- xtask/codegen/src/generate_configuration.rs | 7 +++---- xtask/codegen/src/lib.rs | 4 ++-- xtask/codegen/src/main.rs | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/xtask/codegen/src/generate_configuration.rs b/xtask/codegen/src/generate_configuration.rs index f22776af3a1..c61b45c58bb 100644 --- a/xtask/codegen/src/generate_configuration.rs +++ b/xtask/codegen/src/generate_configuration.rs @@ -4,11 +4,10 @@ use quote::quote; use rome_analyze::{AnalysisFilter, RuleCategories}; use rome_js_analyze::metadata; use std::collections::BTreeMap; -use xtask::glue::fs2; use xtask::*; -use xtask_codegen::to_lower_snake_case; +use xtask_codegen::{to_lower_snake_case, update}; -pub(crate) fn generate_rules_configuration() -> Result<()> { +pub(crate) fn generate_rules_configuration(mode: Mode) -> Result<()> { let config_root = project_root().join("crates/rome_service/src/configuration/linter"); let filter = AnalysisFilter { @@ -97,7 +96,7 @@ pub(crate) fn generate_rules_configuration() -> Result<()> { let pretty = xtask::reformat(ast)?; - fs2::write(config_root.join("rules.rs"), pretty)?; + update(&config_root.join("rules.rs"), &pretty, &mode)?; Ok(()) } diff --git a/xtask/codegen/src/lib.rs b/xtask/codegen/src/lib.rs index ad5f63b9eb6..fd14e772be0 100644 --- a/xtask/codegen/src/lib.rs +++ b/xtask/codegen/src/lib.rs @@ -49,7 +49,7 @@ const JSON_SYNTAX_FACTORY: &str = "crates/rome_json_factory/src/generated/syntax const JSON_NODE_FACTORY: &str = "crates/rome_json_factory/src/generated/node_factory.rs"; const JSON_AST_MACROS: &str = "crates/rome_json_syntax/src/generated/macros.rs"; -enum UpdateResult { +pub enum UpdateResult { NotUpdated, Updated, } @@ -158,7 +158,7 @@ impl LanguageKind { /// A helper to update file on disk if it has changed. /// With verify = false, -fn update(path: &Path, contents: &str, mode: &Mode) -> Result { +pub fn update(path: &Path, contents: &str, mode: &Mode) -> Result { match fs2::read_to_string(path) { Ok(old_contents) if old_contents == contents => { return Ok(UpdateResult::NotUpdated); diff --git a/xtask/codegen/src/main.rs b/xtask/codegen/src/main.rs index bd5894ab437..e554fe3793c 100644 --- a/xtask/codegen/src/main.rs +++ b/xtask/codegen/src/main.rs @@ -37,7 +37,7 @@ fn main() -> Result<()> { } "analyzer" => { generate_analyzer()?; - generate_rules_configuration()?; + generate_rules_configuration(Mode::Overwrite)?; Ok(()) } _ => {