From caa86a7891e2e42a6608284863977227f87de675 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Fri, 24 Apr 2026 11:37:37 +0200 Subject: [PATCH] Replace Array.forEach with for...of loops --- oxlint.config.mts | 5 +- packages/app-neovim/src/registerCommands.ts | 4 +- packages/app-vscode/src/ReleaseNotes.test.ts | 4 +- .../app-vscode/src/createScopeVisualizer.ts | 10 +-- .../VscodeFancyRangeHighlighterRenderer.ts | 28 ++++----- .../VscodeScopeVisualizer.ts | 4 +- .../app-vscode/src/ide/vscode/VscodeEdit.ts | 4 +- .../src/ide/vscode/VscodeFlashHandler.ts | 4 +- .../src/ide/vscode/VscodeToggleBreakpoint.ts | 4 +- .../src/ide/vscode/hats/VscodeHatRenderer.ts | 8 ++- .../src/ide/vscode/hats/VscodeHats.ts | 12 ++-- .../src/ide/vscode/textLine.vscode.test.ts | 4 +- .../src/keyboard/KeyboardHandler.ts | 12 ++-- .../src/keyboard/buildSuffixTrie.test.ts | 4 +- .../src/keyboard/buildSuffixTrie.ts | 13 ++-- .../grammar/getAcceptableTokenTypes.test.ts | 4 +- .../src/keyboard/grammar/grammar.test.ts | 4 +- packages/app-vscode/src/logQuickActions.ts | 4 +- .../src/scripts/hatAdjustments/average.ts | 7 ++- .../src/scripts/initLaunchSandbox.ts | 4 +- .../app-vscode/src/storedTargetHighlighter.ts | 4 +- .../src/docs/components/DynamicTOC.tsx | 5 +- .../src/docs/components/ScopeVisualizer.tsx | 23 +++---- .../docs/components/flattenHighlights.test.ts | 4 +- packages/lib-common/src/ide/fake/FakeIDE.ts | 4 +- .../src/testUtil/extractTargetedMarks.ts | 4 +- packages/lib-common/src/util/Notifier.ts | 4 +- .../lib-common/src/util/disposableFrom.ts | 4 +- packages/lib-common/src/util/itertools.ts | 4 +- packages/lib-common/src/util/object.ts | 4 +- packages/lib-common/src/util/toPlainObject.ts | 7 +-- .../lib-common/src/util/uniqWithHash.test.ts | 8 ++- packages/lib-common/src/util/uniqWithHash.ts | 4 +- .../lib-engine/src/KeyboardTargetUpdater.ts | 4 +- .../lib-engine/src/actions/BringMoveSwap.ts | 12 ++-- .../src/actions/EditNew/runEditTargets.ts | 8 +-- .../EditNew/runInsertLineAfterTargets.ts | 4 +- .../actions/GenerateSnippet/Substituter.ts | 4 +- .../GenerateSnippet/constructSnippetBody.ts | 4 +- packages/lib-engine/src/actions/Scroll.ts | 4 +- packages/lib-engine/src/core/HatAllocator.ts | 4 +- .../lib-engine/src/core/IndividualHatMap.ts | 8 ++- .../canonicalizeTargetsInPlace.ts | 8 +-- .../upgradeV5ToV6/upgradeV5ToV6.ts | 4 +- .../src/core/updateSelections/RangeUpdater.ts | 4 +- .../updateSelections/updateSelections.test.ts | 4 +- .../grammarAction.test.ts | 4 +- .../grammarScopeType.test.ts | 4 +- .../src/customCommandGrammar/lexer.test.ts | 4 +- .../src/customCommandGrammar/lexer.ts | 21 ++++--- .../CustomSpokenFormGeneratorImpl.ts | 4 +- .../generateSpokenForm.test.ts | 6 +- .../src/languages/LanguageDefinitions.ts | 10 +-- .../TreeSitterQuery/parsePredicates.ts | 30 ++++++--- .../scopeHandlers/BaseScopeHandler.test.ts | 4 +- .../src/scopeProviders/ScopeInfoProvider.ts | 4 +- .../src/scopeProviders/ScopeRangeWatcher.ts | 18 +++--- .../src/scopeProviders/ScopeSupportWatcher.ts | 4 +- .../src/snippets/transformSnippetVariables.ts | 5 +- packages/lib-engine/src/test/scopes.test.ts | 24 ++++--- .../src/test/sentenceSegmenter.test.ts | 4 +- .../src/test/spokenForms.talon.test.ts | 16 ++--- packages/lib-engine/src/test/subtoken.test.ts | 4 +- .../src/testUtil/serializeScopeFixture.ts | 16 ++--- .../tokenGraphemeSplitter.test.ts | 8 +-- .../tokenGraphemeSplitter.ts | 4 +- .../src/tokenizer/tokenizer.test.ts | 63 +++++++++---------- .../src/util/allocateHats/allocateHats.ts | 6 +- .../util/allocateHats/getHatRankingContext.ts | 27 ++++---- .../allocateHats/maxByFirstDiffering.test.ts | 4 +- packages/lib-engine/src/util/unifyRanges.ts | 4 +- packages/lib-node-common/src/Cheatsheet.ts | 4 +- .../FileSystemRawTreeSitterQueryProvider.ts | 4 +- .../src/getScopeTestPathsRecursively.ts | 10 ++- .../lib-node-common/src/runRecordedTest.ts | 4 +- packages/lib-node-common/src/walkSync.ts | 8 +-- .../src/launchNeovimAndRunTests.ts | 13 ++-- packages/test-runner/src/runAllTests.ts | 9 ++- .../src/suite/recorded.vscode.test.ts | 6 +- 79 files changed, 356 insertions(+), 294 deletions(-) diff --git a/oxlint.config.mts b/oxlint.config.mts index 0dc1cf779e..1abca6587a 100644 --- a/oxlint.config.mts +++ b/oxlint.config.mts @@ -3,9 +3,9 @@ import { defineConfig } from "oxlint"; // These rules should probably be re-enabled eventually const temporarilyDisabledRules = [ - "unicorn/no-array-for-each", - "unicorn/no-array-reverse", + // Requires es2023 "unicorn/no-array-sort", + "unicorn/no-array-reverse", ]; const disabledRules = [ @@ -26,6 +26,7 @@ const disabledRules = [ "eslint/no-continue", "eslint/no-eq-null", "eslint/no-lonely-if", + "eslint/no-loop-func", "eslint/no-magic-numbers", "eslint/no-negated-condition", "eslint/no-plusplus", diff --git a/packages/app-neovim/src/registerCommands.ts b/packages/app-neovim/src/registerCommands.ts index 0c15dc5b5b..37dd30252a 100644 --- a/packages/app-neovim/src/registerCommands.ts +++ b/packages/app-neovim/src/registerCommands.ts @@ -128,9 +128,9 @@ export function registerCommands( "cursorless.documentationOpened": dummyCommandHandler, }; - Object.entries(commands).forEach(([commandId, callback]) => { + for (const [commandId, callback] of Object.entries(commands)) { getNeovimRegistry().registerCommand(commandId, callback); - }); + } } export function dummyCommandHandler(...args: any[]) { diff --git a/packages/app-vscode/src/ReleaseNotes.test.ts b/packages/app-vscode/src/ReleaseNotes.test.ts index 367bbdfcb8..81f30941f1 100644 --- a/packages/app-vscode/src/ReleaseNotes.test.ts +++ b/packages/app-vscode/src/ReleaseNotes.test.ts @@ -157,12 +157,12 @@ suite("release notes", () => { sinon.restore(); }); - testCases.forEach(({ input, expectedOutput }) => { + for (const { input, expectedOutput } of testCases) { test( getTestName(input), asyncSafety(() => runTest(input, expectedOutput)), ); - }); + } }); function getTestName(input: Input) { diff --git a/packages/app-vscode/src/createScopeVisualizer.ts b/packages/app-vscode/src/createScopeVisualizer.ts index 02db5fc20d..59fc7b5696 100644 --- a/packages/app-vscode/src/createScopeVisualizer.ts +++ b/packages/app-vscode/src/createScopeVisualizer.ts @@ -33,16 +33,18 @@ export function createScopeVisualizer( ); scopeVisualizer.start(); currentScopeType = scopeType; - listeners - .slice() - .forEach((listener) => listener(scopeType, visualizationType)); + for (const listener of listeners.slice()) { + listener(scopeType, visualizationType); + } }, stop() { scopeVisualizer?.dispose(); scopeVisualizer = undefined; currentScopeType = undefined; - listeners.slice().forEach((listener) => listener(undefined, undefined)); + for (const listener of listeners.slice()) { + listener(undefined, undefined); + } }, get scopeType() { diff --git a/packages/app-vscode/src/ide/vscode/VSCodeScopeVisualizer/VscodeFancyRangeHighlighter/VscodeFancyRangeHighlighterRenderer.ts b/packages/app-vscode/src/ide/vscode/VSCodeScopeVisualizer/VscodeFancyRangeHighlighter/VscodeFancyRangeHighlighterRenderer.ts index 73efe1d01a..0780499686 100644 --- a/packages/app-vscode/src/ide/vscode/VSCodeScopeVisualizer/VscodeFancyRangeHighlighter/VscodeFancyRangeHighlighterRenderer.ts +++ b/packages/app-vscode/src/ide/vscode/VSCodeScopeVisualizer/VscodeFancyRangeHighlighter/VscodeFancyRangeHighlighterRenderer.ts @@ -62,29 +62,27 @@ export class VscodeFancyRangeHighlighterRenderer { b.differentiatedStyle.differentiationIndex, ); - decoratedRanges.forEach( - ({ differentiatedStyle: styleParameters, ranges }) => { - const decorationType = this.decorationTypes.get(styleParameters); + for (const { differentiatedStyle, ranges } of decoratedRanges) { + const decorationType = this.decorationTypes.get(differentiatedStyle); - vscodeApi.editor.setDecorations( - editor.vscodeEditor, - decorationType, - ranges.map(toVscodeRange), - ); + vscodeApi.editor.setDecorations( + editor.vscodeEditor, + decorationType, + ranges.map(toVscodeRange), + ); - untouchedDecorationTypes.delete(decorationType); - }, - ); + untouchedDecorationTypes.delete(decorationType); + } - untouchedDecorationTypes.forEach((decorationType) => { + for (const decorationType of untouchedDecorationTypes) { editor.vscodeEditor.setDecorations(decorationType, []); - }); + } } dispose() { - Array.from(this.decorationTypes.values()).forEach((decorationType) => { + for (const decorationType of this.decorationTypes.values()) { decorationType.dispose(); - }); + } } } diff --git a/packages/app-vscode/src/ide/vscode/VSCodeScopeVisualizer/VscodeScopeVisualizer.ts b/packages/app-vscode/src/ide/vscode/VSCodeScopeVisualizer/VscodeScopeVisualizer.ts index 89bce2b34a..0e500060bc 100644 --- a/packages/app-vscode/src/ide/vscode/VSCodeScopeVisualizer/VscodeScopeVisualizer.ts +++ b/packages/app-vscode/src/ide/vscode/VSCodeScopeVisualizer/VscodeScopeVisualizer.ts @@ -97,7 +97,9 @@ export abstract class VscodeScopeVisualizer { } dispose() { - this.disposables.forEach((disposable) => disposable.dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } this.renderer?.dispose(); this.scopeListenerDisposable?.dispose(); } diff --git a/packages/app-vscode/src/ide/vscode/VscodeEdit.ts b/packages/app-vscode/src/ide/vscode/VscodeEdit.ts index dbf39c879a..3263c08008 100644 --- a/packages/app-vscode/src/ide/vscode/VscodeEdit.ts +++ b/packages/app-vscode/src/ide/vscode/VscodeEdit.ts @@ -7,7 +7,7 @@ export async function vscodeEdit( edits: Edit[], ): Promise { return await editor.edit((editBuilder) => { - edits.forEach(({ range, text, isReplace }) => { + for (const { range, text, isReplace } of edits) { if (text === "") { editBuilder.delete(toVscodeRange(range)); } else if (range.isEmpty && !isReplace) { @@ -15,6 +15,6 @@ export async function vscodeEdit( } else { editBuilder.replace(toVscodeRange(range), text); } - }); + } }); } diff --git a/packages/app-vscode/src/ide/vscode/VscodeFlashHandler.ts b/packages/app-vscode/src/ide/vscode/VscodeFlashHandler.ts index 95d9a3ecb8..66953fba56 100644 --- a/packages/app-vscode/src/ide/vscode/VscodeFlashHandler.ts +++ b/packages/app-vscode/src/ide/vscode/VscodeFlashHandler.ts @@ -38,12 +38,12 @@ export class VscodeFlashHandler { ): void { const editorRangeMap = groupBy(ranges, ({ editor }) => editor.id); - this.ide.visibleTextEditors.forEach((editor) => { + for (const editor of this.ide.visibleTextEditors) { const ranges = (editorRangeMap.get(editor.id) ?? []).map( ({ range }) => range, ); void this.highlights.setHighlightRanges(style, editor, ranges); - }); + } } } diff --git a/packages/app-vscode/src/ide/vscode/VscodeToggleBreakpoint.ts b/packages/app-vscode/src/ide/vscode/VscodeToggleBreakpoint.ts index c155f1434e..ecc644bf50 100644 --- a/packages/app-vscode/src/ide/vscode/VscodeToggleBreakpoint.ts +++ b/packages/app-vscode/src/ide/vscode/VscodeToggleBreakpoint.ts @@ -17,7 +17,7 @@ export async function vscodeToggleBreakpoint( const toAdd: vscode.Breakpoint[] = []; const toRemove: vscode.Breakpoint[] = []; - ranges.forEach((range) => { + for (const range of ranges) { const existing = getBreakpoints(uri, range); if (existing.length > 0) { @@ -34,7 +34,7 @@ export async function vscodeToggleBreakpoint( ), ); } - }); + } vscode.debug.addBreakpoints(toAdd); vscode.debug.removeBreakpoints(toRemove); diff --git a/packages/app-vscode/src/ide/vscode/hats/VscodeHatRenderer.ts b/packages/app-vscode/src/ide/vscode/hats/VscodeHatRenderer.ts index 7657d51887..6deb1b9ac0 100644 --- a/packages/app-vscode/src/ide/vscode/hats/VscodeHatRenderer.ts +++ b/packages/app-vscode/src/ide/vscode/hats/VscodeHatRenderer.ts @@ -180,9 +180,9 @@ export class VscodeHatRenderer { } private destroyDecorations() { - Object.values(this.decorationMap).forEach((decoration) => { + for (const decoration of Object.values(this.decorationMap)) { decoration.dispose(); - }); + } } private async recomputeDecorations() { @@ -495,7 +495,9 @@ export class VscodeHatRenderer { dispose() { this.destroyDecorations(); this.hatsDirWatcherDisposable?.dispose(); - this.disposables.forEach(({ dispose }) => dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } } } diff --git a/packages/app-vscode/src/ide/vscode/hats/VscodeHats.ts b/packages/app-vscode/src/ide/vscode/hats/VscodeHats.ts index fa58766197..e1f83bd85f 100644 --- a/packages/app-vscode/src/ide/vscode/hats/VscodeHats.ts +++ b/packages/app-vscode/src/ide/vscode/hats/VscodeHats.ts @@ -107,20 +107,20 @@ export class VscodeHats implements Hats { ]), ); - this.hatRanges.forEach(({ editor, range, styleName }) => { + for (const { editor, range, styleName } of this.hatRanges) { decorationRanges.get(editor)?.[styleName]?.push(range); - }); + } - decorationRanges.forEach((ranges, editor) => { - hatStyleNames.forEach((hatStyleName) => { + for (const [editor, ranges] of decorationRanges) { + for (const hatStyleName of hatStyleNames) { (editor as VscodeTextEditor).vscodeEditor.setDecorations( this.hatRenderer.getDecorationType( hatStyleName as VscodeHatStyleName, )!, ranges[hatStyleName]?.map((range) => toVscodeRange(range)) ?? [], ); - }); - }); + } + } } get enabledHatStyles(): HatStyleMap { diff --git a/packages/app-vscode/src/ide/vscode/textLine.vscode.test.ts b/packages/app-vscode/src/ide/vscode/textLine.vscode.test.ts index fc2ad2e60f..0aa7f8ec9d 100644 --- a/packages/app-vscode/src/ide/vscode/textLine.vscode.test.ts +++ b/packages/app-vscode/src/ide/vscode/textLine.vscode.test.ts @@ -16,7 +16,7 @@ const whiteSpaceTests: [string, number | undefined, number | undefined][] = [ suite("TextLine", function () { this.timeout("100s"); this.retries(5); - whiteSpaceTests.forEach(([text, trimmedStart, trimmedEnd]) => { + for (const [text, trimmedStart, trimmedEnd] of whiteSpaceTests) { test(`whitespace '${text}'`, async () => { const editor = await getReusableEditor(text); const line = new VscodeTextLine(editor.document.lineAt(0)); @@ -24,5 +24,5 @@ suite("TextLine", function () { assert.equal(line.rangeTrimmed?.start?.character, trimmedStart); assert.equal(line.rangeTrimmed?.end?.character, trimmedEnd); }); - }); + } }); diff --git a/packages/app-vscode/src/keyboard/KeyboardHandler.ts b/packages/app-vscode/src/keyboard/KeyboardHandler.ts index 65be18a6b2..caddf11e79 100644 --- a/packages/app-vscode/src/keyboard/KeyboardHandler.ts +++ b/packages/app-vscode/src/keyboard/KeyboardHandler.ts @@ -123,7 +123,9 @@ export class KeyboardHandler { } dispose() { - this.disposables.forEach(({ dispose }) => dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } } /** @@ -150,10 +152,10 @@ export class KeyboardHandler { // one. Eg if you're in the middle of typing a command and we turn off // the modal mode, we want to cancel the command if (index !== -1) { - this.listeners - .slice(index + 1) - .reverse() - .forEach(({ listener }) => listener.handleCancelled()); + const listenersToCancel = this.listeners.slice(index + 1).reverse(); + for (const entry of listenersToCancel) { + entry.listener.handleCancelled(); + } this.listeners.splice(index); } this.ensureState(); diff --git a/packages/app-vscode/src/keyboard/buildSuffixTrie.test.ts b/packages/app-vscode/src/keyboard/buildSuffixTrie.test.ts index e88cef202d..9c74edf403 100644 --- a/packages/app-vscode/src/keyboard/buildSuffixTrie.test.ts +++ b/packages/app-vscode/src/keyboard/buildSuffixTrie.test.ts @@ -120,7 +120,7 @@ const testCases: TestCase[] = [ ]; suite("buildSuffixTrie", () => { - testCases.forEach(({ input, expected, expectedConflicts }) => { + for (const { input, expected, expectedConflicts } of testCases) { test(`input: ${input}`, () => { const { trie, conflicts } = buildSuffixTrie( input.map((key) => [key, key]), @@ -138,7 +138,7 @@ suite("buildSuffixTrie", () => { (expectedConflicts ?? []).map(sortEntries), ); }); - }); + } }); function sortEntries(entries: KeyValuePair[]) { diff --git a/packages/app-vscode/src/keyboard/buildSuffixTrie.ts b/packages/app-vscode/src/keyboard/buildSuffixTrie.ts index 75f4667c5d..ba830e96d5 100644 --- a/packages/app-vscode/src/keyboard/buildSuffixTrie.ts +++ b/packages/app-vscode/src/keyboard/buildSuffixTrie.ts @@ -74,7 +74,9 @@ export function buildSuffixTrie(entries: [string, T][]): BuildTrieReturn { if (isTopLevel) { // If we're top-level, we mark every conflicting entry as bad - conflicting.forEach(({ id }) => badEntries.add(id)); + for (const entry of conflicting) { + badEntries.add(entry.id); + } const conflictingTopLevel = conflicting.filter( ({ isTopLevel }) => isTopLevel, @@ -94,9 +96,12 @@ export function buildSuffixTrie(entries: [string, T][]): BuildTrieReturn { ); } else { // If we're not top-level, we only mark other non-top-level entries as bad - conflicting - .filter(({ isTopLevel }) => !isTopLevel) - .forEach(({ id }) => badEntries.add(id)); + const nonTopLevelEntries = conflicting.filter( + (entry) => !entry.isTopLevel, + ); + for (const entry of nonTopLevelEntries) { + badEntries.add(entry.id); + } } // If we got here, we have a conflict, so we mark ourselves as bad diff --git a/packages/app-vscode/src/keyboard/grammar/getAcceptableTokenTypes.test.ts b/packages/app-vscode/src/keyboard/grammar/getAcceptableTokenTypes.test.ts index 620aa99f11..75bdf4f8a8 100644 --- a/packages/app-vscode/src/keyboard/grammar/getAcceptableTokenTypes.test.ts +++ b/packages/app-vscode/src/keyboard/grammar/getAcceptableTokenTypes.test.ts @@ -137,7 +137,7 @@ suite("keyboard.getAcceptableTokenTypes", () => { parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar)); }); - testCases.forEach(({ tokens, expected }) => { + for (const { tokens, expected } of testCases) { test(`after \`${stringifyTokens(tokens)}\``, () => { parser.feed(tokens); for (const value of expected) { @@ -160,5 +160,5 @@ suite("keyboard.getAcceptableTokenTypes", () => { ); } }); - }); + } }); diff --git a/packages/app-vscode/src/keyboard/grammar/grammar.test.ts b/packages/app-vscode/src/keyboard/grammar/grammar.test.ts index adc6f671d3..419ae8832a 100644 --- a/packages/app-vscode/src/keyboard/grammar/grammar.test.ts +++ b/packages/app-vscode/src/keyboard/grammar/grammar.test.ts @@ -184,12 +184,12 @@ suite("keyboard grammar", () => { parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar)); }); - testCases.forEach(({ tokens, expected }) => { + for (const { tokens, expected } of testCases) { test(`should parse \`${stringifyTokens(tokens)}\``, () => { parser.feed(tokens); assert.equal(parser.results.length, 1); assert.deepEqual(parser.results[0], expected); }); - }); + } }); diff --git a/packages/app-vscode/src/logQuickActions.ts b/packages/app-vscode/src/logQuickActions.ts index 3d32d30929..1747af0e05 100644 --- a/packages/app-vscode/src/logQuickActions.ts +++ b/packages/app-vscode/src/logQuickActions.ts @@ -31,9 +31,9 @@ export async function logQuickActions(kind?: string) { }), ); - availableCodeActions.forEach((availableCodeAction) => { + for (const availableCodeAction of availableCodeActions) { console.log(JSON.stringify(availableCodeAction, null, 2)); - }); + } void window.showInformationMessage( "Run command 'Developer: Toggle Developer Tools' to see available code actions", diff --git a/packages/app-vscode/src/scripts/hatAdjustments/average.ts b/packages/app-vscode/src/scripts/hatAdjustments/average.ts index e58452c2a7..0016ca807b 100644 --- a/packages/app-vscode/src/scripts/hatAdjustments/average.ts +++ b/packages/app-vscode/src/scripts/hatAdjustments/average.ts @@ -55,7 +55,8 @@ function main() { }), ); - (["value", "originalAdjustment", "newAdjustment"] as const).forEach((key) => { + const keys = ["value", "originalAdjustment", "newAdjustment"] as const; + for (const key of keys) { const map = Object.fromEntries( HAT_SHAPES.map((shape) => { return [ @@ -66,10 +67,10 @@ function main() { }, ]; }), - ) as IndividualHatAdjustmentMap; + ); console.log(`${key}: `); console.log(JSON.stringify(map, null, 2)); - }); + } } main(); diff --git a/packages/app-vscode/src/scripts/initLaunchSandbox.ts b/packages/app-vscode/src/scripts/initLaunchSandbox.ts index eb4fc8e125..3c5b1b2f0a 100644 --- a/packages/app-vscode/src/scripts/initLaunchSandbox.ts +++ b/packages/app-vscode/src/scripts/initLaunchSandbox.ts @@ -15,12 +15,12 @@ async function main() { // Read cli tool name from arguments, assume tool name is 'code' if not present let cliToolName = vsCodeToolName; - process.argv.forEach((argument) => { + for (const argument of process.argv) { if (validCliToolParams.has(argument)) { cliToolName = argument.replace("--", ""); console.log(`Cli tool name manually set to ${cliToolName}`); } - }); + } const extensions = [ ...extensionDependencies, diff --git a/packages/app-vscode/src/storedTargetHighlighter.ts b/packages/app-vscode/src/storedTargetHighlighter.ts index 4ce74b0729..5219e4d1b2 100644 --- a/packages/app-vscode/src/storedTargetHighlighter.ts +++ b/packages/app-vscode/src/storedTargetHighlighter.ts @@ -52,14 +52,14 @@ export function storedTargetHighlighter( ({ editor }) => editor.id, ); - ide.visibleTextEditors.forEach((editor) => { + for (const editor of ide.visibleTextEditors) { highlighter.setRanges( editor, (editorRangeMap.get(editor.id) ?? []).map(({ contentRange }) => toCharacterRange(contentRange), ), ); - }); + } }, ); diff --git a/packages/app-web-docs/src/docs/components/DynamicTOC.tsx b/packages/app-web-docs/src/docs/components/DynamicTOC.tsx index 947219b169..d4ffc185e8 100644 --- a/packages/app-web-docs/src/docs/components/DynamicTOC.tsx +++ b/packages/app-web-docs/src/docs/components/DynamicTOC.tsx @@ -40,10 +40,11 @@ function getTOC(minHeadingLevel: number, maxHeadingLevel: number) { const ul = document.createElement("ul"); ul.className = "table-of-contents table-of-contents__left-border"; + const headerElements = getHeaderElements(minHeadingLevel, maxHeadingLevel); let currentLevel: number | undefined = undefined; let indent = 0; - getHeaderElements(minHeadingLevel, maxHeadingLevel).forEach((header) => { + for (const header of headerElements) { const level = Number.parseInt(header.tagName[1], 10); if (level !== currentLevel) { @@ -63,7 +64,7 @@ function getTOC(minHeadingLevel: number, maxHeadingLevel: number) { li.append(a); ul.append(li); - }); + } toc.append(ul); col.append(toc); diff --git a/packages/app-web-docs/src/docs/components/ScopeVisualizer.tsx b/packages/app-web-docs/src/docs/components/ScopeVisualizer.tsx index fb4114fefc..53065c78bf 100644 --- a/packages/app-web-docs/src/docs/components/ScopeVisualizer.tsx +++ b/packages/app-web-docs/src/docs/components/ScopeVisualizer.tsx @@ -315,18 +315,19 @@ function getScopeFixtures( } const result: Scopes = { public: [], internal: [] }; + const sortedScopes = Object.values(scopeMap).sort(nameComparator); - Object.values(scopeMap) - .sort(nameComparator) - .forEach((scope) => { - scope.facets.sort(facetComparator); - scope.facets.forEach((f) => f.fixtures.sort(nameComparator)); - if (isScopeInternal(scope.scopeTypeType)) { - result.internal.push(scope); - } else { - result.public.push(scope); - } - }); + for (const scope of sortedScopes) { + scope.facets.sort(facetComparator); + for (const f of scope.facets) { + f.fixtures.sort(nameComparator); + } + if (isScopeInternal(scope.scopeTypeType)) { + result.internal.push(scope); + } else { + result.public.push(scope); + } + } return result; } diff --git a/packages/app-web-docs/src/docs/components/flattenHighlights.test.ts b/packages/app-web-docs/src/docs/components/flattenHighlights.test.ts index b8f4394d3c..382631ea70 100644 --- a/packages/app-web-docs/src/docs/components/flattenHighlights.test.ts +++ b/packages/app-web-docs/src/docs/components/flattenHighlights.test.ts @@ -80,7 +80,7 @@ const tests: Test[] = [ ]; suite("flatten highlights", () => { - tests.forEach((t) => { + for (const t of tests) { test(t.name, () => { const highlights = t.scopes.flatMap((s) => { const result: Highlight[] = []; @@ -96,7 +96,7 @@ suite("flatten highlights", () => { assert.equal(actual[i].range.concise(), t.expected[i]); } }); - }); + } }); function createHighlight(range: string): Highlight { diff --git a/packages/lib-common/src/ide/fake/FakeIDE.ts b/packages/lib-common/src/ide/fake/FakeIDE.ts index b5fcf64fbe..08db99c00c 100644 --- a/packages/lib-common/src/ide/fake/FakeIDE.ts +++ b/packages/lib-common/src/ide/fake/FakeIDE.ts @@ -146,7 +146,9 @@ export class FakeIDE implements EmittableIDE { } exit(): void { - this.disposables.forEach((disposable) => disposable.dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } } } diff --git a/packages/lib-common/src/testUtil/extractTargetedMarks.ts b/packages/lib-common/src/testUtil/extractTargetedMarks.ts index 79ddea61e7..9b0b72f9b3 100644 --- a/packages/lib-common/src/testUtil/extractTargetedMarks.ts +++ b/packages/lib-common/src/testUtil/extractTargetedMarks.ts @@ -8,14 +8,14 @@ export function extractTargetedMarks( ) { const targetedMarks: { [decoratedCharacter: string]: Token } = {}; - targetKeys.forEach((key) => { + for (const key of targetKeys) { const { hatStyle, character } = splitKey(key); const token = hatTokenMap.getToken(hatStyle, character); if (token == null) { throw new Error(`Couldn't find mark ${hatStyle} '${character}'`); } targetedMarks[key] = token; - }); + } return targetedMarks; } diff --git a/packages/lib-common/src/util/Notifier.ts b/packages/lib-common/src/util/Notifier.ts index 2c386bb515..e8045cc788 100644 --- a/packages/lib-common/src/util/Notifier.ts +++ b/packages/lib-common/src/util/Notifier.ts @@ -18,7 +18,9 @@ export class Notifier { notifyListeners = (...args: [...T]): void => { // Iterate over a snapshot so listener removal during notification doesn't // affect which listeners are notified in this cycle. - this.listeners.slice().forEach((listener) => listener(...args)); + for (const listener of this.listeners.slice()) { + listener(...args); + } }; /** diff --git a/packages/lib-common/src/util/disposableFrom.ts b/packages/lib-common/src/util/disposableFrom.ts index 1664f1c97f..09effa807f 100644 --- a/packages/lib-common/src/util/disposableFrom.ts +++ b/packages/lib-common/src/util/disposableFrom.ts @@ -9,7 +9,7 @@ import type { Disposable } from "../ide/types/ide.types"; export function disposableFrom(...disposables: Disposable[]): Disposable { return { dispose(): void { - disposables.forEach((disposable) => { + for (const disposable of disposables) { try { disposable.dispose(); } catch (error) { @@ -18,7 +18,7 @@ export function disposableFrom(...disposables: Disposable[]): Disposable { // disposables console.error(error); } - }); + } }, }; } diff --git a/packages/lib-common/src/util/itertools.ts b/packages/lib-common/src/util/itertools.ts index 435b3d044c..a3976132d4 100644 --- a/packages/lib-common/src/util/itertools.ts +++ b/packages/lib-common/src/util/itertools.ts @@ -8,7 +8,7 @@ export function groupBy(list: T[], func: (element: T) => U): Map { const map = new Map(); - list.forEach((element) => { + for (const element of list) { const key = func(element); let group: T[]; @@ -20,7 +20,7 @@ export function groupBy(list: T[], func: (element: T) => U): Map { } group.push(element); - }); + } return map; } diff --git a/packages/lib-common/src/util/object.ts b/packages/lib-common/src/util/object.ts index 2236cd131e..021abe86a3 100644 --- a/packages/lib-common/src/util/object.ts +++ b/packages/lib-common/src/util/object.ts @@ -8,7 +8,7 @@ export function mergeStrict( ): Record { const returnValue: Record = {}; - objects.forEach((object: object) => { + for (const object of objects) { for (const [key, value] of Object.entries(object)) { if (Object.hasOwn(returnValue, key)) { throw new Error(`Found duplicate property ${key}`); @@ -16,7 +16,7 @@ export function mergeStrict( returnValue[key] = value; } - }); + } return returnValue; } diff --git a/packages/lib-common/src/util/toPlainObject.ts b/packages/lib-common/src/util/toPlainObject.ts index 87c545d9bf..41f3793d17 100644 --- a/packages/lib-common/src/util/toPlainObject.ts +++ b/packages/lib-common/src/util/toPlainObject.ts @@ -119,10 +119,9 @@ export function marksToPlainObject(marks: { [decoratedCharacter: string]: Token; }) { const serializedMarks: SerializedMarks = {}; - Object.entries(marks).forEach( - ([key, value]: [string, Token]) => - (serializedMarks[key] = rangeToPlainObject(value.range)), - ); + for (const [key, value] of Object.entries(marks)) { + serializedMarks[key] = rangeToPlainObject(value.range); + } return serializedMarks; } diff --git a/packages/lib-common/src/util/uniqWithHash.test.ts b/packages/lib-common/src/util/uniqWithHash.test.ts index e0d60e8e97..fde8bcca8c 100644 --- a/packages/lib-common/src/util/uniqWithHash.test.ts +++ b/packages/lib-common/src/util/uniqWithHash.test.ts @@ -44,7 +44,7 @@ suite("uniqWithHash", () => { (_: number) => "0", ]; - hashFunctions.forEach((hash) => { + for (const hash of hashFunctions) { const check = (testCase: number[]) => { const actual = uniqWithHash(testCase, (a, b) => a === b, hash); const expected = knownGoodUniqWithHash( @@ -55,11 +55,13 @@ suite("uniqWithHash", () => { assert.deepEqual(actual, expected); }; - testCases.forEach(check); + for (const testCase of testCases) { + check(testCase); + } // max length 50 because the known good implementation is quadratic const randomNumbers = fc.array(fc.integer(), { maxLength: 50 }); fc.assert(fc.property(randomNumbers, check)); - }); + } }); }); diff --git a/packages/lib-common/src/util/uniqWithHash.ts b/packages/lib-common/src/util/uniqWithHash.ts index fa689a7d65..f74ecbcf32 100644 --- a/packages/lib-common/src/util/uniqWithHash.ts +++ b/packages/lib-common/src/util/uniqWithHash.ts @@ -53,9 +53,9 @@ export function uniqWithHash( // For hash collisions, uniq the items, // letting uniqWith provide correct semantics. - needsUniq.forEach((key) => { + for (const key of needsUniq) { hashToItems.set(key, uniqWith(hashToItems.get(key), isEqual)); - }); + } // To preserve order, step through the original items // one at a time, returning it as appropriate. diff --git a/packages/lib-engine/src/KeyboardTargetUpdater.ts b/packages/lib-engine/src/KeyboardTargetUpdater.ts index a01ffda7d6..1f97919cee 100644 --- a/packages/lib-engine/src/KeyboardTargetUpdater.ts +++ b/packages/lib-engine/src/KeyboardTargetUpdater.ts @@ -56,7 +56,9 @@ export class KeyboardTargetUpdater { } dispose() { - this.disposables.forEach((disposable) => disposable.dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } this.selectionWatcherDisposable?.dispose(); } } diff --git a/packages/lib-engine/src/actions/BringMoveSwap.ts b/packages/lib-engine/src/actions/BringMoveSwap.ts index ac5c7f2a71..76ede893fe 100644 --- a/packages/lib-engine/src/actions/BringMoveSwap.ts +++ b/packages/lib-engine/src/actions/BringMoveSwap.ts @@ -72,7 +72,7 @@ abstract class BringMoveSwap { const shouldJoinSources = sources.length !== destinations.length && destinations.length === 1; - sources.forEach((source, i) => { + for (const [i, source] of sources.entries()) { let destination = destinations[i]; let destinationEdit: ExtendedEdit | undefined; @@ -132,18 +132,18 @@ abstract class BringMoveSwap { }); } } - }); + } if (this.type === "move") { // Unify overlapping targets. - unifyRemovalTargets(usedSources).forEach((source) => { + for (const source of unifyRemovalTargets(usedSources)) { results.push({ edit: source.constructRemovalEdit(), editor: source.editor, originalTarget: source, isSource: true, }); - }); + } } return results; @@ -370,7 +370,7 @@ export class Swap extends BringMoveSwap { private getEditsSwap(targets1: Target[], targets2: Target[]): ExtendedEdit[] { const results: ExtendedEdit[] = []; - targets1.forEach((target1, i) => { + for (const [i, target1] of targets1.entries()) { const target2 = targets2[i]; if (target1 == null || target2 == null) { throw new Error("Targets must have same number of args"); @@ -395,7 +395,7 @@ export class Swap extends BringMoveSwap { originalTarget: target1, isSource: true, }); - }); + } return results; } diff --git a/packages/lib-engine/src/actions/EditNew/runEditTargets.ts b/packages/lib-engine/src/actions/EditNew/runEditTargets.ts index b1fb1ed1e4..0e2a570910 100644 --- a/packages/lib-engine/src/actions/EditNew/runEditTargets.ts +++ b/packages/lib-engine/src/actions/EditNew/runEditTargets.ts @@ -80,16 +80,16 @@ export async function runEditTargets( const finalCursorRanges = [...state.cursorRanges]; // Update the cursor positions for the command targets - zip(cursorIndices, updatedCursorRanges).forEach(([index, range]) => { + for (const [index, range] of zip(cursorIndices, updatedCursorRanges)) { finalCursorRanges[index!] = range; - }); + } // Add cursor positions for our edit targets. - destinations.forEach((delimiterTarget, index) => { + for (const [index, delimiterTarget] of destinations.entries()) { const edit = edits[index]; const range = edit.updateRange(updatedEditRanges[index]); finalCursorRanges[delimiterTarget.index] = range; - }); + } return { destinations: state.destinations, diff --git a/packages/lib-engine/src/actions/EditNew/runInsertLineAfterTargets.ts b/packages/lib-engine/src/actions/EditNew/runInsertLineAfterTargets.ts index 46f98e3495..762e6374e1 100644 --- a/packages/lib-engine/src/actions/EditNew/runInsertLineAfterTargets.ts +++ b/packages/lib-engine/src/actions/EditNew/runInsertLineAfterTargets.ts @@ -78,9 +78,9 @@ export async function runInsertLineAfterTargets( // up after running the command. We add it to the state so that any // potential edit targets can update them after we return from this function. const cursorRanges = [...state.cursorRanges]; - destinations.forEach((commandTarget, index) => { + for (const [index, commandTarget] of destinations.entries()) { cursorRanges[commandTarget.index] = editor.selections[index]; - }); + } return { destinations: state.destinations.map((destination, index) => diff --git a/packages/lib-engine/src/actions/GenerateSnippet/Substituter.ts b/packages/lib-engine/src/actions/GenerateSnippet/Substituter.ts index 65b485c4de..2d663ced3d 100644 --- a/packages/lib-engine/src/actions/GenerateSnippet/Substituter.ts +++ b/packages/lib-engine/src/actions/GenerateSnippet/Substituter.ts @@ -49,12 +49,12 @@ export class Substituter { */ makeSubstitutions(text: string) { let output = text; - this.substitutions.forEach(({ to, randomId, isQuoted }) => { + for (const { to, randomId, isQuoted } of this.substitutions) { const from = isQuoted ? `"${randomId}"` : randomId; // NB: We use split / join instead of replace because the latter doesn't // handle dollar signs well output = output.split(from).join(to); - }); + } return output; } diff --git a/packages/lib-engine/src/actions/GenerateSnippet/constructSnippetBody.ts b/packages/lib-engine/src/actions/GenerateSnippet/constructSnippetBody.ts index fb499d2bfd..36b38738d3 100644 --- a/packages/lib-engine/src/actions/GenerateSnippet/constructSnippetBody.ts +++ b/packages/lib-engine/src/actions/GenerateSnippet/constructSnippetBody.ts @@ -46,7 +46,7 @@ export function constructSnippetBody( ...remainingLines.map((line) => ({ text: line, startIndex: 0 })), ]; - lines.forEach(({ text, startIndex }) => { + for (const { text, startIndex } of lines) { const newIndentationString = text.match(/^\s*/)?.[0] ?? ""; const firstNonWhitespaceCharacterIndex = newIndentationString.length; @@ -70,7 +70,7 @@ export function constructSnippetBody( const lineContent = text.slice(lineContentStart); outputLines.push(snippetIndentationString + lineContent); - }); + } return outputLines; } diff --git a/packages/lib-engine/src/actions/Scroll.ts b/packages/lib-engine/src/actions/Scroll.ts index 9765f67d6d..b929ccad06 100644 --- a/packages/lib-engine/src/actions/Scroll.ts +++ b/packages/lib-engine/src/actions/Scroll.ts @@ -84,10 +84,10 @@ export class ScrollToBottom extends Scroll { function getLineNumber(targets: Target[], at: RevealLineAt) { let startLine = Number.MAX_SAFE_INTEGER; let endLine = 0; - targets.forEach((target: Target) => { + for (const target of targets) { startLine = Math.min(startLine, target.contentRange.start.line); endLine = Math.max(endLine, target.contentRange.end.line); - }); + } if (at === RevealLineAt.top) { return startLine; diff --git a/packages/lib-engine/src/core/HatAllocator.ts b/packages/lib-engine/src/core/HatAllocator.ts index efd1ce1f96..3a2afbdad5 100644 --- a/packages/lib-engine/src/core/HatAllocator.ts +++ b/packages/lib-engine/src/core/HatAllocator.ts @@ -91,6 +91,8 @@ export class HatAllocator { } dispose() { - this.disposables.forEach(({ dispose }) => dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } } } diff --git a/packages/lib-engine/src/core/IndividualHatMap.ts b/packages/lib-engine/src/core/IndividualHatMap.ts index 17f776dbf4..daa3eda0cd 100644 --- a/packages/lib-engine/src/core/IndividualHatMap.ts +++ b/packages/lib-engine/src/core/IndividualHatMap.ts @@ -75,7 +75,9 @@ export class IndividualHatMap implements ReadOnlyHatMap { // Clear the old assignment this.map = {}; this.documentTokenLists = new Map(); - this.deregisterFunctions.forEach((func) => func()); + for (const func of this.deregisterFunctions) { + func(); + } this.deregisterFunctions = []; // Iterate through the hats in the new assignment, registering them with the @@ -136,7 +138,9 @@ export class IndividualHatMap implements ReadOnlyHatMap { dispose() { this.isExpired = true; - this.deregisterFunctions.forEach((func) => func()); + for (const func of this.deregisterFunctions) { + func(); + } this.deregisterFunctions = []; } } diff --git a/packages/lib-engine/src/core/commandVersionUpgrades/canonicalizeTargetsInPlace.ts b/packages/lib-engine/src/core/commandVersionUpgrades/canonicalizeTargetsInPlace.ts index 86bedb5110..162c85d1d9 100644 --- a/packages/lib-engine/src/core/commandVersionUpgrades/canonicalizeTargetsInPlace.ts +++ b/packages/lib-engine/src/core/commandVersionUpgrades/canonicalizeTargetsInPlace.ts @@ -20,13 +20,13 @@ const COLOR_CANONICALIZATION_MAPPING: Record = { function canonicalizeScopeTypesInPlace( target: PartialPrimitiveTargetDescriptor, ): void { - target.modifiers?.forEach((mod) => { + for (const mod of target.modifiers ?? []) { if (mod.type === "containingScope" || mod.type === "everyScope") { mod.scopeType.type = SCOPE_TYPE_CANONICALIZATION_MAPPING[mod.scopeType.type] ?? mod.scopeType.type; } - }); + } } function canonicalizeColorsInPlace( @@ -42,8 +42,8 @@ function canonicalizeColorsInPlace( export function canonicalizeTargetsInPlace( partialTargets: PartialTargetDescriptor[], ): void { - getPartialPrimitiveTargets(partialTargets).forEach((target) => { + for (const target of getPartialPrimitiveTargets(partialTargets)) { canonicalizeScopeTypesInPlace(target); canonicalizeColorsInPlace(target); - }); + } } diff --git a/packages/lib-engine/src/core/commandVersionUpgrades/upgradeV5ToV6/upgradeV5ToV6.ts b/packages/lib-engine/src/core/commandVersionUpgrades/upgradeV5ToV6/upgradeV5ToV6.ts index 886a0dd528..13cbbcc77f 100644 --- a/packages/lib-engine/src/core/commandVersionUpgrades/upgradeV5ToV6/upgradeV5ToV6.ts +++ b/packages/lib-engine/src/core/commandVersionUpgrades/upgradeV5ToV6/upgradeV5ToV6.ts @@ -276,7 +276,7 @@ function listTargetToDestination( } }; - target.elements.forEach((element) => { + for (const element of target.elements) { const insertionMode = getInsertionMode(element); if (insertionMode != null) { @@ -289,7 +289,7 @@ function listTargetToDestination( } else { currentElements.push(upgradeRangeOrPrimitiveTarget(element)); } - }); + } potentiallyAddDestination(); diff --git a/packages/lib-engine/src/core/updateSelections/RangeUpdater.ts b/packages/lib-engine/src/core/updateSelections/RangeUpdater.ts index b12766c41c..eede7436ba 100644 --- a/packages/lib-engine/src/core/updateSelections/RangeUpdater.ts +++ b/packages/lib-engine/src/core/updateSelections/RangeUpdater.ts @@ -147,7 +147,9 @@ export class RangeUpdater { } dispose() { - this.disposables.forEach((disposable) => disposable.dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } } } diff --git a/packages/lib-engine/src/core/updateSelections/updateSelections.test.ts b/packages/lib-engine/src/core/updateSelections/updateSelections.test.ts index 777c973cb3..b950f0375d 100644 --- a/packages/lib-engine/src/core/updateSelections/updateSelections.test.ts +++ b/packages/lib-engine/src/core/updateSelections/updateSelections.test.ts @@ -66,6 +66,8 @@ class TestIDE extends FakeIDE { }; override emitDidChangeTextDocument = (event: TextDocumentChangeEvent) => { - this.textDocumentChangeListeners.forEach((listener) => listener(event)); + for (const listener of this.textDocumentChangeListeners) { + listener(event); + } }; } diff --git a/packages/lib-engine/src/customCommandGrammar/grammarAction.test.ts b/packages/lib-engine/src/customCommandGrammar/grammarAction.test.ts index 58a55be076..bce9abf006 100644 --- a/packages/lib-engine/src/customCommandGrammar/grammarAction.test.ts +++ b/packages/lib-engine/src/customCommandGrammar/grammarAction.test.ts @@ -131,7 +131,7 @@ const testCases: TestCase[] = [ ]; suite("custom grammar: actions", () => { - testCases.forEach(({ input, expectedOutput }) => { + for (const { input, expectedOutput } of testCases) { test(input, () => { assert.deepEqual( parseAction(input), @@ -139,5 +139,5 @@ suite("custom grammar: actions", () => { JSON.stringify(parseAction(input), null, 4), ); }); - }); + } }); diff --git a/packages/lib-engine/src/customCommandGrammar/grammarScopeType.test.ts b/packages/lib-engine/src/customCommandGrammar/grammarScopeType.test.ts index 38b5ee8129..6300e17d37 100644 --- a/packages/lib-engine/src/customCommandGrammar/grammarScopeType.test.ts +++ b/packages/lib-engine/src/customCommandGrammar/grammarScopeType.test.ts @@ -31,9 +31,9 @@ const testCases: TestCase[] = [ ]; suite("custom grammar: scope types", () => { - testCases.forEach(({ input, expectedOutput }) => { + for (const { input, expectedOutput } of testCases) { test(input, () => { assert.deepEqual(parseScopeType(input), expectedOutput); }); - }); + } }); diff --git a/packages/lib-engine/src/customCommandGrammar/lexer.test.ts b/packages/lib-engine/src/customCommandGrammar/lexer.test.ts index d8cb062d44..eda25764a8 100644 --- a/packages/lib-engine/src/customCommandGrammar/lexer.test.ts +++ b/packages/lib-engine/src/customCommandGrammar/lexer.test.ts @@ -86,7 +86,7 @@ const fixtures: Fixture[] = [ ]; suite("custom grammar: lexer", () => { - fixtures.forEach(({ input, expectedOutput }) => { + for (const { input, expectedOutput } of fixtures) { test(input, () => { assert.deepEqual( Array.from(iterateTokens(lexer, input)).map(({ type, value }) => ({ @@ -96,7 +96,7 @@ suite("custom grammar: lexer", () => { expectedOutput, ); }); - }); + } }); function* iterateTokens(lexer: NearleyLexer, input: string) { diff --git a/packages/lib-engine/src/customCommandGrammar/lexer.ts b/packages/lib-engine/src/customCommandGrammar/lexer.ts index 8b54c63746..b62c5c0364 100644 --- a/packages/lib-engine/src/customCommandGrammar/lexer.ts +++ b/packages/lib-engine/src/customCommandGrammar/lexer.ts @@ -89,21 +89,22 @@ for (const [mark, spokenForm] of Object.entries(marks)) { } } -defaultSpokenFormMap.modifierExtra.next.spokenForms.forEach((spokenForm) => { +const nextSpokenForms = defaultSpokenFormMap.modifierExtra.next.spokenForms; +for (const spokenForm of nextSpokenForms) { tokens[spokenForm] = { type: "direction", value: "forward", }; -}); +} -defaultSpokenFormMap.modifierExtra.previous.spokenForms.forEach( - (spokenForm) => { - tokens[spokenForm] = { - type: "direction", - value: "backward", - }; - }, -); +const previousSpokenForms = + defaultSpokenFormMap.modifierExtra.previous.spokenForms; +for (const spokenForm of previousSpokenForms) { + tokens[spokenForm] = { + type: "direction", + value: "backward", + }; +} export const lexer = new CommandLexer({ ws: /[ \t]+/, diff --git a/packages/lib-engine/src/generateSpokenForm/CustomSpokenFormGeneratorImpl.ts b/packages/lib-engine/src/generateSpokenForm/CustomSpokenFormGeneratorImpl.ts index 6e80633a1f..80a3da55e2 100644 --- a/packages/lib-engine/src/generateSpokenForm/CustomSpokenFormGeneratorImpl.ts +++ b/packages/lib-engine/src/generateSpokenForm/CustomSpokenFormGeneratorImpl.ts @@ -79,6 +79,8 @@ export class CustomSpokenFormGeneratorImpl implements CustomSpokenFormGenerator } dispose() { - this.disposables.forEach((disposable) => disposable.dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } } } diff --git a/packages/lib-engine/src/generateSpokenForm/generateSpokenForm.test.ts b/packages/lib-engine/src/generateSpokenForm/generateSpokenForm.test.ts index ff3cd662a9..2a301d026f 100644 --- a/packages/lib-engine/src/generateSpokenForm/generateSpokenForm.test.ts +++ b/packages/lib-engine/src/generateSpokenForm/generateSpokenForm.test.ts @@ -30,9 +30,9 @@ const spokenFormMap: SpokenFormMap = mapSpokenForms( ); suite("Generate spoken forms", () => { - getRecordedTestPaths().forEach(({ name, path }) => - test(name, () => runTest(path)), - ); + for (const { name, path } of getRecordedTestPaths()) { + test(name, () => runTest(path)); + } test("generate spoken form for custom regex", () => { const generator = new SpokenFormGenerator({ diff --git a/packages/lib-engine/src/languages/LanguageDefinitions.ts b/packages/lib-engine/src/languages/LanguageDefinitions.ts index 9ee0f2276c..663562642d 100644 --- a/packages/lib-engine/src/languages/LanguageDefinitions.ts +++ b/packages/lib-engine/src/languages/LanguageDefinitions.ts @@ -73,9 +73,9 @@ export class LanguageDefinitionsImpl implements LanguageDefinitions { }), ide.onDidChangeVisibleTextEditors((editors) => { - editors.forEach( - ({ document }) => void this.loadLanguage(document.languageId), - ); + for (const editor of editors) { + void this.loadLanguage(editor.document.languageId); + } }), treeSitterQueryProvider.onChanges(() => this.reloadLanguageDefinitions()), @@ -156,6 +156,8 @@ export class LanguageDefinitionsImpl implements LanguageDefinitions { onDidChangeDefinition = this.notifier.registerListener; dispose() { - this.disposables.forEach((disposable) => disposable.dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } } } diff --git a/packages/lib-engine/src/languages/TreeSitterQuery/parsePredicates.ts b/packages/lib-engine/src/languages/TreeSitterQuery/parsePredicates.ts index 1fe3651c27..44cc0d35de 100644 --- a/packages/lib-engine/src/languages/TreeSitterQuery/parsePredicates.ts +++ b/packages/lib-engine/src/languages/TreeSitterQuery/parsePredicates.ts @@ -18,11 +18,21 @@ export function parsePredicates(predicateDescriptors: QueryPredicate[][]) { const errors: PredicateError[] = []; const predicates: PatternPredicate[][] = []; - predicateDescriptors.forEach((patternPredicateDescriptors, patternIdx) => { + for ( + let patternIdx = 0; + patternIdx < predicateDescriptors.length; + ++patternIdx + ) { /** The predicates for a given pattern */ const patternPredicates: PatternPredicate[] = []; + const patternPredicateDescriptors = predicateDescriptors[patternIdx]; - patternPredicateDescriptors.forEach((predicateDescriptor, predicateIdx) => { + for ( + let predicateIdx = 0; + predicateIdx < patternPredicateDescriptors.length; + ++predicateIdx + ) { + const predicateDescriptor = patternPredicateDescriptors[predicateIdx]; const operator = queryPredicateOperators.find( ({ name }) => name === predicateDescriptor.operator, ); @@ -33,27 +43,27 @@ export function parsePredicates(predicateDescriptors: QueryPredicate[][]) { predicateIdx, error: `Unknown predicate operator "${predicateDescriptor.operator}"`, }); - return; + continue; } const result = operator.createPredicate(predicateDescriptor.operands); if (!result.success) { - errors.push( - ...result.errors.map((error) => ({ + for (const error of result.errors) { + errors.push({ patternIdx, predicateIdx, error, - })), - ); - return; + }); + } + continue; } patternPredicates.push(result.predicate); - }); + } predicates.push(patternPredicates); - }); + } return { errors, predicates }; } diff --git a/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.test.ts b/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.test.ts index 68e445a2e0..fd0bf340b4 100644 --- a/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.test.ts +++ b/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.test.ts @@ -119,7 +119,7 @@ const testCases: TestCase[] = [ ]; suite("BaseScopeHandler", () => { - testCases.forEach((testCase) => { + for (const testCase of testCases) { test(testCase.name, () => { const editor = { document: { range: toRange(0, testCase.documentEnd ?? Infinity) }, @@ -165,7 +165,7 @@ suite("BaseScopeHandler", () => { assert.deepEqual(actualScopes, expectedScopes); }); - }); + } }); function fromScope(scope: TargetScope) { diff --git a/packages/lib-engine/src/scopeProviders/ScopeInfoProvider.ts b/packages/lib-engine/src/scopeProviders/ScopeInfoProvider.ts index 9fe28476ae..05ae88b805 100644 --- a/packages/lib-engine/src/scopeProviders/ScopeInfoProvider.ts +++ b/packages/lib-engine/src/scopeProviders/ScopeInfoProvider.ts @@ -59,7 +59,9 @@ export class ScopeInfoProvider { private onChange() { this.updateScopeTypeInfos(); - this.listeners.slice().forEach((listener) => listener(this.scopeInfos)); + for (const listener of this.listeners.slice()) { + listener(this.scopeInfos); + } } private updateScopeTypeInfos(): void { diff --git a/packages/lib-engine/src/scopeProviders/ScopeRangeWatcher.ts b/packages/lib-engine/src/scopeProviders/ScopeRangeWatcher.ts index 8e802718bc..7ed8183372 100644 --- a/packages/lib-engine/src/scopeProviders/ScopeRangeWatcher.ts +++ b/packages/lib-engine/src/scopeProviders/ScopeRangeWatcher.ts @@ -65,7 +65,7 @@ export class ScopeRangeWatcher { config: ScopeRangeConfig, ): Disposable { const fn = () => { - this.ide.visibleTextEditors.forEach((editor) => { + for (const editor of this.ide.visibleTextEditors) { let scopeRanges: ScopeRanges[]; try { scopeRanges = this.scopeRangeProvider.provideScopeRanges( @@ -91,7 +91,7 @@ export class ScopeRangeWatcher { } callback(editor, scopeRanges); - }); + } }; this.listeners.push(fn); @@ -118,12 +118,12 @@ export class ScopeRangeWatcher { config: IterationScopeRangeConfig, ): Disposable { const fn = () => { - this.ide.visibleTextEditors.forEach((editor) => { + for (const editor of this.ide.visibleTextEditors) { callback( editor, this.scopeRangeProvider.provideIterationScopeRanges(editor, config), ); - }); + } }; this.listeners.push(fn); @@ -138,17 +138,19 @@ export class ScopeRangeWatcher { } private onChange() { - this.listeners.slice().forEach((listener) => listener()); + for (const listener of this.listeners.slice()) { + listener(); + } } dispose(): void { - this.disposables.forEach(({ dispose }) => { + for (const disposable of this.disposables) { try { - dispose(); + disposable.dispose(); } catch { // do nothing; some of the VSCode disposables misbehave, and we don't // want that to prevent us from disposing the rest of the disposables } - }); + } } } diff --git a/packages/lib-engine/src/scopeProviders/ScopeSupportWatcher.ts b/packages/lib-engine/src/scopeProviders/ScopeSupportWatcher.ts index 9be585500f..f0454328ef 100644 --- a/packages/lib-engine/src/scopeProviders/ScopeSupportWatcher.ts +++ b/packages/lib-engine/src/scopeProviders/ScopeSupportWatcher.ts @@ -82,7 +82,9 @@ export class ScopeSupportWatcher { const supportLevels = this.getSupportLevels(); - this.listeners.slice().forEach((listener) => listener(supportLevels)); + for (const listener of this.listeners.slice()) { + listener(supportLevels); + } } private getSupportLevels(): ScopeSupportInfo[] { diff --git a/packages/lib-engine/src/snippets/transformSnippetVariables.ts b/packages/lib-engine/src/snippets/transformSnippetVariables.ts index a3e1d6c9b3..88ba306853 100644 --- a/packages/lib-engine/src/snippets/transformSnippetVariables.ts +++ b/packages/lib-engine/src/snippets/transformSnippetVariables.ts @@ -48,7 +48,10 @@ export function transformSnippetVariables( } const placeholder = new Placeholder(placeholderIndex); // oxlint-disable-next-line unicorn/prefer-dom-node-append - candidate.children.forEach((child) => placeholder.appendChild(child)); + for (const child of candidate.children) { + // oxlint-disable-next-line unicorn/prefer-dom-node-append + placeholder.appendChild(child); + } candidate.parent.replace(candidate, [placeholder]); } } else if (candidate instanceof Placeholder) { diff --git a/packages/lib-engine/src/test/scopes.test.ts b/packages/lib-engine/src/test/scopes.test.ts index b7d21957a7..12d5cc92e6 100644 --- a/packages/lib-engine/src/test/scopes.test.ts +++ b/packages/lib-engine/src/test/scopes.test.ts @@ -43,24 +43,22 @@ suite("Scope test cases", () => { languages[language] ??= []; } - Object.keys(languages) - .sort() - .forEach((languageId) => { - const tests = languages[languageId]; - test(`${languageId} facet coverage`, () => - testLanguageSupport( - languageId, - tests.map((test) => test.facet), - )); - }); + for (const languageId of Object.keys(languages).sort()) { + const tests = languages[languageId]; + test(`${languageId} facet coverage`, () => + testLanguageSupport( + languageId, + tests.map((test) => test.facet), + )); + } } - testPaths.forEach(({ path, name, languageId, facet }) => + for (const { path, name, languageId, facet } of testPaths) { test( name, asyncSafety(() => runTest(testEnvironment, path, languageId, facet)), - ), - ); + ); + } }); /** diff --git a/packages/lib-engine/src/test/sentenceSegmenter.test.ts b/packages/lib-engine/src/test/sentenceSegmenter.test.ts index e5eefaedab..fe4a715422 100644 --- a/packages/lib-engine/src/test/sentenceSegmenter.test.ts +++ b/packages/lib-engine/src/test/sentenceSegmenter.test.ts @@ -3,7 +3,7 @@ import { SentenceSegmenter } from "../processTargets/modifiers/scopeHandlers/Sen import { sentenceSegmenterFixture } from "./fixtures/sentenceSegmeter.fixture"; suite("Sentence segmenter", () => { - sentenceSegmenterFixture.forEach(({ input, expectedOutput }) => { + for (const { input, expectedOutput } of sentenceSegmenterFixture) { test(input, () => { assert.deepEqual( Array.from(new SentenceSegmenter().segment(input)).map( @@ -12,5 +12,5 @@ suite("Sentence segmenter", () => { expectedOutput, ); }); - }); + } }); diff --git a/packages/lib-engine/src/test/spokenForms.talon.test.ts b/packages/lib-engine/src/test/spokenForms.talon.test.ts index d933ccd31c..63171100c4 100644 --- a/packages/lib-engine/src/test/spokenForms.talon.test.ts +++ b/packages/lib-engine/src/test/spokenForms.talon.test.ts @@ -34,19 +34,21 @@ suite("Talon spoken forms", () => { ); // Test spoken forms in all of our recorded test fixtures - getRecordedTestPaths().forEach(({ name, path }) => - test(name, () => runRecordedFixture(repl, path)), - ); + for (const { name, path } of getRecordedTestPaths()) { + test(name, () => runRecordedFixture(repl, path)); + } // A few more spoken forms that we want to test - [ + const fixtures = [ ...synonymousSpokenFormsFixture, ...talonApiFixture, ...multiActionFixture, ...communitySnippetsSpokenFormsFixture, - ].forEach(({ spokenForm, commands, mockedGetValue }) => - test(spokenForm, () => runTest(repl, spokenForm, commands, mockedGetValue)), - ); + ]; + + for (const { spokenForm, commands, mockedGetValue } of fixtures) { + test(spokenForm, () => runTest(repl, spokenForm, commands, mockedGetValue)); + } }); async function runRecordedFixture(repl: TalonRepl, file: string) { diff --git a/packages/lib-engine/src/test/subtoken.test.ts b/packages/lib-engine/src/test/subtoken.test.ts index 768673e3cc..69940f2a75 100644 --- a/packages/lib-engine/src/test/subtoken.test.ts +++ b/packages/lib-engine/src/test/subtoken.test.ts @@ -6,7 +6,7 @@ import { subtokenFixture } from "./fixtures/subtoken.fixture"; suite("subtoken regex matcher", () => { const ide = new FakeIDE(); - subtokenFixture.forEach(({ input, expectedOutput }) => { + for (const { input, expectedOutput } of subtokenFixture) { test(input, () => { assert.deepEqual( new WordTokenizer(ide, "anyLang") @@ -15,5 +15,5 @@ suite("subtoken regex matcher", () => { expectedOutput, ); }); - }); + } }); diff --git a/packages/lib-engine/src/testUtil/serializeScopeFixture.ts b/packages/lib-engine/src/testUtil/serializeScopeFixture.ts index 53fed85019..ff03777eba 100644 --- a/packages/lib-engine/src/testUtil/serializeScopeFixture.ts +++ b/packages/lib-engine/src/testUtil/serializeScopeFixture.ts @@ -124,7 +124,7 @@ function serializeIterationScope( (range) => !domain.isRangeEqual(range.range), ); - ranges.forEach((range, index) => { + for (const [index, range] of ranges.entries()) { if (!groupHeaders && index > 0) { lines.push(""); } @@ -141,7 +141,7 @@ function serializeIterationScope( if (!groupHeaders) { lines.push(serializeTargetRange(codeLines, range.range)); } - }); + } if (!groupHeaders) { lines.push(""); @@ -192,11 +192,11 @@ function serializeTarget({ const rangeGroups = groupRanges(ranges); - rangeGroups.forEach((group, i) => { + for (const [i, group] of rangeGroups.entries()) { if (i > 0) { lines.push(""); } - group.headers.forEach((header, j) => { + for (const [j, header] of group.headers.entries()) { lines.push( serializeHeader({ header, @@ -205,9 +205,9 @@ function serializeTarget({ range: j === group.headers.length - 1 ? group.range : undefined, }), ); - }); + } lines.push(serializeTargetRange(codeLines, group.range)); - }); + } if (target.leadingDelimiter != null) { lines.push( @@ -285,7 +285,7 @@ function groupRanges(ranges: [string, Range][]) { const groups: { headers: string[]; range: Range }[] = []; const map: Record = {}; - ranges.forEach(([header, range]) => { + for (const [header, range] of ranges) { const existingGroup = map[range.concise()]; if (existingGroup != null) { existingGroup.headers.push(header); @@ -294,7 +294,7 @@ function groupRanges(ranges: [string, Range][]) { groups.push(group); map[range.concise()] = group; } - }); + } return groups; } diff --git a/packages/lib-engine/src/tokenGraphemeSplitter/tokenGraphemeSplitter.test.ts b/packages/lib-engine/src/tokenGraphemeSplitter/tokenGraphemeSplitter.test.ts index 71ca0359d9..caa10c2693 100644 --- a/packages/lib-engine/src/tokenGraphemeSplitter/tokenGraphemeSplitter.test.ts +++ b/packages/lib-engine/src/tokenGraphemeSplitter/tokenGraphemeSplitter.test.ts @@ -280,7 +280,7 @@ const tokenHatSplittingDefaults: TokenHatSplittingMode = { symbolsToPreserve: [], }; -tests.forEach(({ tokenHatSplittingMode, extraTestCases }) => { +for (const { tokenHatSplittingMode, extraTestCases } of tests) { suite(`getTokenGraphemes(${JSON.stringify(tokenHatSplittingMode)})`, () => { const ide = new FakeIDE(); @@ -291,7 +291,7 @@ tests.forEach(({ tokenHatSplittingMode, extraTestCases }) => { const testCases = [...commonTestCases, ...extraTestCases]; - testCases.forEach(([input, compactExpectedOutput]) => { + for (const [input, compactExpectedOutput] of testCases) { const expectedOutput = compactExpectedOutput.map( ([text, tokenStartOffset, tokenEndOffset]) => ({ text, @@ -308,6 +308,6 @@ tests.forEach(({ tokenHatSplittingMode, extraTestCases }) => { ); assert.deepEqual(actualOutput, expectedOutput); }); - }); + } }); -}); +} diff --git a/packages/lib-engine/src/tokenGraphemeSplitter/tokenGraphemeSplitter.ts b/packages/lib-engine/src/tokenGraphemeSplitter/tokenGraphemeSplitter.ts index b12ff8616d..726e54bca1 100644 --- a/packages/lib-engine/src/tokenGraphemeSplitter/tokenGraphemeSplitter.ts +++ b/packages/lib-engine/src/tokenGraphemeSplitter/tokenGraphemeSplitter.ts @@ -187,7 +187,9 @@ export class TokenGraphemeSplitter { this.algorithmChangeNotifier.registerListener; dispose() { - this.disposables.forEach(({ dispose }) => dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } } } diff --git a/packages/lib-engine/src/tokenizer/tokenizer.test.ts b/packages/lib-engine/src/tokenizer/tokenizer.test.ts index 7bea485cdc..61f17c538c 100644 --- a/packages/lib-engine/src/tokenizer/tokenizer.test.ts +++ b/packages/lib-engine/src/tokenizer/tokenizer.test.ts @@ -119,49 +119,42 @@ const languageTokenizerTests: Record = { suite("tokenizer", () => { const ide = new FakeIDE(); - Object.entries(languageTokenizerTests).forEach( - ([languageId, { wordSeparators }]) => { - ide.configuration.mockConfigurationScope( - { - languageId, - }, - { - wordSeparators, - }, - ); - }, - ); + for (const languageId of Object.keys(languageTokenizerTests)) { + ide.configuration.mockConfigurationScope( + { + languageId, + }, + { + wordSeparators: languageTokenizerTests[languageId].wordSeparators, + }, + ); + } - globalTests.forEach(([input, expectedOutput]) => { + for (const [input, expectedOutput] of globalTests) { test(`tokenizer test, input: "${input}"`, () => { const output = tokenize(ide, input, "anyLang", (match) => match[0]); assert.deepEqual(output, expectedOutput); }); - }); + } - Object.entries(languageTokenizerTests).forEach( - ([ - language, - { - additionalTests: languageSpecificTests, - exclusionPredicate = () => false, - }, - ]) => { - const tests = [ - ...languageSpecificTests, - ...globalTests.filter( - ([input, _expectedOutput]) => !exclusionPredicate(input), - ), - ]; + for (const languageId of Object.keys(languageTokenizerTests)) { + const languageSpecificTests = languageTokenizerTests[languageId]; + const exclusionPredicate = + languageSpecificTests.exclusionPredicate ?? (() => false); + const tests = [ + ...languageSpecificTests.additionalTests, + ...globalTests.filter( + ([input, _expectedOutput]) => !exclusionPredicate(input), + ), + ]; - tests.forEach(([input, expectedOutput]) => { - test(`${language} custom tokenizer, input: "${input}"`, () => { - const output = tokenize(ide, input, language, (match) => match[0]); - assert.deepEqual(output, expectedOutput); - }); + for (const [input, expectedOutput] of tests) { + test(`${languageId} custom tokenizer, input: "${input}"`, () => { + const output = tokenize(ide, input, languageId, (match) => match[0]); + assert.deepEqual(output, expectedOutput); }); - }, - ); + } + } }); /** diff --git a/packages/lib-engine/src/util/allocateHats/allocateHats.ts b/packages/lib-engine/src/util/allocateHats/allocateHats.ts index 5aea0dcf50..534dd1f9b8 100644 --- a/packages/lib-engine/src/util/allocateHats/allocateHats.ts +++ b/packages/lib-engine/src/util/allocateHats/allocateHats.ts @@ -164,9 +164,9 @@ function getTokenOldHatMap(oldTokenHats: readonly TokenHat[]) { ({ editor, offsets }) => [editor.id, offsets.start, offsets.end], ); - oldTokenHats.forEach((descriptor) => - tokenOldHatMap.set(descriptor.token, descriptor), - ); + for (const descriptor of oldTokenHats) { + tokenOldHatMap.set(descriptor.token, descriptor); + } return tokenOldHatMap; } diff --git a/packages/lib-engine/src/util/allocateHats/getHatRankingContext.ts b/packages/lib-engine/src/util/allocateHats/getHatRankingContext.ts index 40884ece70..7044c66e84 100644 --- a/packages/lib-engine/src/util/allocateHats/getHatRankingContext.ts +++ b/packages/lib-engine/src/util/allocateHats/getHatRankingContext.ts @@ -39,26 +39,25 @@ export function getHatRankingContext( number >(({ grapheme, hatStyle }) => [grapheme, hatStyle]); - tokens.forEach(({ token, rank }) => { + for (const { token, rank } of tokens) { const existingTokenHat = oldTokenHatMap.get(token); if (existingTokenHat != null) { hatOldTokenRanks.set(existingTokenHat, rank); } - tokenGraphemeSplitter - .getTokenGraphemes(token.text) - .forEach(({ text: graphemeText }) => { - let tokenRanksForGrapheme: number[]; + const graphemes = tokenGraphemeSplitter.getTokenGraphemes(token.text); + for (const grapheme of graphemes) { + let tokenRanksForGrapheme: number[]; - if (graphemeText in graphemeTokenRanks) { - tokenRanksForGrapheme = graphemeTokenRanks[graphemeText]; - } else { - tokenRanksForGrapheme = []; - graphemeTokenRanks[graphemeText] = tokenRanksForGrapheme; - } + if (grapheme.text in graphemeTokenRanks) { + tokenRanksForGrapheme = graphemeTokenRanks[grapheme.text]; + } else { + tokenRanksForGrapheme = []; + graphemeTokenRanks[grapheme.text] = tokenRanksForGrapheme; + } - tokenRanksForGrapheme.push(rank); - }); - }); + tokenRanksForGrapheme.push(rank); + } + } return { hatOldTokenRanks, diff --git a/packages/lib-engine/src/util/allocateHats/maxByFirstDiffering.test.ts b/packages/lib-engine/src/util/allocateHats/maxByFirstDiffering.test.ts index e2d11a7d2b..c00957a295 100644 --- a/packages/lib-engine/src/util/allocateHats/maxByFirstDiffering.test.ts +++ b/packages/lib-engine/src/util/allocateHats/maxByFirstDiffering.test.ts @@ -31,10 +31,10 @@ suite("maxByFirstDiffering", () => { [1, 0, 0, 1], ]; - testCases.forEach((testCase) => { + for (const testCase of testCases) { const actual = maxByAllowingTies(testCase, (x) => x); const expected = goldenMaxByAllowingTies(testCase, (x) => x); assert.deepEqual(actual, expected); - }); + } }); }); diff --git a/packages/lib-engine/src/util/unifyRanges.ts b/packages/lib-engine/src/util/unifyRanges.ts index fd5d09ad16..715e028ca2 100644 --- a/packages/lib-engine/src/util/unifyRanges.ts +++ b/packages/lib-engine/src/util/unifyRanges.ts @@ -33,7 +33,7 @@ function unifyTargetsOnePass(targets: Target[]): [Target[], boolean] { } const results: Target[] = []; let currentGroup: Target[] = []; - targets.forEach((target) => { + for (const target of targets) { // No intersection. Mark start of new group if ( currentGroup.length > 0 && @@ -44,7 +44,7 @@ function unifyTargetsOnePass(targets: Target[]): [Target[], boolean] { } else { currentGroup.push(target); } - }); + } results.push(mergeTargets(currentGroup)); return [results, results.length !== targets.length]; } diff --git a/packages/lib-node-common/src/Cheatsheet.ts b/packages/lib-node-common/src/Cheatsheet.ts index baac962a45..d0c69f5268 100644 --- a/packages/lib-node-common/src/Cheatsheet.ts +++ b/packages/lib-node-common/src/Cheatsheet.ts @@ -60,9 +60,9 @@ export async function updateDefaults(spokenFormInfo: CheatsheetInfo) { const outputObject = produce(spokenFormInfo, (draft) => { draft.sections = sortBy(draft.sections, "id"); - draft.sections.forEach((section) => { + for (const section of draft.sections) { section.items = sortBy(section.items, "id"); - }); + } }); const json = JSON.stringify(outputObject, null, 2); diff --git a/packages/lib-node-common/src/FileSystemRawTreeSitterQueryProvider.ts b/packages/lib-node-common/src/FileSystemRawTreeSitterQueryProvider.ts index f1f8d31d8f..ead878516e 100644 --- a/packages/lib-node-common/src/FileSystemRawTreeSitterQueryProvider.ts +++ b/packages/lib-node-common/src/FileSystemRawTreeSitterQueryProvider.ts @@ -42,6 +42,8 @@ export class FileSystemRawTreeSitterQueryProvider implements RawTreeSitterQueryP } dispose() { - this.disposables.forEach((disposable) => disposable.dispose()); + for (const disposable of this.disposables) { + disposable.dispose(); + } } } diff --git a/packages/lib-node-common/src/getScopeTestPathsRecursively.ts b/packages/lib-node-common/src/getScopeTestPathsRecursively.ts index ec079f22a9..ba28f2bd71 100644 --- a/packages/lib-node-common/src/getScopeTestPathsRecursively.ts +++ b/packages/lib-node-common/src/getScopeTestPathsRecursively.ts @@ -66,7 +66,11 @@ export function getScopeTestLanguagesRecursively(): Record { if (!result[languageId].includes(importLanguageId)) { result[languageId].push(importLanguageId); const config = configs[importLanguageId]; - config?.imports?.forEach((lang) => add(languageId, lang)); + if (config?.imports != null) { + for (const lang of config.imports) { + add(languageId, lang); + } + } } } @@ -74,7 +78,9 @@ export function getScopeTestLanguagesRecursively(): Record { if (config.skip) { continue; } - config.imports?.forEach((lang) => add(languageId, lang)); + for (const lang of config.imports ?? []) { + add(languageId, lang); + } } return result; diff --git a/packages/lib-node-common/src/runRecordedTest.ts b/packages/lib-node-common/src/runRecordedTest.ts index b2b630bc77..6266a0054b 100644 --- a/packages/lib-node-common/src/runRecordedTest.ts +++ b/packages/lib-node-common/src/runRecordedTest.ts @@ -256,7 +256,7 @@ function checkMarks( return; } - Object.entries(marks).forEach(([key, token]) => { + for (const [key, token] of Object.entries(marks)) { const { hatStyle, character } = splitKey(key); const currentToken = hatTokenMap.getToken(hatStyle, character); assert.ok( @@ -264,5 +264,5 @@ function checkMarks( `Mark "${hatStyle} ${character}" not found`, ); assert.deepEqual(rangeToPlainObject(currentToken.range), token); - }); + } } diff --git a/packages/lib-node-common/src/walkSync.ts b/packages/lib-node-common/src/walkSync.ts index 91caafb5ef..2b8555ba62 100644 --- a/packages/lib-node-common/src/walkSync.ts +++ b/packages/lib-node-common/src/walkSync.ts @@ -10,14 +10,14 @@ import * as path from "node:path"; */ export const walkFilesSync = (dir: string): string[] => { let filelist: string[] = []; - readdirSync(dir, { withFileTypes: true }).forEach((dirent) => { + for (const dirent of readdirSync(dir, { withFileTypes: true })) { const filePath = path.join(dir, dirent.name); if (dirent.isDirectory()) { filelist = filelist.concat(walkFilesSync(filePath)); } else { filelist.push(filePath); } - }); + } return filelist; }; @@ -31,13 +31,13 @@ export const walkDirsSync = (dir: string): string[] => { // Inner function returns absolute paths const walkDirsSyncInner = (dir: string): string[] => { let dirlist: string[] = []; - readdirSync(dir, { withFileTypes: true }).forEach((dirent) => { + for (const dirent of readdirSync(dir, { withFileTypes: true })) { if (dirent.isDirectory()) { const dirPath = path.join(dir, dirent.name); dirlist.push(dirPath); dirlist = dirlist.concat(walkDirsSyncInner(dirPath)); } - }); + } return dirlist; }; // Convert to relative paths diff --git a/packages/test-runner/src/launchNeovimAndRunTests.ts b/packages/test-runner/src/launchNeovimAndRunTests.ts index 2bf759e958..7f166c9978 100644 --- a/packages/test-runner/src/launchNeovimAndRunTests.ts +++ b/packages/test-runner/src/launchNeovimAndRunTests.ts @@ -47,9 +47,9 @@ export async function launchNeovimAndRunTests() { console.log("init.lua copying done"); console.log("listing nvim/:"); - readdirSync(nvimFolder).forEach((file) => { + for (const file of readdirSync(nvimFolder)) { console.log(`\t${file}`); - }); + } const logName = `${getCursorlessRepoRoot()}/packages/app-neovim/out/nvim_node.log`; @@ -98,11 +98,12 @@ export async function launchNeovimAndRunTests() { await sleep(5000); console.log("listing cursorless-neovim/out/:"); - readdirSync(`${getCursorlessRepoRoot()}/packages/app-neovim/out/`).forEach( - (file) => { - console.log(`\t${file}`); - }, + const files = readdirSync( + `${getCursorlessRepoRoot()}/packages/app-neovim/out/`, ); + for (const file of files) { + console.log(`\t${file}`); + } await sleep(10_000); diff --git a/packages/test-runner/src/runAllTests.ts b/packages/test-runner/src/runAllTests.ts index 826db7a1d1..6f8f8292ee 100644 --- a/packages/test-runner/src/runAllTests.ts +++ b/packages/test-runner/src/runAllTests.ts @@ -1,5 +1,5 @@ import * as path from "node:path"; -import glob from "fast-glob"; +import fastGlob from "fast-glob"; import Mocha from "mocha"; import { getCursorlessRepoRoot } from "@cursorless/lib-node-common"; import { @@ -78,9 +78,10 @@ async function runTestsInDir( grep: testSubsetGrepString(), }); - const files = await glob(`**/*.${filePattern}`, { + const files = await fastGlob(`**/*.${filePattern}`, { cwd: testRoot, followSymbolicLinks: false, + absolute: true, ignore: ["**/node_modules/**", ...ignore], }); @@ -91,7 +92,9 @@ async function runTestsInDir( } // Add files to the test suite - files.forEach((f) => mocha.addFile(path.resolve(testRoot, f))); + for (const file of files) { + mocha.addFile(file); + } // Run the mocha test await new Promise((resolve, reject) => { diff --git a/packages/test-vscode-e2e/src/suite/recorded.vscode.test.ts b/packages/test-vscode-e2e/src/suite/recorded.vscode.test.ts index 0f80b81a65..243681df62 100644 --- a/packages/test-vscode-e2e/src/suite/recorded.vscode.test.ts +++ b/packages/test-vscode-e2e/src/suite/recorded.vscode.test.ts @@ -28,7 +28,7 @@ suite("recorded test cases", function () { setupFake(ide, HatStability.stable); }); - getRecordedTestPaths().forEach(({ name, path }) => + for (const { name, path } of getRecordedTestPaths()) { test( name, asyncSafety(async () => { @@ -45,8 +45,8 @@ suite("recorded test cases", function () { runCursorlessCommand, }); }), - ), - ); + ); + } }); async function openNewTestEditor(