mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(linter/unicorn/consistent-function-scoping): count self-referencing variables as captures (#27726)
Treat a function's reference to its own variable binding as a parent-scope capture, matching eslint-plugin-unicorn. For example, a nested `const builder = (...args) => builder.apply(null, args)` was incorrectly reported as movable even though it captures `builder` from the enclosing scope. Limit the recursion exemption to function-name symbols. Add regression cases for arrow functions, anonymous and named function expressions, parameter defaults, and `var` bindings, while retaining warnings for internal function-name recursion and shadowed parameters. Addresses report 5 (`unicorn/consistent-function-scoping`) in #27710.
This commit is contained in:
1 parent
033faa933e
commit
eb461f8344
2 files changed
+41
-1
No files matched your search
@@ -332,7 +332,8 @@ impl ConsistentFunctionScoping {
|
||||
}
|
||||
let scope_id = ctx.scoping().symbol_scope_id(symbol_id);
|
||||
if ctx.scoping().scope_is_descendant_of(function_scope_id, scope_id)
|
||||
&& symbol_id != function_declaration_symbol_id
|
||||
&& (symbol_id != function_declaration_symbol_id
|
||||
|| !ctx.scoping().symbol_flags(symbol_id).is_function())
|
||||
{
|
||||
// Both class declarations and expressions have an internal self binding.
|
||||
// Moving past the class body would lose that binding.
|
||||
@@ -1165,6 +1166,22 @@ fn test() {
|
||||
"class Box { #value; method() { const inner = () => class { field = box.#value; }; return inner; } }",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"const make = (self) => {
|
||||
const builder = (...args) => builder.apply(null, args);
|
||||
builder.self = self;
|
||||
return builder;
|
||||
};
|
||||
module.exports = make;",
|
||||
None,
|
||||
),
|
||||
("function outer() { const inner = function () { return inner(); }; return inner; }", None),
|
||||
(
|
||||
"function outer() { const inner = function recur() { return inner(); }; return inner; }",
|
||||
None,
|
||||
),
|
||||
("function outer() { const inner = (value = inner) => value; return inner; }", None),
|
||||
("function outer() { var inner = () => inner(); return inner; }", None),
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
@@ -1575,6 +1592,11 @@ fn test() {
|
||||
"class External { method() { function outer() { function inner() { return External; } return inner; } return outer; } }",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"function outer() { const inner = function recur() { return recur(); }; return inner; }",
|
||||
None,
|
||||
),
|
||||
("function outer() { const inner = (inner) => inner(); return inner; }", None),
|
||||
];
|
||||
|
||||
Tester::new(ConsistentFunctionScoping::NAME, ConsistentFunctionScoping::PLUGIN, pass, fail)
|
||||
|
||||
@@ -741,3 +741,21 @@ source: crates/oxc_linter/src/tester.rs
|
||||
· ╰── Outer scope where this function is defined
|
||||
╰────
|
||||
help: Move `inner` to the outer scope to avoid recreating it on every call.
|
||||
|
||||
⚠ unicorn(consistent-function-scoping): Function `inner` does not capture any variables from its parent scope
|
||||
╭─[consistent_function_scoping.tsx:1:43]
|
||||
1 │ function outer() { const inner = function recur() { return recur(); }; return inner; }
|
||||
· ──┬── ──┬──
|
||||
· │ ╰── This function does not use any variables from the parent function
|
||||
· ╰── Outer scope where this function is defined
|
||||
╰────
|
||||
help: Move `inner` to the outer scope to avoid recreating it on every call.
|
||||
|
||||
⚠ unicorn(consistent-function-scoping): Function `inner` does not capture any variables from its parent scope
|
||||
╭─[consistent_function_scoping.tsx:1:26]
|
||||
1 │ function outer() { const inner = (inner) => inner(); return inner; }
|
||||
· ──┬── ──┬──
|
||||
· │ ╰── This function does not use any variables from the parent function
|
||||
· ╰── Outer scope where this function is defined
|
||||
╰────
|
||||
help: Move `inner` to the outer scope to avoid recreating it on every call.
|
||||
Reference in new issue
Block a user