diff --git a/crates/oxc_linter/src/generated/rule_runner_impls.rs b/crates/oxc_linter/src/generated/rule_runner_impls.rs index 62426597f3e1a..32bd52da7d7e2 100644 --- a/crates/oxc_linter/src/generated/rule_runner_impls.rs +++ b/crates/oxc_linter/src/generated/rule_runner_impls.rs @@ -200,8 +200,9 @@ impl RuleRunner for crate::rules::eslint::no_case_declarations::NoCaseDeclaratio } impl RuleRunner for crate::rules::eslint::no_class_assign::NoClassAssign { - const NODE_TYPES: Option<&AstTypesBitset> = None; - const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::RunOnSymbol; + const NODE_TYPES: Option<&AstTypesBitset> = + Some(&AstTypesBitset::from_types(&[AstType::Class])); + const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run; } impl RuleRunner for crate::rules::eslint::no_compare_neg_zero::NoCompareNegZero { diff --git a/crates/oxc_linter/src/rules/eslint/no_class_assign.rs b/crates/oxc_linter/src/rules/eslint/no_class_assign.rs index fe4bb841fa328..1759a3c293ee0 100644 --- a/crates/oxc_linter/src/rules/eslint/no_class_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_class_assign.rs @@ -1,6 +1,7 @@ +use oxc_ast::{AstKind, ast::BindingIdentifier}; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_semantic::SymbolId; +use oxc_semantic::AstNode; use oxc_span::Span; use crate::{context::LintContext, rule::Rule}; @@ -82,17 +83,27 @@ declare_oxc_lint!( ); impl Rule for NoClassAssign { - fn run_on_symbol(&self, symbol_id: SymbolId, ctx: &LintContext<'_>) { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + let AstKind::Class(class) = node.kind() else { + return; + }; + + let Some(symbol_id) = class.id.as_ref().map(BindingIdentifier::symbol_id) else { + return; + }; + let symbol_table = ctx.scoping(); - if symbol_table.symbol_flags(symbol_id).is_class() { - for reference in symbol_table.get_resolved_references(symbol_id) { - if reference.is_write() { - ctx.diagnostic(no_class_assign_diagnostic( - symbol_table.symbol_name(symbol_id), - symbol_table.symbol_span(symbol_id), - ctx.semantic().reference_span(reference), - )); - } + // This should always be considered a class (since we got it from a class declaration), + // but we check in debug mode just to be sure. + debug_assert!(symbol_table.symbol_flags(symbol_id).is_class()); + + for reference in symbol_table.get_resolved_references(symbol_id) { + if reference.is_write() { + ctx.diagnostic(no_class_assign_diagnostic( + symbol_table.symbol_name(symbol_id), + symbol_table.symbol_span(symbol_id), + ctx.semantic().reference_span(reference), + )); } } } @@ -119,6 +130,9 @@ fn test() { ("if (foo) { class A {} } else { class A {} } A = 1;", None), // Sequence expression ("(class A {}, A = 1)", None), + // Class expressions + ("let A = class { }; A = 1;", None), + ("let A = class B { }; A = 1;", None), ]; let fail = vec![