Skip to content

Commit 11f523c

Browse files
committed
Support scmResourceState in when clauses
fixes #86180 * Adds `contextValue?: string` to the SourceControlResourceState * Allows when clause in scm/resourceState/context menus to use scmResourceState
1 parent 69e0508 commit 11f523c

File tree

7 files changed

+68
-18
lines changed

7 files changed

+68
-18
lines changed

src/vs/vscode.proposed.d.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1734,4 +1734,30 @@ declare module 'vscode' {
17341734
}
17351735

17361736
//#endregion
1737+
1738+
//#region Support `scmResourceState` in `when` clauses #86180 https://github.com/microsoft/vscode/issues/86180
1739+
1740+
export interface SourceControlResourceState {
1741+
/**
1742+
* Context value of the resource state. This can be used to contribute resource specific actions.
1743+
* For example, if a resource is given a context value as `diffable`. When contributing actions to `scm/resourceState/context`
1744+
* using `menus` extension point, you can specify context value for key `scmResourceState` in `when` expressions, like `scmResourceState == diffable`.
1745+
* ```
1746+
* "contributes": {
1747+
* "menus": {
1748+
* "scm/resourceState/context": [
1749+
* {
1750+
* "command": "extension.diff",
1751+
* "when": "scmResourceState == diffable"
1752+
* }
1753+
* ]
1754+
* }
1755+
* }
1756+
* ```
1757+
* This will show action `extension.diff` only for resources with `contextValue` is `diffable`.
1758+
*/
1759+
readonly contextValue?: string;
1760+
}
1761+
1762+
//#endregion
17371763
}

src/vs/workbench/api/browser/mainThreadSCM.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ class MainThreadSCMResource implements ISCMResource {
6868
private readonly handle: number,
6969
public sourceUri: URI,
7070
public resourceGroup: ISCMResourceGroup,
71-
public decorations: ISCMResourceDecorations
71+
public decorations: ISCMResourceDecorations,
72+
public contextValue: string
7273
) { }
7374

