Skip to content

Commit 7bd16e2

Browse files
committed
label service new structure for formatters
1 parent 6c43492 commit 7bd16e2

8 files changed

Lines changed: 94 additions & 95 deletions

File tree

src/vs/editor/standalone/browser/simpleServices.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingReso
3636
import { IKeybindingItem, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
3737
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
3838
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
39-
import { ILabelService, LabelRules } from 'vs/platform/label/common/label';
39+
import { ILabelService, ResourceLabelFormatter } from 'vs/platform/label/common/label';
4040
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification } from 'vs/platform/notification/common/notification';
4141
import { IProgressRunner, IProgressService } from 'vs/platform/progress/common/progress';
4242
import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -625,7 +625,7 @@ export class SimpleUriLabelService implements ILabelService {
625625
return '';
626626
}
627627

628-
public registerFormatter(selector: string, formatter: LabelRules): IDisposable {
628+
public registerFormatter(formatter: ResourceLabelFormatter): IDisposable {
629629
throw new Error('Not implemented');
630630
}
631631

src/vs/platform/label/common/label.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,23 @@ export interface ILabelService {
2525
getUriLabel(resource: URI, options?: { relative?: boolean, noPrefix?: boolean }): string;
2626
getWorkspaceLabel(workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWorkspace), options?: { verbose: boolean }): string;
2727
getHostLabel(): string;
28-
registerFormatter(selector: string, formatter: LabelRules): IDisposable;
28+
registerFormatter(formatter: ResourceLabelFormatter): IDisposable;
2929
onDidRegisterFormatter: Event<void>;
3030
}
3131

