Skip to content

Commit f1c9243

Browse files
authored
Enable codicon decorations (microsoft#166358)
* Enable codicon decorations Part of microsoft#135591 * Fix test compile error * Add proposal reference * Address feedback
1 parent ab35ce9 commit f1c9243

File tree

8 files changed

+82
-16
lines changed

8 files changed

+82
-16
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
742742
return extHostCustomEditors.registerCustomEditorProvider(extension, viewType, provider, options);
743743
},
744744
registerFileDecorationProvider(provider: vscode.FileDecorationProvider) {
745-
return extHostDecorations.registerFileDecorationProvider(provider, extension.identifier);
745+
return extHostDecorations.registerFileDecorationProvider(provider, extension);
746746
},
747747
registerUriHandler(handler: vscode.UriHandler) {
748748
return extHostUrls.registerUriHandler(extension.identifier, handler);
@@ -1252,6 +1252,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
12521252
ExternalUriOpenerPriority: extHostTypes.ExternalUriOpenerPriority,
12531253
FileChangeType: extHostTypes.FileChangeType,
12541254
FileDecoration: extHostTypes.FileDecoration,
1255+
FileDecoration2: extHostTypes.FileDecoration,
12551256
FileSystemError: extHostTypes.FileSystemError,
12561257
FileType: files.FileType,
12571258
FilePermission: files.FilePermission,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1943,7 +1943,7 @@ export interface DecorationRequest {
19431943
readonly uri: UriComponents;
19441944
}
19451945

1946-
export type DecorationData = [boolean, string, string, ThemeColor];
1946+
export type DecorationData = [boolean, string, string | ThemeIcon, ThemeColor];
19471947
export type DecorationReply = { [id: number]: DecorationData };
19481948

19491949
export interface ExtHostDecorationsShape {

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

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,18 @@ import { URI } from 'vs/base/common/uri';
88
import { MainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData, DecorationRequest, DecorationReply } from 'vs/workbench/api/common/extHost.protocol';
99
import { Disposable, FileDecoration } from 'vs/workbench/api/common/extHostTypes';
1010
import { CancellationToken } from 'vs/base/common/cancellation';
11-
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
11+
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
1212
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
1313
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
1414
import { ILogService } from 'vs/platform/log/common/log';
1515
import { asArray, groupBy } from 'vs/base/common/arrays';
1616
import { compare, count } from 'vs/base/common/strings';
1717
import { dirname } from 'vs/base/common/path';
18+
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
1819

1920
interface ProviderData {
2021
provider: vscode.FileDecorationProvider;
21-
extensionId: ExtensionIdentifier;
22+
extensionDescription: IExtensionDescription;
2223
}
2324

2425
export class ExtHostDecorations implements ExtHostDecorationsShape {
@@ -37,10 +38,10 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
3738
this._proxy = extHostRpc.getProxy(MainContext.MainThreadDecorations);
3839
}
3940

40-
registerFileDecorationProvider(provider: vscode.FileDecorationProvider, extensionId: ExtensionIdentifier): vscode.Disposable {
41+
registerFileDecorationProvider(provider: vscode.FileDecorationProvider, extensionDescription: IExtensionDescription): vscode.Disposable {
4142
const handle = ExtHostDecorations._handlePool++;
42-
this._provider.set(handle, { provider, extensionId });
43-
this._proxy.$registerDecorationProvider(handle, extensionId.value);
43+
this._provider.set(handle, { provider, extensionDescription });
44+
this._proxy.$registerDecorationProvider(handle, extensionDescription.identifier.value);
4445

4546
const listener = provider.onDidChangeFileDecorations && provider.onDidChangeFileDecorations(e => {
4647
if (!e) {
@@ -55,7 +56,7 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
5556

5657
// too many resources per event. pick one resource per folder, starting
5758
// with parent folders
58-
this._logService.warn('[Decorations] CAPPING events from decorations provider', extensionId.value, array.length);
59+
this._logService.warn('[Decorations] CAPPING events from decorations provider', extensionDescription.identifier.value, array.length);
5960
const mapped = array.map(uri => ({ uri, rank: count(uri.path, '/') }));
6061
const groups = groupBy(mapped, (a, b) => a.rank - b.rank || compare(a.uri.path, b.uri.path));
6162
const picked: URI[] = [];
@@ -89,7 +90,7 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
8990
}
9091

9192
const result: DecorationReply = Object.create(null);
92-
const { provider, extensionId } = this._provider.get(handle)!;
93+
const { provider, extensionDescription: extensionId } = this._provider.get(handle)!;
9394

9495
await Promise.all(requests.map(async request => {
9596
try {
@@ -100,9 +101,12 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
100101
}
101102
try {
102103
FileDecoration.validate(data);
104+
if (data.badge && typeof data.badge !== 'string') {
105+
checkProposedApiEnabled(extensionId, 'codiconDecoration');
106+
}
103107
result[id] = <DecorationData>[data.propagate, data.tooltip, data.badge, data.color];
104108
} catch (e) {
105-
this._logService.warn(`INVALID decoration from extension '${extensionId.value}': ${e}`);
109+
this._logService.warn(`INVALID decoration from extension '${extensionId}': ${e}`);
106110
}
107111
} catch (err) {
108112
this._logService.error(err);

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,6 +2654,14 @@ export class ThemeIcon {
26542654
this.id = id;
26552655
this.color = color;
26562656
}
2657+
2658+
static isThemeIcon(thing: any) {
2659+
if (typeof thing.id !== 'string') {
2660+
console.log('INVALID ThemeIcon, invalid id', thing.id);
2661+
return false;
2662+
}
2663+
return true;
2664+
}
26572665
}
26582666
ThemeIcon.File = new ThemeIcon('file');
26592667
ThemeIcon.Folder = new ThemeIcon('folder');
@@ -3278,27 +3286,31 @@ export enum ExtensionKind {
32783286
export class FileDecoration {
32793287

32803288
static validate(d: FileDecoration): boolean {
3281-
if (d.badge) {
3289+
if (typeof d.badge === 'string') {
32823290
let len = nextCharLength(d.badge, 0);
32833291
if (len < d.badge.length) {
32843292
len += nextCharLength(d.badge, len);
32853293
}
32863294
if (d.badge.length > len) {
32873295
throw new Error(`The 'badge'-property must be undefined or a short character`);
32883296
}
3297+
} else if (d.badge) {
3298+
if (!ThemeIcon.isThemeIcon(d.badge)) {
3299+
throw new Error(`The 'badge'-property is not a valid ThemeIcon`);
3300+
}
32893301
}
32903302
if (!d.color && !d.badge && !d.tooltip) {
32913303
throw new Error(`The decoration is empty`);
32923304
}
32933305
return true;
32943306
}
32953307

3296-
badge?: string;
3308+
badge?: string | vscode.ThemeIcon;
32973309
tooltip?: string;
32983310
color?: vscode.ThemeColor;
32993311
propagate?: boolean;
33003312

3301-
constructor(badge?: string, tooltip?: string, color?: ThemeColor) {
3313+
constructor(badge?: string | ThemeIcon, tooltip?: string, color?: ThemeColor) {
33023314
this.badge = badge;
33033315
this.tooltip = tooltip;
33043316
this.color = color;

src/vs/workbench/api/test/browser/extHostDecorations.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ suite('ExtHostDecorations', function () {
5252
calledA = true;
5353
return new Promise(() => { });
5454
}
55-
}, nullExtensionDescription.identifier);
55+
}, nullExtensionDescription);
5656

5757
// always returns
5858
extHostDecorations.registerFileDecorationProvider({
@@ -61,7 +61,7 @@ suite('ExtHostDecorations', function () {
6161
calledB = true;
6262
return new Promise(resolve => resolve({ badge: 'H', tooltip: 'Hello' }));
6363
}
64-
}, nullExtensionDescription.identifier);
64+
}, nullExtensionDescription);
6565

6666

6767
const requests = [...providers.values()].map((handle, idx) => {

src/vs/workbench/services/decorations/browser/decorationsService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class DecorationRule {
136136
createCSSRule(
137137
`.${this.iconBadgeClassName}::after`,
138138
`content: '${definition.fontCharacter}';
139-
color: ${getColor(color)};
139+
color: ${icon.color ? getColor(icon.color.id) : getColor(color)};
140140
font-family: ${asCSSPropertyValue(definition.font?.id ?? 'codicon')};
141141
font-size: 16px;
142142
margin-right: 14px;

src/vs/workbench/services/extensions/common/extensionsApiProposals.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
export const allApiProposals = Object.freeze({
99
authSession: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.authSession.d.ts',
10+
codiconDecoration: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.codiconDecoration.d.ts',
1011
commentsResolvedState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.commentsResolvedState.d.ts',
1112
contribCommentPeekContext: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribCommentPeekContext.d.ts',
1213
contribEditSessions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribEditSessions.d.ts',
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
declare module 'vscode' {
7+
8+
// https://github.com/microsoft/vscode/issues/135591 @alexr00
9+
10+
// export interface FileDecorationProvider {
11+
// provideFileDecoration(uri: Uri, token: CancellationToken): ProviderResult<FileDecoration | FileDecoration1>;
12+
// }
13+
14+
/**
15+
* A file decoration represents metadata that can be rendered with a file.
16+
*/
17+
export class FileDecoration2 {
18+
/**
19+
* A very short string that represents this decoration.
20+
*/
21+
badge?: string | ThemeIcon;
22+
23+
/**
24+
* A human-readable tooltip for this decoration.
25+
*/
26+
tooltip?: string;
27+
28+
/**
29+
* The color of this decoration.
30+
*/
31+
color?: ThemeColor;
32+
33+
/**
34+
* A flag expressing that this decoration should be
35+
* propagated to its parents.
36+
*/
37+
propagate?: boolean;
38+
39+
/**
40+
* Creates a new decoration.
41+
*
42+
* @param badge A letter that represents the decoration.
43+
* @param tooltip The tooltip of the decoration.
44+
* @param color The color of the decoration.
45+
*/
46+
constructor(badge?: string | ThemeIcon, tooltip?: string, color?: ThemeColor);
47+
}
48+
}

0 commit comments

Comments
 (0)