Skip to content

Commit f250297

Browse files
author
Benjamin Pasero
committed
labels - handle file service changes better (fix microsoft#91833)
1 parent f33d982 commit f250297

9 files changed

Lines changed: 56 additions & 38 deletions

File tree

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

Lines changed: 2 additions & 3 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, ResourceLabelFormatter } from 'vs/platform/label/common/label';
39+
import { ILabelService, ResourceLabelFormatter, IFormatterChangeEvent } from 'vs/platform/label/common/label';
4040
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification';
4141
import { IProgressRunner, IEditorProgressService } from 'vs/platform/progress/common/progress';
4242
import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -713,8 +713,7 @@ export class SimpleUriLabelService implements ILabelService {
713713

714714
_serviceBrand: undefined;
715715

716-
private readonly _onDidRegisterFormatter = new Emitter<void>();
717-
public readonly onDidChangeFormatters: Event<void> = this._onDidRegisterFormatter.event;
716+
public readonly onDidChangeFormatters: Event<IFormatterChangeEvent> = Event.None;
718717

719718
public getUriLabel(resource: URI, options?: { relative?: boolean, forceNoTildify?: boolean }): string {
720719
if (resource.scheme === 'file') {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ export interface ILabelService {
2626
getHostLabel(scheme: string, authority?: string): string;
2727
getSeparator(scheme: string, authority?: string): '/' | '\\';
2828
registerFormatter(formatter: ResourceLabelFormatter): IDisposable;
29-
onDidChangeFormatters: Event<void>;
29+
onDidChangeFormatters: Event<IFormatterChangeEvent>;
30+
}
31+
32+
export interface IFormatterChangeEvent {
33+
scheme: string;
3034
}
3135

3236
export interface ResourceLabelFormatter {

src/vs/workbench/browser/labels.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,14 +137,14 @@ export class ResourceLabels extends Disposable {
137137
}));
138138

139139
// notify when label formatters change
140-
this._register(this.labelService.onDidChangeFormatters(() => {
141-
this._widgets.forEach(widget => widget.notifyFormattersChange());
140+
this._register(this.labelService.onDidChangeFormatters(e => {
141+
this._widgets.forEach(widget => widget.notifyFormattersChange(e.scheme));
142142
}));
143143

144144
// notify when untitled labels change
145-
this.textFileService.untitled.onDidChangeLabel(model => {
145+
this._register(this.textFileService.untitled.onDidChangeLabel(model => {
146146
this._widgets.forEach(widget => widget.notifyUntitledLabelChange(model.resource));
147-
});
147+
}));
148148
}
149149

150150
get(index: number): IResourceLabel {
@@ -311,8 +311,10 @@ class ResourceLabelWidget extends IconLabel {
311311
this.render(true);
312312
}
313313

314-
notifyFormattersChange(): void {
315-
this.render(false);
314+
notifyFormattersChange(scheme: string): void {
315+
if (this.label?.resource?.scheme === scheme) {
316+
this.render(false);
317+
}
316318
}
317319

318320
notifyUntitledLabelChange(resource: URI): void {

src/vs/workbench/browser/parts/editor/tabsTitleControl.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
4040
import { BreadcrumbsControl } from 'vs/workbench/browser/parts/editor/breadcrumbsControl';
4141
import { IFileService } from 'vs/platform/files/common/files';
4242
import { withNullAsUndefined, assertAllDefined, assertIsDefined } from 'vs/base/common/types';
43-
import { ILabelService } from 'vs/platform/label/common/label';
4443
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
4544
import { basenameOrAuthority } from 'vs/base/common/resources';
45+
import { RunOnceScheduler } from 'vs/base/common/async';
4646

4747
interface IEditorInputLabel {
4848
name?: string;
@@ -85,10 +85,9 @@ export class TabsTitleControl extends TitleControl {
8585
@IExtensionService extensionService: IExtensionService,
8686
@IConfigurationService configurationService: IConfigurationService,
8787
@IFileService fileService: IFileService,
88-
@ILabelService labelService: ILabelService,
8988
@IEditorService private readonly editorService: EditorServiceImpl
9089
) {
91-
super(parent, accessor, group, contextMenuService, instantiationService, contextKeyService, keybindingService, telemetryService, notificationService, menuService, quickOpenService, themeService, extensionService, configurationService, fileService, labelService);
90+
super(parent, accessor, group, contextMenuService, instantiationService, contextKeyService, keybindingService, telemetryService, notificationService, menuService, quickOpenService, themeService, extensionService, configurationService, fileService);
9291

9392
this.tabResourceLabels = this._register(this.instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER));
9493
this.closeOneEditorAction = this._register(this.instantiationService.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL));
@@ -392,10 +391,16 @@ export class TabsTitleControl extends TitleControl {
392391
this.layout(this.dimension);
393392
}
394393

394+
private updateEditorLabelAggregator = this._register(new RunOnceScheduler(() => this.updateEditorLabels(), 0));
395+
395396
updateEditorLabel(editor: IEditorInput): void {
396397

397398
// Update all labels to account for changes to tab labels
398-
this.updateEditorLabels();
399+
// Since this method may be called a lot of times from
400+
// individual editors, we collect all those requests and
401+
// then run the update once because we have to update
402+
// all opened tabs in the group at once.
403+
this.updateEditorLabelAggregator.schedule();
399404
}
400405

401406
updateEditorLabels(): void {

src/vs/workbench/browser/parts/editor/titleControl.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
4040
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
4141
import { IFileService } from 'vs/platform/files/common/files';
4242
import { withNullAsUndefined, withUndefinedAsNull, assertIsDefined } from 'vs/base/common/types';
43-
import { ILabelService } from 'vs/platform/label/common/label';
4443
import { isFirefox } from 'vs/base/browser/browser';
4544

4645
export interface IToolbarActions {
@@ -82,8 +81,7 @@ export abstract class TitleControl extends Themable {
8281
@IThemeService themeService: IThemeService,
8382
@IExtensionService private readonly extensionService: IExtensionService,
8483
@IConfigurationService protected configurationService: IConfigurationService,
85-
@IFileService private readonly fileService: IFileService,
86-
@ILabelService private readonly labelService: ILabelService
84+
@IFileService private readonly fileService: IFileService
8785
) {
8886
super(themeService);
8987

@@ -97,8 +95,9 @@ export abstract class TitleControl extends Themable {
9795
}
9896

9997
private registerListeners(): void {
98+
99+
// Update actions toolbar when extension register that may contribute them
100100
this._register(this.extensionService.onDidRegisterExtensions(() => this.updateEditorActionsToolbar()));
101-
this._register(this.labelService.onDidChangeFormatters(() => this.updateEditorLabels()));
102101
}
103102

104103
protected abstract create(parent: HTMLElement): void;

src/vs/workbench/browser/parts/titlebar/titlebarPart.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export class TitlebarPart extends Part implements ITitleService {
8686
private readonly properties: ITitleProperties = { isPure: true, isAdmin: false };
8787
private readonly activeEditorListeners = this._register(new DisposableStore());
8888

89-
private titleUpdater: RunOnceScheduler = this._register(new RunOnceScheduler(() => this.doUpdateTitle(), 0));
89+
private readonly titleUpdater = this._register(new RunOnceScheduler(() => this.doUpdateTitle(), 0));
9090

9191
private contextMenu: IMenu;
9292

src/vs/workbench/common/editor.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,20 @@ export abstract class TextResourceEditorInput extends EditorInput {
609609
protected registerListeners(): void {
610610

611611
// Clear label memoizer on certain events that have impact
612-
this._register(this.labelService.onDidChangeFormatters(() => TextResourceEditorInput.MEMOIZER.clear()));
613-
this._register(this.fileService.onDidChangeFileSystemProviderRegistrations(() => TextResourceEditorInput.MEMOIZER.clear()));
612+
this._register(this.labelService.onDidChangeFormatters(e => this.onLabelEvent(e.scheme)));
613+
this._register(this.fileService.onDidChangeFileSystemProviderRegistrations(e => this.onLabelEvent(e.scheme)));
614+
this._register(this.fileService.onDidChangeFileSystemProviderCapabilities(e => this.onLabelEvent(e.scheme)));
615+
}
616+
617+
private onLabelEvent(scheme: string): void {
618+
if (scheme === this.resource.scheme) {
619+
620+
// Clear any cached labels from before
621+
TextResourceEditorInput.MEMOIZER.clear();
622+
623+
// Trigger recompute of label
624+
this._onDidChangeLabel.fire();
625+
}
614626
}
615627

616628
getName(): string {
@@ -685,10 +697,6 @@ export abstract class TextResourceEditorInput extends EditorInput {
685697
return false; // untitled is never readonly
686698
}
687699

688-
if (!this.fileService.canHandleResource(this.resource)) {
689-
return true; // resources without file support are always readonly
690-
}
691-
692700
return this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
693701
}
694702

src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browse
3939
import { ExtensionIdentifier, IExtensionContributions, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
4040
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
4141
import { CancellationToken } from 'vs/base/common/cancellation';
42-
import { ILabelService } from 'vs/platform/label/common/label';
42+
import { ILabelService, IFormatterChangeEvent } from 'vs/platform/label/common/label';
4343
import { ExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/electron-browser/extensionManagementServerService';
4444
import { IProductService } from 'vs/platform/product/common/productService';
4545
import { Schemas } from 'vs/base/common/network';
@@ -92,7 +92,7 @@ suite('ExtensionsActions Test', () => {
9292
}());
9393

9494
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
95-
instantiationService.stub(ILabelService, { onDidChangeFormatters: new Emitter<void>().event });
95+
instantiationService.stub(ILabelService, { onDidChangeFormatters: new Emitter<IFormatterChangeEvent>().event });
9696

9797
instantiationService.set(IExtensionTipsService, instantiationService.createInstance(ExtensionTipsService));
9898
instantiationService.stub(IURLService, URLService);

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66
import { localize } from 'vs/nls';
77
import { URI } from 'vs/base/common/uri';
8-
import { IDisposable } from 'vs/base/common/lifecycle';
8+
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
99
import * as paths from 'vs/base/common/path';
10-
import { Event, Emitter } from 'vs/base/common/event';
10+
import { Emitter } from 'vs/base/common/event';
1111
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions';
1212
import { Registry } from 'vs/platform/registry/common/platform';
1313
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@@ -16,7 +16,7 @@ import { isEqual, basenameOrAuthority, basename, joinPath, dirname } from 'vs/ba
1616
import { tildify, getPathLabel } from 'vs/base/common/labels';
1717
import { ltrim, endsWith } from 'vs/base/common/strings';
1818
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, WORKSPACE_EXTENSION, toWorkspaceIdentifier, isWorkspaceIdentifier, isUntitledWorkspace } from 'vs/platform/workspaces/common/workspaces';
19-
import { ILabelService, ResourceLabelFormatter, ResourceLabelFormatting } from 'vs/platform/label/common/label';
19+
import { ILabelService, ResourceLabelFormatter, ResourceLabelFormatting, IFormatterChangeEvent } from 'vs/platform/label/common/label';
2020
import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
2121
import { match } from 'vs/base/common/glob';
2222
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
@@ -89,19 +89,20 @@ class ResourceLabelFormattersHandler implements IWorkbenchContribution {
8989
}
9090
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ResourceLabelFormattersHandler, LifecyclePhase.Restored);
9191

92-
export class LabelService implements ILabelService {
92+
export class LabelService extends Disposable implements ILabelService {
93+
9394
_serviceBrand: undefined;
9495

9596
private formatters: ResourceLabelFormatter[] = [];
96-
private readonly _onDidChangeFormatters = new Emitter<void>();
97+
98+
private readonly _onDidChangeFormatters = this._register(new Emitter<IFormatterChangeEvent>());
99+
readonly onDidChangeFormatters = this._onDidChangeFormatters.event;
97100

98101
constructor(
99102
@IEnvironmentService private readonly environmentService: IEnvironmentService,
100103
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
101-
) { }
102-
103-
get onDidChangeFormatters(): Event<void> {
104-
return this._onDidChangeFormatters.event;
104+
) {
105+
super();
105106
}
106107

107108
findFormatting(resource: URI): ResourceLabelFormatting | undefined {
@@ -226,12 +227,12 @@ export class LabelService implements ILabelService {
226227

227228
registerFormatter(formatter: ResourceLabelFormatter): IDisposable {
228229
this.formatters.push(formatter);
229-
this._onDidChangeFormatters.fire();
230+
this._onDidChangeFormatters.fire({ scheme: formatter.scheme });
230231

231232
return {
232233
dispose: () => {
233234
this.formatters = this.formatters.filter(f => f !== formatter);
234-
this._onDidChangeFormatters.fire();
235+
this._onDidChangeFormatters.fire({ scheme: formatter.scheme });
235236
}
236237
};
237238
}

0 commit comments

Comments
 (0)