Skip to content

Commit a1cccc5

Browse files
author
Kartik Raj
authored
Merge pull request microsoft#182238 from microsoft/kartik/puzzled-harrier
Updates to environment collection workspace API
2 parents 728197d + c2df3b7 commit a1cccc5

File tree

2 files changed

+125
-56
lines changed

2 files changed

+125
-56
lines changed

src/vs/workbench/api/common/extHostTerminalService.ts

Lines changed: 105 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, ID
5050
registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable;
5151
registerProfileProvider(extension: IExtensionDescription, id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable;
5252
registerTerminalQuickFixProvider(id: string, extensionId: string, provider: vscode.TerminalQuickFixProvider): vscode.Disposable;
53-
getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection;
53+
getEnvironmentVariableCollection(extension: IExtensionDescription): IEnvironmentVariableCollection;
5454
}
55-
55+
type IEnvironmentVariableCollection = vscode.EnvironmentVariableCollection & { getScopedEnvironmentVariableCollection(scope: vscode.EnvironmentVariableScope | undefined): vscode.EnvironmentVariableCollection };
5656
export interface ITerminalInternalOptions {
5757
isFeatureTerminal?: boolean;
5858
useShellEnvironment?: boolean;
@@ -823,13 +823,13 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
823823
return index;
824824
}
825825

826-
public getEnvironmentVariableCollection(extension: IExtensionDescription): vscode.EnvironmentVariableCollection {
826+
public getEnvironmentVariableCollection(extension: IExtensionDescription): IEnvironmentVariableCollection {
827827
let collection = this._environmentVariableCollections.get(extension.identifier.value);
828828
if (!collection) {
829829
collection = new EnvironmentVariableCollection();
830830
this._setEnvironmentVariableCollection(extension.identifier.value, collection);
831831
}
832-
return collection;
832+
return collection.getScopedEnvironmentVariableCollection(undefined);
833833
}
834834

835835
private _syncEnvironmentVariableCollection(extensionIdentifier: string, collection: EnvironmentVariableCollection): void {
@@ -867,8 +867,9 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
867867
}
868868
}
869869

870-
class EnvironmentVariableCollection implements vscode.EnvironmentVariableCollection {
870+
class EnvironmentVariableCollection {
871871
readonly map: Map<string, IEnvironmentVariableMutator> = new Map();
872+
private readonly scopedCollections: Map<string, ScopedEnvironmentVariableCollection> = new Map();
872873
readonly descriptionMap: Map<string, IEnvironmentDescriptionMutator> = new Map();
873874
private _persistent: boolean = true;
874875

@@ -887,23 +888,30 @@ class EnvironmentVariableCollection implements vscode.EnvironmentVariableCollect
887888
this.map = new Map(serialized);
888889
}
889890

890-
get size(): number {
891-
return this.map.size;
891+
getScopedEnvironmentVariableCollection(scope: vscode.EnvironmentVariableScope | undefined): IEnvironmentVariableCollection {
892+
const scopedCollectionKey = this.getScopeKey(scope);
893+
let scopedCollection = this.scopedCollections.get(scopedCollectionKey);
894+
if (!scopedCollection) {
895+
scopedCollection = new ScopedEnvironmentVariableCollection(this, scope);
896+
this.scopedCollections.set(scopedCollectionKey, scopedCollection);
897+
scopedCollection.onDidChangeCollection(() => this._onDidChangeCollection.fire());
898+
}
899+
return scopedCollection;
892900
}
893901

894-
replace(variable: string, value: string, scope?: vscode.EnvironmentVariableScope): void {
902+
replace(variable: string, value: string, scope: vscode.EnvironmentVariableScope | undefined): void {
895903
this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Replace, scope });
896904
}
897905

898-
append(variable: string, value: string, scope?: vscode.EnvironmentVariableScope): void {
906+
append(variable: string, value: string, scope: vscode.EnvironmentVariableScope | undefined): void {
899907
this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Append, scope });
900908
}
901909

902-
prepend(variable: string, value: string, scope?: vscode.EnvironmentVariableScope): void {
910+
prepend(variable: string, value: string, scope: vscode.EnvironmentVariableScope | undefined): void {
903911
this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Prepend, scope });
904912
}
905913

906-
private _setIfDiffers(variable: string, mutator: vscode.EnvironmentVariableMutator): void {
914+
private _setIfDiffers(variable: string, mutator: vscode.EnvironmentVariableMutator & { scope: vscode.EnvironmentVariableScope | undefined }): void {
907915
if (!mutator.scope) {
908916
delete (mutator as any).scope; // Convenient for tests
909917
}
@@ -917,44 +925,42 @@ class EnvironmentVariableCollection implements vscode.EnvironmentVariableCollect
917925
}
918926
}
919927

