diff --git a/src/client/common/extensions.ts b/src/client/common/extensions.ts index e595becd8331..616b21a33365 100644 --- a/src/client/common/extensions.ts +++ b/src/client/common/extensions.ts @@ -39,26 +39,6 @@ declare interface String { trimQuotes(): string; } -declare interface Array { - /** - * Returns the elements of an array that meet the condition specified in an async callback function. - * @param asyncPredicate The filter method calls the async predicate function one time for each element in the array. - */ - asyncFilter(asyncPredicate: (value: T) => Promise): Promise; -} - -/** - * Returns the elements of an array that meet the condition specified in an async callback function. - * @param asyncPredicate The filter method calls the async predicate function one time for each element in the array. - */ -Array.prototype.asyncFilter = async function ( - this: T[], - asyncPredicate: (value: T) => Promise, -): Promise { - const results = await Promise.all(this.map(asyncPredicate)); - return this.filter((_v, index) => results[index]); -}; - /** * Split a string using the cr and lf characters and return them as an array. * By default lines are trimmed and empty lines are removed. diff --git a/src/client/common/utils/arrayUtils.ts b/src/client/common/utils/arrayUtils.ts new file mode 100644 index 000000000000..c58f5a088942 --- /dev/null +++ b/src/client/common/utils/arrayUtils.ts @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * Returns the elements of an array that meet the condition specified in an async callback function. + * @param asyncPredicate The filter method calls the async predicate function one time for each element in the array. + */ +export async function asyncFilter(arr: T[], asyncPredicate: (value: T) => Promise): Promise { + const results = await Promise.all(arr.map(asyncPredicate)); + return arr.filter((_v, index) => results[index]); +} diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts index 3bf0dfa60d4f..54a37b115835 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts @@ -23,6 +23,7 @@ import { buildEnvInfo } from '../../info/env'; import { IPythonEnvsIterator } from '../../locator'; import { FSWatchingLocator } from './fsWatchingLocator'; import '../../../../common/extensions'; +import { asyncFilter } from '../../../../common/utils/arrayUtils'; /** * Default number of levels of sub-directories to recurse when looking for interpreters. @@ -33,7 +34,7 @@ const DEFAULT_SEARCH_DEPTH = 2; * Gets all default virtual environment locations to look for in a workspace. */ function getWorkspaceVirtualEnvDirs(root: string): Promise { - return [root, path.join(root, '.direnv')].asyncFilter(pathExists); + return asyncFilter([root, path.join(root, '.direnv')], pathExists); } /** diff --git a/src/client/pythonEnvironments/discovery/locators/services/customVirtualEnvLocator.ts b/src/client/pythonEnvironments/discovery/locators/services/customVirtualEnvLocator.ts index 05ffdcc5a257..5206a86f50ca 100644 --- a/src/client/pythonEnvironments/discovery/locators/services/customVirtualEnvLocator.ts +++ b/src/client/pythonEnvironments/discovery/locators/services/customVirtualEnvLocator.ts @@ -30,6 +30,7 @@ import { isVirtualenvwrapperEnvironment, } from './virtualEnvironmentIdentifier'; import '../../../../common/extensions'; +import { asyncFilter } from '../../../../common/utils/arrayUtils'; /** * Default number of levels of sub-directories to recurse when looking for interpreters. */ @@ -52,7 +53,7 @@ async function getCustomVirtualEnvDirs(): Promise { if (homeDir && (await pathExists(homeDir))) { venvFolders.map((item) => path.join(homeDir, item)).forEach((d) => venvDirs.push(d)); } - return uniq(venvDirs).asyncFilter(pathExists); + return asyncFilter(uniq(venvDirs), pathExists); } /** diff --git a/src/client/pythonEnvironments/discovery/locators/services/globalVirtualEnvronmentLocator.ts b/src/client/pythonEnvironments/discovery/locators/services/globalVirtualEnvronmentLocator.ts index 60cff72b334b..23c94eab13bd 100644 --- a/src/client/pythonEnvironments/discovery/locators/services/globalVirtualEnvronmentLocator.ts +++ b/src/client/pythonEnvironments/discovery/locators/services/globalVirtualEnvronmentLocator.ts @@ -24,6 +24,7 @@ import { isVirtualenvwrapperEnvironment, } from './virtualEnvironmentIdentifier'; import '../../../../common/extensions'; +import { asyncFilter } from '../../../../common/utils/arrayUtils'; const DEFAULT_SEARCH_DEPTH = 2; /** @@ -48,7 +49,10 @@ async function getGlobalVirtualEnvDirs(): Promise { if (getOSType() !== OSType.Windows) { subDirs.push('envs'); } - const filtered = await subDirs.map((d) => path.join(homeDir, d)).asyncFilter(pathExists); + const filtered = await asyncFilter( + subDirs.map((d) => path.join(homeDir, d)), + pathExists, + ); filtered.forEach((d) => venvDirs.push(d)); } diff --git a/src/client/pythonEnvironments/discovery/locators/services/poetryLocator.ts b/src/client/pythonEnvironments/discovery/locators/services/poetryLocator.ts index a0c7a03d8ed7..ba931072cb76 100644 --- a/src/client/pythonEnvironments/discovery/locators/services/poetryLocator.ts +++ b/src/client/pythonEnvironments/discovery/locators/services/poetryLocator.ts @@ -20,6 +20,7 @@ import { import { getFileInfo, isParentPath, pathExists } from '../../../common/externalDependencies'; import { isPoetryEnvironment, localPoetryEnvDirName, Poetry } from './poetry'; import '../../../../common/extensions'; +import { asyncFilter } from '../../../../common/utils/arrayUtils'; /** * Gets all default virtual environment locations to look for in a workspace. @@ -31,7 +32,7 @@ async function getVirtualEnvDirs(root: string): Promise { if (virtualenvs) { envDirs.push(...virtualenvs); } - return envDirs.asyncFilter(pathExists); + return asyncFilter(envDirs, pathExists); } async function getRootVirtualEnvDir(root: string): Promise { diff --git a/src/test/common/extensions.unit.test.ts b/src/test/common/extensions.unit.test.ts index dcd56fb4d22c..874b6e9bdcfb 100644 --- a/src/test/common/extensions.unit.test.ts +++ b/src/test/common/extensions.unit.test.ts @@ -1,5 +1,6 @@ import { assert, expect } from 'chai'; import '../../client/common/extensions'; +import { asyncFilter } from '../../client/common/utils/arrayUtils'; // Defines a Mocha test suite to group tests of similar kind together suite('String Extensions', () => { @@ -88,7 +89,7 @@ suite('String Extensions', () => { suite('Array extensions', () => { test('Async filter should filter items', async () => { const stringArray = ['Hello', 'I', 'am', 'the', 'Python', 'extension']; - const result = await stringArray.asyncFilter(async (s: string) => { + const result = await asyncFilter(stringArray, async (s: string) => { return s.length > 4; }); assert.deepEqual(result, ['Hello', 'Python', 'extension']);