From 216773f168535316e998d20baf214ad34c97e520 Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Tue, 18 Apr 2023 00:02:47 +0800 Subject: [PATCH 01/19] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20allow=20comments?= =?UTF-8?q?=20in=20json=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/rome_service/src/configuration/json.rs | 14 ++++ crates/rome_service/src/configuration/mod.rs | 77 ++++++------------- .../src/configuration/parse/json.rs | 1 + .../configuration/parse/json/configuration.rs | 6 ++ .../src/configuration/parse/json/json.rs | 39 ++++++++++ 5 files changed, 85 insertions(+), 52 deletions(-) create mode 100644 crates/rome_service/src/configuration/json.rs create mode 100644 crates/rome_service/src/configuration/parse/json/json.rs diff --git a/crates/rome_service/src/configuration/json.rs b/crates/rome_service/src/configuration/json.rs new file mode 100644 index 00000000000..f16d2c170f4 --- /dev/null +++ b/crates/rome_service/src/configuration/json.rs @@ -0,0 +1,14 @@ +use indexmap::IndexSet; +use serde::{Deserialize, Serialize}; + +#[derive(Default, Debug, Deserialize, Serialize, Eq, PartialEq)] +#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] +#[serde(default, deny_unknown_fields)] +pub struct JsonConfiguration { + #[serde(skip_serializing_if = "Option::is_none")] + pub allow_comments: Option>, +} + +impl JsonConfiguration { + pub(crate) const KNOWN_KEYS: &'static [&'static str] = &["allowComments"]; +} diff --git a/crates/rome_service/src/configuration/mod.rs b/crates/rome_service/src/configuration/mod.rs index c6fe15b32e3..c5b5c1c2c03 100644 --- a/crates/rome_service/src/configuration/mod.rs +++ b/crates/rome_service/src/configuration/mod.rs @@ -3,9 +3,9 @@ //! The configuration is divided by "tool", and then it's possible to further customise it //! by language. The language might further options divided by tool. -use crate::{DynRef, WorkspaceError, VERSION}; +use crate::{DynRef, WorkspaceError}; use bpaf::Bpaf; -use rome_fs::{AutoSearchResult, FileSystem, OpenOptions}; +use rome_fs::{FileSystem, OpenOptions}; use serde::{Deserialize, Serialize}; use std::fmt::Debug; use std::io::ErrorKind; @@ -16,6 +16,9 @@ pub mod diagnostics; pub mod formatter; mod generated; pub mod javascript; +mod javascript; +mod javascript; +mod json; pub mod linter; mod merge; pub mod organize_imports; @@ -40,6 +43,8 @@ use rome_js_analyze::metadata; use rome_json_formatter::context::JsonFormatOptions; use rome_json_parser::parse_json; +use self::json::JsonConfiguration; + /// The configuration that is contained inside the file `rome.json` #[derive(Debug, Deserialize, Serialize, Clone, Bpaf)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] @@ -51,7 +56,7 @@ pub struct Configuration { #[bpaf(hide)] pub schema: Option, - /// The configuration of the VCS integration + /// The configuration of the filesystem #[serde(skip_serializing_if = "Option::is_none")] #[bpaf(external(vcs_configuration), optional, hide_usage)] pub vcs: Option, @@ -81,10 +86,9 @@ pub struct Configuration { #[bpaf(external(javascript_configuration), optional)] pub javascript: Option, - /// A list of paths to other JSON files, used to extends the current configuration. + /// Specific configuration for the JavaScript language #[serde(skip_serializing_if = "Option::is_none")] - #[bpaf(hide)] - pub extends: Option, + pub json: Option, } impl Default for Configuration { @@ -100,7 +104,7 @@ impl Default for Configuration { javascript: None, schema: None, vcs: None, - extends: None, + json: None, } } } @@ -114,7 +118,6 @@ impl Configuration { "javascript", "$schema", "organizeImports", - "extends", ]; pub fn is_formatter_disabled(&self) -> bool { self.formatter @@ -251,15 +254,10 @@ pub struct FilesConfiguration { #[serde(skip_serializing_if = "Option::is_none")] #[bpaf(hide)] pub ignore: Option, - - /// Tells Rome to not emit diagnostics when handling files that doesn't know - #[serde(skip_serializing_if = "Option::is_none")] - #[bpaf(long("files-ignore-unknown"), argument("true|false"), optional)] - pub ignore_unknown: Option, } impl FilesConfiguration { - const KNOWN_KEYS: &'static [&'static str] = &["maxSize", "ignore", "ignoreUnknown"]; + const KNOWN_KEYS: &'static [&'static str] = &["maxSize", "ignore"]; } impl MergeWith for FilesConfiguration { @@ -270,26 +268,15 @@ impl MergeWith for FilesConfiguration { if let Some(max_size) = other.max_size { self.max_size = Some(max_size) } - if let Some(ignore_unknown) = other.ignore_unknown { - self.ignore_unknown = Some(ignore_unknown) - } } } /// - [Result]: if an error occurred while loading the configuration file. /// - [Option]: sometimes not having a configuration file should not be an error, so we need this type. -/// - [ConfigurationPayload]: The result of the operation -type LoadConfig = Result, WorkspaceError>; - -pub struct ConfigurationPayload { - /// The result of the deserialization - pub deserialized: Deserialized, - /// The path of where the `rome.json` file was found. This contains the `rome.json` name. - pub configuration_file_path: PathBuf, - /// The base path of where the `rome.json` file was found. - /// This has to be used to resolve other configuration files. - pub configuration_directory_path: PathBuf, -} +/// - [Deserialized]: result of the deserialization of the configuration. +/// - [Configuration]: the type needed to [Deserialized] to infer the return type. +/// - [PathBuf]: the path of where the first `rome.json` path was found +type LoadConfig = Result, PathBuf)>, WorkspaceError>; #[derive(Debug, Default, PartialEq)] pub enum ConfigurationBasePath { @@ -333,22 +320,15 @@ pub fn load_config( None => PathBuf::new(), }, }; + let configuration_file_path = configuration_directory.join(config_name); let should_error = base_path.is_from_user(); let result = file_system.auto_search(configuration_directory, config_name, should_error)?; - if let Some(auto_search_result) = result { - let AutoSearchResult { - content, - directory_path, - file_path, - } = auto_search_result; - let deserialized = deserialize_from_json_str::(&content); - Ok(Some(ConfigurationPayload { - deserialized, - configuration_file_path: file_path, - configuration_directory_path: directory_path, - })) + if let Some((buffer, configuration_path)) = result { + let deserialized = deserialize_from_json_str::(&buffer) + .with_file_path(&configuration_file_path.display().to_string()); + Ok(Some((deserialized, configuration_path))) } else { Ok(None) } @@ -378,17 +358,10 @@ pub fn create_config( })?; // we now check if rome is installed inside `node_modules` and if so, we - if VERSION == "0.0.0" { - let schema_path = Path::new("./node_modules/rome/configuration_schema.json"); - let options = OpenOptions::default().read(true); - if fs.open_with_options(schema_path, options).is_ok() { - configuration.schema = schema_path.to_str().map(String::from); - } - } else { - configuration.schema = Some(format!( - "https://docs.rome.tools/schemas/{}/schema.json", - VERSION - )); + let schema_path = Path::new("./node_modules/rome/configuration_schema.json"); + let options = OpenOptions::default().read(true); + if fs.open_with_options(schema_path, options).is_ok() { + configuration.schema = schema_path.to_str().map(String::from); } let contents = serde_json::to_string_pretty(&configuration).map_err(|_| { diff --git a/crates/rome_service/src/configuration/parse/json.rs b/crates/rome_service/src/configuration/parse/json.rs index 0a1844d52be..92910f05183 100644 --- a/crates/rome_service/src/configuration/parse/json.rs +++ b/crates/rome_service/src/configuration/parse/json.rs @@ -5,6 +5,7 @@ mod configuration; mod files; mod formatter; mod javascript; +mod json; mod linter; mod organize_imports; mod rules; diff --git a/crates/rome_service/src/configuration/parse/json/configuration.rs b/crates/rome_service/src/configuration/parse/json/configuration.rs index 12a441a2e8e..2fdb637d62d 100644 --- a/crates/rome_service/src/configuration/parse/json/configuration.rs +++ b/crates/rome_service/src/configuration/parse/json/configuration.rs @@ -1,3 +1,4 @@ +use crate::configuration::json::JsonConfiguration; use crate::configuration::organize_imports::OrganizeImports; use crate::configuration::parse::json::vcs::validate_vcs_configuration; use crate::configuration::vcs::VcsConfiguration; @@ -60,6 +61,11 @@ impl VisitNode for Configuration { self.map_to_object(&value, name_text, &mut javascript, diagnostics)?; self.javascript = Some(javascript); } + "json" => { + let mut json = JsonConfiguration::default(); + self.map_to_object(&value, name_text, &mut json, diagnostics)?; + self.json = Some(json); + } "organizeImports" => { let mut organize_imports = OrganizeImports::default(); self.map_to_object(&value, name_text, &mut organize_imports, diagnostics)?; diff --git a/crates/rome_service/src/configuration/parse/json/json.rs b/crates/rome_service/src/configuration/parse/json/json.rs new file mode 100644 index 00000000000..2bc6eab4a58 --- /dev/null +++ b/crates/rome_service/src/configuration/parse/json/json.rs @@ -0,0 +1,39 @@ + +use crate::configuration::json::JsonConfiguration; + +use rome_deserialize::json::{has_only_known_keys, VisitJsonNode}; +use rome_deserialize::{DeserializationDiagnostic, VisitNode}; +use rome_json_syntax::{JsonLanguage, JsonSyntaxNode}; +use rome_rowan::SyntaxNode; + +impl VisitJsonNode for JsonConfiguration {} + +impl VisitNode for JsonConfiguration { + fn visit_member_name( + &mut self, + node: &JsonSyntaxNode, + diagnostics: &mut Vec, + ) -> Option<()> { + has_only_known_keys(node, JsonConfiguration::KNOWN_KEYS, diagnostics) + } + + fn visit_map( + &mut self, + key: &SyntaxNode, + value: &SyntaxNode, + diagnostics: &mut Vec, + ) -> Option<()> { + let (name, value) = self.get_key_and_value(key, value, diagnostics)?; + let name_text = name.text(); + + match name_text { + "allowComments" => { + let glob_array = self.map_to_index_set_string(&value, name_text, diagnostics)?; + self.allow_comments = Some(glob_array); + } + _ => {} + } + + Some(()) + } +} From 62527a695ea68a4aee68c3cb41d604970581c009 Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Tue, 18 Apr 2023 00:07:39 +0800 Subject: [PATCH 02/19] =?UTF-8?q?chore:=20=F0=9F=A4=96=20fmt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/rome_service/src/configuration/parse/json/json.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/rome_service/src/configuration/parse/json/json.rs b/crates/rome_service/src/configuration/parse/json/json.rs index 2bc6eab4a58..26a3c294db8 100644 --- a/crates/rome_service/src/configuration/parse/json/json.rs +++ b/crates/rome_service/src/configuration/parse/json/json.rs @@ -1,4 +1,3 @@ - use crate::configuration::json::JsonConfiguration; use rome_deserialize::json::{has_only_known_keys, VisitJsonNode}; From 091b957970ef0a13c33574a1ae11166e49663a20 Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Tue, 18 Apr 2023 00:14:10 +0800 Subject: [PATCH 03/19] =?UTF-8?q?chore:=20=F0=9F=A4=96=20update=20schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- editors/vscode/configuration_schema.json | 281 +++-------------------- npm/rome/configuration_schema.json | 281 +++-------------------- 2 files changed, 68 insertions(+), 494 deletions(-) diff --git a/editors/vscode/configuration_schema.json b/editors/vscode/configuration_schema.json index d0ea9053ee5..b635987a071 100644 --- a/editors/vscode/configuration_schema.json +++ b/editors/vscode/configuration_schema.json @@ -8,10 +8,6 @@ "description": "A field for the [JSON schema](https://json-schema.org/) specification", "type": ["string", "null"] }, - "extends": { - "description": "A list of paths to other JSON files, used to extends the current configuration.", - "anyOf": [{ "$ref": "#/definitions/StringSet" }, { "type": "null" }] - }, "files": { "description": "The configuration of the filesystem", "anyOf": [ @@ -33,6 +29,13 @@ { "type": "null" } ] }, + "json": { + "description": "Specific configuration for the JavaScript language", + "anyOf": [ + { "$ref": "#/definitions/JsonConfiguration" }, + { "type": "null" } + ] + }, "linter": { "description": "The configuration for the linter", "anyOf": [ @@ -45,7 +48,7 @@ "anyOf": [{ "$ref": "#/definitions/OrganizeImports" }, { "type": "null" }] }, "vcs": { - "description": "The configuration of the VCS integration", + "description": "The configuration of the filesystem", "anyOf": [ { "$ref": "#/definitions/VcsConfiguration" }, { "type": "null" } @@ -165,7 +168,7 @@ ] }, "useIframeTitle": { - "description": "Enforces the usage of the attribute title for the element iframe.", + "description": "Enforces the usage of the attribute title for the element iframe", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -215,7 +218,6 @@ } } }, - "ArrowParentheses": { "type": "string", "enum": ["always", "asNeeded"] }, "Complexity": { "description": "A list of rules that belong to this group", "type": "object", @@ -231,6 +233,13 @@ { "type": "null" } ] }, + "noExtraSemicolon": { + "description": "Typing mistakes and misunderstandings about where semicolons are required can lead to semicolons that are unnecessary. While not technically an error, extra semicolons can cause confusion when reading code.", + "anyOf": [ + { "$ref": "#/definitions/RuleConfiguration" }, + { "type": "null" } + ] + }, "noMultipleSpacesInRegularExpressionLiterals": { "description": "Disallow unclear usage of multiple space characters in regular expression literals", "anyOf": [ @@ -280,13 +289,6 @@ { "type": "null" } ] }, - "noUselessTypeConstraint": { - "description": "Disallow using any or unknown as type constraint.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "noWith": { "description": "Disallow with statements in non-strict contexts.", "anyOf": [ @@ -321,20 +323,6 @@ } } }, - "ComplexityOptions": { - "description": "Options for the rule `noNestedModuleImports`.", - "type": "object", - "required": ["maxAllowedComplexity"], - "properties": { - "maxAllowedComplexity": { - "description": "The maximum complexity score that we allow. Anything higher is considered excessive.", - "type": "integer", - "format": "uint8", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, "Correctness": { "description": "A list of rules that belong to this group", "type": "object", @@ -379,7 +367,7 @@ ] }, "noInnerDeclarations": { - "description": "Disallow function and var declarations that are accessible outside their block.", + "description": "Disallow function and var declarations in nested blocks.", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -393,7 +381,7 @@ ] }, "noNewSymbol": { - "description": "Disallow new operators with the Symbol object.", + "description": "Disallow new operators with the Symbol object", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -435,7 +423,7 @@ ] }, "noUndeclaredVariables": { - "description": "Prevents the usage of variables that haven't been declared inside the document.", + "description": "Prevents the usage of variables that haven't been declared inside the document", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -524,22 +512,6 @@ } } }, - "EnumMemberCase": { - "description": "Supported cases for TypeScript `enum` member names.", - "oneOf": [ - { - "description": "PascalCase", - "type": "string", - "enum": ["PascalCase"] - }, - { - "description": "CONSTANT_CASE", - "type": "string", - "enum": ["CONSTANT_CASE"] - }, - { "description": "camelCase", "type": "string", "enum": ["camelCase"] } - ] - }, "FilesConfiguration": { "description": "The configuration of the filesystem", "type": "object", @@ -548,10 +520,6 @@ "description": "A list of Unix shell style patterns. Rome tools will ignore files/folders that will match these patterns.", "anyOf": [{ "$ref": "#/definitions/StringSet" }, { "type": "null" }] }, - "ignoreUnknown": { - "description": "Tells Rome to not emit diagnostics when handling files that doesn't know", - "type": ["boolean", "null"] - }, "maxSize": { "description": "The maximum allowed size for source code files in bytes. Files above this limit will be ignored for performance reason. Defaults to 1 MiB", "default": null, @@ -563,7 +531,6 @@ "additionalProperties": false }, "FormatterConfiguration": { - "description": "Options applied to the formatter", "type": "object", "properties": { "enabled": { "default": true, "type": ["boolean", "null"] }, @@ -599,39 +566,6 @@ }, "additionalProperties": false }, - "Hooks": { - "type": "object", - "required": ["name"], - "properties": { - "closureIndex": { - "description": "The \"position\" of the closure function, starting from zero.\n\n### Example", - "type": ["integer", "null"], - "format": "uint", - "minimum": 0.0 - }, - "dependenciesIndex": { - "description": "The \"position\" of the array of dependencies, starting from zero.", - "type": ["integer", "null"], - "format": "uint", - "minimum": 0.0 - }, - "name": { "description": "The name of the hook", "type": "string" } - }, - "additionalProperties": false - }, - "HooksOptions": { - "description": "Options for the rule `useExhaustiveDependencies` and `useHookAtTopLevel`", - "type": "object", - "required": ["hooks"], - "properties": { - "hooks": { - "description": "List of safe hooks", - "type": "array", - "items": { "$ref": "#/definitions/Hooks" } - } - }, - "additionalProperties": false - }, "JavascriptConfiguration": { "type": "object", "properties": { @@ -650,12 +584,6 @@ { "$ref": "#/definitions/JavascriptOrganizeImports" }, { "type": "null" } ] - }, - "parser": { - "anyOf": [ - { "$ref": "#/definitions/JavascriptParser" }, - { "type": "null" } - ] } }, "additionalProperties": false @@ -663,19 +591,9 @@ "JavascriptFormatter": { "type": "object", "properties": { - "arrowParentheses": { - "description": "Whether to add non-necessary parentheses to arrow functions. Defaults to \"always\".", - "anyOf": [ - { "$ref": "#/definitions/ArrowParentheses" }, - { "type": "null" } - ] - }, - "jsxQuoteStyle": { - "description": "The style for JSX quotes. Defaults to double.", - "anyOf": [{ "$ref": "#/definitions/QuoteStyle" }, { "type": "null" }] - }, "quoteProperties": { "description": "When properties in objects are quoted. Defaults to asNeeded.", + "default": null, "anyOf": [ { "$ref": "#/definitions/QuoteProperties" }, { "type": "null" } @@ -683,14 +601,17 @@ }, "quoteStyle": { "description": "The style for quotes. Defaults to double.", + "default": null, "anyOf": [{ "$ref": "#/definitions/QuoteStyle" }, { "type": "null" }] }, "semicolons": { "description": "Whether the formatter prints semicolons for all statements or only in for statements where it is necessary because of ASI.", + "default": null, "anyOf": [{ "$ref": "#/definitions/Semicolons" }, { "type": "null" }] }, "trailingComma": { "description": "Print trailing commas wherever possible in multi-line comma-separated syntactic structures. Defaults to \"all\".", + "default": null, "anyOf": [ { "$ref": "#/definitions/TrailingComma" }, { "type": "null" } @@ -703,12 +624,13 @@ "type": "object", "additionalProperties": false }, - "JavascriptParser": { + "JsonConfiguration": { "type": "object", "properties": { - "unsafeParameterDecoratorsEnabled": { - "description": "It enables the experimental and unsafe parsing of parameter decorators\n\nThese decorators belong to an old proposal, and they are subject to change.", - "type": ["boolean", "null"] + "allow_comments": { + "type": ["array", "null"], + "items": { "type": "string" }, + "uniqueItems": true } }, "additionalProperties": false @@ -739,21 +661,6 @@ }, "additionalProperties": false }, - "NamingConventionOptions": { - "description": "Rule's options.", - "type": "object", - "properties": { - "enumMemberCase": { - "description": "Allowed cases for _TypeScript_ `enum` member names.", - "allOf": [{ "$ref": "#/definitions/EnumMemberCase" }] - }, - "strictCase": { - "description": "If `false`, then consecutive uppercase are allowed in _camel_ and _pascal_ cases. This does not affect other [Case].", - "type": "boolean" - } - }, - "additionalProperties": false - }, "Nursery": { "description": "A list of rules that belong to this group", "type": "object", @@ -777,7 +684,7 @@ ] }, "noBannedTypes": { - "description": "Disallow primitive type aliases and misleading types.", + "description": "Disallow certain types.", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -804,20 +711,6 @@ { "type": "null" } ] }, - "noControlCharactersInRegex": { - "description": "Prevents from having control characters and some escape sequences that match control characters in regular expressions.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "noDuplicateJsonKeys": { - "description": "Disallow two keys with the same name inside a JSON object.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "noDuplicateJsxProps": { "description": "Prevents JSX properties to be assigned multiple times.", "anyOf": [ @@ -825,20 +718,6 @@ { "type": "null" } ] }, - "noExcessiveComplexity": { - "description": "Disallow functions that exceed a given complexity score.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "noFallthroughSwitchClause": { - "description": "Disallow fallthrough of switch clauses.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "noForEach": { "description": "Prefer for...of statement instead of Array.forEach.", "anyOf": [ @@ -846,20 +725,6 @@ { "type": "null" } ] }, - "noGlobalIsFinite": { - "description": "Use Number.isFinite instead of global isFinite.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "noGlobalIsNan": { - "description": "Use Number.isNaN instead of global isNaN.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "noNoninteractiveTabindex": { "description": "Enforce that tabIndex is not assigned to non-interactive HTML elements.", "anyOf": [ @@ -867,13 +732,6 @@ { "type": "null" } ] }, - "noNonoctalDecimalEscape": { - "description": "Disallow \\8 and \\9 escape sequences in string literals.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "noRedundantRoles": { "description": "Enforce explicit role property is not the same as implicit/default role property on an element.", "anyOf": [ @@ -888,27 +746,6 @@ { "type": "null" } ] }, - "noStaticOnlyClass": { - "description": "This rule reports when a class has no non-static members, such as for a class used exclusively as a static namespace.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "noUselessEmptyExport": { - "description": "Disallow empty exports that don't change anything in a module file.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "noVoid": { - "description": "Disallow the use of void operators, which is not a familiar operator.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "recommended": { "description": "It enables the recommended rules for this group", "type": ["boolean", "null"] @@ -920,13 +757,6 @@ { "type": "null" } ] }, - "useArrowFunction": { - "description": "Use arrow functions over function expressions.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "useCamelCase": { "description": "Enforce camel case naming convention.", "anyOf": [ @@ -962,13 +792,6 @@ { "type": "null" } ] }, - "useIsArray": { - "description": "Use Array.isArray() instead of instanceof Array.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "useIsNan": { "description": "Require calls to isNaN() when checking for NaN.", "anyOf": [ @@ -989,20 +812,6 @@ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } ] - }, - "useNamingConvention": { - "description": "Enforce naming conventions for everything across a codebase.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "useSimpleNumberKeys": { - "description": "Disallow number literal object member names which are not base10 or uses underscore as separator", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] } } }, @@ -1048,23 +857,6 @@ { "description": "Space", "type": "string", "enum": ["space"] } ] }, - "PossibleOptions": { - "anyOf": [ - { - "description": "Options for `noExcessiveComplexity` rule", - "allOf": [{ "$ref": "#/definitions/ComplexityOptions" }] - }, - { - "description": "Options for `useExhaustiveDependencies` and `useHookAtTopLevel` rule", - "allOf": [{ "$ref": "#/definitions/HooksOptions" }] - }, - { - "description": "Options for `useNamingConvention` rule", - "allOf": [{ "$ref": "#/definitions/NamingConventionOptions" }] - }, - { "description": "No options available", "type": "null" } - ] - }, "QuoteProperties": { "type": "string", "enum": ["asNeeded", "preserve"] }, "QuoteStyle": { "type": "string", "enum": ["double", "single"] }, "RuleConfiguration": { @@ -1079,15 +871,10 @@ }, "RuleWithOptions": { "type": "object", - "required": ["level"], + "required": ["level", "options"], "properties": { "level": { "$ref": "#/definitions/RulePlainConfiguration" }, - "options": { - "anyOf": [ - { "$ref": "#/definitions/PossibleOptions" }, - { "type": "null" } - ] - } + "options": true }, "additionalProperties": false }, @@ -1281,7 +1068,7 @@ ] }, "useDefaultParameterLast": { - "description": "Enforce default function parameters and optional function parameters to be last.", + "description": "Enforce default function parameters and optional parameters to be last.", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -1620,7 +1407,7 @@ ] }, "VcsConfiguration": { - "description": "Set of properties to integrate Rome with a VCS software.", + "description": "Set of properties to configure the integration with the VCS", "type": "object", "properties": { "clientKind": { @@ -1635,7 +1422,7 @@ "type": ["boolean", "null"] }, "root": { - "description": "The folder where Rome should check for VCS files. By default, Rome will use the same folder where `rome.json` was found.\n\nIf Rome can't find the configuration, it will attempt to use the current working directory. If no current working directory can't be found, Rome won't use the VCS integration, and a diagnostic will be emitted", + "description": "The folder where Rome should check for VCS files. By default, Rome will use the same folder where `rome.json` was found.\n\nIf Rome can't fine the configuration, it will attempt to use the current working directory. If no current working directory can't be found, Rome won't use the VCS integration.", "type": ["string", "null"] }, "useIgnoreFile": { diff --git a/npm/rome/configuration_schema.json b/npm/rome/configuration_schema.json index d0ea9053ee5..b635987a071 100644 --- a/npm/rome/configuration_schema.json +++ b/npm/rome/configuration_schema.json @@ -8,10 +8,6 @@ "description": "A field for the [JSON schema](https://json-schema.org/) specification", "type": ["string", "null"] }, - "extends": { - "description": "A list of paths to other JSON files, used to extends the current configuration.", - "anyOf": [{ "$ref": "#/definitions/StringSet" }, { "type": "null" }] - }, "files": { "description": "The configuration of the filesystem", "anyOf": [ @@ -33,6 +29,13 @@ { "type": "null" } ] }, + "json": { + "description": "Specific configuration for the JavaScript language", + "anyOf": [ + { "$ref": "#/definitions/JsonConfiguration" }, + { "type": "null" } + ] + }, "linter": { "description": "The configuration for the linter", "anyOf": [ @@ -45,7 +48,7 @@ "anyOf": [{ "$ref": "#/definitions/OrganizeImports" }, { "type": "null" }] }, "vcs": { - "description": "The configuration of the VCS integration", + "description": "The configuration of the filesystem", "anyOf": [ { "$ref": "#/definitions/VcsConfiguration" }, { "type": "null" } @@ -165,7 +168,7 @@ ] }, "useIframeTitle": { - "description": "Enforces the usage of the attribute title for the element iframe.", + "description": "Enforces the usage of the attribute title for the element iframe", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -215,7 +218,6 @@ } } }, - "ArrowParentheses": { "type": "string", "enum": ["always", "asNeeded"] }, "Complexity": { "description": "A list of rules that belong to this group", "type": "object", @@ -231,6 +233,13 @@ { "type": "null" } ] }, + "noExtraSemicolon": { + "description": "Typing mistakes and misunderstandings about where semicolons are required can lead to semicolons that are unnecessary. While not technically an error, extra semicolons can cause confusion when reading code.", + "anyOf": [ + { "$ref": "#/definitions/RuleConfiguration" }, + { "type": "null" } + ] + }, "noMultipleSpacesInRegularExpressionLiterals": { "description": "Disallow unclear usage of multiple space characters in regular expression literals", "anyOf": [ @@ -280,13 +289,6 @@ { "type": "null" } ] }, - "noUselessTypeConstraint": { - "description": "Disallow using any or unknown as type constraint.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "noWith": { "description": "Disallow with statements in non-strict contexts.", "anyOf": [ @@ -321,20 +323,6 @@ } } }, - "ComplexityOptions": { - "description": "Options for the rule `noNestedModuleImports`.", - "type": "object", - "required": ["maxAllowedComplexity"], - "properties": { - "maxAllowedComplexity": { - "description": "The maximum complexity score that we allow. Anything higher is considered excessive.", - "type": "integer", - "format": "uint8", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, "Correctness": { "description": "A list of rules that belong to this group", "type": "object", @@ -379,7 +367,7 @@ ] }, "noInnerDeclarations": { - "description": "Disallow function and var declarations that are accessible outside their block.", + "description": "Disallow function and var declarations in nested blocks.", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -393,7 +381,7 @@ ] }, "noNewSymbol": { - "description": "Disallow new operators with the Symbol object.", + "description": "Disallow new operators with the Symbol object", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -435,7 +423,7 @@ ] }, "noUndeclaredVariables": { - "description": "Prevents the usage of variables that haven't been declared inside the document.", + "description": "Prevents the usage of variables that haven't been declared inside the document", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -524,22 +512,6 @@ } } }, - "EnumMemberCase": { - "description": "Supported cases for TypeScript `enum` member names.", - "oneOf": [ - { - "description": "PascalCase", - "type": "string", - "enum": ["PascalCase"] - }, - { - "description": "CONSTANT_CASE", - "type": "string", - "enum": ["CONSTANT_CASE"] - }, - { "description": "camelCase", "type": "string", "enum": ["camelCase"] } - ] - }, "FilesConfiguration": { "description": "The configuration of the filesystem", "type": "object", @@ -548,10 +520,6 @@ "description": "A list of Unix shell style patterns. Rome tools will ignore files/folders that will match these patterns.", "anyOf": [{ "$ref": "#/definitions/StringSet" }, { "type": "null" }] }, - "ignoreUnknown": { - "description": "Tells Rome to not emit diagnostics when handling files that doesn't know", - "type": ["boolean", "null"] - }, "maxSize": { "description": "The maximum allowed size for source code files in bytes. Files above this limit will be ignored for performance reason. Defaults to 1 MiB", "default": null, @@ -563,7 +531,6 @@ "additionalProperties": false }, "FormatterConfiguration": { - "description": "Options applied to the formatter", "type": "object", "properties": { "enabled": { "default": true, "type": ["boolean", "null"] }, @@ -599,39 +566,6 @@ }, "additionalProperties": false }, - "Hooks": { - "type": "object", - "required": ["name"], - "properties": { - "closureIndex": { - "description": "The \"position\" of the closure function, starting from zero.\n\n### Example", - "type": ["integer", "null"], - "format": "uint", - "minimum": 0.0 - }, - "dependenciesIndex": { - "description": "The \"position\" of the array of dependencies, starting from zero.", - "type": ["integer", "null"], - "format": "uint", - "minimum": 0.0 - }, - "name": { "description": "The name of the hook", "type": "string" } - }, - "additionalProperties": false - }, - "HooksOptions": { - "description": "Options for the rule `useExhaustiveDependencies` and `useHookAtTopLevel`", - "type": "object", - "required": ["hooks"], - "properties": { - "hooks": { - "description": "List of safe hooks", - "type": "array", - "items": { "$ref": "#/definitions/Hooks" } - } - }, - "additionalProperties": false - }, "JavascriptConfiguration": { "type": "object", "properties": { @@ -650,12 +584,6 @@ { "$ref": "#/definitions/JavascriptOrganizeImports" }, { "type": "null" } ] - }, - "parser": { - "anyOf": [ - { "$ref": "#/definitions/JavascriptParser" }, - { "type": "null" } - ] } }, "additionalProperties": false @@ -663,19 +591,9 @@ "JavascriptFormatter": { "type": "object", "properties": { - "arrowParentheses": { - "description": "Whether to add non-necessary parentheses to arrow functions. Defaults to \"always\".", - "anyOf": [ - { "$ref": "#/definitions/ArrowParentheses" }, - { "type": "null" } - ] - }, - "jsxQuoteStyle": { - "description": "The style for JSX quotes. Defaults to double.", - "anyOf": [{ "$ref": "#/definitions/QuoteStyle" }, { "type": "null" }] - }, "quoteProperties": { "description": "When properties in objects are quoted. Defaults to asNeeded.", + "default": null, "anyOf": [ { "$ref": "#/definitions/QuoteProperties" }, { "type": "null" } @@ -683,14 +601,17 @@ }, "quoteStyle": { "description": "The style for quotes. Defaults to double.", + "default": null, "anyOf": [{ "$ref": "#/definitions/QuoteStyle" }, { "type": "null" }] }, "semicolons": { "description": "Whether the formatter prints semicolons for all statements or only in for statements where it is necessary because of ASI.", + "default": null, "anyOf": [{ "$ref": "#/definitions/Semicolons" }, { "type": "null" }] }, "trailingComma": { "description": "Print trailing commas wherever possible in multi-line comma-separated syntactic structures. Defaults to \"all\".", + "default": null, "anyOf": [ { "$ref": "#/definitions/TrailingComma" }, { "type": "null" } @@ -703,12 +624,13 @@ "type": "object", "additionalProperties": false }, - "JavascriptParser": { + "JsonConfiguration": { "type": "object", "properties": { - "unsafeParameterDecoratorsEnabled": { - "description": "It enables the experimental and unsafe parsing of parameter decorators\n\nThese decorators belong to an old proposal, and they are subject to change.", - "type": ["boolean", "null"] + "allow_comments": { + "type": ["array", "null"], + "items": { "type": "string" }, + "uniqueItems": true } }, "additionalProperties": false @@ -739,21 +661,6 @@ }, "additionalProperties": false }, - "NamingConventionOptions": { - "description": "Rule's options.", - "type": "object", - "properties": { - "enumMemberCase": { - "description": "Allowed cases for _TypeScript_ `enum` member names.", - "allOf": [{ "$ref": "#/definitions/EnumMemberCase" }] - }, - "strictCase": { - "description": "If `false`, then consecutive uppercase are allowed in _camel_ and _pascal_ cases. This does not affect other [Case].", - "type": "boolean" - } - }, - "additionalProperties": false - }, "Nursery": { "description": "A list of rules that belong to this group", "type": "object", @@ -777,7 +684,7 @@ ] }, "noBannedTypes": { - "description": "Disallow primitive type aliases and misleading types.", + "description": "Disallow certain types.", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -804,20 +711,6 @@ { "type": "null" } ] }, - "noControlCharactersInRegex": { - "description": "Prevents from having control characters and some escape sequences that match control characters in regular expressions.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "noDuplicateJsonKeys": { - "description": "Disallow two keys with the same name inside a JSON object.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "noDuplicateJsxProps": { "description": "Prevents JSX properties to be assigned multiple times.", "anyOf": [ @@ -825,20 +718,6 @@ { "type": "null" } ] }, - "noExcessiveComplexity": { - "description": "Disallow functions that exceed a given complexity score.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "noFallthroughSwitchClause": { - "description": "Disallow fallthrough of switch clauses.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "noForEach": { "description": "Prefer for...of statement instead of Array.forEach.", "anyOf": [ @@ -846,20 +725,6 @@ { "type": "null" } ] }, - "noGlobalIsFinite": { - "description": "Use Number.isFinite instead of global isFinite.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "noGlobalIsNan": { - "description": "Use Number.isNaN instead of global isNaN.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "noNoninteractiveTabindex": { "description": "Enforce that tabIndex is not assigned to non-interactive HTML elements.", "anyOf": [ @@ -867,13 +732,6 @@ { "type": "null" } ] }, - "noNonoctalDecimalEscape": { - "description": "Disallow \\8 and \\9 escape sequences in string literals.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "noRedundantRoles": { "description": "Enforce explicit role property is not the same as implicit/default role property on an element.", "anyOf": [ @@ -888,27 +746,6 @@ { "type": "null" } ] }, - "noStaticOnlyClass": { - "description": "This rule reports when a class has no non-static members, such as for a class used exclusively as a static namespace.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "noUselessEmptyExport": { - "description": "Disallow empty exports that don't change anything in a module file.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "noVoid": { - "description": "Disallow the use of void operators, which is not a familiar operator.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "recommended": { "description": "It enables the recommended rules for this group", "type": ["boolean", "null"] @@ -920,13 +757,6 @@ { "type": "null" } ] }, - "useArrowFunction": { - "description": "Use arrow functions over function expressions.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "useCamelCase": { "description": "Enforce camel case naming convention.", "anyOf": [ @@ -962,13 +792,6 @@ { "type": "null" } ] }, - "useIsArray": { - "description": "Use Array.isArray() instead of instanceof Array.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, "useIsNan": { "description": "Require calls to isNaN() when checking for NaN.", "anyOf": [ @@ -989,20 +812,6 @@ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } ] - }, - "useNamingConvention": { - "description": "Enforce naming conventions for everything across a codebase.", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] - }, - "useSimpleNumberKeys": { - "description": "Disallow number literal object member names which are not base10 or uses underscore as separator", - "anyOf": [ - { "$ref": "#/definitions/RuleConfiguration" }, - { "type": "null" } - ] } } }, @@ -1048,23 +857,6 @@ { "description": "Space", "type": "string", "enum": ["space"] } ] }, - "PossibleOptions": { - "anyOf": [ - { - "description": "Options for `noExcessiveComplexity` rule", - "allOf": [{ "$ref": "#/definitions/ComplexityOptions" }] - }, - { - "description": "Options for `useExhaustiveDependencies` and `useHookAtTopLevel` rule", - "allOf": [{ "$ref": "#/definitions/HooksOptions" }] - }, - { - "description": "Options for `useNamingConvention` rule", - "allOf": [{ "$ref": "#/definitions/NamingConventionOptions" }] - }, - { "description": "No options available", "type": "null" } - ] - }, "QuoteProperties": { "type": "string", "enum": ["asNeeded", "preserve"] }, "QuoteStyle": { "type": "string", "enum": ["double", "single"] }, "RuleConfiguration": { @@ -1079,15 +871,10 @@ }, "RuleWithOptions": { "type": "object", - "required": ["level"], + "required": ["level", "options"], "properties": { "level": { "$ref": "#/definitions/RulePlainConfiguration" }, - "options": { - "anyOf": [ - { "$ref": "#/definitions/PossibleOptions" }, - { "type": "null" } - ] - } + "options": true }, "additionalProperties": false }, @@ -1281,7 +1068,7 @@ ] }, "useDefaultParameterLast": { - "description": "Enforce default function parameters and optional function parameters to be last.", + "description": "Enforce default function parameters and optional parameters to be last.", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } @@ -1620,7 +1407,7 @@ ] }, "VcsConfiguration": { - "description": "Set of properties to integrate Rome with a VCS software.", + "description": "Set of properties to configure the integration with the VCS", "type": "object", "properties": { "clientKind": { @@ -1635,7 +1422,7 @@ "type": ["boolean", "null"] }, "root": { - "description": "The folder where Rome should check for VCS files. By default, Rome will use the same folder where `rome.json` was found.\n\nIf Rome can't find the configuration, it will attempt to use the current working directory. If no current working directory can't be found, Rome won't use the VCS integration, and a diagnostic will be emitted", + "description": "The folder where Rome should check for VCS files. By default, Rome will use the same folder where `rome.json` was found.\n\nIf Rome can't fine the configuration, it will attempt to use the current working directory. If no current working directory can't be found, Rome won't use the VCS integration.", "type": ["string", "null"] }, "useIgnoreFile": { From a50910ef423d1d81e71b2c82aac783c006d69dd4 Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Tue, 18 Apr 2023 01:06:25 +0800 Subject: [PATCH 04/19] =?UTF-8?q?chore:=20=F0=9F=A4=96=20lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/rome_service/src/configuration/parse/json.rs | 2 +- .../parse/json/{json.rs => json_visitor.rs} | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) rename crates/rome_service/src/configuration/parse/json/{json.rs => json_visitor.rs} (79%) diff --git a/crates/rome_service/src/configuration/parse/json.rs b/crates/rome_service/src/configuration/parse/json.rs index 92910f05183..e404b80fef5 100644 --- a/crates/rome_service/src/configuration/parse/json.rs +++ b/crates/rome_service/src/configuration/parse/json.rs @@ -5,7 +5,7 @@ mod configuration; mod files; mod formatter; mod javascript; -mod json; +mod json_visitor; mod linter; mod organize_imports; mod rules; diff --git a/crates/rome_service/src/configuration/parse/json/json.rs b/crates/rome_service/src/configuration/parse/json/json_visitor.rs similarity index 79% rename from crates/rome_service/src/configuration/parse/json/json.rs rename to crates/rome_service/src/configuration/parse/json/json_visitor.rs index 26a3c294db8..a05a615100a 100644 --- a/crates/rome_service/src/configuration/parse/json/json.rs +++ b/crates/rome_service/src/configuration/parse/json/json_visitor.rs @@ -25,12 +25,9 @@ impl VisitNode for JsonConfiguration { let (name, value) = self.get_key_and_value(key, value, diagnostics)?; let name_text = name.text(); - match name_text { - "allowComments" => { - let glob_array = self.map_to_index_set_string(&value, name_text, diagnostics)?; - self.allow_comments = Some(glob_array); - } - _ => {} + if let "allowComments" = name_text { + let glob_array = self.map_to_index_set_string(&value, name_text, diagnostics)?; + self.allow_comments = Some(glob_array); } Some(()) From 77939fa88420b70c40be46f3046e9cff461da577 Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Sat, 22 Apr 2023 12:51:30 +0800 Subject: [PATCH 05/19] =?UTF-8?q?chore:=20=F0=9F=A4=96=20update=20codegen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/rome_js_unicode_table/src/tables.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/rome_js_unicode_table/src/tables.rs b/crates/rome_js_unicode_table/src/tables.rs index 3ed00b03214..863365853a9 100644 --- a/crates/rome_js_unicode_table/src/tables.rs +++ b/crates/rome_js_unicode_table/src/tables.rs @@ -787,9 +787,7 @@ pub mod derived_property { ('𱍐', '𲎯'), ('\u{e0100}', '\u{e01ef}'), ]; - pub fn ID_Continue(c: char) -> bool { - super::bsearch_range_table(c, ID_Continue_table) - } + pub fn ID_Continue(c: char) -> bool { super::bsearch_range_table(c, ID_Continue_table) } pub const ID_Start_table: &[(char, char)] = &[ ('A', 'Z'), ('a', 'z'), @@ -1451,7 +1449,5 @@ pub mod derived_property { ('𰀀', '𱍊'), ('𱍐', '𲎯'), ]; - pub fn ID_Start(c: char) -> bool { - super::bsearch_range_table(c, ID_Start_table) - } + pub fn ID_Start(c: char) -> bool { super::bsearch_range_table(c, ID_Start_table) } } From 9e5d51f9e3c8a8219fb4a4cfdc7973a2fa60caad Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Thu, 4 May 2023 00:02:26 +0800 Subject: [PATCH 06/19] =?UTF-8?q?chore:=20=F0=9F=A4=96=20pass=20all=20test?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/rome_cli/src/execute/migrate.rs | 3 +- crates/rome_cli/tests/commands/init.rs | 9 +- crates/rome_cli/tests/snap_test.rs | 4 +- crates/rome_deserialize/src/json.rs | 83 +-------- crates/rome_json_formatter/src/lib.rs | 6 +- crates/rome_json_formatter/tests/language.rs | 13 +- .../rome_json_formatter/tests/quick_test.rs | 4 +- crates/rome_json_parser/src/lib.rs | 16 +- crates/rome_json_parser/src/parser.rs | 9 +- crates/rome_json_parser/tests/spec_test.rs | 4 +- crates/rome_migrate/src/lib.rs | 4 +- crates/rome_service/src/configuration/json.rs | 10 +- crates/rome_service/src/configuration/mod.rs | 12 +- .../configuration/parse/json/json_visitor.rs | 2 +- .../src/configuration/string_set.rs | 6 + crates/rome_service/src/file_handlers/json.rs | 151 +++------------- xtask/bench/src/language.rs | 43 ++--- xtask/lintdoc/src/main.rs | 171 ++++-------------- 18 files changed, 155 insertions(+), 395 deletions(-) diff --git a/crates/rome_cli/src/execute/migrate.rs b/crates/rome_cli/src/execute/migrate.rs index 513d4ad8551..59bcc62a29d 100644 --- a/crates/rome_cli/src/execute/migrate.rs +++ b/crates/rome_cli/src/execute/migrate.rs @@ -3,6 +3,7 @@ use crate::{CliDiagnostic, CliSession}; use rome_console::{markup, ConsoleExt}; use rome_diagnostics::{category, PrintDiagnostic}; use rome_fs::OpenOptions; +use rome_json_parser::JsonParserConfig; use rome_json_syntax::JsonRoot; use rome_migrate::{migrate_configuration, ControlFlow}; use rome_rowan::AstNode; @@ -26,7 +27,7 @@ pub(crate) fn run( fs.open_with_options(configuration_path.as_path(), open_options)?; let mut configuration_content = String::new(); configuration_file.read_to_string(&mut configuration_content)?; - let parsed = rome_json_parser::parse_json(&configuration_content); + let parsed = rome_json_parser::parse_json(&configuration_content, JsonParserConfig::default()); let mut errors = 0; let mut tree = parsed.tree(); let mut actions = Vec::new(); diff --git a/crates/rome_cli/tests/commands/init.rs b/crates/rome_cli/tests/commands/init.rs index fd217a937b1..2b5dc7fbb7c 100644 --- a/crates/rome_cli/tests/commands/init.rs +++ b/crates/rome_cli/tests/commands/init.rs @@ -5,7 +5,7 @@ use bpaf::Args; use rome_console::BufferConsole; use rome_fs::{FileSystemExt, MemoryFileSystem}; use rome_json_formatter::context::JsonFormatOptions; -use rome_json_parser::parse_json; +use rome_json_parser::{parse_json, JsonParserConfig}; use rome_service::DynRef; use std::path::Path; @@ -52,7 +52,7 @@ fn creates_config_file() { let mut content = String::new(); file.read_to_string(&mut content) .expect("failed to read file from memory FS"); - let parsed = parse_json(CONFIG_INIT_DEFAULT); + let parsed = parse_json(CONFIG_INIT_DEFAULT, JsonParserConfig::default()); let formatted = rome_json_formatter::format_node(JsonFormatOptions::default(), &parsed.syntax()) .expect("valid format document") @@ -95,7 +95,10 @@ fn creates_config_file_when_rome_installed_via_package_manager() { let mut content = String::new(); file.read_to_string(&mut content) .expect("failed to read file from memory FS"); - let parsed = parse_json(CONFIG_INIT_DEFAULT_WHEN_INSTALLED); + let parsed = parse_json( + CONFIG_INIT_DEFAULT_WHEN_INSTALLED, + JsonParserConfig::default(), + ); let formatted = rome_json_formatter::format_node(JsonFormatOptions::default(), &parsed.syntax()) .expect("valid format document") diff --git a/crates/rome_cli/tests/snap_test.rs b/crates/rome_cli/tests/snap_test.rs index 3807271d174..ac0cf74d7f1 100644 --- a/crates/rome_cli/tests/snap_test.rs +++ b/crates/rome_cli/tests/snap_test.rs @@ -7,7 +7,7 @@ use rome_formatter::IndentStyle; use rome_fs::{FileSystemExt, MemoryFileSystem}; use rome_json_formatter::context::JsonFormatOptions; use rome_json_formatter::format_node; -use rome_json_parser::parse_json; +use rome_json_parser::{parse_json, JsonParserConfig}; use std::borrow::Cow; use std::collections::BTreeMap; use std::env::{current_exe, temp_dir}; @@ -49,7 +49,7 @@ impl CliSnapshot { let mut content = String::new(); if let Some(configuration) = &self.configuration { - let parsed = parse_json(&redact_snapshot(configuration)); + let parsed = parse_json(&redact_snapshot(configuration), JsonParserConfig::default()); let formatted = format_node( JsonFormatOptions::default().with_indent_style(IndentStyle::Space(2)), &parsed.syntax(), diff --git a/crates/rome_deserialize/src/json.rs b/crates/rome_deserialize/src/json.rs index 10cf927b4ad..6805df5ea2c 100644 --- a/crates/rome_deserialize/src/json.rs +++ b/crates/rome_deserialize/src/json.rs @@ -15,7 +15,7 @@ pub trait JsonDeserialize: Sized { /// It accepts a JSON AST and a visitor. The visitor is the [default](Default) implementation of the data /// type that implements this trait. fn deserialize_from_ast( - root: &JsonRoot, + root: JsonRoot, visitor: &mut impl VisitJsonNode, diagnostics: &mut Vec, ) -> Option<()>; @@ -23,7 +23,7 @@ pub trait JsonDeserialize: Sized { impl JsonDeserialize for () { fn deserialize_from_ast( - _root: &JsonRoot, + _root: JsonRoot, _visitor: &mut impl VisitJsonNode, _diagnostics: &mut Vec, ) -> Option<()> { @@ -151,46 +151,6 @@ pub trait VisitJsonNode: VisitNode { } } - /// It attempts to map a [AnyJsonValue] to a [usize]. - /// - /// ## Errors - /// - /// It will fail if: - /// - `value` can't be cast to [JsonNumberValue] - /// - the value of the node can't be parsed to [usize] - fn map_to_usize( - &self, - value: &AnyJsonValue, - name: &str, - maximum: usize, - diagnostics: &mut Vec, - ) -> Option { - let value = JsonNumberValue::cast_ref(value.syntax()).or_else(|| { - diagnostics.push(DeserializationDiagnostic::new_incorrect_type_for_value( - name, - "number", - value.range(), - )); - None - })?; - let value = value.value_token().ok()?; - let result = value.text_trimmed().parse::().map_err(|err| { - emit_diagnostic_form_number( - err, - value.text_trimmed(), - value.text_trimmed_range(), - maximum, - ) - }); - match result { - Ok(number) => Some(number), - Err(err) => { - diagnostics.push(err); - None - } - } - } - /// It attempts to map a [AnyJsonValue] to a [u16]. /// /// ## Errors @@ -381,35 +341,6 @@ pub trait VisitJsonNode: VisitNode { } Some(()) } - - fn map_to_array( - &mut self, - value: &AnyJsonValue, - name: &str, - visitor: &mut V, - diagnostics: &mut Vec, - ) -> Option<()> - where - V: VisitNode, - { - let array = JsonArrayValue::cast_ref(value.syntax()).or_else(|| { - diagnostics.push(DeserializationDiagnostic::new_incorrect_type_for_value( - name, - "array", - value.range(), - )); - None - })?; - if array.elements().is_empty() { - return None; - } - for element in array.elements() { - let element = element.ok()?; - visitor.visit_array_member(element.syntax(), diagnostics); - } - - Some(()) - } } impl VisitJsonNode for () {} @@ -526,14 +457,14 @@ pub fn with_only_known_variants( /// use rome_deserialize::Deserialized; /// let mut output = Self::default(); /// let mut diagnostics = vec![]; -/// NewConfiguration::deserialize_from_ast(&root, &mut output, &mut diagnostics); +/// NewConfiguration::deserialize_from_ast(root, &mut output, &mut diagnostics); /// Deserialized::new(output, diagnostics) /// } /// } /// /// /// impl JsonDeserialize for NewConfiguration { -/// fn deserialize_from_ast(root: &JsonRoot, visitor: &mut impl VisitJsonNode, diagnostics: &mut Vec) -> Option<()> { +/// fn deserialize_from_ast(root: JsonRoot, visitor: &mut impl VisitJsonNode, diagnostics: &mut Vec) -> Option<()> { /// let object = root.value().ok()?; /// let object = object.as_json_object_value()?; /// for member in object.json_member_list() { @@ -560,8 +491,8 @@ where { let mut output = Output::default(); let mut diagnostics = vec![]; - let parse = parse_json(source); - Output::deserialize_from_ast(&parse.tree(), &mut output, &mut diagnostics); + let parse = parse_json(source, rome_json_parser::JsonParserConfig::default()); + Output::deserialize_from_ast(parse.tree(), &mut output, &mut diagnostics); let mut errors = parse .into_diagnostics() .into_iter() @@ -580,7 +511,7 @@ where } /// Attempts to deserialize a JSON AST, given the `Output`. -pub fn deserialize_from_json_ast(parse: &JsonRoot) -> Deserialized +pub fn deserialize_from_json_ast(parse: JsonRoot) -> Deserialized where Output: Default + VisitJsonNode + JsonDeserialize, { diff --git a/crates/rome_json_formatter/src/lib.rs b/crates/rome_json_formatter/src/lib.rs index 89070a1cc15..cddc546dc89 100644 --- a/crates/rome_json_formatter/src/lib.rs +++ b/crates/rome_json_formatter/src/lib.rs @@ -290,9 +290,11 @@ pub fn format_sub_tree(options: JsonFormatOptions, root: &JsonSyntaxNode) -> For #[cfg(test)] mod tests { + use std::default; + use crate::context::JsonFormatOptions; use crate::format_node; - use rome_json_parser::parse_json; + use rome_json_parser::{parse_json, JsonParserConfig}; #[test] fn smoke_test() { @@ -305,7 +307,7 @@ mod tests { "e": false } "#; - let parse = parse_json(src); + let parse = parse_json(src, JsonParserConfig::default()); let options = JsonFormatOptions::default(); let formatted = format_node(options, &parse.syntax()).unwrap(); assert_eq!( diff --git a/crates/rome_json_formatter/tests/language.rs b/crates/rome_json_formatter/tests/language.rs index 4c60441a30c..410fa000c3b 100644 --- a/crates/rome_json_formatter/tests/language.rs +++ b/crates/rome_json_formatter/tests/language.rs @@ -2,10 +2,10 @@ use rome_formatter::{FormatContext, FormatResult, Formatted, IndentStyle, LineWi use rome_formatter_test::TestFormatLanguage; use rome_json_formatter::context::{JsonFormatContext, JsonFormatOptions}; use rome_json_formatter::{format_node, format_range, JsonFormatLanguage}; -use rome_json_parser::parse_json; -use rome_json_syntax::{JsonFileSource, JsonLanguage}; +use rome_json_parser::{parse_json, JsonParserConfig}; +use rome_json_syntax::JsonLanguage; use rome_parser::AnyParse; -use rome_rowan::{FileSource, SyntaxNode, TextRange}; +use rome_rowan::{SyntaxNode, TextRange}; use serde::{Deserialize, Serialize}; #[derive(Default)] @@ -18,12 +18,7 @@ impl TestFormatLanguage for JsonTestFormatLanguage { type FormatLanguage = JsonFormatLanguage; fn parse(&self, text: &str) -> AnyParse { - let parse = parse_json(text); - AnyParse::new( - parse.syntax().as_send().unwrap(), - parse.into_diagnostics(), - JsonFileSource::json().as_any_file_source(), - ) + parse_json(text, JsonParserConfig::default()).into() } fn deserialize_format_options( diff --git a/crates/rome_json_formatter/tests/quick_test.rs b/crates/rome_json_formatter/tests/quick_test.rs index 7bd0a964782..ff8677caed8 100644 --- a/crates/rome_json_formatter/tests/quick_test.rs +++ b/crates/rome_json_formatter/tests/quick_test.rs @@ -1,7 +1,7 @@ use rome_formatter_test::check_reformat::CheckReformat; use rome_json_formatter::context::JsonFormatOptions; use rome_json_formatter::format_node; -use rome_json_parser::parse_json; +use rome_json_parser::{parse_json, JsonParse, JsonParserConfig}; mod language { include!("language.rs"); @@ -27,7 +27,7 @@ fn quick_test() { ] } "#; - let parse = parse_json(src); + let parse = parse_json(src, JsonParserConfig::default()); let options = JsonFormatOptions::default(); let result = format_node(options.clone(), &parse.syntax()) .unwrap() diff --git a/crates/rome_json_parser/src/lib.rs b/crates/rome_json_parser/src/lib.rs index 26b3dee8c77..6dd00d3a0de 100644 --- a/crates/rome_json_parser/src/lib.rs +++ b/crates/rome_json_parser/src/lib.rs @@ -2,6 +2,7 @@ use crate::parser::JsonParser; use crate::syntax::parse_root; +pub use parser::JsonParserConfig; use rome_json_factory::JsonSyntaxFactory; use rome_json_syntax::{JsonLanguage, JsonRoot, JsonSyntaxNode}; pub use rome_parser::prelude::*; @@ -17,15 +18,19 @@ mod token_source; pub(crate) type JsonLosslessTreeSink<'source> = LosslessTreeSink<'source, JsonLanguage, JsonSyntaxFactory>; -pub fn parse_json(source: &str) -> JsonParse { +pub fn parse_json(source: &str, config: JsonParserConfig) -> JsonParse { let mut cache = NodeCache::default(); - parse_json_with_cache(source, &mut cache) + parse_json_with_cache(source, &mut cache, config) } /// Parses the provided string as JSON program using the provided node cache. -pub fn parse_json_with_cache(source: &str, cache: &mut NodeCache) -> JsonParse { +pub fn parse_json_with_cache( + source: &str, + cache: &mut NodeCache, + config: JsonParserConfig, +) -> JsonParse { tracing::debug_span!("parse").in_scope(move || { - let mut parser = JsonParser::new(source); + let mut parser = JsonParser::new(source, config); parse_root(&mut parser); @@ -60,7 +65,8 @@ impl JsonParse { /// /// # fn main() -> Result<(), SyntaxError> { /// use rome_json_syntax::JsonSyntaxKind; - /// let parse = parse_json(r#"["a", 1]"#); + /// use rome_json_parser::JsonParserConfig; + /// let parse = parse_json(r#"["a", 1]"#, JsonParserConfig::default()); /// /// // Get the root value /// let root_value = parse.tree().value()?; diff --git a/crates/rome_json_parser/src/parser.rs b/crates/rome_json_parser/src/parser.rs index 870bc5273df..65c3d522a1b 100644 --- a/crates/rome_json_parser/src/parser.rs +++ b/crates/rome_json_parser/src/parser.rs @@ -9,13 +9,20 @@ use rome_parser::ParserContext; pub(crate) struct JsonParser<'source> { context: ParserContext, source: JsonTokenSource<'source>, + config: JsonParserConfig, +} + +#[derive(Default)] +pub struct JsonParserConfig { + allow_comments: bool, } impl<'source> JsonParser<'source> { - pub fn new(source: &'source str) -> Self { + pub fn new(source: &'source str, config: JsonParserConfig) -> Self { Self { context: ParserContext::default(), source: JsonTokenSource::from_str(source), + config, } } diff --git a/crates/rome_json_parser/tests/spec_test.rs b/crates/rome_json_parser/tests/spec_test.rs index 43486932118..af2a82a21fa 100644 --- a/crates/rome_json_parser/tests/spec_test.rs +++ b/crates/rome_json_parser/tests/spec_test.rs @@ -3,7 +3,7 @@ use rome_console::markup; use rome_diagnostics::display::PrintDiagnostic; use rome_diagnostics::termcolor; use rome_diagnostics::DiagnosticExt; -use rome_json_parser::parse_json; +use rome_json_parser::{parse_json, JsonParserConfig}; use rome_rowan::SyntaxKind; use std::fmt::Write; use std::fs; @@ -35,7 +35,7 @@ pub fn run(test_case: &str, _snapshot_name: &str, test_directory: &str, outcome: let content = fs::read_to_string(test_case_path) .expect("Expected test path to be a readable file in UTF8 encoding"); - let parsed = parse_json(&content); + let parsed = parse_json(&content, JsonParserConfig::default()); let formatted_ast = format!("{:#?}", parsed.tree()); let mut snapshot = String::new(); diff --git a/crates/rome_migrate/src/lib.rs b/crates/rome_migrate/src/lib.rs index 65953d6f527..5843bf034a5 100644 --- a/crates/rome_migrate/src/lib.rs +++ b/crates/rome_migrate/src/lib.rs @@ -97,7 +97,7 @@ where mod test { use crate::migrate_configuration; use rome_analyze::{ControlFlow, Never}; - use rome_json_parser::parse_json; + use rome_json_parser::{parse_json, JsonParserConfig}; use std::path::Path; #[test] @@ -105,7 +105,7 @@ mod test { fn smoke() { let source = r#"{ "something": "else" }"#; - let parsed = parse_json(source); + let parsed = parse_json(source, JsonParserConfig::default()); migrate_configuration(&parsed.tree().value().unwrap(), Path::new(""), |signal| { for action in signal.actions() { diff --git a/crates/rome_service/src/configuration/json.rs b/crates/rome_service/src/configuration/json.rs index f16d2c170f4..4dcc10cff84 100644 --- a/crates/rome_service/src/configuration/json.rs +++ b/crates/rome_service/src/configuration/json.rs @@ -1,12 +1,18 @@ +use std::str::FromStr; + +use bpaf::Bpaf; use indexmap::IndexSet; use serde::{Deserialize, Serialize}; +use serde_json::from_str; -#[derive(Default, Debug, Deserialize, Serialize, Eq, PartialEq)] +use super::StringSet; +#[derive(Default, Debug, Deserialize, Serialize, Eq, PartialEq, Clone, Bpaf)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[serde(default, deny_unknown_fields)] pub struct JsonConfiguration { #[serde(skip_serializing_if = "Option::is_none")] - pub allow_comments: Option>, + #[bpaf(hide)] + pub allow_comments: Option, } impl JsonConfiguration { diff --git a/crates/rome_service/src/configuration/mod.rs b/crates/rome_service/src/configuration/mod.rs index c5b5c1c2c03..bd411477603 100644 --- a/crates/rome_service/src/configuration/mod.rs +++ b/crates/rome_service/src/configuration/mod.rs @@ -16,8 +16,6 @@ pub mod diagnostics; pub mod formatter; mod generated; pub mod javascript; -mod javascript; -mod javascript; mod json; pub mod linter; mod merge; @@ -35,15 +33,14 @@ use crate::configuration::vcs::{vcs_configuration, VcsConfiguration}; use crate::settings::{LanguagesSettings, LinterSettings}; pub use formatter::{formatter_configuration, FormatterConfiguration, PlainIndentStyle}; pub use javascript::{javascript_configuration, JavascriptConfiguration, JavascriptFormatter}; +pub use json::{json_configuration, JsonConfiguration}; pub use linter::{linter_configuration, LinterConfiguration, RuleConfiguration, Rules}; use rome_analyze::{AnalyzerConfiguration, AnalyzerRules}; use rome_deserialize::json::deserialize_from_json_str; use rome_deserialize::Deserialized; use rome_js_analyze::metadata; use rome_json_formatter::context::JsonFormatOptions; -use rome_json_parser::parse_json; - -use self::json::JsonConfiguration; +use rome_json_parser::{parse_json, JsonParserConfig}; /// The configuration that is contained inside the file `rome.json` #[derive(Debug, Deserialize, Serialize, Clone, Bpaf)] @@ -86,8 +83,9 @@ pub struct Configuration { #[bpaf(external(javascript_configuration), optional)] pub javascript: Option, - /// Specific configuration for the JavaScript language + /// Specific configuration for the Json language #[serde(skip_serializing_if = "Option::is_none")] + #[bpaf(external(json_configuration), optional)] pub json: Option, } @@ -368,7 +366,7 @@ pub fn create_config( WorkspaceError::Configuration(ConfigurationDiagnostic::new_serialization_error()) })?; - let parsed = parse_json(&contents); + let parsed = parse_json(&contents, JsonParserConfig::default()); let formatted = rome_json_formatter::format_node(JsonFormatOptions::default(), &parsed.syntax())? .print() diff --git a/crates/rome_service/src/configuration/parse/json/json_visitor.rs b/crates/rome_service/src/configuration/parse/json/json_visitor.rs index a05a615100a..b1d12fc9fe0 100644 --- a/crates/rome_service/src/configuration/parse/json/json_visitor.rs +++ b/crates/rome_service/src/configuration/parse/json/json_visitor.rs @@ -27,7 +27,7 @@ impl VisitNode for JsonConfiguration { if let "allowComments" = name_text { let glob_array = self.map_to_index_set_string(&value, name_text, diagnostics)?; - self.allow_comments = Some(glob_array); + self.allow_comments = Some(glob_array.into()); } Some(()) diff --git a/crates/rome_service/src/configuration/string_set.rs b/crates/rome_service/src/configuration/string_set.rs index 1b09ad073f5..dbd5fd93138 100644 --- a/crates/rome_service/src/configuration/string_set.rs +++ b/crates/rome_service/src/configuration/string_set.rs @@ -104,3 +104,9 @@ impl FromStr for StringSet { Ok(StringSet::default()) } } + +impl From> for StringSet { + fn from(value: IndexSet) -> Self { + Self::new(value) + } +} diff --git a/crates/rome_service/src/file_handlers/json.rs b/crates/rome_service/src/file_handlers/json.rs index 222c195bb4e..168bc1ea938 100644 --- a/crates/rome_service/src/file_handlers/json.rs +++ b/crates/rome_service/src/file_handlers/json.rs @@ -1,5 +1,4 @@ use super::{ExtensionHandler, Mime}; -use crate::configuration::to_analyzer_configuration; use crate::file_handlers::{ AnalyzerCapabilities, Capabilities, FixAllParams, FormatterCapabilities, LintParams, LintResults, ParserCapabilities, @@ -12,26 +11,23 @@ use crate::workspace::{ FixFileResult, GetSyntaxTreeResult, OrganizeImportsResult, PullActionsResult, }; use crate::{Configuration, Rules, WorkspaceError}; -use rome_analyze::{AnalyzerOptions, ControlFlow, Never, RuleCategories}; use rome_deserialize::json::deserialize_from_json_ast; -use rome_diagnostics::{category, Diagnostic, DiagnosticExt, Severity}; +use rome_diagnostics::{Diagnostic, Severity}; use rome_formatter::{FormatError, Printed}; use rome_fs::{RomePath, CONFIG_NAME}; -use rome_json_analyze::analyze; use rome_json_formatter::context::JsonFormatOptions; use rome_json_formatter::format_node; -use rome_json_syntax::{JsonFileSource, JsonLanguage, JsonRoot, JsonSyntaxNode}; +use rome_json_parser::JsonParserConfig; +use rome_json_syntax::{JsonLanguage, JsonRoot, JsonSyntaxNode}; use rome_parser::AnyParse; -use rome_rowan::{AstNode, FileSource, NodeCache}; +use rome_rowan::{AstNode, NodeCache}; use rome_rowan::{TextRange, TextSize, TokenAtOffset}; -use std::path::PathBuf; impl Language for JsonLanguage { type FormatterSettings = (); type LinterSettings = (); type FormatOptions = JsonFormatOptions; type OrganizeImportsSettings = (); - type ParserSettings = (); fn lookup_settings(language: &LanguagesSettings) -> &LanguageSettings { &language.json @@ -88,23 +84,9 @@ impl ExtensionHandler for JsonFileHandler { } } -fn parse( - _: &RomePath, - _: LanguageId, - text: &str, - _: SettingsHandle, - cache: &mut NodeCache, -) -> AnyParse { - let parse = rome_json_parser::parse_json_with_cache(text, cache); - let root = parse.syntax(); - let diagnostics = parse.into_diagnostics(); - - AnyParse::new( - // SAFETY: the parser should always return a root node - root.as_send().unwrap(), - diagnostics, - JsonFileSource::json().as_any_file_source(), - ) +fn parse(_: &RomePath, _: LanguageId, text: &str, cache: &mut NodeCache) -> AnyParse { + let parse = rome_json_parser::parse_json_with_cache(text, cache, JsonParserConfig::default()); + AnyParse::from(parse) } fn debug_syntax_tree(_rome_path: &RomePath, parse: AnyParse) -> GetSyntaxTreeResult { @@ -149,7 +131,6 @@ fn format( } } -#[tracing::instrument(level = "debug", skip(parse))] fn format_range( rome_path: &RomePath, parse: AnyParse, @@ -163,7 +144,6 @@ fn format_range( Ok(printed) } -#[tracing::instrument(level = "debug", skip(parse))] fn format_on_type( rome_path: &RomePath, parse: AnyParse, @@ -201,96 +181,35 @@ fn format_on_type( } fn lint(params: LintParams) -> LintResults { - tracing::debug_span!("lint").in_scope(move || { - let root: JsonRoot = params.parse.tree(); - let mut diagnostics = params.parse.into_diagnostics(); - - // if we're parsing the `rome.json` file, we deserialize it, so we can emit diagnostics for - // malformed configuration - if params.path.ends_with(CONFIG_NAME) { - let deserialized = deserialize_from_json_ast::(&root); - diagnostics.extend( - deserialized - .into_diagnostics() - .into_iter() - .map(rome_diagnostics::serde::Diagnostic::new) - .collect::>(), - ); - } - - let mut diagnostic_count = diagnostics.len() as u64; - let mut errors = diagnostics - .iter() - .filter(|diag| diag.severity() <= Severity::Error) - .count(); - - let skipped_diagnostics = diagnostic_count - diagnostics.len() as u64; - - let has_lint = params.filter.categories.contains(RuleCategories::LINT); - let analyzer_options = - compute_analyzer_options(¶ms.settings, PathBuf::from(params.path.as_path())); - - let (_, analyze_diagnostics) = analyze( - &root.value().unwrap(), - params.filter, - &analyzer_options, - |signal| { - if let Some(mut diagnostic) = signal.diagnostic() { - // Do not report unused suppression comment diagnostics if this is a syntax-only analyzer pass - if !has_lint && diagnostic.category() == Some(category!("suppressions/unused")) - { - return ControlFlow::::Continue(()); - } - - diagnostic_count += 1; - - // We do now check if the severity of the diagnostics should be changed. - // The configuration allows to change the severity of the diagnostics emitted by rules. - let severity = diagnostic - .category() - .filter(|category| category.name().starts_with("lint/")) - .map(|category| { - params - .rules - .and_then(|rules| rules.get_severity_from_code(category)) - .unwrap_or(Severity::Warning) - }) - .unwrap_or_else(|| diagnostic.severity()); - - if severity <= Severity::Error { - errors += 1; - } - - if diagnostic_count <= params.max_diagnostics { - for action in signal.actions() { - if !action.is_suppression() { - diagnostic = diagnostic.add_code_suggestion(action.into()); - } - } - - let error = diagnostic.with_severity(severity); - - diagnostics.push(rome_diagnostics::serde::Diagnostic::new(error)); - } - } - - ControlFlow::::Continue(()) - }, - ); + let root: JsonRoot = params.parse.tree(); + let mut diagnostics = params.parse.into_diagnostics(); + // if we're parsing the `rome.json` file, we deserialize it, so we can emit diagnostics for + // malformed configuration + if params.path.ends_with(CONFIG_NAME) { + let deserialized = deserialize_from_json_ast::(root); diagnostics.extend( - analyze_diagnostics + deserialized + .into_diagnostics() .into_iter() .map(rome_diagnostics::serde::Diagnostic::new) .collect::>(), ); + } - LintResults { - diagnostics, - errors, - skipped_diagnostics, - } - }) + let diagnostic_count = diagnostics.len() as u64; + let errors = diagnostics + .iter() + .filter(|diag| diag.severity() <= Severity::Error) + .count(); + + let skipped_diagnostics = diagnostic_count - diagnostics.len() as u64; + + LintResults { + diagnostics, + errors, + skipped_diagnostics, + } } fn code_actions( @@ -320,15 +239,3 @@ fn organize_imports(parse: AnyParse) -> Result().to_string(), }) } - -fn compute_analyzer_options(settings: &SettingsHandle, file_path: PathBuf) -> AnalyzerOptions { - let configuration = to_analyzer_configuration( - settings.as_ref().linter(), - &settings.as_ref().languages, - |_| vec![], - ); - AnalyzerOptions { - configuration, - file_path, - } -} diff --git a/xtask/bench/src/language.rs b/xtask/bench/src/language.rs index 124d90bc350..b2b1cfe5974 100644 --- a/xtask/bench/src/language.rs +++ b/xtask/bench/src/language.rs @@ -4,21 +4,21 @@ use rome_analyze::{AnalysisFilter, AnalyzerOptions, ControlFlow, Never, RuleCate use rome_formatter::{FormatResult, Formatted, PrintResult, Printed}; use rome_js_analyze::analyze; use rome_js_formatter::context::{JsFormatContext, JsFormatOptions}; -use rome_js_parser::JsParserOptions; -use rome_js_syntax::{AnyJsRoot, JsFileSource, JsSyntaxNode}; +use rome_js_syntax::{AnyJsRoot, JsSyntaxNode, SourceType}; use rome_json_formatter::context::{JsonFormatContext, JsonFormatOptions}; +use rome_json_parser::JsonParserConfig; use rome_json_syntax::JsonSyntaxNode; use rome_parser::prelude::ParseDiagnostic; use rome_rowan::NodeCache; pub enum Parse<'a> { - JavaScript(JsFileSource, &'a str), + JavaScript(SourceType, &'a str), Json(&'a str), } impl<'a> Parse<'a> { pub fn try_from_case(case: &TestCase) -> Option { - match JsFileSource::try_from(case.path()) { + match SourceType::try_from(case.path()) { Ok(source_type) => Some(Parse::JavaScript(source_type, case.code())), Err(_) => match case.extension() { "json" => Some(Parse::Json(case.code())), @@ -29,36 +29,33 @@ impl<'a> Parse<'a> { pub fn parse(&self) -> Parsed { match self { - Parse::JavaScript(source_type, code) => Parsed::JavaScript( - rome_js_parser::parse( - code, - *source_type, - JsParserOptions::default().with_parse_class_parameter_decorators(), - ), - *source_type, - ), - Parse::Json(code) => Parsed::Json(rome_json_parser::parse_json(code)), + Parse::JavaScript(source_type, code) => { + Parsed::JavaScript(rome_js_parser::parse(code, *source_type), *source_type) + } + Parse::Json(code) => Parsed::Json(rome_json_parser::parse_json( + code, + JsonParserConfig::default(), + )), } } pub fn parse_with_cache(&self, cache: &mut NodeCache) -> Parsed { match self { Parse::JavaScript(source_type, code) => Parsed::JavaScript( - rome_js_parser::parse_js_with_cache( - code, - *source_type, - JsParserOptions::default().with_parse_class_parameter_decorators(), - cache, - ), + rome_js_parser::parse_js_with_cache(code, *source_type, cache), *source_type, ), - Parse::Json(code) => Parsed::Json(rome_json_parser::parse_json_with_cache(code, cache)), + Parse::Json(code) => Parsed::Json(rome_json_parser::parse_json_with_cache( + code, + cache, + JsonParserConfig::default(), + )), } } } pub enum Parsed { - JavaScript(rome_js_parser::Parse, JsFileSource), + JavaScript(rome_js_parser::Parse, SourceType), Json(rome_json_parser::JsonParse), } @@ -88,7 +85,7 @@ impl Parsed { } pub enum FormatNode { - JavaScript(JsSyntaxNode, JsFileSource), + JavaScript(JsSyntaxNode, SourceType), Json(JsonSyntaxNode), } @@ -134,7 +131,7 @@ impl Analyze { ..AnalysisFilter::default() }; let options = AnalyzerOptions::default(); - analyze(root, filter, &options, JsFileSource::default(), |event| { + analyze(root, filter, &options, SourceType::default(), |event| { black_box(event.diagnostic()); black_box(event.actions()); ControlFlow::::Continue(()) diff --git a/xtask/lintdoc/src/main.rs b/xtask/lintdoc/src/main.rs index e443198c556..12c0d480457 100644 --- a/xtask/lintdoc/src/main.rs +++ b/xtask/lintdoc/src/main.rs @@ -10,9 +10,9 @@ use rome_console::{ }; use rome_diagnostics::termcolor::NoColor; use rome_diagnostics::{Diagnostic, DiagnosticExt, PrintDiagnostic}; -use rome_js_parser::JsParserOptions; -use rome_js_syntax::{JsFileSource, JsLanguage, Language, LanguageVariant, ModuleKind}; -use rome_json_syntax::JsonLanguage; +use rome_js_analyze::{analyze, visit_registry}; +use rome_js_syntax::{JsLanguage, Language, LanguageVariant, ModuleKind, SourceType}; +use rome_json_parser::JsonParserConfig; use rome_service::settings::WorkspaceSettings; use std::{ collections::BTreeMap, @@ -26,9 +26,8 @@ use xtask::{glue::fs2, *}; fn main() -> Result<()> { let root = project_root().join("website/src/pages/lint/rules"); - let reference_groups = project_root().join("website/src/components/generated/Groups.astro"); - let reference_number_of_rules = - project_root().join("website/src/components/generated/NumberOfRules.astro"); + let reference_groups = project_root().join("website/src/components/reference/Groups.astro"); + // Clear the rules directory ignoring "not found" errors if let Err(err) = fs2::remove_dir_all(&root) { let is_not_found = err @@ -66,7 +65,6 @@ fn main() -> Result<()> { #[derive(Default)] struct LintRulesVisitor { groups: BTreeMap<&'static str, BTreeMap<&'static str, RuleMetadata>>, - number_or_rules: u16, } impl RegistryVisitor for LintRulesVisitor { @@ -82,28 +80,6 @@ fn main() -> Result<()> { R::Query: Queryable, ::Output: Clone, { - self.number_or_rules += 1; - self.groups - .entry(::NAME) - .or_insert_with(BTreeMap::new) - .insert(R::METADATA.name, R::METADATA); - } - } - - impl RegistryVisitor for LintRulesVisitor { - fn record_category>(&mut self) { - if matches!(C::CATEGORY, RuleCategory::Lint) { - C::record_groups(self); - } - } - - fn record_rule(&mut self) - where - R: Rule + 'static, - R::Query: Queryable, - ::Output: Clone, - { - self.number_or_rules += 1; self.groups .entry(::NAME) .or_insert_with(BTreeMap::new) @@ -112,13 +88,9 @@ fn main() -> Result<()> { } let mut visitor = LintRulesVisitor::default(); - rome_js_analyze::visit_registry(&mut visitor); - rome_json_analyze::visit_registry(&mut visitor); + visit_registry(&mut visitor); - let LintRulesVisitor { - mut groups, - number_or_rules, - } = visitor; + let LintRulesVisitor { mut groups } = visitor; let nursery_rules = groups .remove("nursery") @@ -147,14 +119,8 @@ fn main() -> Result<()> { ); } - let number_of_rules_buffer = format!( - "\n \ -

