diff --git a/crates/oxc_linter/src/rules/eslint/default_param_last.rs b/crates/oxc_linter/src/rules/eslint/default_param_last.rs index cdc32fc9dbab3..0262276652088 100644 --- a/crates/oxc_linter/src/rules/eslint/default_param_last.rs +++ b/crates/oxc_linter/src/rules/eslint/default_param_last.rs @@ -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(); diff --git a/crates/oxc_linter/src/snapshots/eslint_default_param_last.snap b/crates/oxc_linter/src/snapshots/eslint_default_param_last.snap index c0cd80f8183dd..49f25282c6aa1 100644 --- a/crates/oxc_linter/src/snapshots/eslint_default_param_last.snap +++ b/crates/oxc_linter/src/snapshots/eslint_default_param_last.snap @@ -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.