Merge VS Code 1.31.1 (#4283)

This commit is contained in:
Matt Irvine
2019-03-15 13:09:45 -07:00
committed by GitHub
parent 7d31575149
commit 86bac90001
1716 changed files with 53308 additions and 48375 deletions

View File

@@ -87,13 +87,13 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR
const instantiationService = accessor.get(IInstantiationService);
const lifecycleService = accessor.get(ILifecycleService);
Promise.resolve(this.triggerAndDisposeAction(instantiationService, lifecycleService, descriptor, args)).then(null, err => {
Promise.resolve(this.triggerAndDisposeAction(instantiationService, lifecycleService, descriptor, args)).then(undefined, err => {
notificationService.error(err);
});
};
}
private triggerAndDisposeAction(instantiationService: IInstantiationService, lifecycleService: ILifecycleService, descriptor: SyncActionDescriptor, args: any): Thenable<void> {
private triggerAndDisposeAction(instantiationService: IInstantiationService, lifecycleService: ILifecycleService, descriptor: SyncActionDescriptor, args: any): Promise<void> {
// run action when workbench is created
return lifecycleService.when(LifecyclePhase.Ready).then(() => {
@@ -105,7 +105,7 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR
if (!actionInstance.enabled) {
actionInstance.dispose();
return void 0;
return undefined;
}
const from = args && args.from || 'keybinding';

View File

@@ -11,7 +11,7 @@ export interface IActivity {
id: string;
name: string;
keybindingId?: string;
cssClass: string;
cssClass?: string;
}
export interface IGlobalActivity extends IActivity {

View File

@@ -15,7 +15,7 @@ export interface IComposite {
/**
* Returns the name of this composite to show in the title area.
*/
getTitle(): string;
getTitle(): string | null;
/**
* Returns the primary actions of the composite.
@@ -35,12 +35,12 @@ export interface IComposite {
/**
* Returns the action item for a specific action.
*/
getActionItem(action: IAction): IActionItem;
getActionItem(action: IAction): IActionItem | null;
/**
* Returns the underlying control of this composite.
*/
getControl(): ICompositeControl;
getControl(): ICompositeControl | null;
/**
* Asks the underlying control to focus.

View File

@@ -8,8 +8,6 @@ import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/
import { Registry } from 'vs/platform/registry/common/platform';
import { runWhenIdle, IdleDeadline } from 'vs/base/common/async';
// --- Workbench Contribution Registry
/**
* A workbench contribution that will be loaded when the workbench starts and disposed when the workbench shuts down.
*/

View File

@@ -3,8 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { Event, Emitter, once } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import * as objects from 'vs/base/common/objects';
import * as types from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
@@ -20,7 +19,7 @@ import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsSer
import { ICompositeControl } from 'vs/workbench/common/composite';
import { ActionRunner, IAction } from 'vs/base/common/actions';
export const ActiveEditorContext = new RawContextKey<string>('activeEditor', null);
export const ActiveEditorContext = new RawContextKey<string | null>('activeEditor', null);
export const EditorsVisibleContext = new RawContextKey<boolean>('editorIsOpen', false);
export const EditorGroupActiveEditorDirtyContext = new RawContextKey<boolean>('groupActiveEditorDirty', false);
export const NoEditorsVisibleContext: ContextKeyExpr = EditorsVisibleContext.toNegated();
@@ -47,17 +46,17 @@ export interface IEditor {
/**
* The assigned input of this editor.
*/
input: IEditorInput;
input: IEditorInput | null;
/**
* The assigned options of this editor.
*/
options: IEditorOptions;
options: IEditorOptions | null;
/**
* The assigned group this editor is showing in.
*/
group: IEditorGroup;
group: IEditorGroup | undefined;
/**
* The minimum width of this editor.
@@ -82,7 +81,7 @@ export interface IEditor {
/**
* An event to notify whenever minimum/maximum width/height changes.
*/
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; }>;
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; } | undefined>;
/**
* Returns the unique identifier of this editor.
@@ -92,7 +91,7 @@ export interface IEditor {
/**
* Returns the underlying control of this editor.
*/
getControl(): IEditorControl;
getControl(): IEditorControl | null;
/**
* Asks the underlying control to focus.
@@ -277,7 +276,7 @@ export interface IEditorInput extends IDisposable {
/**
* Returns the associated resource of this input.
*/
getResource(): URI;
getResource(): URI | null;
/**
* Unique type identifier for this inpput.
@@ -287,22 +286,22 @@ export interface IEditorInput extends IDisposable {
/**
* Returns the display name of this input.
*/
getName(): string;
getName(): string | null;
/**
* Returns the display description of this input.
*/
getDescription(verbosity?: Verbosity): string;
getDescription(verbosity?: Verbosity): string | null;
/**
* Returns the display title of this input.
*/
getTitle(verbosity?: Verbosity): string;
getTitle(verbosity?: Verbosity): string | null;
/**
* Resolves the input.
*/
resolve(): Thenable<IEditorModel>;
resolve(): Promise<IEditorModel | null>;
/**
* Returns if this input is dirty or not.
@@ -312,7 +311,7 @@ export interface IEditorInput extends IDisposable {
/**
* Reverts this input.
*/
revert(options?: IRevertOptions): TPromise<boolean>;
revert(options?: IRevertOptions): Promise<boolean>;
/**
* Returns if the other object matches this input.
@@ -345,7 +344,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
/**
* Returns the associated resource of this input if any.
*/
getResource(): URI {
getResource(): URI | null {
return null;
}
@@ -353,7 +352,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
* Returns the name of this input that can be shown to the user. Examples include showing the name of the input
* above the editor area when the input is shown.
*/
getName(): string {
getName(): string | null {
return null;
}
@@ -361,7 +360,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
* Returns the description of this input that can be shown to the user. Examples include showing the description of
* the input above the editor area to the side of the name of the input.
*/
getDescription(verbosity?: Verbosity): string {
getDescription(verbosity?: Verbosity): string | null {
return null;
}
@@ -369,7 +368,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
* Returns the title of this input that can be shown to the user. Examples include showing the title of
* the input above the editor area as hover over the input label.
*/
getTitle(verbosity?: Verbosity): string {
getTitle(verbosity?: Verbosity): string | null {
return this.getName();
}
@@ -377,7 +376,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
* Returns the preferred editor for this input. A list of candidate editors is passed in that whee registered
* for the input. This allows subclasses to decide late which editor to use for the input on a case by case basis.
*/
getPreferredEditorId(candidates: string[]): string {
getPreferredEditorId(candidates: string[]): string | null {
if (candidates && candidates.length > 0) {
return candidates[0];
}
@@ -403,7 +402,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
* Returns a type of EditorModel that represents the resolved input. Subclasses should
* override to provide a meaningful model.
*/
abstract resolve(): Thenable<IEditorModel>;
abstract resolve(): Promise<IEditorModel | null>;
/**
* An editor that is dirty will be asked to be saved once it closes.
@@ -415,22 +414,22 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
/**
* Subclasses should bring up a proper dialog for the user if the editor is dirty and return the result.
*/
confirmSave(): TPromise<ConfirmResult> {
return TPromise.wrap(ConfirmResult.DONT_SAVE);
confirmSave(): Promise<ConfirmResult> {
return Promise.resolve(ConfirmResult.DONT_SAVE);
}
/**
* Saves the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation.
*/
save(): TPromise<boolean> {
return TPromise.as(true);
save(): Promise<boolean> {
return Promise.resolve(true);
}
/**
* Reverts the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation.
*/
revert(options?: IRevertOptions): TPromise<boolean> {
return TPromise.as(true);
revert(options?: IRevertOptions): Promise<boolean> {
return Promise.resolve(true);
}
/**
@@ -522,6 +521,8 @@ export interface IEncodingSupport {
*/
export interface IFileEditorInput extends IEditorInput, IEncodingSupport {
getResource(): URI;
/**
* Sets the preferred encodingt to use for this input.
*/
@@ -558,15 +559,15 @@ export class SideBySideEditorInput extends EditorInput {
return this.master.isDirty();
}
confirmSave(): TPromise<ConfirmResult> {
confirmSave(): Promise<ConfirmResult> {
return this.master.confirmSave();
}
save(): TPromise<boolean> {
save(): Promise<boolean> {
return this.master.save();
}
revert(): TPromise<boolean> {
revert(): Promise<boolean> {
return this.master.revert();
}
@@ -578,14 +579,14 @@ export class SideBySideEditorInput extends EditorInput {
private registerListeners(): void {
// When the details or master input gets disposed, dispose this diff editor input
const onceDetailsDisposed = once(this.details.onDispose);
const onceDetailsDisposed = Event.once(this.details.onDispose);
this._register(onceDetailsDisposed(() => {
if (!this.isDisposed()) {
this.dispose();
}
}));
const onceMasterDisposed = once(this.master.onDispose);
const onceMasterDisposed = Event.once(this.master.onDispose);
this._register(onceMasterDisposed(() => {
if (!this.isDisposed()) {
this.dispose();
@@ -597,7 +598,7 @@ export class SideBySideEditorInput extends EditorInput {
this._register(this.master.onDidChangeLabel(() => this._onDidChangeLabel.fire()));
}
resolve(): Thenable<EditorModel> {
resolve(): Promise<EditorModel | null> {
return Promise.resolve(null);
}
@@ -648,7 +649,7 @@ export class EditorModel extends Disposable implements IEditorModel {
/**
* Causes this model to load returning a promise when loading is completed.
*/
load(): Thenable<EditorModel> {
load(): Promise<EditorModel> {
return Promise.resolve(this);
}
@@ -706,41 +707,41 @@ export class EditorOptions implements IEditorOptions {
* Tells the editor to not receive keyboard focus when the editor is being opened. By default,
* the editor will receive keyboard focus on open.
*/
preserveFocus: boolean;
preserveFocus: boolean | undefined;
/**
* Tells the editor to reload the editor input in the editor even if it is identical to the one
* already showing. By default, the editor will not reload the input if it is identical to the
* one showing.
*/
forceReload: boolean;
forceReload: boolean | undefined;
/**
* Will reveal the editor if it is already opened and visible in any of the opened editor groups.
*/
revealIfVisible: boolean;
revealIfVisible: boolean | undefined;
/**
* Will reveal the editor if it is already opened (even when not visible) in any of the opened editor groups.
*/
revealIfOpened: boolean;
revealIfOpened: boolean | undefined;
/**
* An editor that is pinned remains in the editor stack even when another editor is being opened.
* An editor that is not pinned will always get replaced by another editor that is not pinned.
*/
pinned: boolean;
pinned: boolean | undefined;
/**
* The index in the document stack where to insert the editor into when opening.
*/
index: number;
index: number | undefined;
/**
* An active editor that is opened will show its contents directly. Set to true to open an editor
* in the background.
*/
inactive: boolean;
inactive: boolean | undefined;
}
/**
@@ -753,9 +754,9 @@ export class TextEditorOptions extends EditorOptions {
private endColumn: number;
private revealInCenterIfOutsideViewport: boolean;
private editorViewState: IEditorViewState;
private editorViewState: IEditorViewState | null;
static from(input?: IBaseResourceInput): TextEditorOptions {
static from(input?: IBaseResourceInput): TextEditorOptions | null {
if (!input || !input.options) {
return null;
}
@@ -927,7 +928,7 @@ export class EditorCommandsContextActionRunner extends ActionRunner {
super();
}
run(action: IAction, context?: any): Thenable<void> {
run(action: IAction, context?: any): Promise<void> {
return super.run(action, this.context);
}
}
@@ -951,6 +952,7 @@ export interface IWorkbenchEditorPartConfiguration {
highlightModifiedTabs?: boolean;
tabCloseButton?: 'left' | 'right' | 'off';
tabSizing?: 'fit' | 'shrink';
focusRecentEditorAfterClose?: boolean;
showIcons?: boolean;
enablePreview?: boolean;
enablePreviewFromQuickOpen?: boolean;
@@ -969,7 +971,7 @@ export interface IResourceOptions {
filter?: string | string[];
}
export function toResource(editor: IEditorInput, options?: IResourceOptions): URI {
export function toResource(editor: IEditorInput, options?: IResourceOptions): URI | null {
if (!editor) {
return null;
}
@@ -1019,8 +1021,8 @@ export interface IEditorMemento<T> {
saveEditorState(group: IEditorGroup, resource: URI, state: T): void;
saveEditorState(group: IEditorGroup, editor: EditorInput, state: T): void;
loadEditorState(group: IEditorGroup, resource: URI): T;
loadEditorState(group: IEditorGroup, editor: EditorInput): T;
loadEditorState(group: IEditorGroup, resource: URI): T | undefined;
loadEditorState(group: IEditorGroup, editor: EditorInput): T | undefined;
clearEditorState(resource: URI, group?: IEditorGroup): void;
clearEditorState(editor: EditorInput, group?: IEditorGroup): void;

View File

@@ -22,7 +22,7 @@ export class BinaryEditorModel extends EditorModel {
constructor(
resource: URI,
name: string,
@IFileService private fileService: IFileService
@IFileService private readonly fileService: IFileService
) {
super();
@@ -35,7 +35,7 @@ export class BinaryEditorModel extends EditorModel {
this.size = Number(metadata.get(DataUri.META_DATA_SIZE));
}
this.mime = metadata.get(DataUri.META_DATA_MIME);
this.mime = metadata.get(DataUri.META_DATA_MIME)!;
}
}
@@ -74,13 +74,15 @@ export class BinaryEditorModel extends EditorModel {
return this.etag;
}
load(): Thenable<EditorModel> {
load(): Promise<EditorModel> {
// Make sure to resolve up to date stat for file resources
if (this.fileService.canHandleResource(this.resource)) {
return this.fileService.resolveFile(this.resource).then(stat => {
this.etag = stat.etag;
this.size = stat.size;
if (typeof stat.size === 'number') {
this.size = stat.size;
}
return this;
});

View File

@@ -18,14 +18,14 @@ export class DataUriEditorInput extends EditorInput {
static readonly ID: string = 'workbench.editors.dataUriEditorInput';
private resource: URI;
private name: string;
private description: string;
private readonly name: string | undefined;
private readonly description: string | undefined;
constructor(
name: string,
description: string,
resource: URI,
@IInstantiationService private instantiationService: IInstantiationService
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
super();
@@ -54,15 +54,15 @@ export class DataUriEditorInput extends EditorInput {
return DataUriEditorInput.ID;
}
getName(): string {
return this.name;
getName(): string | null {
return this.name || null;
}
getDescription(): string {
return this.description;
getDescription(): string | null {
return this.description || null;
}
resolve(): Thenable<BinaryEditorModel> {
resolve(): Promise<BinaryEditorModel> {
return this.instantiationService.createInstance(BinaryEditorModel, this.resource, this.getName()).load().then(m => m as BinaryEditorModel);
}

View File

@@ -34,7 +34,7 @@ export class DiffEditorInput extends SideBySideEditorInput {
return this.master;
}
resolve(): Thenable<EditorModel> {
resolve(): Promise<EditorModel> {
// Create Model - we never reuse our cached model if refresh is true because we cannot
// decide for the inputs within if the cached model can be reused or not. There may be
@@ -55,7 +55,7 @@ export class DiffEditorInput extends SideBySideEditorInput {
return this.forceOpenAsBinary ? BINARY_DIFF_EDITOR_ID : TEXT_DIFF_EDITOR_ID;
}
private createModel(): Thenable<DiffEditorModel> {
private createModel(): Promise<DiffEditorModel> {
// Join resolve call over two inputs and build diff editor model
return Promise.all([

View File

@@ -29,7 +29,7 @@ export class DiffEditorModel extends EditorModel {
return this._modifiedModel as EditorModel;
}
load(): Thenable<EditorModel> {
load(): Promise<EditorModel> {
return Promise.all([
this._originalModel.load(),
this._modifiedModel.load()

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter, once } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { Extensions, IEditorInputFactoryRegistry, EditorInput, toResource, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, SideBySideEditorInput, CloseDirection } from 'vs/workbench/common/editor';
import { URI } from 'vs/base/common/uri';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -11,6 +11,7 @@ import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/co
import { dispose, IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { ResourceMap } from 'vs/base/common/map';
import { coalesce } from 'vs/base/common/arrays';
// {{SQL CARBON EDIT}}
import { QueryInput } from 'sql/parts/query/common/queryInput';
@@ -49,7 +50,7 @@ export interface ISerializedEditorGroup {
id: number;
editors: ISerializedEditorInput[];
mru: number[];
preview: number;
preview?: number;
}
export function isSerializedEditorGroup(obj?: any): obj is ISerializedEditorGroup {
@@ -99,15 +100,16 @@ export class EditorGroup extends Disposable {
private mru: EditorInput[] = [];
private mapResourceToEditorCount: ResourceMap<number> = new ResourceMap<number>();
private preview: EditorInput; // editor in preview state
private active: EditorInput; // editor in active state
private preview: EditorInput | null; // editor in preview state
private active: EditorInput | null; // editor in active state
private editorOpenPositioning: 'left' | 'right' | 'first' | 'last';
private focusRecentEditorAfterClose: boolean;
constructor(
labelOrSerializedGroup: ISerializedEditorGroup,
@IInstantiationService private instantiationService: IInstantiationService,
@IConfigurationService private configurationService: IConfigurationService
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IConfigurationService private readonly configurationService: IConfigurationService
) {
super();
@@ -127,6 +129,7 @@ export class EditorGroup extends Disposable {
private onConfigurationUpdated(event?: IConfigurationChangeEvent): void {
this.editorOpenPositioning = this.configurationService.getValue('workbench.editor.openPositioning');
this.focusRecentEditorAfterClose = this.configurationService.getValue('workbench.editor.focusRecentEditorAfterClose');
}
get id(): GroupIdentifier {
@@ -141,9 +144,9 @@ export class EditorGroup extends Disposable {
return mru ? this.mru.slice(0) : this.editors.slice(0);
}
getEditor(index: number): EditorInput;
getEditor(resource: URI): EditorInput;
getEditor(arg1: any): EditorInput {
getEditor(index: number): EditorInput | null;
getEditor(resource: URI): EditorInput | null;
getEditor(arg1: any): EditorInput | null {
if (typeof arg1 === 'number') {
return this.editors[arg1];
}
@@ -153,8 +156,7 @@ export class EditorGroup extends Disposable {
return null; // fast check for resource opened or not
}
for (let i = 0; i < this.editors.length; i++) {
const editor = this.editors[i];
for (const editor of this.editors) {
const editorResource = toResource(editor, { supportSideBySide: true });
if (editorResource && editorResource.toString() === resource.toString()) {
return editor;
@@ -164,7 +166,7 @@ export class EditorGroup extends Disposable {
return null;
}
get activeEditor(): EditorInput {
get activeEditor(): EditorInput | null {
return this.active;
}
@@ -172,7 +174,7 @@ export class EditorGroup extends Disposable {
return this.matches(this.active, editor);
}
get previewEditor(): EditorInput {
get previewEditor(): EditorInput | null {
return this.preview;
}
@@ -277,7 +279,7 @@ export class EditorGroup extends Disposable {
const unbind: IDisposable[] = [];
// Re-emit disposal of editor input as our own event
const onceDispose = once(editor.onDispose);
const onceDispose = Event.once(editor.onDispose);
unbind.push(onceDispose(() => {
if (this.indexOf(editor) >= 0) {
this._onDidEditorDispose.fire(editor);
@@ -302,20 +304,20 @@ export class EditorGroup extends Disposable {
}));
}
private replaceEditor(toReplace: EditorInput, replaceWidth: EditorInput, replaceIndex: number, openNext = true): void {
private replaceEditor(toReplace: EditorInput, replaceWith: EditorInput, replaceIndex: number, openNext = true): void {
const event = this.doCloseEditor(toReplace, openNext, true); // optimization to prevent multiple setActive() in one call
// We want to first add the new editor into our model before emitting the close event because
// firing the close event can trigger a dispose on the same editor that is now being added.
// This can lead into opening a disposed editor which is not what we want.
this.splice(replaceIndex, false, replaceWidth);
this.splice(replaceIndex, false, replaceWith);
if (event) {
this._onDidEditorClose.fire(event);
}
}
closeEditor(editor: EditorInput, openNext = true): number {
closeEditor(editor: EditorInput, openNext = true): number | undefined {
const event = this.doCloseEditor(editor, openNext, false);
if (event) {
@@ -324,10 +326,10 @@ export class EditorGroup extends Disposable {
return event.index;
}
return void 0;
return undefined;
}
private doCloseEditor(editor: EditorInput, openNext: boolean, replaced: boolean): EditorCloseEvent {
private doCloseEditor(editor: EditorInput, openNext: boolean, replaced: boolean): EditorCloseEvent | null {
const index = this.indexOf(editor);
if (index === -1) {
return null; // not found
@@ -338,7 +340,18 @@ export class EditorGroup extends Disposable {
// More than one editor
if (this.mru.length > 1) {
this.setActive(this.mru[1]); // active editor is always first in MRU, so pick second editor after as new active
let newActive: EditorInput;
if (this.focusRecentEditorAfterClose) {
newActive = this.mru[1]; // active editor is always first in MRU, so pick second editor after as new active
} else {
if (index === this.editors.length - 1) {
newActive = this.editors[index - 1]; // last editor is closed, pick previous as new active
} else {
newActive = this.editors[index + 1]; // pick next editor as new active
}
}
this.setActive(newActive);
}
// One Editor
@@ -389,7 +402,9 @@ export class EditorGroup extends Disposable {
// Optimize: close all non active editors first to produce less upstream work
this.mru.filter(e => !this.matches(e, this.active)).forEach(e => this.closeEditor(e));
this.closeEditor(this.active);
if (this.active) {
this.closeEditor(this.active);
}
}
moveEditor(editor: EditorInput, toIndex: number): void {
@@ -460,7 +475,9 @@ export class EditorGroup extends Disposable {
this._onDidEditorUnpin.fire(editor);
// Close old preview editor if any
this.closeEditor(oldPreview);
if (oldPreview) {
this.closeEditor(oldPreview);
}
}
isPinned(editor: EditorInput): boolean;
@@ -515,7 +532,7 @@ export class EditorGroup extends Disposable {
}
// Replace
else {
else if (del && editor) {
this.mru.splice(indexInMRU, 1, editor); // replace MRU at location
this.updateResourceMap(editor, false /* add */); // add new to resource map
this.updateResourceMap(editorToDeleteOrReplace, true /* delete */); // remove replaced from resource map
@@ -529,21 +546,28 @@ export class EditorGroup extends Disposable {
// It is possible to have the same resource opened twice (once as normal input and once as diff input)
// So we need to do ref counting on the resource to provide the correct picture
let counter = this.mapResourceToEditorCount.get(resource) || 0;
const counter = this.mapResourceToEditorCount.get(resource) || 0;
// Add
let newCounter: number;
if (remove) {
if (counter > 1) {
newCounter = counter - 1;
}
} else {
if (!remove) {
newCounter = counter + 1;
}
this.mapResourceToEditorCount.set(resource, newCounter);
// Delete
else {
newCounter = counter - 1;
}
if (newCounter > 0) {
this.mapResourceToEditorCount.set(resource, newCounter);
} else {
this.mapResourceToEditorCount.delete(resource);
}
}
}
indexOf(candidate: EditorInput, editors = this.editors): number {
indexOf(candidate: EditorInput | null, editors = this.editors): number {
if (!candidate) {
return -1;
}
@@ -596,12 +620,12 @@ export class EditorGroup extends Disposable {
this.mru.unshift(editor);
}
private matches(editorA: EditorInput, editorB: EditorInput): boolean {
private matches(editorA: EditorInput | null, editorB: EditorInput | null): boolean {
return !!editorA && !!editorB && editorA.matches(editorB);
}
clone(): EditorGroup {
const group = this.instantiationService.createInstance(EditorGroup, void 0);
const group = this.instantiationService.createInstance(EditorGroup, undefined);
group.editors = this.editors.slice(0);
group.mru = this.mru.slice(0);
group.mapResourceToEditorCount = this.mapResourceToEditorCount.clone();
@@ -620,7 +644,7 @@ export class EditorGroup extends Disposable {
// from mru, active and preview if any.
let serializableEditors: EditorInput[] = [];
let serializedEditors: ISerializedEditorInput[] = [];
let serializablePreviewIndex: number;
let serializablePreviewIndex: number | undefined;
// {{SQL CARBON EDIT}}
let editors = this.editors.map(e => {
if (e instanceof QueryInput) {
@@ -683,7 +707,7 @@ export class EditorGroup extends Disposable {
this._id = EditorGroup.IDS++; // backwards compatibility
}
this.editors = data.editors.map(e => {
this.editors = coalesce(data.editors.map(e => {
const factory = registry.getEditorInputFactory(e.id);
if (factory) {
const editor = factory.deserialize(this.instantiationService, e.value);
@@ -696,9 +720,11 @@ export class EditorGroup extends Disposable {
}
return null;
}).filter(e => !!e);
}));
this.mru = data.mru.map(i => this.editors[i]);
this.active = this.mru[0];
this.preview = this.editors[data.preview];
if (typeof data.preview === 'number') {
this.preview = this.editors[data.preview];
}
}
}

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { EditorInput, ITextEditorModel } from 'vs/workbench/common/editor';
import { URI } from 'vs/base/common/uri';
import { IReference } from 'vs/base/common/lifecycle';
@@ -20,7 +19,7 @@ export class ResourceEditorInput extends EditorInput {
static readonly ID: string = 'workbench.editors.resourceEditorInput';
private modelReference: TPromise<IReference<ITextEditorModel>>;
private modelReference: Promise<IReference<ITextEditorModel>>;
private resource: URI;
private name: string;
private description: string;
@@ -29,8 +28,8 @@ export class ResourceEditorInput extends EditorInput {
name: string,
description: string,
resource: URI,
@ITextModelService private textModelResolverService: ITextModelService,
@IHashService private hashService: IHashService
@ITextModelService private readonly textModelResolverService: ITextModelService,
@IHashService private readonly hashService: IHashService
) {
super();
@@ -81,7 +80,7 @@ export class ResourceEditorInput extends EditorInput {
return descriptor;
}
resolve(): Thenable<ITextEditorModel> {
resolve(): Promise<ITextEditorModel> {
if (!this.modelReference) {
this.modelReference = this.textModelResolverService.createModelReference(this.resource);
}

View File

@@ -29,7 +29,7 @@ export class TextDiffEditorModel extends DiffEditorModel {
return this._modifiedModel as BaseTextEditorModel;
}
load(): Thenable<EditorModel> {
load(): Promise<EditorModel> {
return super.load().then(() => {
this.updateTextDiffEditorModel();

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { ITextModel, ITextBufferFactory } from 'vs/editor/common/model';
import { EditorModel } from 'vs/workbench/common/editor';
import { URI } from 'vs/base/common/uri';
@@ -69,11 +68,11 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
/**
* Creates the text editor model with the provided value, modeId (can be comma separated for multiple values) and optional resource URL.
*/
protected createTextEditorModel(value: ITextBufferFactory, resource?: URI, modeId?: string): TPromise<EditorModel> {
protected createTextEditorModel(value: ITextBufferFactory, resource?: URI, modeId?: string): EditorModel {
const firstLineText = this.getFirstLineText(value);
const languageSelection = this.getOrCreateMode(this.modeService, modeId, firstLineText);
return TPromise.as(this.doCreateTextEditorModel(value, languageSelection, resource));
return this.doCreateTextEditorModel(value, languageSelection, resource);
}
private doCreateTextEditorModel(value: ITextBufferFactory, languageSelection: ILanguageSelection, resource: URI): EditorModel {

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { URI } from 'vs/base/common/uri';
import { suggestFilename } from 'vs/base/common/mime';
import { memoize } from 'vs/base/common/decorators';
@@ -28,7 +27,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
private _hasAssociatedFilePath: boolean;
private cachedModel: UntitledEditorModel;
private modelResolve: TPromise<UntitledEditorModel>;
private modelResolve: Promise<UntitledEditorModel>;
private readonly _onDidModelChangeContent: Emitter<void> = this._register(new Emitter<void>());
get onDidModelChangeContent(): Event<void> { return this._onDidModelChangeContent.event; }
@@ -42,10 +41,10 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
private modeId: string,
private initialValue: string,
private preferredEncoding: string,
@IInstantiationService private instantiationService: IInstantiationService,
@ITextFileService private textFileService: ITextFileService,
@IHashService private hashService: IHashService,
@ILabelService private labelService: ILabelService
@IInstantiationService private readonly instantiationService: IInstantiationService,
@ITextFileService private readonly textFileService: ITextFileService,
@IHashService private readonly hashService: IHashService,
@ILabelService private readonly labelService: ILabelService
) {
super();
@@ -168,22 +167,22 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
return this.hasAssociatedFilePath;
}
confirmSave(): TPromise<ConfirmResult> {
confirmSave(): Promise<ConfirmResult> {
return this.textFileService.confirmSave([this.resource]);
}
save(): TPromise<boolean> {
save(): Promise<boolean> {
return this.textFileService.save(this.resource);
}
revert(): TPromise<boolean> {
revert(): Promise<boolean> {
if (this.cachedModel) {
this.cachedModel.revert();
}
this.dispose(); // a reverted untitled editor is no longer valid, so we dispose it
return TPromise.as(true);
return Promise.resolve(true);
}
suggestFileName(): string {
@@ -215,7 +214,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
}
}
resolve(): Thenable<UntitledEditorModel> {
resolve(): Promise<UntitledEditorModel> {
// Join a model resolve if we have had one before
if (this.modelResolve) {
@@ -268,7 +267,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
}
dispose(): void {
this.modelResolve = void 0;
this.modelResolve = undefined;
super.dispose();
}

View File

@@ -43,8 +43,8 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
private preferredEncoding: string,
@IModeService modeService: IModeService,
@IModelService modelService: IModelService,
@IBackupFileService private backupFileService: IBackupFileService,
@ITextResourceConfigurationService private configurationService: ITextResourceConfigurationService
@IBackupFileService private readonly backupFileService: IBackupFileService,
@ITextResourceConfigurationService private readonly configurationService: ITextResourceConfigurationService
) {
super(modelService, modeService);
@@ -134,7 +134,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
this.contentChangeEventScheduler.schedule();
}
load(): Thenable<UntitledEditorModel> {
load(): Promise<UntitledEditorModel> {
// Check for backups first
return this.backupFileService.loadBackupResource(this.resource).then(backupResource => {
@@ -156,37 +156,29 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
untitledContents = createTextBufferFactory(this.initialValue || '');
}
return this.doLoad(untitledContents).then(model => {
// Create text editor model if not yet done
if (!this.textEditorModel) {
this.createTextEditorModel(untitledContents, this.resource, this.modeId);
}
// Encoding
this.configuredEncoding = this.configurationService.getValue<string>(this.resource, 'files.encoding');
// Otherwise update
else {
this.updateTextEditorModel(untitledContents);
}
// Listen to content changes
this._register(this.textEditorModel.onDidChangeContent(() => this.onModelContentChanged()));
// Encoding
this.configuredEncoding = this.configurationService.getValue<string>(this.resource, 'files.encoding');
// Listen to mode changes
this._register(this.textEditorModel.onDidChangeLanguage(() => this.onConfigurationChange())); // mode change can have impact on config
// Listen to content changes
this._register(this.textEditorModel.onDidChangeContent(() => this.onModelContentChanged()));
return model;
});
// Listen to mode changes
this._register(this.textEditorModel.onDidChangeLanguage(() => this.onConfigurationChange())); // mode change can have impact on config
return this;
});
}
private doLoad(content: ITextBufferFactory): Thenable<UntitledEditorModel> {
// Create text editor model if not yet done
if (!this.textEditorModel) {
return this.createTextEditorModel(content, this.resource, this.modeId).then(model => this);
}
// Otherwise update
else {
this.updateTextEditorModel(content);
}
return Promise.resolve<UntitledEditorModel>(this);
}
private onModelContentChanged(): void {
this.versionId++;

View File

@@ -5,7 +5,7 @@
import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice } from 'vs/platform/notification/common/notification';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { Event, Emitter, once } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { Action } from 'vs/base/common/actions';
@@ -53,7 +53,7 @@ export class NotificationHandle implements INotificationHandle {
}
private registerListeners(): void {
once(this.item.onDidClose)(() => {
Event.once(this.item.onDidClose)(() => {
this._onDidClose.fire();
this._onDidClose.dispose();
});
@@ -126,14 +126,13 @@ export class NotificationsModel extends Disposable implements INotificationsMode
}
private findNotification(item: INotificationViewItem): INotificationViewItem | undefined {
for (let i = 0; i < this._notifications.length; i++) {
const notification = this._notifications[i];
for (const notification of this._notifications) {
if (notification.equals(item)) {
return notification;
}
}
return void 0;
return undefined;
}
private createViewItem(notification: INotification): INotificationViewItem | null {
@@ -160,7 +159,7 @@ export class NotificationsModel extends Disposable implements INotificationsMode
}
});
once(item.onDidClose)(() => {
Event.once(item.onDidClose)(() => {
itemExpansionChangeListener.dispose();
itemLabelChangeListener.dispose();
@@ -258,9 +257,9 @@ export class NotificationViewItemProgress extends Disposable implements INotific
this._state.infinite = true;
this._state.total = void 0;
this._state.worked = void 0;
this._state.done = void 0;
this._state.total = undefined;
this._state.worked = undefined;
this._state.done = undefined;
this._onDidChange.fire();
}
@@ -272,9 +271,9 @@ export class NotificationViewItemProgress extends Disposable implements INotific
this._state.done = true;
this._state.infinite = void 0;
this._state.total = void 0;
this._state.worked = void 0;
this._state.infinite = undefined;
this._state.total = undefined;
this._state.worked = undefined;
this._onDidChange.fire();
}
@@ -286,8 +285,8 @@ export class NotificationViewItemProgress extends Disposable implements INotific
this._state.total = value;
this._state.infinite = void 0;
this._state.done = void 0;
this._state.infinite = undefined;
this._state.done = undefined;
this._onDidChange.fire();
}
@@ -299,8 +298,8 @@ export class NotificationViewItemProgress extends Disposable implements INotific
this._state.worked = value;
}
this._state.infinite = void 0;
this._state.done = void 0;
this._state.infinite = undefined;
this._state.done = undefined;
this._onDidChange.fire();
}
@@ -378,7 +377,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie
}
if (!message) {
return void 0; // we need a message to show
return undefined; // we need a message to show
}
const raw = message;
@@ -587,7 +586,7 @@ export class ChoiceAction extends Action {
private _keepOpen: boolean;
constructor(id: string, choice: IPromptChoice) {
super(id, choice.label, void 0, true, () => {
super(id, choice.label, undefined, true, () => {
// Pass to runner
choice.run();
@@ -595,7 +594,7 @@ export class ChoiceAction extends Action {
// Emit Event
this._onDidRun.fire();
return Promise.resolve(void 0);
return Promise.resolve();
});
this._keepOpen = !!choice.keepOpen;

View File

@@ -9,7 +9,6 @@ import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/cont
import { IModeService } from 'vs/editor/common/services/modeService';
import { IFileService } from 'vs/platform/files/common/files';
import { Disposable } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
export class ResourceContextKey extends Disposable implements IContextKey<URI> {
@@ -20,7 +19,6 @@ export class ResourceContextKey extends Disposable implements IContextKey<URI> {
static Extension = new RawContextKey<string>('resourceExtname', undefined);
static HasResource = new RawContextKey<boolean>('resourceSet', false);
static IsFileSystemResource = new RawContextKey<boolean>('isFileSystemResource', false);
static IsFileSystemResourceOrUntitled = new RawContextKey<boolean>('isFileSystemResourceOrUntitled', false);
private readonly _resourceKey: IContextKey<URI>;
private readonly _schemeKey: IContextKey<string>;
@@ -29,7 +27,6 @@ export class ResourceContextKey extends Disposable implements IContextKey<URI> {
private readonly _extensionKey: IContextKey<string>;
private readonly _hasResource: IContextKey<boolean>;
private readonly _isFileSystemResource: IContextKey<boolean>;
private readonly _isFileSystemResourceOrUntitled: IContextKey<boolean>;
constructor(
@IContextKeyService contextKeyService: IContextKeyService,
@@ -45,12 +42,15 @@ export class ResourceContextKey extends Disposable implements IContextKey<URI> {
this._extensionKey = ResourceContextKey.Extension.bindTo(contextKeyService);
this._hasResource = ResourceContextKey.HasResource.bindTo(contextKeyService);
this._isFileSystemResource = ResourceContextKey.IsFileSystemResource.bindTo(contextKeyService);
this._isFileSystemResourceOrUntitled = ResourceContextKey.IsFileSystemResourceOrUntitled.bindTo(contextKeyService);
this._register(_fileService.onDidChangeFileSystemProviderRegistrations(() => {
const resource = this._resourceKey.get();
this._isFileSystemResource.set(Boolean(resource && _fileService.canHandleResource(resource)));
this._isFileSystemResourceOrUntitled.set(this._isFileSystemResource.get() || this._schemeKey.get() === Schemas.untitled);
}));
this._register(_modeService.onDidCreateMode(() => {
const value = this._resourceKey.get();
this._langIdKey.set(value ? this._modeService.getModeIdByFilepathOrFirstLine(value.fsPath) : null);
}));
}
@@ -63,7 +63,6 @@ export class ResourceContextKey extends Disposable implements IContextKey<URI> {
this._extensionKey.set(value && paths.extname(value.fsPath));
this._hasResource.set(!!value);
this._isFileSystemResource.set(value && this._fileService.canHandleResource(value));
this._isFileSystemResourceOrUntitled.set(this._isFileSystemResource.get() || this._schemeKey.get() === Schemas.untitled);
}
}
@@ -75,7 +74,6 @@ export class ResourceContextKey extends Disposable implements IContextKey<URI> {
this._extensionKey.reset();
this._hasResource.reset();
this._isFileSystemResource.reset();
this._isFileSystemResourceOrUntitled.reset();
}
get(): URI | undefined {

View File

@@ -298,6 +298,11 @@ export const STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND = registerColor('statusB
hc: '#369432'
}, nls.localize('statusBarProminentItemHoverBackground', "Status bar prominent items background color when hovering. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window."));
export const STATUS_BAR_HOST_NAME_BACKGROUND = registerColor('statusBarItem.hostBackground', {
dark: STATUS_BAR_PROMINENT_ITEM_BACKGROUND,
light: STATUS_BAR_PROMINENT_ITEM_BACKGROUND,
hc: STATUS_BAR_PROMINENT_ITEM_BACKGROUND
}, nls.localize('statusBarItemHostBackground', "Background color for the remote host name on the status bar."));
// < --- Activity Bar --- >

View File

@@ -10,5 +10,5 @@ export interface IViewlet extends IComposite {
/**
* Returns the minimal width needed to avoid any content horizontal truncation
*/
getOptimalWidth(): number;
getOptimalWidth(): number | null;
}

View File

@@ -13,11 +13,12 @@ import { IViewlet } from 'vs/workbench/common/viewlet';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable } from 'vs/base/common/lifecycle';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { values } from 'vs/base/common/map';
import { values, keys } from 'vs/base/common/map';
import { Registry } from 'vs/platform/registry/common/platform';
import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IAction } from 'vs/base/common/actions';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export const TEST_VIEW_CONTAINER_ID = 'workbench.view.extension.test';
@@ -31,6 +32,11 @@ export interface IViewContainersRegistry {
*/
readonly onDidRegister: Event<ViewContainer>;
/**
* An event that is triggerred when a view container is deregistered.
*/
readonly onDidDeregister: Event<ViewContainer>;
/**
* All registered view containers
*/
@@ -44,46 +50,65 @@ export interface IViewContainersRegistry {
*
* @returns the registered ViewContainer.
*/
registerViewContainer(id: string, extensionId?: string): ViewContainer;
registerViewContainer(id: string, extensionId?: ExtensionIdentifier): ViewContainer;
/**
* Deregisters the given view container
* No op if the view container is not registered
*/
deregisterViewContainer(viewContainer: ViewContainer): void;
/**
* Returns the view container with given id.
*
* @param id
* @returns the view container with given id.
*/
get(id: string): ViewContainer;
get(id: string): ViewContainer | undefined;
}
export class ViewContainer {
protected constructor(readonly id: string, readonly extensionId: string) { }
protected constructor(readonly id: string, readonly extensionId: ExtensionIdentifier) { }
}
class ViewContainersRegistryImpl implements IViewContainersRegistry {
private readonly _onDidRegister: Emitter<ViewContainer> = new Emitter<ViewContainer>();
private readonly _onDidRegister = new Emitter<ViewContainer>();
readonly onDidRegister: Event<ViewContainer> = this._onDidRegister.event;
private readonly _onDidDeregister = new Emitter<ViewContainer>();
readonly onDidDeregister: Event<ViewContainer> = this._onDidDeregister.event;
private viewContainers: Map<string, ViewContainer> = new Map<string, ViewContainer>();
get all(): ViewContainer[] {
return values(this.viewContainers);
}
registerViewContainer(id: string, extensionId: string): ViewContainer {
if (!this.viewContainers.has(id)) {
const viewContainer = new class extends ViewContainer {
constructor() {
super(id, extensionId);
}
};
this.viewContainers.set(id, viewContainer);
this._onDidRegister.fire(viewContainer);
registerViewContainer(id: string, extensionId: ExtensionIdentifier): ViewContainer {
const existing = this.viewContainers.get(id);
if (existing) {
return existing;
}
return this.get(id);
const viewContainer = new class extends ViewContainer {
constructor() {
super(id, extensionId);
}
};
this.viewContainers.set(id, viewContainer);
this._onDidRegister.fire(viewContainer);
return viewContainer;
}
get(id: string): ViewContainer {
deregisterViewContainer(viewContainer: ViewContainer): void {
const existing = this.viewContainers.get(viewContainer.id);
if (existing) {
this.viewContainers.delete(viewContainer.id);
this._onDidDeregister.fire(viewContainer);
}
}
get(id: string): ViewContainer | undefined {
return this.viewContainers.get(id);
}
}
@@ -96,8 +121,6 @@ export interface IViewDescriptor {
readonly name: string;
readonly container: ViewContainer;
// TODO@Sandeep do we really need this?!
readonly ctor: any;
@@ -117,7 +140,7 @@ export interface IViewDescriptor {
readonly focusCommand?: { id: string, keybindings?: IKeybindings };
}
export interface IViewDescriptorCollection {
export interface IViewDescriptorCollection extends IDisposable {
readonly onDidChangeActiveViews: Event<{ added: IViewDescriptor[], removed: IViewDescriptor[] }>;
readonly activeViewDescriptors: IViewDescriptor[];
readonly allViewDescriptors: IViewDescriptor[];
@@ -125,70 +148,61 @@ export interface IViewDescriptorCollection {
export interface IViewsRegistry {
readonly onViewsRegistered: Event<IViewDescriptor[]>;
readonly onViewsRegistered: Event<{ views: IViewDescriptor[], viewContainer: ViewContainer }>;
readonly onViewsDeregistered: Event<IViewDescriptor[]>;
readonly onViewsDeregistered: Event<{ views: IViewDescriptor[], viewContainer: ViewContainer }>;
registerViews(views: IViewDescriptor[]): void;
readonly onDidChangeContainer: Event<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }>;
deregisterViews(ids: string[], container: ViewContainer): void;
registerViews(views: IViewDescriptor[], viewContainer: ViewContainer): void;
getViews(loc: ViewContainer): IViewDescriptor[];
deregisterViews(views: IViewDescriptor[], viewContainer: ViewContainer): void;
moveViews(views: IViewDescriptor[], viewContainer: ViewContainer): void;
getViews(viewContainer: ViewContainer): IViewDescriptor[];
getView(id: string): IViewDescriptor | null;
getAllViews(): IViewDescriptor[];
getViewContainer(id: string): ViewContainer | null;
}
export const ViewsRegistry: IViewsRegistry = new class implements IViewsRegistry {
private readonly _onViewsRegistered: Emitter<IViewDescriptor[]> = new Emitter<IViewDescriptor[]>();
readonly onViewsRegistered: Event<IViewDescriptor[]> = this._onViewsRegistered.event;
private readonly _onViewsRegistered: Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = new Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }>();
readonly onViewsRegistered: Event<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = this._onViewsRegistered.event;
private readonly _onViewsDeregistered: Emitter<IViewDescriptor[]> = new Emitter<IViewDescriptor[]>();
readonly onViewsDeregistered: Event<IViewDescriptor[]> = this._onViewsDeregistered.event;
private readonly _onViewsDeregistered: Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = new Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }>();
readonly onViewsDeregistered: Event<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = this._onViewsDeregistered.event;
private _viewContainer: ViewContainer[] = [];
private readonly _onDidChangeContainer: Emitter<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }> = new Emitter<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }>();
readonly onDidChangeContainer: Event<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }> = this._onDidChangeContainer.event;
private _viewContainers: ViewContainer[] = [];
private _views: Map<ViewContainer, IViewDescriptor[]> = new Map<ViewContainer, IViewDescriptor[]>();
registerViews(viewDescriptors: IViewDescriptor[]): void {
if (viewDescriptors.length) {
for (const viewDescriptor of viewDescriptors) {
let views = this._views.get(viewDescriptor.container);
if (!views) {
views = [];
this._views.set(viewDescriptor.container, views);
this._viewContainer.push(viewDescriptor.container);
}
if (views.some(v => v.id === viewDescriptor.id)) {
throw new Error(localize('duplicateId', "A view with id '{0}' is already registered in the container '{1}'", viewDescriptor.id, viewDescriptor.container.id));
}
views.push(viewDescriptor);
}
this._onViewsRegistered.fire(viewDescriptors);
registerViews(views: IViewDescriptor[], viewContainer: ViewContainer): void {
this.addViews(views, viewContainer);
this._onViewsRegistered.fire({ views: views, viewContainer });
}
deregisterViews(viewDescriptors: IViewDescriptor[], viewContainer: ViewContainer): void {
const views = this.removeViews(viewDescriptors, viewContainer);
if (views.length) {
this._onViewsDeregistered.fire({ views, viewContainer });
}
}
deregisterViews(ids: string[], container: ViewContainer): void {
const views = this._views.get(container);
if (!views) {
return;
}
const viewsToDeregister = views.filter(view => ids.indexOf(view.id) !== -1);
if (viewsToDeregister.length) {
const remaningViews = views.filter(view => ids.indexOf(view.id) === -1);
if (remaningViews.length) {
this._views.set(container, remaningViews);
} else {
this._views.delete(container);
this._viewContainer.splice(this._viewContainer.indexOf(container), 1);
moveViews(viewsToMove: IViewDescriptor[], viewContainer: ViewContainer): void {
keys(this._views).forEach(container => {
if (container !== viewContainer) {
const views = this.removeViews(viewsToMove, container);
if (views.length) {
this.addViews(views, viewContainer);
this._onDidChangeContainer.fire({ views, from: container, to: viewContainer });
}
}
this._onViewsDeregistered.fire(viewsToDeregister);
}
});
}
getViews(loc: ViewContainer): IViewDescriptor[] {
@@ -196,7 +210,7 @@ export const ViewsRegistry: IViewsRegistry = new class implements IViewsRegistry
}
getView(id: string): IViewDescriptor | null {
for (const viewContainer of this._viewContainer) {
for (const viewContainer of this._viewContainers) {
const viewDescriptor = (this._views.get(viewContainer) || []).filter(v => v.id === id)[0];
if (viewDescriptor) {
return viewDescriptor;
@@ -205,10 +219,54 @@ export const ViewsRegistry: IViewsRegistry = new class implements IViewsRegistry
return null;
}
getAllViews(): IViewDescriptor[] {
const allViews: IViewDescriptor[] = [];
this._views.forEach(views => allViews.push(...views));
return allViews;
getViewContainer(viewId: string): ViewContainer | null {
for (const viewContainer of this._viewContainers) {
const viewDescriptor = (this._views.get(viewContainer) || []).filter(v => v.id === viewId)[0];
if (viewDescriptor) {
return viewContainer;
}
}
return null;
}
private addViews(viewDescriptors: IViewDescriptor[], viewContainer: ViewContainer): void {
let views = this._views.get(viewContainer);
if (!views) {
views = [];
this._views.set(viewContainer, views);
this._viewContainers.push(viewContainer);
}
for (const viewDescriptor of viewDescriptors) {
if (views.some(v => v.id === viewDescriptor.id)) {
throw new Error(localize('duplicateId', "A view with id '{0}' is already registered in the container '{1}'", viewDescriptor.id, viewContainer.id));
}
views.push(viewDescriptor);
}
}
private removeViews(viewDescriptors: IViewDescriptor[], viewContainer: ViewContainer): IViewDescriptor[] {
const views = this._views.get(viewContainer);
if (!views) {
return [];
}
const viewsToDeregister: IViewDescriptor[] = [];
const remaningViews: IViewDescriptor[] = [];
for (const view of views) {
if (viewDescriptors.indexOf(view) === -1) {
remaningViews.push(view);
} else {
viewsToDeregister.push(view);
}
}
if (viewsToDeregister.length) {
if (remaningViews.length) {
this._views.set(viewContainer, remaningViews);
} else {
this._views.delete(viewContainer);
this._viewContainers.splice(this._viewContainers.indexOf(viewContainer), 1);
}
}
return viewsToDeregister;
}
};
@@ -229,9 +287,9 @@ export const IViewsService = createDecorator<IViewsService>('viewsService');
export interface IViewsService {
_serviceBrand: any;
openView(id: string, focus?: boolean): Thenable<IView>;
openView(id: string, focus?: boolean): Promise<IView | null>;
getViewDescriptors(container: ViewContainer): IViewDescriptorCollection;
getViewDescriptors(container: ViewContainer): IViewDescriptorCollection | null;
}
// Custom views
@@ -268,9 +326,9 @@ export interface ITreeView extends IDisposable {
getOptimalWidth(): number;
reveal(item: ITreeItem): Thenable<void>;
reveal(item: ITreeItem): Promise<void>;
expand(itemOrItems: ITreeItem | ITreeItem[]): Thenable<void>;
expand(itemOrItems: ITreeItem | ITreeItem[]): Promise<void>;
setSelection(items: ITreeItem[]): void;
@@ -291,7 +349,7 @@ export interface IRevealOptions {
}
export interface ICustomViewDescriptor extends IViewDescriptor {
export interface ITreeViewDescriptor extends IViewDescriptor {
readonly treeView: ITreeView;