Rome's linter has a total of {} rules

", - number_or_rules - ); fs2::write(root.join("index.mdx"), index)?; fs2::write(reference_groups, reference_buffer)?; - fs2::write(reference_number_of_rules, number_of_rules_buffer)?; Ok(()) } @@ -436,14 +402,13 @@ fn parse_documentation( } enum BlockType { - Js(JsFileSource), + Js(SourceType), Json, } struct CodeBlockTest { block_type: BlockType, expect_diagnostic: bool, - ignore: bool, } impl FromStr for CodeBlockTest { @@ -458,27 +423,25 @@ impl FromStr for CodeBlockTest { .filter(|token| !token.is_empty()); let mut test = CodeBlockTest { - block_type: BlockType::Js(JsFileSource::default()), + block_type: BlockType::Js(SourceType::default()), expect_diagnostic: false, - ignore: false, }; for token in tokens { match token { // Determine the language, using the same list of extensions as `compute_source_type_from_path_or_extension` "cjs" => { - test.block_type = BlockType::Js( - JsFileSource::js_module().with_module_kind(ModuleKind::Script), - ); + test.block_type = + BlockType::Js(SourceType::js_module().with_module_kind(ModuleKind::Script)); } "js" | "mjs" | "jsx" => { - test.block_type = BlockType::Js(JsFileSource::jsx()); + test.block_type = BlockType::Js(SourceType::jsx()); } "ts" | "mts" | "cts" => { - test.block_type = BlockType::Js(JsFileSource::ts()); + test.block_type = BlockType::Js(SourceType::ts()); } "tsx" => { - test.block_type = BlockType::Js(JsFileSource::tsx()); + test.block_type = BlockType::Js(SourceType::tsx()); } // Other attributes @@ -486,10 +449,6 @@ impl FromStr for CodeBlockTest { test.expect_diagnostic = true; } - "ignore" => { - test.ignore = true; - } - "json" => { test.block_type = BlockType::Json; } @@ -523,7 +482,6 @@ fn assert_lint( let mut write_diagnostic = |code: &str, diag: rome_diagnostics::Error| { let category = diag.category().map_or("", |code| code.name()); - Formatter::new(&mut write).write_markup(markup! { {PrintDiagnostic::verbose(&diag)} })?; @@ -570,12 +528,10 @@ fn assert_lint( diagnostic_count += 1; Ok(()) }; - if test.ignore { - return Ok(()); - } + match test.block_type { BlockType::Js(source_type) => { - let parse = rome_js_parser::parse(code, source_type, JsParserOptions::default()); + let parse = rome_js_parser::parse(code, source_type); if parse.has_errors() { for diag in parse.into_diagnostics() { @@ -596,39 +552,33 @@ fn assert_lint( }; let options = AnalyzerOptions::default(); - let (_, diagnostics) = rome_js_analyze::analyze( - &root, - filter, - &options, - source_type, - |signal| { - if let Some(mut diag) = signal.diagnostic() { - let category = diag.category().expect("linter diagnostic has no code"); - let severity = settings.get_severity_from_rule_code(category).expect( + let (_, diagnostics) = analyze(&root, filter, &options, source_type, |signal| { + if let Some(mut diag) = signal.diagnostic() { + let category = diag.category().expect("linter diagnostic has no code"); + let severity = settings.get_severity_from_rule_code(category).expect( "If you see this error, it means you need to run cargo codegen-configuration", ); - for action in signal.actions() { - if !action.is_suppression() { - diag = diag.add_code_suggestion(action.into()); - } + for action in signal.actions() { + if !action.is_suppression() { + diag = diag.add_code_suggestion(action.into()); } + } - let error = diag - .with_severity(severity) - .with_file_path(file.clone()) - .with_file_source_code(code); - let res = write_diagnostic(code, error); + let error = diag + .with_severity(severity) + .with_file_path(file.clone()) + .with_file_source_code(code); + let res = write_diagnostic(code, error); - // Abort the analysis on error - if let Err(err) = res { - return ControlFlow::Break(err); - } + // Abort the analysis on error + if let Err(err) = res { + return ControlFlow::Break(err); } + } - ControlFlow::Continue(()) - }, - ); + ControlFlow::Continue(()) + }); // Result is Some(_) if analysis aborted with an error for diagnostic in diagnostics { @@ -646,7 +596,7 @@ fn assert_lint( } } BlockType::Json => { - let parse = rome_json_parser::parse_json(code); + let parse = rome_json_parser::parse_json(code, JsonParserConfig::default()); if parse.has_errors() { for diag in parse.into_diagnostics() { @@ -655,55 +605,6 @@ fn assert_lint( .with_file_source_code(code); write_diagnostic(code, error)?; } - } else { - let root = parse.tree(); - - let settings = WorkspaceSettings::default(); - - let rule_filter = RuleFilter::Rule(group, rule); - let filter = AnalysisFilter { - enabled_rules: Some(slice::from_ref(&rule_filter)), - ..AnalysisFilter::default() - }; - - let options = AnalyzerOptions::default(); - let (_, diagnostics) = rome_json_analyze::analyze( - &root.value().unwrap(), - filter, - &options, - |signal| { - if let Some(mut diag) = signal.diagnostic() { - let category = diag.category().expect("linter diagnostic has no code"); - let severity = settings.get_severity_from_rule_code(category).expect( - "If you see this error, it means you need to run cargo codegen-configuration", - ); - - for action in signal.actions() { - if !action.is_suppression() { - diag = diag.add_code_suggestion(action.into()); - } - } - - let error = diag - .with_severity(severity) - .with_file_path(file.clone()) - .with_file_source_code(code); - let res = write_diagnostic(code, error); - - // Abort the analysis on error - if let Err(err) = res { - return ControlFlow::Break(err); - } - } - - ControlFlow::Continue(()) - }, - ); - - // Result is Some(_) if analysis aborted with an error - for diagnostic in diagnostics { - write_diagnostic(code, diagnostic)?; - } } } } From 8a2531e46dddde2e37220c2feca5d9399ead5d54 Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Thu, 4 May 2023 01:02:06 +0800 Subject: [PATCH 07/19] =?UTF-8?q?chore:=20=F0=9F=A4=96=20basic=20finish=20?= =?UTF-8?q?parse=20with=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/rome_json_parser/src/lexer/mod.rs | 29 ++++++++--- crates/rome_json_parser/src/parser.rs | 31 +++++++++-- crates/rome_json_parser/src/token_source.rs | 19 ++++++- .../json_test_suite/allow_comments/basic.json | 1 + .../allow_comments/basic.json.snap | 52 +++++++++++++++++++ crates/rome_json_parser/tests/spec_test.rs | 12 +++-- crates/rome_json_parser/tests/spec_tests.rs | 5 ++ crates/rome_json_syntax/src/lib.rs | 7 +++ crates/rome_service/src/configuration/json.rs | 4 -- 9 files changed, 138 insertions(+), 22 deletions(-) create mode 100644 crates/rome_json_parser/tests/json_test_suite/allow_comments/basic.json create mode 100644 crates/rome_json_parser/tests/json_test_suite/allow_comments/basic.json.snap diff --git a/crates/rome_json_parser/src/lexer/mod.rs b/crates/rome_json_parser/src/lexer/mod.rs index 95cc27c5362..3afe3af5f84 100644 --- a/crates/rome_json_parser/src/lexer/mod.rs +++ b/crates/rome_json_parser/src/lexer/mod.rs @@ -9,6 +9,8 @@ use rome_parser::diagnostic::ParseDiagnostic; use std::iter::FusedIterator; use std::ops::Add; +use crate::JsonParserConfig; + pub struct Token { kind: JsonSyntaxKind, range: TextRange, @@ -34,6 +36,7 @@ pub(crate) struct Lexer<'src> { position: usize, diagnostics: Vec, + config: JsonParserConfig, } impl<'src> Lexer<'src> { @@ -43,6 +46,7 @@ impl<'src> Lexer<'src> { source: string, position: 0, diagnostics: vec![], + config: JsonParserConfig::default(), } } @@ -695,10 +699,12 @@ impl<'src> Lexer<'src> { b'*' if self.peek_byte() == Some(b'/') => { self.advance(2); - self.diagnostics.push(ParseDiagnostic::new( - "JSON standard does not allow comments.", - start..self.text_position(), - )); + if !self.config.allow_comments { + self.diagnostics.push(ParseDiagnostic::new( + "JSON standard does not allow comments.", + start..self.text_position(), + )); + } if has_newline { return MULTILINE_COMMENT; @@ -739,16 +745,23 @@ impl<'src> Lexer<'src> { } } - self.diagnostics.push(ParseDiagnostic::new( - "JSON standard does not allow comments.", - start..self.text_position(), - )); + if !self.config.allow_comments { + self.diagnostics.push(ParseDiagnostic::new( + "JSON standard does not allow comments.", + start..self.text_position(), + )); + } COMMENT } _ => self.eat_unexpected_character(), } } + + pub(crate) fn with_config(mut self, config: JsonParserConfig) -> Self { + self.config = config; + self + } } impl Iterator for Lexer<'_> { diff --git a/crates/rome_json_parser/src/parser.rs b/crates/rome_json_parser/src/parser.rs index 65c3d522a1b..c5b0e7a79bf 100644 --- a/crates/rome_json_parser/src/parser.rs +++ b/crates/rome_json_parser/src/parser.rs @@ -1,6 +1,6 @@ use crate::token_source::JsonTokenSource; use rome_json_syntax::JsonSyntaxKind; -use rome_parser::diagnostic::merge_diagnostics; +use rome_parser::diagnostic::{expected_token, merge_diagnostics}; use rome_parser::event::Event; use rome_parser::prelude::*; use rome_parser::token_source::Trivia; @@ -12,16 +12,16 @@ pub(crate) struct JsonParser<'source> { config: JsonParserConfig, } -#[derive(Default)] +#[derive(Default, Debug, Clone, Copy)] pub struct JsonParserConfig { - allow_comments: bool, + pub allow_comments: bool, } impl<'source> JsonParser<'source> { pub fn new(source: &'source str, config: JsonParserConfig) -> Self { Self { context: ParserContext::default(), - source: JsonTokenSource::from_str(source), + source: JsonTokenSource::from_str(source, config), config, } } @@ -61,4 +61,27 @@ impl<'source> Parser for JsonParser<'source> { fn source_mut(&mut self) -> &mut Self::Source { &mut self.source } + + /// Try to eat a specific token kind, if the kind is not there then adds an error to the events stack. + fn expect(&mut self, kind: Self::Kind) -> bool { + if self.eat(kind) { + true + } else { + if self.config.allow_comments { + println!("something"); + while matches!( + kind, + JsonSyntaxKind::COMMENT | JsonSyntaxKind::MULTILINE_COMMENT + ) { + self.bump_any(); + } + } + if self.eat(kind) { + return true; + } + + self.error(expected_token(kind)); + false + } + } } diff --git a/crates/rome_json_parser/src/token_source.rs b/crates/rome_json_parser/src/token_source.rs index b2fd0fa8338..f8860bb7f56 100644 --- a/crates/rome_json_parser/src/token_source.rs +++ b/crates/rome_json_parser/src/token_source.rs @@ -1,4 +1,5 @@ use crate::lexer::Lexer; +use crate::JsonParserConfig; use rome_json_syntax::JsonSyntaxKind::{EOF, TOMBSTONE}; use rome_json_syntax::{JsonSyntaxKind, TextRange}; use rome_parser::diagnostic::ParseDiagnostic; @@ -12,11 +13,12 @@ pub(crate) struct JsonTokenSource<'source> { current: JsonSyntaxKind, current_range: TextRange, preceding_line_break: bool, + config: JsonParserConfig, } impl<'source> JsonTokenSource<'source> { - pub fn from_str(source: &'source str) -> Self { - let lexer = Lexer::from_str(source); + pub fn from_str(source: &'source str, config: JsonParserConfig) -> Self { + let lexer = Lexer::from_str(source).with_config(config); let mut source = Self { lexer, @@ -24,6 +26,7 @@ impl<'source> JsonTokenSource<'source> { current: TOMBSTONE, current_range: TextRange::default(), preceding_line_break: false, + config, }; source.next_non_trivia_token(true); @@ -39,6 +42,18 @@ impl<'source> JsonTokenSource<'source> { match trivia_kind { Err(_) => { + if self.config.allow_comments && token.kind().is_comments() { + dbg!(token.kind()); + let trivia_kind = match token.kind() { + JsonSyntaxKind::COMMENT => TriviaPieceKind::SingleLineComment, + JsonSyntaxKind::MULTILINE_COMMENT => TriviaPieceKind::MultiLineComment, + _ => unreachable!(), + }; + self.trivia + .push(Trivia::new(trivia_kind, token.range(), trailing)); + continue; + } + self.current = token.kind(); self.current_range = token.range(); diff --git a/crates/rome_json_parser/tests/json_test_suite/allow_comments/basic.json b/crates/rome_json_parser/tests/json_test_suite/allow_comments/basic.json new file mode 100644 index 00000000000..700cb8e4111 --- /dev/null +++ b/crates/rome_json_parser/tests/json_test_suite/allow_comments/basic.json @@ -0,0 +1 @@ +/*leading*/ [1,true] // trivial diff --git a/crates/rome_json_parser/tests/json_test_suite/allow_comments/basic.json.snap b/crates/rome_json_parser/tests/json_test_suite/allow_comments/basic.json.snap new file mode 100644 index 00000000000..9244bff5c10 --- /dev/null +++ b/crates/rome_json_parser/tests/json_test_suite/allow_comments/basic.json.snap @@ -0,0 +1,52 @@ +--- +source: crates/rome_json_parser/tests/spec_test.rs +expression: snapshot +--- + +## Input + +```json +/*leading*/ [1,true] // trivial + +``` + + +## AST + +``` +JsonRoot { + value: JsonArrayValue { + l_brack_token: L_BRACK@0..13 "[" [Comments("/*leading*/"), Whitespace(" ")] [], + elements: JsonArrayElementList [ + JsonNumberValue { + value_token: JSON_NUMBER_LITERAL@13..14 "1" [] [], + }, + COMMA@14..15 "," [] [], + JsonBooleanValue { + value_token: TRUE_KW@15..19 "true" [] [], + }, + ], + r_brack_token: R_BRACK@19..31 "]" [] [Whitespace(" "), Comments("// trivial")], + }, + eof_token: EOF@31..32 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: JSON_ROOT@0..32 + 0: JSON_ARRAY_VALUE@0..31 + 0: L_BRACK@0..13 "[" [Comments("/*leading*/"), Whitespace(" ")] [] + 1: JSON_ARRAY_ELEMENT_LIST@13..19 + 0: JSON_NUMBER_VALUE@13..14 + 0: JSON_NUMBER_LITERAL@13..14 "1" [] [] + 1: COMMA@14..15 "," [] [] + 2: JSON_BOOLEAN_VALUE@15..19 + 0: TRUE_KW@15..19 "true" [] [] + 2: R_BRACK@19..31 "]" [] [Whitespace(" "), Comments("// trivial")] + 1: EOF@31..32 "" [Newline("\n")] [] + +``` + + diff --git a/crates/rome_json_parser/tests/spec_test.rs b/crates/rome_json_parser/tests/spec_test.rs index af2a82a21fa..253dbd90c29 100644 --- a/crates/rome_json_parser/tests/spec_test.rs +++ b/crates/rome_json_parser/tests/spec_test.rs @@ -16,12 +16,13 @@ pub enum ExpectedOutcome { Undefined, } -pub fn run(test_case: &str, _snapshot_name: &str, test_directory: &str, outcome: &str) { - let outcome = match outcome { +pub fn run(test_case: &str, _snapshot_name: &str, test_directory: &str, outcome_str: &str) { + let outcome = match outcome_str { "ok" => ExpectedOutcome::Pass, "error" => ExpectedOutcome::Fail, "undefined" => ExpectedOutcome::Undefined, - _ => panic!("Invalid expected outcome {outcome}"), + "allow_comments" => ExpectedOutcome::Pass, + _ => panic!("Invalid expected outcome {outcome_str}"), }; let test_case_path = Path::new(test_case); @@ -35,7 +36,10 @@ pub fn run(test_case: &str, _snapshot_name: &str, test_directory: &str, outcome: let content = fs::read_to_string(test_case_path) .expect("Expected test path to be a readable file in UTF8 encoding"); - let parsed = parse_json(&content, JsonParserConfig::default()); + let parse_conifg = JsonParserConfig { + allow_comments: outcome_str == "allow_comments", + }; + let parsed = parse_json(&content, parse_conifg); let formatted_ast = format!("{:#?}", parsed.tree()); let mut snapshot = String::new(); diff --git a/crates/rome_json_parser/tests/spec_tests.rs b/crates/rome_json_parser/tests/spec_tests.rs index 27cc3c11d4f..e7322bdcdf7 100644 --- a/crates/rome_json_parser/tests/spec_tests.rs +++ b/crates/rome_json_parser/tests/spec_tests.rs @@ -16,3 +16,8 @@ mod undefined { //! parsers are free to accept or reject content tests_macros::gen_tests! {"tests/json_test_suite/undefined/*.json", crate::spec_test::run, "undefined"} } + +mod allow_comments { + //! Tests should pass even with comments in json + tests_macros::gen_tests! {"tests/json_test_suite/allow_comments/*.json", crate::spec_test::run, "allow_comments"} +} diff --git a/crates/rome_json_syntax/src/lib.rs b/crates/rome_json_syntax/src/lib.rs index 12d148db7b6..9d8790cbb9c 100644 --- a/crates/rome_json_syntax/src/lib.rs +++ b/crates/rome_json_syntax/src/lib.rs @@ -30,6 +30,13 @@ impl JsonSyntaxKind { matches!(self, JsonSyntaxKind::NEWLINE | JsonSyntaxKind::WHITESPACE) } + pub fn is_comments(self) -> bool { + matches!( + self, + JsonSyntaxKind::COMMENT | JsonSyntaxKind::MULTILINE_COMMENT + ) + } + #[inline] pub const fn is_keyword(self) -> bool { matches!(self, T![null] | T![true] | T![false]) diff --git a/crates/rome_service/src/configuration/json.rs b/crates/rome_service/src/configuration/json.rs index 4dcc10cff84..3532d502d5b 100644 --- a/crates/rome_service/src/configuration/json.rs +++ b/crates/rome_service/src/configuration/json.rs @@ -1,9 +1,5 @@ -use std::str::FromStr; - use bpaf::Bpaf; -use indexmap::IndexSet; use serde::{Deserialize, Serialize}; -use serde_json::from_str; use super::StringSet; #[derive(Default, Debug, Deserialize, Serialize, Eq, PartialEq, Clone, Bpaf)] From 43c655dde85a01ebfc9c4741ecc4b9484b1b5dcf Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Thu, 4 May 2023 22:07:33 +0800 Subject: [PATCH 08/19] =?UTF-8?q?chore:=20=F0=9F=A4=96=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/rome_js_unicode_table/src/tables.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/rome_js_unicode_table/src/tables.rs b/crates/rome_js_unicode_table/src/tables.rs index 863365853a9..3ed00b03214 100644 --- a/crates/rome_js_unicode_table/src/tables.rs +++ b/crates/rome_js_unicode_table/src/tables.rs @@ -787,7 +787,9 @@ pub mod derived_property { ('𱍐', '𲎯'), ('\u{e0100}', '\u{e01ef}'), ]; - pub fn ID_Continue(c: char) -> bool { super::bsearch_range_table(c, ID_Continue_table) } + pub fn ID_Continue(c: char) -> bool { + super::bsearch_range_table(c, ID_Continue_table) + } pub const ID_Start_table: &[(char, char)] = &[ ('A', 'Z'), ('a', 'z'), @@ -1449,5 +1451,7 @@ pub mod derived_property { ('𰀀', '𱍊'), ('𱍐', '𲎯'), ]; - pub fn ID_Start(c: char) -> bool { super::bsearch_range_table(c, ID_Start_table) } + pub fn ID_Start(c: char) -> bool { + super::bsearch_range_table(c, ID_Start_table) + } } From b816d45b3f2951fb1224e7297eadab16ee10963f Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Thu, 4 May 2023 22:18:06 +0800 Subject: [PATCH 09/19] =?UTF-8?q?chore:=20=F0=9F=A4=96=20lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/rome_json_formatter/src/lib.rs | 1 - crates/rome_json_formatter/tests/quick_test.rs | 2 +- crates/rome_json_parser/src/parser.rs | 3 +-- crates/rome_json_parser/src/token_source.rs | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/rome_json_formatter/src/lib.rs b/crates/rome_json_formatter/src/lib.rs index cddc546dc89..cab99766f4a 100644 --- a/crates/rome_json_formatter/src/lib.rs +++ b/crates/rome_json_formatter/src/lib.rs @@ -290,7 +290,6 @@ pub fn format_sub_tree(options: JsonFormatOptions, root: &JsonSyntaxNode) -> For #[cfg(test)] mod tests { - use std::default; use crate::context::JsonFormatOptions; use crate::format_node; diff --git a/crates/rome_json_formatter/tests/quick_test.rs b/crates/rome_json_formatter/tests/quick_test.rs index ff8677caed8..1a2e9474a9e 100644 --- a/crates/rome_json_formatter/tests/quick_test.rs +++ b/crates/rome_json_formatter/tests/quick_test.rs @@ -1,7 +1,7 @@ use rome_formatter_test::check_reformat::CheckReformat; use rome_json_formatter::context::JsonFormatOptions; use rome_json_formatter::format_node; -use rome_json_parser::{parse_json, JsonParse, JsonParserConfig}; +use rome_json_parser::{parse_json, JsonParserConfig}; mod language { include!("language.rs"); diff --git a/crates/rome_json_parser/src/parser.rs b/crates/rome_json_parser/src/parser.rs index c5b0e7a79bf..0b8e306a7c8 100644 --- a/crates/rome_json_parser/src/parser.rs +++ b/crates/rome_json_parser/src/parser.rs @@ -68,9 +68,8 @@ impl<'source> Parser for JsonParser<'source> { true } else { if self.config.allow_comments { - println!("something"); while matches!( - kind, + self.cur(), JsonSyntaxKind::COMMENT | JsonSyntaxKind::MULTILINE_COMMENT ) { self.bump_any(); diff --git a/crates/rome_json_parser/src/token_source.rs b/crates/rome_json_parser/src/token_source.rs index f8860bb7f56..288cbee6dcd 100644 --- a/crates/rome_json_parser/src/token_source.rs +++ b/crates/rome_json_parser/src/token_source.rs @@ -43,7 +43,6 @@ impl<'source> JsonTokenSource<'source> { match trivia_kind { Err(_) => { if self.config.allow_comments && token.kind().is_comments() { - dbg!(token.kind()); let trivia_kind = match token.kind() { JsonSyntaxKind::COMMENT => TriviaPieceKind::SingleLineComment, JsonSyntaxKind::MULTILINE_COMMENT => TriviaPieceKind::MultiLineComment, From 584e045a07f6257957a26e5d168104f65960cc5e Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Fri, 5 May 2023 01:00:42 +0800 Subject: [PATCH 10/19] =?UTF-8?q?fix:=20=F0=9F=90=9B=20compile=20erorr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- xtask/codegen/src/generate_schema.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xtask/codegen/src/generate_schema.rs b/xtask/codegen/src/generate_schema.rs index 79e4e9fdceb..16c5f70f02a 100644 --- a/xtask/codegen/src/generate_schema.rs +++ b/xtask/codegen/src/generate_schema.rs @@ -1,5 +1,5 @@ use rome_json_formatter::context::JsonFormatOptions; -use rome_json_parser::parse_json; +use rome_json_parser::{parse_json, JsonParserConfig}; use rome_service::Configuration; use schemars::schema_for; use serde_json::to_string; @@ -13,7 +13,7 @@ pub(crate) fn generate_configuration_schema(mode: Mode) -> Result<()> { let schema = schema_for!(Configuration); let json_schema = to_string(&schema)?; - let parsed = parse_json(&json_schema); + let parsed = parse_json(&json_schema, JsonParserConfig::default()); let formatted = rome_json_formatter::format_node(JsonFormatOptions::default(), &parsed.syntax()) .unwrap() From 7fc1bec6c5be4f630c1c31b1636101bc5c05f4cb Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Sat, 6 May 2023 00:26:47 +0800 Subject: [PATCH 11/19] =?UTF-8?q?chore:=20=F0=9F=A4=96=20add=20matcher?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 2 + crates/rome_cli/Cargo.toml | 89 ++++--- crates/rome_service/Cargo.toml | 78 +++---- .../src/file_handlers/javascript.rs | 220 +++++++----------- crates/rome_service/src/file_handlers/json.rs | 24 +- crates/rome_service/src/file_handlers/mod.rs | 19 +- crates/rome_service/src/settings.rs | 22 +- crates/rome_service/src/workspace/server.rs | 2 + 8 files changed, 196 insertions(+), 260 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8eb3b6f1c1f..f4612491806 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1684,6 +1684,7 @@ dependencies = [ "bpaf", "crossbeam", "dashmap", + "globset", "hdrhistogram", "indexmap", "insta", @@ -2186,6 +2187,7 @@ version = "0.0.0" dependencies = [ "bpaf", "dashmap", + "globset", "indexmap", "insta", "rome_analyze", diff --git a/crates/rome_cli/Cargo.toml b/crates/rome_cli/Cargo.toml index d6d7b152201..ee6f03a8eef 100644 --- a/crates/rome_cli/Cargo.toml +++ b/crates/rome_cli/Cargo.toml @@ -1,10 +1,10 @@ [package] -authors.workspace = true -edition.workspace = true -license.workspace = true -name = "rome_cli" -repository.workspace = true -version = "0.0.0" +name = "rome_cli" +version = "0.0.0" +edition = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +license = { workspace = true } # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[bin]] @@ -12,39 +12,41 @@ name = "rome" path = "src/main.rs" [dependencies] -anyhow = "1.0.52" -bpaf = { workspace = true } -crossbeam = "0.8.1" -dashmap = { workspace = true } -hdrhistogram = { version = "7.5.0", default-features = false } -indexmap = { workspace = true } -lazy_static = { workspace = true } -rayon = "1.5.1" -rome_console = { workspace = true } -rome_deserialize = { workspace = true } -rome_diagnostics = { workspace = true } -rome_flags = { workspace = true } -rome_formatter = { workspace = true } -rome_fs = { workspace = true } -rome_json_formatter = { workspace = true } -rome_json_parser = { workspace = true } -rome_json_syntax = { workspace = true } -rome_lsp = { workspace = true } -rome_migrate = { workspace = true } -rome_rowan = { workspace = true } -rome_service = { workspace = true } -rome_text_edit = { workspace = true } -rome_text_size = { workspace = true } -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true } -tokio = { workspace = true, features = ["io-std", "io-util", "net", "time", "rt", "sync", "rt-multi-thread", "macros"] } -tracing = { workspace = true } -tracing-appender = "0.2" -tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } -tracing-tree = "0.2.2" +rome_formatter = { path = "../rome_formatter" } +rome_diagnostics = { path = "../rome_diagnostics" } +rome_service = { path = "../rome_service" } +rome_flags = { path = "../rome_flags" } +rome_fs = { path = "../rome_fs" } +rome_console = { path = "../rome_console" } +rome_text_edit = { path = "../rome_text_edit" } +rome_lsp = { path = "../rome_lsp" } +rome_deserialize = { path = "../rome_deserialize" } +pico-args = { version ="0.5.0", features=["eq-separator"] } +bpaf = { workspace = true } +tracing = { workspace = true } +tracing-tree = "0.2.2" +tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } +tracing-appender = "0.2" +lazy_static = { workspace = true } +hdrhistogram = { version = "7.5.0", default-features = false } +crossbeam = "0.8.1" +rayon = "1.5.1" +serde = { version = "1.0.133", features = ["derive"] } +serde_json = { version = "1.0.74" } +tokio = { workspace = true, features = ["io-std", "io-util", "net", "time", "rt","sync", "rt-multi-thread", "macros"] } +anyhow = "1.0.52" +dashmap = { workspace = true } +rome_text_size = { path = "../rome_text_size" } +rome_json_parser = { path = "../rome_json_parser" } +rome_json_formatter = { path = "../rome_json_formatter" } +rome_json_syntax = { path = "../rome_json_syntax" } +rome_migrate = { path = "../rome_migrate" } +rome_rowan = { path = "../rome_rowan" } +indexmap = { workspace = true } +globset = "0.4.10" [target.'cfg(unix)'.dependencies] -libc = "0.2.127" +libc = "0.2.127" tokio = { workspace = true, features = ["process"] } [target.'cfg(windows)'.dependencies] @@ -54,11 +56,8 @@ mimalloc = "0.1.29" tikv-jemallocator = "0.5.0" [dev-dependencies] -insta = { workspace = true } -rome_js_formatter = { workspace = true } -rome_json_formatter = { workspace = true } -rome_json_parser = { workspace = true } -tokio = { workspace = true, features = ["io-util"] } - -[features] -docgen = ["bpaf/docgen"] +insta = { workspace = true } +tokio = { workspace = true, features = ["io-util"] } +rome_json_formatter = { path = "../rome_json_formatter" } +rome_js_formatter = { path = "../rome_js_formatter" } +rome_json_parser = { path = "../rome_json_parser" } diff --git a/crates/rome_service/Cargo.toml b/crates/rome_service/Cargo.toml index 7cc6793c6dd..00b7223f94b 100644 --- a/crates/rome_service/Cargo.toml +++ b/crates/rome_service/Cargo.toml @@ -1,51 +1,45 @@ [package] -authors.workspace = true -edition.workspace = true -license.workspace = true -name = "rome_service" -repository.workspace = true -version = "0.0.0" +name = "rome_service" +version = "0.0.0" +edition = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +license = { workspace = true } # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bpaf = { workspace = true } -dashmap = { workspace = true } -indexmap = { workspace = true, features = ["serde"] } -rome_analyze = { workspace = true, features = ["serde"] } -rome_console = { workspace = true } -rome_deserialize = { workspace = true } -rome_diagnostics = { workspace = true } -rome_flags = { workspace = true } -rome_formatter = { workspace = true, features = ["serde"] } -rome_fs = { workspace = true, features = ["serde"] } -rome_js_analyze = { workspace = true } -rome_js_factory = { workspace = true, optional = true } -rome_js_formatter = { workspace = true, features = ["serde"] } -rome_js_parser = { workspace = true } -rome_js_semantic = { workspace = true } -rome_js_syntax = { workspace = true, features = ["serde"] } -rome_json_analyze = { workspace = true } -rome_json_formatter = { workspace = true } -rome_json_parser = { workspace = true } -rome_json_syntax = { workspace = true } -rome_parser = { workspace = true } -rome_rowan = { workspace = true, features = ["serde"] } -rome_text_edit = { workspace = true } -schemars = { workspace = true, features = ["indexmap1"], optional = true } -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true, features = ["raw_value"] } -tracing = { workspace = true, features = ["attributes"] } +dashmap = { workspace = true } +serde = { version = "1.0.133", features = ["derive"] } +serde_json = { version = "1.0.74", features = ["raw_value"] } +rome_analyze = { path = "../rome_analyze", features = ["serde"] } +rome_console = { path = "../rome_console" } +rome_diagnostics = { path = "../rome_diagnostics" } +rome_formatter = { path = "../rome_formatter", features = ["serde"] } +rome_fs = { path = "../rome_fs", features = ["serde"] } +rome_flags = { path = "../rome_flags" } +rome_js_analyze = { path = "../rome_js_analyze" } +rome_js_syntax = { path = "../rome_js_syntax", features = ["serde"] } +rome_parser = { path = "../rome_parser" } +rome_js_parser = { path = "../rome_js_parser" } +rome_js_factory = { path = "../rome_js_factory", optional = true } +rome_js_formatter = { path = "../rome_js_formatter", features = ["serde"] } +rome_js_semantic = { path = "../rome_js_semantic" } +rome_json_parser = { path = "../rome_json_parser" } +rome_json_syntax = { path = "../rome_json_syntax" } +rome_json_formatter = { path = "../rome_json_formatter" } +rome_deserialize = { path = "../rome_deserialize" } +rome_rowan = { path = "../rome_rowan", features = ["serde"] } +rome_text_edit = { path = "../rome_text_edit" } +indexmap = { workspace = true, features = ["serde"] } +schemars = { version = "0.8.10", features = ["indexmap1"], optional = true } +tracing = { workspace = true, features = ["attributes"] } +bpaf = { workspace = true } +globset = "0.4.10" [features] -schemars = [ - "dep:schemars", - "rome_js_analyze/schemars", - "rome_formatter/serde", - "rome_js_factory", - "rome_text_edit/schemars", -] +schemars = ["dep:schemars", "rome_formatter/serde", "rome_js_factory", "rome_text_edit/schemars"] [dev-dependencies] -insta = { workspace = true } -tests_macros = { workspace = true } +insta = { workspace = true } +tests_macros = { path = "../tests_macros" } diff --git a/crates/rome_service/src/file_handlers/javascript.rs b/crates/rome_service/src/file_handlers/javascript.rs index f4ec23981e3..d9ce86a132a 100644 --- a/crates/rome_service/src/file_handlers/javascript.rs +++ b/crates/rome_service/src/file_handlers/javascript.rs @@ -3,7 +3,7 @@ use super::{ LintResults, Mime, ParserCapabilities, }; use crate::configuration::to_analyzer_configuration; -use crate::file_handlers::{is_diagnostic_error, Features, FixAllParams, Language as LanguageId}; +use crate::file_handlers::{is_diagnostic_error, FixAllParams, Language as LanguageId}; use crate::workspace::OrganizeImportsResult; use crate::{ settings::{FormatSettings, Language, LanguageSettings, LanguagesSettings, SettingsHandle}, @@ -26,37 +26,27 @@ use rome_js_analyze::{ analyze, analyze_with_inspect_matcher, visit_registry, ControlFlowGraph, RuleError, }; use rome_js_formatter::context::{ - trailing_comma::TrailingComma, ArrowParentheses, QuoteProperties, QuoteStyle, Semicolons, + trailing_comma::TrailingComma, QuoteProperties, QuoteStyle, Semicolons, }; use rome_js_formatter::{context::JsFormatOptions, format_node}; -use rome_js_parser::JsParserOptions; use rome_js_semantic::{semantic_model, SemanticModelOptions}; use rome_js_syntax::{ - AnyJsRoot, JsFileSource, JsLanguage, JsSyntaxNode, TextRange, TextSize, TokenAtOffset, + AnyJsRoot, JsLanguage, JsSyntaxNode, SourceType, TextRange, TextSize, TokenAtOffset, }; use rome_parser::AnyParse; -use rome_rowan::{AstNode, BatchMutationExt, Direction, FileSource, NodeCache}; +use rome_rowan::{AstNode, BatchMutationExt, Direction, NodeCache}; use std::borrow::Cow; -use std::ffi::OsStr; use std::fmt::Debug; use std::path::PathBuf; -use tracing::{debug, trace}; +use tracing::debug; #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct JsFormatterSettings { pub quote_style: Option, - pub jsx_quote_style: Option, pub quote_properties: Option, pub trailing_comma: Option, pub semicolons: Option, - pub arrow_parentheses: Option, -} - -#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] -pub struct JsParserSettings { - pub parse_class_parameter_decorators: bool, } #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] @@ -74,8 +64,7 @@ impl Language for JsLanguage { type LinterSettings = JsLinterSettings; type FormatOptions = JsFormatOptions; type OrganizeImportsSettings = JsOrganizeImportsSettings; - type ParserSettings = JsParserSettings; - + type AllowCommentsOptions = (); fn lookup_settings(languages: &LanguagesSettings) -> &LanguageSettings { &languages.javascript } @@ -89,11 +78,9 @@ impl Language for JsLanguage { .with_indent_style(global.indent_style.unwrap_or_default()) .with_line_width(global.line_width.unwrap_or_default()) .with_quote_style(language.quote_style.unwrap_or_default()) - .with_jsx_quote_style(language.jsx_quote_style.unwrap_or_default()) .with_quote_properties(language.quote_properties.unwrap_or_default()) .with_trailing_comma(language.trailing_comma.unwrap_or_default()) .with_semicolons(language.semicolons.unwrap_or_default()) - .with_arrow_parentheses(language.arrow_parentheses.unwrap_or_default()) } } @@ -137,45 +124,23 @@ impl ExtensionHandler for JsFileHandler { } } -fn extension_error(path: &RomePath) -> WorkspaceError { - let language = Features::get_language(path).or(LanguageId::from_path(path)); - WorkspaceError::source_file_not_supported( - language, - path.clone().display().to_string(), - path.clone() - .extension() - .and_then(OsStr::to_str) - .map(|s| s.to_string()), - ) -} - fn parse( rome_path: &RomePath, language_hint: LanguageId, text: &str, - settings: SettingsHandle, cache: &mut NodeCache, + _: SettingsHandle, ) -> AnyParse { let source_type = - JsFileSource::try_from(rome_path.as_path()).unwrap_or_else(|_| match language_hint { - LanguageId::JavaScriptReact => JsFileSource::jsx(), - LanguageId::TypeScript => JsFileSource::ts(), - LanguageId::TypeScriptReact => JsFileSource::tsx(), - _ => JsFileSource::js_module(), + SourceType::try_from(rome_path.as_path()).unwrap_or_else(|_| match language_hint { + LanguageId::JavaScriptReact => SourceType::jsx(), + LanguageId::TypeScript => SourceType::ts(), + LanguageId::TypeScriptReact => SourceType::tsx(), + _ => SourceType::js_module(), }); - let settings = &settings.as_ref().languages.javascript.parser; - let options = JsParserOptions { - parse_class_parameter_decorators: settings.parse_class_parameter_decorators, - }; - let parse = rome_js_parser::parse_js_with_cache(text, source_type, options, cache); - let root = parse.syntax(); - let diagnostics = parse.into_diagnostics(); - AnyParse::new( - // SAFETY: the parser should always return a root node - root.as_send().unwrap(), - diagnostics, - source_type.as_any_file_source(), - ) + + let parse = rome_js_parser::parse_js_with_cache(text, source_type, cache); + AnyParse::from(parse) } fn debug_syntax_tree(_rome_path: &RomePath, parse: AnyParse) -> GetSyntaxTreeResult { @@ -223,7 +188,7 @@ fn debug_control_flow(parse: AnyParse, cursor: TextSize) -> String { } }, &options, - JsFileSource::default(), + SourceType::default(), |_| ControlFlow::::Continue(()), ); @@ -245,15 +210,6 @@ fn debug_formatter_ir( } fn lint(params: LintParams) -> LintResults { - let Ok(file_source) = params - .parse - .file_source(params.path) else { - return LintResults { - errors: 0, - diagnostics: vec![], - skipped_diagnostics: 0 - } - }; let tree = params.parse.tree(); let mut diagnostics = params.parse.into_diagnostics(); @@ -272,7 +228,7 @@ fn lint(params: LintParams) -> LintResults { &tree, params.filter, &analyzer_options, - file_source, + SourceType::default(), |signal| { if let Some(mut diagnostic) = signal.diagnostic() { // Do not report unused suppression comment diagnostics if this is a syntax-only analyzer pass @@ -295,7 +251,7 @@ fn lint(params: LintParams) -> LintResults { }) .unwrap_or_else(|| diagnostic.severity()); - if severity >= Severity::Error { + if severity <= Severity::Error { errors += 1; } @@ -359,7 +315,6 @@ impl RegistryVisitor for ActionsVisitor<'_> { } } -#[tracing::instrument(level = "debug", skip(parse))] fn code_actions( parse: AnyParse, range: TextRange, @@ -371,56 +326,48 @@ fn code_actions( let mut actions = Vec::new(); - let mut enabled_rules = vec![]; - if settings.as_ref().organize_imports.enabled { - enabled_rules.push(RuleFilter::Rule("correctness", "organizeImports")); - } - if let Some(rules) = rules { - let rules = rules.as_enabled_rules().into_iter().collect(); + let enabled_rules: Option> = if let Some(rules) = rules { + let enabled_rules = rules.as_enabled_rules().into_iter().collect(); // The rules in the assist category do not have configuration entries, // always add them all to the enabled rules list - let mut visitor = ActionsVisitor { - enabled_rules: rules, - }; + let mut visitor = ActionsVisitor { enabled_rules }; visit_registry(&mut visitor); - enabled_rules.extend(visitor.enabled_rules); - } - - let mut filter = if !enabled_rules.is_empty() { - AnalysisFilter::from_enabled_rules(Some(enabled_rules.as_slice())) + Some(visitor.enabled_rules) } else { - AnalysisFilter::default() + None + }; + + let mut filter = match &enabled_rules { + Some(rules) => AnalysisFilter::from_enabled_rules(Some(rules.as_slice())), + _ => AnalysisFilter::default(), }; filter.categories = RuleCategories::SYNTAX | RuleCategories::LINT; - if settings.as_ref().organize_imports.enabled { - filter.categories |= RuleCategories::ACTION; - } filter.range = Some(range); - trace!("Filter applied for code actions: {:?}", &filter); let analyzer_options = compute_analyzer_options(&settings, PathBuf::from(path.as_path())); - let Ok(source_type) = parse.file_source(path) else { - return PullActionsResult { - actions: vec![] - } - }; - - analyze(&tree, filter, &analyzer_options, source_type, |signal| { - actions.extend(signal.actions().into_code_action_iter().map(|item| { - CodeAction { - category: item.category.clone(), - rule_name: item - .rule_name - .map(|(group, name)| (Cow::Borrowed(group), Cow::Borrowed(name))), - suggestion: item.suggestion, - } - })); - ControlFlow::::Continue(()) - }); + analyze( + &tree, + filter, + &analyzer_options, + SourceType::default(), + |signal| { + actions.extend(signal.actions().into_code_action_iter().map(|item| { + CodeAction { + category: item.category.clone(), + rule_name: item + .rule_name + .map(|(group, name)| (Cow::Borrowed(group), Cow::Borrowed(name))), + suggestion: item.suggestion, + } + })); + + ControlFlow::::Continue(()) + }, + ); PullActionsResult { actions } } @@ -438,9 +385,6 @@ fn fix_all(params: FixAllParams) -> Result { rome_path, } = params; - let file_source = parse - .file_source(rome_path) - .map_err(|_| extension_error(params.rome_path))?; let mut tree: AnyJsRoot = parse.tree(); let mut actions = Vec::new(); @@ -462,45 +406,51 @@ fn fix_all(params: FixAllParams) -> Result { let mut errors: u16 = 0; let analyzer_options = compute_analyzer_options(&settings, PathBuf::from(rome_path.as_path())); loop { - let (action, _) = analyze(&tree, filter, &analyzer_options, file_source, |signal| { - let current_diagnostic = signal.diagnostic(); - - if let Some(diagnostic) = current_diagnostic.as_ref() { - if is_diagnostic_error(diagnostic, params.rules) { - errors += 1; + let (action, _) = analyze( + &tree, + filter, + &analyzer_options, + SourceType::default(), + |signal| { + let current_diagnostic = signal.diagnostic(); + + if let Some(diagnostic) = current_diagnostic.as_ref() { + if is_diagnostic_error(diagnostic, params.rules) { + errors += 1; + } } - } - for action in signal.actions() { - // suppression actions should not be part of the fixes (safe or suggested) - if action.is_suppression() { - continue; - } + for action in signal.actions() { + // suppression actions should not be part of the fixes (safe or suggested) + if action.is_suppression() { + continue; + } - match fix_file_mode { - FixFileMode::SafeFixes => { - if action.applicability == Applicability::MaybeIncorrect { - skipped_suggested_fixes += 1; + match fix_file_mode { + FixFileMode::SafeFixes => { + if action.applicability == Applicability::MaybeIncorrect { + skipped_suggested_fixes += 1; + } + if action.applicability == Applicability::Always { + errors = errors.saturating_sub(1); + return ControlFlow::Break(action); + } } - if action.applicability == Applicability::Always { - errors = errors.saturating_sub(1); - return ControlFlow::Break(action); - } - } - FixFileMode::SafeAndUnsafeFixes => { - if matches!( - action.applicability, - Applicability::Always | Applicability::MaybeIncorrect - ) { - errors = errors.saturating_sub(1); - return ControlFlow::Break(action); + FixFileMode::SafeAndUnsafeFixes => { + if matches!( + action.applicability, + Applicability::Always | Applicability::MaybeIncorrect + ) { + errors = errors.saturating_sub(1); + return ControlFlow::Break(action); + } } } } - } - ControlFlow::Continue(()) - }); + ControlFlow::Continue(()) + }, + ); match action { Some(action) => { @@ -669,7 +619,7 @@ fn organize_imports(parse: AnyParse) -> Result; fn lookup_settings(language: &LanguagesSettings) -> &LanguageSettings { &language.json } @@ -84,8 +84,24 @@ impl ExtensionHandler for JsonFileHandler { } } -fn parse(_: &RomePath, _: LanguageId, text: &str, cache: &mut NodeCache) -> AnyParse { - let parse = rome_json_parser::parse_json_with_cache(text, cache, JsonParserConfig::default()); +fn parse( + path: &RomePath, + _: LanguageId, + text: &str, + cache: &mut NodeCache, + settings: SettingsHandle, +) -> AnyParse { + let allow_comment_matcher = &settings.as_ref().languages.json.allow_comments; + let parse = rome_json_parser::parse_json_with_cache( + text, + cache, + JsonParserConfig { + allow_comments: allow_comment_matcher + .as_ref() + .map(|matcher| matcher.matches_path(&*path)) + .unwrap_or(false), + }, + ); AnyParse::from(parse) } diff --git a/crates/rome_service/src/file_handlers/mod.rs b/crates/rome_service/src/file_handlers/mod.rs index 354e483794b..6ae7cd1d6db 100644 --- a/crates/rome_service/src/file_handlers/mod.rs +++ b/crates/rome_service/src/file_handlers/mod.rs @@ -16,7 +16,6 @@ use rome_js_syntax::{TextRange, TextSize}; use rome_parser::AnyParse; use rome_rowan::NodeCache; use std::ffi::OsStr; -use std::path::Path; mod javascript; mod json; @@ -54,14 +53,6 @@ impl Language { } } - /// Returns the language corresponding to the file path - pub fn from_path(path: &Path) -> Self { - path.extension() - .and_then(|path| path.to_str()) - .map(Language::from_extension) - .unwrap_or(Language::Unknown) - } - /// Returns the language corresponding to this language ID /// /// See the [microsoft spec] @@ -161,17 +152,17 @@ pub struct FixAllParams<'a> { #[derive(Default)] /// The list of capabilities that are available for a language -pub struct Capabilities { +pub(crate) struct Capabilities { pub(crate) parser: ParserCapabilities, pub(crate) debug: DebugCapabilities, pub(crate) analyzer: AnalyzerCapabilities, pub(crate) formatter: FormatterCapabilities, } -type Parse = fn(&RomePath, Language, &str, SettingsHandle, &mut NodeCache) -> AnyParse; +type Parse = fn(&RomePath, Language, &str, &mut NodeCache, SettingsHandle) -> AnyParse; #[derive(Default)] -pub struct ParserCapabilities { +pub(crate) struct ParserCapabilities { /// Parse a file pub(crate) parse: Option, } @@ -181,7 +172,7 @@ type DebugControlFlow = fn(AnyParse, TextSize) -> String; type DebugFormatterIR = fn(&RomePath, AnyParse, SettingsHandle) -> Result; #[derive(Default)] -pub struct DebugCapabilities { +pub(crate) struct DebugCapabilities { /// Prints the syntax tree pub(crate) debug_syntax_tree: Option, /// Prints the control flow graph @@ -213,7 +204,7 @@ type Rename = fn(&RomePath, AnyParse, TextSize, String) -> Result Result; #[derive(Default)] -pub struct AnalyzerCapabilities { +pub(crate) struct AnalyzerCapabilities { /// It lints a file pub(crate) lint: Option, /// It extracts code actions for a file diff --git a/crates/rome_service/src/settings.rs b/crates/rome_service/src/settings.rs index 500fcfed82b..09bb2d94c36 100644 --- a/crates/rome_service/src/settings.rs +++ b/crates/rome_service/src/settings.rs @@ -76,20 +76,9 @@ impl WorkspaceSettings { let formatter = javascript.formatter; if let Some(formatter) = formatter { self.languages.javascript.formatter.quote_style = formatter.quote_style; - self.languages.javascript.formatter.jsx_quote_style = formatter.jsx_quote_style; self.languages.javascript.formatter.quote_properties = formatter.quote_properties; self.languages.javascript.formatter.trailing_comma = formatter.trailing_comma; self.languages.javascript.formatter.semicolons = formatter.semicolons; - self.languages.javascript.formatter.arrow_parentheses = formatter.arrow_parentheses; - } - - if let Some(parser) = javascript.parser { - self.languages - .javascript - .parser - .parse_class_parameter_decorators = parser - .unsafe_parameter_decorators_enabled - .unwrap_or_default(); } let organize_imports = javascript.organize_imports; @@ -217,8 +206,7 @@ pub trait Language: rome_rowan::Language { /// Fully resolved formatter options type for this language type FormatOptions: rome_formatter::FormatOptions; - /// Settings that belong to the parser - type ParserSettings: Default; + type AllowCommentsOptions: Default; /// Read the settings type for this language from the [LanguagesSettings] map fn lookup_settings(languages: &LanguagesSettings) -> &LanguageSettings; @@ -246,8 +234,7 @@ pub struct LanguageSettings { /// Organize imports settings for this language pub organize_imports: L::OrganizeImportsSettings, - /// Parser settings for this language - pub parser: L::ParserSettings, + pub allow_comments: L::AllowCommentsOptions, } /// Filesystem settings for the entire workspace @@ -258,9 +245,6 @@ pub struct FilesSettings { /// List of paths/files to matcher pub ignored_files: Matcher, - - /// Files not recognized by Rome should not emit a diagnostic - pub ignore_unknown: bool, } /// Limit the size of files to 1.0 MiB by default @@ -277,7 +261,6 @@ impl Default for FilesSettings { require_literal_leading_dot: false, require_literal_separator: false, }), - ignore_unknown: false, } } } @@ -306,7 +289,6 @@ impl TryFrom for FilesSettings { Ok(Self { max_size: config.max_size.unwrap_or(DEFAULT_FILE_SIZE_LIMIT), ignored_files: matcher, - ignore_unknown: config.ignore_unknown.unwrap_or_default(), }) } } diff --git a/crates/rome_service/src/workspace/server.rs b/crates/rome_service/src/workspace/server.rs index aaa81215435..168f2b23efc 100644 --- a/crates/rome_service/src/workspace/server.rs +++ b/crates/rome_service/src/workspace/server.rs @@ -130,6 +130,7 @@ impl WorkspaceServer { &self, rome_path: RomePath, feature: Option, + // settings: SettingsHandle, ) -> Result { let ignored = if let Some(feature) = feature { self.is_path_ignored(IsPathIgnoredParams { @@ -187,6 +188,7 @@ impl WorkspaceServer { document.content.as_str(), settings, &mut document.node_cache, + self.settings(), ); Ok(entry.insert(parsed).clone()) From a55484f483e4185e03337636b76fb5fda429a5fe Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Sat, 6 May 2023 00:54:58 +0800 Subject: [PATCH 12/19] =?UTF-8?q?chore:=20=F0=9F=A4=96=20add=20extra=20tes?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/rome_cli/tests/commands/format.rs | 532 ++++++------------ ...re_comments_error_when_allow_comments.snap | 32 ++ ...omments_error_when_allow_comments.snap.new | 71 +++ 3 files changed, 273 insertions(+), 362 deletions(-) create mode 100644 crates/rome_cli/tests/snapshots/main_commands_format/ignore_comments_error_when_allow_comments.snap create mode 100644 crates/rome_cli/tests/snapshots/main_commands_format/ignore_comments_error_when_allow_comments.snap.new diff --git a/crates/rome_cli/tests/commands/format.rs b/crates/rome_cli/tests/commands/format.rs index d09b870edb6..a245c95d5af 100644 --- a/crates/rome_cli/tests/commands/format.rs +++ b/crates/rome_cli/tests/commands/format.rs @@ -19,15 +19,6 @@ const CUSTOM_FORMAT_AFTER: &str = r#"function f() { } "#; -const APPLY_JSX_QUOTE_STYLE_BEFORE: &str = r#" -