7475
open(): Promise<void> {
@@ -198,7 +199,7 @@ class MainThreadSCMProvider implements ISCMProvider {
198199

199200
for (const [start, deleteCount, rawResources] of groupSlices) {
200201
const resources = rawResources.map(rawResource => {
201-
const [handle, sourceUri, icons, tooltip, strikeThrough, faded] = rawResource;
202+
const [handle, sourceUri, icons, tooltip, strikeThrough, faded, contextValue] = rawResource;
202203
const icon = icons[0];
203204
const iconDark = icons[1] || icon;
204205
const decorations = {
@@ -216,7 +217,8 @@ class MainThreadSCMProvider implements ISCMProvider {
216217
handle,
217218
URI.revive(sourceUri),
218219
group,
219-
decorations
220+
decorations,
221+
contextValue
220222
);
221223
});
222224

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,8 @@ export type SCMRawResource = [
715715
UriComponents[] /*icons: light, dark*/,
716716
string /*tooltip*/,
717717
boolean /*strike through*/,
718-
boolean /*faded*/
718+
boolean /*faded*/,
719+
string /*context value*/
719720
];
720721

721722
export type SCMRawResourceSplice = [

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,9 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
306306
const tooltip = (r.decorations && r.decorations.tooltip) || '';
307307
const strikeThrough = r.decorations && !!r.decorations.strikeThrough;
308308
const faded = r.decorations && !!r.decorations.faded;
309+
const contextValue = r.contextValue || '';
309310

310-
const rawResource = [handle, sourceUri, icons, tooltip, strikeThrough, faded] as SCMRawResource;
311+
const rawResource = [handle, sourceUri, icons, tooltip, strikeThrough, faded, contextValue] as SCMRawResource;
311312

312313
return { rawResource, handle };
313314
});

src/vs/workbench/contrib/scm/browser/menus.ts

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@ interface ISCMResourceGroupMenuEntry {
2727

2828
interface ISCMMenus {
2929
readonly resourceGroupMenu: IMenu;
30-
readonly resourceMenu: IMenu;
3130
readonly resourceFolderMenu: IMenu;
3231
}
3332

33+
interface ISCMResourceMenu extends IDisposable {
34+
readonly menu: IMenu;
35+
}
36+
3437
export function getSCMResourceContextKey(resource: ISCMResourceGroup | ISCMResource): string {
3538
return isSCMResource(resource) ? resource.resourceGroup.id : resource.id;
3639
}
@@ -111,13 +114,20 @@ export class SCMMenus implements IDisposable {
111114
return this.getActions(MenuId.SCMResourceContext, resource).secondary;
112115
}
113116

117+
getResourceInlineActions(resource: ISCMResource): IAction[] {
118+
return this.getActions(MenuId.SCMResourceContext, resource).primary;
119+
}
120+
114121
getResourceFolderContextActions(group: ISCMResourceGroup): IAction[] {
115122
return this.getActions(MenuId.SCMResourceFolderContext, group).secondary;
116123
}
117124

118125
private getActions(menuId: MenuId, resource: ISCMResourceGroup | ISCMResource): { primary: IAction[]; secondary: IAction[]; } {
119126
const contextKeyService = this.contextKeyService.createScoped();
120127
contextKeyService.createKey('scmResourceGroup', getSCMResourceContextKey(resource));
128+
if (isSCMResource(resource)) {
129+
contextKeyService.createKey('scmResourceState', resource.contextValue);
130+
}
121131

122132
const menu = this.menuService.createMenu(menuId, contextKeyService);
123133
const primary: IAction[] = [];
@@ -131,20 +141,26 @@ export class SCMMenus implements IDisposable {
131141
return result;
132142
}
133143

134-
getResourceGroupMenu(group: ISCMResourceGroup): IMenu {
135-
if (!this.resourceGroupMenus.has(group)) {
136-
throw new Error('SCM Resource Group menu not found');
137-
}
144+
createResourceMenu(group: ISCMResourceGroup, resource: ISCMResource): ISCMResourceMenu {
145+
const contextKeyService = this.contextKeyService.createScoped();
146+
contextKeyService.createKey('scmProvider', group.provider.contextValue);
147+
contextKeyService.createKey('scmResourceGroup', getSCMResourceContextKey(resource));
148+
contextKeyService.createKey('scmResourceState', resource.contextValue);
138149

139-
return this.resourceGroupMenus.get(group)!.resourceGroupMenu;
150+
const menu = this.menuService.createMenu(MenuId.SCMResourceContext, contextKeyService);
151+
152+
const disposable = combinedDisposable(menu, contextKeyService);
153+
const dispose = () => disposable.dispose();
154+
155+
return { menu, dispose };
140156
}
141157

142-
getResourceMenu(group: ISCMResourceGroup): IMenu {
158+
getResourceGroupMenu(group: ISCMResourceGroup): IMenu {
143159
if (!this.resourceGroupMenus.has(group)) {
144160
throw new Error('SCM Resource Group menu not found');
145161
}
146162

147-
return this.resourceGroupMenus.get(group)!.resourceMenu;
163+
return this.resourceGroupMenus.get(group)!.resourceGroupMenu;
148164
}
149165

150166
getResourceFolderMenu(group: ISCMResourceGroup): IMenu {
@@ -162,11 +178,10 @@ export class SCMMenus implements IDisposable {
162178
contextKeyService.createKey('scmResourceGroup', getSCMResourceContextKey(group));
163179

164180
const resourceGroupMenu = this.menuService.createMenu(MenuId.SCMResourceGroupContext, contextKeyService);
165-
const resourceMenu = this.menuService.createMenu(MenuId.SCMResourceContext, contextKeyService);
166181
const resourceFolderMenu = this.menuService.createMenu(MenuId.SCMResourceFolderContext, contextKeyService);
167-
const disposable = combinedDisposable(contextKeyService, resourceGroupMenu, resourceMenu, resourceFolderMenu);
182+
const disposable = combinedDisposable(contextKeyService, resourceGroupMenu, resourceFolderMenu);
168183

169-
this.resourceGroupMenus.set(group, { resourceGroupMenu, resourceMenu, resourceFolderMenu });
184+
this.resourceGroupMenus.set(group, { resourceGroupMenu, resourceFolderMenu });
170185
return { group, disposable };
171186
});
172187

src/vs/workbench/contrib/scm/browser/repositoryPane.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,9 @@ class ResourceRenderer implements ICompressibleTreeRenderer<ISCMResource | IReso
220220

221221
if (ResourceTree.isResourceNode(resourceOrFolder)) {
222222
if (resourceOrFolder.element) {
223-
elementDisposables.add(connectPrimaryMenuToInlineActionBar(this.menus.getResourceMenu(resourceOrFolder.element.resourceGroup), template.actionBar));
223+
const menu = this.menus.createResourceMenu(resourceOrFolder.element.resourceGroup, resourceOrFolder.element);
224+
elementDisposables.add(menu);
225+
elementDisposables.add(connectPrimaryMenuToInlineActionBar(menu.menu, template.actionBar));
224226
toggleClass(template.name, 'strike-through', resourceOrFolder.element.decorations.strikeThrough);
225227
toggleClass(template.element, 'faded', resourceOrFolder.element.decorations.faded);
226228
} else {
@@ -229,7 +231,9 @@ class ResourceRenderer implements ICompressibleTreeRenderer<ISCMResource | IReso
229231
removeClass(template.element, 'faded');
230232
}
231233
} else {
232-
elementDisposables.add(connectPrimaryMenuToInlineActionBar(this.menus.getResourceMenu(resourceOrFolder.resourceGroup), template.actionBar));
234+
const menu = this.menus.createResourceMenu(resourceOrFolder.resourceGroup, resourceOrFolder);
235+
elementDisposables.add(menu);
236+
elementDisposables.add(connectPrimaryMenuToInlineActionBar(menu.menu, template.actionBar));
233237
toggleClass(template.name, 'strike-through', resourceOrFolder.decorations.strikeThrough);
234238
toggleClass(template.element, 'faded', resourceOrFolder.decorations.faded);
235239
}

src/vs/workbench/contrib/scm/common/scm.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export interface ISCMResource {
3030
readonly resourceGroup: ISCMResourceGroup;
3131
readonly sourceUri: URI;
3232
readonly decorations: ISCMResourceDecorations;
33+
readonly contextValue: string
3334
open(): Promise<void>;
3435
}
3536

0 commit comments

Comments
 (0)