diff --git a/crates/oxc_linter/src/rules/eslint/no_useless_constructor.rs b/crates/oxc_linter/src/rules/eslint/no_useless_constructor.rs index 31f091792b2e4..cddffa447ea55 100644 --- a/crates/oxc_linter/src/rules/eslint/no_useless_constructor.rs +++ b/crates/oxc_linter/src/rules/eslint/no_useless_constructor.rs @@ -7,18 +7,34 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::Span; +use oxc_span::{GetSpan, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; +/// ```js +/// class A { constructor(){} } +/// ``` fn no_empty_constructor(constructor_span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("Empty constructors are unnecessary") .with_label(constructor_span) .with_help("Remove the constructor or add code to it.") } -fn no_redundant_super_call(constructor_span: Span) -> OxcDiagnostic { + +/// ```js +/// class A { } +/// class B extends A { +/// constructor() { +/// super(); +/// } +/// } +/// ``` +fn no_redundant_super_call(constructor_span: Span, super_span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("Redundant super call in constructor") - .with_label(constructor_span).with_help("Constructors of subclasses invoke super() automatically if they are empty. Remove this constructor or add code to it.") + .with_labels([ + constructor_span.primary_label("This constructor is unnecessary,"), + super_span.label("because it only passes arguments through to the superclass"), + ]) + .with_help("Subclasses automatically use the constructor of their superclass, making this redundant.\nRemove this constructor or add code to it.") } #[derive(Debug, Default, Clone)] @@ -165,9 +181,10 @@ fn lint_redundant_super_call<'a>( && !is_overriding(params) && (is_spread_arguments(super_args) || is_passing_through(params, super_args)) { - ctx.diagnostic_with_fix(no_redundant_super_call(constructor.span), |fixer| { - fixer.delete_range(constructor.span) - }); + ctx.diagnostic_with_fix( + no_redundant_super_call(constructor.key.span(), super_call.span()), + |fixer| fixer.delete_range(constructor.span), + ); } } @@ -276,6 +293,11 @@ fn test() { "class A { constructor(){} }", "class A { 'constructor'(){} }", "class A extends B { constructor() { super(); } }", + "class A extends B { + constructor() { + super(); + } +}", "class A extends B { constructor(foo){ super(foo); } }", "class A extends B { constructor(foo, bar){ super(foo, bar); } }", "class A extends B { constructor(...args){ super(...args); } }", diff --git a/crates/oxc_linter/src/snapshots/no_useless_constructor.snap b/crates/oxc_linter/src/snapshots/no_useless_constructor.snap index 825e576e9f782..d74b69116e938 100644 --- a/crates/oxc_linter/src/snapshots/no_useless_constructor.snap +++ b/crates/oxc_linter/src/snapshots/no_useless_constructor.snap @@ -18,51 +18,86 @@ source: crates/oxc_linter/src/tester.rs ⚠ eslint(no-useless-constructor): Redundant super call in constructor ╭─[no_useless_constructor.tsx:1:21] 1 │ class A extends B { constructor() { super(); } } - · ────────────────────────── + · ─────┬───── ───┬─── + · │ ╰── because it only passes arguments through to the superclass + · ╰── This constructor is unnecessary, ╰──── - help: Constructors of subclasses invoke super() automatically if they are empty. Remove this constructor or add code to it. + help: Subclasses automatically use the constructor of their superclass, making this redundant. + Remove this constructor or add code to it. + + ⚠ eslint(no-useless-constructor): Redundant super call in constructor + ╭─[no_useless_constructor.tsx:2:5] + 1 │ class A extends B { + 2 │ constructor() { + · ─────┬───── + · ╰── This constructor is unnecessary, + 3 │ super(); + · ───┬─── + · ╰── because it only passes arguments through to the superclass + 4 │ } + ╰──── + help: Subclasses automatically use the constructor of their superclass, making this redundant. + Remove this constructor or add code to it. ⚠ eslint(no-useless-constructor): Redundant super call in constructor ╭─[no_useless_constructor.tsx:1:21] 1 │ class A extends B { constructor(foo){ super(foo); } } - · ─────────────────────────────── + · ─────┬───── ─────┬──── + · │ ╰── because it only passes arguments through to the superclass + · ╰── This constructor is unnecessary, ╰──── - help: Constructors of subclasses invoke super() automatically if they are empty. Remove this constructor or add code to it. + help: Subclasses automatically use the constructor of their superclass, making this redundant. + Remove this constructor or add code to it. ⚠ eslint(no-useless-constructor): Redundant super call in constructor ╭─[no_useless_constructor.tsx:1:21] 1 │ class A extends B { constructor(foo, bar){ super(foo, bar); } } - · ───────────────────────────────────────── + · ─────┬───── ───────┬─────── + · │ ╰── because it only passes arguments through to the superclass + · ╰── This constructor is unnecessary, ╰──── - help: Constructors of subclasses invoke super() automatically if they are empty. Remove this constructor or add code to it. + help: Subclasses automatically use the constructor of their superclass, making this redundant. + Remove this constructor or add code to it. ⚠ eslint(no-useless-constructor): Redundant super call in constructor ╭─[no_useless_constructor.tsx:1:21] 1 │ class A extends B { constructor(...args){ super(...args); } } - · ─────────────────────────────────────── + · ─────┬───── ───────┬────── + · │ ╰── because it only passes arguments through to the superclass + · ╰── This constructor is unnecessary, ╰──── - help: Constructors of subclasses invoke super() automatically if they are empty. Remove this constructor or add code to it. + help: Subclasses automatically use the constructor of their superclass, making this redundant. + Remove this constructor or add code to it. ⚠ eslint(no-useless-constructor): Redundant super call in constructor ╭─[no_useless_constructor.tsx:1:23] 1 │ class A extends B.C { constructor() { super(...arguments); } } - · ────────────────────────────────────── + · ─────┬───── ─────────┬───────── + · │ ╰── because it only passes arguments through to the superclass + · ╰── This constructor is unnecessary, ╰──── - help: Constructors of subclasses invoke super() automatically if they are empty. Remove this constructor or add code to it. + help: Subclasses automatically use the constructor of their superclass, making this redundant. + Remove this constructor or add code to it. ⚠ eslint(no-useless-constructor): Redundant super call in constructor ╭─[no_useless_constructor.tsx:1:21] 1 │ class A extends B { constructor(a, b, ...c) { super(...arguments); } } - · ──────────────────────────────────────────────── + · ─────┬───── ─────────┬───────── + · │ ╰── because it only passes arguments through to the superclass + · ╰── This constructor is unnecessary, ╰──── - help: Constructors of subclasses invoke super() automatically if they are empty. Remove this constructor or add code to it. + help: Subclasses automatically use the constructor of their superclass, making this redundant. + Remove this constructor or add code to it. ⚠ eslint(no-useless-constructor): Redundant super call in constructor ╭─[no_useless_constructor.tsx:1:21] 1 │ class A extends B { constructor(a, b, ...c) { super(a, b, ...c); } } - · ────────────────────────────────────────────── + · ─────┬───── ────────┬──────── + · │ ╰── because it only passes arguments through to the superclass + · ╰── This constructor is unnecessary, ╰──── - help: Constructors of subclasses invoke super() automatically if they are empty. Remove this constructor or add code to it. + help: Subclasses automatically use the constructor of their superclass, making this redundant. + Remove this constructor or add code to it. ⚠ eslint(no-useless-constructor): Empty constructors are unnecessary ╭─[no_useless_constructor.tsx:1:11]