Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)

* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973

* disable strict null check
This commit is contained in:
Anthony Dresser
2019-07-15 22:35:46 -07:00
committed by GitHub
parent f720ec642f
commit 0b7e7ddbf9
2406 changed files with 59140 additions and 35464 deletions

View File

@@ -8,7 +8,7 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co
import { ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands';
import { SyncActionDescriptor, MenuRegistry, MenuId, ICommandAction } from 'vs/platform/actions/common/actions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
@@ -33,10 +33,10 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR
}
private registerWorkbenchCommandFromAction(descriptor: SyncActionDescriptor, alias: string, category?: string, when?: ContextKeyExpr): IDisposable {
let registrations: IDisposable[] = [];
const registrations = new DisposableStore();
// command
registrations.push(CommandsRegistry.registerCommand(descriptor.id, this.createCommandHandler(descriptor)));
registrations.add(CommandsRegistry.registerCommand(descriptor.id, this.createCommandHandler(descriptor)));
// keybinding
const weight = (typeof descriptor.keybindingWeight === 'undefined' ? KeybindingWeight.WorkbenchContrib : descriptor.keybindingWeight);
@@ -72,13 +72,13 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR
MenuRegistry.addCommand(command);
registrations.push(MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command, when }));
registrations.add(MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command, when }));
}
// TODO@alex,joh
// support removal of keybinding rule
// support removal of command-ui
return combinedDisposable(registrations);
return registrations;
}
private createCommandHandler(descriptor: SyncActionDescriptor): ICommandHandler {

View File

@@ -3,10 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Registry } from 'vs/platform/registry/common/platform';
import { IAction } from 'vs/base/common/actions';
import { IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation';
export interface IActivity {
id: string;
name: string;
@@ -14,31 +10,4 @@ export interface IActivity {
cssClass?: string;
}
export interface IGlobalActivity extends IActivity {
getActions(): IAction[];
}
export const GlobalActivityExtensions = 'workbench.contributions.globalActivities';
export interface IGlobalActivityRegistry {
registerActivity(descriptor: IConstructorSignature0<IGlobalActivity>): void;
getActivities(): IConstructorSignature0<IGlobalActivity>[];
}
export class GlobalActivityRegistry implements IGlobalActivityRegistry {
private readonly activityDescriptors = new Set<IConstructorSignature0<IGlobalActivity>>();
registerActivity(descriptor: IConstructorSignature0<IGlobalActivity>): void {
this.activityDescriptors.add(descriptor);
}
getActivities(): IConstructorSignature0<IGlobalActivity>[] {
const result: IConstructorSignature0<IGlobalActivity>[] = [];
this.activityDescriptors.forEach(d => result.push(d));
return result;
}
}
Registry.add(GlobalActivityExtensions, new GlobalActivityRegistry());
export const GLOBAL_ACTIVITY_ID = 'workbench.action.globalActivity';

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Memento } from 'vs/workbench/common/memento';
import { Memento, MementoObject } from 'vs/workbench/common/memento';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { Themable } from 'vs/workbench/common/theme';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
@@ -35,7 +35,7 @@ export class Component extends Themable {
return this.id;
}
protected getMemento(scope: StorageScope): object {
protected getMemento(scope: StorageScope): MementoObject {
return this.memento.getMemento(scope);
}

View File

@@ -20,17 +20,17 @@ export interface IComposite {
/**
* Returns the primary actions of the composite.
*/
getActions(): IAction[];
getActions(): ReadonlyArray<IAction>;
/**
* Returns the secondary actions of the composite.
*/
getSecondaryActions(): IAction[];
getSecondaryActions(): ReadonlyArray<IAction>;
/**
* Returns an array of actions to show in the context menu of the composite
*/
getContextMenuActions(): IAction[];
getContextMenuActions(): ReadonlyArray<IAction>;
/**
* Returns the action item for a specific action.

View File

@@ -23,7 +23,9 @@ import { coalesce } from 'vs/base/common/arrays';
export const ActiveEditorContext = new RawContextKey<string | null>('activeEditor', null);
export const EditorsVisibleContext = new RawContextKey<boolean>('editorIsOpen', false);
export const EditorPinnedContext = new RawContextKey<boolean>('editorPinned', false);
export const EditorGroupActiveEditorDirtyContext = new RawContextKey<boolean>('groupActiveEditorDirty', false);
export const EditorGroupEditorsCountContext = new RawContextKey<number>('groupEditorsCount', 0);
export const NoEditorsVisibleContext: ContextKeyExpr = EditorsVisibleContext.toNegated();
export const TextCompareEditorVisibleContext = new RawContextKey<boolean>('textCompareEditorVisible', false);
export const TextCompareEditorActiveContext = new RawContextKey<boolean>('textCompareEditorActive', false);
@@ -31,6 +33,7 @@ export const ActiveEditorGroupEmptyContext = new RawContextKey<boolean>('activeE
export const MultipleEditorGroupsContext = new RawContextKey<boolean>('multipleEditorGroups', false);
export const SingleEditorGroupsContext = MultipleEditorGroupsContext.toNegated();
export const InEditorZenModeContext = new RawContextKey<boolean>('inZenMode', false);
export const IsCenteredLayoutContext = new RawContextKey<boolean>('isCenteredLayout', false);
export const SplitEditorsVertically = new RawContextKey<boolean>('splitEditorsVertically', false);
/**
@@ -175,7 +178,7 @@ export interface IEditorInputFactoryRegistry {
*
* @param editorInputId the identifier of the editor input
*/
getEditorInputFactory(editorInputId: string): IEditorInputFactory;
getEditorInputFactory(editorInputId: string): IEditorInputFactory | undefined;
/**
* Starts the registry by providing the required services.
@@ -292,7 +295,7 @@ export interface IEditorInput extends IDisposable {
/**
* Returns the display description of this input.
*/
getDescription(verbosity?: Verbosity): string | null;
getDescription(verbosity?: Verbosity): string | undefined;
/**
* Returns the display title of this input.
@@ -327,13 +330,13 @@ export interface IEditorInput extends IDisposable {
export abstract class EditorInput extends Disposable implements IEditorInput {
protected readonly _onDidChangeDirty: Emitter<void> = this._register(new Emitter<void>());
get onDidChangeDirty(): Event<void> { return this._onDidChangeDirty.event; }
readonly onDidChangeDirty: Event<void> = this._onDidChangeDirty.event;
protected readonly _onDidChangeLabel: Emitter<void> = this._register(new Emitter<void>());
get onDidChangeLabel(): Event<void> { return this._onDidChangeLabel.event; }
readonly onDidChangeLabel: Event<void> = this._onDidChangeLabel.event;
private readonly _onDispose: Emitter<void> = this._register(new Emitter<void>());
get onDispose(): Event<void> { return this._onDispose.event; }
readonly onDispose: Event<void> = this._onDispose.event;
private disposed: boolean = false;
@@ -361,8 +364,8 @@ 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 | null {
return null;
getDescription(verbosity?: Verbosity): string | undefined {
return undefined;
}
/**
@@ -377,12 +380,12 @@ 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 | null {
if (candidates && candidates.length > 0) {
getPreferredEditorId(candidates: string[]): string | undefined {
if (candidates.length > 0) {
return candidates[0];
}
return null;
return undefined;
}
/**
@@ -560,7 +563,7 @@ export class SideBySideEditorInput extends EditorInput {
constructor(
private readonly name: string,
private readonly description: string | null,
private readonly description: string | undefined,
private readonly _details: EditorInput,
private readonly _master: EditorInput
) {
@@ -633,7 +636,7 @@ export class SideBySideEditorInput extends EditorInput {
return this.name;
}
getDescription(): string | null {
getDescription(): string | undefined {
return this.description;
}
@@ -666,7 +669,7 @@ export interface ITextEditorModel extends IEditorModel {
export class EditorModel extends Disposable implements IEditorModel {
private readonly _onDispose: Emitter<void> = this._register(new Emitter<void>());
get onDispose(): Event<void> { return this._onDispose.event; }
readonly onDispose: Event<void> = this._onDispose.event;
/**
* Causes this model to load returning a promise when loading is completed.
@@ -994,7 +997,7 @@ interface IEditorPartConfiguration {
openSideBySideDirection?: 'right' | 'down';
closeEmptyGroups?: boolean;
revealIfOpen?: boolean;
swipeToNavigate?: boolean;
mouseBackForwardToNavigate?: boolean;
labelFormat?: 'default' | 'short' | 'medium' | 'long';
restoreViewState?: boolean;
}
@@ -1058,23 +1061,22 @@ export interface IEditorMemento<T> {
class EditorInputFactoryRegistry implements IEditorInputFactoryRegistry {
private instantiationService: IInstantiationService;
private fileInputFactory: IFileInputFactory;
private editorInputFactoryConstructors: { [editorInputId: string]: IConstructorSignature0<IEditorInputFactory> } = Object.create(null);
private readonly editorInputFactoryInstances: { [editorInputId: string]: IEditorInputFactory } = Object.create(null);
private readonly editorInputFactoryConstructors: Map<string, IConstructorSignature0<IEditorInputFactory>> = new Map();
private readonly editorInputFactoryInstances: Map<string, IEditorInputFactory> = new Map();
start(accessor: ServicesAccessor): void {
this.instantiationService = accessor.get(IInstantiationService);
for (let key in this.editorInputFactoryConstructors) {
const element = this.editorInputFactoryConstructors[key];
this.createEditorInputFactory(key, element);
}
this.editorInputFactoryConstructors.forEach((ctor, key) => {
this.createEditorInputFactory(key, ctor);
});
this.editorInputFactoryConstructors = Object.create(null);
this.editorInputFactoryConstructors.clear();
}
private createEditorInputFactory(editorInputId: string, ctor: IConstructorSignature0<IEditorInputFactory>): void {
const instance = this.instantiationService.createInstance(ctor);
this.editorInputFactoryInstances[editorInputId] = instance;
this.editorInputFactoryInstances.set(editorInputId, instance);
}
registerFileInputFactory(factory: IFileInputFactory): void {
@@ -1087,14 +1089,14 @@ class EditorInputFactoryRegistry implements IEditorInputFactoryRegistry {
registerEditorInputFactory(editorInputId: string, ctor: IConstructorSignature0<IEditorInputFactory>): void {
if (!this.instantiationService) {
this.editorInputFactoryConstructors[editorInputId] = ctor;
this.editorInputFactoryConstructors.set(editorInputId, ctor);
} else {
this.createEditorInputFactory(editorInputId, ctor);
}
}
getEditorInputFactory(editorInputId: string): IEditorInputFactory {
return this.editorInputFactoryInstances[editorInputId];
getEditorInputFactory(editorInputId: string): IEditorInputFactory | undefined {
return this.editorInputFactoryInstances.get(editorInputId);
}
}

View File

@@ -55,8 +55,8 @@ export class DataUriEditorInput extends EditorInput {
return withUndefinedAsNull(this.name);
}
getDescription(): string | null {
return withUndefinedAsNull(this.description);
getDescription(): string | undefined {
return this.description;
}
resolve(): Promise<BinaryEditorModel> {

View File

@@ -18,7 +18,7 @@ export class DiffEditorInput extends SideBySideEditorInput {
private cachedModel: DiffEditorModel | null;
constructor(name: string, description: string | null, original: EditorInput, modified: EditorInput, private readonly forceOpenAsBinary?: boolean) {
constructor(name: string, description: string | undefined, original: EditorInput, modified: EditorInput, private readonly forceOpenAsBinary?: boolean) {
super(name, description, original, modified);
}

View File

@@ -8,7 +8,7 @@ import { Extensions, IEditorInputFactoryRegistry, EditorInput, toResource, IEdit
import { URI } from 'vs/base/common/uri';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { dispose, IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { dispose, Disposable, DisposableStore } 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';
@@ -69,31 +69,31 @@ export class EditorGroup extends Disposable {
//#region events
private readonly _onDidEditorActivate = this._register(new Emitter<EditorInput>());
get onDidEditorActivate(): Event<EditorInput> { return this._onDidEditorActivate.event; }
readonly onDidEditorActivate: Event<EditorInput> = this._onDidEditorActivate.event;
private readonly _onDidEditorOpen = this._register(new Emitter<EditorInput>());
get onDidEditorOpen(): Event<EditorInput> { return this._onDidEditorOpen.event; }
readonly onDidEditorOpen: Event<EditorInput> = this._onDidEditorOpen.event;
private readonly _onDidEditorClose = this._register(new Emitter<EditorCloseEvent>());
get onDidEditorClose(): Event<EditorCloseEvent> { return this._onDidEditorClose.event; }
readonly onDidEditorClose: Event<EditorCloseEvent> = this._onDidEditorClose.event;
private readonly _onDidEditorDispose = this._register(new Emitter<EditorInput>());
get onDidEditorDispose(): Event<EditorInput> { return this._onDidEditorDispose.event; }
readonly onDidEditorDispose: Event<EditorInput> = this._onDidEditorDispose.event;
private readonly _onDidEditorBecomeDirty = this._register(new Emitter<EditorInput>());
get onDidEditorBecomeDirty(): Event<EditorInput> { return this._onDidEditorBecomeDirty.event; }
readonly onDidEditorBecomeDirty: Event<EditorInput> = this._onDidEditorBecomeDirty.event;
private readonly _onDidEditorLabelChange = this._register(new Emitter<EditorInput>());
get onDidEditorLabelChange(): Event<EditorInput> { return this._onDidEditorLabelChange.event; }
readonly onDidEditorLabelChange: Event<EditorInput> = this._onDidEditorLabelChange.event;
private readonly _onDidEditorMove = this._register(new Emitter<EditorInput>());
get onDidEditorMove(): Event<EditorInput> { return this._onDidEditorMove.event; }
readonly onDidEditorMove: Event<EditorInput> = this._onDidEditorMove.event;
private readonly _onDidEditorPin = this._register(new Emitter<EditorInput>());
get onDidEditorPin(): Event<EditorInput> { return this._onDidEditorPin.event; }
readonly onDidEditorPin: Event<EditorInput> = this._onDidEditorPin.event;
private readonly _onDidEditorUnpin = this._register(new Emitter<EditorInput>());
get onDidEditorUnpin(): Event<EditorInput> { return this._onDidEditorUnpin.event; }
readonly onDidEditorUnpin: Event<EditorInput> = this._onDidEditorUnpin.event;
//#endregion
@@ -147,16 +147,16 @@ export class EditorGroup extends Disposable {
return mru ? this.mru.slice(0) : this.editors.slice(0);
}
getEditor(index: number): EditorInput | null;
getEditor(resource: URI): EditorInput | null;
getEditor(arg1: number | URI): EditorInput | null {
getEditor(index: number): EditorInput | undefined;
getEditor(resource: URI): EditorInput | undefined;
getEditor(arg1: number | URI): EditorInput | undefined {
if (typeof arg1 === 'number') {
return this.editors[arg1];
}
const resource: URI = arg1;
if (!this.contains(resource)) {
return null; // fast check for resource opened or not
return undefined; // fast check for resource opened or not
}
for (const editor of this.editors) {
@@ -166,7 +166,7 @@ export class EditorGroup extends Disposable {
}
}
return null;
return undefined;
}
get activeEditor(): EditorInput | null {
@@ -279,30 +279,30 @@ export class EditorGroup extends Disposable {
}
private registerEditorListeners(editor: EditorInput): void {
const unbind: IDisposable[] = [];
const listeners = new DisposableStore();
// Re-emit disposal of editor input as our own event
const onceDispose = Event.once(editor.onDispose);
unbind.push(onceDispose(() => {
listeners.add(onceDispose(() => {
if (this.indexOf(editor) >= 0) {
this._onDidEditorDispose.fire(editor);
}
}));
// Re-Emit dirty state changes
unbind.push(editor.onDidChangeDirty(() => {
listeners.add(editor.onDidChangeDirty(() => {
this._onDidEditorBecomeDirty.fire(editor);
}));
// Re-Emit label changes
unbind.push(editor.onDidChangeLabel(() => {
listeners.add(editor.onDidChangeLabel(() => {
this._onDidEditorLabelChange.fire(editor);
}));
// Clean up dispose listeners once the editor gets closed
unbind.push(this.onDidEditorClose(event => {
listeners.add(this.onDidEditorClose(event => {
if (event.editor.matches(editor)) {
dispose(unbind);
dispose(listeners);
}
}));
}

View File

@@ -22,7 +22,7 @@ export class ResourceEditorInput extends EditorInput implements IModeSupport {
constructor(
private name: string,
private description: string | null,
private description: string | undefined,
private readonly resource: URI,
private preferredMode: string | undefined,
@ITextModelService private readonly textModelResolverService: ITextModelService
@@ -53,7 +53,7 @@ export class ResourceEditorInput extends EditorInput implements IModeSupport {
}
}
getDescription(): string | null {
getDescription(): string | undefined {
return this.description;
}
@@ -90,7 +90,7 @@ export class ResourceEditorInput extends EditorInput implements IModeSupport {
ref.dispose();
this.modelReference = null;
return Promise.reject(new Error(`Unexpected model for ResourceInput: ${this.resource}`));
throw new Error(`Unexpected model for ResourceInput: ${this.resource}`);
}
this.cachedModel = model;

View File

@@ -9,8 +9,9 @@ import { URI } from 'vs/base/common/uri';
import { ITextEditorModel, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
import { IModeService, ILanguageSelection } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { MutableDisposable } from 'vs/base/common/lifecycle';
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
import { withUndefinedAsNull } from 'vs/base/common/types';
/**
* The base text editor model leverages the code editor model. This class is only intended to be subclassed and not instantiated.
@@ -19,7 +20,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
protected textEditorModelHandle: URI | null;
private createdEditorModel: boolean;
private modelDisposeListener: IDisposable | null;
private readonly modelDisposeListener = this._register(new MutableDisposable());
constructor(
@IModelService protected modelService: IModelService,
@@ -48,11 +49,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
}
private registerModelDisposeListener(model: ITextModel): void {
if (this.modelDisposeListener) {
this.modelDisposeListener.dispose();
}
this.modelDisposeListener = model.onWillDispose(() => {
this.modelDisposeListener.value = model.onWillDispose(() => {
this.textEditorModelHandle = null; // make sure we do not dispose code editor model again
this.dispose();
});
@@ -126,7 +123,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
// lookup mode via resource path if the provided mode is unspecific
if (!preferredMode || preferredMode === PLAINTEXT_MODE_ID) {
return modeService.createByFilepathOrFirstLine(resource ? resource.path : null, firstLineText);
return modeService.createByFilepathOrFirstLine(withUndefinedAsNull(resource), firstLineText);
}
// otherwise take the preferred mode for granted
@@ -165,10 +162,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
}
dispose(): void {
if (this.modelDisposeListener) {
this.modelDisposeListener.dispose(); // dispose this first because it will trigger another dispose() otherwise
this.modelDisposeListener = null;
}
this.modelDisposeListener.dispose(); // dispose this first because it will trigger another dispose() otherwise
if (this.textEditorModelHandle && this.createdEditorModel) {
this.modelService.destroyModel(this.textEditorModelHandle);

View File

@@ -28,10 +28,10 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
private modelResolve: Promise<UntitledEditorModel & IResolvedTextEditorModel> | null;
private readonly _onDidModelChangeContent: Emitter<void> = this._register(new Emitter<void>());
get onDidModelChangeContent(): Event<void> { return this._onDidModelChangeContent.event; }
readonly onDidModelChangeContent: Event<void> = this._onDidModelChangeContent.event;
private readonly _onDidModelChangeEncoding: Emitter<void> = this._register(new Emitter<void>());
get onDidModelChangeEncoding(): Event<void> { return this._onDidModelChangeEncoding.event; }
readonly onDidModelChangeEncoding: Event<void> = this._onDidModelChangeEncoding.event;
constructor(
private readonly resource: URI,
@@ -77,9 +77,9 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
return this.labelService.getUriLabel(dirname(this.resource));
}
getDescription(verbosity: Verbosity = Verbosity.MEDIUM): string | null {
getDescription(verbosity: Verbosity = Verbosity.MEDIUM): string | undefined {
if (!this.hasAssociatedFilePath) {
return null;
return undefined;
}
switch (verbosity) {
@@ -144,6 +144,14 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
return this.hasAssociatedFilePath;
}
hasBackup(): boolean {
if (this.cachedModel) {
return this.cachedModel.hasBackup();
}
return false;
}
confirmSave(): Promise<ConfirmResult> {
return this.textFileService.confirmSave([this.resource]);
}

View File

@@ -22,13 +22,13 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
static DEFAULT_CONTENT_CHANGE_BUFFER_DELAY = CONTENT_CHANGE_EVENT_BUFFER_DELAY;
private readonly _onDidChangeContent: Emitter<void> = this._register(new Emitter<void>());
get onDidChangeContent(): Event<void> { return this._onDidChangeContent.event; }
readonly onDidChangeContent: Event<void> = this._onDidChangeContent.event;
private readonly _onDidChangeDirty: Emitter<void> = this._register(new Emitter<void>());
get onDidChangeDirty(): Event<void> { return this._onDidChangeDirty.event; }
readonly onDidChangeDirty: Event<void> = this._onDidChangeDirty.event;
private readonly _onDidChangeEncoding: Emitter<void> = this._register(new Emitter<void>());
get onDidChangeEncoding(): Event<void> { return this._onDidChangeEncoding.event; }
readonly onDidChangeEncoding: Event<void> = this._onDidChangeEncoding.event;
private dirty: boolean = false;
private versionId: number = 0;
@@ -135,6 +135,10 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
return Promise.resolve();
}
hasBackup(): boolean {
return this.backupFileService.hasBackupSync(this.resource, this.versionId);
}
async load(): Promise<UntitledEditorModel & IResolvedTextEditorModel> {
// Check for backups first

View File

@@ -6,10 +6,12 @@
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { isEmptyObject } from 'vs/base/common/types';
export type MementoObject = { [key: string]: any };
export class Memento {
private static globalMementos: { [id: string]: ScopedMemento } = Object.create(null);
private static workspaceMementos: { [id: string]: ScopedMemento } = Object.create(null);
private static readonly globalMementos = new Map<string, ScopedMemento>();
private static readonly workspaceMementos = new Map<string, ScopedMemento>();
private static readonly COMMON_PREFIX = 'memento/';
@@ -19,24 +21,24 @@ export class Memento {
this.id = Memento.COMMON_PREFIX + id;
}
getMemento(scope: StorageScope): object {
getMemento(scope: StorageScope): MementoObject {
// Scope by Workspace
if (scope === StorageScope.WORKSPACE) {
let workspaceMemento = Memento.workspaceMementos[this.id];
let workspaceMemento = Memento.workspaceMementos.get(this.id);
if (!workspaceMemento) {
workspaceMemento = new ScopedMemento(this.id, scope, this.storageService);
Memento.workspaceMementos[this.id] = workspaceMemento;
Memento.workspaceMementos.set(this.id, workspaceMemento);
}
return workspaceMemento.getMemento();
}
// Scope Global
let globalMemento = Memento.globalMementos[this.id];
let globalMemento = Memento.globalMementos.get(this.id);
if (!globalMemento) {
globalMemento = new ScopedMemento(this.id, scope, this.storageService);
Memento.globalMementos[this.id] = globalMemento;
Memento.globalMementos.set(this.id, globalMemento);
}
return globalMemento.getMemento();
@@ -45,13 +47,13 @@ export class Memento {
saveMemento(): void {
// Workspace
const workspaceMemento = Memento.workspaceMementos[this.id];
const workspaceMemento = Memento.workspaceMementos.get(this.id);
if (workspaceMemento) {
workspaceMemento.save();
}
// Global
const globalMemento = Memento.globalMementos[this.id];
const globalMemento = Memento.globalMementos.get(this.id);
if (globalMemento) {
globalMemento.save();
}
@@ -59,17 +61,17 @@ export class Memento {
}
class ScopedMemento {
private readonly mementoObj: object;
private readonly mementoObj: MementoObject;
constructor(private id: string, private scope: StorageScope, private storageService: IStorageService) {
this.mementoObj = this.load();
}
getMemento(): object {
getMemento(): MementoObject {
return this.mementoObj;
}
private load(): object {
private load(): MementoObject {
const memento = this.storageService.get(this.id, this.scope);
if (memento) {
return JSON.parse(memento);

View File

@@ -3,10 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice } from 'vs/platform/notification/common/notification';
import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { Event, Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { Action } from 'vs/base/common/actions';
import { isErrorWithActions } from 'vs/base/common/errorsWithActions';
@@ -15,10 +15,25 @@ import { localize } from 'vs/nls';
export interface INotificationsModel {
//
// Notifications as Toasts/Center
//
readonly notifications: INotificationViewItem[];
readonly onDidNotificationChange: Event<INotificationChangeEvent>;
notify(notification: INotification): INotificationHandle;
addNotification(notification: INotification): INotificationHandle;
//
// Notifications as Status
//
readonly statusMessage: IStatusMessageViewItem | undefined;
readonly onDidStatusMessageChange: Event<IStatusMessageChangeEvent>;
showStatusMessage(message: NotificationMessage, options?: IStatusMessageOptions): IDisposable;
}
export const enum NotificationChangeType {
@@ -45,10 +60,33 @@ export interface INotificationChangeEvent {
kind: NotificationChangeType;
}
export const enum StatusMessageChangeType {
ADD,
REMOVE
}
export interface IStatusMessageViewItem {
message: string;
options?: IStatusMessageOptions;
}
export interface IStatusMessageChangeEvent {
/**
* The status message item this change is about.
*/
item: IStatusMessageViewItem;
/**
* The kind of status message change.
*/
kind: StatusMessageChangeType;
}
export class NotificationHandle implements INotificationHandle {
private readonly _onDidClose: Emitter<void> = new Emitter();
get onDidClose(): Event<void> { return this._onDidClose.event; }
readonly onDidClose: Event<void> = this._onDidClose.event;
constructor(private readonly item: INotificationViewItem, private readonly closeItem: (item: INotificationViewItem) => void) {
this.registerListeners();
@@ -88,15 +126,18 @@ export class NotificationsModel extends Disposable implements INotificationsMode
private static NO_OP_NOTIFICATION = new NoOpNotification();
private readonly _onDidNotificationChange: Emitter<INotificationChangeEvent> = this._register(new Emitter<INotificationChangeEvent>());
get onDidNotificationChange(): Event<INotificationChangeEvent> { return this._onDidNotificationChange.event; }
readonly onDidNotificationChange: Event<INotificationChangeEvent> = this._onDidNotificationChange.event;
private readonly _onDidStatusMessageChange: Emitter<IStatusMessageChangeEvent> = this._register(new Emitter<IStatusMessageChangeEvent>());
readonly onDidStatusMessageChange: Event<IStatusMessageChangeEvent> = this._onDidStatusMessageChange.event;
private readonly _notifications: INotificationViewItem[] = [];
get notifications(): INotificationViewItem[] { return this._notifications; }
get notifications(): INotificationViewItem[] {
return this._notifications;
}
private _statusMessage: IStatusMessageViewItem | undefined;
get statusMessage(): IStatusMessageViewItem | undefined { return this._statusMessage; }
notify(notification: INotification): INotificationHandle {
addNotification(notification: INotification): INotificationHandle {
const item = this.createViewItem(notification);
if (!item) {
return NotificationsModel.NO_OP_NOTIFICATION; // return early if this is a no-op
@@ -174,6 +215,26 @@ export class NotificationsModel extends Disposable implements INotificationsMode
return item;
}
showStatusMessage(message: NotificationMessage, options?: IStatusMessageOptions): IDisposable {
const item = StatusMessageViewItem.create(message, options);
if (!item) {
return Disposable.None;
}
// Remember as current status message and fire events
this._statusMessage = item;
this._onDidStatusMessageChange.fire({ kind: StatusMessageChangeType.ADD, item });
return toDisposable(() => {
// Only reset status message if the item is still the one we had remembered
if (this._statusMessage === item) {
this._statusMessage = undefined;
this._onDidStatusMessageChange.fire({ kind: StatusMessageChangeType.REMOVE, item });
}
});
}
}
export interface INotificationViewItem {
@@ -240,7 +301,7 @@ export class NotificationViewItemProgress extends Disposable implements INotific
private readonly _state: INotificationViewItemProgressState;
private readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
get onDidChange(): Event<void> { return this._onDidChange.event; }
readonly onDidChange: Event<void> = this._onDidChange.event;
constructor() {
super();
@@ -336,13 +397,13 @@ export class NotificationViewItem extends Disposable implements INotificationVie
private _progress: NotificationViewItemProgress;
private readonly _onDidExpansionChange: Emitter<void> = this._register(new Emitter<void>());
get onDidExpansionChange(): Event<void> { return this._onDidExpansionChange.event; }
readonly onDidExpansionChange: Event<void> = this._onDidExpansionChange.event;
private readonly _onDidClose: Emitter<void> = this._register(new Emitter<void>());
get onDidClose(): Event<void> { return this._onDidClose.event; }
readonly onDidClose: Event<void> = this._onDidClose.event;
private readonly _onDidLabelChange: Emitter<INotificationViewItemLabelChangeEvent> = this._register(new Emitter<INotificationViewItemLabelChangeEvent>());
get onDidLabelChange(): Event<INotificationViewItemLabelChangeEvent> { return this._onDidLabelChange.event; }
readonly onDidLabelChange: Event<INotificationViewItemLabelChangeEvent> = this._onDidLabelChange.event;
static create(notification: INotification): INotificationViewItem | null {
if (!notification || !notification.message || isPromiseCanceledError(notification.message)) {
@@ -593,7 +654,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie
export class ChoiceAction extends Action {
private readonly _onDidRun = new Emitter<void>();
get onDidRun(): Event<void> { return this._onDidRun.event; }
readonly onDidRun: Event<void> = this._onDidRun.event;
private readonly _keepOpen: boolean;
@@ -621,4 +682,26 @@ export class ChoiceAction extends Action {
this._onDidRun.dispose();
}
}
class StatusMessageViewItem {
static create(notification: NotificationMessage, options?: IStatusMessageOptions): IStatusMessageViewItem | null {
if (!notification || isPromiseCanceledError(notification)) {
return null; // we need a message to show
}
let message: string | undefined;
if (notification instanceof Error) {
message = toErrorMessage(notification, false);
} else if (typeof notification === 'string') {
message = notification;
}
if (!message) {
return null; // we need a message to show
}
return { message, options };
}
}

View File

@@ -8,5 +8,6 @@ import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
export const ActivePanelContext = new RawContextKey<string>('activePanel', '');
export const PanelFocusContext = new RawContextKey<boolean>('panelFocus', false);
export const PanelPositionContext = new RawContextKey<string>('panelPosition', 'bottom');
export interface IPanel extends IComposite { }

View File

@@ -56,7 +56,7 @@ export class ResourceContextKey extends Disposable implements IContextKey<URI> {
this._register(_modeService.onDidCreateMode(() => {
const value = this._resourceKey.get();
this._langIdKey.set(value ? this._modeService.getModeIdByFilepathOrFirstLine(value.fsPath) : null);
this._langIdKey.set(value ? this._modeService.getModeIdByFilepathOrFirstLine(value) : null);
}));
}
@@ -65,7 +65,7 @@ export class ResourceContextKey extends Disposable implements IContextKey<URI> {
this._resourceKey.set(value);
this._schemeKey.set(value ? value.scheme : null);
this._filenameKey.set(value ? basename(value) : null);
this._langIdKey.set(value ? this._modeService.getModeIdByFilepathOrFirstLine(value.fsPath) : null);
this._langIdKey.set(value ? this._modeService.getModeIdByFilepathOrFirstLine(value) : null);
this._extensionKey.set(value ? extname(value) : null);
this._hasResource.set(!!value);
this._isFileSystemResource.set(value ? this._fileService.canHandleResource(value) : false);
@@ -107,7 +107,7 @@ export class ResourceGlobMatcher extends Disposable {
private static readonly NO_ROOT: string | null = null;
private readonly _onExpressionChange: Emitter<void> = this._register(new Emitter<void>());
get onExpressionChange(): Event<void> { return this._onExpressionChange.event; }
readonly onExpressionChange: Event<void> = this._onExpressionChange.event;
private readonly mapRootToParsedExpression: Map<string | null, ParsedExpression> = new Map<string, ParsedExpression>();
private readonly mapRootToExpressionConfig: Map<string | null, IExpression> = new Map<string, IExpression>();

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { registerColor, editorBackground, contrastBorder, transparent, editorWidgetBackground, textLinkForeground, lighten, darken, focusBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { registerColor, editorBackground, contrastBorder, transparent, editorWidgetBackground, textLinkForeground, lighten, darken, focusBorder, activeContrastBorder, editorWidgetForeground } from 'vs/platform/theme/common/colorRegistry';
import { Disposable } from 'vs/base/common/lifecycle';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { Color } from 'vs/base/common/color';
@@ -30,6 +30,12 @@ export const TAB_ACTIVE_BACKGROUND = registerColor('tab.activeBackground', {
hc: editorBackground
}, nls.localize('tabActiveBackground', "Active tab background color. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups."));
export const TAB_UNFOCUSED_ACTIVE_BACKGROUND = registerColor('tab.unfocusedActiveBackground', {
dark: TAB_ACTIVE_BACKGROUND,
light: TAB_ACTIVE_BACKGROUND,
hc: TAB_ACTIVE_BACKGROUND
}, nls.localize('tabUnfocusedActiveBackground', "Active tab background color in an unfocused group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups."));
export const TAB_INACTIVE_BACKGROUND = registerColor('tab.inactiveBackground', {
dark: '#2D2D2D',
light: '#ECECEC',
@@ -138,7 +144,6 @@ export const TAB_UNFOCUSED_INACTIVE_FOREGROUND = registerColor('tab.unfocusedIna
hc: Color.white
}, nls.localize('tabUnfocusedInactiveForeground', "Inactive tab foreground color in an unfocused group. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups."));
// < --- Editors --- >
export const EDITOR_PANE_BACKGROUND = registerColor('editorPane.background', {
@@ -195,7 +200,13 @@ export const EDITOR_DRAG_AND_DROP_BACKGROUND = registerColor('editorGroup.dropBa
hc: null
}, nls.localize('editorDragAndDropBackground', "Background color when dragging editors around. The color should have transparency so that the editor contents can still shine through."));
// < --- Resource Viewer --- >
export const IMAGE_PREVIEW_BORDER = registerColor('imagePreview.border', {
dark: Color.fromHex('#808080').transparent(0.35),
light: Color.fromHex('#808080').transparent(0.35),
hc: contrastBorder
}, nls.localize('imagePreviewBorder', "Border color for image in image preview."));
// < --- Panels --- >
@@ -432,6 +443,20 @@ export const SIDE_BAR_SECTION_HEADER_BORDER = registerColor('sideBarSectionHeade
}, nls.localize('sideBarSectionHeaderBorder', "Side bar section header border color. The side bar is the container for views like explorer and search."));
// < --- Quick Input -- >
export const QUICK_INPUT_BACKGROUND = registerColor('quickInput.background', {
dark: SIDE_BAR_BACKGROUND,
light: SIDE_BAR_BACKGROUND,
hc: SIDE_BAR_BACKGROUND
}, nls.localize('quickInputBackground', "Quick Input background color. The Quick Input widget is the container for views like the color theme picker"));
export const QUICK_INPUT_FOREGROUND = registerColor('quickInput.foreground', {
dark: SIDE_BAR_FOREGROUND,
light: SIDE_BAR_FOREGROUND,
hc: SIDE_BAR_FOREGROUND
}, nls.localize('quickInputForeground', "Quick Input foreground color. The Quick Input widget is the container for views like the color theme picker"));
// < --- Title Bar --- >
export const TITLE_BAR_ACTIVE_FOREGROUND = registerColor('titleBar.activeForeground', {
@@ -499,9 +524,9 @@ export const NOTIFICATIONS_TOAST_BORDER = registerColor('notificationToast.borde
}, nls.localize('notificationToastBorder', "Notification toast border color. Notifications slide in from the bottom right of the window."));
export const NOTIFICATIONS_FOREGROUND = registerColor('notifications.foreground', {
dark: null,
light: null,
hc: null
dark: editorWidgetForeground,
light: editorWidgetForeground,
hc: editorWidgetForeground
}, nls.localize('notificationsForeground', "Notifications foreground color. Notifications slide in from the bottom right of the window."));
export const NOTIFICATIONS_BACKGROUND = registerColor('notifications.background', {
@@ -570,4 +595,4 @@ export class Themable extends Disposable {
return color ? color.toString() : null;
}
}
}

View File

@@ -11,7 +11,7 @@ import { ITreeViewDataProvider } from 'vs/workbench/common/views';
import { localize } from 'vs/nls';
import { IViewlet } from 'vs/workbench/common/viewlet';
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { values, keys } from 'vs/base/common/map';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -71,12 +71,12 @@ export class ViewContainer {
protected constructor(readonly id: string, readonly hideIfEmpty: boolean, readonly extensionId?: ExtensionIdentifier) { }
}
class ViewContainersRegistryImpl implements IViewContainersRegistry {
class ViewContainersRegistryImpl extends Disposable implements IViewContainersRegistry {
private readonly _onDidRegister = new Emitter<ViewContainer>();
private readonly _onDidRegister = this._register(new Emitter<ViewContainer>());
readonly onDidRegister: Event<ViewContainer> = this._onDidRegister.event;
private readonly _onDidDeregister = new Emitter<ViewContainer>();
private readonly _onDidDeregister = this._register(new Emitter<ViewContainer>());
readonly onDidDeregister: Event<ViewContainer> = this._onDidDeregister.event;
private viewContainers: Map<string, ViewContainer> = new Map<string, ViewContainer>();
@@ -169,15 +169,15 @@ export interface IViewsRegistry {
getViewContainer(id: string): ViewContainer | null;
}
class ViewsRegistry implements IViewsRegistry {
class ViewsRegistry extends Disposable implements IViewsRegistry {
private readonly _onViewsRegistered: Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = new Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }>();
private readonly _onViewsRegistered: Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = this._register(new Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }>());
readonly onViewsRegistered: Event<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = this._onViewsRegistered.event;
private readonly _onViewsDeregistered: Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = new Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }>();
private readonly _onViewsDeregistered: Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = this._register(new Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }>());
readonly onViewsDeregistered: Event<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = this._onViewsDeregistered.event;
private readonly _onDidChangeContainer: Emitter<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }> = new Emitter<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }>();
private readonly _onDidChangeContainer: Emitter<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }> = this._register(new Emitter<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }>());
readonly onDidChangeContainer: Event<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }> = this._onDidChangeContainer.event;
private _viewContainers: ViewContainer[] = [];