920-
get(variable: string, scope?: vscode.EnvironmentVariableScope): vscode.EnvironmentVariableMutator | undefined {
928+
get(variable: string, scope: vscode.EnvironmentVariableScope | undefined): vscode.EnvironmentVariableMutator | undefined {
921929
const key = this.getKey(variable, scope);
922930
const value = this.map.get(key);
923931
return value ? convertMutator(value) : undefined;
924932
}
925933

926934
private getKey(variable: string, scope: vscode.EnvironmentVariableScope | undefined) {
927-
const workspaceKey = this.getWorkspaceKey(scope?.workspaceFolder);
928-
return workspaceKey ? `${variable}:::${workspaceKey}` : variable;
935+
const scopeKey = this.getScopeKey(scope);
936+
return scopeKey.length ? `${variable}:::${scopeKey}` : variable;
929937
}
930938

931-
private getWorkspaceKey(workspaceFolder: vscode.WorkspaceFolder | undefined): string | undefined {
932-
return workspaceFolder ? workspaceFolder.uri.toString() : undefined;
939+
private getScopeKey(scope: vscode.EnvironmentVariableScope | undefined): string {
940+
return this.getWorkspaceKey(scope?.workspaceFolder) ?? '';
933941
}
934942

935-
forEach(callback: (variable: string, mutator: vscode.EnvironmentVariableMutator, collection: vscode.EnvironmentVariableCollection) => any, thisArg?: any): void {
936-
this.map.forEach((value, _) => callback.call(thisArg, value.variable, convertMutator(value), this));
943+
private getWorkspaceKey(workspaceFolder: vscode.WorkspaceFolder | undefined): string | undefined {
944+
return workspaceFolder ? workspaceFolder.uri.toString() : undefined;
937945
}
938946

939-
[Symbol.iterator](): IterableIterator<[variable: string, mutator: vscode.EnvironmentVariableMutator]> {
940-
const map: Map<string, vscode.EnvironmentVariableMutator> = new Map();
941-
this.map.forEach((mutator, _key) => {
942-
if (mutator.scope) {
943-
// Scoped mutators are not supported via this iterator, as it returns variable as the key which is supposed to be unique.
944-
return;
947+
public getVariableMap(scope: vscode.EnvironmentVariableScope | undefined): Map<string, IEnvironmentVariableMutator> {
948+
const map = new Map<string, IEnvironmentVariableMutator>();
949+
for (const [key, value] of this.map) {
950+
if (this.getScopeKey(value.scope) === this.getScopeKey(scope)) {
951+
map.set(key, value);
945952
}
946-
map.set(mutator.variable, convertMutator(mutator));
947-
});
948-
return map.entries();
953+
}
954+
return map;
949955
}
950956

951-
delete(variable: string, scope?: vscode.EnvironmentVariableScope): void {
957+
delete(variable: string, scope: vscode.EnvironmentVariableScope | undefined): void {
952958
const key = this.getKey(variable, scope);
953959
this.map.delete(key);
954960
this._onDidChangeCollection.fire();
955961
}
956962

957-
clear(scope?: vscode.EnvironmentVariableScope): void {
963+
clear(scope: vscode.EnvironmentVariableScope | undefined): void {
958964
if (scope?.workspaceFolder) {
959965
for (const [key, mutator] of this.map) {
960966
if (mutator.scope?.workspaceFolder?.index === scope.workspaceFolder.index) {
@@ -969,8 +975,8 @@ class EnvironmentVariableCollection implements vscode.EnvironmentVariableCollect
969975
this._onDidChangeCollection.fire();
970976
}
971977

972-
setDescription(description: string | vscode.MarkdownString | undefined, scope?: vscode.EnvironmentVariableScope): void {
973-
const key = this.getKey('', scope);
978+
setDescription(description: string | vscode.MarkdownString | undefined, scope: vscode.EnvironmentVariableScope | undefined): void {
979+
const key = this.getScopeKey(scope);
974980
const current = this.descriptionMap.get(key);
975981
if (!current || current.description !== description) {
976982
let descriptionStr: string | undefined;
@@ -986,12 +992,78 @@ class EnvironmentVariableCollection implements vscode.EnvironmentVariableCollect
986992
}
987993
}
988994

989-
private clearDescription(scope?: vscode.EnvironmentVariableScope): void {
990-
const key = this.getKey('', scope);
995+
public getDescription(scope: vscode.EnvironmentVariableScope | undefined): string | vscode.MarkdownString | undefined {
996+
const key = this.getScopeKey(scope);
997+
return this.descriptionMap.get(key)?.description;
998+
}
999+
1000+
private clearDescription(scope: vscode.EnvironmentVariableScope | undefined): void {
1001+
const key = this.getScopeKey(scope);
9911002
this.descriptionMap.delete(key);
9921003
}
9931004
}
9941005

1006+
class ScopedEnvironmentVariableCollection implements vscode.EnvironmentVariableCollection, IEnvironmentVariableCollection {
1007+
public get persistent(): boolean { return this.collection.persistent; }
1008+
public set persistent(value: boolean) {
1009+
this.collection.persistent = value;
1010+
}
1011+
1012+
protected readonly _onDidChangeCollection = new Emitter<void>();
1013+
get onDidChangeCollection(): Event<void> { return this._onDidChangeCollection && this._onDidChangeCollection.event; }
1014+
1015+
constructor(
1016+
private readonly collection: EnvironmentVariableCollection,
1017+
private readonly scope: vscode.EnvironmentVariableScope | undefined
1018+
) {
1019+
}
1020+
1021+
getScopedEnvironmentVariableCollection() {
1022+
return this.collection.getScopedEnvironmentVariableCollection(this.scope);
1023+
}
1024+
1025+
replace(variable: string, value: string): void {
1026+
this.collection.replace(variable, value, this.scope);
1027+
}
1028+
1029+
append(variable: string, value: string): void {
1030+
this.collection.append(variable, value, this.scope);
1031+
}
1032+
1033+
prepend(variable: string, value: string): void {
1034+
this.collection.prepend(variable, value, this.scope);
1035+
}
1036+
1037+
get(variable: string): vscode.EnvironmentVariableMutator | undefined {
1038+
return this.collection.get(variable, this.scope);
1039+
}
1040+
1041+
forEach(callback: (variable: string, mutator: vscode.EnvironmentVariableMutator, collection: vscode.EnvironmentVariableCollection) => any, thisArg?: any): void {
1042+
this.collection.getVariableMap(this.scope).forEach((value, variable) => callback.call(thisArg, variable, convertMutator(value), this), this.scope);
1043+
}
1044+
1045+
[Symbol.iterator](): IterableIterator<[variable: string, mutator: vscode.EnvironmentVariableMutator]> {
1046+
return this.collection.getVariableMap(this.scope).entries();
1047+
}
1048+
1049+
delete(variable: string): void {
1050+
this.collection.delete(variable, this.scope);
1051+
this._onDidChangeCollection.fire(undefined);
1052+
}
1053+
1054+
clear(): void {
1055+
this.collection.clear(this.scope);
1056+
}
1057+
1058+
set description(description: string | vscode.MarkdownString | undefined) {
1059+
this.collection.setDescription(description, this.scope);
1060+
}
1061+
1062+
get description(): string | vscode.MarkdownString | undefined {
1063+
return this.collection.getDescription(this.scope);
1064+
}
1065+
}
1066+
9951067
export class WorkerExtHostTerminalService extends BaseExtHostTerminalService {
9961068
constructor(
9971069
@IExtHostRpcService extHostRpc: IExtHostRpcService

src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,30 @@
55

66
declare module 'vscode' {
77

8-
// https://github.com/microsoft/vscode/issues/171173
8+
// https://github.com/microsoft/vscode/issues/182069
99

10-
export interface EnvironmentVariableMutator {
11-
readonly type: EnvironmentVariableMutatorType;
12-
readonly value: string;
13-
readonly scope: EnvironmentVariableScope | undefined;
14-
}
15-
16-
export interface EnvironmentVariableCollection extends Iterable<[variable: string, mutator: EnvironmentVariableMutator]> {
17-
/**
18-
* Sets a description for the environment variable collection, this will be used to describe the changes in the UI.
19-
* @param description A description for the environment variable collection.
20-
* @param scope Specific scope to which this description applies to.
21-
*/
22-
setDescription(description: string | MarkdownString | undefined, scope?: EnvironmentVariableScope): void;
23-
replace(variable: string, value: string, scope?: EnvironmentVariableScope): void;
24-
append(variable: string, value: string, scope?: EnvironmentVariableScope): void;
25-
prepend(variable: string, value: string, scope?: EnvironmentVariableScope): void;
26-
get(variable: string, scope?: EnvironmentVariableScope): EnvironmentVariableMutator | undefined;
27-
delete(variable: string, scope?: EnvironmentVariableScope): void;
28-
clear(scope?: EnvironmentVariableScope): void;
29-
}
10+
// export interface ExtensionContext {
11+
// /**
12+
// * Gets the extension's environment variable collection for this workspace, enabling changes
13+
// * to be applied to terminal environment variables.
14+
// *
15+
// * @param scope The scope to which the environment variable collection applies to.
16+
// */
17+
// readonly environmentVariableCollection: EnvironmentVariableCollection & { getScopedEnvironmentVariableCollection(scope: EnvironmentVariableScope): EnvironmentVariableCollection };
18+
// }
3019

3120
export type EnvironmentVariableScope = {
3221
/**
33-
* The workspace folder to which this collection applies to. If unspecified, collection applies to all workspace folders.
34-
*/
22+
* Any specific workspace folder to get collection for. If unspecified, collection applicable to all workspace folders is returned.
23+
*/
3524
workspaceFolder?: WorkspaceFolder;
3625
};
26+
27+
export interface EnvironmentVariableCollection extends Iterable<[variable: string, mutator: EnvironmentVariableMutator]> {
28+
/**
29+
* A description for the environment variable collection, this will be used to describe the
30+
* changes in the UI.
31+
*/
32+
description: string | MarkdownString | undefined;
33+
}
3734
}

0 commit comments

Comments
 (0)