diff --git a/crates/oxc_linter/src/config/flat.rs b/crates/oxc_linter/src/config/flat.rs index dea2b9129a6ac0..5c657dd92211ed 100644 --- a/crates/oxc_linter/src/config/flat.rs +++ b/crates/oxc_linter/src/config/flat.rs @@ -186,7 +186,10 @@ mod test { #[allow(clippy::default_trait_access)] fn no_explicit_any() -> RuleWithSeverity { - RuleWithSeverity::new(RuleEnum::NoExplicitAny(Default::default()), AllowWarnDeny::Warn) + RuleWithSeverity::new( + RuleEnum::TypescriptNoExplicitAny(Default::default()), + AllowWarnDeny::Warn, + ) } /// an empty ruleset is a no-op diff --git a/crates/oxc_linter/src/config/rules.rs b/crates/oxc_linter/src/config/rules.rs index ce140ce642f546..cdd1c68c28556a 100644 --- a/crates/oxc_linter/src/config/rules.rs +++ b/crates/oxc_linter/src/config/rules.rs @@ -431,7 +431,7 @@ mod test { fn test_override_allow() { let mut rules = RuleSet::default(); rules.insert(RuleWithSeverity { - rule: RuleEnum::NoConsole(Default::default()), + rule: RuleEnum::EslintNoConsole(Default::default()), severity: AllowWarnDeny::Deny, }); r#override(&mut rules, &json!({ "eslint/no-console": "off" })); @@ -461,7 +461,7 @@ mod test { for config in &configs { let mut rules = RuleSet::default(); rules.insert(RuleWithSeverity { - rule: RuleEnum::NoUnusedVars(Default::default()), + rule: RuleEnum::EslintNoUnusedVars(Default::default()), severity: AllowWarnDeny::Warn, }); r#override(&mut rules, config); diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 24276f83686ab7..aa9864ebd5a968 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -12,7 +12,6 @@ mod import { pub mod default; pub mod export; pub mod first; - pub mod import_no_namespace; pub mod max_dependencies; pub mod named; pub mod namespace; @@ -24,6 +23,7 @@ mod import { pub mod no_dynamic_require; pub mod no_named_as_default; pub mod no_named_as_default_member; + pub mod no_namespace; pub mod no_self_import; pub mod no_webpack_loader_syntax; pub mod unambiguous; @@ -639,7 +639,7 @@ oxc_macros::declare_all_lint_rules! { import::default, import::export, import::first, - import::import_no_namespace, + import::no_namespace, import::max_dependencies, import::named, import::namespace, diff --git a/crates/oxc_linter/src/rules/import/import_no_namespace.rs b/crates/oxc_linter/src/rules/import/no_namespace.rs similarity index 90% rename from crates/oxc_linter/src/rules/import/import_no_namespace.rs rename to crates/oxc_linter/src/rules/import/no_namespace.rs index 09ede4e7b88de8..7d548a7174c1c9 100644 --- a/crates/oxc_linter/src/rules/import/import_no_namespace.rs +++ b/crates/oxc_linter/src/rules/import/no_namespace.rs @@ -7,22 +7,22 @@ use oxc_syntax::module_record::ImportImportName; use crate::{context::LintContext, rule::Rule}; -fn import_no_namespace_diagnostic(span: Span) -> OxcDiagnostic { +fn no_namespace_diagnostic(span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("Usage of namespaced aka wildcard \"*\" imports prohibited") .with_help("Use named or default imports") .with_label(span) } #[derive(Debug, Default, Clone)] -pub struct ImportNoNamespace(Box); +pub struct NoNamespace(Box); #[derive(Debug, Default, Clone)] -pub struct ImportNoNamespaceConfig { +pub struct NoNamespaceConfig { ignore: Vec, } -impl std::ops::Deref for ImportNoNamespace { - type Target = ImportNoNamespaceConfig; +impl std::ops::Deref for NoNamespace { + type Target = NoNamespaceConfig; fn deref(&self) -> &Self::Target { &self.0 @@ -77,16 +77,16 @@ declare_oxc_lint!( /// import defaultExport, { isUser } from './user'; /// ``` /// - ImportNoNamespace, + NoNamespace, style, pending // TODO: fixer ); /// -impl Rule for ImportNoNamespace { +impl Rule for NoNamespace { fn from_configuration(value: serde_json::Value) -> Self { let obj = value.get(0); - Self(Box::new(ImportNoNamespaceConfig { + Self(Box::new(NoNamespaceConfig { ignore: obj .and_then(|v| v.get("ignore")) .and_then(serde_json::Value::as_array) @@ -110,7 +110,7 @@ impl Rule for ImportNoNamespace { let source = entry.module_request.name(); if self.ignore.is_empty() { - ctx.diagnostic(import_no_namespace_diagnostic(entry.local_name.span())); + ctx.diagnostic(no_namespace_diagnostic(entry.local_name.span())); } else { if !source.contains('.') { return; @@ -124,7 +124,7 @@ impl Rule for ImportNoNamespace { return; } - ctx.diagnostic(import_no_namespace_diagnostic(entry.local_name.span())); + ctx.diagnostic(no_namespace_diagnostic(entry.local_name.span())); } } ImportImportName::Name(_) | ImportImportName::Default(_) => {} @@ -159,7 +159,7 @@ fn test() { (r"import * as foo from './foo';", None), ]; - Tester::new(ImportNoNamespace::NAME, pass, fail) + Tester::new(NoNamespace::NAME, pass, fail) .change_rule_path("index.js") .with_import_plugin(true) .test_and_snapshot(); diff --git a/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs b/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs index 6aa20a763626b9..b075f84655e4ce 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs @@ -208,7 +208,7 @@ impl Rule for AutocompleteValid { #[test] fn test() { - use crate::{rules::AutocompleteValid, tester::Tester}; + use crate::tester::Tester; fn settings() -> serde_json::Value { serde_json::json!({ diff --git a/crates/oxc_linter/src/rules/jsx_a11y/no_redundant_roles.rs b/crates/oxc_linter/src/rules/jsx_a11y/no_redundant_roles.rs index f4d53b514667eb..e00b2b9dcc6474 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/no_redundant_roles.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/no_redundant_roles.rs @@ -84,7 +84,7 @@ impl Rule for NoRedundantRoles { #[test] fn test() { - use crate::{rules::NoRedundantRoles, tester::Tester}; + use crate::tester::Tester; fn settings() -> serde_json::Value { serde_json::json!({ diff --git a/crates/oxc_linter/src/rules/jsx_a11y/role_has_required_aria_props.rs b/crates/oxc_linter/src/rules/jsx_a11y/role_has_required_aria_props.rs index a4e4692ea6cbd6..6236a938522703 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/role_has_required_aria_props.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/role_has_required_aria_props.rs @@ -84,7 +84,7 @@ impl Rule for RoleHasRequiredAriaProps { #[test] fn test() { - use crate::{rules::RoleHasRequiredAriaProps, tester::Tester}; + use crate::tester::Tester; fn settings() -> serde_json::Value { serde_json::json!({ diff --git a/crates/oxc_linter/src/rules/security/api_keys/secrets/aws_access_token.rs b/crates/oxc_linter/src/rules/security/api_keys/secrets/aws_access_token.rs index 20b789079031a5..a99375f2dea6cd 100644 --- a/crates/oxc_linter/src/rules/security/api_keys/secrets/aws_access_token.rs +++ b/crates/oxc_linter/src/rules/security/api_keys/secrets/aws_access_token.rs @@ -68,7 +68,7 @@ static AWS_TOKEN_PREFIXES: Map<&'static str, &'static str> = phf_map! { #[test] fn test() { - use crate::{rules::ApiKeys, tester::Tester, RuleMeta}; + use crate::{rules::SecurityApiKeys, tester::Tester, RuleMeta}; let pass = vec![ "let x = ''", @@ -94,7 +94,7 @@ fn test() { "let key = 'AKIAAABCD1099FAM9KEY'", ]; - Tester::new(ApiKeys::NAME, pass, fail) + Tester::new(SecurityApiKeys::NAME, pass, fail) .with_snapshot_suffix("aws_access_token") .test_and_snapshot(); } diff --git a/crates/oxc_linter/src/tester.rs b/crates/oxc_linter/src/tester.rs index 8403dd394b44de..b8f0a9b6803ebb 100644 --- a/crates/oxc_linter/src/tester.rs +++ b/crates/oxc_linter/src/tester.rs @@ -350,7 +350,10 @@ impl Tester { } settings.bind(|| { - insta::assert_snapshot!(name.as_ref(), self.snapshot); + insta::assert_snapshot!( + format!("{}_{}", self.find_rule().plugin_name(), name.as_ref()), + self.snapshot + ); }); } diff --git a/crates/oxc_macros/src/declare_all_lint_rules.rs b/crates/oxc_macros/src/declare_all_lint_rules.rs index 0394bbdafaf5e7..9ad10bd1460f6e 100644 --- a/crates/oxc_macros/src/declare_all_lint_rules.rs +++ b/crates/oxc_macros/src/declare_all_lint_rules.rs @@ -8,18 +8,39 @@ use syn::{ }; pub struct LintRuleMeta { - name: syn::Ident, + rule_name: syn::Ident, + enum_name: syn::Ident, path: syn::Path, } impl Parse for LintRuleMeta { fn parse(input: ParseStream<'_>) -> Result { let path = input.parse::()?; + + let segments = &path.segments; + let last_two_segments = segments.iter().rev().take(2).collect::>(); // Collect the last two segments in reverse order + let combined = last_two_segments + .iter() + .rev() + .map(|seg| seg.ident.to_string().to_case(Case::Pascal)) + .join(""); + + let combined = combined.to_case(Case::Pascal); + let name = syn::parse_str( - &path.segments.iter().last().unwrap().ident.to_string().to_case(Case::Pascal), + //&path.segments.iter().last().unwrap().ident.to_string().to_case(Case::Pascal), + &combined, ) .unwrap(); - Ok(Self { name, path }) + Ok(Self { + enum_name: name, + rule_name: syn::parse_str( + &path.segments.iter().last().unwrap().ident.to_string().to_case(Case::Pascal), + //&combined, + ) + .unwrap(), + path, + }) } } @@ -39,14 +60,16 @@ impl Parse for AllLintRulesMeta { pub fn declare_all_lint_rules(metadata: AllLintRulesMeta) -> TokenStream { let AllLintRulesMeta { rules } = metadata; - let mut use_stmts = Vec::with_capacity(rules.len()); + let mut use_stmts: Vec<&syn::Path> = Vec::with_capacity(rules.len()); let mut struct_names = Vec::with_capacity(rules.len()); + let mut struct_rule_names = Vec::with_capacity(rules.len()); let mut plugin_names = Vec::with_capacity(rules.len()); let mut ids = Vec::with_capacity(rules.len()); for (i, rule) in rules.iter().enumerate() { use_stmts.push(&rule.path); - struct_names.push(&rule.name); + struct_names.push(&rule.enum_name); + struct_rule_names.push(&rule.rule_name); plugin_names.push( rule.path .segments @@ -59,7 +82,7 @@ pub fn declare_all_lint_rules(metadata: AllLintRulesMeta) -> TokenStream { } let expanded = quote! { - #(pub use self::#use_stmts::#struct_names;)* + #(pub use self::#use_stmts::#struct_rule_names as #struct_names;)* use crate::{ context::{ContextHost, LintContext},