"#; - -const APPLY_JSX_QUOTE_STYLE_AFTER: &str = r#"
; -"#; - const APPLY_QUOTE_STYLE_BEFORE: &str = r#" let a = "something"; let b = { @@ -52,23 +43,6 @@ const APPLY_TRAILING_COMMA_AFTER: &str = r#"const a = [ ]; "#; -const APPLY_ARROW_PARENTHESES_BEFORE: &str = r#" -action => {} -(action) => {} -({ action }) => {} -([ action ]) => {} -(...action) => {} -(action = 1) => {} -"#; - -const APPLY_ARROW_PARENTHESES_AFTER: &str = r#"action => {}; -action => {}; -({ action }) => {}; -([action]) => {}; -(...action) => {}; -(action = 1) => {}; -"#; - const DEFAULT_CONFIGURATION_BEFORE: &str = r#"function f() { return { a, b } }"#; @@ -98,7 +72,7 @@ fn format_help() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), "--help"].as_slice()), + Args::from(&[("format"), "--help"]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -123,7 +97,7 @@ fn print() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), file_path.as_os_str().to_str().unwrap()].as_slice()), + Args::from(&[("format"), file_path.as_os_str().to_str().unwrap()]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -159,14 +133,11 @@ fn write() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--write"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -210,7 +181,7 @@ fn write_only_files_in_correct_base() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--write"), ("./src")].as_slice()), + Args::from(&[("format"), ("--write"), ("./src")]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -256,7 +227,7 @@ fn lint_warning() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), file_path.as_os_str().to_str().unwrap()].as_slice()), + Args::from(&[("format"), file_path.as_os_str().to_str().unwrap()]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -310,19 +281,16 @@ fn custom_config_file_path() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - format!( - "--config-path={}", - config_path.display().to_string().as_str() - ) - .as_str(), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + format!( + "--config-path={}", + config_path.display().to_string().as_str() + ) + .as_str(), + ("--write"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -362,16 +330,13 @@ fn invalid_config_file_path() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--config-path"), - (config_path.display().to_string().as_str()), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--config-path"), + (config_path.display().to_string().as_str()), + ("--write"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -396,20 +361,17 @@ fn applies_custom_configuration() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--line-width"), - ("10"), - ("--indent-style"), - ("space"), - ("--indent-size"), - ("8"), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--line-width"), + ("10"), + ("--indent-style"), + ("space"), + ("--indent-size"), + ("8"), + ("--write"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -448,20 +410,17 @@ fn applies_custom_configuration_over_config_file() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--line-width"), - ("10"), - ("--indent-style"), - ("space"), - ("--indent-size"), - ("8"), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--line-width"), + ("10"), + ("--indent-style"), + ("space"), + ("--indent-size"), + ("8"), + ("--write"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -500,15 +459,12 @@ fn applies_custom_configuration_over_config_file_issue_3175_v1() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--quote-style"), - ("single"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--quote-style"), + ("single"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -552,15 +508,12 @@ fn applies_custom_configuration_over_config_file_issue_3175_v2() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--indent-style"), - ("space"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--indent-style"), + ("space"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -585,53 +538,6 @@ fn applies_custom_configuration_over_config_file_issue_3175_v2() { )); } -#[test] -fn applies_custom_jsx_quote_style() { - let mut fs = MemoryFileSystem::default(); - let mut console = BufferConsole::default(); - - let file_path = Path::new("file.js"); - fs.insert(file_path.into(), APPLY_JSX_QUOTE_STYLE_BEFORE.as_bytes()); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from( - [ - ("format"), - ("--jsx-quote-style"), - ("single"), - ("--quote-properties"), - ("preserve"), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), - ); - - assert!(result.is_ok(), "run_cli returned {result:?}"); - - let mut file = fs - .open(file_path) - .expect("formatting target file was removed by the CLI"); - - let mut content = String::new(); - file.read_to_string(&mut content) - .expect("failed to read file from memory FS"); - - assert_eq!(content, APPLY_JSX_QUOTE_STYLE_AFTER); - - drop(file); - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "applies_custom_jsx_quote_style", - fs, - console, - result, - )); -} - #[test] fn applies_custom_quote_style() { let mut fs = MemoryFileSystem::default(); @@ -643,18 +549,15 @@ fn applies_custom_quote_style() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--quote-style"), - ("single"), - ("--quote-properties"), - ("preserve"), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--quote-style"), + ("single"), + ("--quote-properties"), + ("preserve"), + ("--write"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -690,16 +593,13 @@ fn applies_custom_trailing_comma() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--trailing-comma"), - ("none"), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--trailing-comma"), + ("none"), + ("--write"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -724,51 +624,6 @@ fn applies_custom_trailing_comma() { )); } -#[test] -fn applies_custom_arrow_parentheses() { - let mut fs = MemoryFileSystem::default(); - let mut console = BufferConsole::default(); - - let file_path = Path::new("file.js"); - fs.insert(file_path.into(), APPLY_ARROW_PARENTHESES_BEFORE.as_bytes()); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from( - [ - ("format"), - ("--arrow-parentheses"), - ("as-needed"), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), - ); - - assert!(result.is_ok(), "run_cli returned {result:?}"); - - let mut file = fs - .open(file_path) - .expect("formatting target file was removed by the CLI"); - - let mut content = String::new(); - file.read_to_string(&mut content) - .expect("failed to read file from memory FS"); - - assert_eq!(content, APPLY_ARROW_PARENTHESES_AFTER); - - drop(file); - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "applies_custom_arrow_parentheses", - fs, - console, - result, - )); -} - #[test] fn trailing_comma_parse_errors() { let mut console = BufferConsole::default(); @@ -777,7 +632,7 @@ fn trailing_comma_parse_errors() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--trailing-comma"), ("NONE"), ("file.js")].as_slice()), + Args::from(&[("format"), ("--trailing-comma"), ("NONE"), ("file.js")]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -802,15 +657,12 @@ fn with_semicolons_options() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--semicolons=as-needed"), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--semicolons=as-needed"), + ("--write"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -843,7 +695,7 @@ fn with_invalid_semicolons_option() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--semicolons"), ("asneed"), ("file.js")].as_slice()), + Args::from(&[("format"), ("--semicolons"), ("asneed"), ("file.js")]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -865,7 +717,7 @@ fn indent_style_parse_errors() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--indent-style"), ("invalid"), ("file.js")].as_slice()), + Args::from(&[("format"), ("--indent-style"), ("invalid"), ("file.js")]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -887,7 +739,7 @@ fn indent_size_parse_errors_negative() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--indent-size=-1"), ("file.js")].as_slice()), + Args::from(&[("format"), ("--indent-size=-1"), ("file.js")]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -909,7 +761,7 @@ fn indent_size_parse_errors_overflow() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--indent-size=257"), ("file.js")].as_slice()), + Args::from(&[("format"), ("--indent-size=257"), ("file.js")]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -931,7 +783,7 @@ fn line_width_parse_errors_negative() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from(["format", "--line-width=-1", "file.js"].as_slice()), + Args::from(&["format", "--line-width=-1", "file.js"]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -952,7 +804,7 @@ fn line_width_parse_errors_overflow() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--line-width"), ("321"), ("file.js")].as_slice()), + Args::from(&[("format"), ("--line-width"), ("321"), ("file.js")]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -974,15 +826,12 @@ fn quote_properties_parse_errors_letter_case() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--quote-properties"), - ("As-needed"), - ("file.js"), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--quote-properties"), + ("As-needed"), + ("file.js"), + ]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -1009,7 +858,7 @@ fn format_with_configuration() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("file.js"), ("--write")].as_slice()), + Args::from(&[("format"), ("file.js"), ("--write")]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -1047,7 +896,7 @@ fn format_is_disabled() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("file.js"), ("--write")].as_slice()), + Args::from(&[("format"), ("file.js"), ("--write")]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -1084,7 +933,7 @@ fn format_stdin_successfully() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--stdin-file-path"), ("mock.js")].as_slice()), + Args::from(&[("format"), ("--stdin-file-path"), ("mock.js")]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -1117,7 +966,7 @@ fn format_stdin_with_errors() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--stdin-file-path"), ("mock.js")].as_slice()), + Args::from(&[("format"), ("--stdin-file-path"), ("mock.js")]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -1146,7 +995,7 @@ fn does_not_format_if_disabled() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--stdin-file-path"), ("mock.js")].as_slice()), + Args::from(&[("format"), ("--stdin-file-path"), ("mock.js")]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -1184,7 +1033,7 @@ fn does_not_format_ignored_files() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("test.js"), ("--write")].as_slice()), + Args::from(&[("format"), ("test.js"), ("--write")]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -1229,15 +1078,12 @@ fn does_not_format_if_files_are_listed_in_ignore_option() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - file_path_test1.as_os_str().to_str().unwrap(), - file_path_test2.as_os_str().to_str().unwrap(), - ("--write"), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + file_path_test1.as_os_str().to_str().unwrap(), + file_path_test2.as_os_str().to_str().unwrap(), + ("--write"), + ]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -1298,7 +1144,7 @@ fn does_not_format_ignored_directories() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("./"), ("--write")].as_slice()), + Args::from(&[("format"), ("./"), ("--write")]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -1344,14 +1190,11 @@ fn fs_error_read_only() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--write"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--write"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -1379,14 +1222,11 @@ fn file_too_large() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - file_path.as_os_str().to_str().unwrap(), - ("--write"), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + file_path.as_os_str().to_str().unwrap(), + ("--write"), + ]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -1416,7 +1256,7 @@ fn file_too_large_config_limit() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), file_path.as_os_str().to_str().unwrap()].as_slice()), + Args::from(&[("format"), file_path.as_os_str().to_str().unwrap()]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -1441,14 +1281,11 @@ fn file_too_large_cli_limit() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--files-max-size=16"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--files-max-size=16"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -1473,14 +1310,11 @@ fn files_max_size_parse_error() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--files-max-size=-1"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--files-max-size=-1"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_err(), "run_cli returned {result:?}"); @@ -1507,7 +1341,7 @@ fn max_diagnostics_default() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("src")].as_slice()), + Args::from(&[("format"), ("src")]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -1544,7 +1378,7 @@ fn max_diagnostics_default() { result, )); - assert_eq!(diagnostic_count, 20); + assert_eq!(diagnostic_count, 50); } #[test] @@ -1560,7 +1394,7 @@ fn max_diagnostics() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), ("--max-diagnostics"), ("10"), ("src")].as_slice()), + Args::from(&[("format"), ("--max-diagnostics"), ("10"), ("src")]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -1608,7 +1442,7 @@ fn no_supported_file_found() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), "."].as_slice()), + Args::from(&[("check"), "."]), ); eprintln!("{:?}", console.out_buffer); @@ -1633,14 +1467,11 @@ fn print_verbose() { let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--verbose"), - file_path.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--verbose"), + file_path.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -1701,15 +1532,12 @@ file2.js let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--write"), - file_path1.as_os_str().to_str().unwrap(), - file_path2.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--write"), + file_path1.as_os_str().to_str().unwrap(), + file_path2.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -1758,19 +1586,16 @@ file2.js let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from( - [ - ("format"), - ("--vcs-enabled=true"), - ("--vcs-client-kind=git"), - ("--vcs-use-ignore-file=true"), - ("--vcs-root=."), - ("--write"), - file_path1.as_os_str().to_str().unwrap(), - file_path2.as_os_str().to_str().unwrap(), - ] - .as_slice(), - ), + Args::from(&[ + ("format"), + ("--vcs-enabled=true"), + ("--vcs-client-kind=git"), + ("--vcs-use-ignore-file=true"), + ("--vcs-root=."), + ("--write"), + file_path1.as_os_str().to_str().unwrap(), + file_path2.as_os_str().to_str().unwrap(), + ]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); @@ -1785,55 +1610,38 @@ file2.js } #[test] -fn ignores_unknown_file() { +fn ignore_comments_error_when_allow_comments() { let mut fs = MemoryFileSystem::default(); let mut console = BufferConsole::default(); - let file_path1 = Path::new("test.txt"); - fs.insert(file_path1.into(), *b"content"); + let config_json = r#" - let file_path2 = Path::new("test.js"); - fs.insert(file_path2.into(), *b"console.log('bar');\n"); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from( - [ - ("format"), - file_path1.as_os_str().to_str().unwrap(), - file_path2.as_os_str().to_str().unwrap(), - "--files-ignore-unknown=true", - ] - .as_slice(), - ), - ); - - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "ignores_unknown_file", - fs, - console, - result, - )); +{ + "json": { + "allow_comments": ["*.json"] + } } -#[test] -fn doesnt_error_if_no_files_were_processed() { - let mut console = BufferConsole::default(); - let mut fs = MemoryFileSystem::default(); + "#; + let rome_config = "rome.json"; + let code = r#" +[] + "#; + let file_path = Path::new("tsconfig.json"); + fs.insert(file_path.into(), code.as_bytes()); + fs.insert(rome_config.into(), config_json); let result = run_cli( DynRef::Borrowed(&mut fs), &mut console, - Args::from([("format"), "--no-errors-on-unmatched", ("file.js")].as_slice()), + Args::from(&[("format"), file_path.as_os_str().to_str().unwrap()]), ); assert!(result.is_ok(), "run_cli returned {result:?}"); assert_cli_snapshot(SnapshotPayload::new( module_path!(), - "doesnt_error_if_no_files_were_processed", + "ignore_comments_error_when_allow_comments", fs, console, result, diff --git a/crates/rome_cli/tests/snapshots/main_commands_format/ignore_comments_error_when_allow_comments.snap b/crates/rome_cli/tests/snapshots/main_commands_format/ignore_comments_error_when_allow_comments.snap new file mode 100644 index 00000000000..abd731f9fb4 --- /dev/null +++ b/crates/rome_cli/tests/snapshots/main_commands_format/ignore_comments_error_when_allow_comments.snap @@ -0,0 +1,32 @@ +--- +source: crates/rome_cli/tests/snap_test.rs +expression: content +--- +## `format.json` + +```json + +[] + +``` + +# Emitted Messages + +```block +format.json format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Formatter would have printed the following content: + + 1 │ - + 2 1 │ [] + 3 │ - → + 2 │ + + + +``` + +```block +Compared 1 file(s) in