Initial VS Code 1.19 source merge (#571)

* Initial 1.19 xcopy

* Fix yarn build

* Fix numerous build breaks

* Next batch of build break fixes

* More build break fixes

* Runtime breaks

* Additional post merge fixes

* Fix windows setup file

* Fix test failures.

* Update license header blocks to refer to source eula
This commit is contained in:
Karl Burtram
2018-01-28 23:37:17 -08:00
committed by GitHub
parent 9a1ac20710
commit 251ae01c3e
8009 changed files with 93378 additions and 35634 deletions

View File

@@ -6,24 +6,19 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { Registry } from 'vs/platform/registry/common/platform';
import { IAction } from 'vs/base/common/actions';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands';
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { IMessageService } from 'vs/platform/message/common/message';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import Severity from 'vs/base/common/severity';
import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
export const Extensions = {
WorkbenchActions: 'workbench.contributions.actions'
};
export interface IActionProvider {
getActions(): IAction[];
}
export interface IWorkbenchActionRegistry {
/**
@@ -62,13 +57,20 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR
// menu item
// TODO@Rob slightly weird if-check required because of
// https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/parts/search/browser/search.contribution.ts#L266
// https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/parts/search/electron-browser/search.contribution.ts#L266
if (descriptor.label) {
let idx = alias.indexOf(': ');
let categoryOriginal;
if (idx > 0) {
categoryOriginal = alias.substr(0, idx);
alias = alias.substr(idx + 2);
}
const command = {
id: descriptor.id,
title: { value: descriptor.label, original: alias },
category
category: category && { value: category, original: categoryOriginal }
};
MenuRegistry.addCommand(command);
@@ -86,15 +88,15 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR
return (accessor, args) => {
const messageService = accessor.get(IMessageService);
const instantiationService = accessor.get(IInstantiationService);
const partService = accessor.get(IPartService);
const lifecycleService = accessor.get(ILifecycleService);
TPromise.as(this._triggerAndDisposeAction(instantiationService, partService, descriptor, args)).done(null, (err) => {
TPromise.as(this._triggerAndDisposeAction(instantiationService, lifecycleService, descriptor, args)).then(null, (err) => {
messageService.show(Severity.Error, err);
});
};
}
private _triggerAndDisposeAction(instantitationService: IInstantiationService, partService: IPartService, descriptor: SyncActionDescriptor, args: any): TPromise<any> {
private _triggerAndDisposeAction(instantitationService: IInstantiationService, lifecycleService: ILifecycleService, descriptor: SyncActionDescriptor, args: any): Thenable<void> {
const actionInstance = instantitationService.createInstance(descriptor.syncDescriptor);
actionInstance.label = descriptor.label || actionInstance.label;
@@ -108,7 +110,7 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR
const from = args && args.from || 'keybinding';
// run action when workbench is created
return partService.joinCreation().then(() => {
return lifecycleService.when(LifecyclePhase.Running).then(() => {
try {
return TPromise.as(actionInstance.run(undefined, { from })).then(() => {
actionInstance.dispose();

View File

@@ -4,8 +4,9 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Registry, BaseRegistry } from 'vs/platform/registry/common/platform';
import { Registry } from 'vs/platform/registry/common/platform';
import { IInstantiationService, IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
// --- Workbench Contribution Registry
@@ -13,11 +14,7 @@ import { IInstantiationService, IConstructorSignature0 } from 'vs/platform/insta
* A workbench contribution that will be loaded when the workbench starts and disposed when the workbench shuts down.
*/
export interface IWorkbenchContribution {
/**
* The unique identifier of this workbench contribution.
*/
getId(): string;
// Marker Interface
}
export namespace Extensions {
@@ -31,29 +28,73 @@ export interface IWorkbenchContributionsRegistry {
/**
* Registers a workbench contribution to the platform that will be loaded when the workbench starts and disposed when
* the workbench shuts down.
*
* @param phase the lifecycle phase when to instantiate the contribution.
*/
registerWorkbenchContribution(contribution: IWorkbenchContributionSignature): void;
registerWorkbenchContribution(contribution: IWorkbenchContributionSignature, phase: LifecyclePhase): void;
/**
* Returns all workbench contributions that are known to the platform.
* Starts the registry by providing the required services.
*/
getWorkbenchContributions(): IWorkbenchContribution[];
setInstantiationService(service: IInstantiationService): void;
start(instantiationService: IInstantiationService, lifecycleService: ILifecycleService): void;
}
class WorkbenchContributionsRegistry extends BaseRegistry<IWorkbenchContribution> implements IWorkbenchContributionsRegistry {
export class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry {
private instantiationService: IInstantiationService;
private lifecycleService: ILifecycleService;
public registerWorkbenchContribution(ctor: IWorkbenchContributionSignature): void {
super._register(ctor);
private toBeInstantiated: Map<LifecyclePhase, IConstructorSignature0<IWorkbenchContribution>[]> = new Map<LifecyclePhase, IConstructorSignature0<IWorkbenchContribution>[]>();
public registerWorkbenchContribution(ctor: IWorkbenchContributionSignature, phase: LifecyclePhase = LifecyclePhase.Starting): void {
// Instantiate directly if we are already matching the provided phase
if (this.instantiationService && this.lifecycleService && this.lifecycleService.phase >= phase) {
this.instantiationService.createInstance(ctor);
}
// Otherwise keep contributions by lifecycle phase
else {
let toBeInstantiated = this.toBeInstantiated.get(phase);
if (!toBeInstantiated) {
toBeInstantiated = [];
this.toBeInstantiated.set(phase, toBeInstantiated);
}
toBeInstantiated.push(ctor);
}
}
public getWorkbenchContributions(): IWorkbenchContribution[] {
return super._getInstances();
public start(instantiationService: IInstantiationService, lifecycleService: ILifecycleService): void {
this.instantiationService = instantiationService;
this.lifecycleService = lifecycleService;
[LifecyclePhase.Starting, LifecyclePhase.Restoring, LifecyclePhase.Running, LifecyclePhase.Eventually].forEach(phase => {
this.instantiateByPhase(instantiationService, lifecycleService, phase);
});
}
public setWorkbenchContributions(contributions: IWorkbenchContribution[]): void {
super._setInstances(contributions);
private instantiateByPhase(instantiationService: IInstantiationService, lifecycleService: ILifecycleService, phase: LifecyclePhase): void {
// Instantiate contributions directly when phase is already reached
if (lifecycleService.phase >= phase) {
this.doInstantiateByPhase(instantiationService, phase);
}
// Otherwise wait for phase to be reached
else {
lifecycleService.when(phase).then(() => {
this.doInstantiateByPhase(instantiationService, phase);
});
}
}
private doInstantiateByPhase(instantiationService: IInstantiationService, phase: LifecyclePhase): void {
const toBeInstantiated = this.toBeInstantiated.get(phase);
if (toBeInstantiated) {
while (toBeInstantiated.length > 0) {
instantiationService.createInstance(toBeInstantiated.shift());
}
}
}
}

View File

@@ -276,7 +276,7 @@ export interface IEditorOpeningEvent {
prevent(callback: () => TPromise<IBaseEditor>): void;
}
export class EditorOpeningEvent {
export class EditorOpeningEvent implements IEditorOpeningEvent {
private override: () => TPromise<IBaseEditor>;
constructor(private _input: IEditorInput, private _options: IEditorOptions, private _position: Position) {
@@ -755,6 +755,7 @@ export interface IEditorStacksModel {
next(jumpGroups: boolean, cycleAtEnd?: boolean): IEditorIdentifier;
previous(jumpGroups: boolean, cycleAtStart?: boolean): IEditorIdentifier;
last(): IEditorIdentifier;
isOpen(resource: URI): boolean;
@@ -792,7 +793,7 @@ export interface IEditorContext extends IEditorIdentifier {
}
export interface IEditorCloseEvent extends IEditorIdentifier {
pinned: boolean;
replaced: boolean;
index: number;
}
@@ -808,23 +809,11 @@ export const EditorOpenPositioning = {
export const OPEN_POSITIONING_CONFIG = 'workbench.editor.openPositioning';
export interface IWorkbenchEditorConfiguration {
/* __GDPR__FRAGMENT__
"IWorkbenchEditorConfiguration" : {
"showTabs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"tabCloseButton": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"showIcons": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"enablePreview": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"enablePreviewFromQuickOpen": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"closeOnFileDelete": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"openPositioning": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"revealIfOpen": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"swipeToNavigate": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
workbench: {
editor: {
showTabs: boolean;
tabCloseButton: 'left' | 'right' | 'off';
tabSizing: 'fit' | 'shrink';
showIcons: boolean;
enablePreview: boolean;
enablePreviewFromQuickOpen: boolean;
@@ -833,7 +822,8 @@ export interface IWorkbenchEditorConfiguration {
revealIfOpen: boolean;
swipeToNavigate: boolean,
labelFormat: 'default' | 'short' | 'medium' | 'long';
}
},
iconTheme: string;
};
}

View File

@@ -8,6 +8,8 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { EditorModel } from 'vs/workbench/common/editor';
import URI from 'vs/base/common/uri';
import { IFileService } from 'vs/platform/files/common/files';
import { Schemas } from 'vs/base/common/network';
import { DataUri } from 'vs/workbench/common/resources';
/**
* An editor model that just represents a resource that can be loaded.
@@ -17,6 +19,7 @@ export class BinaryEditorModel extends EditorModel {
private resource: URI;
private size: number;
private etag: string;
private mime: string;
constructor(
resource: URI,
@@ -25,8 +28,17 @@ export class BinaryEditorModel extends EditorModel {
) {
super();
this.name = name;
this.resource = resource;
this.name = name;
if (resource.scheme === Schemas.data) {
const metadata = DataUri.parseMetaData(resource);
if (metadata.has(DataUri.META_DATA_SIZE)) {
this.size = Number(metadata.get(DataUri.META_DATA_SIZE));
}
this.mime = metadata.get(DataUri.META_DATA_MIME);
}
}
/**
@@ -44,25 +56,38 @@ export class BinaryEditorModel extends EditorModel {
}
/**
* The size of the binary file if known.
* The size of the binary resource if known.
*/
public getSize(): number {
return this.size;
}
/**
* The etag of the binary file if known.
* The mime of the binary resource if known.
*/
public getMime(): string {
return this.mime;
}
/**
* The etag of the binary resource if known.
*/
public getETag(): string {
return this.etag;
}
public load(): TPromise<EditorModel> {
return this.fileService.resolveFile(this.resource).then(stat => {
this.etag = stat.etag;
this.size = stat.size;
return this;
});
// 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;
return this;
});
}
return TPromise.wrap(this);
}
}

View File

@@ -0,0 +1,86 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { EditorInput } from 'vs/workbench/common/editor';
import URI from 'vs/base/common/uri';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel';
import { DataUri } from 'vs/workbench/common/resources';
/**
* An editor input to present data URIs in a binary editor. Data URIs have the form of:
* data:[mime type];[meta data <key=value>;...];base64,[base64 encoded value]
*/
export class DataUriEditorInput extends EditorInput {
static ID: string = 'workbench.editors.dataUriEditorInput';
private resource: URI;
private name: string;
private description: string;
constructor(
name: string,
description: string,
resource: URI,
@IInstantiationService private instantiationService: IInstantiationService
) {
super();
this.name = name;
this.description = description;
this.resource = resource;
if (!this.name || !this.description) {
const metadata = DataUri.parseMetaData(this.resource);
if (!this.name) {
this.name = metadata.get(DataUri.META_DATA_LABEL);
}
if (!this.description) {
this.description = metadata.get(DataUri.META_DATA_DESCRIPTION);
}
}
}
public getResource(): URI {
return this.resource;
}
public getTypeId(): string {
return DataUriEditorInput.ID;
}
public getName(): string {
return this.name;
}
public getDescription(): string {
return this.description;
}
public resolve(refresh?: boolean): TPromise<BinaryEditorModel> {
return this.instantiationService.createInstance(BinaryEditorModel, this.resource, this.getName()).load().then(m => m as BinaryEditorModel);
}
public matches(otherInput: any): boolean {
if (super.matches(otherInput) === true) {
return true;
}
if (otherInput instanceof DataUriEditorInput) {
const otherDataUriEditorInput = <DataUriEditorInput>otherInput;
// Compare by resource
return otherDataUriEditorInput.resource.toString() === this.resource.toString();
}
return false;
}
}

View File

@@ -16,7 +16,7 @@ import { TextDiffEditorModel } from 'vs/workbench/common/editor/textDiffEditorMo
*/
export class DiffEditorInput extends SideBySideEditorInput {
public static ID = 'workbench.editors.diffEditorInput';
public static readonly ID = 'workbench.editors.diffEditorInput';
private cachedModel: DiffEditorModel;

View File

@@ -346,8 +346,8 @@ export class EditorGroup implements IEditorGroup {
}));
}
public replaceEditor(toReplace: EditorInput, replaceWidth: EditorInput, replaceIndex: number, openNext = true): void {
const event = this.doCloseEditor(toReplace, openNext); // optimization to prevent multiple setActive() in one call
private replaceEditor(toReplace: EditorInput, replaceWidth: 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.
@@ -360,14 +360,14 @@ export class EditorGroup implements IEditorGroup {
}
public closeEditor(editor: EditorInput, openNext = true): void {
const event = this.doCloseEditor(editor, openNext);
const event = this.doCloseEditor(editor, openNext, false);
if (event) {
this.fireEvent(this._onEditorClosed, event, true);
}
}
private doCloseEditor(editor: EditorInput, openNext = true): EditorCloseEvent {
private doCloseEditor(editor: EditorInput, openNext: boolean, replaced: boolean): EditorCloseEvent {
const index = this.indexOf(editor);
if (index === -1) {
return null; // not found
@@ -388,17 +388,15 @@ export class EditorGroup implements IEditorGroup {
}
// Preview Editor closed
let pinned = true;
if (this.matches(this.preview, editor)) {
this.preview = null;
pinned = false;
}
// Remove from arrays
this.splice(index, true);
// Event
return { editor, pinned, index, group: this };
return { editor, replaced, index, group: this };
}
public closeEditors(except: EditorInput, direction?: Direction): void {
@@ -721,7 +719,7 @@ interface ISerializedEditorStacksModel {
export class EditorStacksModel implements IEditorStacksModel {
private static STORAGE_KEY = 'editorStacks.model';
private static readonly STORAGE_KEY = 'editorStacks.model';
private toDispose: IDisposable[];
private loaded: boolean;
@@ -1098,6 +1096,16 @@ export class EditorStacksModel implements IEditorStacksModel {
return { group: lastGroup, editor: lastGroup.getEditor(lastGroup.count - 1) };
}
public last(): IEditorIdentifier {
this.ensureLoaded();
if (!this.activeGroup) {
return null;
}
return { group: this.activeGroup, editor: this.activeGroup.getEditor(this.activeGroup.count - 1) };
}
private save(): void {
const serialized = this.serialize();

View File

@@ -1,116 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IDisposable } from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri';
import Event, { Emitter } from 'vs/base/common/event';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IRange } from 'vs/editor/common/core/range';
import { CursorChangeReason, ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations';
export interface IRangeHighlightDecoration {
resource: URI;
range: IRange;
isWholeLine?: boolean;
}
export class RangeHighlightDecorations implements IDisposable {
private rangeHighlightDecorationId: string = null;
private editor: editorCommon.ICommonCodeEditor = null;
private editorDisposables: IDisposable[] = [];
private _onHighlightRemoved: Emitter<void> = new Emitter<void>();
public readonly onHighlghtRemoved: Event<void> = this._onHighlightRemoved.event;
constructor( @IWorkbenchEditorService private editorService: IWorkbenchEditorService) {
}
public removeHighlightRange() {
if (this.editor && this.editor.getModel() && this.rangeHighlightDecorationId) {
this.editor.deltaDecorations([this.rangeHighlightDecorationId], []);
this._onHighlightRemoved.fire();
}
this.rangeHighlightDecorationId = null;
}
public highlightRange(range: IRangeHighlightDecoration, editor?: editorCommon.ICommonCodeEditor) {
editor = editor ? editor : this.getEditor(range);
if (editor) {
this.doHighlightRange(editor, range);
}
}
private doHighlightRange(editor: editorCommon.ICommonCodeEditor, selectionRange: IRangeHighlightDecoration) {
this.removeHighlightRange();
editor.changeDecorations((changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => {
this.rangeHighlightDecorationId = changeAccessor.addDecoration(selectionRange.range, this.createRangeHighlightDecoration(selectionRange.isWholeLine));
});
this.setEditor(editor);
}
private getEditor(resourceRange: IRangeHighlightDecoration): editorCommon.ICommonCodeEditor {
const activeInput = this.editorService.getActiveEditorInput();
const resource = activeInput && activeInput.getResource();
if (resource) {
if (resource.toString() === resourceRange.resource.toString()) {
return <editorCommon.ICommonCodeEditor>this.editorService.getActiveEditor().getControl();
}
}
return null;
}
private setEditor(editor: editorCommon.ICommonCodeEditor) {
if (this.editor !== editor) {
this.disposeEditorListeners();
this.editor = editor;
this.editorDisposables.push(this.editor.onDidChangeCursorPosition((e: ICursorPositionChangedEvent) => {
if (
e.reason === CursorChangeReason.NotSet
|| e.reason === CursorChangeReason.Explicit
|| e.reason === CursorChangeReason.Undo
|| e.reason === CursorChangeReason.Redo
) {
this.removeHighlightRange();
}
}));
this.editorDisposables.push(this.editor.onDidChangeModel(() => { this.removeHighlightRange(); }));
this.editorDisposables.push(this.editor.onDidDispose(() => {
this.removeHighlightRange();
this.editor = null;
}));
}
}
private disposeEditorListeners() {
this.editorDisposables.forEach(disposable => disposable.dispose());
this.editorDisposables = [];
}
private static _WHOLE_LINE_RANGE_HIGHLIGHT = ModelDecorationOptions.register({
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
className: 'rangeHighlight',
isWholeLine: true
});
private static _RANGE_HIGHLIGHT = ModelDecorationOptions.register({
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
className: 'rangeHighlight'
});
private createRangeHighlightDecoration(isWholeLine: boolean = true): ModelDecorationOptions {
return (isWholeLine ? RangeHighlightDecorations._WHOLE_LINE_RANGE_HIGHLIGHT : RangeHighlightDecorations._RANGE_HIGHLIGHT);
}
public dispose() {
if (this.editor && this.editor.getModel()) {
this.removeHighlightRange();
this.disposeEditorListeners();
this.editor = null;
}
}
}

View File

@@ -70,11 +70,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
protected createTextEditorModel(value: string | IRawTextSource, resource?: URI, modeId?: string): TPromise<EditorModel> {
const firstLineText = this.getFirstLineText(value);
const mode = this.getOrCreateMode(this.modeService, modeId, firstLineText);
// To avoid flickering, give the mode at most 50ms to load. If the mode doesn't load in 50ms, proceed creating the model with a mode promise
return TPromise.any<any>([TPromise.timeout(50), mode]).then(() => {
return this.doCreateTextEditorModel(value, mode, resource);
});
return TPromise.as(this.doCreateTextEditorModel(value, mode, resource));
}
private doCreateTextEditorModel(value: string | IRawTextSource, mode: TPromise<IMode>, resource: URI): EditorModel {
@@ -166,4 +162,4 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
super.dispose();
}
}
}

View File

@@ -269,11 +269,8 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
return true;
}
// {{SQL CARBON EDIT}}
let isUntitledInput: boolean = otherInput instanceof UntitledEditorInput;
let isQueryInput: boolean = otherInput && otherInput.sql && otherInput.sql instanceof UntitledEditorInput;
if (isUntitledInput || isQueryInput) {
const otherUntitledEditorInput = isUntitledInput ? <UntitledEditorInput>otherInput : <UntitledEditorInput>otherInput.sql;
if (otherInput instanceof UntitledEditorInput) {
const otherUntitledEditorInput = <UntitledEditorInput>otherInput;
// Otherwise compare by properties
return otherUntitledEditorInput.resource.toString() === this.resource.toString();

View File

@@ -11,7 +11,7 @@ import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'
import URI from 'vs/base/common/uri';
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
import { EndOfLinePreference } from 'vs/editor/common/editorCommon';
import { IFilesConfiguration, CONTENT_CHANGE_EVENT_BUFFER_DELAY } from 'vs/platform/files/common/files';
import { CONTENT_CHANGE_EVENT_BUFFER_DELAY } from 'vs/platform/files/common/files';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IMode } from 'vs/editor/common/modes';
@@ -98,8 +98,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
}
private onConfigurationChange(): void {
const configuration = this.configurationService.getConfiguration<IFilesConfiguration>(this.resource);
const configuredEncoding = configuration && configuration.files && configuration.files.encoding;
const configuredEncoding = this.configurationService.getValue<string>(this.resource, 'files.encoding');
if (this.configuredEncoding !== configuredEncoding) {
this.configuredEncoding = configuredEncoding;
@@ -185,10 +184,8 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
this.setDirty(this.hasAssociatedFilePath || !!backupContent);
return this.doLoad(backupContent || this.initialValue || '').then(model => {
const configuration = this.configurationService.getConfiguration<IFilesConfiguration>(this.resource);
// Encoding
this.configuredEncoding = configuration && configuration.files && configuration.files.encoding;
this.configuredEncoding = this.configurationService.getValue<string>(this.resource, 'files.encoding');
// Listen to content changes
this.toDispose.push(this.textEditorModel.onDidChangeContent(() => this.onModelContentChanged()));

View File

@@ -32,7 +32,7 @@ export class Memento {
private static globalMementos: { [id: string]: ScopedMemento } = {};
private static workspaceMementos: { [id: string]: ScopedMemento } = {};
private static COMMON_PREFIX = 'memento/';
private static readonly COMMON_PREFIX = 'memento/';
private id: string;

View File

@@ -6,13 +6,7 @@
'use strict';
import URI from 'vs/base/common/uri';
import objects = require('vs/base/common/objects');
import paths = require('vs/base/common/paths');
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import Event, { Emitter } from 'vs/base/common/event';
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { ParsedExpression, IExpression, parse } from 'vs/base/common/glob';
import { basename } from 'vs/base/common/paths';
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IModeService } from 'vs/editor/common/services/modeService';
@@ -63,114 +57,36 @@ export class ResourceContextKey implements IContextKey<URI> {
}
}
export class ResourceGlobMatcher {
/**
* Data URI related helpers.
*/
export namespace DataUri {
private static readonly NO_ROOT: string = null;
export const META_DATA_LABEL = 'label';
export const META_DATA_DESCRIPTION = 'description';
export const META_DATA_SIZE = 'size';
export const META_DATA_MIME = 'mime';
private _onExpressionChange: Emitter<void>;
private toUnbind: IDisposable[];
private mapRootToParsedExpression: Map<string, ParsedExpression>;
private mapRootToExpressionConfig: Map<string, IExpression>;
export function parseMetaData(dataUri: URI): Map<string, string> {
const metadata = new Map<string, string>();
constructor(
private globFn: (root?: URI) => IExpression,
private shouldUpdate: (event: IConfigurationChangeEvent) => boolean,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IConfigurationService private configurationService: IConfigurationService
) {
this.toUnbind = [];
this.mapRootToParsedExpression = new Map<string, ParsedExpression>();
this.mapRootToExpressionConfig = new Map<string, IExpression>();
this._onExpressionChange = new Emitter<void>();
this.toUnbind.push(this._onExpressionChange);
this.updateExcludes(false);
this.registerListeners();
}
public get onExpressionChange(): Event<void> {
return this._onExpressionChange.event;
}
private registerListeners(): void {
this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => {
if (this.shouldUpdate(e)) {
this.updateExcludes(true);
}
}));
this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateExcludes(true)));
}
private updateExcludes(fromEvent: boolean): void {
let changed = false;
// Add excludes per workspaces that got added
this.contextService.getWorkspace().folders.forEach(folder => {
const rootExcludes = this.globFn(folder.uri);
if (!this.mapRootToExpressionConfig.has(folder.uri.toString()) || !objects.equals(this.mapRootToExpressionConfig.get(folder.uri.toString()), rootExcludes)) {
changed = true;
this.mapRootToParsedExpression.set(folder.uri.toString(), parse(rootExcludes));
this.mapRootToExpressionConfig.set(folder.uri.toString(), objects.clone(rootExcludes));
// Given a URI of: data:image/png;size:2313;label:SomeLabel;description:SomeDescription;base64,77+9UE5...
// the metadata is: size:2313;label:SomeLabel;description:SomeDescription
const meta = dataUri.path.substring(dataUri.path.indexOf(';') + 1, dataUri.path.lastIndexOf(';'));
meta.split(';').forEach(property => {
const [key, value] = property.split(':');
if (key && value) {
metadata.set(key, value);
}
});
// Remove excludes per workspace no longer present
this.mapRootToExpressionConfig.forEach((value, root) => {
if (root === ResourceGlobMatcher.NO_ROOT) {
return; // always keep this one
}
if (!this.contextService.getWorkspaceFolder(URI.parse(root))) {
this.mapRootToParsedExpression.delete(root);
this.mapRootToExpressionConfig.delete(root);
changed = true;
}
});
// Always set for resources outside root as well
const globalExcludes = this.globFn();
if (!this.mapRootToExpressionConfig.has(ResourceGlobMatcher.NO_ROOT) || !objects.equals(this.mapRootToExpressionConfig.get(ResourceGlobMatcher.NO_ROOT), globalExcludes)) {
changed = true;
this.mapRootToParsedExpression.set(ResourceGlobMatcher.NO_ROOT, parse(globalExcludes));
this.mapRootToExpressionConfig.set(ResourceGlobMatcher.NO_ROOT, objects.clone(globalExcludes));
// Given a URI of: data:image/png;size:2313;label:SomeLabel;description:SomeDescription;base64,77+9UE5...
// the mime is: image/png
const mime = dataUri.path.substring(0, dataUri.path.indexOf(';'));
if (mime) {
metadata.set(META_DATA_MIME, mime);
}
if (fromEvent && changed) {
this._onExpressionChange.fire();
}
}
public matches(resource: URI): boolean {
const folder = this.contextService.getWorkspaceFolder(resource);
let expressionForRoot: ParsedExpression;
if (folder && this.mapRootToParsedExpression.has(folder.uri.toString())) {
expressionForRoot = this.mapRootToParsedExpression.get(folder.uri.toString());
} else {
expressionForRoot = this.mapRootToParsedExpression.get(ResourceGlobMatcher.NO_ROOT);
}
// If the resource if from a workspace, convert its absolute path to a relative
// path so that glob patterns have a higher probability to match. For example
// a glob pattern of "src/**" will not match on an absolute path "/folder/src/file.txt"
// but can match on "src/file.txt"
let resourcePathToMatch: string;
if (folder) {
resourcePathToMatch = paths.normalize(paths.relative(folder.uri.fsPath, resource.fsPath));
} else {
resourcePathToMatch = resource.fsPath;
}
return !!expressionForRoot(resourcePathToMatch);
}
public dispose(): void {
this.toUnbind = dispose(this.toUnbind);
return metadata;
}
}

View File

@@ -9,7 +9,7 @@ import { Command } from 'vs/editor/common/modes';
export type TreeViewItemHandleArg = {
$treeViewId: string,
$treeItemHandle: number
$treeItemHandle: string
};
export enum TreeItemCollapsibleState {
@@ -20,7 +20,9 @@ export enum TreeItemCollapsibleState {
export interface ITreeItem {
handle: number;
handle: string;
parentHandle: string;
label: string;