From 60c5d741b7d7e32e40f4e7dc1197793c82de037e Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Thu, 9 Mar 2023 18:20:25 +0100 Subject: [PATCH 1/6] feat(rome_js_analyze): noNamespace --- .../src/categories.rs | 1 + .../src/semantic_analyzers/nursery.rs | 3 +- .../nursery/no_namespace.rs | 80 +++++++++ .../specs/nursery/noNamespace/invalid.ts | 5 + .../specs/nursery/noNamespace/invalid.ts.snap | 79 +++++++++ .../tests/specs/nursery/noNamespace/valid.ts | 7 + .../specs/nursery/noNamespace/valid.ts.snap | 17 ++ .../src/configuration/linter/rules.rs | 162 ++++++++++-------- .../src/configuration/parse/json/rules.rs | 19 ++ editors/vscode/configuration_schema.json | 7 + npm/backend-jsonrpc/src/workspace.ts | 5 + npm/rome/configuration_schema.json | 7 + website/src/pages/lint/rules/index.mdx | 6 + website/src/pages/lint/rules/noNamespace.md | 94 ++++++++++ 14 files changed, 419 insertions(+), 73 deletions(-) create mode 100644 crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs create mode 100644 crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts create mode 100644 crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts.snap create mode 100644 crates/rome_js_analyze/tests/specs/nursery/noNamespace/valid.ts create mode 100644 crates/rome_js_analyze/tests/specs/nursery/noNamespace/valid.ts.snap create mode 100644 website/src/pages/lint/rules/noNamespace.md diff --git a/crates/rome_diagnostics_categories/src/categories.rs b/crates/rome_diagnostics_categories/src/categories.rs index d499e643d23..68d3d50a8b5 100644 --- a/crates/rome_diagnostics_categories/src/categories.rs +++ b/crates/rome_diagnostics_categories/src/categories.rs @@ -98,6 +98,7 @@ define_categories! { "lint/nursery/noSvgWithoutTitle": "https://docs.rome.tools/lint/rules/noSvgWithoutTitle", "lint/nursery/noUselessCatch": "https://docs.rome.tools/lint/rules/noUselessCatch", "lint/nursery/noParameterAssign": "https://docs.rome.tools/lint/rules/noParameterAssign", +"lint/nursery/noNamespace": "https://docs.rome.tools/lint/rules/noNamespace", // Insert new nursery rule here "lint/nursery/noRedeclaration": "https://docs.rome.tools/lint/rules/noRedeclaration", "lint/nursery/useNamespaceKeyword": "https://docs.rome.tools/lint/rules/useNamespaceKeyword", diff --git a/crates/rome_js_analyze/src/semantic_analyzers/nursery.rs b/crates/rome_js_analyze/src/semantic_analyzers/nursery.rs index ed094d956ba..4f626e10a24 100644 --- a/crates/rome_js_analyze/src/semantic_analyzers/nursery.rs +++ b/crates/rome_js_analyze/src/semantic_analyzers/nursery.rs @@ -2,6 +2,7 @@ use rome_analyze::declare_group; mod no_class_assign; +mod no_namespace; mod no_parameter_assign; mod no_redeclaration; mod no_restricted_globals; @@ -9,4 +10,4 @@ mod use_camel_case; mod use_exhaustive_dependencies; mod use_hook_at_top_level; mod use_iframe_title; -declare_group! { pub (crate) Nursery { name : "nursery" , rules : [self :: no_class_assign :: NoClassAssign , self :: no_parameter_assign :: NoParameterAssign , self :: no_redeclaration :: NoRedeclaration , self :: no_restricted_globals :: NoRestrictedGlobals , self :: use_camel_case :: UseCamelCase , self :: use_exhaustive_dependencies :: UseExhaustiveDependencies , self :: use_hook_at_top_level :: UseHookAtTopLevel , self :: use_iframe_title :: UseIframeTitle ,] } } +declare_group! { pub (crate) Nursery { name : "nursery" , rules : [self :: no_class_assign :: NoClassAssign , self :: no_namespace :: NoNamespace , self :: no_parameter_assign :: NoParameterAssign , self :: no_redeclaration :: NoRedeclaration , self :: no_restricted_globals :: NoRestrictedGlobals , self :: use_camel_case :: UseCamelCase , self :: use_exhaustive_dependencies :: UseExhaustiveDependencies , self :: use_hook_at_top_level :: UseHookAtTopLevel , self :: use_iframe_title :: UseIframeTitle ,] } } diff --git a/crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs b/crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs new file mode 100644 index 00000000000..1798cd4f2e4 --- /dev/null +++ b/crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs @@ -0,0 +1,80 @@ +use crate::{semantic_services::Semantic, JsRuleAction}; +use rome_analyze::{context::RuleContext, declare_rule, Rule, RuleDiagnostic}; +use rome_console::markup; +use rome_js_syntax::TsModuleDeclaration; +use rome_rowan::AstNode; + +declare_rule! { + /// Disallow the use of TypeScript's `namespace`s. + /// + /// Namespaces are an old way to organize your code in TypeScript. + /// They are not recommended anymore and should be replaced by ES6 modules + /// (the `import`/`export` syntax). + /// + /// Add a link to the corresponding ESLint rule (if any): + /// + /// Source: https://typescript-eslint.io/rules/no-namespace + /// + /// ## Examples + /// + /// ### Invalid + /// + /// ```ts,expect_diagnostic + /// module foo {} + /// declare module foo {} + /// ``` + /// + /// ```ts,expect_diagnostic + /// namespace foo {} + /// declare namespace foo {} + /// ``` + /// + /// ## Valid + /// + /// ```ts + /// import foo from 'foo'; + /// export { bar }; + /// + /// declare global {} + /// + /// declare module 'foo' {} + /// ``` + /// + pub(crate) NoNamespace { + version: "next", + name: "noNamespace", + recommended: true, + } +} + +impl Rule for NoNamespace { + type Query = Semantic; + type State = (); + type Signals = Option; + type Options = (); + + fn run(_: &RuleContext) -> Self::Signals { + Some(()) + } + + fn diagnostic(ctx: &RuleContext, _: &Self::State) -> Option { + let node = ctx.query(); + + Some( + RuleDiagnostic::new( + rule_category!(), + node.syntax().text_trimmed_range(), + markup! { + "Do not use TypeScript's namespaces." + }, + ) + .note(markup! { + "Prefer the ES6 modules (import/export) over namespaces." + }), + ) + } + + fn action(_: &RuleContext, _: &Self::State) -> Option { + None + } +} diff --git a/crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts b/crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts new file mode 100644 index 00000000000..f2f275ed0e2 --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts @@ -0,0 +1,5 @@ +module foo {} +declare module foo {} + +namespace foo {} +declare namespace foo {} diff --git a/crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts.snap b/crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts.snap new file mode 100644 index 00000000000..73d43a3f291 --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts.snap @@ -0,0 +1,79 @@ +--- +source: crates/rome_js_analyze/tests/spec_tests.rs +expression: invalid.ts +--- +# Input +```js +module foo {} +declare module foo {} + +namespace foo {} +declare namespace foo {} + +``` + +# Diagnostics +``` +invalid.ts:1:1 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not use TypeScript's namespaces. + + > 1 │ module foo {} + │ ^^^^^^^^^^^^^ + 2 │ declare module foo {} + 3 │ + + i Prefer the ES6 modules (import/export) over namespaces. + + +``` + +``` +invalid.ts:2:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not use TypeScript's namespaces. + + 1 │ module foo {} + > 2 │ declare module foo {} + │ ^^^^^^^^^^^^^ + 3 │ + 4 │ namespace foo {} + + i Prefer the ES6 modules (import/export) over namespaces. + + +``` + +``` +invalid.ts:4:1 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not use TypeScript's namespaces. + + 2 │ declare module foo {} + 3 │ + > 4 │ namespace foo {} + │ ^^^^^^^^^^^^^^^^ + 5 │ declare namespace foo {} + 6 │ + + i Prefer the ES6 modules (import/export) over namespaces. + + +``` + +``` +invalid.ts:5:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not use TypeScript's namespaces. + + 4 │ namespace foo {} + > 5 │ declare namespace foo {} + │ ^^^^^^^^^^^^^^^^ + 6 │ + + i Prefer the ES6 modules (import/export) over namespaces. + + +``` + + diff --git a/crates/rome_js_analyze/tests/specs/nursery/noNamespace/valid.ts b/crates/rome_js_analyze/tests/specs/nursery/noNamespace/valid.ts new file mode 100644 index 00000000000..51f485d4609 --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/nursery/noNamespace/valid.ts @@ -0,0 +1,7 @@ +/* should not generate diagnostics */ + +export {}; + +declare global {} + +declare module "foo" {} diff --git a/crates/rome_js_analyze/tests/specs/nursery/noNamespace/valid.ts.snap b/crates/rome_js_analyze/tests/specs/nursery/noNamespace/valid.ts.snap new file mode 100644 index 00000000000..44441ba04a8 --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/nursery/noNamespace/valid.ts.snap @@ -0,0 +1,17 @@ +--- +source: crates/rome_js_analyze/tests/spec_tests.rs +expression: valid.ts +--- +# Input +```js +/* should not generate diagnostics */ + +export {}; + +declare global {} + +declare module "foo" {} + +``` + + diff --git a/crates/rome_service/src/configuration/linter/rules.rs b/crates/rome_service/src/configuration/linter/rules.rs index dd702481eb9..5e968c4b7c4 100644 --- a/crates/rome_service/src/configuration/linter/rules.rs +++ b/crates/rome_service/src/configuration/linter/rules.rs @@ -1214,6 +1214,9 @@ pub struct Nursery { #[doc = "Prevents the incorrect use of super() inside classes. It also checks whether a call super() is missing from classes that extends other constructors."] #[serde(skip_serializing_if = "Option::is_none")] pub no_invalid_constructor_super: Option, + #[doc = "Disallow the use of TypeScript's namespaces."] + #[serde(skip_serializing_if = "Option::is_none")] + pub no_namespace: Option, #[doc = "Enforce that interactive ARIA roles are not assigned to non-interactive HTML elements."] #[serde(skip_serializing_if = "Option::is_none")] pub no_noninteractive_element_to_interactive_role: Option, @@ -1307,7 +1310,7 @@ pub struct Nursery { } impl Nursery { const GROUP_NAME: &'static str = "nursery"; - pub(crate) const GROUP_RULES: [&'static str; 44] = [ + pub(crate) const GROUP_RULES: [&'static str; 45] = [ "noAssignInExpressions", "noBannedTypes", "noClassAssign", @@ -1322,6 +1325,7 @@ impl Nursery { "noInferrableTypes", "noInnerDeclarations", "noInvalidConstructorSuper", + "noNamespace", "noNoninteractiveElementToInteractiveRole", "noParameterAssign", "noParameterProperties", @@ -1353,7 +1357,7 @@ impl Nursery { "useValidLang", "useYield", ]; - const RECOMMENDED_RULES: [&'static str; 37] = [ + const RECOMMENDED_RULES: [&'static str; 38] = [ "noAssignInExpressions", "noBannedTypes", "noClassAssign", @@ -1368,6 +1372,7 @@ impl Nursery { "noInferrableTypes", "noInnerDeclarations", "noInvalidConstructorSuper", + "noNamespace", "noNoninteractiveElementToInteractiveRole", "noParameterAssign", "noRedeclaration", @@ -1392,7 +1397,7 @@ impl Nursery { "useValidLang", "useYield", ]; - const RECOMMENDED_RULES_AS_FILTERS: [RuleFilter<'static>; 37] = [ + const RECOMMENDED_RULES_AS_FILTERS: [RuleFilter<'static>; 38] = [ RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[0]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[1]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[2]), @@ -1409,9 +1414,9 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24]), @@ -1422,16 +1427,17 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[37]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[34]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[41]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[40]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[42]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[43]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[44]), ]; - const ALL_RULES_AS_FILTERS: [RuleFilter<'static>; 44] = [ + const ALL_RULES_AS_FILTERS: [RuleFilter<'static>; 45] = [ RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[0]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[1]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[2]), @@ -1476,6 +1482,7 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[41]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[42]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[43]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[44]), ]; pub(crate) fn is_recommended(&self) -> bool { !matches!(self.recommended, Some(false)) } pub(crate) fn is_all(&self) -> bool { matches!(self.all, Some(true)) } @@ -1552,156 +1559,161 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13])); } } - if let Some(rule) = self.no_noninteractive_element_to_interactive_role.as_ref() { + if let Some(rule) = self.no_namespace.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14])); } } - if let Some(rule) = self.no_parameter_assign.as_ref() { + if let Some(rule) = self.no_noninteractive_element_to_interactive_role.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15])); } } - if let Some(rule) = self.no_parameter_properties.as_ref() { + if let Some(rule) = self.no_parameter_assign.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16])); } } - if let Some(rule) = self.no_prototype_builtins.as_ref() { + if let Some(rule) = self.no_parameter_properties.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17])); } } - if let Some(rule) = self.no_redeclaration.as_ref() { + if let Some(rule) = self.no_prototype_builtins.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18])); } } - if let Some(rule) = self.no_redundant_alt.as_ref() { + if let Some(rule) = self.no_redeclaration.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19])); } } - if let Some(rule) = self.no_restricted_globals.as_ref() { + if let Some(rule) = self.no_redundant_alt.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20])); } } - if let Some(rule) = self.no_self_assign.as_ref() { + if let Some(rule) = self.no_restricted_globals.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21])); } } - if let Some(rule) = self.no_self_compare.as_ref() { + if let Some(rule) = self.no_self_assign.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22])); } } - if let Some(rule) = self.no_svg_without_title.as_ref() { + if let Some(rule) = self.no_self_compare.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23])); } } - if let Some(rule) = self.no_switch_declarations.as_ref() { + if let Some(rule) = self.no_svg_without_title.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24])); } } - if let Some(rule) = self.no_unreachable_super.as_ref() { + if let Some(rule) = self.no_switch_declarations.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25])); } } - if let Some(rule) = self.no_unsafe_optional_chaining.as_ref() { + if let Some(rule) = self.no_unreachable_super.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26])); } } - if let Some(rule) = self.no_unused_labels.as_ref() { + if let Some(rule) = self.no_unsafe_optional_chaining.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27])); } } - if let Some(rule) = self.no_useless_catch.as_ref() { + if let Some(rule) = self.no_unused_labels.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28])); } } - if let Some(rule) = self.no_useless_rename.as_ref() { + if let Some(rule) = self.no_useless_catch.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29])); } } - if let Some(rule) = self.no_useless_switch_case.as_ref() { + if let Some(rule) = self.no_useless_rename.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30])); } } - if let Some(rule) = self.no_with.as_ref() { + if let Some(rule) = self.no_useless_switch_case.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31])); } } - if let Some(rule) = self.use_aria_prop_types.as_ref() { + if let Some(rule) = self.no_with.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32])); } } - if let Some(rule) = self.use_aria_props_for_role.as_ref() { + if let Some(rule) = self.use_aria_prop_types.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33])); } } - if let Some(rule) = self.use_camel_case.as_ref() { + if let Some(rule) = self.use_aria_props_for_role.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[34])); } } - if let Some(rule) = self.use_exhaustive_dependencies.as_ref() { + if let Some(rule) = self.use_camel_case.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35])); } } - if let Some(rule) = self.use_hook_at_top_level.as_ref() { + if let Some(rule) = self.use_exhaustive_dependencies.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36])); } } - if let Some(rule) = self.use_iframe_title.as_ref() { + if let Some(rule) = self.use_hook_at_top_level.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[37])); } } - if let Some(rule) = self.use_is_nan.as_ref() { + if let Some(rule) = self.use_iframe_title.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38])); } } - if let Some(rule) = self.use_media_caption.as_ref() { + if let Some(rule) = self.use_is_nan.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39])); } } - if let Some(rule) = self.use_namespace_keyword.as_ref() { + if let Some(rule) = self.use_media_caption.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[40])); } } - if let Some(rule) = self.use_valid_aria_props.as_ref() { + if let Some(rule) = self.use_namespace_keyword.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[41])); } } - if let Some(rule) = self.use_valid_lang.as_ref() { + if let Some(rule) = self.use_valid_aria_props.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[42])); } } - if let Some(rule) = self.use_yield.as_ref() { + if let Some(rule) = self.use_valid_lang.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[43])); } } + if let Some(rule) = self.use_yield.as_ref() { + if rule.is_enabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[44])); + } + } index_set } pub(crate) fn get_disabled_rules(&self) -> IndexSet { @@ -1776,156 +1788,161 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13])); } } - if let Some(rule) = self.no_noninteractive_element_to_interactive_role.as_ref() { + if let Some(rule) = self.no_namespace.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14])); } } - if let Some(rule) = self.no_parameter_assign.as_ref() { + if let Some(rule) = self.no_noninteractive_element_to_interactive_role.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15])); } } - if let Some(rule) = self.no_parameter_properties.as_ref() { + if let Some(rule) = self.no_parameter_assign.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16])); } } - if let Some(rule) = self.no_prototype_builtins.as_ref() { + if let Some(rule) = self.no_parameter_properties.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17])); } } - if let Some(rule) = self.no_redeclaration.as_ref() { + if let Some(rule) = self.no_prototype_builtins.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18])); } } - if let Some(rule) = self.no_redundant_alt.as_ref() { + if let Some(rule) = self.no_redeclaration.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19])); } } - if let Some(rule) = self.no_restricted_globals.as_ref() { + if let Some(rule) = self.no_redundant_alt.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20])); } } - if let Some(rule) = self.no_self_assign.as_ref() { + if let Some(rule) = self.no_restricted_globals.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21])); } } - if let Some(rule) = self.no_self_compare.as_ref() { + if let Some(rule) = self.no_self_assign.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22])); } } - if let Some(rule) = self.no_svg_without_title.as_ref() { + if let Some(rule) = self.no_self_compare.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23])); } } - if let Some(rule) = self.no_switch_declarations.as_ref() { + if let Some(rule) = self.no_svg_without_title.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24])); } } - if let Some(rule) = self.no_unreachable_super.as_ref() { + if let Some(rule) = self.no_switch_declarations.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25])); } } - if let Some(rule) = self.no_unsafe_optional_chaining.as_ref() { + if let Some(rule) = self.no_unreachable_super.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26])); } } - if let Some(rule) = self.no_unused_labels.as_ref() { + if let Some(rule) = self.no_unsafe_optional_chaining.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27])); } } - if let Some(rule) = self.no_useless_catch.as_ref() { + if let Some(rule) = self.no_unused_labels.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28])); } } - if let Some(rule) = self.no_useless_rename.as_ref() { + if let Some(rule) = self.no_useless_catch.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29])); } } - if let Some(rule) = self.no_useless_switch_case.as_ref() { + if let Some(rule) = self.no_useless_rename.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30])); } } - if let Some(rule) = self.no_with.as_ref() { + if let Some(rule) = self.no_useless_switch_case.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31])); } } - if let Some(rule) = self.use_aria_prop_types.as_ref() { + if let Some(rule) = self.no_with.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32])); } } - if let Some(rule) = self.use_aria_props_for_role.as_ref() { + if let Some(rule) = self.use_aria_prop_types.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33])); } } - if let Some(rule) = self.use_camel_case.as_ref() { + if let Some(rule) = self.use_aria_props_for_role.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[34])); } } - if let Some(rule) = self.use_exhaustive_dependencies.as_ref() { + if let Some(rule) = self.use_camel_case.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35])); } } - if let Some(rule) = self.use_hook_at_top_level.as_ref() { + if let Some(rule) = self.use_exhaustive_dependencies.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36])); } } - if let Some(rule) = self.use_iframe_title.as_ref() { + if let Some(rule) = self.use_hook_at_top_level.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[37])); } } - if let Some(rule) = self.use_is_nan.as_ref() { + if let Some(rule) = self.use_iframe_title.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38])); } } - if let Some(rule) = self.use_media_caption.as_ref() { + if let Some(rule) = self.use_is_nan.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39])); } } - if let Some(rule) = self.use_namespace_keyword.as_ref() { + if let Some(rule) = self.use_media_caption.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[40])); } } - if let Some(rule) = self.use_valid_aria_props.as_ref() { + if let Some(rule) = self.use_namespace_keyword.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[41])); } } - if let Some(rule) = self.use_valid_lang.as_ref() { + if let Some(rule) = self.use_valid_aria_props.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[42])); } } - if let Some(rule) = self.use_yield.as_ref() { + if let Some(rule) = self.use_valid_lang.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[43])); } } + if let Some(rule) = self.use_yield.as_ref() { + if rule.is_disabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[44])); + } + } index_set } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] @@ -1934,10 +1951,10 @@ impl Nursery { pub(crate) fn is_recommended_rule(rule_name: &str) -> bool { Self::RECOMMENDED_RULES.contains(&rule_name) } - pub(crate) fn recommended_rules_as_filters() -> [RuleFilter<'static>; 37] { + pub(crate) fn recommended_rules_as_filters() -> [RuleFilter<'static>; 38] { Self::RECOMMENDED_RULES_AS_FILTERS } - pub(crate) fn all_rules_as_filters() -> [RuleFilter<'static>; 44] { Self::ALL_RULES_AS_FILTERS } + pub(crate) fn all_rules_as_filters() -> [RuleFilter<'static>; 45] { Self::ALL_RULES_AS_FILTERS } #[doc = r" Select preset rules"] pub(crate) fn collect_preset_rules( &self, @@ -1969,6 +1986,7 @@ impl Nursery { "noInferrableTypes" => self.no_inferrable_types.as_ref(), "noInnerDeclarations" => self.no_inner_declarations.as_ref(), "noInvalidConstructorSuper" => self.no_invalid_constructor_super.as_ref(), + "noNamespace" => self.no_namespace.as_ref(), "noNoninteractiveElementToInteractiveRole" => { self.no_noninteractive_element_to_interactive_role.as_ref() } diff --git a/crates/rome_service/src/configuration/parse/json/rules.rs b/crates/rome_service/src/configuration/parse/json/rules.rs index c684fad4706..c701844ed4d 100644 --- a/crates/rome_service/src/configuration/parse/json/rules.rs +++ b/crates/rome_service/src/configuration/parse/json/rules.rs @@ -925,6 +925,7 @@ impl VisitNode for Nursery { "noInferrableTypes", "noInnerDeclarations", "noInvalidConstructorSuper", + "noNamespace", "noNoninteractiveElementToInteractiveRole", "noParameterAssign", "noParameterProperties", @@ -1226,6 +1227,24 @@ impl VisitNode for Nursery { )); } }, + "noNamespace" => match value { + AnyJsonValue::JsonStringValue(_) => { + let mut configuration = RuleConfiguration::default(); + self.map_to_known_string(&value, name_text, &mut configuration, diagnostics)?; + self.no_namespace = Some(configuration); + } + AnyJsonValue::JsonObjectValue(_) => { + let mut configuration = RuleConfiguration::default(); + self.map_to_object(&value, name_text, &mut configuration, diagnostics)?; + self.no_namespace = Some(configuration); + } + _ => { + diagnostics.push(DeserializationDiagnostic::new_incorrect_type( + "object or string", + value.range(), + )); + } + }, "noNoninteractiveElementToInteractiveRole" => match value { AnyJsonValue::JsonStringValue(_) => { let mut configuration = RuleConfiguration::default(); diff --git a/editors/vscode/configuration_schema.json b/editors/vscode/configuration_schema.json index c061a5bf11f..1ed2bd6bb99 100644 --- a/editors/vscode/configuration_schema.json +++ b/editors/vscode/configuration_schema.json @@ -580,6 +580,13 @@ { "type": "null" } ] }, + "noNamespace": { + "description": "Disallow the use of TypeScript's namespaces.", + "anyOf": [ + { "$ref": "#/definitions/RuleConfiguration" }, + { "type": "null" } + ] + }, "noNoninteractiveElementToInteractiveRole": { "description": "Enforce that interactive ARIA roles are not assigned to non-interactive HTML elements.", "anyOf": [ diff --git a/npm/backend-jsonrpc/src/workspace.ts b/npm/backend-jsonrpc/src/workspace.ts index beec47f6adf..704754fcd90 100644 --- a/npm/backend-jsonrpc/src/workspace.ts +++ b/npm/backend-jsonrpc/src/workspace.ts @@ -408,6 +408,10 @@ export interface Nursery { * Prevents the incorrect use of super() inside classes. It also checks whether a call super() is missing from classes that extends other constructors. */ noInvalidConstructorSuper?: RuleConfiguration; + /** + * Disallow the use of TypeScript's namespaces. + */ + noNamespace?: RuleConfiguration; /** * Enforce that interactive ARIA roles are not assigned to non-interactive HTML elements. */ @@ -924,6 +928,7 @@ export type Category = | "lint/nursery/noSvgWithoutTitle" | "lint/nursery/noUselessCatch" | "lint/nursery/noParameterAssign" + | "lint/nursery/noNamespace" | "lint/nursery/noRedeclaration" | "lint/nursery/useNamespaceKeyword" | "lint/performance/noDelete" diff --git a/npm/rome/configuration_schema.json b/npm/rome/configuration_schema.json index c061a5bf11f..1ed2bd6bb99 100644 --- a/npm/rome/configuration_schema.json +++ b/npm/rome/configuration_schema.json @@ -580,6 +580,13 @@ { "type": "null" } ] }, + "noNamespace": { + "description": "Disallow the use of TypeScript's namespaces.", + "anyOf": [ + { "$ref": "#/definitions/RuleConfiguration" }, + { "type": "null" } + ] + }, "noNoninteractiveElementToInteractiveRole": { "description": "Enforce that interactive ARIA roles are not assigned to non-interactive HTML elements.", "anyOf": [ diff --git a/website/src/pages/lint/rules/index.mdx b/website/src/pages/lint/rules/index.mdx index dc632daf45e..621c9f30b92 100644 --- a/website/src/pages/lint/rules/index.mdx +++ b/website/src/pages/lint/rules/index.mdx @@ -720,6 +720,12 @@ Prevents the incorrect use of super() inside classes. It also checks whether a call super() is missing from classes that extends other constructors.
+

+ noNamespace +

+Disallow the use of TypeScript's namespaces. +
+

noNoninteractiveElementToInteractiveRole

diff --git a/website/src/pages/lint/rules/noNamespace.md b/website/src/pages/lint/rules/noNamespace.md new file mode 100644 index 00000000000..980cbf622a7 --- /dev/null +++ b/website/src/pages/lint/rules/noNamespace.md @@ -0,0 +1,94 @@ +--- +title: Lint Rule noNamespace +parent: lint/rules/index +--- + +# noNamespace (since vnext) + +Disallow the use of TypeScript's `namespace`s. + +Namespaces are an old way to organize your code in TypeScript. +They are not recommended anymore and should be replaced by ES6 modules +(the `import`/`export` syntax). + +Add a link to the corresponding ESLint rule (if any): + +Source: https://typescript-eslint.io/rules/no-namespace + +## Examples + +### Invalid + +```ts +module foo {} +declare module foo {} +``` + +
nursery/noNamespace.js:1:1 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+   Do not use TypeScript's namespaces.
+  
+  > 1 │ module foo {}
+   ^^^^^^^^^^^^^
+    2 │ declare module foo {}
+    3 │ 
+  
+   Prefer the ES6 modules (import/export) over namespaces.
+  
+nursery/noNamespace.js:2:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+   Do not use TypeScript's namespaces.
+  
+    1 │ module foo {}
+  > 2 │ declare module foo {}
+           ^^^^^^^^^^^^^
+    3 │ 
+  
+   Prefer the ES6 modules (import/export) over namespaces.
+  
+
+ +```ts +namespace foo {} +declare namespace foo {} +``` + +
nursery/noNamespace.js:1:1 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+   Do not use TypeScript's namespaces.
+  
+  > 1 │ namespace foo {}
+   ^^^^^^^^^^^^^^^^
+    2 │ declare namespace foo {}
+    3 │ 
+  
+   Prefer the ES6 modules (import/export) over namespaces.
+  
+nursery/noNamespace.js:2:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+   Do not use TypeScript's namespaces.
+  
+    1 │ namespace foo {}
+  > 2 │ declare namespace foo {}
+           ^^^^^^^^^^^^^^^^
+    3 │ 
+  
+   Prefer the ES6 modules (import/export) over namespaces.
+  
+
+ +## Valid + +```ts +import foo from 'foo'; +export { bar }; + +declare global {} + +declare module 'foo' {} +``` + +## Related links + +- [Disable a rule](/linter/#disable-a-lint-rule) +- [Rule options](/linter/#rule-options) From d2883a61726edb1545ed6d86108e524ab18c03c5 Mon Sep 17 00:00:00 2001 From: Elliot Date: Fri, 10 Mar 2023 09:14:39 +0100 Subject: [PATCH 2/6] Reword error message Co-authored-by: Victorien ELVINGER --- .../src/semantic_analyzers/nursery/no_namespace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs b/crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs index 1798cd4f2e4..cc1518ec2ff 100644 --- a/crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs +++ b/crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs @@ -65,7 +65,7 @@ impl Rule for NoNamespace { rule_category!(), node.syntax().text_trimmed_range(), markup! { - "Do not use TypeScript's namespaces." + "TypeScript's namespaces are an oudated way to organize code." }, ) .note(markup! { From 554adc00ff8888524dc8397170aa016aceb70d45 Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Fri, 10 Mar 2023 09:45:57 +0100 Subject: [PATCH 3/6] Move rule from semantic_analyzer to analyzer --- crates/rome_js_analyze/src/analyzers/nursery.rs | 3 ++- .../nursery/no_namespace.rs | 9 ++------- crates/rome_js_analyze/src/semantic_analyzers/nursery.rs | 3 +-- .../tests/specs/nursery/noNamespace/invalid.ts.snap | 8 ++++---- website/src/pages/lint/rules/noNamespace.md | 8 ++++---- 5 files changed, 13 insertions(+), 18 deletions(-) rename crates/rome_js_analyze/src/{semantic_analyzers => analyzers}/nursery/no_namespace.rs (86%) diff --git a/crates/rome_js_analyze/src/analyzers/nursery.rs b/crates/rome_js_analyze/src/analyzers/nursery.rs index b53a0f9a387..19aa70a982d 100644 --- a/crates/rome_js_analyze/src/analyzers/nursery.rs +++ b/crates/rome_js_analyze/src/analyzers/nursery.rs @@ -14,6 +14,7 @@ mod no_global_object_calls; mod no_inferrable_types; mod no_inner_declarations; mod no_invalid_constructor_super; +mod no_namespace; mod no_parameter_properties; mod no_prototype_builtins; mod no_redundant_alt; @@ -32,4 +33,4 @@ mod use_is_nan; mod use_media_caption; mod use_namespace_keyword; mod use_yield; -declare_group! { pub (crate) Nursery { name : "nursery" , rules : [self :: no_assign_in_expressions :: NoAssignInExpressions , self :: no_banned_types :: NoBannedTypes , self :: no_comma_operator :: NoCommaOperator , self :: no_confusing_labels :: NoConfusingLabels , self :: no_duplicate_case :: NoDuplicateCase , self :: no_duplicate_class_members :: NoDuplicateClassMembers , self :: no_duplicate_jsx_props :: NoDuplicateJsxProps , self :: no_extra_labels :: NoExtraLabels , self :: no_extra_semicolons :: NoExtraSemicolons , self :: no_global_object_calls :: NoGlobalObjectCalls , self :: no_inferrable_types :: NoInferrableTypes , self :: no_inner_declarations :: NoInnerDeclarations , self :: no_invalid_constructor_super :: NoInvalidConstructorSuper , self :: no_parameter_properties :: NoParameterProperties , self :: no_prototype_builtins :: NoPrototypeBuiltins , self :: no_redundant_alt :: NoRedundantAlt , self :: no_self_assign :: NoSelfAssign , self :: no_self_compare :: NoSelfCompare , self :: no_svg_without_title :: NoSvgWithoutTitle , self :: no_switch_declarations :: NoSwitchDeclarations , self :: no_unreachable_super :: NoUnreachableSuper , self :: no_unsafe_optional_chaining :: NoUnsafeOptionalChaining , self :: no_unused_labels :: NoUnusedLabels , self :: no_useless_catch :: NoUselessCatch , self :: no_useless_rename :: NoUselessRename , self :: no_useless_switch_case :: NoUselessSwitchCase , self :: no_with :: NoWith , self :: use_is_nan :: UseIsNan , self :: use_media_caption :: UseMediaCaption , self :: use_namespace_keyword :: UseNamespaceKeyword , self :: use_yield :: UseYield ,] } } +declare_group! { pub (crate) Nursery { name : "nursery" , rules : [self :: no_assign_in_expressions :: NoAssignInExpressions , self :: no_banned_types :: NoBannedTypes , self :: no_comma_operator :: NoCommaOperator , self :: no_confusing_labels :: NoConfusingLabels , self :: no_duplicate_case :: NoDuplicateCase , self :: no_duplicate_class_members :: NoDuplicateClassMembers , self :: no_duplicate_jsx_props :: NoDuplicateJsxProps , self :: no_extra_labels :: NoExtraLabels , self :: no_extra_semicolons :: NoExtraSemicolons , self :: no_global_object_calls :: NoGlobalObjectCalls , self :: no_inferrable_types :: NoInferrableTypes , self :: no_inner_declarations :: NoInnerDeclarations , self :: no_invalid_constructor_super :: NoInvalidConstructorSuper , self :: no_namespace :: NoNamespace , self :: no_parameter_properties :: NoParameterProperties , self :: no_prototype_builtins :: NoPrototypeBuiltins , self :: no_redundant_alt :: NoRedundantAlt , self :: no_self_assign :: NoSelfAssign , self :: no_self_compare :: NoSelfCompare , self :: no_svg_without_title :: NoSvgWithoutTitle , self :: no_switch_declarations :: NoSwitchDeclarations , self :: no_unreachable_super :: NoUnreachableSuper , self :: no_unsafe_optional_chaining :: NoUnsafeOptionalChaining , self :: no_unused_labels :: NoUnusedLabels , self :: no_useless_catch :: NoUselessCatch , self :: no_useless_rename :: NoUselessRename , self :: no_useless_switch_case :: NoUselessSwitchCase , self :: no_with :: NoWith , self :: use_is_nan :: UseIsNan , self :: use_media_caption :: UseMediaCaption , self :: use_namespace_keyword :: UseNamespaceKeyword , self :: use_yield :: UseYield ,] } } diff --git a/crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs b/crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs similarity index 86% rename from crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs rename to crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs index cc1518ec2ff..4a90e623c12 100644 --- a/crates/rome_js_analyze/src/semantic_analyzers/nursery/no_namespace.rs +++ b/crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs @@ -1,5 +1,4 @@ -use crate::{semantic_services::Semantic, JsRuleAction}; -use rome_analyze::{context::RuleContext, declare_rule, Rule, RuleDiagnostic}; +use rome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic}; use rome_console::markup; use rome_js_syntax::TsModuleDeclaration; use rome_rowan::AstNode; @@ -48,7 +47,7 @@ declare_rule! { } impl Rule for NoNamespace { - type Query = Semantic; + type Query = Ast; type State = (); type Signals = Option; type Options = (); @@ -73,8 +72,4 @@ impl Rule for NoNamespace { }), ) } - - fn action(_: &RuleContext, _: &Self::State) -> Option { - None - } } diff --git a/crates/rome_js_analyze/src/semantic_analyzers/nursery.rs b/crates/rome_js_analyze/src/semantic_analyzers/nursery.rs index 4f626e10a24..ed094d956ba 100644 --- a/crates/rome_js_analyze/src/semantic_analyzers/nursery.rs +++ b/crates/rome_js_analyze/src/semantic_analyzers/nursery.rs @@ -2,7 +2,6 @@ use rome_analyze::declare_group; mod no_class_assign; -mod no_namespace; mod no_parameter_assign; mod no_redeclaration; mod no_restricted_globals; @@ -10,4 +9,4 @@ mod use_camel_case; mod use_exhaustive_dependencies; mod use_hook_at_top_level; mod use_iframe_title; -declare_group! { pub (crate) Nursery { name : "nursery" , rules : [self :: no_class_assign :: NoClassAssign , self :: no_namespace :: NoNamespace , self :: no_parameter_assign :: NoParameterAssign , self :: no_redeclaration :: NoRedeclaration , self :: no_restricted_globals :: NoRestrictedGlobals , self :: use_camel_case :: UseCamelCase , self :: use_exhaustive_dependencies :: UseExhaustiveDependencies , self :: use_hook_at_top_level :: UseHookAtTopLevel , self :: use_iframe_title :: UseIframeTitle ,] } } +declare_group! { pub (crate) Nursery { name : "nursery" , rules : [self :: no_class_assign :: NoClassAssign , self :: no_parameter_assign :: NoParameterAssign , self :: no_redeclaration :: NoRedeclaration , self :: no_restricted_globals :: NoRestrictedGlobals , self :: use_camel_case :: UseCamelCase , self :: use_exhaustive_dependencies :: UseExhaustiveDependencies , self :: use_hook_at_top_level :: UseHookAtTopLevel , self :: use_iframe_title :: UseIframeTitle ,] } } diff --git a/crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts.snap b/crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts.snap index 73d43a3f291..ff2a77efb37 100644 --- a/crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts.snap +++ b/crates/rome_js_analyze/tests/specs/nursery/noNamespace/invalid.ts.snap @@ -16,7 +16,7 @@ declare namespace foo {} ``` invalid.ts:1:1 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Do not use TypeScript's namespaces. + ! TypeScript's namespaces are an oudated way to organize code. > 1 │ module foo {} │ ^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ invalid.ts:1:1 lint/nursery/noNamespace ━━━━━━━━━━━━━ ``` invalid.ts:2:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Do not use TypeScript's namespaces. + ! TypeScript's namespaces are an oudated way to organize code. 1 │ module foo {} > 2 │ declare module foo {} @@ -47,7 +47,7 @@ invalid.ts:2:9 lint/nursery/noNamespace ━━━━━━━━━━━━━ ``` invalid.ts:4:1 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Do not use TypeScript's namespaces. + ! TypeScript's namespaces are an oudated way to organize code. 2 │ declare module foo {} 3 │ @@ -64,7 +64,7 @@ invalid.ts:4:1 lint/nursery/noNamespace ━━━━━━━━━━━━━ ``` invalid.ts:5:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Do not use TypeScript's namespaces. + ! TypeScript's namespaces are an oudated way to organize code. 4 │ namespace foo {} > 5 │ declare namespace foo {} diff --git a/website/src/pages/lint/rules/noNamespace.md b/website/src/pages/lint/rules/noNamespace.md index 980cbf622a7..db27905bd8a 100644 --- a/website/src/pages/lint/rules/noNamespace.md +++ b/website/src/pages/lint/rules/noNamespace.md @@ -26,7 +26,7 @@ declare module foo {}
nursery/noNamespace.js:1:1 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
-   Do not use TypeScript's namespaces.
+   TypeScript's namespaces are an oudated way to organize code.
   
   > 1 │ module foo {}
    ^^^^^^^^^^^^^
@@ -37,7 +37,7 @@ declare module foo {}
   
 nursery/noNamespace.js:2:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
-   Do not use TypeScript's namespaces.
+   TypeScript's namespaces are an oudated way to organize code.
   
     1 │ module foo {}
   > 2 │ declare module foo {}
@@ -55,7 +55,7 @@ declare namespace foo {}
 
 
nursery/noNamespace.js:1:1 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
-   Do not use TypeScript's namespaces.
+   TypeScript's namespaces are an oudated way to organize code.
   
   > 1 │ namespace foo {}
    ^^^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@ declare namespace foo {}
   
 nursery/noNamespace.js:2:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
-   Do not use TypeScript's namespaces.
+   TypeScript's namespaces are an oudated way to organize code.
   
     1 │ namespace foo {}
   > 2 │ declare namespace foo {}

From 1c47260d8b58cc926910731f0d5a7cd8c86152b1 Mon Sep 17 00:00:00 2001
From: Elliot 
Date: Fri, 10 Mar 2023 11:48:10 +0100
Subject: [PATCH 4/6] Set version to v12

Co-authored-by: Victorien ELVINGER 
---
 crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs b/crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs
index 4a90e623c12..1ebe624aa69 100644
--- a/crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs
+++ b/crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs
@@ -40,7 +40,7 @@ declare_rule! {
     /// ```
     ///
     pub(crate) NoNamespace {
-        version: "next",
+        version: "12.0.0",
         name: "noNamespace",
         recommended: true,
     }

From bfdaa48e4b255975869ad082dce320bceddbda7a Mon Sep 17 00:00:00 2001
From: Elliot Maisl 
Date: Fri, 10 Mar 2023 12:05:01 +0100
Subject: [PATCH 5/6] Separate the code samples

---
 .../src/analyzers/nursery/no_namespace.rs     | 10 +++++
 website/src/pages/lint/rules/noNamespace.md   | 40 ++++++++++++-------
 2 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs b/crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs
index 1ebe624aa69..ced5bac6f6b 100644
--- a/crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs
+++ b/crates/rome_js_analyze/src/analyzers/nursery/no_namespace.rs
@@ -20,11 +20,17 @@ declare_rule! {
     ///
     /// ```ts,expect_diagnostic
     /// module foo {}
+    /// ```
+    ///
+    /// ```ts,expect_diagnostic
     /// declare module foo {}
     /// ```
     ///
     /// ```ts,expect_diagnostic
     /// namespace foo {}
+    /// ```
+    ///
+    /// ```ts,expect_diagnostic
     /// declare namespace foo {}
     /// ```
     ///
@@ -33,9 +39,13 @@ declare_rule! {
     /// ```ts
     /// import foo from 'foo';
     /// export { bar };
+    /// ```
     ///
+    /// ```ts
     /// declare global {}
+    /// ```
     ///
+    /// ```ts
     /// declare module 'foo' {}
     /// ```
     ///
diff --git a/website/src/pages/lint/rules/noNamespace.md b/website/src/pages/lint/rules/noNamespace.md
index db27905bd8a..9ad4ad069a8 100644
--- a/website/src/pages/lint/rules/noNamespace.md
+++ b/website/src/pages/lint/rules/noNamespace.md
@@ -3,7 +3,7 @@ title: Lint Rule noNamespace
 parent: lint/rules/index
 ---
 
-# noNamespace (since vnext)
+# noNamespace (since v12.0.0)
 
 Disallow the use of TypeScript's `namespace`s.
 
@@ -21,7 +21,6 @@ Source: https://typescript-eslint.io/rules/no-namespace
 
 ```ts
 module foo {}
-declare module foo {}
 ```
 
 
nursery/noNamespace.js:1:1 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -30,19 +29,23 @@ declare module foo {}
   
   > 1 │ module foo {}
    ^^^^^^^^^^^^^
-    2 │ declare module foo {}
-    3 │ 
+    2 │ 
   
    Prefer the ES6 modules (import/export) over namespaces.
   
-nursery/noNamespace.js:2:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+ +```ts +declare module foo {} +``` + +
nursery/noNamespace.js:1:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
    TypeScript's namespaces are an oudated way to organize code.
   
-    1 │ module foo {}
-  > 2 │ declare module foo {}
+  > 1 │ declare module foo {}
            ^^^^^^^^^^^^^
-    3 │ 
+    2 │ 
   
    Prefer the ES6 modules (import/export) over namespaces.
   
@@ -50,7 +53,6 @@ nursery/noNamespace.js:2:9 nursery/noNamespace.js:1:1 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -59,19 +61,23 @@ declare namespace foo {}
   
   > 1 │ namespace foo {}
    ^^^^^^^^^^^^^^^^
-    2 │ declare namespace foo {}
-    3 │ 
+    2 │ 
   
    Prefer the ES6 modules (import/export) over namespaces.
   
-nursery/noNamespace.js:2:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+ +```ts +declare namespace foo {} +``` + +
nursery/noNamespace.js:1:9 lint/nursery/noNamespace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
    TypeScript's namespaces are an oudated way to organize code.
   
-    1 │ namespace foo {}
-  > 2 │ declare namespace foo {}
+  > 1 │ declare namespace foo {}
            ^^^^^^^^^^^^^^^^
-    3 │ 
+    2 │ 
   
    Prefer the ES6 modules (import/export) over namespaces.
   
@@ -82,9 +88,13 @@ nursery/noNamespace.js:2:9