32-
export interface LabelRules {
33-
uri: {
34-
label: string; // myLabel:/${path}
35-
separator: '/' | '\\' | '';
36-
tildify?: boolean;
37-
normalizeDriveLetter?: boolean;
38-
authorityPrefix?: string;
39-
};
40-
workspace?: {
41-
suffix: string;
42-
};
32+
export interface ResourceLabelFormatter {
33+
scheme: string;
34+
authority?: string;
35+
formatting: ResourceLabelFormatting;
36+
}
37+
38+
export interface ResourceLabelFormatting {
39+
label: string; // myLabel:/${path}
40+
separator: '/' | '\\' | '';
41+
tildify?: boolean;
42+
normalizeDriveLetter?: boolean;
43+
workspaceSuffix?: string;
44+
authorityPrefix?: string;
4345
}
4446

4547
const LABEL_SERVICE_ID = 'label';

src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { URI } from 'vs/base/common/uri';
99
import { FileWriteOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IFileSystemProvider, IStat, IWatchOptions, FileType, FileOverwriteOptions, FileDeleteOptions } from 'vs/platform/files/common/files';
1010
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
1111
import { ExtHostContext, ExtHostFileSystemShape, IExtHostContext, IFileChangeDto, MainContext, MainThreadFileSystemShape } from '../node/extHost.protocol';
12-
import { LabelRules, ILabelService } from 'vs/platform/label/common/label';
12+
import { ResourceLabelFormatter, ILabelService } from 'vs/platform/label/common/label';
1313

1414
@extHostNamedCustomer(MainContext.MainThreadFileSystem)
1515
export class MainThreadFileSystem implements MainThreadFileSystemShape {
@@ -39,8 +39,8 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape {
3939
this._fileProvider.delete(handle);
4040
}
4141

42-
$setUriFormatter(selector: string, formatter: LabelRules): void {
43-
this._labelService.registerFormatter(selector, formatter);
42+
$setUriFormatter(formatter: ResourceLabelFormatter): void {
43+
this._labelService.registerFormatter(formatter);
4444
}
4545

4646
$onFileSystemChange(handle: number, changes: IFileChangeDto[]): void {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands
2121
import { ConfigurationTarget, IConfigurationData, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
2222
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
2323
import { FileChangeType, FileDeleteOptions, FileOverwriteOptions, FileSystemProviderCapabilities, FileType, FileWriteOptions, IStat, IWatchOptions } from 'vs/platform/files/common/files';
24-
import { LabelRules } from 'vs/platform/label/common/label';
24+
import { ResourceLabelFormatter } from 'vs/platform/label/common/label';
2525
import { LogLevel } from 'vs/platform/log/common/log';
2626
import { IMarkerData } from 'vs/platform/markers/common/markers';
2727
import { IPickOptions, IQuickInputButton, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
@@ -512,7 +512,7 @@ export interface IFileChangeDto {
512512
export interface MainThreadFileSystemShape extends IDisposable {
513513
$registerFileSystemProvider(handle: number, scheme: string, capabilities: FileSystemProviderCapabilities): void;
514514
$unregisterProvider(handle: number): void;
515-
$setUriFormatter(scheme: string, formatter: LabelRules): void;
515+
$setUriFormatter(formatter: ResourceLabelFormatter): void;
516516
$onFileSystemChange(handle: number, resource: IFileChangeDto[]): void;
517517
}
518518

src/vs/workbench/api/node/extHostFileSystem.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { FileChangeType, DocumentLink } from 'vs/workbench/api/node/extHostTypes
1212
import * as typeConverter from 'vs/workbench/api/node/extHostTypeConverters';
1313
import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures';
1414
import { Schemas } from 'vs/base/common/network';
15-
import { LabelRules } from 'vs/platform/label/common/label';
15+
import { ResourceLabelFormatter } from 'vs/platform/label/common/label';
1616
import { State, StateMachine, LinkComputer } from 'vs/editor/common/modes/linkComputer';
1717
import { commonPrefixLength } from 'vs/base/common/strings';
1818
import { CharCode } from 'vs/base/common/charCode';
@@ -205,8 +205,8 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
205205
});
206206
}
207207

208-
setUriFormatter(scheme: string, formatter: LabelRules): void {
209-
this._proxy.$setUriFormatter(scheme, formatter);
208+
setUriFormatter(formatter: ResourceLabelFormatter): void {
209+
this._proxy.$setUriFormatter(formatter);
210210
}
211211

212212
private static _asIStat(stat: vscode.FileStat): files.IStat {

src/vs/workbench/parts/files/electron-browser/files.contribution.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,15 @@ export class OpenExplorerViewletAction extends ShowViewletAction {
5757
class FileUriLabelContribution implements IWorkbenchContribution {
5858

5959
constructor(@ILabelService labelService: ILabelService) {
60-
labelService.registerFormatter('file://', {
61-
uri: {
60+
labelService.registerFormatter({
61+
scheme: 'file',
62+
formatting: {
6263
label: '${authority}${path}',
6364
separator: nativeSep,
6465
tildify: !platform.isWindows,
6566
normalizeDriveLetter: platform.isWindows,
66-
authorityPrefix: nativeSep + nativeSep
67-
},
68-
workspace: {
69-
suffix: ''
67+
authorityPrefix: nativeSep + nativeSep,
68+
workspaceSuffix: ''
7069
}
7170
});
7271
}

src/vs/workbench/services/label/common/labelService.ts

Lines changed: 59 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -12,65 +12,56 @@ import { IWorkspaceContextService, IWorkspace } from 'vs/platform/workspace/comm
1212
import { isEqual, basenameOrAuthority, basename as resourceBasename } from 'vs/base/common/resources';
1313
import { isLinux, isWindows } from 'vs/base/common/platform';
1414
import { tildify, getPathLabel } from 'vs/base/common/labels';
15-
import { ltrim, startsWith } from 'vs/base/common/strings';
15+
import { ltrim } from 'vs/base/common/strings';
1616
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, WORKSPACE_EXTENSION, toWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
1717
import { isParent } from 'vs/platform/files/common/files';
1818
import { basename, dirname, join } from 'vs/base/common/paths';
1919
import { Schemas } from 'vs/base/common/network';
2020
import { IWindowService } from 'vs/platform/windows/common/windows';
2121
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
22-
import { ILabelService, LabelRules } from 'vs/platform/label/common/label';
22+
import { ILabelService, ResourceLabelFormatter, ResourceLabelFormatting } from 'vs/platform/label/common/label';
2323
import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
24+
import { match } from 'vs/base/common/glob';
2425

25-
interface LabelRulesWithPrefix extends LabelRules {
26-
prefix: string;
27-
}
28-
29-
export const labelsExtPoint = ExtensionsRegistry.registerExtensionPoint<LabelRulesWithPrefix[]>({
30-
extensionPoint: 'labels',
26+
export const labelsExtPoint = ExtensionsRegistry.registerExtensionPoint<ResourceLabelFormatter[]>({
27+
extensionPoint: 'resourceLabelFormatters',
3128
jsonSchema: {
32-
description: localize('vscode.extension.contributes.labels', 'Contributes label formatting rules.'),
29+
description: localize('vscode.extension.contributes.resourceLabelFormatters', 'Contributes resource label formatting rules.'),
3330
type: 'array',
3431
items: {
3532
type: 'object',
36-
required: ['prefix'],
33+
required: ['scheme', 'formatting'],
3734
properties: {
38-
prefix: {
35+
scheme: {
3936
type: 'string',
40-
description: localize('vscode.extension.contributes.labels.prefix', 'URI prefix on which to match the rules on. For example file:///myFolder'),
37+
description: localize('vscode.extension.contributes.resourceLabelFormatters.scheme', 'URI scheme on which to match the formatter on. For example "file". Simple glob patterns are supported.'),
4138
},
42-
uri: {
43-
description: localize('vscode.extension.contributes.labels.uri', "Rules for formatting uri resource labels."),
39+
authority: {
40+
type: 'string',
41+
description: localize('vscode.extension.contributes.resourceLabelFormatters.authority', 'URI authority on which to match the formatter on. Simple glob patterns are supported.'),
42+
},
43+
formatting: {
44+
description: localize('vscode.extension.contributes.resourceLabelFormatters.formatting', "Rules for formatting uri resource labels."),
4445
type: 'object',
4546
properties: {
4647
label: {
4748
type: 'string',
48-
description: localize('vscode.extension.contributes.labels.uri.label', "Label rules to display. For example: myLabel:/${path}. ${path}, ${scheme} and ${authority} are supported as variables.")
49+
description: localize('vscode.extension.contributes.resourceLabelFormatters.label', "Label rules to display. For example: myLabel:/${path}. ${path}, ${scheme} and ${authority} are supported as variables.")
4950
},
5051
separator: {
5152
type: 'string',
52-
description: localize('vscode.extension.contributes.labels.uri.separator', "Separator to be used in the uri label display. '/' or '\' as an example.")
53+
description: localize('vscode.extension.contributes.resourceLabelFormatters.separator', "Separator to be used in the uri label display. '/' or '\' as an example.")
5354
},
5455
tildify: {
5556
type: 'boolean',
56-
description: localize('vscode.extension.contributes.labels.uri.tildify', "Controls if the start of the uri label should be tildified when possible.")
57+
description: localize('vscode.extension.contributes.resourceLabelFormatters.tildify', "Controls if the start of the uri label should be tildified when possible.")
5758
},
58-
normalizeDriveLetter: {
59-
type: 'boolean',
60-
description: localize('vscode.extension.contributes.labels.uri.normalizeDriveLetter', "Controls if the drive letters should be upper cased.")
61-
}
62-
}
63-
},
64-
workspace: {
65-
description: localize('vscode.extension.contributes.labels.workspace', "Rules for formatting workspace labels."),
66-
type: 'object',
67-
properties: {
68-
suffix: {
59+
workspaceSuffix: {
6960
type: 'string',
70-
description: localize('vscode.extension.contributes.labels.workspace.suffix', "Suffix appended to the workspace label.")
61+
description: localize('vscode.extension.contributes.resourceLabelFormatters.formatting.workspaceSuffix', "Suffix appended to the workspace label.")
7162
}
7263
}
73-
},
64+
}
7465
}
7566
}
7667
}
@@ -86,7 +77,7 @@ function hasDriveLetter(path: string): boolean {
8677
export class LabelService implements ILabelService {
8778
_serviceBrand: any;
8879

89-
private readonly formatters: { [prefix: string]: LabelRules } = Object.create(null);
80+
private formatters: ResourceLabelFormatter[] = [];
9081
private readonly _onDidRegisterFormatter = new Emitter<void>();
9182

9283
constructor(
@@ -95,7 +86,7 @@ export class LabelService implements ILabelService {
9586
@IWindowService private readonly windowService: IWindowService
9687
) {
9788
labelsExtPoint.setHandler(extensions => {
98-
extensions.forEach(extension => extension.value.forEach(rule => this.formatters[rule.prefix] = rule));
89+
extensions.forEach(extension => extension.value.forEach(formatter => this.formatters.push(formatter)));
9990
this._onDidRegisterFormatter.fire();
10091
});
10192
}
@@ -104,23 +95,28 @@ export class LabelService implements ILabelService {
10495
return this._onDidRegisterFormatter.event;
10596
}
10697

107-
findFormatter(resource: URI): LabelRules | undefined {
108-
const path = `${resource.scheme}://${resource.authority}`;
109-
let bestPrefix = '';
110-
for (let prefix in this.formatters) {
111-
if (startsWith(path, prefix) && prefix.length > bestPrefix.length) {
112-
bestPrefix = prefix;
98+
findFormatting(resource: URI): ResourceLabelFormatting | undefined {
99+
let bestResult: ResourceLabelFormatter;
100+
101+
this.formatters.forEach(formatter => {
102+
if (formatter.scheme === resource.scheme) {
103+
if (!formatter.authority && !bestResult) {
104+
bestResult = formatter;
105+
return;
106+
}
107+
108+
if (match(resource.authority, formatter.authority) && (!bestResult.authority || formatter.authority.length > bestResult.authority.length)) {
109+
bestResult = formatter;
110+
}
113111
}
114-
}
115-
if (bestPrefix.length) {
116-
return this.formatters[bestPrefix];
117-
}
118-
return undefined;
112+
});
113+
114+
return bestResult.formatting;
119115
}
120116

121117
getUriLabel(resource: URI, options: { relative?: boolean, noPrefix?: boolean } = {}): string {
122-
const formatter = this.findFormatter(resource);
123-
if (!formatter) {
118+
const formatting = this.findFormatting(resource);
119+
if (!formatting) {
124120
return getPathLabel(resource.path, this.environmentService, options.relative ? this.contextService : undefined);
125121
}
126122

@@ -131,8 +127,8 @@ export class LabelService implements ILabelService {
131127
if (isEqual(baseResource.uri, resource, !isLinux)) {
132128
relativeLabel = ''; // no label if resources are identical
133129
} else {
134-
const baseResourceLabel = this.formatUri(baseResource.uri, formatter, options.noPrefix);
135-
relativeLabel = ltrim(this.formatUri(resource, formatter, options.noPrefix).substring(baseResourceLabel.length), formatter.uri.separator);
130+
const baseResourceLabel = this.formatUri(baseResource.uri, formatting, options.noPrefix);
131+
relativeLabel = ltrim(this.formatUri(resource, formatting, options.noPrefix).substring(baseResourceLabel.length), formatting.separator);
136132
}
137133

138134
const hasMultipleRoots = this.contextService.getWorkspace().folders.length > 1;
@@ -145,7 +141,7 @@ export class LabelService implements ILabelService {
145141
}
146142
}
147143

148-
return this.formatUri(resource, formatter, options.noPrefix);
144+
return this.formatUri(resource, formatting, options.noPrefix);
149145
}
150146

151147
getWorkspaceLabel(workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWorkspace), options?: { verbose: boolean }): string {
@@ -166,8 +162,8 @@ export class LabelService implements ILabelService {
166162
return label;
167163
}
168164

169-
const formatter = this.findFormatter(workspace);
170-
const suffix = formatter && formatter.workspace && (typeof formatter.workspace.suffix === 'string') ? formatter.workspace.suffix : workspace.scheme;
165+
const formatting = this.findFormatting(workspace);
166+
const suffix = formatting && (typeof formatting.workspaceSuffix === 'string') ? formatting.workspaceSuffix : workspace.scheme;
171167
return suffix ? `${label} (${suffix})` : label;
172168
}
173169

@@ -190,26 +186,26 @@ export class LabelService implements ILabelService {
190186
if (this.windowService) {
191187
const authority = this.windowService.getConfiguration().remoteAuthority;
192188
if (authority) {
193-
const formatter = this.findFormatter(URI.from({ scheme: REMOTE_HOST_SCHEME, authority }));
194-
if (formatter && formatter.workspace) {
195-
return formatter.workspace.suffix;
189+
const formatter = this.findFormatting(URI.from({ scheme: REMOTE_HOST_SCHEME, authority }));
190+
if (formatter && formatter.workspaceSuffix) {
191+
return formatter.workspaceSuffix;
196192
}
197193
}
198194
}
199195
return '';
200196
}
201197

202-
registerFormatter(selector: string, formatter: LabelRules): IDisposable {
203-
this.formatters[selector] = formatter;
198+
registerFormatter(formatter: ResourceLabelFormatter): IDisposable {
199+
this.formatters.push(formatter);
204200
this._onDidRegisterFormatter.fire();
205201

206202
return {
207-
dispose: () => delete this.formatters[selector]
203+
dispose: () => this.formatters = this.formatters.filter(f => f !== formatter)
208204
};
209205
}
210206

211-
private formatUri(resource: URI, formatter: LabelRules, forceNoTildify?: boolean): string {
212-
let label = formatter.uri.label.replace(labelMatchingRegexp, match => {
207+
private formatUri(resource: URI, formatting: ResourceLabelFormatting, forceNoTildify?: boolean): string {
208+
let label = formatting.label.replace(labelMatchingRegexp, match => {
213209
switch (match) {
214210
case '${scheme}': return resource.scheme;
215211
case '${authority}': return resource.authority;
@@ -219,17 +215,17 @@ export class LabelService implements ILabelService {
219215
});
220216

221217
// convert \c:\something => C:\something
222-
if (formatter.uri.normalizeDriveLetter && hasDriveLetter(label)) {
218+
if (formatting.normalizeDriveLetter && hasDriveLetter(label)) {
223219
label = label.charAt(1).toUpperCase() + label.substr(2);
224220
}
225221

226-
if (formatter.uri.tildify && !forceNoTildify) {
222+
if (formatting.tildify && !forceNoTildify) {
227223
label = tildify(label, this.environmentService.userHome);
228224
}
229-
if (formatter.uri.authorityPrefix && resource.authority) {
230-
label = formatter.uri.authorityPrefix + label;
225+
if (formatting.authorityPrefix && resource.authority) {
226+
label = formatting.authorityPrefix + label;
231227
}
232228

233-
return label.replace(sepRegexp, formatter.uri.separator);
229+
return label.replace(sepRegexp, formatting.separator);
234230
}
235231
}

src/vs/workbench/services/label/test/label.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ suite('URI Label', () => {
2020
});
2121

2222
test('file scheme', function () {
23-
labelService.registerFormatter('file://', {
24-
uri: {
23+
labelService.registerFormatter({
24+
scheme: 'file://',
25+
formatting: {
2526
label: '${path}',
2627
separator: nativeSep,
2728
tildify: !isWindows,
@@ -38,8 +39,9 @@ suite('URI Label', () => {
3839
});
3940

4041
test('custom scheme', function () {
41-
labelService.registerFormatter('vscode://', {
42-
uri: {
42+
labelService.registerFormatter({
43+
scheme: 'vscode://',
44+
formatting: {
4345
label: 'LABEL/${path}/${authority}/END',
4446
separator: '/',
4547
tildify: true,

0 commit comments

Comments
 (0)