Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions src/client/common/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,6 @@ declare interface String {
trimQuotes(): string;
}

declare interface Array<T> {
/**
* 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<unknown>): Promise<T[]>;
}

/**
* 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 <T>(
this: T[],
asyncPredicate: (value: T) => Promise<unknown>,
): Promise<T[]> {
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.
Expand Down
11 changes: 11 additions & 0 deletions src/client/common/utils/arrayUtils.ts
Original file line number Diff line number Diff line change
@@ -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<T>(arr: T[], asyncPredicate: (value: T) => Promise<unknown>): Promise<T[]> {
const results = await Promise.all(arr.map(asyncPredicate));
return arr.filter((_v, index) => results[index]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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<string[]> {
return [root, path.join(root, '.direnv')].asyncFilter(pathExists);
return asyncFilter([root, path.join(root, '.direnv')], pathExists);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -52,7 +53,7 @@ async function getCustomVirtualEnvDirs(): Promise<string[]> {
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);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
isVirtualenvwrapperEnvironment,
} from './virtualEnvironmentIdentifier';
import '../../../../common/extensions';
import { asyncFilter } from '../../../../common/utils/arrayUtils';

const DEFAULT_SEARCH_DEPTH = 2;
/**
Expand All @@ -48,7 +49,10 @@ async function getGlobalVirtualEnvDirs(): Promise<string[]> {
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));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -31,7 +32,7 @@ async function getVirtualEnvDirs(root: string): Promise<string[]> {
if (virtualenvs) {
envDirs.push(...virtualenvs);
}
return envDirs.asyncFilter(pathExists);
return asyncFilter(envDirs, pathExists);
}

async function getRootVirtualEnvDir(root: string): Promise<string[]> {
Expand Down
3 changes: 2 additions & 1 deletion src/test/common/extensions.unit.test.ts
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand Down Expand Up @@ -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']);
Expand Down