Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the ultimate quick pick experience #1229

Merged
merged 55 commits into from
Dec 7, 2022
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
80e57f6
It's full of stars
bwateratmsft Aug 30, 2022
df01530
Add a TODO comment
bwateratmsft Aug 30, 2022
493704b
Some explanatory comments
bwateratmsft Aug 31, 2022
39c3dd3
Check if isLeaf is null instead of undefined
alexweininger Sep 2, 2022
e7e66a2
Boxing / unboxing functionality (#1231)
alexweininger Sep 2, 2022
789b44a
Check `undefined` and `null`
bwateratmsft Sep 6, 2022
da6ccc3
Add find-by-ID experience and step
bwateratmsft Sep 6, 2022
bb38f55
Merge remote-tracking branch 'origin/api-v2' into bmw/quickPick_v8.30
alexweininger Sep 6, 2022
28c5e44
Changes to tree item picker (#1232)
alexweininger Sep 7, 2022
4a544a4
Commit rough progress
bwateratmsft Sep 9, 2022
77cd7d9
Rename Box to Wrapper
bwateratmsft Sep 9, 2022
09ec22a
Add compatibility steps (#1235)
alexweininger Sep 15, 2022
14f9334
Refactor and expose `isAzExtParentTreeItem` (#1236)
alexweininger Sep 16, 2022
d29d16d
Fix circular dependency (#1238)
alexweininger Sep 16, 2022
25018ea
Remove reliance on `quickPickOptions`, use `TreeItem`s directly (#1239)
alexweininger Sep 23, 2022
2c67a25
Add `PickFilter` interface and refactor steps (#1240)
alexweininger Oct 3, 2022
904f0a2
Fix go back behavior (#1241)
alexweininger Oct 6, 2022
a159f8c
Add compatibility pick subscription experience (#1245)
alexweininger Oct 13, 2022
086856a
Add `unwrapArgs` util (#1246)
alexweininger Oct 17, 2022
06b63ac
Add minimal v2 api types
alexweininger Oct 17, 2022
df3e93c
Add `getResourceGroupsApi` util (#1248)
alexweininger Oct 18, 2022
8121774
Fixup
alexweininger Oct 18, 2022
cfd9468
Fix `compatibilitySubscriptionExperience`
alexweininger Oct 19, 2022
7db798f
Rename `PickFilter` methods
alexweininger Nov 3, 2022
3227c42
Default `hideStepCount` to `true` in `RecursiveQuickPickStep`
alexweininger Nov 3, 2022
e23facc
Remove redundant `skipIfOne` property
alexweininger Nov 4, 2022
4d3502b
Add registerCommandWithTreeNodeUnwrapping util (#1262)
alexweininger Nov 7, 2022
580ffc7
Merge remote-tracking branch 'origin/api-v2' into bmw/quickPick_v8.30
alexweininger Nov 8, 2022
3999dda
Merge remote-tracking branch 'origin/api-v2' into bmw/quickPick_v8.30
alexweininger Nov 8, 2022
cc4bdc7
Move `isAzExtTreeItem`
alexweininger Nov 10, 2022
a9501cc
Expose a subset of `vscode.TreeDataProvider`.
alexweininger Nov 11, 2022
ee794bd
Fixup `isAncestorPick` jsdoc
alexweininger Nov 11, 2022
f448f8a
Use `Array.prototype.at`
alexweininger Nov 12, 2022
6164932
Fix double parens
alexweininger Nov 12, 2022
af98623
Make a copy of context
alexweininger Nov 15, 2022
6d0c31c
Move file
alexweininger Nov 15, 2022
d9367fb
import type
alexweininger Nov 15, 2022
23fe238
Organize compatibility experiences into namespace
alexweininger Nov 15, 2022
d31f406
Remove findById steps and experience
alexweininger Nov 29, 2022
07f0e5e
Add `isAzExtTreeItem` util (#1280)
alexweininger Nov 30, 2022
a084caf
Merge branch 'main' into api-v2
alexweininger Dec 5, 2022
22fe99a
Merge branch 'api-v2' into bmw/quickPick_v8.30
alexweininger Dec 6, 2022
adbb83b
Delete isAzExtParentTreeItem.ts
alexweininger Dec 6, 2022
5544e3b
Reset changes to AzExtTreeItem* classes
alexweininger Dec 6, 2022
bbebe06
Temporarily remove apiUtils
alexweininger Dec 6, 2022
2390d1e
Fixups
alexweininger Dec 6, 2022
6c36000
Remove pick resource group step
alexweininger Dec 6, 2022
0bbe730
Rename and move file
alexweininger Dec 6, 2022
92616e8
Rename to final + ancestor naming
alexweininger Dec 6, 2022
619e6da
Rename item to element
alexweininger Dec 6, 2022
d02d880
Add v2 hostapi typings (#1289)
alexweininger Dec 6, 2022
9d2f0dc
Merge branch 'api-v2' into bmw/quickPick_v8.30
alexweininger Dec 6, 2022
1d8ac62
Merge remote-tracking branch 'origin/main' into bmw/quickPick_v8.30
alexweininger Dec 6, 2022
feb7cf0
Remove unused QuickPickWithCreateStep for now
alexweininger Dec 6, 2022
7c150b8
Make some types internal
alexweininger Dec 6, 2022
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
8 changes: 4 additions & 4 deletions utils/hostapi.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface AzureHostExtensionApi {
/**
* The VSCode TreeView for the shared app resource view
*/
readonly appResourceTreeView: vscode.TreeView<AzExtTreeItem>;
readonly appResourceTreeView: vscode.TreeView<unknown>;

/**
* The `AzExtTreeDataProvider` for the shared workspace resource view
Expand All @@ -28,12 +28,12 @@ export interface AzureHostExtensionApi {
/**
* The VSCode TreeView for the shared workspace resource view
*/
readonly workspaceResourceTreeView: vscode.TreeView<AzExtTreeItem>;
readonly workspaceResourceTreeView: vscode.TreeView<unknown>;

/**
* Version of the API
*/
readonly apiVersion: string;
readonly apiVersion: '0.0.1';

/**
* Reveals an item in the shared app resource tree
Expand Down Expand Up @@ -76,7 +76,7 @@ export interface AzureHostExtensionApi {
/**
* @deprecated Use `appResourceTreeView` instead
*/
readonly treeView: vscode.TreeView<AzExtTreeItem>;
readonly treeView: vscode.TreeView<unknown>;

/**
* @deprecated Use `registerWorkspaceResourceProvider` instead
Expand Down
67 changes: 67 additions & 0 deletions utils/hostapi.v2.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import type { IActionContext, AzExtResourceType, QuickPickWizardContext } from "./index";
import * as vscode from 'vscode';
import type { Environment } from '@azure/ms-rest-azure-env';
import { AzureExtensionApi } from "./api";

export declare interface ApplicationAuthentication {
getSession(scopes?: string[]): vscode.ProviderResult<vscode.AuthenticationSession>;
}

/**
* Information specific to the Subscription
*/
export interface ApplicationSubscription {
alexweininger marked this conversation as resolved.
Show resolved Hide resolved
readonly authentication: ApplicationAuthentication;
readonly displayName: string;
readonly subscriptionId: string;
readonly subscriptionPath: string;
readonly tenantId: string;
readonly environment: Environment;
readonly isCustomCloud: boolean;
}

export declare interface ResourceBase {
readonly id: string;
readonly name: string;
}

export declare interface ApplicationResourceType {
readonly type: string;
readonly kinds?: string[];
}

/**
* Represents an individual resource in Azure.
* @remarks The `id` property is expected to be the Azure resource ID.
*/
export declare interface ApplicationResource extends ResourceBase {
alexweininger marked this conversation as resolved.
Show resolved Hide resolved
readonly subscription: ApplicationSubscription;
readonly type: ApplicationResourceType;
readonly azExtResourceType?: AzExtResourceType;
readonly location?: string;
readonly resourceGroup?: string;
/** Resource tags */
readonly tags?: {
[propertyName: string]: string;
};
/* add more properties from GenericResource if needed */
}

export declare interface PickSubscriptionWizardContext extends QuickPickWizardContext {
bwateratmsft marked this conversation as resolved.
Show resolved Hide resolved
subscription?: ApplicationSubscription;
}

export declare interface AzureResourceQuickPickWizardContext extends QuickPickWizardContext, PickSubscriptionWizardContext {
resource?: ApplicationResource;
resourceGroup?: string;
}

export interface V2AzureResourcesApi extends AzureExtensionApi {
readonly applicationResourceTreeDataProvider: vscode.TreeDataProvider<unknown>;
alexweininger marked this conversation as resolved.
Show resolved Hide resolved
readonly workspaceResourceTreeDataProvider: vscode.TreeDataProvider<unknown>;
}
114 changes: 110 additions & 4 deletions utils/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import type { Environment } from '@azure/ms-rest-azure-env';
import { CancellationToken, CancellationTokenSource, Disposable, Event, ExtensionContext, FileChangeEvent, FileChangeType, FileStat, FileSystemProvider, FileType, InputBoxOptions, MarkdownString, MessageItem, MessageOptions, OpenDialogOptions, OutputChannel, Progress, QuickPickItem, QuickPickOptions, TextDocumentShowOptions, ThemeIcon, TreeDataProvider, TreeItem, TreeItemCollapsibleState, TreeView, Uri } from 'vscode';
import { CancellationToken, CancellationTokenSource, Disposable, Event, ExtensionContext, FileChangeEvent, FileChangeType, FileStat, FileSystemProvider, FileType, InputBoxOptions, MarkdownString, MessageItem, MessageOptions, OpenDialogOptions, OutputChannel, Progress, QuickPickItem, QuickPickOptions as VSCodeQuickPickOptions, TextDocumentShowOptions, ThemeIcon, TreeDataProvider, TreeItem, TreeItemCollapsibleState, TreeView, Uri } from 'vscode';
import { TargetPopulation } from 'vscode-tas-client';
import { AzureExtensionApi, AzureExtensionApiProvider } from './api';
import type { Activity, ActivityTreeItemOptions, AppResource, OnErrorActivityData, OnProgressActivityData, OnStartActivityData, OnSuccessActivityData } from './hostapi'; // This must remain `import type` or else a circular reference will result
import type { Activity, ActivityTreeItemOptions, AppResource, AzureHostExtensionApi, OnErrorActivityData, OnProgressActivityData, OnStartActivityData, OnSuccessActivityData } from './hostapi'; // This must remain `import type` or else a circular reference will result

export declare interface RunWithTemporaryDescriptionOptions {
description: string;
Expand Down Expand Up @@ -464,6 +464,9 @@ export declare abstract class AzExtTreeItem implements IAzExtTreeItem {
public resolveTooltip?(): Promise<string | MarkdownString>;
}

export declare function isAzExtTreeItem(maybeTreeItem: unknown): maybeTreeItem is AzExtTreeItem;
alexweininger marked this conversation as resolved.
Show resolved Hide resolved
export declare function isAzExtParentTreeItem(maybeParentTreeItem: unknown): maybeParentTreeItem is AzExtParentTreeItem;

export interface IGenericTreeItemOptions {
id?: string;
label: string;
Expand Down Expand Up @@ -635,7 +638,9 @@ export declare class UserCancelledError extends Error {
constructor(stepName?: string);
}

export declare class NoResourceFoundError extends Error { }
export declare class NoResourceFoundError extends Error {
constructor(context?: ITreeItemPickerContext);
}

export type CommandCallback = (context: IActionContext, ...args: any[]) => any;

Expand Down Expand Up @@ -990,7 +995,7 @@ export interface IAzureQuickPickItem<T = undefined> extends QuickPickItem {
/**
* Provides additional options for QuickPicks used in Azure Extensions
*/
export interface IAzureQuickPickOptions extends QuickPickOptions, AzExtUserInputOptions {
export interface IAzureQuickPickOptions extends VSCodeQuickPickOptions, AzExtUserInputOptions {
nturinski marked this conversation as resolved.
Show resolved Hide resolved
/**
* An optional id to identify this QuickPick across sessions, used in persisting previous selections
* If not specified, a hash of the placeHolder will be used
Expand Down Expand Up @@ -1676,3 +1681,104 @@ export declare enum AzExtResourceType {
VirtualNetworks = 'VirtualNetworks',
WebHostingEnvironments = 'WebHostingEnvironments',
}

/**
* Describes command callbacks for tree node context menu commands
*/
export type TreeNodeCommandCallback<T> = (context: IActionContext, node?: T, nodes?: T[], ...args: any[]) => any;

/**
* Used to register VSCode tree node context menu commands that are in the host extension's tree. It wraps your callback with consistent error and telemetry handling
* Use debounce property if you need a delay between clicks for this particular command
* A telemetry event is automatically sent whenever a command is executed. The telemetry event ID will default to the same as the
* commandId passed in, but can be overridden per command with telemetryId
* The telemetry event for this command will be named telemetryId if specified, otherwise it defaults to the commandId
* NOTE: If the environment variable `DEBUGTELEMETRY` is set to a non-empty, non-zero value, then telemetry will not be sent. If the value is 'verbose' or 'v', telemetry will be displayed in the console window.
*/
export declare function registerCommandWithTreeNodeUnwrapping<T>(commandId: string, callback: TreeNodeCommandCallback<T>, debounce?: number, telemetryId?: string): void;

export declare function unwrapArgs<T>(treeNodeCallback: TreeNodeCommandCallback<T>): TreeNodeCommandCallback<T>;

/**
* Interface describing an object that wraps another object.
*
* The host extension will wrap all tree nodes provided by the client
* extensions. When commands are executed, the wrapper objects are
* sent directly to the client extension, which will need to unwrap
* them. The `registerCommandWithTreeNodeUnwrapping` method below, used
* in place of `registerCommand`, will intelligently do this
* unwrapping automatically (i.e., will not unwrap if the arguments
* aren't wrappers)
*/
export declare interface Wrapper {
unwrap<T>(): T;
}

// temporary
type ResourceGroupsItem = unknown;

/**
* Tests to see if something is a wrapper, by ensuring it is an object
* and has an "unwrap" function
* @param maybeWrapper An object to test if it is a wrapper
* @returns True if a wrapper, false otherwise
*/
export declare function isWrapper(maybeWrapper: unknown): maybeWrapper is Wrapper;

export declare function appResourceExperience<TPick extends unknown>(context: IActionContext, tdp: TreeDataProvider<ResourceGroupsItem>, resourceTypes?: AzExtResourceType | AzExtResourceType[], childItemFilter?: ContextValueFilter): Promise<TPick>;
bwateratmsft marked this conversation as resolved.
Show resolved Hide resolved
export declare function contextValueExperience<TPick extends unknown>(context: IActionContext, tdp: TreeDataProvider<ResourceGroupsItem>, contextValueFilter: ContextValueFilter): Promise<TPick>;
export declare function findByIdExperience<TPick extends unknown>(context: IActionContext, tdp: TreeDataProvider<ResourceGroupsItem>, id: string | Uri): Promise<TPick>;

interface CompatibilityPickResourceExperienceOptions {
resourceTypes?: AzExtResourceType | AzExtResourceType[];
childItemFilter?: ContextValueFilter
}

export declare function compatibilityPickAppResourceExperience<TPick extends AzExtTreeItem>(context: IActionContext, tdp: TreeDataProvider<ResourceGroupsItem>, options: CompatibilityPickResourceExperienceOptions): Promise<TPick>;
export declare function compatibilitySubscriptionExperience(context: IActionContext, tdp: TreeDataProvider<ResourceGroupsItem>): Promise<ISubscriptionContext>;

export declare interface QuickPickWizardContext extends IActionContext {
pickedNodes: unknown[];
}

/**
* Describes filtering based on context value. Items that pass the filter will
* match at least one of the `include` filters, but none of the `exclude` filters.
*/
export declare interface ContextValueFilter {
/**
* This filter will include items that match *any* of the values in the array.
* When a string is used, exact value comparison is done.
*/
include: string | RegExp | (string | RegExp)[];
nturinski marked this conversation as resolved.
Show resolved Hide resolved

/**
* This filter will exclude items that match *any* of the values in the array.
* When a string is used, exact value comparison is done.
*/
exclude?: string | RegExp | (string | RegExp)[];
}

type CreateCallback<TNode = unknown> = (context: IActionContext) => TNode | Promise<TNode>;

type CreateOptions<TNode = unknown> = {
label?: string;
callback: CreateCallback<TNode>;
}

export declare interface FindableByIdTreeNodeV2 {
id: string;
}

export declare type FindableByIdTreeNode = FindableByIdTreeNodeV2 | AzExtTreeItem;

/**
* Gets the Azure Resource Groups API
*/
export declare function getResourceGroupsApi(apiVersionRange: AzureHostExtensionApi['apiVersion']): Promise<AzureHostExtensionApi>;
alexweininger marked this conversation as resolved.
Show resolved Hide resolved
export declare function getResourceGroupsApi<T extends AzureExtensionApi>(apiVersionRange: string): Promise<T>;

/**
* Get exported API from an extension
*/
export declare function getApiExport<T>(extensionId: string): Promise<T | undefined>;
8 changes: 8 additions & 0 deletions utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export { addExtensionValueToMask, callWithMaskHandling, maskValue } from './mask
export * from './openReadOnlyContent';
export * from './parseError';
export * from './registerCommand';
export * from './registerCommandWithTreeNodeUnwrapping';
export * from './registerEvent';
export { registerReportIssueCommand } from './registerReportIssueCommand';
export * from './tree/AzExtParentTreeItem';
Expand All @@ -36,4 +37,11 @@ export * from './utils/contextUtils';
export * from './activityLog/activities/ExecuteActivity';
export * from './getAzExtResourceType';
export * from './AzExtResourceType';
export * from './treev2/quickPickWizard/experiences/appResourceExperience';
export * from './treev2/quickPickWizard/experiences/compatibilityPickResourceExperience';
export * from './treev2/quickPickWizard/experiences/contextValueExperience';
export * from './treev2/quickPickWizard/experiences/findByIdExperience';
export * from './treev2/quickPickWizard/experiences/compatibility/compatibilityPickSubscriptionExperience';
export * from './tree/isAzExtParentTreeItem';
export * from './utils/apiUtils';
// NOTE: The auto-fix action "source.organizeImports" does weird things with this file, but there doesn't seem to be a way to disable it on a per-file basis so we'll just let it happen
53 changes: 53 additions & 0 deletions utils/src/registerCommandWithTreeNodeUnwrapping.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*---------------------------------------------------------------------------------------------
alexweininger marked this conversation as resolved.
Show resolved Hide resolved
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import type { IActionContext, Wrapper, TreeNodeCommandCallback } from '../index';
import { registerCommand } from './registerCommand';

export function registerCommandWithTreeNodeUnwrapping<T>(commandId: string, treeNodeCallback: TreeNodeCommandCallback<T>, debounce?: number, telemetryId?: string): void {
registerCommand(commandId, unwrapArgs(treeNodeCallback), debounce, telemetryId);
}

export function unwrapArgs<T>(treeNodeCallback: TreeNodeCommandCallback<T>): TreeNodeCommandCallback<T> {
return async (context: IActionContext, ...args: unknown[]) => {
const maybeNodeWrapper = args?.[0];
const maybeNodeWrapperArray = args?.[1];
const remainingArgs = args.slice(2);

let node: T | undefined;
if (maybeNodeWrapper && isWrapper(maybeNodeWrapper)) {
// If the first arg is a wrapper, unwrap it
node = await maybeNodeWrapper.unwrap();
} else if (maybeNodeWrapper) {
// Otherwise, assume it is just a T
node = maybeNodeWrapper as T;
}

let nodes: T[] | undefined;
if (maybeNodeWrapperArray && Array.isArray(maybeNodeWrapperArray) && maybeNodeWrapperArray.every(n => isWrapper(n))) {
// If the first arg is an array of wrappers, unwrap them
const wrappedNodes = maybeNodeWrapperArray as Wrapper[];
nodes = [];
for (const n of wrappedNodes) {
nodes.push(n.unwrap<T>())
}
} else if (maybeNodeWrapperArray && Array.isArray(maybeNodeWrapperArray)) {
// Otherwise, assume it is just an array of T's
nodes = maybeNodeWrapperArray as T[];
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return treeNodeCallback(context, node, nodes, ...remainingArgs);
};
}

export function isWrapper(maybeWrapper: unknown): maybeWrapper is Wrapper {
if (maybeWrapper && typeof maybeWrapper === 'object' &&
(maybeWrapper as Wrapper).unwrap && typeof (maybeWrapper as Wrapper).unwrap === 'function') {
return true;
}

return false;
}
5 changes: 3 additions & 2 deletions utils/src/tree/AzExtParentTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import { localize } from '../localize';
import { randomUtils } from '../utils/randomUtils';
import { AzExtTreeItem } from './AzExtTreeItem';
import { GenericTreeItem } from './GenericTreeItem';
import { IAzExtParentTreeItemInternal, isAzExtParentTreeItem } from './InternalInterfaces';
import { IAzExtParentTreeItemInternal } from './InternalInterfaces';
import { isAzExtParentTreeItem } from './isAzExtParentTreeItem';
import { runWithLoadingNotification } from './runWithLoadingNotification';
import { loadMoreLabel } from './treeConstants';

Expand Down Expand Up @@ -246,7 +247,7 @@ export abstract class AzExtParentTreeItem extends AzExtTreeItem implements types
// Just in case implementers of `loadMoreChildrenImpl` re-use the same child node, we want to clear those caches as well
for (const child of this._cachedChildren) {
if (isAzExtParentTreeItem(child)) {
(<AzExtParentTreeItem>child).clearCache();
child.clearCache();
alexweininger marked this conversation as resolved.
Show resolved Hide resolved
}
}
this._cachedChildren = [];
Expand Down
7 changes: 4 additions & 3 deletions utils/src/tree/AzExtTreeDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { AzExtParentTreeItem, InvalidTreeItem } from './AzExtParentTreeItem';
import { AzExtTreeItem } from './AzExtTreeItem';
import { CollapsibleStateTracker } from './CollapsibleStateTracker';
import { GenericTreeItem } from './GenericTreeItem';
import { IAzExtTreeDataProviderInternal, isAzExtParentTreeItem } from './InternalInterfaces';
import { IAzExtTreeDataProviderInternal } from './InternalInterfaces';
import { isAzExtParentTreeItem } from './isAzExtParentTreeItem';
import { runWithLoadingNotification } from './runWithLoadingNotification';
import { loadMoreLabel } from './treeConstants';

Expand Down Expand Up @@ -147,7 +148,7 @@ export class AzExtTreeDataProvider implements IAzExtTreeDataProviderInternal, ty
}

if (isAzExtParentTreeItem(treeItem)) {
(<AzExtParentTreeItem>treeItem).clearCache();
treeItem.clearCache();
}

this.refreshUIOnly(treeItem);
Expand Down Expand Up @@ -179,7 +180,7 @@ export class AzExtTreeDataProvider implements IAzExtTreeDataProviderInternal, ty

while (!treeItem.matchesContextValue(expectedContextValues)) {
if (isAzExtParentTreeItem(treeItem)) {
const pickedItems: AzExtTreeItem | AzExtTreeItem[] = await (<AzExtParentTreeItem>treeItem).pickChildTreeItem(expectedContextValues, context);
const pickedItems: AzExtTreeItem | AzExtTreeItem[] = await treeItem.pickChildTreeItem(expectedContextValues, context);
if (Array.isArray(pickedItems)) {
// canPickMany is only supported at the last stage of the picker, so automatically return if this is an array
return <T[]><unknown>pickedItems;
Expand Down
7 changes: 5 additions & 2 deletions utils/src/tree/AzExtTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ import * as types from '../../index';
import { NotImplementedError } from '../errors';
import { localize } from '../localize';
import { nonNullProp } from '../utils/nonNull';
import { IAzExtParentTreeItemInternal, IAzExtTreeDataProviderInternal, isAzExtParentTreeItem } from "./InternalInterfaces";
import { IAzExtParentTreeItemInternal, IAzExtTreeDataProviderInternal } from "./InternalInterfaces";
import { settingUtils } from '../utils/settingUtils';
import { showContextValueSetting } from '../constants';
import { isAzExtParentTreeItem } from './isAzExtParentTreeItem';

export abstract class AzExtTreeItem implements types.AzExtTreeItem {
public readonly _isAzExtTreeItem = true;

//#region Properties implemented by base class
public abstract label: string;
public abstract contextValue: string;
Expand Down Expand Up @@ -120,7 +123,7 @@ export abstract class AzExtTreeItem implements types.AzExtTreeItem {
}

public get tooltip(): string | undefined {
if(process.env.DEBUGTELEMETRY === 'v' && !!settingUtils.getWorkspaceSetting<unknown>(showContextValueSetting)) {
if (process.env.DEBUGTELEMETRY === 'v' && !!settingUtils.getWorkspaceSetting<unknown>(showContextValueSetting)) {
return `Context: "${this.contextValue}"`;
} else {
return this._tooltip;
Expand Down
Loading