Skip to content

Commit

Permalink
feat(linter): add eslint/constructor-super
Browse files Browse the repository at this point in the history
  • Loading branch information
Sysix committed Dec 9, 2024
1 parent eaf6e26 commit 0e88ebb
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 12 deletions.
37 changes: 28 additions & 9 deletions crates/oxc_linter/src/rules/eslint/constructor_super.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,20 +240,31 @@ fn executes_always_super_expression<'a>(
}

if let Statement::IfStatement(if_statement) = &statement {
if if_statement.alternate.is_none() {
if matches!(&if_statement.consequent, Statement::ReturnStatement(return_statement) if return_statement.argument.is_none())
{
return Err(ErrorReport {
reason: ErrorReason::NotFound,
spans: vec![if_statement.span],
reason: ErrorReason::ReturnWithoutCall,
spans: vec![if_statement.consequent.span()],
});
}

if let Ok(mut consequent) = executes_always_super_expression(&if_statement.consequent) {
if let Ok(alternative) =
executes_always_super_expression(if_statement.alternate.as_ref().unwrap())
{
let Some(alternative_call) = if_statement.alternate.as_ref() else {
return Err(ErrorReport {
reason: ErrorReason::MissingCallOnBranch,
spans: vec![if_statement.span],
});
};

if let Ok(alternative) = executes_always_super_expression(alternative_call) {
consequent.extend(alternative);
return Ok(consequent);
}

return Err(ErrorReport {
reason: ErrorReason::MissingCallOnBranch,
spans: vec![if_statement.span],
});
}

return Err(ErrorReport { reason: ErrorReason::NotFound, spans: vec![if_statement.span] });
Expand Down Expand Up @@ -362,14 +373,22 @@ fn has_return_statement<'a>(method: &'a MethodDefinition<'a>) -> bool {
};

for statement in &func_body.statements {
if matches!(statement, Statement::ReturnStatement(_)) {
if is_blocking_execution(statement) {
return true;
}
}

false
}

fn is_blocking_execution<'a>(statement: &'a Statement<'a>) -> bool {
if matches!(statement, Statement::ReturnStatement(_) | Statement::ThrowStatement(_)) {
return true;
}

false
}

fn get_constructor_method<'a>(class: &'a ClassBody<'a>) -> Option<&'a MethodDefinition<'a>> {
if class.body.is_empty() {
return None;
Expand Down Expand Up @@ -524,10 +543,10 @@ fn test() {
"class A extends B { constructor() { switch (a) { case 0: break; default: super(); } } }",
"class A extends B { constructor() { try { super(); } catch (err) {} } }",
"class A extends B { constructor() { try { a; } catch (err) { super(); } } }",
// "class A extends B { constructor() { if (a) return; super(); } }",
"class A extends B { constructor() { if (a) return; super(); } }",
// "class A extends B { constructor() { super(); super(); } }",
// "class A extends B { constructor() { super() || super(); } }",
// "class A extends B { constructor() { if (a) super(); super(); } }",
"class A extends B { constructor() { if (a) super(); super(); } }",
// "class A extends B { constructor() { switch (a) { case 0: super(); default: super(); } } }",
"class A extends B { constructor(a) { while (a) super(); } }",
"class A extends B { constructor() { return; super(); } }",
Expand Down
21 changes: 18 additions & 3 deletions crates/oxc_linter/src/snapshots/eslint_constructor_super.snap
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,11 @@ snapshot_kind: text
· ───────────
╰────

eslint(constructor-super): Expected to call 'super()'
╭─[constructor_super.tsx:1:21]
eslint(constructor-super): Lacked a call of 'super()' in some code paths.
╭─[constructor_super.tsx:1:37]
1class A extends B { constructor() { if (a) super(); } }
· ───────────
· ───────┬───────
· ╰── This path is lacking of a 'super()' call
╰────

eslint(constructor-super): Expected to call 'super()'
Expand Down Expand Up @@ -186,6 +187,20 @@ snapshot_kind: text
· ╰── Inside a 'try' and 'catch' block, a 'super' call not be guaranteed to be called
╰────

eslint(constructor-super): Lacked a call of 'super()' in some code paths.
╭─[constructor_super.tsx:1:44]
1class A extends B { constructor() { if (a) return; super(); } }
· ───┬───
· ╰── This path fast returns without calling 'super()'
╰────

eslint(constructor-super): Lacked a call of 'super()' in some code paths.
╭─[constructor_super.tsx:1:37]
1class A extends B { constructor() { if (a) super(); super(); } }
· ───────┬───────
· ╰── This path is lacking of a 'super()' call
╰────

eslint(constructor-super): Expected to call 'super()'
╭─[constructor_super.tsx:1:21]
1class A extends B { constructor(a) { while (a) super(); } }
Expand Down

0 comments on commit 0e88ebb

Please sign in to comment.