fix(linter): enhance default_param_last rule to handle optional parameters (#8563)

- Enhanced default_param_last to handle optional parameters based on the
corresponding typescript-eslint rule.
- Added additional test cases from the typescript-eslint rule.

Closes https://github.com/oxc-project/oxc/issues/8556
This commit is contained in:
Tapan Prakash 2025-01-17 17:05:27 +05:30 committed by GitHub
parent 5cb9e979fe
commit 869bc73e67
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 458 additions and 3 deletions

View file

@ -54,11 +54,13 @@ impl Rule for DefaultParamLast {
fn check_params<'a>(items: &'a [FormalParameter<'a>], ctx: &LintContext<'a>) {
let mut has_seen_plain_param = false;
for param in items.iter().rev() {
if !param.pattern.kind.is_assignment_pattern() {
if !param.pattern.kind.is_assignment_pattern() && !param.pattern.optional {
has_seen_plain_param = true;
continue;
}
if has_seen_plain_param && param.pattern.kind.is_assignment_pattern() {
if has_seen_plain_param
&& (param.pattern.kind.is_assignment_pattern() || param.pattern.optional)
{
ctx.diagnostic(default_param_last_diagnostic(param.span));
}
}
@ -82,6 +84,100 @@ fn test() {
"const f = function f() {}",
"const f = function f(a) {}",
"const f = function f(a = 5) {}",
"function fn(a: string = 'a', b?: string) {}",
"function foo() {}",
"function foo(a: number) {}",
"function foo(a = 1) {}",
"function foo(a?: number) {}",
"function foo(a: number, b: number) {}",
"function foo(a: number, b: number, c?: number) {}",
"function foo(a: number, b = 1) {}",
"function foo(a: number, b = 1, c = 1) {}",
"function foo(a: number, b = 1, c?: number) {}",
"function foo(a: number, b?: number, c = 1) {}",
"function foo(a: number, b = 1, ...c) {}",
"const foo = function () {};",
"const foo = function (a: number) {};",
"const foo = function (a = 1) {};",
"const foo = function (a?: number) {};",
"const foo = function (a: number, b: number) {};",
"const foo = function (a: number, b: number, c?: number) {};",
"const foo = function (a: number, b = 1) {};",
"const foo = function (a: number, b = 1, c = 1) {};",
"const foo = function (a: number, b = 1, c?: number) {};",
"const foo = function (a: number, b?: number, c = 1) {};",
"const foo = function (a: number, b = 1, ...c) {};",
"const foo = () => {};",
"const foo = (a: number) => {};",
"const foo = (a = 1) => {};",
"const foo = (a?: number) => {};",
"const foo = (a: number, b: number) => {};",
"const foo = (a: number, b: number, c?: number) => {};",
"const foo = (a: number, b = 1) => {};",
"const foo = (a: number, b = 1, c = 1) => {};",
"const foo = (a: number, b = 1, c?: number) => {};",
"const foo = (a: number, b?: number, c = 1) => {};",
"const foo = (a: number, b = 1, ...c) => {};",
"
class Foo {
constructor(a: number, b: number, c: number) {}
}",
"
class Foo {
constructor(a: number, b?: number, c = 1) {}
}",
"
class Foo {
constructor(a: number, b = 1, c?: number) {}
}",
"
class Foo {
constructor(
public a: number,
protected b: number,
private c: number,
) {}
}",
"
class Foo {
constructor(
public a: number,
protected b?: number,
private c = 10,
) {}
}",
"
class Foo {
constructor(
public a: number,
protected b = 10,
private c?: number,
) {}
}",
"
class Foo {
constructor(
a: number,
protected b?: number,
private c = 0,
) {}
}",
"
class Foo {
constructor(
a: number,
b?: number,
private c = 0,
) {}
}",
"
class Foo {
constructor(
a: number,
private b?: number,
c = 0,
) {}
}",
];
let fail = vec![
@ -96,6 +192,56 @@ fn test() {
"const f = ({ a, b } = { a: 1, b: 2 }, c) => {}",
"const f = ([a] = [], b) => {}",
"const f = ([a, b] = [1, 2], c) => {}",
"function foo(a = 1, b: number) {}",
"function foo(a = 1, b = 2, c: number) {}",
"function foo(a = 1, b: number, c = 2, d: number) {}",
"function foo(a = 1, b: number, c = 2) {}",
"function foo(a = 1, b: number, ...c) {}",
"function foo(a?: number, b: number) {}",
"function foo(a: number, b?: number, c: number) {}",
"function foo(a = 1, b?: number, c: number) {}",
"function foo(a = 1, { b }) {}",
"function foo({ a } = {}, b) {}",
"function foo({ a, b } = { a: 1, b: 2 }, c) {}",
"const foo = function (a = 1, b: number) {};",
"const foo = function (a = 1, b = 2, c: number) {};",
"const foo = function (a = 1, b: number, c = 2, d: number) {};",
"const foo = function (a = 1, b: number, c = 2) {};",
"const foo = function (a = 1, b: number, ...c) {};",
"const foo = function (a?: number, b: number) {};",
"const foo = function (a: number, b?: number, c: number) {};",
"const foo = function (a = 1, b?: number, c: number) {};",
"const foo = function (a = 1, { b }) {};",
"const foo = function ({ a } = {}, b) {};",
"const foo = function ({ a, b } = { a: 1, b: 2 }, c) {};",
"const foo = (a = 1, b: number) => {};",
"const foo = (a = 1, b = 2, c: number) => {};",
"const foo = (a = 1, b: number, c = 2, d: number) => {};",
"const foo = (a = 1, b: number, c = 2) => {};",
"const foo = (a = 1, b: number, ...c) => {};",
"const foo = (a?: number, b: number) => {};",
"const foo = (a: number, b?: number, c: number) => {};",
"const foo = (a = 1, b?: number, c: number) => {};",
"
class Foo {
constructor(
public a?: number,
private b: number,
) {}
}",
"
class Foo {
constructor(a = 0, b: number) {}
}",
"class Foo {
constructor(a?: number, b: number) {}
}",
"class Foo {
constructor(
public a = 0,
private b: number,
) {}
}",
];
Tester::new(DefaultParamLast::NAME, DefaultParamLast::PLUGIN, pass, fail).test_and_snapshot();

View file

@ -1,6 +1,6 @@
---
source: crates/oxc_linter/src/tester.rs
snapshot_kind: text
assertion_line: 357
---
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:12]
@ -92,3 +92,312 @@ snapshot_kind: text
· ───────────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ function foo(a = 1, b: number) {}
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:21]
1 │ function foo(a = 1, b = 2, c: number) {}
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ function foo(a = 1, b = 2, c: number) {}
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:32]
1 │ function foo(a = 1, b: number, c = 2, d: number) {}
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ function foo(a = 1, b: number, c = 2, d: number) {}
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ function foo(a = 1, b: number, c = 2) {}
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ function foo(a = 1, b: number, ...c) {}
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ function foo(a?: number, b: number) {}
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:25]
1 │ function foo(a: number, b?: number, c: number) {}
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:21]
1 │ function foo(a = 1, b?: number, c: number) {}
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ function foo(a = 1, b?: number, c: number) {}
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ function foo(a = 1, { b }) {}
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ function foo({ a } = {}, b) {}
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ function foo({ a, b } = { a: 1, b: 2 }, c) {}
· ─────────────────────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:23]
1 │ const foo = function (a = 1, b: number) {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:30]
1 │ const foo = function (a = 1, b = 2, c: number) {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:23]
1 │ const foo = function (a = 1, b = 2, c: number) {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:41]
1 │ const foo = function (a = 1, b: number, c = 2, d: number) {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:23]
1 │ const foo = function (a = 1, b: number, c = 2, d: number) {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:23]
1 │ const foo = function (a = 1, b: number, c = 2) {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:23]
1 │ const foo = function (a = 1, b: number, ...c) {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:23]
1 │ const foo = function (a?: number, b: number) {};
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:34]
1 │ const foo = function (a: number, b?: number, c: number) {};
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:30]
1 │ const foo = function (a = 1, b?: number, c: number) {};
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:23]
1 │ const foo = function (a = 1, b?: number, c: number) {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:23]
1 │ const foo = function (a = 1, { b }) {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:23]
1 │ const foo = function ({ a } = {}, b) {};
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:23]
1 │ const foo = function ({ a, b } = { a: 1, b: 2 }, c) {};
· ─────────────────────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ const foo = (a = 1, b: number) => {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:21]
1 │ const foo = (a = 1, b = 2, c: number) => {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ const foo = (a = 1, b = 2, c: number) => {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:32]
1 │ const foo = (a = 1, b: number, c = 2, d: number) => {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ const foo = (a = 1, b: number, c = 2, d: number) => {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ const foo = (a = 1, b: number, c = 2) => {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ const foo = (a = 1, b: number, ...c) => {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ const foo = (a?: number, b: number) => {};
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:25]
1 │ const foo = (a: number, b?: number, c: number) => {};
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:21]
1 │ const foo = (a = 1, b?: number, c: number) => {};
· ──────────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:1:14]
1 │ const foo = (a = 1, b?: number, c: number) => {};
· ─────
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:4:17]
3 │ constructor(
4 │ public a?: number,
· ─────────────────
5 │ private b: number,
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:3:25]
2 │ class Foo {
3 │ constructor(a = 0, b: number) {}
· ─────
4 │ }
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:2:25]
1 │ class Foo {
2 │ constructor(a?: number, b: number) {}
· ──────────
3 │ }
╰────
help: Enforce default parameters to be last.
⚠ eslint(default-param-last): Default parameters should be last
╭─[default_param_last.tsx:3:17]
2 │ constructor(
3 │ public a = 0,
· ────────────
4 │ private b: number,
╰────
help: Enforce default parameters to be last.