-
-
Notifications
You must be signed in to change notification settings - Fork 484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(linter): improve no-accumulating-spread #5302
feat(linter): improve no-accumulating-spread #5302
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
cc648de
to
b1ba16f
Compare
CodSpeed Performance ReportMerging #5302 will not alter performanceComparing Summary
|
I disagree with this change. These examples are still |
why would the fixed version of this code be O(n^2)? it would improve performance in the same way converting a spread in a reduce loop to a push would. |
i also think i've dona a bad job explaining this. so let me try again, and attempt to explain why this is a good thing to add to the lint rule. 🙂 lets take the following example, where let foo = [];
for (let i = 0; i < n; i++) {
foo = [...foo, i];
} The time complexity of this example
this leads to a total time complexity of If we rewrite this code as let foo = [];
for (let i = 0; i < n; i++) {
foo.push(i)
} The time complexity of this will be:
leading to a total time complexity of Furthermore, in the first example, it will make We can see the difference in performance brenchmarks import { bench, run } from 'mitata';
const Ns = [1, 10, 100, 1000, 10000, 100000, 1000000];
for (const N of Ns) {
bench(`slow (spread array) ${N}`, () => {
let foo = [];
for (let i = 0; i < N; i++) {
foo = [...foo, i];
}
});
bench(`fast (push into array) ${N}`, () => {
let foo = [];
for (let i = 0; i < N; i++) {
foo.push(i);
}
});
}
await run(); yeilds the following results: (
represented a bit cleaner:
as you can see. using @DonIsaac let me know your thoughts |
@camc314 i owe you an apology, I though this PR was allowing spreads in for-loops. This is a misunderstanding on my part. I'll re-open this PR. |
This is nice 👍 |
no worries, thanks for bearing with me! the description lacked a clear explanation |
b1ba16f
to
85c4122
Compare
Merge activity
|
VSCode has a couple violations. examples: ``` x oxc(no-accumulating-spread): Do not spread accumulators in loops ,-[src/vs/workbench/services/textMate/common/TMGrammarFactory.ts:65:5] 64 | let injections: string[] = []; 65 | for (let i = 1; i <= scopeParts.length; i++) { : ^|^ : `-- For this loop 66 | const subScopeName = scopeParts.slice(0, i).join('.'); 67 | injections = [...injections, ...(this._injections[subScopeName] || [])]; : ^^^^^^|^^^^^^ : `-- From this spread 68 | } `---- help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. x oxc(no-accumulating-spread): Do not spread accumulators in loops ,-[src/vs/base/common/actions.ts:205:3] 204 | let out: IAction[] = []; 205 | for (const list of actionLists) { : ^|^ : `-- For this loop 206 | if (!list.length) { 207 | // skip 208 | } else if (out.length) { 209 | out = [...out, new Separator(), ...list]; : ^^^|^^ : `-- From this spread 210 | } else { `---- help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. help: It looks like you're spreading an `Array`. Consider using the `Array.push` or `Array.concat` methods to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. x oxc(no-accumulating-spread): Do not spread accumulators in loops ,-[src/vs/workbench/contrib/extensions/browser/extensionsActions.ts:302:3] 301 | let actions: IAction[] = []; 302 | for (const visibleActions of actionsGroups) { : ^|^ : `-- For this loop 303 | if (visibleActions.length) { 304 | actions = [...actions, ...visibleActions, new Separator()]; : ^^^^^|^^^^ : `-- From this spread 305 | } `---- help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. x oxc(no-accumulating-spread): Do not spread accumulators in loops ,-[src/vs/workbench/contrib/extensions/browser/extensionsActions.ts:1141:3] 1140 | let actions: IAction[] = []; 1141 | for (const menuActions of menuActionGroups) { : ^|^ : `-- For this loop 1142 | actions = [...actions, ...menuActions, new Separator()]; : ^^^^^|^^^^ : `-- From this spread 1143 | } `---- help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. x oxc(no-accumulating-spread): Do not spread accumulators in loops ,-[src/vs/workbench/contrib/extensions/browser/extensionsViews.ts:334:4] 333 | let actions: IAction[] = []; 334 | for (const menuActions of groups) { : ^|^ : `-- For this loop 335 | actions = [...actions, ...menuActions, new Separator()]; : ^^^^^|^^^^ : `-- From this spread 336 | } `---- help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead. Using spreads within accumulators leads to `O(n^2)` time complexity. ```
85c4122
to
b103737
Compare
…d` (#5373) mentioned here: #5302 (comment) it's not exactly clear why we check that it's a `let` declaration kind.
## [0.9.2] - 2024-09-02 ### Features - f81e8a1 linter: Add `oxc/no-async-endpoint-handlers` (#5364) (DonIsaac) - b103737 linter: Improve no-accumulating-spread (#5302) (camc314) - 9c22ce9 linter: Add hyperlinks to diagnostic messages (#5318) (DonIsaac) - 1967c67 linter/eslint: Implement no-new-func (#5360) (dalaoshu) - b867e5f linter/eslint-plugin-promise: Implement catch-or-return (#5121) (Jelle van der Waa) - 8d781e7 linter/oxc: Differentiate between array/object in `no-accumulating-spread` loop diagnostic (#5375) (camc314) - db55444 linter/oxc: Add fixer for `double-comparisons` (#5378) (camc314) - e5c755a linter/promise: Add `spec-only` rule (#5124) (Jelle van der Waa) - 4c0861f linter/unicorn: Add fixer for `prefer-type-error` (#5311) (camc314) - 084c2d1 linter/vitest: Implement prefer-to-be-object (#5321) (dalaoshu) ### Bug Fixes - 11b93af linter/unicorn: Consistent-function-scoping false positive on assignment expression (#5312) (Arian94) ### Performance - f052a6d linter: `react/jsx_no_undef` faster check for unbound references (#5349) (overlookmotel) - 05636b7 linter: Avoid unnecessary work in `jsx_a11y/anchor_is_valid` rule (#5341) (overlookmotel) ### Refactor - afb038e linter: `react/jsx_no_undef` use loop instead of recursion (#5347) (overlookmotel) - fe62687 linter: Simplify skipping JSX elements in `unicorn/consistent_function_scoping` (#5351) (overlookmotel) - 381d9fe linter: Shorten code in `react/jsx_no_useless_fragment` (#5350) (overlookmotel) - 83b9a82 linter: Fix indentation in `nextjs/no_script_component_in_head` rule (#5338) (overlookmotel) - 89f0188 linter: Improve docs for `react/jsx_no_target_blank` rule (#5342) (overlookmotel) - 57050ab linter: Shorten code in `jsx_a11y/aria_activedescendant_has_tabindex` rule (#5340) (overlookmotel) - ed31d67 linter/jest: Fix indentation in code comment (#5372) (camc314) - 2499cb9 linter/oxc: Update rule docs for `erasing-op` (#5376) (camc314) - 69493d2 linter/oxc: Improve diagnostic for `no-accumulating-spread` in loops (#5374) (camc314) - 024b585 linter/oxc: Improve code comment for `no-accumulating-spread` (#5373) (camc314) Co-authored-by: Boshen <[email protected]>
VSCode has a couple violations. examples: