From 5ef59ca27869dd915ff48b126ce1320f317866d7 Mon Sep 17 00:00:00 2001 From: Hweinstock <42325418+Hweinstock@users.noreply.github.com> Date: Mon, 23 Dec 2024 16:29:29 -0500 Subject: [PATCH] build(lint): enable `no-array-for-each` #6281 ## Problem Many bugs, and confusing behavior stem from developers using an async function within a forEach. This is almost always not desired. Additionally, `forEach` can lead to bloated implementations when other methods like `some`, `find`, `reduce`, or `flatMap` are more applicable. According to https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-for-each.md It is also faster with `for ... of`. ## Solution - Add lint rule: https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-for-each.md - Migrate existing cases with `eslint CLI --fix` (75% of cases). - For remaining cases, mark as exception. --- .eslintrc.js | 2 + .../controller/inlineChatController.ts | 4 +- .../src/inlineChat/output/computeDiff.ts | 7 +- .../amazonq/test/e2e/amazonq/explore.test.ts | 4 +- .../amazonq/test/e2e/amazonq/welcome.test.ts | 4 +- .../service/keyStrokeHandler.test.ts | 4 +- .../util/crossFileContextUtil.test.ts | 16 ++--- .../codewhisperer/util/editorContext.test.ts | 4 +- .../util/runtimeLanguageContext.test.ts | 12 ++-- .../util/securityScanLanguageContext.test.ts | 4 +- packages/amazonq/test/web/testRunner.ts | 1 + .../scripts/build/generateServiceClient.ts | 8 +-- packages/core/scripts/lint/testLint.ts | 4 +- .../commons/controllers/contentController.ts | 4 +- packages/core/src/amazonq/commons/diff.ts | 4 +- .../core/src/amazonq/lsp/lspController.ts | 34 ++++----- packages/core/src/amazonq/webview/ui/main.ts | 4 +- .../webview/ui/quickActions/handler.ts | 8 +-- packages/core/src/amazonqDoc/app.ts | 4 +- packages/core/src/amazonqFeatureDev/app.ts | 4 +- .../chat/controller/messenger/messenger.ts | 12 ++-- .../amazonqTest/chat/controller/controller.ts | 8 +-- .../applicationcomposer/composerWebview.ts | 4 +- .../src/auth/credentials/sharedCredentials.ts | 4 +- .../core/src/auth/credentials/validation.ts | 6 +- packages/core/src/auth/sso/cache.ts | 4 +- packages/core/src/auth/sso/server.ts | 4 +- .../accessanalyzer/vue/iamPolicyChecks.ts | 6 ++ .../appBuilder/explorer/detectSamProjects.ts | 4 +- .../wizards/templateParametersWizard.ts | 4 +- .../src/awsService/apprunner/activation.ts | 4 +- .../apprunner/explorer/apprunnerNode.ts | 2 + .../cdk/explorer/detectCdkProjects.ts | 4 +- .../cloudWatchLogs/commands/tailLogGroup.ts | 15 ++-- .../document/logStreamsCodeLensProvider.ts | 4 +- .../core/src/awsService/ec2/activation.ts | 1 + .../awsService/ec2/remoteSessionManager.ts | 1 + packages/core/src/awsexplorer/toolView.ts | 4 +- packages/core/src/codecatalyst/explorer.ts | 4 +- .../codecatalyst/wizards/devenvSettings.ts | 4 +- packages/core/src/codewhisperer/activation.ts | 4 +- .../src/codewhisperer/client/codewhisperer.ts | 8 +-- .../codewhisperer/commands/basicCommands.ts | 72 ++++++++++--------- .../service/completionProvider.ts | 4 +- .../service/diagnosticsProvider.ts | 54 +++++++------- .../service/importAdderProvider.ts | 1 + .../service/recommendationHandler.ts | 24 +++---- .../service/securityScanHandler.ts | 16 ++--- .../transformByQ/transformApiHandler.ts | 19 +++-- .../transformByQ/transformFileHandler.ts | 2 + .../transformationResultsViewProvider.ts | 12 ++-- .../codewhispererCodeCoverageTracker.ts | 4 +- .../core/src/codewhisperer/util/authUtil.ts | 4 +- .../codewhisperer/util/closingBracketUtil.ts | 4 +- .../codewhisperer/util/customizationUtil.ts | 10 +-- .../src/codewhisperer/util/editorContext.ts | 4 +- .../src/codewhisperer/util/licenseUtil.ts | 10 +-- .../util/supplementalContext/rankBm25.ts | 38 +++++----- .../src/codewhisperer/util/telemetryHelper.ts | 4 +- .../core/src/codewhisperer/util/zipUtil.ts | 9 ++- .../views/securityPanelViewProvider.ts | 37 +++++----- .../controllers/chat/chatRequest/converter.ts | 30 ++++---- .../controllers/chat/controller.ts | 4 +- .../src/codewhispererChat/editor/codelens.ts | 4 +- .../editor/context/file/fileExtractor.ts | 10 +-- .../storages/triggerEvents.ts | 1 + .../commands/downloadSchemaItemCode.ts | 4 +- .../src/eventSchemas/vue/searchSchemas.ts | 4 +- packages/core/src/extensionNode.ts | 21 +++--- .../src/lambda/commands/createNewSamApp.ts | 4 +- .../vue/configEditor/samInvokeFrontend.ts | 4 +- .../src/lambda/wizards/samDeployWizard.ts | 4 +- .../webview/vue/toolkit/backend_toolkit.ts | 4 +- packages/core/src/shared/awsClientBuilder.ts | 4 +- .../core/src/shared/codelens/codeLensUtils.ts | 4 +- .../src/shared/codelens/goCodeLensProvider.ts | 1 + .../defaultCredentialSelectionDataProvider.ts | 8 +-- .../core/src/shared/extensionUtilities.ts | 12 ++-- packages/core/src/shared/extensions/git.ts | 21 ++++-- packages/core/src/shared/featureConfig.ts | 17 ++--- .../shared/multiStepInputFlowController.ts | 8 ++- .../core/src/shared/regions/regionProvider.ts | 16 ++--- packages/core/src/shared/remoteSession.ts | 4 +- .../src/shared/sam/debugger/csharpSamDebug.ts | 4 +- .../treeview/resourceTreeDataProvider.ts | 18 ++++- .../shared/typescriptLambdaHandlerSearch.ts | 8 +-- packages/core/src/shared/ui/input.ts | 4 +- packages/core/src/shared/ui/inputPrompter.ts | 4 +- packages/core/src/shared/ui/picker.ts | 4 +- packages/core/src/shared/ui/pickerPrompter.ts | 4 +- .../src/shared/utilities/collectionUtils.ts | 4 +- .../core/src/shared/utilities/diffUtils.ts | 1 + .../src/shared/utilities/editorUtilities.ts | 8 +-- .../src/shared/utilities/streamUtilities.ts | 4 +- packages/core/src/shared/vscode/commands2.ts | 12 ++-- packages/core/src/shared/wizards/wizard.ts | 12 ++-- .../core/src/shared/wizards/wizardForm.ts | 8 +-- .../ssmDocument/commands/openDocumentItem.ts | 4 +- .../commands/updateDocumentVersion.ts | 4 +- .../ssmDocument/explorer/registryItemNode.ts | 4 +- .../core/src/stepFunctions/asl/aslServer.ts | 5 +- .../visualizeStateMachine/aslVisualization.ts | 4 +- .../controllers/chat/controller.test.ts | 8 +-- .../accessanalyzer/iamPolicyChecks.test.ts | 8 +-- .../explorer/apiGatewayNodes.test.ts | 4 +- .../commands/tailLogGroup.test.ts | 8 ++- .../explorer/cloudWatchLogsNode.test.ts | 8 ++- .../ec2/explorer/ec2ParentNode.test.ts | 5 +- .../src/test/awsService/ecr/utils.test.ts | 4 +- .../s3/commands/createFolder.test.ts | 4 +- .../s3/util/validateBucketName.test.ts | 8 +-- .../commands/transformByQ.test.ts | 8 +-- .../codewhispererChat/editor/codelens.test.ts | 1 + .../sharedCredentialsProvider.test.ts | 4 +- .../sso/ssoAccessTokenProvider.test.ts | 1 + .../core/src/test/credentials/utils.test.ts | 12 ++-- .../explorer/moreResourcesNode.test.ts | 8 +-- .../explorer/resourceTypeNode.test.ts | 16 +++-- .../model/schemaCodeGenUtils.test.ts | 4 +- .../commands/submitFeedbackListener.test.ts | 4 +- .../lambda/commands/listSamResources.test.ts | 1 + .../explorer/cloudFormationNodes.test.ts | 12 ++-- .../test/lambda/explorer/lambdaNodes.test.ts | 8 +-- .../lambda/models/samLambdaRuntime.test.ts | 16 ++--- .../test/lambda/models/samTemplates.test.ts | 4 +- .../test/lambda/vue/samInvokeBackend.test.ts | 8 +-- .../src/test/notifications/rendering.test.ts | 4 +- .../explorer/nodes/deployedNode.test.ts | 4 +- .../explorer/nodes/propertyNode.test.ts | 4 +- .../codelens/csharpCodeLensProvider.test.ts | 4 +- .../codelens/javaCodeLensProvider.test.ts | 4 +- .../codelens/pythonCodeLensProvider.test.ts | 8 +-- .../src/test/shared/crashMonitoring.test.ts | 10 ++- .../credentials/userCredentialsUtils.test.ts | 4 +- packages/core/src/test/shared/errors.test.ts | 4 +- packages/core/src/test/shared/fs/fs.test.ts | 10 +-- .../core/src/test/shared/globalState.test.ts | 8 +-- .../shared/logger/consoleLogLogger.test.ts | 4 +- .../test/shared/logger/toolkitLogger.test.ts | 12 ++-- .../test/shared/sam/cli/samCliInfo.test.ts | 4 +- .../cli/samCliValidationNotification.test.ts | 4 +- .../shared/sam/cli/samCliValidator.test.ts | 12 ++-- .../sam/cli/testSamCliProcessInvoker.ts | 4 +- .../core/src/test/shared/sam/deploy.test.ts | 4 +- .../core/src/test/shared/sam/samTestUtils.ts | 4 +- .../core/src/test/shared/sam/sync.test.ts | 8 +-- .../core/src/test/shared/sam/utils.test.ts | 8 +-- .../core/src/test/shared/settings.test.ts | 16 ++--- .../test/shared/telemetry/activation.test.ts | 4 +- .../src/test/shared/telemetry/util.test.ts | 8 +-- .../src/test/shared/ui/inputPrompter.test.ts | 4 +- .../src/test/shared/ui/pickerPrompter.test.ts | 4 +- .../shared/ui/prompters/regionSubmenu.test.ts | 4 +- .../shared/utilities/asyncCollection.test.ts | 8 ++- .../shared/utilities/textUtilities.test.ts | 8 +-- .../core/src/test/shared/vscode/env.test.ts | 4 +- .../core/src/test/shared/vscode/quickInput.ts | 16 +++-- .../core/src/test/shared/vscode/window.ts | 1 + .../shared/wizards/compositWizard.test.ts | 8 +-- .../src/test/shared/wizards/prompterTester.ts | 12 ++-- .../src/test/shared/wizards/wizard.test.ts | 24 +++++-- .../explorer/documentTypeNode.test.ts | 4 +- .../explorer/registryItemNode.test.ts | 4 +- .../explorer/ssmDocumentNode.test.ts | 4 +- .../util/validateDocumentName.test.ts | 8 +-- .../explorer/stepFunctionNodes.test.ts | 4 +- packages/core/src/test/testRunner.ts | 8 ++- packages/core/src/test/testUtil.ts | 6 +- .../src/testE2E/codecatalyst/client.test.ts | 4 +- .../appBuilder/sidebar/appBuilderNode.test.ts | 4 +- .../testInteg/appBuilder/walkthrough.test.ts | 4 +- packages/core/src/testInteg/sam.test.ts | 4 +- .../shared/utilities/workspaceUtils.test.ts | 4 +- packages/core/src/testLint/gitSecrets.test.ts | 8 +-- .../threatComposer/threatComposerEditor.ts | 4 +- packages/core/src/webviews/client.ts | 4 +- packages/core/src/webviews/mixins/saveData.ts | 8 +-- packages/toolkit/src/api.ts | 1 + .../lib/rules/no-incorrect-once-usage.ts | 13 ++-- .../rules/no-string-exec-for-child-process.ts | 4 +- 180 files changed, 777 insertions(+), 616 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index b3e5e39dc9f..c7fc4cd9c13 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -158,6 +158,8 @@ module.exports = { 'unicorn/prefer-reflect-apply': 'error', 'unicorn/prefer-string-trim-start-end': 'error', 'unicorn/prefer-type-error': 'error', + // Discourage `.forEach` because it can lead to accidental, incorrect use of async callbacks. + 'unicorn/no-array-for-each': 'error', 'security-node/detect-child-process': 'error', 'header/header': [ diff --git a/packages/amazonq/src/inlineChat/controller/inlineChatController.ts b/packages/amazonq/src/inlineChat/controller/inlineChatController.ts index ce0df6a0878..4ffa6e1e1de 100644 --- a/packages/amazonq/src/inlineChat/controller/inlineChatController.ts +++ b/packages/amazonq/src/inlineChat/controller/inlineChatController.ts @@ -156,7 +156,9 @@ export class InlineChatController { } private async reset() { - this.listeners.forEach((listener) => listener.dispose()) + for (const listener of this.listeners) { + listener.dispose() + } this.listeners = [] this.task = undefined diff --git a/packages/amazonq/src/inlineChat/output/computeDiff.ts b/packages/amazonq/src/inlineChat/output/computeDiff.ts index 9b599b2eff3..a17a7914cf6 100644 --- a/packages/amazonq/src/inlineChat/output/computeDiff.ts +++ b/packages/amazonq/src/inlineChat/output/computeDiff.ts @@ -2,7 +2,7 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ -import { type LinesOptions, diffLines, Change } from 'diff' +import { type LinesOptions, diffLines } from 'diff' import * as vscode from 'vscode' import { InlineTask, TextDiff } from '../controller/inlineTask' @@ -24,8 +24,7 @@ export function computeDiff(response: string, inlineTask: InlineTask, isPartialD const textDiff: TextDiff[] = [] let startLine = selectedRange.start.line - - diffs.forEach((part: Change) => { + for (const part of diffs) { const count = part.count ?? 0 if (part.removed) { if (part.value !== '\n') { @@ -49,7 +48,7 @@ export function computeDiff(response: string, inlineTask: InlineTask, isPartialD } } startLine += count - }) + } inlineTask.diff = textDiff return textDiff } diff --git a/packages/amazonq/test/e2e/amazonq/explore.test.ts b/packages/amazonq/test/e2e/amazonq/explore.test.ts index 6833849617d..970d93d00bb 100644 --- a/packages/amazonq/test/e2e/amazonq/explore.test.ts +++ b/packages/amazonq/test/e2e/amazonq/explore.test.ts @@ -36,10 +36,10 @@ describe('Amazon Q Explore page', function () { it('should have correct button IDs', async () => { const features = ['featuredev', 'testgen', 'doc', 'review', 'gumby'] - features.forEach((feature, index) => { + for (const [index, feature] of features.entries()) { const buttons = (tab.getStore().chatItems ?? [])[index].buttons ?? [] assert.deepStrictEqual(buttons[0].id, `user-guide-${feature}`) assert.deepStrictEqual(buttons[1].id, `quick-start-${feature}`) - }) + } }) }) diff --git a/packages/amazonq/test/e2e/amazonq/welcome.test.ts b/packages/amazonq/test/e2e/amazonq/welcome.test.ts index 1e15d13381a..59ba7e728f2 100644 --- a/packages/amazonq/test/e2e/amazonq/welcome.test.ts +++ b/packages/amazonq/test/e2e/amazonq/welcome.test.ts @@ -51,11 +51,11 @@ describe('Amazon Q Welcome page', function () { framework.createTab() let welcomeCount = 0 - framework.getTabs().forEach((tab) => { + for (const tab of framework.getTabs()) { if (tab.getStore().tabTitle === 'Welcome to Q') { welcomeCount++ } - }) + } // 3 welcome tabs assert.deepStrictEqual(welcomeCount, 3) diff --git a/packages/amazonq/test/unit/codewhisperer/service/keyStrokeHandler.test.ts b/packages/amazonq/test/unit/codewhisperer/service/keyStrokeHandler.test.ts index 075dc769b0e..4b6a5291f22 100644 --- a/packages/amazonq/test/unit/codewhisperer/service/keyStrokeHandler.test.ts +++ b/packages/amazonq/test/unit/codewhisperer/service/keyStrokeHandler.test.ts @@ -212,7 +212,7 @@ describe('keyStrokeHandler', function () { ['function suggestedByIntelliSense():', DocumentChangedSource.Unknown], ] - cases.forEach((tuple) => { + for (const tuple of cases) { const input = tuple[0] const expected = tuple[1] it(`test input ${input} should return ${expected}`, function () { @@ -221,7 +221,7 @@ describe('keyStrokeHandler', function () { ).checkChangeSource() assert.strictEqual(actual, expected) }) - }) + } function createFakeDocumentChangeEvent(str: string): ReadonlyArray { return [ diff --git a/packages/amazonq/test/unit/codewhisperer/util/crossFileContextUtil.test.ts b/packages/amazonq/test/unit/codewhisperer/util/crossFileContextUtil.test.ts index 75825232d7c..8f54a43bf52 100644 --- a/packages/amazonq/test/unit/codewhisperer/util/crossFileContextUtil.test.ts +++ b/packages/amazonq/test/unit/codewhisperer/util/crossFileContextUtil.test.ts @@ -251,11 +251,11 @@ describe('crossFileContextUtil', function () { const actual = await crossFile.getCrossFileCandidates(editor) assert.ok(actual.length === 5) - actual.forEach((actualFile, index) => { + for (const [index, actualFile] of actual.entries()) { const expectedFile = path.join(tempFolder, expectedFilePaths[index]) assert.strictEqual(normalize(expectedFile), normalize(actualFile)) assert.ok(areEqual(tempFolder, actualFile, expectedFile)) - }) + } }) }) @@ -274,7 +274,7 @@ describe('crossFileContextUtil', function () { await closeAllEditors() }) - fileExtLists.forEach((fileExt) => { + for (const fileExt of fileExtLists) { it('should be empty if userGroup is control', async function () { const editor = await toTextEditor('content-1', `file-1.${fileExt}`, tempFolder) await toTextEditor('content-2', `file-2.${fileExt}`, tempFolder, { preview: false }) @@ -287,7 +287,7 @@ describe('crossFileContextUtil', function () { assert.ok(actual && actual.supplementalContextItems.length === 0) }) - }) + } }) describe.skip('partial support - crossfile group', function () { @@ -305,7 +305,7 @@ describe('crossFileContextUtil', function () { await closeAllEditors() }) - fileExtLists.forEach((fileExt) => { + for (const fileExt of fileExtLists) { it('should be non empty if usergroup is Crossfile', async function () { const editor = await toTextEditor('content-1', `file-1.${fileExt}`, tempFolder) await toTextEditor('content-2', `file-2.${fileExt}`, tempFolder, { preview: false }) @@ -318,7 +318,7 @@ describe('crossFileContextUtil', function () { assert.ok(actual && actual.supplementalContextItems.length !== 0) }) - }) + } }) describe('full support', function () { @@ -337,7 +337,7 @@ describe('crossFileContextUtil', function () { await closeAllEditors() }) - fileExtLists.forEach((fileExt) => { + for (const fileExt of fileExtLists) { it(`supplemental context for file ${fileExt} should be non empty`, async function () { sinon.stub(FeatureConfigProvider.instance, 'getProjectContextGroup').returns('control') sinon @@ -361,7 +361,7 @@ describe('crossFileContextUtil', function () { assert.ok(actual && actual.supplementalContextItems.length !== 0) }) - }) + } }) describe('splitFileToChunks', function () { diff --git a/packages/amazonq/test/unit/codewhisperer/util/editorContext.test.ts b/packages/amazonq/test/unit/codewhisperer/util/editorContext.test.ts index 22be4199375..d5085e4db0c 100644 --- a/packages/amazonq/test/unit/codewhisperer/util/editorContext.test.ts +++ b/packages/amazonq/test/unit/codewhisperer/util/editorContext.test.ts @@ -95,12 +95,12 @@ describe('editorContext', function () { ['c', 'c'], ]) - languageToExtension.forEach((extension, language) => { + for (const [language, extension] of languageToExtension.entries()) { const editor = createMockTextEditor('', 'test.ipynb', language, 1, 17) const actual = EditorContext.getFileRelativePath(editor) const expected = 'test.' + extension assert.strictEqual(actual, expected) - }) + } }) it('Should return relative path', async function () { diff --git a/packages/amazonq/test/unit/codewhisperer/util/runtimeLanguageContext.test.ts b/packages/amazonq/test/unit/codewhisperer/util/runtimeLanguageContext.test.ts index 653505d6cf9..9cf61920861 100644 --- a/packages/amazonq/test/unit/codewhisperer/util/runtimeLanguageContext.test.ts +++ b/packages/amazonq/test/unit/codewhisperer/util/runtimeLanguageContext.test.ts @@ -52,7 +52,7 @@ describe('runtimeLanguageContext', function () { await resetCodeWhispererGlobalVariables() }) - cases.forEach((tuple) => { + for (const tuple of cases) { const languageId = tuple[0] const expected = tuple[1] @@ -60,7 +60,7 @@ describe('runtimeLanguageContext', function () { const actual = languageContext.isLanguageSupported(languageId) assert.strictEqual(actual, expected) }) - }) + } describe('test isLanguageSupported with document as the argument', function () { const cases: [string, boolean][] = [ @@ -105,7 +105,7 @@ describe('runtimeLanguageContext', function () { ['helloFoo.foo', false], ] - cases.forEach((tuple) => { + for (const tuple of cases) { const fileName = tuple[0] const expected = tuple[1] @@ -114,7 +114,7 @@ describe('runtimeLanguageContext', function () { const actual = languageContext.isLanguageSupported(doc) assert.strictEqual(actual, expected) }) - }) + } }) }) @@ -148,14 +148,14 @@ describe('runtimeLanguageContext', function () { [undefined, 'plaintext'], ] - cases.forEach((tuple) => { + for (const tuple of cases) { const vscLanguageId = tuple[0] const expectedCwsprLanguageId = tuple[1] it(`given vscLanguage ${vscLanguageId} should return ${expectedCwsprLanguageId}`, function () { const result = runtimeLanguageContext.getLanguageContext(vscLanguageId) assert.strictEqual(result.language as string, expectedCwsprLanguageId) }) - }) + } }) describe('normalizeLanguage', function () { diff --git a/packages/amazonq/test/unit/codewhisperer/util/securityScanLanguageContext.test.ts b/packages/amazonq/test/unit/codewhisperer/util/securityScanLanguageContext.test.ts index cb0a51fdad8..e1d2cf91189 100644 --- a/packages/amazonq/test/unit/codewhisperer/util/securityScanLanguageContext.test.ts +++ b/packages/amazonq/test/unit/codewhisperer/util/securityScanLanguageContext.test.ts @@ -51,7 +51,7 @@ describe('securityScanLanguageContext', function () { await resetCodeWhispererGlobalVariables() }) - cases.forEach((tuple) => { + for (const tuple of cases) { const languageId = tuple[0] const expected = tuple[1] @@ -59,7 +59,7 @@ describe('securityScanLanguageContext', function () { const actual = languageContext.isLanguageSupported(languageId) assert.strictEqual(actual, expected) }) - }) + } }) describe('normalizeLanguage', function () { diff --git a/packages/amazonq/test/web/testRunner.ts b/packages/amazonq/test/web/testRunner.ts index a2c8f8e90cc..1d0726be98b 100644 --- a/packages/amazonq/test/web/testRunner.ts +++ b/packages/amazonq/test/web/testRunner.ts @@ -35,6 +35,7 @@ function setupMocha() { function gatherTestFiles() { // Bundles all files in the current directory matching `*.test` + // eslint-disable-next-line unicorn/no-array-for-each const importAll = (r: __WebpackModuleApi.RequireContext) => r.keys().forEach(r) importAll(require.context('.', true, /\.test$/)) } diff --git a/packages/core/scripts/build/generateServiceClient.ts b/packages/core/scripts/build/generateServiceClient.ts index 4c6fb730b19..7ef217be21b 100644 --- a/packages/core/scripts/build/generateServiceClient.ts +++ b/packages/core/scripts/build/generateServiceClient.ts @@ -106,7 +106,7 @@ async function insertServiceClientsIntoJsSdk( jsSdkPath: string, serviceClientDefinitions: ServiceClientDefinition[] ): Promise { - serviceClientDefinitions.forEach((serviceClientDefinition) => { + for (const serviceClientDefinition of serviceClientDefinitions) { const apiVersion = getApiVersion(serviceClientDefinition.serviceJsonPath) // Copy the Service Json into the JS SDK for generation @@ -116,7 +116,7 @@ async function insertServiceClientsIntoJsSdk( `${serviceClientDefinition.serviceName.toLowerCase()}-${apiVersion}.normal.json` ) nodefs.copyFileSync(serviceClientDefinition.serviceJsonPath, jsSdkServiceJsonPath) - }) + } const apiMetadataPath = path.join(jsSdkPath, 'apis', 'metadata.json') await patchServicesIntoApiMetadata( @@ -151,9 +151,9 @@ async function patchServicesIntoApiMetadata(apiMetadataPath: string, serviceName const apiMetadataJson = nodefs.readFileSync(apiMetadataPath).toString() const apiMetadata = JSON.parse(apiMetadataJson) as ApiMetadata - serviceNames.forEach((serviceName) => { + for (const serviceName of serviceNames) { apiMetadata[serviceName.toLowerCase()] = { name: serviceName } - }) + } nodefs.writeFileSync(apiMetadataPath, JSON.stringify(apiMetadata, undefined, 4)) } diff --git a/packages/core/scripts/lint/testLint.ts b/packages/core/scripts/lint/testLint.ts index 43bafb6ae00..d215e57f675 100644 --- a/packages/core/scripts/lint/testLint.ts +++ b/packages/core/scripts/lint/testLint.ts @@ -12,9 +12,9 @@ void (async () => { const mocha = new Mocha() const testFiles = await glob('dist/src/testLint/**/*.test.js') - testFiles.forEach((file) => { + for (const file of testFiles) { mocha.addFile(file) - }) + } mocha.run((failures) => { const exitCode = failures ? 1 : 0 diff --git a/packages/core/src/amazonq/commons/controllers/contentController.ts b/packages/core/src/amazonq/commons/controllers/contentController.ts index 0af3b317025..cdf19fe86b4 100644 --- a/packages/core/src/amazonq/commons/controllers/contentController.ts +++ b/packages/core/src/amazonq/commons/controllers/contentController.ts @@ -50,13 +50,13 @@ export class EditorContentController { indent = ' '.repeat(indent.length - indent.trimStart().length) } let textWithIndent = '' - text.split('\n').forEach((line, index) => { + for (const [index, line] of text.split('\n').entries()) { if (index === 0) { textWithIndent += line } else { textWithIndent += '\n' + indent + line } - }) + } editor .edit((editBuilder) => { editBuilder.insert(cursorStart, textWithIndent) diff --git a/packages/core/src/amazonq/commons/diff.ts b/packages/core/src/amazonq/commons/diff.ts index beb45d88096..ed6642b9192 100644 --- a/packages/core/src/amazonq/commons/diff.ts +++ b/packages/core/src/amazonq/commons/diff.ts @@ -46,7 +46,7 @@ export async function computeDiff(leftPath: string, rightPath: string, tabId: st let charsRemoved = 0 let linesAdded = 0 let linesRemoved = 0 - changes.forEach((change) => { + for (const change of changes) { const lines = change.value.split('\n') const charCount = lines.reduce((sum, line) => sum + line.length, 0) const lineCount = change.count ?? lines.length - 1 // ignoring end-of-file empty line @@ -57,6 +57,6 @@ export async function computeDiff(leftPath: string, rightPath: string, tabId: st charsRemoved += charCount linesRemoved += lineCount } - }) + } return { changes, charsAdded, linesAdded, charsRemoved, linesRemoved } } diff --git a/packages/core/src/amazonq/lsp/lspController.ts b/packages/core/src/amazonq/lsp/lspController.ts index bb5cc88f5a2..d3f8960d1fc 100644 --- a/packages/core/src/amazonq/lsp/lspController.ts +++ b/packages/core/src/amazonq/lsp/lspController.ts @@ -280,23 +280,25 @@ export class LspController { async query(s: string): Promise { const chunks: Chunk[] | undefined = await LspClient.instance.queryVectorIndex(s) const resp: RelevantTextDocument[] = [] - chunks?.forEach((chunk) => { - const text = chunk.context ? chunk.context : chunk.content - if (chunk.programmingLanguage && chunk.programmingLanguage !== 'unknown') { - resp.push({ - text: text, - relativeFilePath: chunk.relativePath ? chunk.relativePath : path.basename(chunk.filePath), - programmingLanguage: { - languageName: chunk.programmingLanguage, - }, - }) - } else { - resp.push({ - text: text, - relativeFilePath: chunk.relativePath ? chunk.relativePath : path.basename(chunk.filePath), - }) + if (chunks) { + for (const chunk of chunks) { + const text = chunk.context ? chunk.context : chunk.content + if (chunk.programmingLanguage && chunk.programmingLanguage !== 'unknown') { + resp.push({ + text: text, + relativeFilePath: chunk.relativePath ? chunk.relativePath : path.basename(chunk.filePath), + programmingLanguage: { + languageName: chunk.programmingLanguage, + }, + }) + } else { + resp.push({ + text: text, + relativeFilePath: chunk.relativePath ? chunk.relativePath : path.basename(chunk.filePath), + }) + } } - }) + } return resp } diff --git a/packages/core/src/amazonq/webview/ui/main.ts b/packages/core/src/amazonq/webview/ui/main.ts index 78ae17aef95..d056871bda2 100644 --- a/packages/core/src/amazonq/webview/ui/main.ts +++ b/packages/core/src/amazonq/webview/ui/main.ts @@ -663,10 +663,10 @@ export const createMynahUI = ( ideApi.postMessage(createClickTelemetry('amazonq-disclaimer-acknowledge-button')) // remove all disclaimer cards from all tabs - Object.keys(mynahUI.getAllTabs()).forEach((storeTabKey) => { + for (const storeTabKey of Object.keys(mynahUI.getAllTabs())) { // eslint-disable-next-line unicorn/no-null mynahUI.updateStore(storeTabKey, { promptInputStickyCard: null }) - }) + } return } case 'quick-start': { diff --git a/packages/core/src/amazonq/webview/ui/quickActions/handler.ts b/packages/core/src/amazonq/webview/ui/quickActions/handler.ts index 78ef3d0e7ec..221fb4e53b6 100644 --- a/packages/core/src/amazonq/webview/ui/quickActions/handler.ts +++ b/packages/core/src/amazonq/webview/ui/quickActions/handler.ts @@ -109,11 +109,11 @@ export class QuickActionHandler { } let scanTabId: string | undefined = undefined - this.tabsStorage.getTabs().forEach((tab) => { + for (const tab of this.tabsStorage.getTabs()) { if (tab.type === 'review') { scanTabId = tab.id } - }) + } if (scanTabId !== undefined) { this.mynahUI.selectTab(scanTabId, eventId || '') @@ -292,11 +292,11 @@ export class QuickActionHandler { let gumbyTabId: string | undefined = undefined - this.tabsStorage.getTabs().forEach((tab) => { + for (const tab of this.tabsStorage.getTabs()) { if (tab.type === 'gumby') { gumbyTabId = tab.id } - }) + } if (gumbyTabId !== undefined) { this.mynahUI.selectTab(gumbyTabId, eventId || '') diff --git a/packages/core/src/amazonqDoc/app.ts b/packages/core/src/amazonqDoc/app.ts index 4aba1b9e9bc..1847da2e168 100644 --- a/packages/core/src/amazonqDoc/app.ts +++ b/packages/core/src/amazonqDoc/app.ts @@ -89,7 +89,9 @@ export function init(appContext: AmazonQAppInitContext) { authenticatingSessionIDs = authenticatingSessions.map((session: any) => session.tabID) // We've already authenticated these sessions - authenticatingSessions.forEach((session: any) => (session.isAuthenticating = false)) + for (const session of authenticatingSessions) { + session.isAuthenticating = false + } } messenger.sendAuthenticationUpdate(authenticated, authenticatingSessionIDs) diff --git a/packages/core/src/amazonqFeatureDev/app.ts b/packages/core/src/amazonqFeatureDev/app.ts index 99164f417be..a72851e8ac7 100644 --- a/packages/core/src/amazonqFeatureDev/app.ts +++ b/packages/core/src/amazonqFeatureDev/app.ts @@ -95,7 +95,9 @@ export function init(appContext: AmazonQAppInitContext) { authenticatingSessionIDs = authenticatingSessions.map((session) => session.tabID) // We've already authenticated these sessions - authenticatingSessions.forEach((session) => (session.isAuthenticating = false)) + for (const session of authenticatingSessions) { + session.isAuthenticating = false + } } messenger.sendAuthenticationUpdate(authenticated, authenticatingSessionIDs) diff --git a/packages/core/src/amazonqGumby/chat/controller/messenger/messenger.ts b/packages/core/src/amazonqGumby/chat/controller/messenger/messenger.ts index 3d947b8caff..5ee48f0e824 100644 --- a/packages/core/src/amazonqGumby/chat/controller/messenger/messenger.ts +++ b/packages/core/src/amazonqGumby/chat/controller/messenger/messenger.ts @@ -197,13 +197,13 @@ export class Messenger { const projectFormOptions: { value: any; label: string }[] = [] const detectedJavaVersions = new Array() - projects.forEach((candidateProject) => { + for (const candidateProject of projects) { projectFormOptions.push({ value: candidateProject.path, label: candidateProject.name, }) detectedJavaVersions.push(candidateProject.JDKVersion) - }) + } const formItems: ChatItemFormItem[] = [] formItems.push({ @@ -279,12 +279,12 @@ export class Messenger { public async sendSQLConversionProjectPrompt(projects: TransformationCandidateProject[], tabID: string) { const projectFormOptions: { value: any; label: string }[] = [] - projects.forEach((candidateProject) => { + for (const candidateProject of projects) { projectFormOptions.push({ value: candidateProject.path, label: candidateProject.name, }) - }) + } const formItems: ChatItemFormItem[] = [] formItems.push({ @@ -661,12 +661,12 @@ ${codeSnippet} const valueFormOptions: { value: any; label: string }[] = [] - versions.allVersions.forEach((version) => { + for (const version of versions.allVersions) { valueFormOptions.push({ value: version, label: version, }) - }) + } const formItems: ChatItemFormItem[] = [] formItems.push({ diff --git a/packages/core/src/amazonqTest/chat/controller/controller.ts b/packages/core/src/amazonqTest/chat/controller/controller.ts index 79d4d117057..8c99e7a2dcb 100644 --- a/packages/core/src/amazonqTest/chat/controller/controller.ts +++ b/packages/core/src/amazonqTest/chat/controller/controller.ts @@ -667,7 +667,7 @@ export class TestController { const fileName = path.basename(session.generatedFilePath) const time = new Date().toLocaleString() // TODO: this is duplicated in basicCommands.ts for scan (codewhisperer). Fix this later. - session.references.forEach((reference) => { + for (const reference of session.references) { getLogger().debug('Processing reference: %O', reference) // Log values for debugging getLogger().debug('updatedContent: %s', updatedContent) @@ -702,7 +702,7 @@ export class TestController { '
' getLogger().debug('Adding reference log: %s', referenceLog) ReferenceLogViewProvider.instance.addReferenceLog(referenceLog) - }) + } // TODO: see if there's a better way to check if active file is a diff if (vscode.window.tabGroups.activeTabGroup.activeTab?.label.includes(amazonQTabSuffix)) { @@ -1241,7 +1241,7 @@ export class TestController { groupName ) if (session.listOfTestGenerationJobId.length && groupName) { - session.listOfTestGenerationJobId.forEach((id) => { + for (const id of session.listOfTestGenerationJobId) { if (id === session.acceptedJobId) { TelemetryHelper.instance.sendTestGenerationEvent( groupName, @@ -1267,7 +1267,7 @@ export class TestController { 0 ) } - }) + } } session.listOfTestGenerationJobId = [] session.testGenerationJobGroupName = undefined diff --git a/packages/core/src/applicationcomposer/composerWebview.ts b/packages/core/src/applicationcomposer/composerWebview.ts index 94493091c3a..f43775df3c7 100644 --- a/packages/core/src/applicationcomposer/composerWebview.ts +++ b/packages/core/src/applicationcomposer/composerWebview.ts @@ -104,9 +104,9 @@ export class ApplicationComposer { } this.isPanelDisposed = true this.onVisualizationDisposeEmitter.fire() - this.disposables.forEach((disposable) => { + for (const disposable of this.disposables) { disposable.dispose() - }) + } this.onVisualizationDisposeEmitter.dispose() } diff --git a/packages/core/src/auth/credentials/sharedCredentials.ts b/packages/core/src/auth/credentials/sharedCredentials.ts index 1b7ea038653..b78c0d53251 100644 --- a/packages/core/src/auth/credentials/sharedCredentials.ts +++ b/packages/core/src/auth/credentials/sharedCredentials.ts @@ -176,7 +176,7 @@ export function mergeAndValidateSections(data: BaseSection[]): ParseResult { export function parseIni(iniData: string, source: vscode.Uri): BaseSection[] { const sections = [] as BaseSection[] const lines = iniData.split(/\r?\n/).map((l) => l.split(/(^|\s)[;#]/)[0]) // remove comments - lines.forEach((line, lineNumber) => { + for (const [lineNumber, line] of lines.entries()) { const section = line.match(/^\s*\[([^\[\]]+)]\s*$/) const currentSection: BaseSection | undefined = sections[sections.length - 1] if (section) { @@ -195,7 +195,7 @@ export function parseIni(iniData: string, source: vscode.Uri): BaseSection[] { }) } } - }) + } return sections } diff --git a/packages/core/src/auth/credentials/validation.ts b/packages/core/src/auth/credentials/validation.ts index e1bee0b8c08..a82eb26a36a 100644 --- a/packages/core/src/auth/credentials/validation.ts +++ b/packages/core/src/auth/credentials/validation.ts @@ -36,12 +36,12 @@ export function getCredentialsErrors( validateFunc: GetCredentialError = getCredentialError ): CredentialsErrors | undefined { const errors: CredentialsData = {} - Object.entries(data).forEach(([key, value]) => { + for (const [key, value] of Object.entries(data)) { if (!isCredentialsKey(key)) { - return + continue } errors[key] = validateFunc(key, value) - }) + } const hasErrors = Object.values(errors).some(Boolean) if (!hasErrors) { diff --git a/packages/core/src/auth/sso/cache.ts b/packages/core/src/auth/sso/cache.ts index a9cdfa43ce0..7d43c07da35 100644 --- a/packages/core/src/auth/sso/cache.ts +++ b/packages/core/src/auth/sso/cache.ts @@ -149,7 +149,9 @@ function getRegistrationCacheFile(ssoCacheDir: string, key: RegistrationKey): st const hash = (startUrl: string, scopes: string[]) => { const shasum = crypto.createHash('sha256') shasum.update(startUrl) - scopes.forEach((s) => shasum.update(s)) + for (const s of scopes) { + shasum.update(s) + } return shasum.digest('hex') } diff --git a/packages/core/src/auth/sso/server.ts b/packages/core/src/auth/sso/server.ts index 7c95b5ce016..cf25c1456d5 100644 --- a/packages/core/src/auth/sso/server.ts +++ b/packages/core/src/auth/sso/server.ts @@ -163,9 +163,9 @@ export class AuthSSOServer { getLogger().debug('AuthSSOServer: Attempting to close server.') - this.connections.forEach((connection) => { + for (const connection of this.connections) { connection.destroy() - }) + } this.server.close((err) => { if (err) { diff --git a/packages/core/src/awsService/accessanalyzer/vue/iamPolicyChecks.ts b/packages/core/src/awsService/accessanalyzer/vue/iamPolicyChecks.ts index da9c0738819..f6cc5e8cf18 100644 --- a/packages/core/src/awsService/accessanalyzer/vue/iamPolicyChecks.ts +++ b/packages/core/src/awsService/accessanalyzer/vue/iamPolicyChecks.ts @@ -203,6 +203,7 @@ export class IamPolicyChecksWebview extends VueWebview { span.record({ findingsCount: data.findings.length, }) + // eslint-disable-next-line unicorn/no-array-for-each data.findings.forEach((finding: AccessAnalyzer.ValidatePolicyFinding) => { const message = `${finding.findingType}: ${finding.issueCode} - ${finding.findingDetails} Learn more: ${finding.learnMoreLink}` if ((finding.findingType as ValidatePolicyFindingType) === 'ERROR') { @@ -616,10 +617,12 @@ export class IamPolicyChecksWebview extends VueWebview { getResultCssColor('Success'), ]) } else { + // eslint-disable-next-line unicorn/no-array-for-each jsonOutput.BlockingFindings.forEach((finding: any) => { this.pushValidatePolicyDiagnostic(diagnostics, finding, true) findingsCount++ }) + // eslint-disable-next-line unicorn/no-array-for-each jsonOutput.NonBlockingFindings.forEach((finding: any) => { this.pushValidatePolicyDiagnostic(diagnostics, finding, false) findingsCount++ @@ -682,11 +685,13 @@ export class IamPolicyChecksWebview extends VueWebview { getResultCssColor('Success'), ]) } else { + // eslint-disable-next-line unicorn/no-array-for-each jsonOutput.BlockingFindings.forEach((finding: any) => { this.pushCustomCheckDiagnostic(diagnostics, finding, true) errorMessage = getCheckNoNewAccessErrorMessage(finding) findingsCount++ }) + // eslint-disable-next-line unicorn/no-array-for-each jsonOutput.NonBlockingFindings.forEach((finding: any) => { this.pushCustomCheckDiagnostic(diagnostics, finding, false) findingsCount++ @@ -724,6 +729,7 @@ export class IamPolicyChecksWebview extends VueWebview { : finding.message const message = `${finding.findingType}: ${findingMessage} - Resource name: ${finding.resourceName}, Policy name: ${finding.policyName}` if (finding.details.reasons) { + // eslint-disable-next-line unicorn/no-array-for-each finding.details.reasons.forEach((reason: any) => { diagnostics.push( new vscode.Diagnostic( diff --git a/packages/core/src/awsService/appBuilder/explorer/detectSamProjects.ts b/packages/core/src/awsService/appBuilder/explorer/detectSamProjects.ts index cb179d94f0d..f17bec9213a 100644 --- a/packages/core/src/awsService/appBuilder/explorer/detectSamProjects.ts +++ b/packages/core/src/awsService/appBuilder/explorer/detectSamProjects.ts @@ -21,7 +21,9 @@ export async function detectSamProjects(): Promise { [] ) - projects.forEach((p) => results.set(p.samTemplateUri.toString(), p)) + for (const p of projects) { + results.set(p.samTemplateUri.toString(), p) + } return Array.from(results.values()) } diff --git a/packages/core/src/awsService/appBuilder/wizards/templateParametersWizard.ts b/packages/core/src/awsService/appBuilder/wizards/templateParametersWizard.ts index 75c80c4eda9..9641562d6f0 100644 --- a/packages/core/src/awsService/appBuilder/wizards/templateParametersWizard.ts +++ b/packages/core/src/awsService/appBuilder/wizards/templateParametersWizard.ts @@ -35,7 +35,7 @@ export class TemplateParametersWizard extends Wizard { this.preloadedTemplate = await CloudFormation.load(this.template.fsPath) const samTemplateNames = new Set(this.samTemplateParameters?.keys() ?? []) - samTemplateNames.forEach((name) => { + for (const name of samTemplateNames) { if (this.preloadedTemplate) { const defaultValue = this.preloadedTemplate.Parameters ? (this.preloadedTemplate.Parameters[name]?.Default as string) @@ -47,7 +47,7 @@ export class TemplateParametersWizard extends Wizard { }) ) } - }) + } return this } diff --git a/packages/core/src/awsService/apprunner/activation.ts b/packages/core/src/awsService/apprunner/activation.ts index 14cfb167f75..5b907d2b968 100644 --- a/packages/core/src/awsService/apprunner/activation.ts +++ b/packages/core/src/awsService/apprunner/activation.ts @@ -79,7 +79,7 @@ commandMap.set(['aws.apprunner.deleteService', deleteServiceFailed], deleteServi * Activates App Runner */ export async function activate(context: ExtContext): Promise { - commandMap.forEach((command, tuple) => { + for (const [tuple, command] of commandMap.entries()) { context.extensionContext.subscriptions.push( Commands.register(tuple[0], async (...args: any) => { try { @@ -90,5 +90,5 @@ export async function activate(context: ExtContext): Promise { } }) ) - }) + } } diff --git a/packages/core/src/awsService/apprunner/explorer/apprunnerNode.ts b/packages/core/src/awsService/apprunner/explorer/apprunnerNode.ts index 889f94a51cc..a2eabbe6d2d 100644 --- a/packages/core/src/awsService/apprunner/explorer/apprunnerNode.ts +++ b/packages/core/src/awsService/apprunner/explorer/apprunnerNode.ts @@ -58,6 +58,7 @@ export class AppRunnerNode extends AWSTreeNodeBase { while (true) { const next = await iterator.next() + // eslint-disable-next-line unicorn/no-array-for-each next.value.ServiceSummaryList.forEach((summary: AppRunner.Service) => services.push(summary)) if (next.done) { @@ -87,6 +88,7 @@ export class AppRunnerNode extends AWSTreeNodeBase { }) ) + // eslint-disable-next-line unicorn/no-array-for-each deletedNodeArns.forEach(this.deleteNode.bind(this)) } diff --git a/packages/core/src/awsService/cdk/explorer/detectCdkProjects.ts b/packages/core/src/awsService/cdk/explorer/detectCdkProjects.ts index 9a3fd363d1a..55f47f5938f 100644 --- a/packages/core/src/awsService/cdk/explorer/detectCdkProjects.ts +++ b/packages/core/src/awsService/cdk/explorer/detectCdkProjects.ts @@ -21,7 +21,9 @@ export async function detectCdkProjects( [] ) - projects.forEach((p) => results.set(p.cdkJsonUri.toString(), p)) + for (const p of projects) { + results.set(p.cdkJsonUri.toString(), p) + } return Array.from(results.values()) } diff --git a/packages/core/src/awsService/cloudWatchLogs/commands/tailLogGroup.ts b/packages/core/src/awsService/cloudWatchLogs/commands/tailLogGroup.ts index 4aa1feb272a..c584a6147ce 100644 --- a/packages/core/src/awsService/cloudWatchLogs/commands/tailLogGroup.ts +++ b/packages/core/src/awsService/cloudWatchLogs/commands/tailLogGroup.ts @@ -77,7 +77,9 @@ export async function tailLogGroup( }) await handleSessionStream(stream, document, session) } finally { - disposables.forEach((disposable) => disposable.dispose()) + for (const disposable of disposables) { + disposable.dispose() + } } }) } @@ -138,6 +140,7 @@ async function handleSessionStream( // amount of new lines can push bottom of file out of view before scrolling. const editorsToScroll = getTextEditorsToScroll(document) await updateTextDocumentWithNewLogEvents(formattedLogEvents, document, session.maxLines) + // eslint-disable-next-line unicorn/no-array-for-each editorsToScroll.forEach(scrollTextEditorToBottom) } session.eventRate = eventRate(event.sessionUpdate) @@ -200,9 +203,10 @@ async function updateTextDocumentWithNewLogEvents( maxLines: number ) { const edit = new vscode.WorkspaceEdit() - formattedLogEvents.forEach((formattedLogEvent) => + for (const formattedLogEvent of formattedLogEvents) { edit.insert(document.uri, new vscode.Position(document.lineCount, 0), formattedLogEvent) - ) + } + if (document.lineCount + formattedLogEvents.length > maxLines) { trimOldestLines(formattedLogEvents.length, maxLines, document, edit) } @@ -270,14 +274,15 @@ function closeSessionWhenAllEditorsClosed( function isLiveTailSessionOpenInAnyTab(liveTailSession: LiveTailSession) { let isOpen = false + // eslint-disable-next-line unicorn/no-array-for-each vscode.window.tabGroups.all.forEach(async (tabGroup) => { - tabGroup.tabs.forEach((tab) => { + for (const tab of tabGroup.tabs) { if (tab.input instanceof vscode.TabInputText) { if (liveTailSession.uri.toString() === tab.input.uri.toString()) { isOpen = true } } - }) + } }) return isOpen } diff --git a/packages/core/src/awsService/cloudWatchLogs/document/logStreamsCodeLensProvider.ts b/packages/core/src/awsService/cloudWatchLogs/document/logStreamsCodeLensProvider.ts index 9870ff009d2..9c6409d7318 100644 --- a/packages/core/src/awsService/cloudWatchLogs/document/logStreamsCodeLensProvider.ts +++ b/packages/core/src/awsService/cloudWatchLogs/document/logStreamsCodeLensProvider.ts @@ -50,9 +50,9 @@ export class LogStreamCodeLensProvider implements vscode.CodeLensProvider { const linesToGenerateCodeLens = await this.getStartingLineOfEachStreamId(document) // Create a code lens at the start of each Log Stream in the document - linesToGenerateCodeLens.forEach((idWithLine) => { + for (const idWithLine of linesToGenerateCodeLens) { codelenses.push(this.createLogStreamCodeLens(logGroupInfo, idWithLine)) - }) + } return codelenses } diff --git a/packages/core/src/awsService/ec2/activation.ts b/packages/core/src/awsService/ec2/activation.ts index f8881af8347..18660732754 100644 --- a/packages/core/src/awsService/ec2/activation.ts +++ b/packages/core/src/awsService/ec2/activation.ts @@ -83,5 +83,6 @@ export async function activate(ctx: ExtContext): Promise { } export async function deactivate(): Promise { + // eslint-disable-next-line unicorn/no-array-for-each connectionManagers.forEach(async (manager) => await manager.dispose()) } diff --git a/packages/core/src/awsService/ec2/remoteSessionManager.ts b/packages/core/src/awsService/ec2/remoteSessionManager.ts index 4c1843aabdb..4c5c8a665b8 100644 --- a/packages/core/src/awsService/ec2/remoteSessionManager.ts +++ b/packages/core/src/awsService/ec2/remoteSessionManager.ts @@ -31,6 +31,7 @@ export class Ec2SessionTracker extends Map implem } public async dispose(): Promise { + // eslint-disable-next-line unicorn/no-array-for-each this.forEach(async (_sessionId, instanceId) => await this.disconnectEnv(instanceId)) } diff --git a/packages/core/src/awsexplorer/toolView.ts b/packages/core/src/awsexplorer/toolView.ts index 6153e8a1ab3..e3417f25521 100644 --- a/packages/core/src/awsexplorer/toolView.ts +++ b/packages/core/src/awsexplorer/toolView.ts @@ -30,13 +30,13 @@ export function createToolView(viewNode: ToolView): vscode.TreeView { // Cloud9 will only refresh when refreshing the entire tree if (isCloud9()) { - viewNode.nodes.forEach((node) => { + for (const node of viewNode.nodes) { // Refreshes are delayed to guard against excessive calls to `getTreeItem` and `getChildren` // The 10ms delay is arbitrary. A single event loop may be good enough in many scenarios. const refresh = debounce(() => treeDataProvider.refresh(node), 10) node.onDidChangeTreeItem?.(() => refresh()) node.onDidChangeChildren?.(() => refresh()) - }) + } } return view diff --git a/packages/core/src/codecatalyst/explorer.ts b/packages/core/src/codecatalyst/explorer.ts index da41ceede27..a2239d41d89 100644 --- a/packages/core/src/codecatalyst/explorer.ts +++ b/packages/core/src/codecatalyst/explorer.ts @@ -141,7 +141,9 @@ export class CodeCatalystRootNode implements TreeNode { this.addRefreshEmitter(() => this.onDidChangeEmitter.fire()) this.authProvider.onDidChange(() => { - this.refreshEmitters.forEach((fire) => fire()) + for (const fire of this.refreshEmitters) { + fire() + } }) } diff --git a/packages/core/src/codecatalyst/wizards/devenvSettings.ts b/packages/core/src/codecatalyst/wizards/devenvSettings.ts index 590b936bfb2..676b65fb74c 100644 --- a/packages/core/src/codecatalyst/wizards/devenvSettings.ts +++ b/packages/core/src/codecatalyst/wizards/devenvSettings.ts @@ -50,7 +50,9 @@ export function getInstanceDescription(type: InstanceType): InstanceDescription export function getAllInstanceDescriptions(): { [key: string]: InstanceDescription } { const desc: { [key: string]: InstanceDescription } = {} - entries(devenvOptions.instanceType).forEach(([k]) => (desc[k] = getInstanceDescription(k))) + for (const [k] of entries(devenvOptions.instanceType)) { + desc[k] = getInstanceDescription(k) + } return desc } diff --git a/packages/core/src/codewhisperer/activation.ts b/packages/core/src/codewhisperer/activation.ts index 4034c6397f4..474d8d68121 100644 --- a/packages/core/src/codewhisperer/activation.ts +++ b/packages/core/src/codewhisperer/activation.ts @@ -721,7 +721,9 @@ function toggleIssuesVisibility(visibleCondition: (issue: CodeScanIssue, filePat issues: group.issues.map((issue) => ({ ...issue, visible: visibleCondition(issue, group.filePath) })), })) securityScanRender.securityDiagnosticCollection?.clear() - updatedIssues.forEach((issue) => updateSecurityDiagnosticCollection(issue)) + for (const issue of updatedIssues) { + updateSecurityDiagnosticCollection(issue) + } SecurityIssueProvider.instance.issues = updatedIssues SecurityIssueTreeViewProvider.instance.refresh() } diff --git a/packages/core/src/codewhisperer/client/codewhisperer.ts b/packages/core/src/codewhisperer/client/codewhisperer.ts index 02f8a5f2f52..69ec6ad1b34 100644 --- a/packages/core/src/codewhisperer/client/codewhisperer.ts +++ b/packages/core/src/codewhisperer/client/codewhisperer.ts @@ -232,14 +232,14 @@ export class DefaultCodeWhispererClient { .promise() .then((resps) => { let logStr = 'amazonq: listAvailableCustomizations API request:' - resps.forEach((resp) => { + for (const resp of resps) { const requestId = resp.$response.requestId logStr += `\n${indent('RequestID: ', 4)}${requestId},\n${indent('Customizations:', 4)}` - resp.customizations.forEach((c, index) => { + for (const [index, c] of resp.customizations.entries()) { const entry = `${index.toString().padStart(2, '0')}: ${c.name?.trim()}` logStr += `\n${indent(entry, 8)}` - }) - }) + } + } getLogger().debug(logStr) return resps }) diff --git a/packages/core/src/codewhisperer/commands/basicCommands.ts b/packages/core/src/codewhisperer/commands/basicCommands.ts index 8ec54d02a2a..999c2c53ac5 100644 --- a/packages/core/src/codewhisperer/commands/basicCommands.ts +++ b/packages/core/src/codewhisperer/commands/basicCommands.ts @@ -489,42 +489,44 @@ export const applySecurityFix = Commands.declare( const fileName = path.basename(targetFilePath) const time = new Date().toLocaleString() // TODO: this is duplicated in controller.ts for test. Fix this later. - suggestedFix.references?.forEach((reference) => { - getLogger().debug('Processing reference: %O', reference) - // Log values for debugging - getLogger().debug('suggested fix code: %s', suggestedFix.code) - getLogger().debug('updated content: %s', updatedContent) - getLogger().debug( - 'start: %d, end: %d', - reference.recommendationContentSpan?.start, - reference.recommendationContentSpan?.end - ) - // given a start and end index, figure out which line number they belong to when splitting a string on /n characters - const getLineNumber = (content: string, index: number): number => { - const lines = content.slice(0, index).split('\n') - return lines.length + if (suggestedFix.references) { + for (const reference of suggestedFix.references) { + getLogger().debug('Processing reference: %O', reference) + // Log values for debugging + getLogger().debug('suggested fix code: %s', suggestedFix.code) + getLogger().debug('updated content: %s', updatedContent) + getLogger().debug( + 'start: %d, end: %d', + reference.recommendationContentSpan?.start, + reference.recommendationContentSpan?.end + ) + // given a start and end index, figure out which line number they belong to when splitting a string on /n characters + const getLineNumber = (content: string, index: number): number => { + const lines = content.slice(0, index).split('\n') + return lines.length + } + const startLine = getLineNumber(updatedContent, reference.recommendationContentSpan!.start!) + const endLine = getLineNumber(updatedContent, reference.recommendationContentSpan!.end!) + getLogger().debug('startLine: %d, endLine: %d', startLine, endLine) + const code = updatedContent.slice( + reference.recommendationContentSpan?.start, + reference.recommendationContentSpan?.end + ) + getLogger().debug('Extracted code slice: %s', code) + const referenceLog = + `[${time}] Accepted recommendation ` + + CodeWhispererConstants.referenceLogText( + `
${code}
`, + reference.licenseName!, + reference.repository!, + fileName, + startLine === endLine ? `(line at ${startLine})` : `(lines from ${startLine} to ${endLine})` + ) + + '
' + getLogger().debug('Adding reference log: %s', referenceLog) + ReferenceLogViewProvider.instance.addReferenceLog(referenceLog) } - const startLine = getLineNumber(updatedContent, reference.recommendationContentSpan!.start!) - const endLine = getLineNumber(updatedContent, reference.recommendationContentSpan!.end!) - getLogger().debug('startLine: %d, endLine: %d', startLine, endLine) - const code = updatedContent.slice( - reference.recommendationContentSpan?.start, - reference.recommendationContentSpan?.end - ) - getLogger().debug('Extracted code slice: %s', code) - const referenceLog = - `[${time}] Accepted recommendation ` + - CodeWhispererConstants.referenceLogText( - `
${code}
`, - reference.licenseName!, - reference.repository!, - fileName, - startLine === endLine ? `(line at ${startLine})` : `(lines from ${startLine} to ${endLine})` - ) + - '
' - getLogger().debug('Adding reference log: %s', referenceLog) - ReferenceLogViewProvider.instance.addReferenceLog(referenceLog) - }) + } removeDiagnostic(document.uri, targetIssue) SecurityIssueProvider.instance.removeIssue(document.uri, targetIssue) diff --git a/packages/core/src/codewhisperer/service/completionProvider.ts b/packages/core/src/codewhisperer/service/completionProvider.ts index 10b90372cb4..226d04dec2b 100644 --- a/packages/core/src/codewhisperer/service/completionProvider.ts +++ b/packages/core/src/codewhisperer/service/completionProvider.ts @@ -16,10 +16,10 @@ import path from 'path' */ export function getCompletionItems(document: vscode.TextDocument, position: vscode.Position) { const completionItems: vscode.CompletionItem[] = [] - session.recommendations.forEach((recommendation, index) => { + for (const [index, recommendation] of session.recommendations.entries()) { completionItems.push(getCompletionItem(document, position, recommendation, index)) session.setSuggestionState(index, 'Showed') - }) + } return completionItems } diff --git a/packages/core/src/codewhisperer/service/diagnosticsProvider.ts b/packages/core/src/codewhisperer/service/diagnosticsProvider.ts index 3fcc9cb8b7d..65afc885073 100644 --- a/packages/core/src/codewhisperer/service/diagnosticsProvider.ts +++ b/packages/core/src/codewhisperer/service/diagnosticsProvider.ts @@ -35,10 +35,10 @@ export function initSecurityScanRender( } else if (scope === CodeAnalysisScope.PROJECT) { securityScanRender.securityDiagnosticCollection?.clear() } - securityRecommendationList.forEach((securityRecommendation) => { + for (const securityRecommendation of securityRecommendationList) { updateSecurityDiagnosticCollection(securityRecommendation) updateSecurityIssuesForProviders(securityRecommendation) - }) + } securityScanRender.initialized = true } @@ -58,11 +58,9 @@ export function updateSecurityDiagnosticCollection(securityRecommendation: Aggre const securityDiagnostics: vscode.Diagnostic[] = vscode.languages .getDiagnostics(uri) .filter((diagnostic) => diagnostic.source === codewhispererDiagnosticSourceLabel) - securityRecommendation.issues - .filter((securityIssue) => securityIssue.visible) - .forEach((securityIssue) => { - securityDiagnostics.push(createSecurityDiagnostic(securityIssue)) - }) + for (const securityIssue of securityRecommendation.issues.filter((securityIssue) => securityIssue.visible)) { + securityDiagnostics.push(createSecurityDiagnostic(securityIssue)) + } securityDiagnosticCollection.set(uri, securityDiagnostics) } @@ -108,27 +106,29 @@ export function disposeSecurityDiagnostic(event: vscode.TextDocumentChangeEvent) } ) - currentSecurityDiagnostics?.forEach((issue) => { - const intersection = changedRange.intersection(issue.range) - if ( - issue.severity === vscode.DiagnosticSeverity.Warning && - intersection && - (/\S/.test(changedText) || changedText === '') && - !CodeScansState.instance.isScansEnabled() - ) { - issue.severity = vscode.DiagnosticSeverity.Information - issue.message = 'Re-scan to validate the fix: ' + issue.message - issue.range = new vscode.Range(intersection.start, intersection.start) - } else if (issue.range.start.line >= changedRange.end.line) { - issue.range = new vscode.Range( - issue.range.start.line + lineOffset, - issue.range.start.character, - issue.range.end.line + lineOffset, - issue.range.end.character - ) + if (currentSecurityDiagnostics) { + for (const issue of currentSecurityDiagnostics) { + const intersection = changedRange.intersection(issue.range) + if ( + issue.severity === vscode.DiagnosticSeverity.Warning && + intersection && + (/\S/.test(changedText) || changedText === '') && + !CodeScansState.instance.isScansEnabled() + ) { + issue.severity = vscode.DiagnosticSeverity.Information + issue.message = 'Re-scan to validate the fix: ' + issue.message + issue.range = new vscode.Range(intersection.start, intersection.start) + } else if (issue.range.start.line >= changedRange.end.line) { + issue.range = new vscode.Range( + issue.range.start.line + lineOffset, + issue.range.start.character, + issue.range.end.line + lineOffset, + issue.range.end.character + ) + } + newSecurityDiagnostics.push(issue) } - newSecurityDiagnostics.push(issue) - }) + } securityScanRender.securityDiagnosticCollection?.set(uri, newSecurityDiagnostics) } diff --git a/packages/core/src/codewhisperer/service/importAdderProvider.ts b/packages/core/src/codewhisperer/service/importAdderProvider.ts index de16365713e..717373148c4 100644 --- a/packages/core/src/codewhisperer/service/importAdderProvider.ts +++ b/packages/core/src/codewhisperer/service/importAdderProvider.ts @@ -55,6 +55,7 @@ export class ImportAdderProvider implements vscode.CodeLensProvider { ) { const line = findLineToInsertImportStatement(editor, firstLineOfRecommendation) let mergedStatements = `` + // eslint-disable-next-line unicorn/no-array-for-each r.mostRelevantMissingImports?.forEach(async (i) => { // trust service response that this to-be-added import is necessary if (i.statement) { diff --git a/packages/core/src/codewhisperer/service/recommendationHandler.ts b/packages/core/src/codewhisperer/service/recommendationHandler.ts index bbcd177a03b..57accdfe44f 100644 --- a/packages/core/src/codewhisperer/service/recommendationHandler.ts +++ b/packages/core/src/codewhisperer/service/recommendationHandler.ts @@ -309,10 +309,10 @@ export class RecommendationHandler { 4, true ).trimStart() - recommendations.forEach((item, index) => { + for (const [index, item] of recommendations.entries()) { msg += `\n ${index.toString().padStart(2, '0')}: ${indent(item.content, 8, true).trim()}` session.requestIdList.push(requestId) - }) + } getLogger().debug(msg) if (invocationResult === 'Succeeded') { CodeWhispererCodeCoverageTracker.getTracker(session.language)?.incrementServiceInvocationCount() @@ -368,7 +368,7 @@ export class RecommendationHandler { TelemetryHelper.instance.setTypeAheadLength(typedPrefix.length) // mark suggestions that does not match typeahead when arrival as Discard // these suggestions can be marked as Showed if typeahead can be removed with new inline API - recommendations.forEach((r, i) => { + for (const [i, r] of recommendations.entries()) { const recommendationIndex = i + session.recommendations.length if ( !r.content.startsWith(typedPrefix) && @@ -377,7 +377,7 @@ export class RecommendationHandler { session.setSuggestionState(recommendationIndex, 'Discard') } session.setCompletionType(recommendationIndex, r) - }) + } session.recommendations = pagination ? session.recommendations.concat(recommendations) : recommendations if (isInlineCompletionEnabled() && this.hasAtLeastOneValidSuggestion(typedPrefix)) { this._onDidReceiveRecommendation.fire() @@ -472,9 +472,9 @@ export class RecommendationHandler { } reportDiscardedUserDecisions() { - session.recommendations.forEach((r, i) => { + for (const [i, _] of session.recommendations.entries()) { session.setSuggestionState(i, 'Discard') - }) + } this.reportUserDecisions(-1) } @@ -526,9 +526,9 @@ export class RecommendationHandler { // do not show recommendation if cursor is before invocation position // also mark as Discard if (editor.selection.active.isBefore(session.startPos)) { - session.recommendations.forEach((r, i) => { + for (const [i, _] of session.recommendations.entries()) { session.setSuggestionState(i, 'Discard') - }) + } reject() return false } @@ -544,9 +544,9 @@ export class RecommendationHandler { ) ) if (!session.recommendations[0].content.startsWith(typedPrefix.trimStart())) { - session.recommendations.forEach((r, i) => { + for (const [i, _] of session.recommendations.entries()) { session.setSuggestionState(i, 'Discard') - }) + } reject() return false } @@ -668,9 +668,9 @@ export class RecommendationHandler { editor.selection.active.isBefore(session.startPos) || editor.document.uri.fsPath !== this.documentUri?.fsPath ) { - session.recommendations.forEach((r, i) => { + for (const [i, _] of session.recommendations.entries()) { session.setSuggestionState(i, 'Discard') - }) + } this.reportUserDecisions(-1) } else if (session.recommendations.length > 0) { await this.showRecommendation(0, true) diff --git a/packages/core/src/codewhisperer/service/securityScanHandler.ts b/packages/core/src/codewhisperer/service/securityScanHandler.ts index d328034d560..ba70e558733 100644 --- a/packages/core/src/codewhisperer/service/securityScanHandler.ts +++ b/packages/core/src/codewhisperer/service/securityScanHandler.ts @@ -68,13 +68,13 @@ export async function listScanResults( return resp.codeAnalysisFindings }) .promise() - issues.forEach((issue) => { + for (const issue of issues) { mapToAggregatedList(codeScanIssueMap, issue, editor, scope) - }) - codeScanIssueMap.forEach((issues, key) => { + } + for (const [key, issues] of codeScanIssueMap.entries()) { // Project path example: /Users/username/project // Key example: project/src/main/java/com/example/App.java - projectPaths.forEach((projectPath) => { + for (const projectPath of projectPaths) { // We need to remove the project path from the key to get the absolute path to the file // Do not use .. in between because there could be multiple project paths in the same parent dir. const filePath = path.join(projectPath, key.split('/').slice(1).join('/')) @@ -85,7 +85,7 @@ export async function listScanResults( } aggregatedCodeScanIssueList.push(aggregatedCodeScanIssue) } - }) + } const maybeAbsolutePath = `/${key}` if (existsSync(maybeAbsolutePath) && statSync(maybeAbsolutePath).isFile()) { const aggregatedCodeScanIssue: AggregatedCodeScanIssue = { @@ -94,7 +94,7 @@ export async function listScanResults( } aggregatedCodeScanIssueList.push(aggregatedCodeScanIssue) } - }) + } return aggregatedCodeScanIssueList } @@ -158,7 +158,7 @@ export function mapToAggregatedList( return true }) - filteredIssues.forEach((issue) => { + for (const issue of filteredIssues) { const filePath = issue.filePath if (codeScanIssueMap.has(filePath)) { if (!isExistingIssue(issue, codeScanIssueMap)) { @@ -169,7 +169,7 @@ export function mapToAggregatedList( } else { codeScanIssueMap.set(filePath, [issue]) } - }) + } } function isDuplicateIssue(issueA: RawCodeScanIssue, issueB: RawCodeScanIssue) { diff --git a/packages/core/src/codewhisperer/service/transformByQ/transformApiHandler.ts b/packages/core/src/codewhisperer/service/transformByQ/transformApiHandler.ts index b6f3eda36ce..cbf6bf92710 100644 --- a/packages/core/src/codewhisperer/service/transformByQ/transformApiHandler.ts +++ b/packages/core/src/codewhisperer/service/transformByQ/transformApiHandler.ts @@ -359,9 +359,9 @@ export async function zipCode( }, } // TO-DO: later consider making this add to path.join(zipManifest.dependenciesRoot, 'qct-sct-metadata', entry.entryName) so that it's more organized - metadataZip - .getEntries() - .forEach((entry) => zip.addFile(path.join(zipManifest.dependenciesRoot, entry.name), entry.getData())) + for (const entry of metadataZip.getEntries()) { + zip.addFile(path.join(zipManifest.dependenciesRoot, entry.name), entry.getData()) + } const sqlMetadataSize = (await nodefs.promises.stat(transformByQState.getMetadataPathSQL())).size getLogger().info(`CodeTransformation: SQL metadata file size = ${sqlMetadataSize}`) } @@ -514,15 +514,19 @@ export function addTableMarkdown(plan: string, stepId: string, tableMapping: { [ const table = JSON.parse(tableObj) plan += `\n\n\n${table.name}\n|` const columns = table.columnNames + // eslint-disable-next-line unicorn/no-array-for-each columns.forEach((columnName: string) => { plan += ` ${getFormattedString(columnName)} |` }) plan += '\n|' + // eslint-disable-next-line unicorn/no-array-for-each columns.forEach((_: any) => { plan += '-----|' }) + // eslint-disable-next-line unicorn/no-array-for-each table.rows.forEach((row: any) => { plan += '\n|' + // eslint-disable-next-line unicorn/no-array-for-each columns.forEach((columnName: string) => { if (columnName === 'relativePath') { plan += ` [${row[columnName]}](${row[columnName]}) |` // add MD link only for files @@ -537,11 +541,11 @@ export function addTableMarkdown(plan: string, stepId: string, tableMapping: { [ export function getTableMapping(stepZeroProgressUpdates: ProgressUpdates) { const map: { [key: string]: string } = {} - stepZeroProgressUpdates.forEach((update) => { + for (const update of stepZeroProgressUpdates) { // description should never be undefined since even if no data we show an empty table // but just in case, empty string allows us to skip this table without errors when rendering map[update.name] = update.description ?? '' - }) + } return map } @@ -551,6 +555,7 @@ export function getJobStatisticsHtml(jobStatistics: any) { return htmlString } htmlString += `
` + // eslint-disable-next-line unicorn/no-array-for-each jobStatistics.forEach((stat: { name: string; value: string }) => { htmlString += `

${CodeWhispererConstants.planHeaderMessage}

${CodeWhispererConstants.planDisclaimerMessage} Read more.

` - response.transformationPlan.transformationSteps.slice(1).forEach((step) => { + for (const step of response.transformationPlan.transformationSteps.slice(1)) { plan += `

${step.name}

Scroll to top

${step.description}

` plan = addTableMarkdown(plan, step.id, tableMapping) plan += `

` - }) + } plan += `

` plan += `

Appendix
Scroll to top


` plan = addTableMarkdown(plan, '-1', tableMapping) // ID of '-1' reserved for appendix table diff --git a/packages/core/src/codewhisperer/service/transformByQ/transformFileHandler.ts b/packages/core/src/codewhisperer/service/transformByQ/transformFileHandler.ts index 516471fc078..767869d0310 100644 --- a/packages/core/src/codewhisperer/service/transformByQ/transformFileHandler.ts +++ b/packages/core/src/codewhisperer/service/transformByQ/transformFileHandler.ts @@ -97,10 +97,12 @@ export async function validateSQLMetadataFile(fileContents: string, message: any const serverNodeLocations = sctData['tree']['instances'][0]['ProjectModel'][0]['relations'][0]['server-node-location'] const schemaNames = new Set() + // eslint-disable-next-line unicorn/no-array-for-each serverNodeLocations.forEach((serverNodeLocation: any) => { const schemaNodes = serverNodeLocation['FullNameNodeInfoList'][0]['nameParts'][0][ 'FullNameNodeInfo' ].filter((node: any) => node['$']['typeNode'].toLowerCase() === 'schema') + // eslint-disable-next-line unicorn/no-array-for-each schemaNodes.forEach((node: any) => { schemaNames.add(node['$']['nameNode'].toUpperCase()) }) diff --git a/packages/core/src/codewhisperer/service/transformByQ/transformationResultsViewProvider.ts b/packages/core/src/codewhisperer/service/transformByQ/transformationResultsViewProvider.ts index 1f4058a54dc..b41e8b7793c 100644 --- a/packages/core/src/codewhisperer/service/transformByQ/transformationResultsViewProvider.ts +++ b/packages/core/src/codewhisperer/service/transformByQ/transformationResultsViewProvider.ts @@ -145,7 +145,7 @@ export class DiffModel { public copyProject(pathToWorkspace: string, changedFiles: ParsedDiff[]) { const pathToTmpSrcDir = path.join(os.tmpdir(), `project-copy-${Date.now()}`) fs.mkdirSync(pathToTmpSrcDir) - changedFiles.forEach((file) => { + for (const file of changedFiles) { const pathToTmpFile = path.join(pathToTmpSrcDir, file.oldFileName!.substring(2)) // use mkdirsSync to create parent directories in pathToTmpFile too fs.mkdirSync(path.dirname(pathToTmpFile), { recursive: true }) @@ -154,7 +154,7 @@ export class DiffModel { if (fs.existsSync(pathToOldFile)) { fs.copyFileSync(pathToOldFile, pathToTmpFile) } - }) + } return pathToTmpSrcDir } @@ -243,11 +243,11 @@ export class DiffModel { } public saveChanges() { - this.patchFileNodes.forEach((patchFileNode) => { - patchFileNode.children.forEach((changeNode) => { + for (const patchFileNode of this.patchFileNodes) { + for (const changeNode of patchFileNode.children) { changeNode.saveChange() - }) - }) + } + } } public rejectChanges() { diff --git a/packages/core/src/codewhisperer/tracker/codewhispererCodeCoverageTracker.ts b/packages/core/src/codewhisperer/tracker/codewhispererCodeCoverageTracker.ts index 925609ce185..d0ad76c26da 100644 --- a/packages/core/src/codewhisperer/tracker/codewhispererCodeCoverageTracker.ts +++ b/packages/core/src/codewhisperer/tracker/codewhispererCodeCoverageTracker.ts @@ -104,12 +104,12 @@ export class CodeWhispererCodeCoverageTracker { // the accepted characters after calculating user modification let unmodifiedAcceptedTokens = 0 for (const filename in this._acceptedTokens) { - this._acceptedTokens[filename].forEach((v) => { + for (const v of this._acceptedTokens[filename]) { if (filename in this._totalTokens && this._totalTokens[filename] >= v.accepted) { unmodifiedAcceptedTokens += v.accepted acceptedTokens += v.text.length } - }) + } } const percentCount = ((acceptedTokens / totalTokens) * 100).toFixed(2) const percentage = Math.round(parseInt(percentCount)) diff --git a/packages/core/src/codewhisperer/util/authUtil.ts b/packages/core/src/codewhisperer/util/authUtil.ts index afb15aff133..53c33c2ed4e 100644 --- a/packages/core/src/codewhisperer/util/authUtil.ts +++ b/packages/core/src/codewhisperer/util/authUtil.ts @@ -457,7 +457,9 @@ export class AuthUtil { state[Features.codewhispererCore] = AuthStates.connected } if (isValidAmazonQConnection(conn)) { - Object.values(Features).forEach((v) => (state[v as Feature] = AuthStates.connected)) + for (const v of Object.values(Features)) { + state[v as Feature] = AuthStates.connected + } } } diff --git a/packages/core/src/codewhisperer/util/closingBracketUtil.ts b/packages/core/src/codewhisperer/util/closingBracketUtil.ts index 4273094b58a..b9511349e9c 100644 --- a/packages/core/src/codewhisperer/util/closingBracketUtil.ts +++ b/packages/core/src/codewhisperer/util/closingBracketUtil.ts @@ -111,13 +111,13 @@ const removeBracketsFromRightContext = async ( } else { await editor.edit( (editBuilder) => { - idxToRemove.forEach((idx) => { + for (const idx of idxToRemove) { const range = new vscode.Range( editor.document.positionAt(offset + idx), editor.document.positionAt(offset + idx + 1) ) editBuilder.delete(range) - }) + } }, { undoStopAfter: false, undoStopBefore: false } ) diff --git a/packages/core/src/codewhisperer/util/customizationUtil.ts b/packages/core/src/codewhisperer/util/customizationUtil.ts index cfaf68b1afd..d2b14cb5247 100644 --- a/packages/core/src/codewhisperer/util/customizationUtil.ts +++ b/packages/core/src/codewhisperer/util/customizationUtil.ts @@ -328,11 +328,11 @@ export const selectCustomization = async (customization: Customization) => { export const getAvailableCustomizationsList = async () => { const items: Customization[] = [] const response = await codeWhispererClient.listAvailableCustomizations() - response - .map((listAvailableCustomizationsResponse) => listAvailableCustomizationsResponse.customizations) - .forEach((customizations) => { - items.push(...customizations) - }) + for (const customizations of response.map( + (listAvailableCustomizationsResponse) => listAvailableCustomizationsResponse.customizations + )) { + items.push(...customizations) + } return items } diff --git a/packages/core/src/codewhisperer/util/editorContext.ts b/packages/core/src/codewhisperer/util/editorContext.ts index 4b58cb4f848..99a15fd1f02 100644 --- a/packages/core/src/codewhisperer/util/editorContext.ts +++ b/packages/core/src/codewhisperer/util/editorContext.ts @@ -216,7 +216,7 @@ function logSupplementalContext(supplementalContext: CodeWhispererSupplementalCo true ).trimStart() - supplementalContext.supplementalContextItems.forEach((context, index) => { + for (const [index, context] of supplementalContext.supplementalContextItems.entries()) { logString += indent(`\nChunk ${index}:\n`, 4, true) logString += indent( `Path: ${context.filePath} @@ -225,7 +225,7 @@ function logSupplementalContext(supplementalContext: CodeWhispererSupplementalCo 8, true ) - }) + } getLogger().debug(logString) } diff --git a/packages/core/src/codewhisperer/util/licenseUtil.ts b/packages/core/src/codewhisperer/util/licenseUtil.ts index 3a49adc6b4a..d21cd093e12 100644 --- a/packages/core/src/codewhisperer/util/licenseUtil.ts +++ b/packages/core/src/codewhisperer/util/licenseUtil.ts @@ -471,11 +471,13 @@ export class LicenseUtil { public static getUniqueLicenseNames(references: References | undefined): Set { const n = new Set() - references?.forEach((r) => { - if (r.licenseName) { - n.add(r.licenseName) + if (references) { + for (const r of references) { + if (r.licenseName) { + n.add(r.licenseName) + } } - }) + } return n } } diff --git a/packages/core/src/codewhisperer/util/supplementalContext/rankBm25.ts b/packages/core/src/codewhisperer/util/supplementalContext/rankBm25.ts index 3e00013c9cf..a2c77e0b10f 100644 --- a/packages/core/src/codewhisperer/util/supplementalContext/rankBm25.ts +++ b/packages/core/src/codewhisperer/util/supplementalContext/rankBm25.ts @@ -31,24 +31,22 @@ export abstract class BM25 { this.corpusSize = corpus.length let numDoc = 0 - corpus - .map((document) => { - return tokenizer(document) - }) - .forEach((document) => { - this.docLen.push(document.length) - numDoc += document.length - - const frequencies = new Map() - document.forEach((word) => { - frequencies.set(word, (frequencies.get(word) || 0) + 1) - }) - this.docFreqs.push(frequencies) - - frequencies.forEach((freq, word) => { - this.nd.set(word, (this.nd.get(word) || 0) + 1) - }) - }) + for (const document of corpus.map((document) => { + return tokenizer(document) + })) { + this.docLen.push(document.length) + numDoc += document.length + + const frequencies = new Map() + for (const word of document) { + frequencies.set(word, (frequencies.get(word) || 0) + 1) + } + this.docFreqs.push(frequencies) + + for (const [word, _] of frequencies.entries()) { + this.nd.set(word, (this.nd.get(word) || 0) + 1) + } + } this.avgdl = numDoc / this.corpusSize @@ -96,14 +94,14 @@ export class BM25Okapi extends BM25 { const queryWords = defaultTokenizer(query) return this.docFreqs.map((docFreq, index) => { let score = 0 - queryWords.forEach((queryWord, _) => { + for (const [_, queryWord] of queryWords.entries()) { const queryWordFreqForDocument = docFreq.get(queryWord) || 0 const numerator = (this.idf.get(queryWord) || 0.0) * queryWordFreqForDocument * (this.k1 + 1) const denominator = queryWordFreqForDocument + this.k1 * (1 - this.b + (this.b * this.docLen[index]) / this.avgdl) score += numerator / denominator - }) + } return { content: this.corpus[index], diff --git a/packages/core/src/codewhisperer/util/telemetryHelper.ts b/packages/core/src/codewhisperer/util/telemetryHelper.ts index 9518aa610fc..6505e248f28 100644 --- a/packages/core/src/codewhisperer/util/telemetryHelper.ts +++ b/packages/core/src/codewhisperer/util/telemetryHelper.ts @@ -257,7 +257,7 @@ export class TelemetryHelper { ) { const events: CodewhispererUserDecision[] = [] // emit user decision telemetry - recommendations.forEach((_elem, i) => { + for (const [i, _elem] of recommendations.entries()) { let uniqueSuggestionReferences: string | undefined = undefined const uniqueLicenseSet = LicenseUtil.getUniqueLicenseNames(_elem.references) if (uniqueLicenseSet.size > 0) { @@ -288,7 +288,7 @@ export class TelemetryHelper { } telemetry.codewhisperer_userDecision.emit(event) events.push(event) - }) + } // aggregate suggestion references count const referenceCount = this.getAggregatedSuggestionReferenceCount(events) diff --git a/packages/core/src/codewhisperer/util/zipUtil.ts b/packages/core/src/codewhisperer/util/zipUtil.ts index b75a6798ab2..ab938aeb643 100644 --- a/packages/core/src/codewhisperer/util/zipUtil.ts +++ b/packages/core/src/codewhisperer/util/zipUtil.ts @@ -433,12 +433,11 @@ export class ZipUtil { } protected processOtherFiles(zip: admZip, languageCount: Map) { - vscode.workspace.textDocuments + for (const document of vscode.workspace.textDocuments .filter((document) => document.uri.scheme === 'file') - .filter((document) => vscode.workspace.getWorkspaceFolder(document.uri) === undefined) - .forEach((document) => - this.processTextFile(zip, document.uri, document.getText(), languageCount, document.uri.fsPath) - ) + .filter((document) => vscode.workspace.getWorkspaceFolder(document.uri) === undefined)) { + this.processTextFile(zip, document.uri, document.getText(), languageCount, document.uri.fsPath) + } } protected async processTestCoverageFiles(targetPath: string) { diff --git a/packages/core/src/codewhisperer/views/securityPanelViewProvider.ts b/packages/core/src/codewhisperer/views/securityPanelViewProvider.ts index d02eea155eb..5f3b6cece70 100644 --- a/packages/core/src/codewhisperer/views/securityPanelViewProvider.ts +++ b/packages/core/src/codewhisperer/views/securityPanelViewProvider.ts @@ -88,9 +88,9 @@ export class SecurityPanelViewProvider implements vscode.WebviewViewProvider { this.packageName } found ${total} issues

` ) - this.panelSets.forEach((panelSet, index) => { + for (const [index, panelSet] of this.panelSets.entries()) { this.addLine(panelSet, index) - }) + } this.update() if (editor) { this.setDecoration(editor, editor.document.uri) @@ -111,20 +111,20 @@ export class SecurityPanelViewProvider implements vscode.WebviewViewProvider { this.dynamicLog.push( `
` ) - panelSet.items.forEach((item) => { + for (const item of panelSet.items) { if (item.severity === vscode.DiagnosticSeverity.Warning) { this.dynamicLog.push(`${this.addClickableWarningItem(item)}`) } else { this.dynamicLog.push(`${this.addClickableInfoItem(item)}`) } - }) + } this.dynamicLog.push(`
`) } private persistLines() { - this.panelSets.forEach((panelSet, index) => { + for (const [index, panelSet] of this.panelSets.entries()) { this.persistLine(panelSet, index) - }) + } } private persistLine(panelSet: SecurityPanelSet, index: number) { @@ -134,13 +134,13 @@ export class SecurityPanelViewProvider implements vscode.WebviewViewProvider { this.persistLog.push( `
` ) - panelSet.items.forEach((item) => { + for (const item of panelSet.items) { if (item.severity === vscode.DiagnosticSeverity.Warning) { this.persistLog.push(`${this.addUnclickableWarningItem(item)}`) } else { this.persistLog.push(`${this.addUnclickableInfoItem(item)}`) } - }) + } this.persistLog.push(`
`) } @@ -171,13 +171,13 @@ export class SecurityPanelViewProvider implements vscode.WebviewViewProvider { } private createPanelSets(securityRecommendationCollection: AggregatedCodeScanIssue[]) { - securityRecommendationCollection.forEach((securityRecommendation) => { + for (const securityRecommendation of securityRecommendationCollection) { const panelSet: SecurityPanelSet = { path: securityRecommendation.filePath, uri: vscode.Uri.parse(securityRecommendation.filePath), items: [], } - securityRecommendation.issues.forEach((issue) => { + for (const issue of securityRecommendation.issues) { panelSet.items.push({ path: securityRecommendation.filePath, range: new vscode.Range(issue.startLine, 0, issue.endLine, 0), @@ -189,9 +189,9 @@ export class SecurityPanelViewProvider implements vscode.WebviewViewProvider { hoverMessage: issue.comment, }, }) - }) + } this.panelSets.push(panelSet) - }) + } } private getHtml(webview: vscode.Webview): string { @@ -232,15 +232,15 @@ export class SecurityPanelViewProvider implements vscode.WebviewViewProvider { public setDecoration(editor: vscode.TextEditor, uri: vscode.Uri) { editor.setDecorations(this.getDecorator(), []) const rangesToRend: vscode.DecorationOptions[] = [] - this.panelSets.forEach((panelSet) => { + for (const panelSet of this.panelSets) { if (panelSet.uri.fsPath === uri.fsPath) { - panelSet.items.forEach((item) => { + for (const item of panelSet.items) { if (item.severity === vscode.DiagnosticSeverity.Warning) { rangesToRend.push(item.decoration) } - }) + } } - }) + } if (rangesToRend.length > 0) { editor.setDecorations(this.getDecorator(), rangesToRend) } @@ -261,6 +261,7 @@ export class SecurityPanelViewProvider implements vscode.WebviewViewProvider { const changedText = event.contentChanges[0].text const lineOffset = this.getLineOffset(changedRange, changedText) + // eslint-disable-next-line unicorn/no-array-for-each currentPanelSet.items.forEach((item, index, items) => { const intersection = changedRange.intersection(item.range) if ( @@ -282,9 +283,9 @@ export class SecurityPanelViewProvider implements vscode.WebviewViewProvider { }) this.panelSets[index] = currentPanelSet this.dynamicLog = [] - this.panelSets.forEach((panelSet, index) => { + for (const [index, panelSet] of this.panelSets.entries()) { this.addLine(panelSet, index) - }) + } this.update() if (editor) { this.setDecoration(editor, editor.document.uri) diff --git a/packages/core/src/codewhispererChat/controllers/chat/chatRequest/converter.ts b/packages/core/src/codewhispererChat/controllers/chat/chatRequest/converter.ts index 9ff56523379..a3236f7d402 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/chatRequest/converter.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/chatRequest/converter.ts @@ -43,22 +43,24 @@ export function triggerPayloadToChatRequest(triggerPayload: TriggerPayload): { c if (triggerPayload.filePath !== undefined && triggerPayload.filePath !== '') { const documentSymbolFqns: DocumentSymbol[] = [] - triggerPayload.codeQuery?.fullyQualifiedNames?.used?.forEach((fqn) => { - const elem = { - name: fqn.symbol?.join('.') ?? '', - type: SymbolType.USAGE, - source: fqn.source?.join('.'), - } + if (triggerPayload.codeQuery?.fullyQualifiedNames?.used) { + for (const fqn of triggerPayload.codeQuery.fullyQualifiedNames.used) { + const elem = { + name: fqn.symbol?.join('.') ?? '', + type: SymbolType.USAGE, + source: fqn.source?.join('.'), + } - if ( - elem.name.length >= fqnNameSizeDownLimit && - elem.name.length < fqnNameSizeUpLimit && - (elem.source === undefined || - (elem.source.length >= fqnNameSizeDownLimit && elem.source.length < fqnNameSizeUpLimit)) - ) { - documentSymbolFqns.push(elem) + if ( + elem.name.length >= fqnNameSizeDownLimit && + elem.name.length < fqnNameSizeUpLimit && + (elem.source === undefined || + (elem.source.length >= fqnNameSizeDownLimit && elem.source.length < fqnNameSizeUpLimit)) + ) { + documentSymbolFqns.push(elem) + } } - }) + } let programmingLanguage if ( diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 6a1d388c05d..57b45d414c1 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -632,11 +632,11 @@ export class ChatController { if (CodeWhispererSettings.instance.isLocalIndexEnabled()) { const start = performance.now() triggerPayload.relevantTextDocuments = await LspController.instance.query(triggerPayload.message) - triggerPayload.relevantTextDocuments.forEach((doc) => { + for (const doc of triggerPayload.relevantTextDocuments) { getLogger().info( `amazonq: Using workspace files ${doc.relativeFilePath}, content(partial): ${doc.text?.substring(0, 200)}` ) - }) + } triggerPayload.projectContextQueryLatencyMs = performance.now() - start } else { this.messenger.sendOpenSettingsMessage(triggerID, tabID) diff --git a/packages/core/src/codewhispererChat/editor/codelens.ts b/packages/core/src/codewhispererChat/editor/codelens.ts index 651853a78cf..4df72d776d6 100644 --- a/packages/core/src/codewhispererChat/editor/codelens.ts +++ b/packages/core/src/codewhispererChat/editor/codelens.ts @@ -151,7 +151,9 @@ export class TryChatCodeLensProvider implements vscode.CodeLensProvider { dispose() { globals.globalState.tryUpdate('aws.amazonq.showTryChatCodeLens', false) TryChatCodeLensProvider.providerDisposable?.dispose() - this.disposables.forEach((d) => d.dispose()) + for (const d of this.disposables) { + d.dispose() + } } } diff --git a/packages/core/src/codewhispererChat/editor/context/file/fileExtractor.ts b/packages/core/src/codewhispererChat/editor/context/file/fileExtractor.ts index e9f0220dfd7..7606fe0708c 100644 --- a/packages/core/src/codewhispererChat/editor/context/file/fileExtractor.ts +++ b/packages/core/src/codewhispererChat/editor/context/file/fileExtractor.ts @@ -41,11 +41,11 @@ export class FileContextExtractor { if (languageId !== undefined) { const imports = await readImports(file.getText(), languageId) - imports - .filter(function (elem, index, self) { - return index === self.indexOf(elem) && elem !== languageId - }) - .forEach((importKey) => should.add(importKey)) + for (const importKey of imports.filter(function (elem, index, self) { + return index === self.indexOf(elem) && elem !== languageId + })) { + should.add(importKey) + } } return { diff --git a/packages/core/src/codewhispererChat/storages/triggerEvents.ts b/packages/core/src/codewhispererChat/storages/triggerEvents.ts index d30ebf48939..1bbf08b6de9 100644 --- a/packages/core/src/codewhispererChat/storages/triggerEvents.ts +++ b/packages/core/src/codewhispererChat/storages/triggerEvents.ts @@ -30,6 +30,7 @@ export class TriggerEventsStorage { public removeTabEvents(tabID: string) { const events = this.triggerEventsByTabID.get(tabID) ?? [] + // eslint-disable-next-line unicorn/no-array-for-each events.forEach((event: TriggerEvent) => { this.triggerEvents.delete(event.id) }) diff --git a/packages/core/src/eventSchemas/commands/downloadSchemaItemCode.ts b/packages/core/src/eventSchemas/commands/downloadSchemaItemCode.ts index 3ee5d8c865c..6c6ec818444 100644 --- a/packages/core/src/eventSchemas/commands/downloadSchemaItemCode.ts +++ b/packages/core/src/eventSchemas/commands/downloadSchemaItemCode.ts @@ -328,7 +328,7 @@ export class CodeExtractor { const zipEntries = zip.getEntries() const detectedCollisions: string[] = [] - zipEntries.forEach(function (zipEntry) { + for (const zipEntry of zipEntries) { if (zipEntry.isDirectory) { // Ignore directories because those can/will merged } else { @@ -337,7 +337,7 @@ export class CodeExtractor { detectedCollisions.push(intendedDestinationPath) } } - }) + } if (detectedCollisions.length > 0) { this.writeToOutputChannel(detectedCollisions) diff --git a/packages/core/src/eventSchemas/vue/searchSchemas.ts b/packages/core/src/eventSchemas/vue/searchSchemas.ts index 32f04e954c8..a5dcb55527d 100644 --- a/packages/core/src/eventSchemas/vue/searchSchemas.ts +++ b/packages/core/src/eventSchemas/vue/searchSchemas.ts @@ -151,7 +151,9 @@ export async function getRegistryNames(node: RegistryItemNode | SchemasNode, cli if (node instanceof SchemasNode) { try { const registries = await toArrayAsync(listRegistryItems(client)) - registries.forEach((element) => registryNames.push(element.RegistryName!)) + for (const element of registries) { + registryNames.push(element.RegistryName!) + } } catch (err) { const error = err as Error getLogger().error(error) diff --git a/packages/core/src/extensionNode.ts b/packages/core/src/extensionNode.ts index b6d4a599ce1..480e409f5d8 100644 --- a/packages/core/src/extensionNode.ts +++ b/packages/core/src/extensionNode.ts @@ -85,10 +85,9 @@ export async function activate(context: vscode.ExtensionContext) { const toolkitEnvDetails = getExtEnvironmentDetails() // Splits environment details by new line, filter removes the empty string - toolkitEnvDetails - .split(/\r?\n/) - .filter(Boolean) - .forEach((line) => getLogger().info(line)) + for (const line of toolkitEnvDetails.split(/\r?\n/).filter(Boolean)) { + getLogger().info(line) + } globals.awsContextCommands = new AwsContextCommands(globals.regionProvider, Auth.instance) globals.schemaService = new SchemaService() @@ -343,17 +342,23 @@ async function getAuthState(): Promise> { const enabledScopes: Set = new Set() if (Auth.instance.hasConnections) { authStatus = 'expired' - ;(await Auth.instance.listConnections()).forEach((conn) => { + for (const conn of await Auth.instance.listConnections()) { const state = Auth.instance.getConnectionState(conn) if (state === 'valid') { authStatus = 'connected' } - getAuthFormIdsFromConnection(conn).forEach((id) => enabledConnections.add(id)) + for (const id of getAuthFormIdsFromConnection(conn)) { + enabledConnections.add(id) + } if (isSsoConnection(conn)) { - conn.scopes?.forEach((s) => enabledScopes.add(s)) + if (conn.scopes) { + for (const s of conn.scopes) { + enabledScopes.add(s) + } + } } - }) + } } // There may be other SSO connections in toolkit, but there is no use case for diff --git a/packages/core/src/lambda/commands/createNewSamApp.ts b/packages/core/src/lambda/commands/createNewSamApp.ts index 629130dbb2a..e60e60c31ed 100644 --- a/packages/core/src/lambda/commands/createNewSamApp.ts +++ b/packages/core/src/lambda/commands/createNewSamApp.ts @@ -417,12 +417,12 @@ export async function addInitialLaunchConfiguration( // optional for ZIP-lambdas but required for Image-lambdas if (runtime !== undefined) { - filtered.forEach((configuration) => { + for (const configuration of filtered) { if (!configuration.lambda) { configuration.lambda = {} } configuration.lambda.runtime = runtime - }) + } } await launchConfiguration.addDebugConfigurations(filtered) diff --git a/packages/core/src/lambda/vue/configEditor/samInvokeFrontend.ts b/packages/core/src/lambda/vue/configEditor/samInvokeFrontend.ts index 551be9d09cf..c266abb8a4b 100644 --- a/packages/core/src/lambda/vue/configEditor/samInvokeFrontend.ts +++ b/packages/core/src/lambda/vue/configEditor/samInvokeFrontend.ts @@ -448,9 +448,9 @@ export default defineComponent({ }, clearForm() { const init = initData() - Object.keys(init).forEach((k) => { + for (const k of Object.keys(init)) { ;(this as any)[k] = init[k as keyof typeof init] - }) + } }, }, }) diff --git a/packages/core/src/lambda/wizards/samDeployWizard.ts b/packages/core/src/lambda/wizards/samDeployWizard.ts index a45e07b0b74..98047b75db1 100644 --- a/packages/core/src/lambda/wizards/samDeployWizard.ts +++ b/packages/core/src/lambda/wizards/samDeployWizard.ts @@ -946,11 +946,11 @@ async function getTemplateChoices(...workspaceFolders: vscode.Uri[]): Promise = new Map() const labelCounts: Map = new Map() - templateUris.forEach((uri) => { + for (const uri of templateUris) { const label = SamTemplateQuickPickItem.getLabel(uri) uriToLabel.set(uri, label) labelCounts.set(label, 1 + (labelCounts.get(label) || 0)) - }) + } return Array.from(uriToLabel, ([uri, label]) => { const showWorkspaceFolderDetails: boolean = (labelCounts.get(label) || 0) > 1 diff --git a/packages/core/src/login/webview/vue/toolkit/backend_toolkit.ts b/packages/core/src/login/webview/vue/toolkit/backend_toolkit.ts index 06f39603bb0..b50fe563745 100644 --- a/packages/core/src/login/webview/vue/toolkit/backend_toolkit.ts +++ b/packages/core/src/login/webview/vue/toolkit/backend_toolkit.ts @@ -134,7 +134,7 @@ export class ToolkitLoginWebview extends CommonAuthWebview { */ async fetchConnections(): Promise { const connections: AwsConnection[] = [] - Auth.instance.declaredConnections.forEach((conn) => { + for (const conn of Auth.instance.declaredConnections) { // No need to display Builder ID as an existing connection, // users can just select the Builder ID login option and it would have the same effect. if (conn.startUrl !== builderIdStartUrl) { @@ -143,7 +143,7 @@ export class ToolkitLoginWebview extends CommonAuthWebview { startUrl: conn.startUrl, } as AwsConnection) } - }) + } return connections } diff --git a/packages/core/src/shared/awsClientBuilder.ts b/packages/core/src/shared/awsClientBuilder.ts index 25ef698b27a..bdec40957cb 100644 --- a/packages/core/src/shared/awsClientBuilder.ts +++ b/packages/core/src/shared/awsClientBuilder.ts @@ -171,7 +171,9 @@ export class DefaultAWSClientBuilder implements AWSClientBuilder { service.setupRequestListeners = (request: Request) => { originalSetup(request) - listeners.forEach((l) => l(request as AWS.Request & RequestExtras)) + for (const l of listeners) { + l(request as AWS.Request & RequestExtras) + } } return service diff --git a/packages/core/src/shared/codelens/codeLensUtils.ts b/packages/core/src/shared/codelens/codeLensUtils.ts index ef2e0f6c526..5eb0c08fafe 100644 --- a/packages/core/src/shared/codelens/codeLensUtils.ts +++ b/packages/core/src/shared/codelens/codeLensUtils.ts @@ -230,7 +230,7 @@ export async function pickAddSamDebugConfiguration( const templateItemsMap = new Map() const templateItems: vscode.QuickPickItem[] = [] - templateConfigs.forEach((templateConfig) => { + for (const templateConfig of templateConfigs) { const label = `${ getWorkspaceRelativePath(templateConfig.rootUri.fsPath)?.relativePath ?? templateConfig.rootUri.fsPath }:${templateConfig.resourceName}` @@ -246,7 +246,7 @@ export async function pickAddSamDebugConfiguration( templateItems.push({ label: label }) templateItemsMap.set(label, templateConfig) } - }) + } const noTemplate = localize('AWS.pickDebugConfig.noTemplate', 'No Template') const picker = createQuickPick({ diff --git a/packages/core/src/shared/codelens/goCodeLensProvider.ts b/packages/core/src/shared/codelens/goCodeLensProvider.ts index 26683f2f349..3d3bf1c1942 100644 --- a/packages/core/src/shared/codelens/goCodeLensProvider.ts +++ b/packages/core/src/shared/codelens/goCodeLensProvider.ts @@ -126,6 +126,7 @@ function parseTypes(params: string): string[] { const paramParts = params.split(',') // Names of parameters must either be all present or all absent: https://golang.org/ref/spec#Function_types + // eslint-disable-next-line unicorn/no-array-for-each paramParts.forEach((element: string, i: number) => { const parts: string[] = element.trim().split(/\s+/) const type: string = parts.length > 1 ? parts[1].trim() : parts[0].trim() diff --git a/packages/core/src/shared/credentials/defaultCredentialSelectionDataProvider.ts b/packages/core/src/shared/credentials/defaultCredentialSelectionDataProvider.ts index 1683a14d598..08339136ce8 100644 --- a/packages/core/src/shared/credentials/defaultCredentialSelectionDataProvider.ts +++ b/packages/core/src/shared/credentials/defaultCredentialSelectionDataProvider.ts @@ -185,7 +185,7 @@ export class DefaultCredentialSelectionDataProvider implements CredentialSelecti const orderedProfiles: ProfileEntry[] = this.getOrderedProfiles() const selectionList: vscode.QuickPickItem[] = [] - orderedProfiles.forEach((profile) => { + for (const profile of orderedProfiles) { const selectionItem: vscode.QuickPickItem = { label: profile.profileName } if (profile.isRecentlyUsed) { @@ -193,7 +193,7 @@ export class DefaultCredentialSelectionDataProvider implements CredentialSelecti } selectionList.push(selectionItem) - }) + } return selectionList } @@ -209,10 +209,10 @@ export class DefaultCredentialSelectionDataProvider implements CredentialSelecti const orderedNames = new Set() // Add MRU entries first - mostRecentProfileNames.forEach((profileName) => { + for (const profileName of mostRecentProfileNames) { orderedProfiles.push({ profileName: profileName, isRecentlyUsed: true }) orderedNames.add(profileName) - }) + } // Add default if it hasn't been, and is an existing profile name const defaultProfileName = DefaultCredentialSelectionDataProvider.defaultCredentialsProfileName diff --git a/packages/core/src/shared/extensionUtilities.ts b/packages/core/src/shared/extensionUtilities.ts index 1b30c22bbc8..4d758182205 100644 --- a/packages/core/src/shared/extensionUtilities.ts +++ b/packages/core/src/shared/extensionUtilities.ts @@ -379,13 +379,13 @@ export class UserActivity implements vscode.Disposable { ) if (customEvents) { - customEvents.forEach((event) => + for (const event of customEvents) { this.register( event(() => { throttledEmit(event) }) ) - ) + } } else { this.registerAllEvents(throttledEmit) } @@ -409,13 +409,13 @@ export class UserActivity implements vscode.Disposable { vscode.window.onDidChangeTextEditorViewColumn, ] - activityEvents.forEach((event) => + for (const event of activityEvents) { this.register( event(() => { throttledEmit(event) }) ) - ) + } // // Events with special cases: @@ -478,6 +478,8 @@ export class UserActivity implements vscode.Disposable { } dispose() { - this.disposables.forEach((d) => d.dispose()) + for (const d of this.disposables) { + d.dispose() + } } } diff --git a/packages/core/src/shared/extensions/git.ts b/packages/core/src/shared/extensions/git.ts index 32f21a51df3..6a13a749480 100644 --- a/packages/core/src/shared/extensions/git.ts +++ b/packages/core/src/shared/extensions/git.ts @@ -209,7 +209,11 @@ export class GitExtension { public async getRemotes(): Promise { const api = await this.validateApi('git: api is disabled, returning empty array of remotes') const remotes: GitTypes.Remote[] = [] - api?.repositories.forEach((repo) => remotes.push(...repo.state.remotes)) + if (api) { + for (const repo of api.repositories) { + remotes.push(...repo.state.remotes) + } + } return remotes } @@ -237,7 +241,7 @@ export class GitExtension { .map((repo) => repo.state.remotes.filter((other) => other.fetchUrl === remote.fetchUrl)) .reduce((a, b) => a.concat(b), []) - api.repositories.forEach((repo) => + for (const repo of api.repositories) { branches.push( ...repo.state.refs.filter( (ref: GitTypes.Ref) => @@ -246,7 +250,7 @@ export class GitExtension { remotes.some((remote) => remote.name === ref.remote) ) ) - ) + } getLogger().debug(`git: found ${branches.length} branches from local repositories`) @@ -289,18 +293,21 @@ export class GitExtension { if (!api) { return config } else if (repository) { - ;(await repository.getConfigs()).forEach(({ key, value }) => (config[key] = value)) + for (const { key, value } of await repository.getConfigs()) { + config[key] = value + } } else { const { stdout } = await this.execFileAsync(api.git.path, ['config', '--list', `--global`]).catch((err) => { getLogger().verbose(`git: failed to read config: %s`, err) return { stdout: '' } }) - stdout + for (const [k, v] of stdout .toString() .split(/\r?\n/) - .map((l) => l.split('=')) - .forEach(([k, v]) => (config[k] = v)) + .map((l) => l.split('='))) { + config[k] = v + } } return config diff --git a/packages/core/src/shared/featureConfig.ts b/packages/core/src/shared/featureConfig.ts index 4097cfbab28..73eea42bbf3 100644 --- a/packages/core/src/shared/featureConfig.ts +++ b/packages/core/src/shared/featureConfig.ts @@ -106,7 +106,7 @@ export class FeatureConfigProvider { const response = await this.listFeatureEvaluations() // Overwrite feature configs from server response - response.featureEvaluations.forEach((evaluation) => { + for (const evaluation of response.featureEvaluations) { this.featureConfigs.set( evaluation.feature, new FeatureContext(evaluation.feature, evaluation.variation, evaluation.value) @@ -119,7 +119,7 @@ export class FeatureConfigProvider { featureValue: JSON.stringify(evaluation.value), }) }) - }) + } getLogger().info('AB Testing Cohort Assignments %O', response.featureEvaluations) const customizationArnOverride = this.featureConfigs.get(Features.customizationArnOverride)?.value @@ -133,14 +133,11 @@ export class FeatureConfigProvider { try { const items: Customization[] = [] const response = await client.listAvailableCustomizations() - response - .map( - (listAvailableCustomizationsResponse) => - listAvailableCustomizationsResponse.customizations - ) - .forEach((customizations) => { - items.push(...customizations) - }) + for (const customizations of response.map( + (listAvailableCustomizationsResponse) => listAvailableCustomizationsResponse.customizations + )) { + items.push(...customizations) + } availableCustomizations = items.map((c) => c.arn) } catch (e) { getLogger().debug('amazonq: Failed to list available customizations') diff --git a/packages/core/src/shared/multiStepInputFlowController.ts b/packages/core/src/shared/multiStepInputFlowController.ts index ce95ba1e480..96d66e4a2f2 100644 --- a/packages/core/src/shared/multiStepInputFlowController.ts +++ b/packages/core/src/shared/multiStepInputFlowController.ts @@ -91,7 +91,9 @@ export class MultiStepInputFlowController { this.current.show() }) } finally { - disposables.forEach((d) => d.dispose() as void) + for (const d of disposables) { + d.dispose() as void + } } } @@ -164,7 +166,9 @@ export class MultiStepInputFlowController { this.current.show() }) } finally { - disposables.forEach((d) => d.dispose() as void) + for (const d of disposables) { + d.dispose() as void + } } } diff --git a/packages/core/src/shared/regions/regionProvider.ts b/packages/core/src/shared/regions/regionProvider.ts index fed5919645d..c9c010a250a 100644 --- a/packages/core/src/shared/regions/regionProvider.ts +++ b/packages/core/src/shared/regions/regionProvider.ts @@ -128,26 +128,26 @@ export class RegionProvider { private loadFromEndpoints(endpoints: Endpoints) { this.regionData.clear() - endpoints.partitions.forEach((partition) => { - partition.regions.forEach((region) => + for (const partition of endpoints.partitions) { + for (const region of partition.regions) { this.regionData.set(region.id, { dnsSuffix: partition.dnsSuffix, partitionId: partition.id, region: region, serviceIds: [], }) - ) + } - partition.services.forEach((service) => { - service.endpoints.forEach((endpoint) => { + for (const service of partition.services) { + for (const endpoint of service.endpoints) { const regionData = this.regionData.get(endpoint.regionId) if (regionData) { regionData.serviceIds.push(service.id) } - }) - }) - }) + } + } + } this.onDidChangeEmitter.fire() } diff --git a/packages/core/src/shared/remoteSession.ts b/packages/core/src/shared/remoteSession.ts index 9f51c747de7..abe5d981a84 100644 --- a/packages/core/src/shared/remoteSession.ts +++ b/packages/core/src/shared/remoteSession.ts @@ -167,11 +167,11 @@ export async function handleMissingTool(tools: Err) { missing ) - tools.err().forEach((d) => { + for (const d of tools.err()) { if (d.reason) { getLogger().error(`codecatalyst: failed to get tool "${d.name}": ${d.reason}`) } - }) + } return Result.err( new ToolkitError(msg, { diff --git a/packages/core/src/shared/sam/debugger/csharpSamDebug.ts b/packages/core/src/shared/sam/debugger/csharpSamDebug.ts index 496c8514f07..d502d72bbdf 100644 --- a/packages/core/src/shared/sam/debugger/csharpSamDebug.ts +++ b/packages/core/src/shared/sam/debugger/csharpSamDebug.ts @@ -255,10 +255,10 @@ export async function makeDotnetDebugConfiguration( } // we could safely leave this entry in, but might as well give the user full control if they're specifying mappings delete config.sourceFileMap['/build'] - config.lambda.pathMappings.forEach((mapping) => { + for (const mapping of config.lambda.pathMappings) { // this looks weird because we're mapping the PDB path to the local workspace config.sourceFileMap[mapping.remoteRoot] = mapping.localRoot - }) + } } return { diff --git a/packages/core/src/shared/treeview/resourceTreeDataProvider.ts b/packages/core/src/shared/treeview/resourceTreeDataProvider.ts index e7c6f39cf8c..6920d18f7d6 100644 --- a/packages/core/src/shared/treeview/resourceTreeDataProvider.ts +++ b/packages/core/src/shared/treeview/resourceTreeDataProvider.ts @@ -101,7 +101,11 @@ export class ResourceTreeDataProvider implements vscode.TreeDataProvider this.clear(n)) + if (this.children.has(element.id)) { + for (const n of this.children.get(element.id)!) { + this.clear(n) + } + } } } @@ -144,7 +148,11 @@ export class ResourceTreeDataProvider implements vscode.TreeDataProvider this.clear(c)) + if (children) { + for (const c of children) { + this.clear(c) + } + } } private insert(id: string, resource: TreeNode): TreeNode { @@ -154,7 +162,11 @@ export class ResourceTreeDataProvider implements vscode.TreeDataProvider { - this.children.get(node.id)?.forEach((n) => this.clear(n)) + if (this.children.has(node.id)) { + for (const n of this.children.get(node.id)!) { + this.clear(n) + } + } this.children.delete(node.id) this.onDidChangeTreeDataEmitter.fire(node) }) diff --git a/packages/core/src/shared/typescriptLambdaHandlerSearch.ts b/packages/core/src/shared/typescriptLambdaHandlerSearch.ts index 57e17f58ec4..88e313ce776 100644 --- a/packages/core/src/shared/typescriptLambdaHandlerSearch.ts +++ b/packages/core/src/shared/typescriptLambdaHandlerSearch.ts @@ -164,7 +164,7 @@ export class TypescriptLambdaHandlerSearch implements LambdaHandlerSearch { private findCandidateHandlersInExportDecls(): RootlessLambdaHandlerCandidate[] { const handlers: RootlessLambdaHandlerCandidate[] = [] - this._candidateExportDeclarations.forEach((exportDeclaration) => { + for (const exportDeclaration of this._candidateExportDeclarations) { if (exportDeclaration.exportClause) { exportDeclaration.exportClause.forEachChild((clause) => { if (ts.isExportSpecifier(clause)) { @@ -180,7 +180,7 @@ export class TypescriptLambdaHandlerSearch implements LambdaHandlerSearch { } }) } - }) + } return handlers } @@ -191,7 +191,7 @@ export class TypescriptLambdaHandlerSearch implements LambdaHandlerSearch { private findCandidateHandlersInExportedFunctions(): RootlessLambdaHandlerCandidate[] { const handlers: RootlessLambdaHandlerCandidate[] = [] - this._candidateExportNodes.forEach((exportNode) => { + for (const exportNode of this._candidateExportNodes) { if ( ts.isFunctionLike(exportNode) && TypescriptLambdaHandlerSearch.isFunctionLambdaHandlerCandidate(exportNode) && @@ -218,7 +218,7 @@ export class TypescriptLambdaHandlerSearch implements LambdaHandlerSearch { } }) } - }) + } return handlers } diff --git a/packages/core/src/shared/ui/input.ts b/packages/core/src/shared/ui/input.ts index cd093007b03..4f252fdf8e5 100644 --- a/packages/core/src/shared/ui/input.ts +++ b/packages/core/src/shared/ui/input.ts @@ -127,7 +127,9 @@ export async function promptUser({ return response } finally { - disposables.forEach((d) => d.dispose() as void) + for (const d of disposables) { + d.dispose() as void + } inputBox.hide() } } diff --git a/packages/core/src/shared/ui/inputPrompter.ts b/packages/core/src/shared/ui/inputPrompter.ts index 48095abf964..ad2fa2ac2c8 100644 --- a/packages/core/src/shared/ui/inputPrompter.ts +++ b/packages/core/src/shared/ui/inputPrompter.ts @@ -115,7 +115,9 @@ export class InputBoxPrompter extends Prompter { * @param validate Validator function. */ public setValidation(validate: ValidateFn): void { - this.validateEvents.forEach((d) => d.dispose()) + for (const d of this.validateEvents) { + d.dispose() + } this.validateEvents = [] this.inputBox.onDidChangeValue( diff --git a/packages/core/src/shared/ui/picker.ts b/packages/core/src/shared/ui/picker.ts index ed0eacf35c6..6a801cdf6ab 100644 --- a/packages/core/src/shared/ui/picker.ts +++ b/packages/core/src/shared/ui/picker.ts @@ -135,7 +135,9 @@ export async function promptUser({ return response } finally { - disposables.forEach((d) => d.dispose() as void) + for (const d of disposables) { + d.dispose() as void + } picker.hide() } } diff --git a/packages/core/src/shared/ui/pickerPrompter.ts b/packages/core/src/shared/ui/pickerPrompter.ts index 6c9b1baaeb4..daa65246fed 100644 --- a/packages/core/src/shared/ui/pickerPrompter.ts +++ b/packages/core/src/shared/ui/pickerPrompter.ts @@ -248,7 +248,9 @@ function acceptItems(picker: DataQuickPick, resolve: (items: DataQuickPick return } - picker.selectedItems.forEach((item) => (item.onClick !== undefined ? item.onClick() : undefined)) + for (const item of picker.selectedItems) { + item.onClick !== undefined ? item.onClick() : undefined + } if (picker.selectedItems.some((item) => item.invalidSelection)) { return diff --git a/packages/core/src/shared/utilities/collectionUtils.ts b/packages/core/src/shared/utilities/collectionUtils.ts index 3776d7fac7b..f723e0096cc 100644 --- a/packages/core/src/shared/utilities/collectionUtils.ts +++ b/packages/core/src/shared/utilities/collectionUtils.ts @@ -346,13 +346,13 @@ export function inspect(obj: any, opt?: { depth: number }): string { export function stripUndefined>( obj: T ): asserts obj is { [P in keyof T]-?: NonNullable } { - Object.keys(obj).forEach((key) => { + for (const key of Object.keys(obj)) { if (obj[key] === undefined) { delete obj[key] } else if (typeof obj[key] === 'object') { stripUndefined(obj[key]) } - }) + } } export function isAsyncIterable(obj: any): obj is AsyncIterable { diff --git a/packages/core/src/shared/utilities/diffUtils.ts b/packages/core/src/shared/utilities/diffUtils.ts index 46292b07ef1..81e0af69000 100644 --- a/packages/core/src/shared/utilities/diffUtils.ts +++ b/packages/core/src/shared/utilities/diffUtils.ts @@ -136,6 +136,7 @@ export function getDiffCharsAndLines( ignoreNewlineAtEof: true, } as LinesOptions) + // eslint-disable-next-line unicorn/no-array-for-each diffs.forEach((part: Change) => { if (part.added) { addedChars += part.value.length diff --git a/packages/core/src/shared/utilities/editorUtilities.ts b/packages/core/src/shared/utilities/editorUtilities.ts index 2528dda1a76..4b70bef00c0 100644 --- a/packages/core/src/shared/utilities/editorUtilities.ts +++ b/packages/core/src/shared/utilities/editorUtilities.ts @@ -36,11 +36,11 @@ export async function getOpenFilesInWindow( try { const tabArrays = vscode.window.tabGroups.all - tabArrays.forEach((tabArray) => { - tabArray.tabs.forEach((tab) => { + for (const tabArray of tabArrays) { + for (const tab of tabArray.tabs) { filesOpenedInEditor.push((tab.input as any).uri.fsPath) - }) - }) + } + } } catch (e) { // Older versions of VSC do not have the tab API } diff --git a/packages/core/src/shared/utilities/streamUtilities.ts b/packages/core/src/shared/utilities/streamUtilities.ts index 5d734ac72a1..0b7d74fca5f 100644 --- a/packages/core/src/shared/utilities/streamUtilities.ts +++ b/packages/core/src/shared/utilities/streamUtilities.ts @@ -44,7 +44,9 @@ class BufferWriter { public write(chunk: Buffer) { const buffer = this.buffer if (Buffer.isBuffer(buffer)) { - chunk.forEach((byte) => (this.offset = buffer.writeUInt8(byte, this.offset))) + for (const byte of chunk) { + this.offset = buffer.writeUInt8(byte, this.offset) + } } else { buffer.push(...chunk) this.offset += chunk.length diff --git a/packages/core/src/shared/vscode/commands2.ts b/packages/core/src/shared/vscode/commands2.ts index 527862faebb..342acfdfbac 100644 --- a/packages/core/src/shared/vscode/commands2.ts +++ b/packages/core/src/shared/vscode/commands2.ts @@ -523,7 +523,7 @@ function handleBadCompositeKey(data: { id: string; args: any[]; compositeKey: Co return // nothing to do since no key } - Object.entries(compositeKey).forEach(([index, field]) => { + for (const [index, field] of Object.entries(compositeKey)) { const indexAsInt = parseInt(index) const arg = args[indexAsInt] if (field === 'source' && arg === undefined) { @@ -540,7 +540,7 @@ function handleBadCompositeKey(data: { id: string; args: any[]; compositeKey: Co getLogger().error('Commands/Telemetry: "%s" executed with invalid "source" type: "%O"', id, args) args[indexAsInt] = unsetSource } - }) + } } /** @@ -555,11 +555,11 @@ function findFieldsToAddToMetric(args: any[], compositeKey: CompositeKey): { [fi const sortedIndexesWithValue = indexesWithValue.sort((a, b) => a - b) const result: { [field in MetricField]?: any } = {} - sortedIndexesWithValue.forEach((i) => { + for (const i of sortedIndexesWithValue) { const fieldName: MetricField = compositeKey[i] const fieldValue = args[i] result[fieldName] = fieldValue - }) + } return result } @@ -639,7 +639,9 @@ export class TelemetryDebounceInfo { }) const hasher = crypto.createHash('sha256') - hashableObjects.forEach((o) => hasher.update(o)) + for (const o of hashableObjects) { + hasher.update(o) + } return hasher.digest('hex') } } diff --git a/packages/core/src/shared/wizards/wizard.ts b/packages/core/src/shared/wizards/wizard.ts index 05d45584802..f472e982813 100644 --- a/packages/core/src/shared/wizards/wizard.ts +++ b/packages/core/src/shared/wizards/wizard.ts @@ -154,12 +154,12 @@ export class Wizard>> { public async init?(): Promise private assignSteps(): void { - this._form.properties.forEach((prop) => { + for (const prop of this._form.properties) { const provider = this._form.getPrompterProvider(prop) if (!this.boundSteps.has(prop) && provider !== undefined) { this.boundSteps.set(prop, this.createBoundStep(prop, provider)) } - }) + } } public async run(): Promise { @@ -170,9 +170,9 @@ export class Wizard>> { } this.assignSteps() - this.resolveNextSteps((this.options.initState ?? {}) as TState).forEach((step) => + for (const step of this.resolveNextSteps((this.options.initState ?? {}) as TState)) { this.stateController.addStep(step) - ) + } const outputState = await this.stateController.run() @@ -238,14 +238,14 @@ export class Wizard>> { protected resolveNextSteps(state: TState): Branch { const nextSteps: Branch = [] const defaultState = this._form.applyDefaults(state) - this.boundSteps.forEach((step, targetProp) => { + for (const [targetProp, step] of this.boundSteps.entries()) { if ( this._form.canShowProperty(targetProp, state, defaultState) && !this.stateController.containsStep(step) ) { nextSteps.push(step) } - }) + } return nextSteps } diff --git a/packages/core/src/shared/wizards/wizardForm.ts b/packages/core/src/shared/wizards/wizardForm.ts index 7d3a55a2635..e4933bb1acf 100644 --- a/packages/core/src/shared/wizards/wizardForm.ts +++ b/packages/core/src/shared/wizards/wizardForm.ts @@ -110,7 +110,7 @@ export class WizardForm>> { public applyDefaults(state: TState): TState { const defaultState = _.cloneDeep(state) - this.formData.forEach((opt, targetProp) => { + for (const [targetProp, opt] of this.formData.entries()) { const current = _.get(state, targetProp) if (!isAssigned(current) && opt.setDefault !== undefined && !checkParent(targetProp, state, opt)) { @@ -119,7 +119,7 @@ export class WizardForm>> { _.set(defaultState, targetProp, defaultValue) } } - }) + } return defaultState } @@ -212,10 +212,10 @@ export class WizardForm>> { private createApplyFormMethod>(prop: string): ApplyBoundForm { return (form: WizardForm, options?: ContextOptions) => { - form.formData.forEach((element, key) => { + for (const [key, element] of form.formData.entries()) { // TODO: use an assert here to ensure that no elements are rewritten this.applyElement(`${prop}.${key}`, this.convertElement(prop, element, options)) - }) + } } } diff --git a/packages/core/src/ssmDocument/commands/openDocumentItem.ts b/packages/core/src/ssmDocument/commands/openDocumentItem.ts index c794e56ff71..9b6793b76d0 100644 --- a/packages/core/src/ssmDocument/commands/openDocumentItem.ts +++ b/packages/core/src/ssmDocument/commands/openDocumentItem.ts @@ -68,14 +68,14 @@ export async function openDocumentItemYaml(node: DocumentItemNode, awsContext: A async function promptUserforDocumentVersion(versions: SSM.Types.DocumentVersionInfo[]): Promise { // Prompt user to pick document version const quickPickItems: vscode.QuickPickItem[] = [] - versions.forEach((version) => { + for (const version of versions) { if (version.DocumentVersion) { quickPickItems.push({ label: version.DocumentVersion, description: `${version.IsDefaultVersion ? 'Default' : ''}`, }) } - }) + } if (quickPickItems.length > 1) { const versionPick = picker.createQuickPick({ diff --git a/packages/core/src/ssmDocument/commands/updateDocumentVersion.ts b/packages/core/src/ssmDocument/commands/updateDocumentVersion.ts index 576f38a3e75..92e788bcb89 100644 --- a/packages/core/src/ssmDocument/commands/updateDocumentVersion.ts +++ b/packages/core/src/ssmDocument/commands/updateDocumentVersion.ts @@ -79,14 +79,14 @@ export async function updateDocumentVersion(node: DocumentItemNodeWriteable, aws async function promptUserforDocumentVersion(versions: SSM.Types.DocumentVersionInfo[]): Promise { // Prompt user to pick document version const quickPickItems: vscode.QuickPickItem[] = [] - versions.forEach((version) => { + for (const version of versions) { if (version.DocumentVersion) { quickPickItems.push({ label: version.DocumentVersion, description: `${version.IsDefaultVersion ? 'Default' : ''}`, }) } - }) + } if (quickPickItems.length > 1) { const versionPick = picker.createQuickPick({ diff --git a/packages/core/src/ssmDocument/explorer/registryItemNode.ts b/packages/core/src/ssmDocument/explorer/registryItemNode.ts index c4eeac02a9c..d5ca928f88f 100644 --- a/packages/core/src/ssmDocument/explorer/registryItemNode.ts +++ b/packages/core/src/ssmDocument/explorer/registryItemNode.ts @@ -98,9 +98,9 @@ export class RegistryItemNode extends AWSTreeNodeBase { const documents = new Map() const docs = await this.getDocumentByOwner(this.client) - docs.forEach((doc) => { + for (const doc of docs) { documents.set(doc.Name!, doc) - }) + } if (this.registryName === userRegistryName) { updateInPlace( diff --git a/packages/core/src/stepFunctions/asl/aslServer.ts b/packages/core/src/stepFunctions/asl/aslServer.ts index 6ec961ba9d1..8da1363969c 100644 --- a/packages/core/src/stepFunctions/asl/aslServer.ts +++ b/packages/core/src/stepFunctions/asl/aslServer.ts @@ -317,12 +317,13 @@ function validateTextDocument(textDocument: TextDocument, callback?: (diagnostic connection.onDidChangeWatchedFiles((change) => { // Monitored files have changed in VSCode let hasChanges = false - change.changes.forEach((c) => { + for (const c of change.changes) { if (getLanguageService('asl').resetSchema(c.uri)) { hasChanges = true } - }) + } if (hasChanges) { + // eslint-disable-next-line unicorn/no-array-for-each documents.all().forEach(triggerValidation) } }) diff --git a/packages/core/src/stepFunctions/commands/visualizeStateMachine/aslVisualization.ts b/packages/core/src/stepFunctions/commands/visualizeStateMachine/aslVisualization.ts index 301bd493834..56467343d15 100644 --- a/packages/core/src/stepFunctions/commands/visualizeStateMachine/aslVisualization.ts +++ b/packages/core/src/stepFunctions/commands/visualizeStateMachine/aslVisualization.ts @@ -188,9 +188,9 @@ export class AslVisualization { this.isPanelDisposed = true debouncedUpdate.cancel() this.onVisualizationDisposeEmitter.fire() - this.disposables.forEach((disposable) => { + for (const disposable of this.disposables) { disposable.dispose() - }) + } this.onVisualizationDisposeEmitter.dispose() } diff --git a/packages/core/src/test/amazonqFeatureDev/controllers/chat/controller.test.ts b/packages/core/src/test/amazonqFeatureDev/controllers/chat/controller.test.ts index 4c2639a553f..44cfe17eb1f 100644 --- a/packages/core/src/test/amazonqFeatureDev/controllers/chat/controller.test.ts +++ b/packages/core/src/test/amazonqFeatureDev/controllers/chat/controller.test.ts @@ -553,11 +553,11 @@ describe('Controller', () => { ) }) - runs.forEach(({ name, error }) => { + for (const { name, error } of runs) { it(`sends failure operation telemetry on ${name}`, async () => { await verifyException(error) }) - }) + } }) describe('processErrorChatMessage', function () { @@ -639,11 +639,11 @@ describe('Controller', () => { } } - runs.forEach((run) => { + for (const run of runs) { it(`should handle ${run.name}`, async function () { await verifyException(run.error) }) - }) + } }) }) diff --git a/packages/core/src/test/awsService/accessanalyzer/iamPolicyChecks.test.ts b/packages/core/src/test/awsService/accessanalyzer/iamPolicyChecks.test.ts index 536ec3e224c..37c6d0fe649 100644 --- a/packages/core/src/test/awsService/accessanalyzer/iamPolicyChecks.test.ts +++ b/packages/core/src/test/awsService/accessanalyzer/iamPolicyChecks.test.ts @@ -695,14 +695,14 @@ describe('customChecks', function () { fakePolicyChecksWebview.pushCustomCheckDiagnostic(diagnostics, finding, isBlocking) assert.strictEqual(diagnostics.length, 2) // One diagnostic per reason - diagnostics.forEach((diagnostic, index) => { + for (const [index, diagnostic] of diagnostics.entries()) { assert.deepStrictEqual(diagnostic.range, new vscode.Range(0, 0, 0, 0)) assert.strictEqual(diagnostic.severity, vscode.DiagnosticSeverity.Error) assert.strictEqual( diagnostic.message, `${finding.findingType}: Test message with reference document - Resource name: ${finding.resourceName}, Policy name: ${finding.policyName} - Reason ${index + 1}` ) - }) + } assert(customPolicyDiagnosticSetStub.calledOnce) }) @@ -722,14 +722,14 @@ describe('customChecks', function () { fakePolicyChecksWebview.pushCustomCheckDiagnostic(diagnostics, finding, isBlocking) assert.strictEqual(diagnostics.length, 2) // One diagnostic per reason - diagnostics.forEach((diagnostic, index) => { + for (const [index, diagnostic] of diagnostics.entries()) { assert.deepStrictEqual(diagnostic.range, new vscode.Range(0, 0, 0, 0)) assert.strictEqual(diagnostic.severity, vscode.DiagnosticSeverity.Warning) assert.strictEqual( diagnostic.message, `WARNING: Another test message - Resource name: ${finding.resourceName}, Policy name: ${finding.policyName} - Reason ${index === 0 ? 'A' : 'B'}` ) - }) + } assert(customPolicyDiagnosticSetStub.calledOnce) }) diff --git a/packages/core/src/test/awsService/apigateway/explorer/apiGatewayNodes.test.ts b/packages/core/src/test/awsService/apigateway/explorer/apiGatewayNodes.test.ts index 81b79b6587d..cf5bf5f648b 100644 --- a/packages/core/src/test/awsService/apigateway/explorer/apiGatewayNodes.test.ts +++ b/packages/core/src/test/awsService/apigateway/explorer/apiGatewayNodes.test.ts @@ -65,7 +65,9 @@ describe('ApiGatewayNode', function () { assert.strictEqual(childNodes.length, apiNames.length, 'Unexpected child count') - childNodes.forEach((node) => assert.ok(node instanceof RestApiNode, 'Expected child node to be RestApiNode')) + for (const node of childNodes) { + assert.ok(node instanceof RestApiNode, 'Expected child node to be RestApiNode') + } }) it('sorts child nodes', async function () { diff --git a/packages/core/src/test/awsService/cloudWatchLogs/commands/tailLogGroup.test.ts b/packages/core/src/test/awsService/cloudWatchLogs/commands/tailLogGroup.test.ts index 44b18f8ea12..bd4b3b4b66b 100644 --- a/packages/core/src/test/awsService/cloudWatchLogs/commands/tailLogGroup.test.ts +++ b/packages/core/src/test/awsService/cloudWatchLogs/commands/tailLogGroup.test.ts @@ -104,7 +104,9 @@ describe('TailLogGroup', function () { // registry is asserted to have only one entry, so this is assumed to be the session that was // started in this test. let sessionUri: vscode.Uri | undefined - registry.forEach((session) => (sessionUri = session.uri)) + for (const [_, session] of registry) { + sessionUri = session.uri + } if (sessionUri === undefined) { throw Error } @@ -127,9 +129,9 @@ describe('TailLogGroup', function () { // Test that closing all tabs the session's document is open in will cause the session to close let tabs: vscode.Tab[] = [] - window.tabGroups.all.forEach((tabGroup) => { + for (const tabGroup of window.tabGroups.all) { tabs = tabs.concat(getLiveTailSessionTabsFromTabGroup(tabGroup, sessionUri!)) - }) + } await Promise.all(tabs.map((tab) => window.tabGroups.close(tab))) // Before the test ends, signal the abort controller, interrupting the mock response stream. This diff --git a/packages/core/src/test/awsService/cloudWatchLogs/explorer/cloudWatchLogsNode.test.ts b/packages/core/src/test/awsService/cloudWatchLogs/explorer/cloudWatchLogsNode.test.ts index 0bffe4a72f9..ac2ebffded8 100644 --- a/packages/core/src/test/awsService/cloudWatchLogs/explorer/cloudWatchLogsNode.test.ts +++ b/packages/core/src/test/awsService/cloudWatchLogs/explorer/cloudWatchLogsNode.test.ts @@ -49,19 +49,21 @@ describe('CloudWatchLogsNode', function () { assert.strictEqual(childNodes.length, logGroupNames.length, 'Unexpected child count') - childNodes.forEach((node) => assert.ok(node instanceof LogGroupNode, 'Expected child node to be LogGroupNode')) + for (const node of childNodes) { + assert.ok(node instanceof LogGroupNode, 'Expected child node to be LogGroupNode') + } }) it('has child nodes with CloudWatch Log contextValue', async function () { const childNodes = await testNode.getChildren() - childNodes.forEach((node) => + for (const node of childNodes) { assert.strictEqual( node.contextValue, contextValueCloudwatchLog, 'expected the node to have a CloudWatch Log contextValue' ) - ) + } }) it('sorts child nodes', async function () { diff --git a/packages/core/src/test/awsService/ec2/explorer/ec2ParentNode.test.ts b/packages/core/src/test/awsService/ec2/explorer/ec2ParentNode.test.ts index 67d801a4ea4..274272c3729 100644 --- a/packages/core/src/test/awsService/ec2/explorer/ec2ParentNode.test.ts +++ b/packages/core/src/test/awsService/ec2/explorer/ec2ParentNode.test.ts @@ -93,9 +93,10 @@ describe('ec2ParentNode', function () { assert.strictEqual(childNodes.length, instances.length, 'Unexpected child count') - childNodes.forEach((node) => + for (const node of childNodes) { assert.ok(node instanceof Ec2InstanceNode, 'Expected child node to be Ec2InstanceNode') - ) + } + getInstanceStub.restore() }) diff --git a/packages/core/src/test/awsService/ecr/utils.test.ts b/packages/core/src/test/awsService/ecr/utils.test.ts index 22c5cf2f8dc..6d0feee0db9 100644 --- a/packages/core/src/test/awsService/ecr/utils.test.ts +++ b/packages/core/src/test/awsService/ecr/utils.test.ts @@ -21,9 +21,9 @@ describe('createRepositoryCommand', function () { }) it('Validates repository name against large regex the service uses', function () { - ;['abc--a', 'abc//a', 'abc__a', 'abc-', 'abc/', 'abc_'].forEach((item) => + for (const item of ['abc--a', 'abc//a', 'abc__a', 'abc-', 'abc/', 'abc_']) { assert.strictEqual(validateRepositoryName(item), 'Invalid repository name') - ) + } }) it('Allows lowercase names with slashes, underscores, and dashes', function () { diff --git a/packages/core/src/test/awsService/s3/commands/createFolder.test.ts b/packages/core/src/test/awsService/s3/commands/createFolder.test.ts index f64ddaf1f2a..36b13e861aa 100644 --- a/packages/core/src/test/awsService/s3/commands/createFolder.test.ts +++ b/packages/core/src/test/awsService/s3/commands/createFolder.test.ts @@ -75,7 +75,7 @@ describe('createFolderCommand', function () { sandbox.assert.calledWith(spyExecuteCommand, 'aws.refreshAwsExplorerNode', node) }) - invalidFolderNames.forEach((invalid) => { + for (const invalid of invalidFolderNames) { it(`warns '${invalid.error}' when folder name is '${invalid.folderName}'`, async () => { getTestWindow().onDidShowInputBox((input) => { input.acceptValue(invalid.folderName) @@ -84,5 +84,5 @@ describe('createFolderCommand', function () { }) await assert.rejects(() => createFolderCommand(node)) }) - }) + } }) diff --git a/packages/core/src/test/awsService/s3/util/validateBucketName.test.ts b/packages/core/src/test/awsService/s3/util/validateBucketName.test.ts index ec07224c1d8..f1331f06633 100644 --- a/packages/core/src/test/awsService/s3/util/validateBucketName.test.ts +++ b/packages/core/src/test/awsService/s3/util/validateBucketName.test.ts @@ -26,13 +26,13 @@ describe('validateBucketName', function () { assert.strictEqual(validateBucketName('v.4.l1d.buc.ket-n4.m3'), undefined) }) - invalidErrors.forEach((invalid) => { + for (const invalid of invalidErrors) { describe(invalid.error, () => { - invalid.bucketNames.forEach((bucketName) => { + for (const bucketName of invalid.bucketNames) { it(bucketName, () => { assert.strictEqual(validateBucketName(bucketName), invalid.error) }) - }) + } }) - }) + } }) diff --git a/packages/core/src/test/codewhisperer/commands/transformByQ.test.ts b/packages/core/src/test/codewhisperer/commands/transformByQ.test.ts index 016ebf1682a..0e1e326b6c5 100644 --- a/packages/core/src/test/codewhisperer/commands/transformByQ.test.ts +++ b/packages/core/src/test/codewhisperer/commands/transformByQ.test.ts @@ -372,9 +372,9 @@ describe('transformByQ', function () { // Each dependency version folder contains each expected file, thus we multiply const expectedNumberOfDependencyFiles = m2Folders.length * expectedFilesAfterClean.length assert.strictEqual(expectedNumberOfDependencyFiles, dependenciesToUpload.length) - dependenciesToUpload.forEach((dependency) => { + for (const dependency of dependenciesToUpload) { assert(expectedFilesAfterClean.includes(dependency.name)) - }) + } }) }) @@ -456,9 +456,9 @@ describe('transformByQ', function () { assert.strictEqual(transformByQState.getTargetDB(), DB.AURORA_POSTGRESQL) assert.strictEqual(transformByQState.getSourceServerName(), 'sample.rds.amazonaws.com') const expectedSchemaOptions = ['SCHEMA1', 'SCHEMA2', 'SCHEMA3'] - expectedSchemaOptions.forEach((schema) => { + for (const schema of expectedSchemaOptions) { assert(transformByQState.getSchemaOptions().has(schema)) - }) + } }) it(`WHEN validateMetadataFile on .sct file with unsupported source DB THEN fails validation`, async function () { diff --git a/packages/core/src/test/codewhispererChat/editor/codelens.test.ts b/packages/core/src/test/codewhispererChat/editor/codelens.test.ts index 855985218da..52243027ebf 100644 --- a/packages/core/src/test/codewhispererChat/editor/codelens.test.ts +++ b/packages/core/src/test/codewhispererChat/editor/codelens.test.ts @@ -163,6 +163,7 @@ describe('TryChatCodeLensProvider', () => { TryMoreExState.id, ] + // eslint-disable-next-line unicorn/no-array-for-each lineAnnotationControllerStates.forEach((id: string) => { it(`id - ${id}`, async () => { await globals.globalState.update(inlinehintKey, id) diff --git a/packages/core/src/test/credentials/provider/sharedCredentialsProvider.test.ts b/packages/core/src/test/credentials/provider/sharedCredentialsProvider.test.ts index e76472f83e1..8e266cc11d3 100644 --- a/packages/core/src/test/credentials/provider/sharedCredentialsProvider.test.ts +++ b/packages/core/src/test/credentials/provider/sharedCredentialsProvider.test.ts @@ -463,5 +463,7 @@ describe('SharedCredentialsProvider', async function () { function assertSubstringsInText(text: string | undefined, ...substrings: string[]) { assert.ok(text) - substrings.forEach((substring) => assert.notStrictEqual(text!.indexOf(substring), -1)) + for (const substring of substrings) { + assert.notStrictEqual(text!.indexOf(substring), -1) + } } diff --git a/packages/core/src/test/credentials/sso/ssoAccessTokenProvider.test.ts b/packages/core/src/test/credentials/sso/ssoAccessTokenProvider.test.ts index b662556e0aa..f552e8d08c8 100644 --- a/packages/core/src/test/credentials/sso/ssoAccessTokenProvider.test.ts +++ b/packages/core/src/test/credentials/sso/ssoAccessTokenProvider.test.ts @@ -226,6 +226,7 @@ describe('SsoAccessTokenProvider', function () { // combinations of args for createToken() const args: CreateTokenArgs[] = [{ isReAuth: true }, { isReAuth: false }] + // eslint-disable-next-line unicorn/no-array-for-each args.forEach((args) => { it(`runs the full SSO flow with args: ${JSON.stringify(args)}`, async function () { const { token, registration } = setupFlow() diff --git a/packages/core/src/test/credentials/utils.test.ts b/packages/core/src/test/credentials/utils.test.ts index a90a3fc7bcf..7fc06aef897 100644 --- a/packages/core/src/test/credentials/utils.test.ts +++ b/packages/core/src/test/credentials/utils.test.ts @@ -106,13 +106,13 @@ describe('connection exists funcs', function () { }) const allCases = [...anyCases, ...cwIdcCases] - allCases.forEach((args) => { + for (const args of allCases) { it(`ssoExists() returns '${args.expected}' when kind '${args.kind}' given [${args.connections .map((c) => c.label) .join(', ')}]`, async function () { assert.strictEqual(await hasSso(args.kind, async () => args.connections), args.expected) }) - }) + } }) describe('builderIdExists()', function () { @@ -136,13 +136,13 @@ describe('connection exists funcs', function () { const allCases = [...cwBuilderIdCases, ...ccBuilderIdCases] - allCases.forEach((args) => { + for (const args of allCases) { it(`builderIdExists() returns '${args.expected}' when kind '${args.kind}' given [${args.connections .map((c) => c.label) .join(', ')}]`, async function () { assert.strictEqual(await hasBuilderId(args.kind, async () => args.connections), args.expected) }) - }) + } }) describe('credentialExists()', function () { @@ -153,7 +153,7 @@ describe('connection exists funcs', function () { [allConnections.filter((c) => c !== iamConnection), false], ] - cases.forEach((args) => { + for (const args of cases) { it(`credentialExists() returns '${args[1]}' given [${args[0] .map((c) => c.label) .join(', ')}]`, async function () { @@ -162,6 +162,6 @@ describe('connection exists funcs', function () { assert.strictEqual(await hasIamCredentials(async () => connections), expected) }) - }) + } }) }) diff --git a/packages/core/src/test/dynamicResources/explorer/moreResourcesNode.test.ts b/packages/core/src/test/dynamicResources/explorer/moreResourcesNode.test.ts index 5e6b3c380b8..4719c0e87db 100644 --- a/packages/core/src/test/dynamicResources/explorer/moreResourcesNode.test.ts +++ b/packages/core/src/test/dynamicResources/explorer/moreResourcesNode.test.ts @@ -61,21 +61,21 @@ describe('ResourcesNode', function () { assert.strictEqual(childNodes.length, resourceTypes.length, 'Unexpected child count') - childNodes.forEach((node) => + for (const node of childNodes) { assert.ok(node instanceof ResourceTypeNode, 'Expected child node to be ResourceTypeNode') - ) + } }) it('has child nodes with ResourceTypeNode contextValue', async function () { const childNodes = await testNode.getChildren() - childNodes.forEach((node) => + for (const node of childNodes) { assert.strictEqual( node.contextValue?.endsWith('ResourceTypeNode'), true, 'expected the node to have a resourceTypeNode contextValue' ) - ) + } }) it('sorts child nodes', async function () { diff --git a/packages/core/src/test/dynamicResources/explorer/resourceTypeNode.test.ts b/packages/core/src/test/dynamicResources/explorer/resourceTypeNode.test.ts index 7312f519339..2c69cb7a9c0 100644 --- a/packages/core/src/test/dynamicResources/explorer/resourceTypeNode.test.ts +++ b/packages/core/src/test/dynamicResources/explorer/resourceTypeNode.test.ts @@ -57,45 +57,47 @@ describe('ResourceTypeNode', function () { assert.strictEqual(childNodes.length, resourceIdentifiers.length, 'Unexpected child count') - childNodes.forEach((node) => assert.ok(node instanceof ResourceNode, 'Expected child node to be ResourceNode')) + for (const node of childNodes) { + assert.ok(node instanceof ResourceNode, 'Expected child node to be ResourceNode') + } }) it('has child nodes with all operations contextValue when unknown operations', async function () { const childNodes = await testNode.getChildren() - childNodes.forEach((node) => + for (const node of childNodes) { assert.strictEqual( node.contextValue, 'CreatableDeletableUpdatableResourceNode', 'expected the node to have a ResourceNode contextValue' ) - ) + } }) it('has child nodes with ResourceNode contextValue including single supported operation', async function () { testNode = generateTestNode(cloudControl, ['CREATE']) const childNodes = await testNode.getChildren() - childNodes.forEach((node) => + for (const node of childNodes) { assert.strictEqual( node.contextValue, 'CreatableResourceNode', 'expected the node to have a CreatableResourceNode contextValue' ) - ) + } }) it('has child nodes with ResourceNode contextValue including multiple supported operations', async function () { testNode = generateTestNode(cloudControl, ['CREATE', 'DELETE']) const childNodes = await testNode.getChildren() - childNodes.forEach((node) => + for (const node of childNodes) { assert.strictEqual( node.contextValue, 'CreatableDeletableResourceNode', 'expected the node to have a CreatableDeletableResourceNode contextValue' ) - ) + } }) it('sorts child nodes', async function () { diff --git a/packages/core/src/test/eventSchemas/model/schemaCodeGenUtils.test.ts b/packages/core/src/test/eventSchemas/model/schemaCodeGenUtils.test.ts index 60e39480c79..619bb24b717 100644 --- a/packages/core/src/test/eventSchemas/model/schemaCodeGenUtils.test.ts +++ b/packages/core/src/test/eventSchemas/model/schemaCodeGenUtils.test.ts @@ -56,13 +56,13 @@ describe('SchemaCodeGenUtils', async function () { ] describe('buildSchemaPackageName', async function () { - testScenarios.forEach((test) => { + for (const test of testScenarios) { it(test.scenario, async () => { const codeGen = new SchemaCodeGenUtils() const result = codeGen.buildSchemaPackageName(test.input) assert.strictEqual(result, test.expectedResult, 'Invalid package name returned') }) - }) + } }) }) diff --git a/packages/core/src/test/feedback/commands/submitFeedbackListener.test.ts b/packages/core/src/test/feedback/commands/submitFeedbackListener.test.ts index a4a88e1703a..176e12974ea 100644 --- a/packages/core/src/test/feedback/commands/submitFeedbackListener.test.ts +++ b/packages/core/src/test/feedback/commands/submitFeedbackListener.test.ts @@ -25,7 +25,7 @@ describe('submitFeedbackListener', function () { { productName: 'Amazon Q', expectedError: 'Expected failure' }, { productName: 'AWS Toolkit', expectedError: 'Expected failure' }, ] - testCases.forEach(({ productName, expectedError }) => { + for (const { productName, expectedError } of testCases) { it(`submits ${productName} feedback, disposes, and shows message on success`, async function () { const postStub = sinon.stub() mockTelemetry.postFeedback = postStub @@ -47,5 +47,5 @@ describe('submitFeedbackListener', function () { const result = await webview.submit(message) assert.strictEqual(result, expectedError) }) - }) + } }) diff --git a/packages/core/src/test/lambda/commands/listSamResources.test.ts b/packages/core/src/test/lambda/commands/listSamResources.test.ts index 37a7d227f10..428a04316eb 100644 --- a/packages/core/src/test/lambda/commands/listSamResources.test.ts +++ b/packages/core/src/test/lambda/commands/listSamResources.test.ts @@ -62,6 +62,7 @@ describe('listSamResources', () => { { name: 'stringify array', value: '[]' }, { name: 'array object', value: [] }, ] + // eslint-disable-next-line unicorn/no-array-for-each testcases.forEach(async ({ name, value }) => { it(`returns empty array given SAM CLI return ${name} given any issue`, async () => { runSamCliListResourceStub.resolves(value) diff --git a/packages/core/src/test/lambda/explorer/cloudFormationNodes.test.ts b/packages/core/src/test/lambda/explorer/cloudFormationNodes.test.ts index bcc65e10781..2eac7d75ecc 100644 --- a/packages/core/src/test/lambda/explorer/cloudFormationNodes.test.ts +++ b/packages/core/src/test/lambda/explorer/cloudFormationNodes.test.ts @@ -107,9 +107,9 @@ describe('CloudFormationStackNode', function () { assert.strictEqual(childNodes.length, 2, 'Unexpected child count') - childNodes.forEach((node) => + for (const node of childNodes) { assert.ok(node instanceof LambdaFunctionNode, 'Expected child node to be LambdaFunctionNode') - ) + } }) it('has child nodes with CloudFormation contextValue', async function () { @@ -121,13 +121,13 @@ describe('CloudFormationStackNode', function () { const node = generateTestNode({ lambdaClient, cloudFormationClient }) const childNodes = await node.getChildren() - childNodes.forEach((node) => + for (const node of childNodes) { assert.strictEqual( node.contextValue, contextValueCloudformationLambdaFunction, 'expected the node to have a CloudFormation contextValue' ) - ) + } }) it('only includes functions which are in a CloudFormation stack', async function () { @@ -163,9 +163,9 @@ describe('CloudFormationNode', function () { const cloudFormationNode = new CloudFormationNode(regionCode, client) const children = await cloudFormationNode.getChildren() - children.forEach((node) => + for (const node of children) { assert.ok(node instanceof CloudFormationStackNode, 'Expected child node to be CloudFormationStackNode') - ) + } }) it('has sorted child nodes', async function () { diff --git a/packages/core/src/test/lambda/explorer/lambdaNodes.test.ts b/packages/core/src/test/lambda/explorer/lambdaNodes.test.ts index c77230a0f49..ba494680911 100644 --- a/packages/core/src/test/lambda/explorer/lambdaNodes.test.ts +++ b/packages/core/src/test/lambda/explorer/lambdaNodes.test.ts @@ -39,21 +39,21 @@ describe('LambdaNode', function () { assert.strictEqual(childNodes.length, 2, 'Unexpected child count') - childNodes.forEach((node) => + for (const node of childNodes) { assert.ok(node instanceof LambdaFunctionNode, 'Expected child node to be LambdaFunctionNode') - ) + } }) it('has child nodes with Lambda Function contextValue', async function () { const childNodes = await createNode('f1', 'f2').getChildren() - childNodes.forEach((node) => + for (const node of childNodes) { assert.strictEqual( node.contextValue, contextValueLambdaFunction, 'expected the node to have a CloudFormation contextValue' ) - ) + } }) it('sorts child nodes', async function () { diff --git a/packages/core/src/test/lambda/models/samLambdaRuntime.test.ts b/packages/core/src/test/lambda/models/samLambdaRuntime.test.ts index 0bfe1acefe0..f47cc3fe06b 100644 --- a/packages/core/src/test/lambda/models/samLambdaRuntime.test.ts +++ b/packages/core/src/test/lambda/models/samLambdaRuntime.test.ts @@ -27,7 +27,7 @@ describe('compareSamLambdaRuntime', async function () { { lowerRuntime: 'nodejs14.x (Image)', higherRuntime: 'nodejs16.x' }, ] - scenarios.forEach((scenario) => { + for (const scenario of scenarios) { it(`${scenario.lowerRuntime} < ${scenario.higherRuntime}`, () => { assert.ok(compareSamLambdaRuntime(scenario.lowerRuntime, scenario.higherRuntime) < 0) }) @@ -35,14 +35,14 @@ describe('compareSamLambdaRuntime', async function () { it(`${scenario.higherRuntime} > ${scenario.lowerRuntime}`, () => { assert.ok(compareSamLambdaRuntime(scenario.higherRuntime, scenario.lowerRuntime) > 0) }) - }) + } }) describe('getDependencyManager', function () { it('all runtimes are handled', function () { - samZipLambdaRuntimes.forEach((runtime) => { + for (const runtime of samZipLambdaRuntimes) { assert.ok(getDependencyManager(runtime)) - }) + } }) it('throws on deprecated runtimes', function () { assert.throws(() => getDependencyManager('nodejs')) @@ -57,9 +57,9 @@ describe('getFamily', function () { assert.strictEqual(getFamily('foo'), RuntimeFamily.Unknown) }) it('handles all known runtimes', function () { - samZipLambdaRuntimes.forEach((runtime) => { + for (const runtime of samZipLambdaRuntimes) { assert.notStrictEqual(getFamily(runtime), RuntimeFamily.Unknown) - }) + } }) it('throws on deprecated runtimes', function () { assert.throws(() => getFamily('nodejs')) @@ -158,12 +158,12 @@ describe('getNodeMajorVersion()', () => { }) describe('extracts a version from existing runtimes', function () { - nodeJsRuntimes.forEach((versionString) => { + for (const versionString of nodeJsRuntimes) { it(`extracts from runtime: "${versionString}"`, () => { const version = getNodeMajorVersion(versionString) assert(version !== undefined) assert(0 < version && version < 999) }) - }) + } }) }) diff --git a/packages/core/src/test/lambda/models/samTemplates.test.ts b/packages/core/src/test/lambda/models/samTemplates.test.ts index f8ceb68bbe0..e9105adf0b6 100644 --- a/packages/core/src/test/lambda/models/samTemplates.test.ts +++ b/packages/core/src/test/lambda/models/samTemplates.test.ts @@ -128,9 +128,9 @@ describe('getSamCliTemplateParameter', function () { describe('getTemplateDescription', async function () { it('all templates are handled', async function () { - validTemplateOptions.forEach((template) => { + for (const template of validTemplateOptions) { // Checking that call does not throw getTemplateDescription(template) - }) + } }) }) diff --git a/packages/core/src/test/lambda/vue/samInvokeBackend.test.ts b/packages/core/src/test/lambda/vue/samInvokeBackend.test.ts index 4651eda1c13..89a9272df30 100644 --- a/packages/core/src/test/lambda/vue/samInvokeBackend.test.ts +++ b/packages/core/src/test/lambda/vue/samInvokeBackend.test.ts @@ -94,7 +94,7 @@ describe('SamInvokeWebview', () => { const tempFolder = await makeTemporaryToolkitFolder() const testCases = [{ input: vscode.Uri.file(path.join(tempFolder, 'file.txt')), expected: 'file.txt' }] - testCases.forEach(({ input, expected }) => { + for (const { input, expected } of testCases) { const result = samInvokeWebview.getFileName(input.fsPath) assert.strictEqual(result, expected, `getFileName("${input}") should return "${expected}"`) @@ -105,7 +105,7 @@ describe('SamInvokeWebview', () => { nodeResult, `getFileName result should match Node's path.basename for "${input}"` ) - }) + } await fs.delete(tempFolder, { recursive: true }) }) }) @@ -396,7 +396,7 @@ describe('SamInvokeWebview', () => { const tempFolder = await makeTemporaryToolkitFolder() const testCases = [{ input: vscode.Uri.file(path.join(tempFolder, 'file.txt')), expected: 'file.txt' }] - testCases.forEach(({ input, expected }) => { + for (const { input, expected } of testCases) { const result = samInvokeWebview.getFileName(input.fsPath) assert.strictEqual(result, expected, `getFileName("${input}") should return "${expected}"`) @@ -407,7 +407,7 @@ describe('SamInvokeWebview', () => { nodeResult, `getFileName result should match Node's path.basename for "${input}"` ) - }) + } await fs.delete(tempFolder, { recursive: true }) }) it('prompts the user for a file and returns the selected file', async () => { diff --git a/packages/core/src/test/notifications/rendering.test.ts b/packages/core/src/test/notifications/rendering.test.ts index ccda76195a2..684ef97b4d2 100644 --- a/packages/core/src/test/notifications/rendering.test.ts +++ b/packages/core/src/test/notifications/rendering.test.ts @@ -65,12 +65,12 @@ describe('Notifications Rendering', function () { testWindow.onDidShowMessage((message) => { const expectedButtons = notification.uiRenderInstructions.actions?.map((actions) => actions.displayText['en-US']) ?? [] - expectedButtons.forEach((buttonText) => { + for (const buttonText of expectedButtons) { assert.ok( message.items.some((item) => item.title === buttonText), `Button "${buttonText}" is missing` ) - }) + } }) await panelNode.onReceiveNotifications([notification]) diff --git a/packages/core/src/test/shared/applicationBuilder/explorer/nodes/deployedNode.test.ts b/packages/core/src/test/shared/applicationBuilder/explorer/nodes/deployedNode.test.ts index e7ee29f41da..4917979fe1f 100644 --- a/packages/core/src/test/shared/applicationBuilder/explorer/nodes/deployedNode.test.ts +++ b/packages/core/src/test/shared/applicationBuilder/explorer/nodes/deployedNode.test.ts @@ -298,9 +298,9 @@ describe('generateDeployedNode', () => { name?: string description?: string } - Object.entries(options).forEach(([key, value]) => { + for (const [key, value] of Object.entries(options)) { value !== undefined && Object.defineProperty(mockNode, key, { value, writable: true }) - }) + } return mockNode } diff --git a/packages/core/src/test/shared/applicationBuilder/explorer/nodes/propertyNode.test.ts b/packages/core/src/test/shared/applicationBuilder/explorer/nodes/propertyNode.test.ts index 66515add392..8de0f71f50b 100644 --- a/packages/core/src/test/shared/applicationBuilder/explorer/nodes/propertyNode.test.ts +++ b/packages/core/src/test/shared/applicationBuilder/explorer/nodes/propertyNode.test.ts @@ -105,11 +105,11 @@ describe('PropertyNode', () => { { key: 'baz', value: 42 }, ] assert.strictEqual(nodes.length, expectedNodes.length) - nodes.forEach((node, index) => { + for (const [index, node] of nodes.entries()) { assert(node instanceof PropertyNode) assert.strictEqual(node.id, expectedNodes[index].key) assert.strictEqual(node.resource, expectedNodes[index].value) - }) + } }) }) }) diff --git a/packages/core/src/test/shared/codelens/csharpCodeLensProvider.test.ts b/packages/core/src/test/shared/codelens/csharpCodeLensProvider.test.ts index 26d3ee7a78b..86db6f54796 100644 --- a/packages/core/src/test/shared/codelens/csharpCodeLensProvider.test.ts +++ b/packages/core/src/test/shared/codelens/csharpCodeLensProvider.test.ts @@ -145,7 +145,7 @@ describe('isPublicMethodSymbol', async function () { }, ] - validPublicMethodTests.forEach((test) => { + for (const test of validPublicMethodTests) { const sampleMethodSymbol: vscode.DocumentSymbol = new vscode.DocumentSymbol( 'FunctionHandler(APIGatewayProxyRequest apigProxyEvent, ILambdaContext context)', '', @@ -164,7 +164,7 @@ describe('isPublicMethodSymbol', async function () { const isPublic = isValidLambdaHandler(doc, sampleMethodSymbol) assert.strictEqual(isPublic, true, 'Expected symbol to be a public method') }) - }) + } it('returns false for a symbol that is not a method', async function () { const symbol = new vscode.DocumentSymbol( diff --git a/packages/core/src/test/shared/codelens/javaCodeLensProvider.test.ts b/packages/core/src/test/shared/codelens/javaCodeLensProvider.test.ts index 12480997f9b..f7d42d516b6 100644 --- a/packages/core/src/test/shared/codelens/javaCodeLensProvider.test.ts +++ b/packages/core/src/test/shared/codelens/javaCodeLensProvider.test.ts @@ -210,7 +210,7 @@ describe('javaCodeLensProvider', () => { }, ] - validPublicMethodTests.forEach((test) => { + for (const test of validPublicMethodTests) { const sampleMethodSymbol: vscode.DocumentSymbol = new vscode.DocumentSymbol( 'FunctionHandler(APIGatewayProxyRequest apigProxyEvent, ILambdaContext context)', '', @@ -236,7 +236,7 @@ describe('javaCodeLensProvider', () => { const isValid = isValidLambdaHandler(doc, sampleMethodSymbol) assert.strictEqual(isValid, true, 'Expected symbol to be a valid method') }) - }) + } it('returns false for a symbol that is not a method', async function () { const symbol = new vscode.DocumentSymbol( diff --git a/packages/core/src/test/shared/codelens/pythonCodeLensProvider.test.ts b/packages/core/src/test/shared/codelens/pythonCodeLensProvider.test.ts index 5894d7259ff..f96d75e123a 100644 --- a/packages/core/src/test/shared/codelens/pythonCodeLensProvider.test.ts +++ b/packages/core/src/test/shared/codelens/pythonCodeLensProvider.test.ts @@ -24,7 +24,7 @@ describe('pythonCodeLensProvider', async function () { }, ] - testScenarios.forEach((test) => { + for (const test of testScenarios) { it(`Returns cased-drive variants for windows platforms: ${test.situation}`, async () => { const variants = getLocalRootVariants(test.inputText) assert.ok(variants) @@ -32,7 +32,7 @@ describe('pythonCodeLensProvider', async function () { assert.strictEqual(variants[0], test.asLower, 'Unexpected variant text') assert.strictEqual(variants[1], test.asUpper, 'Unexpected variant text') }) - }) + } it('Returns the same string for network location - windows', async function () { const variants = getLocalRootVariants('//share/src/code.js') @@ -63,14 +63,14 @@ describe('pythonCodeLensProvider', async function () { }, ] - testScenarios.forEach((test) => { + for (const test of testScenarios) { it(`Returns the same string for non-windows platforms: ${test.situation}`, async () => { const variants = getLocalRootVariants(test.inputText) assert.ok(variants) assert.strictEqual(variants.length, 1, 'Only expected one variant') assert.strictEqual(variants[0], test.inputText, 'Unexpected variant text') }) - }) + } } }) }) diff --git a/packages/core/src/test/shared/crashMonitoring.test.ts b/packages/core/src/test/shared/crashMonitoring.test.ts index c06b8b167a1..85ea33dfcf7 100644 --- a/packages/core/src/test/shared/crashMonitoring.test.ts +++ b/packages/core/src/test/shared/crashMonitoring.test.ts @@ -84,7 +84,11 @@ export const crashMonitoringTest = async () => { afterEach(async function () { // clean up all running instances - spawnedExtensions?.forEach((e) => e.crash()) + if (spawnedExtensions) { + for (const e of spawnedExtensions) { + void e.crash() + } + } sandbox.restore() }) @@ -255,13 +259,13 @@ export const crashMonitoringTest = async () => { expectedExts.sort((a, b) => a.metadata.sessionId.localeCompare(b.metadata.sessionId)) deduplicatedSessionEnds.sort((a, b) => a.proxiedSessionId!.localeCompare(b.proxiedSessionId!)) - expectedExts.forEach((ext, i) => { + for (const [i, ext] of expectedExts.entries()) { partialDeepCompare(deduplicatedSessionEnds[i], { result: 'Failed', proxiedSessionId: ext.metadata.sessionId, reason: 'ExtHostCrashed', }) - }) + } } function deduplicate(array: T[], predicate: (a: T, b: T) => boolean): T[] { diff --git a/packages/core/src/test/shared/credentials/userCredentialsUtils.test.ts b/packages/core/src/test/shared/credentials/userCredentialsUtils.test.ts index eaeb9bc571d..664eb454fd6 100644 --- a/packages/core/src/test/shared/credentials/userCredentialsUtils.test.ts +++ b/packages/core/src/test/shared/credentials/userCredentialsUtils.test.ts @@ -156,13 +156,13 @@ describe('UserCredentialsUtils', function () { async function createCredentialsFile(filename: string, profileNames: string[]): Promise { let fileContents = '' - profileNames.forEach((profileName) => { + for (const profileName of profileNames) { fileContents += `[${profileName}] aws_access_key_id = FAKEKEY aws_SecRet_aCCess_key = FAKESECRET REGION = us-weast-3 ` - }) + } await fs.writeFile(filename, fileContents) } diff --git a/packages/core/src/test/shared/errors.test.ts b/packages/core/src/test/shared/errors.test.ts index 428a32c13ee..32d18186912 100644 --- a/packages/core/src/test/shared/errors.test.ts +++ b/packages/core/src/test/shared/errors.test.ts @@ -367,12 +367,12 @@ describe('resolveErrorMessageToDisplay()', function () { }) // Sanity check specific errors are resolved as expected - prioritiziedAwsErrors.forEach((error) => { + for (const error of prioritiziedAwsErrors) { it(`resolves ${error.code} message when provided directly`, function () { const message = resolveErrorMessageToDisplay(error, defaultMessage) assert.strictEqual(message, `${defaultMessage}: ${awsErrorMessage}`) }) - }) + } it('gets default message if no error is given', function () { const message = resolveErrorMessageToDisplay(undefined, defaultMessage) diff --git a/packages/core/src/test/shared/fs/fs.test.ts b/packages/core/src/test/shared/fs/fs.test.ts index 5fa4428559f..ad8d8777462 100644 --- a/packages/core/src/test/shared/fs/fs.test.ts +++ b/packages/core/src/test/shared/fs/fs.test.ts @@ -69,13 +69,13 @@ describe('FileSystem', function () { describe('writeFile()', function () { const opts: { atomic: boolean }[] = [{ atomic: false }, { atomic: true }] - opts.forEach((opt) => { + for (const opt of opts) { it(`writes a file (atomic: ${opt.atomic})`, async function () { const filePath = testFolder.pathFrom('myFileName') await fs.writeFile(filePath, 'MyContent', opt) assert.strictEqual(readFileSync(filePath, 'utf-8'), 'MyContent') }) - }) + } it('writes a file with encoded text', async function () { const filePath = testFolder.pathFrom('myFileName') @@ -100,7 +100,7 @@ describe('FileSystem', function () { { vsc: true, node: false }, { vsc: true, node: true }, ] - throwCombinations.forEach((throws) => { + for (const throws of throwCombinations) { it(`still writes a file if one of the atomic write methods fails: ${JSON.stringify(throws)}`, async function () { if (throws.vsc) { sandbox.stub(fs, 'rename').throws(new Error('Test Error Message VSC')) @@ -134,7 +134,7 @@ describe('FileSystem', function () { testutil.assertTelemetry('ide_fileSystem', expectedTelemetry) } }) - }) + } it('throws when existing file + no permission', async function () { if (isWin()) { @@ -218,6 +218,7 @@ describe('FileSystem', function () { describe('mkdir()', function () { const paths = ['a', 'a/b', 'a/b/c', 'a/b/c/d/'] + // eslint-disable-next-line unicorn/no-array-for-each paths.forEach(async function (p) { it(`creates folder: '${p}'`, async function () { const dirPath = testFolder.pathFrom(p) @@ -226,6 +227,7 @@ describe('FileSystem', function () { }) }) + // eslint-disable-next-line unicorn/no-array-for-each paths.forEach(async function (p) { it(`creates folder but uses the "fs" module if in Cloud9: '${p}'`, async function () { sandbox.stub(extensionUtilities, 'isCloud9').returns(true) diff --git a/packages/core/src/test/shared/globalState.test.ts b/packages/core/src/test/shared/globalState.test.ts index 6788abc50e9..d632b745051 100644 --- a/packages/core/src/test/shared/globalState.test.ts +++ b/packages/core/src/test/shared/globalState.test.ts @@ -33,24 +33,24 @@ describe('GlobalState', function () { ] describe('get()', function () { - scenarios.forEach((scenario) => { + for (const scenario of scenarios) { it(scenario.desc, async () => { await globalState.update(testKey, scenario.testValue) const actualValue = globalState.get(testKey) assert.deepStrictEqual(actualValue, scenario.testValue) }) - }) + } }) describe('update()', function () { - scenarios.forEach((scenario) => { + for (const scenario of scenarios) { it(scenario.desc, async () => { await globalState.update(testKey, scenario.testValue) const savedValue = globalState.get(testKey) assert.deepStrictEqual(savedValue, scenario.testValue) }) - }) + } }) it('getStrict()', async () => { diff --git a/packages/core/src/test/shared/logger/consoleLogLogger.test.ts b/packages/core/src/test/shared/logger/consoleLogLogger.test.ts index d66790514e0..3a2f323d8d4 100644 --- a/packages/core/src/test/shared/logger/consoleLogLogger.test.ts +++ b/packages/core/src/test/shared/logger/consoleLogLogger.test.ts @@ -20,7 +20,7 @@ describe('ConsoleLogTransport', async function () { }) const allLevels = Object.keys(Levels) as Level[] - allLevels.forEach((level) => { + for (const level of allLevels) { it(`logs to console with level: '${level}'`, async function () { const untilLogged = instance.log({ level, message: 'myMessage', [MESSAGE]: 'myMessageFormatted' }, next) await untilLogged @@ -28,7 +28,7 @@ describe('ConsoleLogTransport', async function () { assert.strictEqual(fakeConsole[level].getCall(0).args[0], 'myMessageFormatted') assert.strictEqual(next.callCount, 1) }) - }) + } it(`logs to the default if non-supported log level provided`, async function () { const untilLogged = instance.log( diff --git a/packages/core/src/test/shared/logger/toolkitLogger.test.ts b/packages/core/src/test/shared/logger/toolkitLogger.test.ts index b8ced878c7a..80545f1c006 100644 --- a/packages/core/src/test/shared/logger/toolkitLogger.test.ts +++ b/packages/core/src/test/shared/logger/toolkitLogger.test.ts @@ -179,7 +179,7 @@ describe('ToolkitLogger', function () { await checkFile(testLogger, tempLogPath, [loggedVerboseEntry], [nonLoggedVerboseEntry]) }) - happyLogScenarios.forEach((scenario) => { + for (const scenario of happyLogScenarios) { it(scenario.name, async () => { const msg = `message for ${scenario.name} arg1 %s, arg2 %O` const args = [42, ['a', 'b']] @@ -191,7 +191,7 @@ describe('ToolkitLogger', function () { await checkFile(testLogger, tempLogPath, [expectedMsg]) }) - }) + } }) describe('logs to an OutputChannel', async function () { @@ -257,7 +257,7 @@ describe('ToolkitLogger', function () { assertLogsContain('This is a test message', true, 'verbose') }) - happyLogScenarios.forEach((scenario) => { + for (const scenario of happyLogScenarios) { it(scenario.name, async () => { const message = `message for ${scenario.name}` testLogger = new ToolkitLogger('debug') @@ -269,7 +269,7 @@ describe('ToolkitLogger', function () { assert.ok((await waitForMessage).includes(message), 'Expected error message to be logged') }) - }) + } // Logger writes to OutputChannel in async manner. async function waitForLoggedTextByCount(entries: number): Promise { @@ -351,7 +351,9 @@ describe('ToolkitLogger', function () { } await checkFile(testLogger, tempLogPath, expected, unexpected) - idMap.forEach((msg, id) => assert.ok(testLogger.getLogById(id, tempLogPath)?.includes(msg))) + for (const [id, msg] of idMap.entries()) { + assert.ok(testLogger.getLogById(id, tempLogPath)?.includes(msg)) + } }) it('can find log from multiple files', async function () { diff --git a/packages/core/src/test/shared/sam/cli/samCliInfo.test.ts b/packages/core/src/test/shared/sam/cli/samCliInfo.test.ts index 1fb4dc6d268..dc27ad4ed89 100644 --- a/packages/core/src/test/shared/sam/cli/samCliInfo.test.ts +++ b/packages/core/src/test/shared/sam/cli/samCliInfo.test.ts @@ -35,10 +35,10 @@ describe('SamCliInfoInvocation', async function () { }) it('converts non-response to undefined', async function () { - ;['qwerty', '{"version": "1.2.3"} you have no new email messages'].forEach((output) => { + for (const output of ['qwerty', '{"version": "1.2.3"} you have no new email messages']) { const response = new TestSamCliInfoCommand('').convertOutput(output) assert.strictEqual(response, undefined, `Expected text to not parse: ${output}`) - }) + } }) }) diff --git a/packages/core/src/test/shared/sam/cli/samCliValidationNotification.test.ts b/packages/core/src/test/shared/sam/cli/samCliValidationNotification.test.ts index 78943dca218..3156e2afb1e 100644 --- a/packages/core/src/test/shared/sam/cli/samCliValidationNotification.test.ts +++ b/packages/core/src/test/shared/sam/cli/samCliValidationNotification.test.ts @@ -65,7 +65,7 @@ describe('getInvalidSamMsg', async function () { }, ] - versionValidationTestScenarios.forEach((test) => { + for (const test of versionValidationTestScenarios) { it(`handles InvalidSamCliVersionError - ${test.situation}`, async () => { const validatorResult: SamCliVersionValidatorResult = { version: '1.2.3', @@ -92,7 +92,7 @@ describe('getInvalidSamMsg', async function () { } ) }) - }) + } it('handles Unexpected input', async function () { getInvalidSamMsg( diff --git a/packages/core/src/test/shared/sam/cli/samCliValidator.test.ts b/packages/core/src/test/shared/sam/cli/samCliValidator.test.ts index f5cb05a7dbd..15c1a57a139 100644 --- a/packages/core/src/test/shared/sam/cli/samCliValidator.test.ts +++ b/packages/core/src/test/shared/sam/cli/samCliValidator.test.ts @@ -69,7 +69,7 @@ describe('DefaultSamCliValidator', async function () { ] as const describe('detectValidSamCli', async function () { - scenarios.forEach((test) => { + for (const test of scenarios) { it(`found SAM CLI, ${test.situation}`, async () => { const validatorContext = new TestSamCliValidatorContext(test.version) validatorContext.mockSamLocation = 'somesamclipath' @@ -80,7 +80,7 @@ describe('DefaultSamCliValidator', async function () { assert.strictEqual(actual.versionValidation?.version, test.version) assert.strictEqual(actual.versionValidation?.validation, test.expected) }) - }) + } it('SAM CLI not found', async function () { const validatorContext = new TestSamCliValidatorContext('') @@ -93,7 +93,7 @@ describe('DefaultSamCliValidator', async function () { }) describe('getVersionValidatorResult', async function () { - scenarios.forEach((test) => { + for (const test of scenarios) { it(test.situation, async () => { const validatorContext = new TestSamCliValidatorContext(test.version) const samCliValidator = new DefaultSamCliValidator(validatorContext) @@ -102,15 +102,15 @@ describe('DefaultSamCliValidator', async function () { assert.strictEqual(actual.version, test.version) assert.strictEqual(actual.validation, test.expected) }) - }) + } }) describe('validateSamCliVersion', async function () { - scenarios.forEach((test) => { + for (const test of scenarios) { it(test.situation, async () => { const validation = DefaultSamCliValidator.validateSamCliVersion(test.version) assert.strictEqual(validation, test.expected) }) - }) + } }) }) diff --git a/packages/core/src/test/shared/sam/cli/testSamCliProcessInvoker.ts b/packages/core/src/test/shared/sam/cli/testSamCliProcessInvoker.ts index db804ba718d..8528b0c6189 100644 --- a/packages/core/src/test/shared/sam/cli/testSamCliProcessInvoker.ts +++ b/packages/core/src/test/shared/sam/cli/testSamCliProcessInvoker.ts @@ -103,7 +103,7 @@ export async function assertLogContainsBadExitInformation( .getLoggedEntries() .filter((x) => !isError(x)) .join('\n') - expectedTexts.forEach((expectedText) => { + for (const expectedText of expectedTexts) { assert.ok(logText.includes(expectedText.text), expectedText.verifyMessage) - }) + } } diff --git a/packages/core/src/test/shared/sam/deploy.test.ts b/packages/core/src/test/shared/sam/deploy.test.ts index c38c6eb8731..7a8cf0ed807 100644 --- a/packages/core/src/test/shared/sam/deploy.test.ts +++ b/packages/core/src/test/shared/sam/deploy.test.ts @@ -801,9 +801,9 @@ describe('SAM DeployWizard', async function () { } ) - expectedCallOrder.forEach((title, index) => { + for (const [index, title] of expectedCallOrder.entries()) { prompterTester.assertCallOrder(title, index + 1) - }) + } }) it('happy path with samconfig.toml', async () => { diff --git a/packages/core/src/test/shared/sam/samTestUtils.ts b/packages/core/src/test/shared/sam/samTestUtils.ts index 16520c0ca95..61b67446f5b 100644 --- a/packages/core/src/test/shared/sam/samTestUtils.ts +++ b/packages/core/src/test/shared/sam/samTestUtils.ts @@ -72,9 +72,9 @@ export function generateSamconfigData(data: { for (const [operation, parameters] of Object.entries(data)) { if (parameters && parameters.length > 0) { result.push('', `[default.${operation}.parameters]`) - parameters.forEach(({ key, value }) => { + for (const { key, value } of parameters) { value && result.push(`${key} = "${value}"`) - }) + } } } diff --git a/packages/core/src/test/shared/sam/sync.test.ts b/packages/core/src/test/shared/sam/sync.test.ts index 627cee964f6..acb74619171 100644 --- a/packages/core/src/test/shared/sam/sync.test.ts +++ b/packages/core/src/test/shared/sam/sync.test.ts @@ -901,9 +901,9 @@ describe('SAM SyncWizard', async () => { 'Select an S3 Bucket', 'Specify parameters for sync', ] - expectedCallOrder.forEach((title, index) => { + for (const [index, title] of expectedCallOrder.entries()) { prompterTester.assertCallOrder(title, index + 1) - }) + } }) describe('entry: command palette', () => { @@ -2160,7 +2160,7 @@ describe('SAM sync helper functions', () => { }, ] - testCases.forEach(({ name, response }) => { + for (const { name, response } of testCases) { it(`should handle ${name}`, async () => { createRepositoryStub.resolves(response) @@ -2169,7 +2169,7 @@ describe('SAM sync helper functions', () => { assert(!result) assert(createRepositoryStub.calledOnceWith(repoName)) }) - }) + } }) }) }) diff --git a/packages/core/src/test/shared/sam/utils.test.ts b/packages/core/src/test/shared/sam/utils.test.ts index 590db5a9a81..991e6644471 100644 --- a/packages/core/src/test/shared/sam/utils.test.ts +++ b/packages/core/src/test/shared/sam/utils.test.ts @@ -68,11 +68,11 @@ describe('SAM utils', async function () { expected: undefined, }, ] - testScenarios.forEach((scenario) => { + for (const scenario of testScenarios) { it(`returns Source for ${scenario.name}`, async () => { assert.strictEqual(getSource(scenario.value), scenario.expected) }) - }) + } }) describe('checks if it is DotNet', async function () { @@ -159,12 +159,12 @@ describe('SAM utils', async function () { sandbox.restore() }) - testScenarios.forEach((scenario) => { + for (const scenario of testScenarios) { it(`returns isDotNetRuntime for ${scenario.name}`, async () => { const response = await isDotnetRuntime(noUri, scenario.template) assert.strictEqual(response, scenario.expected) }) - }) + } }) describe('getSamCliPathAndVersion', async function () { diff --git a/packages/core/src/test/shared/settings.test.ts b/packages/core/src/test/shared/settings.test.ts index 5d485489138..da68ada2cde 100644 --- a/packages/core/src/test/shared/settings.test.ts +++ b/packages/core/src/test/shared/settings.test.ts @@ -79,14 +79,14 @@ describe('Settings', function () { settings = vscode.workspace.getConfiguration() }) - scenarios.forEach((scenario) => { + for (const scenario of scenarios) { it(scenario.desc, async () => { await settings.update(settingKey, scenario.testValue, settingsTarget) const actualValue = sut.get(settingKey) assert.deepStrictEqual(actualValue, scenario.testValue) }) - }) + } it('failure modes', async () => { // @@ -112,7 +112,7 @@ describe('Settings', function () { }) describe('update', function () { - scenarios.forEach((scenario) => { + for (const scenario of scenarios) { it(scenario.desc, async () => { await sut.update(settingKey, scenario.testValue) @@ -122,7 +122,7 @@ describe('Settings', function () { assert.deepStrictEqual(savedValue, scenario.testValue) }) - }) + } it('shows message on failure', async () => { // TODO: could avoid sinon if we can force vscode to use a dummy settings.json file. @@ -452,7 +452,7 @@ describe('PromptSetting', function () { desc: 'suppresses prompt', }, ] - scenarios.forEach((scenario) => { + for (const scenario of scenarios) { it(scenario.desc, async () => { const defaultSetting = settings.get(promptSettingKey, Object) await settings.update(promptSettingKey, scenario.testValue) @@ -461,7 +461,7 @@ describe('PromptSetting', function () { const expected = { ...defaultSetting, ...scenario.expected } assert.deepStrictEqual(actual, expected) }) - }) + } }) describe('isPromptEnabled', async function () { @@ -494,7 +494,7 @@ describe('PromptSetting', function () { }, ] - scenarios.forEach((scenario) => { + for (const scenario of scenarios) { it(scenario.desc, async () => { await settings.update(promptSettingKey, scenario.testValue) const before = settings.get(promptSettingKey, Object, {}) @@ -506,7 +506,7 @@ describe('PromptSetting', function () { { ...before, ...scenario.promptAfter } ) }) - }) + } }) }) diff --git a/packages/core/src/test/shared/telemetry/activation.test.ts b/packages/core/src/test/shared/telemetry/activation.test.ts index f7643046358..a277cb0b042 100644 --- a/packages/core/src/test/shared/telemetry/activation.test.ts +++ b/packages/core/src/test/shared/telemetry/activation.test.ts @@ -59,10 +59,10 @@ describe('hasUserSeenTelemetryNotice', async function () { { currentState: 9999, expectedHasSeen: true, desc: 'seen a future version' }, ] - scenarios.forEach((scenario) => { + for (const scenario of scenarios) { it(scenario.desc, async () => { await globals.globalState.update('awsTelemetryNoticeVersionAck', scenario.currentState) assert.strictEqual(hasUserSeenTelemetryNotice(), scenario.expectedHasSeen) }) - }) + } }) diff --git a/packages/core/src/test/shared/telemetry/util.test.ts b/packages/core/src/test/shared/telemetry/util.test.ts index 627ad58f5e7..4c19e924585 100644 --- a/packages/core/src/test/shared/telemetry/util.test.ts +++ b/packages/core/src/test/shared/telemetry/util.test.ts @@ -83,17 +83,17 @@ describe('TelemetryConfig', function () { ] describe('isTelemetryEnabled', function () { - scenarios.forEach((scenario) => { + for (const scenario of scenarios) { it(scenario.desc, async () => { await settings.update(settingKey, scenario.initialSettingValue) assert.strictEqual(sut.isEnabled(), scenario.expectedIsEnabledValue) }) - }) + } }) describe('sanitizeTelemetrySetting', function () { - scenarios.forEach((scenario) => { + for (const scenario of scenarios) { it(scenario.desc, () => { const tryConvert = () => { try { @@ -105,7 +105,7 @@ describe('TelemetryConfig', function () { assert.deepStrictEqual(tryConvert(), scenario.expectedSanitizedValue) }) - }) + } }) }) diff --git a/packages/core/src/test/shared/ui/inputPrompter.test.ts b/packages/core/src/test/shared/ui/inputPrompter.test.ts index 2f8c64d3cd8..fdf8dbb1600 100644 --- a/packages/core/src/test/shared/ui/inputPrompter.test.ts +++ b/packages/core/src/test/shared/ui/inputPrompter.test.ts @@ -21,9 +21,9 @@ describe('createInputBox', function () { const prompter = createInputBox() const inputBox = prompter.inputBox - Object.keys(defaultInputboxOptions).forEach((key) => { + for (const key of Object.keys(defaultInputboxOptions)) { assert.strictEqual(inputBox[key as keyof vscode.InputBox], (defaultInputboxOptions as any)[key]) - }) + } }) }) diff --git a/packages/core/src/test/shared/ui/pickerPrompter.test.ts b/packages/core/src/test/shared/ui/pickerPrompter.test.ts index 67cd56c5d61..cbf2a7ae3af 100644 --- a/packages/core/src/test/shared/ui/pickerPrompter.test.ts +++ b/packages/core/src/test/shared/ui/pickerPrompter.test.ts @@ -31,12 +31,12 @@ describe('createQuickPick', function () { const prompter = createQuickPick([]) const picker = prompter.quickPick - Object.keys(picker).forEach((key) => { + for (const key of Object.keys(picker)) { const defaultValue = (defaultQuickpickOptions as Record)[key] if (defaultValue !== undefined) { assert.strictEqual(picker[key as keyof vscode.QuickPick], defaultValue) } - }) + } }) it('creates a new prompter with options', async function () { diff --git a/packages/core/src/test/shared/ui/prompters/regionSubmenu.test.ts b/packages/core/src/test/shared/ui/prompters/regionSubmenu.test.ts index 4687ec10d5f..00a9dd7eeb3 100644 --- a/packages/core/src/test/shared/ui/prompters/regionSubmenu.test.ts +++ b/packages/core/src/test/shared/ui/prompters/regionSubmenu.test.ts @@ -89,7 +89,9 @@ describe('regionSubmenu', function () { submenuPrompter.activePrompter!.onDidChangeBusy((b: boolean) => { if (!b) { const itemsAfterLabels = submenuPrompter.activePrompter!.quickPick.items.map((i) => i.label) - region2Data.forEach((item) => assert(itemsAfterLabels.includes(item))) + for (const item of region2Data) { + assert(itemsAfterLabels.includes(item)) + } assert.notStrictEqual(itemsBeforeLabels, itemsAfterLabels) } }) diff --git a/packages/core/src/test/shared/utilities/asyncCollection.test.ts b/packages/core/src/test/shared/utilities/asyncCollection.test.ts index 5272026b97c..ee10a1ad4bd 100644 --- a/packages/core/src/test/shared/utilities/asyncCollection.test.ts +++ b/packages/core/src/test/shared/utilities/asyncCollection.test.ts @@ -52,12 +52,16 @@ describe('AsyncCollection', function () { it('can turn into a map using property key', async function () { const map = await toCollection(genItem).toMap('name') - items.forEach((v) => assert.strictEqual(map.get(v.name), v)) + for (const v of items) { + assert.strictEqual(map.get(v.name), v) + } }) it('can turn into a map using function', async function () { const map = await toCollection(genItem).toMap((i) => i.data.toString()) - items.forEach((v) => assert.strictEqual(map.get(v.data.toString()), v)) + for (const v of items) { + assert.strictEqual(map.get(v.data.toString()), v) + } }) it('can map', async function () { diff --git a/packages/core/src/test/shared/utilities/textUtilities.test.ts b/packages/core/src/test/shared/utilities/textUtilities.test.ts index 8a62de243df..0ea0e14377b 100644 --- a/packages/core/src/test/shared/utilities/textUtilities.test.ts +++ b/packages/core/src/test/shared/utilities/textUtilities.test.ts @@ -141,11 +141,11 @@ describe('sanitizeFilename', function () { { input: 'foo.txt', output: 'foo.txt', case: 'keeps dot' }, { input: 'züb', output: 'züb', case: 'keeps special chars' }, ] - cases.forEach((testCase) => { + for (const testCase of cases) { it(testCase.case, function () { assert.strictEqual(sanitizeFilename(testCase.input, testCase.replaceString), testCase.output) }) - }) + } }) describe('undefinedIfEmpty', function () { @@ -157,9 +157,9 @@ describe('undefinedIfEmpty', function () { { input: ' foo ', output: ' foo ', case: 'return original str without trim' }, ] - cases.forEach((testCases) => { + for (const testCases of cases) { it(testCases.case, function () { assert.strictEqual(undefinedIfEmpty(testCases.input), testCases.output) }) - }) + } }) diff --git a/packages/core/src/test/shared/vscode/env.test.ts b/packages/core/src/test/shared/vscode/env.test.ts index bc1c1dde9dc..ef81bdf05ab 100644 --- a/packages/core/src/test/shared/vscode/env.test.ts +++ b/packages/core/src/test/shared/vscode/env.test.ts @@ -35,7 +35,9 @@ describe('env', function () { const envVars: string[] = [] afterEach(() => { - envVars.forEach((v) => delete process.env[v]) + for (const v of envVars) { + delete process.env[v] + } envVars.length = 0 }) diff --git a/packages/core/src/test/shared/vscode/quickInput.ts b/packages/core/src/test/shared/vscode/quickInput.ts index 8d1e702eb5d..1601485fc1d 100644 --- a/packages/core/src/test/shared/vscode/quickInput.ts +++ b/packages/core/src/test/shared/vscode/quickInput.ts @@ -107,11 +107,11 @@ function assertItems(actual: T[], expected: Item return throwError('Picker had different number of items', actual, expected) } - actual.forEach((actualItem, index) => { + for (const [index, actualItem] of actual.entries()) { if (!matchItem(actualItem, expected[index])) { throwError(`Unexpected item found at index ${index}`, actual, expected[index]) } - }) + } } function assertItemButtons(actual: T[], expected: ItemButtonMatcher[]): void { @@ -119,11 +119,11 @@ function assertItemButtons(actual: T[], expec return throwError('Item had different number of buttons', actual, expected) } - actual.forEach((actualItem, index) => { + for (const [index, actualItem] of actual.entries()) { if (!matchItemButton(actualItem, expected[index])) { throwError(`Unexpected item button found at index ${index}`, actual, expected[index]) } - }) + } } function findButtonOrThrow( @@ -338,7 +338,9 @@ export function createTestQuickPick(picker: vsco const emitters = toRecord(pickerEvents, () => new vscode.EventEmitter()) const triggers = toRecord(pickerEvents, (k) => emitters[k].fire.bind(emitters[k])) const extraEmitters = createExtraEmitters() - keys(emitters).forEach((key) => picker[key](triggers[key])) + for (const key of keys(emitters)) { + picker[key](triggers[key]) + } const state = { visible: false } const tester = new PickerTester(picker, emitters, extraEmitters) @@ -439,7 +441,9 @@ export function createTestInputBox(inputBox: vscode.InputBox): TestInputBox { const triggers = toRecord(inputEvents, (k) => emitters[k].fire.bind(emitters[k])) const extraEmitters = createExtraEmitters() - keys(emitters).forEach((key) => inputBox[key](triggers[key])) + for (const key of keys(emitters)) { + inputBox[key](triggers[key]) + } const state = { visible: false } const tester = new InputBoxTester(inputBox, emitters, extraEmitters) diff --git a/packages/core/src/test/shared/vscode/window.ts b/packages/core/src/test/shared/vscode/window.ts index 971ae78c4ba..c01cae66ded 100644 --- a/packages/core/src/test/shared/vscode/window.ts +++ b/packages/core/src/test/shared/vscode/window.ts @@ -196,6 +196,7 @@ export function createTestWindow(workspace = vscode.workspace): Window & TestWin const picker = createQuickPick() const onDidSelectItem = options?.onDidSelectItem?.bind(options) if (onDidSelectItem) { + // eslint-disable-next-line unicorn/no-array-for-each picker.onDidChangeSelection((items) => items.forEach(onDidSelectItem)) } diff --git a/packages/core/src/test/shared/wizards/compositWizard.test.ts b/packages/core/src/test/shared/wizards/compositWizard.test.ts index 44e074fc96c..e148a3deea1 100644 --- a/packages/core/src/test/shared/wizards/compositWizard.test.ts +++ b/packages/core/src/test/shared/wizards/compositWizard.test.ts @@ -429,18 +429,18 @@ describe('NestedWizard', () => { function setupPrompterTester(titles: string[]) { const prompterTester = PrompterTester.init() - titles.forEach((title) => { + for (const title of titles) { prompterTester.handleQuickPick(title, (quickPick) => { quickPick.acceptItem(quickPick.items[0]) }) - }) + } prompterTester.build() return prompterTester } function assertWizardOutput(prompterTester: PrompterTester, orderedTitle: string[], result: any, output: any) { assert.deepStrictEqual(result, output) - orderedTitle.forEach((title, index) => { + for (const [index, title] of orderedTitle.entries()) { prompterTester.assertCallOrder(title, index + 1) - }) + } } diff --git a/packages/core/src/test/shared/wizards/prompterTester.ts b/packages/core/src/test/shared/wizards/prompterTester.ts index 0fbe93f084a..e859816039e 100644 --- a/packages/core/src/test/shared/wizards/prompterTester.ts +++ b/packages/core/src/test/shared/wizards/prompterTester.ts @@ -146,11 +146,13 @@ export function createPromptHandler(config: { const handlersMap = new Map() // Setup handlers map - config.numbered?.forEach((item) => { - item.order.forEach((orderNum) => { - handlersMap.set(orderNum, item.handler) - }) - }) + if (config.numbered) { + for (const item of config.numbered) { + for (const orderNum of item.order) { + handlersMap.set(orderNum, item.handler) + } + } + } while (true) { currentIteration++ diff --git a/packages/core/src/test/shared/wizards/wizard.test.ts b/packages/core/src/test/shared/wizards/wizard.test.ts index 188d25767c2..2e93ac2fa03 100644 --- a/packages/core/src/test/shared/wizards/wizard.test.ts +++ b/packages/core/src/test/shared/wizards/wizard.test.ts @@ -160,12 +160,20 @@ class TestPrompter extends Prompter { public assertStepEstimate(input: T, expected: number): AssertStepMethods { return { - onCall: (...order: number[]) => order.forEach((i) => this.checkEstimate(input, expected, i)), + onCall: (...order: number[]) => { + for (const i of order) { + this.checkEstimate(input, expected, i) + } + }, onFirstCall: () => this.checkEstimate(input, expected, 1), onSecondCall: () => this.checkEstimate(input, expected, 2), onThirdCall: () => this.checkEstimate(input, expected, 3), onFourthCall: () => this.checkEstimate(input, expected, 4), - onEveryCall: () => this.acceptedStates.forEach((_, i) => this.checkEstimate(input, expected, i + 1)), + onEveryCall: () => { + for (const [i, _] of this.acceptedStates.entries()) { + this.checkEstimate(input, expected, i + 1) + } + }, } as AssertStepMethods } @@ -185,12 +193,20 @@ class TestPrompter extends Prompter { /** Check if the prompter was given the expected steps */ public assertSteps(current: number, total: number): AssertStepMethods { return { - onCall: (...order: number[]) => order.forEach((i) => this.checkSteps([current, total], i)), + onCall: (...order: number[]) => { + for (const i of order) { + this.checkSteps([current, total], i) + } + }, onFirstCall: () => this.checkSteps([current, total], 1), onSecondCall: () => this.checkSteps([current, total], 2), onThirdCall: () => this.checkSteps([current, total], 3), onFourthCall: () => this.checkSteps([current, total], 4), - onEveryCall: () => this.acceptedSteps.forEach((_, i) => this.checkSteps([current, total], i + 1)), + onEveryCall: () => { + for (const [i, _] of this.acceptedSteps.entries()) { + this.checkSteps([current, total], i + 1) + } + }, } as AssertStepMethods } diff --git a/packages/core/src/test/ssmDocument/explorer/documentTypeNode.test.ts b/packages/core/src/test/ssmDocument/explorer/documentTypeNode.test.ts index ee031d5841d..771dff9a5dd 100644 --- a/packages/core/src/test/ssmDocument/explorer/documentTypeNode.test.ts +++ b/packages/core/src/test/ssmDocument/explorer/documentTypeNode.test.ts @@ -29,9 +29,9 @@ describe('DocumentTypeNode', function () { const childNodes = await testNode.getChildren() assert.strictEqual(childNodes.length, expectedChildNodeNames.length) - childNodes.forEach((child, index) => { + for (const [index, child] of childNodes.entries()) { assert.strictEqual(child.label, expectedChildNodeNames[index]) - }) + } }) it('handles error', async function () { diff --git a/packages/core/src/test/ssmDocument/explorer/registryItemNode.test.ts b/packages/core/src/test/ssmDocument/explorer/registryItemNode.test.ts index 203c8e2af8b..2c44bc45315 100644 --- a/packages/core/src/test/ssmDocument/explorer/registryItemNode.test.ts +++ b/packages/core/src/test/ssmDocument/explorer/registryItemNode.test.ts @@ -53,9 +53,9 @@ describe('RegistryItemNode', function () { const expectedNodeNames = [`${owner}doc`] assert.strictEqual(childNode.length, expectedNodeNames.length) - childNode.forEach((node, index) => { + for (const [index, node] of childNode.entries()) { assert.strictEqual(node.label, expectedNodeNames[index]) - }) + } }) ) }) diff --git a/packages/core/src/test/ssmDocument/explorer/ssmDocumentNode.test.ts b/packages/core/src/test/ssmDocument/explorer/ssmDocumentNode.test.ts index b815980c6be..29eb906b7a8 100644 --- a/packages/core/src/test/ssmDocument/explorer/ssmDocumentNode.test.ts +++ b/packages/core/src/test/ssmDocument/explorer/ssmDocumentNode.test.ts @@ -16,9 +16,9 @@ describe('SsmDocumentNode', function () { assert.strictEqual(childNodes.length, expectedChildNodeNames.length, 'Unexpected child node length') - childNodes.forEach((node, index) => { + for (const [index, node] of childNodes.entries()) { assert.ok(node instanceof DocumentTypeNode, 'Expected child node to be RegistryItemNode') assert.strictEqual(node.label, expectedChildNodeNames[index]) - }) + } }) }) diff --git a/packages/core/src/test/ssmDocument/util/validateDocumentName.test.ts b/packages/core/src/test/ssmDocument/util/validateDocumentName.test.ts index 32af415ecde..7aee7f61641 100644 --- a/packages/core/src/test/ssmDocument/util/validateDocumentName.test.ts +++ b/packages/core/src/test/ssmDocument/util/validateDocumentName.test.ts @@ -26,13 +26,13 @@ describe('validateDocumenttName', function () { assert.strictEqual(validateDocumentName('Aaaaa'), undefined) }) - invalidErrors.forEach((invalid) => { + for (const invalid of invalidErrors) { describe(invalid.error, () => { - invalid.documentNames.forEach((documentName) => { + for (const documentName of invalid.documentNames) { it(documentName, () => { assert.strictEqual(validateDocumentName(documentName), invalid.error) }) - }) + } }) - }) + } }) diff --git a/packages/core/src/test/stepFunctions/explorer/stepFunctionNodes.test.ts b/packages/core/src/test/stepFunctions/explorer/stepFunctionNodes.test.ts index e6b534f5117..0f6df30e3e7 100644 --- a/packages/core/src/test/stepFunctions/explorer/stepFunctionNodes.test.ts +++ b/packages/core/src/test/stepFunctions/explorer/stepFunctionNodes.test.ts @@ -52,14 +52,14 @@ describe('StepFunctionsNode', function () { assert.strictEqual(childNodes.length, 2, 'Unexpected child count') - childNodes.forEach((node) => { + for (const node of childNodes) { assert.ok(node instanceof StateMachineNode, 'Expected child node to be StateMachineNode') assert.strictEqual( node.contextValue, contextValueStateMachine, 'expected the node to have a State Machine contextValue' ) - }) + } }) it('sorts child nodes', async function () { diff --git a/packages/core/src/test/testRunner.ts b/packages/core/src/test/testRunner.ts index 7a90977587c..dfd8071d8bc 100644 --- a/packages/core/src/test/testRunner.ts +++ b/packages/core/src/test/testRunner.ts @@ -97,7 +97,7 @@ export async function runTests( // The `require` option for Mocha isn't working for some reason (maybe user error?) // So instead we are loading the modules ourselves and registering the relevant hooks - initTests.forEach((relativePath) => { + for (const relativePath of initTests) { const fullPath = path.join(dist, relativePath).replace('.ts', '.js') if (!fs.exists(fullPath)) { console.error(`error: missing ${fullPath}`) @@ -114,10 +114,12 @@ export async function runTests( if (pluginFile.mochaHooks) { mocha.rootHooks(pluginFile.mochaHooks) } - }) + } function runMocha(files: string[]): Promise { - files.forEach((f) => mocha.addFile(path.resolve(dist, f))) + for (const f of files) { + mocha.addFile(path.resolve(dist, f)) + } return new Promise((resolve, reject) => { mocha.run((failures) => { if (failures > 0) { diff --git a/packages/core/src/test/testUtil.ts b/packages/core/src/test/testUtil.ts index eac5ffc2a2b..d5b9cc324c2 100644 --- a/packages/core/src/test/testUtil.ts +++ b/packages/core/src/test/testUtil.ts @@ -344,9 +344,9 @@ export function assertTelemetry( const passive = expectedCopy?.passive delete expectedCopy['passive'] - Object.keys(expectedCopy).forEach( - (k) => ((expectedCopy as any)[k] = (expectedCopy as Record)[k]?.toString()) - ) + for (const k of Object.keys(expectedCopy)) { + ;(expectedCopy as any)[k] = (expectedCopy as Record)[k]?.toString() + } const msg = `telemetry metric ${i + 1} (of ${ expectedList.length diff --git a/packages/core/src/testE2E/codecatalyst/client.test.ts b/packages/core/src/testE2E/codecatalyst/client.test.ts index b6db9cbdd8f..242f0f64086 100644 --- a/packages/core/src/testE2E/codecatalyst/client.test.ts +++ b/packages/core/src/testE2E/codecatalyst/client.test.ts @@ -344,9 +344,9 @@ describe('Test how this codebase uses the CodeCatalyst API', function () { if (remainingDevEnvs.length > 0) { // Dev Envs may still be returned if they are still in the process of being deleted. // Just ensure they are in the process or fully deleted. - remainingDevEnvs.forEach((devEnv) => { + for (const devEnv of remainingDevEnvs) { assert.ok(['DELETING', 'DELETED'].includes(devEnv.status), 'Dev Env was not successfully deleted') - }) + } } }) diff --git a/packages/core/src/testInteg/appBuilder/sidebar/appBuilderNode.test.ts b/packages/core/src/testInteg/appBuilder/sidebar/appBuilderNode.test.ts index f644ada53da..c18f28b47d2 100644 --- a/packages/core/src/testInteg/appBuilder/sidebar/appBuilderNode.test.ts +++ b/packages/core/src/testInteg/appBuilder/sidebar/appBuilderNode.test.ts @@ -110,7 +110,7 @@ describe('Application Builder', async () => { const expectedStackName = await samConfig.getCommandParam('global', 'stack_name') const expectedRegion = await samConfig.getCommandParam('global', 'region') - appBuilderTestAppResourceNodes.forEach((node) => { + for (const node of appBuilderTestAppResourceNodes) { if (node instanceof ResourceNode) { assert.strictEqual(node.resource.region, expectedRegion) assert.strictEqual(node.resource.stackName, expectedStackName) @@ -119,7 +119,7 @@ describe('Application Builder', async () => { } else { assert.fail('Node is not an instance of ResourceNode') } - }) + } // Validate Lambda resource node const lambdaResourceNode = getResourceNodeByType( diff --git a/packages/core/src/testInteg/appBuilder/walkthrough.test.ts b/packages/core/src/testInteg/appBuilder/walkthrough.test.ts index 79b76a09a24..a8097101b1e 100644 --- a/packages/core/src/testInteg/appBuilder/walkthrough.test.ts +++ b/packages/core/src/testInteg/appBuilder/walkthrough.test.ts @@ -10,7 +10,7 @@ describe('Walkthrough pattern URL exists', function () { const serverlessLandOwner = 'aws-samples' const serverlessLandRepo = 'serverless-patterns' - appMap.forEach((app, key) => { + for (const [key, app] of appMap.entries()) { it(`Walkthrough pattern URL exists for ${key}`, async function () { const url = `https://github.com/${serverlessLandOwner}/${serverlessLandRepo}/releases/latest/download/${app.asset}` const response = await fetch(url, { @@ -19,5 +19,5 @@ describe('Walkthrough pattern URL exists', function () { // ignore if too frequent assert.ok(response.status === 200 || response.status === 429) }) - }) + } }) diff --git a/packages/core/src/testInteg/sam.test.ts b/packages/core/src/testInteg/sam.test.ts index 50e8817f409..e2eeb3b751c 100644 --- a/packages/core/src/testInteg/sam.test.ts +++ b/packages/core/src/testInteg/sam.test.ts @@ -396,7 +396,9 @@ describe('SAM Integration Tests', async function () { }) afterEach(async function () { - testDisposables.forEach((d) => d.dispose()) + for (const d of testDisposables) { + d.dispose() + } await stopDebugger(undefined) }) diff --git a/packages/core/src/testInteg/shared/utilities/workspaceUtils.test.ts b/packages/core/src/testInteg/shared/utilities/workspaceUtils.test.ts index e6bbb3bd83a..d64d3a81d6c 100644 --- a/packages/core/src/testInteg/shared/utilities/workspaceUtils.test.ts +++ b/packages/core/src/testInteg/shared/utilities/workspaceUtils.test.ts @@ -107,7 +107,7 @@ describe('workspaceUtils', () => { globals.codelensRootRegistry.dispose() }) - testScenarios.forEach((test) => { + for (const test of testScenarios) { it(test.scenario, async () => { filesToDelete = test.filesToUse for (const file of test.filesToUse) { @@ -125,7 +125,7 @@ describe('workspaceUtils', () => { assert.strictEqual(projectFile, test.expectedResult) } }) - }) + } }) describe('getWorkspaceRelativePath', function () { diff --git a/packages/core/src/testLint/gitSecrets.test.ts b/packages/core/src/testLint/gitSecrets.test.ts index deea710018a..fce29585d1c 100644 --- a/packages/core/src/testLint/gitSecrets.test.ts +++ b/packages/core/src/testLint/gitSecrets.test.ts @@ -25,19 +25,19 @@ describe('git-secrets', function () { function setAllowListPatterns(gitSecrets: string) { const allowListPatterns: string[] = ['"accountId": "123456789012"'] - allowListPatterns.forEach((pattern) => { + for (const pattern of allowListPatterns) { // Returns non-zero exit code if pattern already exists runCmd([gitSecrets, '--add', '--allowed', pattern], { cwd: toolkitProjectDir, throws: false }) - }) + } } function setDenyListPatterns(gitSecrets: string) { const denyListPatterns: string[] = [] - denyListPatterns.forEach((pattern) => { + for (const pattern of denyListPatterns) { // Returns non-zero exit code if pattern already exists runCmd([gitSecrets, '--add', pattern], { cwd: toolkitProjectDir, throws: false }) - }) + } } function setupTestFixturesDir(toolkitProjectDir: string) { diff --git a/packages/core/src/threatComposer/threatComposerEditor.ts b/packages/core/src/threatComposer/threatComposerEditor.ts index 8312113e16b..7bab20ca1a2 100644 --- a/packages/core/src/threatComposer/threatComposerEditor.ts +++ b/packages/core/src/threatComposer/threatComposerEditor.ts @@ -186,9 +186,9 @@ export class ThreatComposerEditor { this.isPanelDisposed = true contextObject.loaderNotification?.promiseResolve() this.onVisualizationDisposeEmitter.fire() - this.disposables.forEach((disposable) => { + for (const disposable of this.disposables) { disposable.dispose() - }) + } this.onVisualizationDisposeEmitter.dispose() }) } diff --git a/packages/core/src/webviews/client.ts b/packages/core/src/webviews/client.ts index 6125e738dac..e68935cf658 100644 --- a/packages/core/src/webviews/client.ts +++ b/packages/core/src/webviews/client.ts @@ -68,7 +68,9 @@ export class WebviewClientFactory { const { command } = event.data if (command === '$clear') { vscode.setState({}) - this.messageListeners.forEach((listener) => this.removeListener(listener)) + for (const listener of this.messageListeners) { + this.removeListener(listener) + } window.dispatchEvent(remountEvent) } }) diff --git a/packages/core/src/webviews/mixins/saveData.ts b/packages/core/src/webviews/mixins/saveData.ts index e5cacf3e0b7..da0fdd8923d 100644 --- a/packages/core/src/webviews/mixins/saveData.ts +++ b/packages/core/src/webviews/mixins/saveData.ts @@ -45,11 +45,11 @@ const saveData: Vue.ComponentOptionsMixin = { _unids.add(unid) const old = state[unid] ?? {} - Object.keys(this.$data).forEach((k) => { + for (const k of Object.keys(this.$data)) { this.$data[k] = old[k] ?? this.$data[k] - }) + } - Object.keys(this.$data).forEach((k) => { + for (const k of Object.keys(this.$data)) { this.$watch( k, (v: unknown) => { @@ -61,7 +61,7 @@ const saveData: Vue.ComponentOptionsMixin = { }, { deep: true } ) - }) + } }, } diff --git a/packages/toolkit/src/api.ts b/packages/toolkit/src/api.ts index 1cead54d6a5..9c9bb1f7a85 100644 --- a/packages/toolkit/src/api.ts +++ b/packages/toolkit/src/api.ts @@ -21,6 +21,7 @@ export const awsToolkitApi = { getLogger().debug(`listConnections: extension ${extensionId}`) const connections = await Auth.instance.listConnections() const exposedConnections: AwsConnection[] = [] + // eslint-disable-next-line unicorn/no-array-for-each connections.forEach((x: Connection) => { if (x.type === 'sso') { const connState = Auth.instance.getConnectionState(x) diff --git a/plugins/eslint-plugin-aws-toolkits/lib/rules/no-incorrect-once-usage.ts b/plugins/eslint-plugin-aws-toolkits/lib/rules/no-incorrect-once-usage.ts index 9a8a4853af7..a41dfd784fa 100644 --- a/plugins/eslint-plugin-aws-toolkits/lib/rules/no-incorrect-once-usage.ts +++ b/plugins/eslint-plugin-aws-toolkits/lib/rules/no-incorrect-once-usage.ts @@ -115,7 +115,7 @@ export default ESLintUtils.RuleCreator.withoutDocs({ return } - node.declarations.forEach((declaration) => { + for (const declaration of node.declarations) { if ( declaration.init?.type === AST_NODE_TYPES.CallExpression && declaration.id.type === AST_NODE_TYPES.Identifier && @@ -134,11 +134,11 @@ export default ESLintUtils.RuleCreator.withoutDocs({ // Check if it is being referenced multiple times // TODO: expand to check if it is being referenced inside nested scopes only? (currently checks current scope as well) if (refs.length > 1) { - return + continue } // Check if it is being referenced once, but inside a loop. - refs.forEach((ref) => { + for (const ref of refs) { let currNode: TSESTree.Node | undefined = ref.identifier while (currNode && currNode !== scope.block) { @@ -154,18 +154,19 @@ export default ESLintUtils.RuleCreator.withoutDocs({ } currNode = currNode.parent } - }) + } } // If the variable is somehow not assigned? or only used once and not in a loop. if (variable === undefined || !isUsedInLoopScope) { - return context.report({ + context.report({ node: declaration.init.callee, messageId: 'notReusableErr', }) + continue } } - }) + } }, } }, diff --git a/plugins/eslint-plugin-aws-toolkits/lib/rules/no-string-exec-for-child-process.ts b/plugins/eslint-plugin-aws-toolkits/lib/rules/no-string-exec-for-child-process.ts index 769b1157cfa..7313ceed61e 100644 --- a/plugins/eslint-plugin-aws-toolkits/lib/rules/no-string-exec-for-child-process.ts +++ b/plugins/eslint-plugin-aws-toolkits/lib/rules/no-string-exec-for-child-process.ts @@ -45,7 +45,7 @@ export default ESLintUtils.RuleCreator.withoutDocs({ ImportDeclaration(node: TSESTree.ImportDeclaration) { // Detect imports for child_process if (node.source.value === 'child_process') { - node.specifiers.forEach((specifier) => { + for (const specifier of node.specifiers) { if (specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier) { // Detect the name of the import, e.g. "proc" from "import * as proc from child_process" libImportName = specifier.local.name @@ -59,7 +59,7 @@ export default ESLintUtils.RuleCreator.withoutDocs({ messageId: 'errMsg', }) } - }) + } } }, CallExpression(node: TSESTree.CallExpression) {