From 1844142a86dbd1c98735dbdb9616a13e98bd0178 Mon Sep 17 00:00:00 2001 From: Antoine ZANARDI Date: Mon, 1 Sep 2025 21:50:02 +0200 Subject: [PATCH 1/3] refactor(eslint/default-param-last): simplify implementation and enhance readability --- .../src/rules/eslint/default_param_last.rs | 74 ++++++++++++++----- 1 file changed, 55 insertions(+), 19 deletions(-) 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 78c580c515208..159f297e4cdc3 100644 --- a/crates/oxc_linter/src/rules/eslint/default_param_last.rs +++ b/crates/oxc_linter/src/rules/eslint/default_param_last.rs @@ -1,3 +1,4 @@ +use oxc_ast::ast::Function; use oxc_ast::{AstKind, ast::FormalParameter}; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; @@ -17,26 +18,62 @@ pub struct DefaultParamLast; declare_oxc_lint!( /// ### What it does /// - /// Enforce default parameters to be last + /// Requires default parameters in functions to be the last ones. /// /// ### Why is this bad? /// - /// Putting default parameter at last allows function calls to omit optional tail arguments. + /// Placing default parameters last allows function calls to omit optional trailing arguments, + /// which improves readability and consistency. This rule applies equally to JavaScript and + /// TypeScript functions. + /// + /// ### Options + /// + /// No options available for this rule /// /// ### Examples /// /// Examples of **incorrect** code for this rule: - /// ```javascript - /// // Incorrect: optional argument can **not** be omitted + /// ```js + /// /* default-param-last: "error" */ + /// + /// /* ✘ Bad: */ + /// function f(a = 0, b) {} + /// function f(a, b = 0, c) {} /// function createUser(isAdmin = false, id) {} /// createUser(undefined, "tabby") /// ``` /// /// Examples of **correct** code for this rule: - /// ```javascript + /// ```js + /// /* default-param-last: "error" */ + /// + /// /* ✔ Good: */ + /// function f(a, b = 0) {} + /// function f(a = 0, b = 0) {} /// function createUser(id, isAdmin = false) {} /// createUser("tabby") /// ``` + /// + /// Examples of **incorrect** TypeScript code for this rule: + /// ```ts + /// /* default-param-last: "error" */ + /// + /// /* ✘ Bad: */ + /// function greet(message: string = "Hello", name: string) {} + /// function combine(a: number = 1, b: number, c: number) {} + /// function combine(a: number, b: number = 2, c: number) {} + /// function combine(a: number = 1, b?: number, c: number) {} + /// ``` + /// + /// Examples of **correct** TypeScript code for this rule: + /// ```ts + /// /* default-param-last: "error" */ + /// + /// /* ✔ Good: */ + /// function greet(name: string, message: string = "Hello") {} + /// function combine(a: number, b: number = 2, c: number = 3) {} + /// function combine(a: number, b?: number, c: number = 3) {} + /// ``` DefaultParamLast, eslint, style @@ -45,10 +82,7 @@ declare_oxc_lint!( impl Rule for DefaultParamLast { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { match node.kind() { - AstKind::Function(function) => { - if !function.is_declaration() && !function.is_expression() { - return; - } + AstKind::Function(function) if is_function_decl_or_expr(function) => { check_params(&function.params.items, ctx); } AstKind::ArrowFunctionExpression(function) => check_params(&function.params.items, ctx), @@ -57,16 +91,18 @@ 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() && !param.pattern.optional { - has_seen_plain_param = true; - continue; - } - if has_seen_plain_param - && (param.pattern.kind.is_assignment_pattern() || param.pattern.optional) - { +fn is_function_decl_or_expr(function: &Function) -> bool { + function.is_declaration() || function.is_expression() +} + +fn check_params<'a>(params: &'a [FormalParameter<'a>], ctx: &LintContext<'a>) { + let mut seen_plain = false; + for param in params.iter().rev() { + let is_default = param.pattern.kind.is_assignment_pattern() || param.pattern.optional; + + if !is_default { + seen_plain = true; + } else if seen_plain { ctx.diagnostic(default_param_last_diagnostic(param.span)); } } From 6755d4ad52758865b9c2f70c84eb1d4d34b41e76 Mon Sep 17 00:00:00 2001 From: Antoine ZANARDI Date: Mon, 1 Sep 2025 22:01:13 +0200 Subject: [PATCH 2/3] refactor(eslint/default-param-last): consolidate imports for improved clarity --- crates/oxc_linter/src/rules/eslint/default_param_last.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 159f297e4cdc3..3e241845932b5 100644 --- a/crates/oxc_linter/src/rules/eslint/default_param_last.rs +++ b/crates/oxc_linter/src/rules/eslint/default_param_last.rs @@ -1,5 +1,4 @@ -use oxc_ast::ast::Function; -use oxc_ast::{AstKind, ast::FormalParameter}; +use oxc_ast::{AstKind, ast::FormalParameter, ast::Function}; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::Span; From b9a61be5cdba47a71d07e6dedaec2b5b18364c72 Mon Sep 17 00:00:00 2001 From: Cameron Date: Tue, 2 Sep 2025 10:47:52 +0800 Subject: [PATCH 3/3] Apply suggestions from code review --- crates/oxc_linter/src/rules/eslint/default_param_last.rs | 4 ---- 1 file changed, 4 deletions(-) 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 3e241845932b5..bbe9f9158fbcf 100644 --- a/crates/oxc_linter/src/rules/eslint/default_param_last.rs +++ b/crates/oxc_linter/src/rules/eslint/default_param_last.rs @@ -35,7 +35,6 @@ declare_oxc_lint!( /// ```js /// /* default-param-last: "error" */ /// - /// /* ✘ Bad: */ /// function f(a = 0, b) {} /// function f(a, b = 0, c) {} /// function createUser(isAdmin = false, id) {} @@ -46,7 +45,6 @@ declare_oxc_lint!( /// ```js /// /* default-param-last: "error" */ /// - /// /* ✔ Good: */ /// function f(a, b = 0) {} /// function f(a = 0, b = 0) {} /// function createUser(id, isAdmin = false) {} @@ -57,7 +55,6 @@ declare_oxc_lint!( /// ```ts /// /* default-param-last: "error" */ /// - /// /* ✘ Bad: */ /// function greet(message: string = "Hello", name: string) {} /// function combine(a: number = 1, b: number, c: number) {} /// function combine(a: number, b: number = 2, c: number) {} @@ -68,7 +65,6 @@ declare_oxc_lint!( /// ```ts /// /* default-param-last: "error" */ /// - /// /* ✔ Good: */ /// function greet(name: string, message: string = "Hello") {} /// function combine(a: number, b: number = 2, c: number = 3) {} /// function combine(a: number, b?: number, c: number = 3) {}