Merge from master

This commit is contained in:
Raj Musuku
2019-02-21 17:56:04 -08:00
parent 5a146e34fa
commit 666ae11639
11482 changed files with 119352 additions and 255574 deletions

View File

@@ -2,39 +2,42 @@
* 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 * as nls from 'vs/nls';
import * as network from 'vs/base/common/network';
import { Event, Emitter } from 'vs/base/common/event';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { Emitter, Event } from 'vs/base/common/event';
import { MarkdownString } from 'vs/base/common/htmlContent';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { IMarker, IMarkerService, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers';
import { Range } from 'vs/editor/common/core/range';
import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel';
import { IMode, LanguageIdentifier } from 'vs/editor/common/modes';
import { IModelService } from 'vs/editor/common/services/modelService';
import * as platform from 'vs/base/common/platform';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/config/editorOptions';
import { PLAINTEXT_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/modesRegistry';
import { IModelLanguageChangedEvent } from 'vs/editor/common/model/textModelEvents';
import { ClassName } from 'vs/editor/common/model/intervalTree';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { themeColorFromId, ThemeColor } from 'vs/platform/theme/common/themeService';
import { overviewRulerWarning, overviewRulerError, overviewRulerInfo } from 'vs/editor/common/view/editorColorRegistry';
import { ITextModel, IModelDeltaDecoration, IModelDecorationOptions, TrackedRangeStickiness, OverviewRulerLane, DefaultEndOfLine, ITextModelCreationOptions, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextBufferFactory, ITextBuffer, EndOfLinePreference } from 'vs/editor/common/model';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { escape } from 'vs/base/common/strings';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import * as network from 'vs/base/common/network';
import { basename } from 'vs/base/common/paths';
import * as platform from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/config/editorOptions';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Range } from 'vs/editor/common/core/range';
import { DefaultEndOfLine, EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, IModelDecorationOptions, IModelDeltaDecoration, ITextBuffer, ITextBufferFactory, ITextModel, ITextModelCreationOptions, OverviewRulerLane, TrackedRangeStickiness } from 'vs/editor/common/model';
import { ClassName } from 'vs/editor/common/model/intervalTree';
import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel';
import { IModelLanguageChangedEvent } from 'vs/editor/common/model/textModelEvents';
import { LanguageIdentifier } from 'vs/editor/common/modes';
import { PLAINTEXT_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/modesRegistry';
import { ILanguageSelection } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
import { overviewRulerError, overviewRulerInfo, overviewRulerWarning } from 'vs/editor/common/view/editorColorRegistry';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IMarker, IMarkerService, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers';
import { ThemeColor, themeColorFromId } from 'vs/platform/theme/common/themeService';
function MODEL_ID(resource: URI): string {
return resource.toString();
}
class ModelData implements IDisposable {
model: ITextModel;
public readonly model: ITextModel;
private _languageSelection: ILanguageSelection | null;
private _languageSelectionListener: IDisposable | null;
private _markerDecorations: string[];
private _modelEventListeners: IDisposable[];
@@ -46,6 +49,9 @@ class ModelData implements IDisposable {
) {
this.model = model;
this._languageSelection = null;
this._languageSelectionListener = null;
this._markerDecorations = [];
this._modelEventListeners = [];
@@ -53,15 +59,33 @@ class ModelData implements IDisposable {
this._modelEventListeners.push(model.onDidChangeLanguage((e) => onDidChangeLanguage(model, e)));
}
private _disposeLanguageSelection(): void {
if (this._languageSelectionListener) {
this._languageSelectionListener.dispose();
this._languageSelectionListener = null;
}
if (this._languageSelection) {
this._languageSelection.dispose();
this._languageSelection = null;
}
}
public dispose(): void {
this._markerDecorations = this.model.deltaDecorations(this._markerDecorations, []);
this._modelEventListeners = dispose(this._modelEventListeners);
this.model = null;
this._disposeLanguageSelection();
}
public acceptMarkerDecorations(newDecorations: IModelDeltaDecoration[]): void {
this._markerDecorations = this.model.deltaDecorations(this._markerDecorations, newDecorations);
}
public setLanguage(languageSelection: ILanguageSelection): void {
this._disposeLanguageSelection();
this._languageSelection = languageSelection;
this._languageSelectionListener = this._languageSelection.onDidChange(() => this.model.setMode(languageSelection.languageIdentifier));
this.model.setMode(languageSelection.languageIdentifier);
}
}
class ModelMarkerHandler {
@@ -73,8 +97,8 @@ class ModelMarkerHandler {
let newModelDecorations: IModelDeltaDecoration[] = markers.map((marker) => {
return {
range: this._createDecorationRange(modelData.model, marker),
options: this._createDecorationOption(marker)
range: ModelMarkerHandler._createDecorationRange(modelData.model, marker),
options: ModelMarkerHandler._createDecorationOption(marker)
};
});
@@ -85,9 +109,12 @@ class ModelMarkerHandler {
let ret = Range.lift(rawMarker);
if (rawMarker.severity === MarkerSeverity.Hint && Range.spansMultipleLines(ret)) {
// never render hints on multiple lines
ret = ret.setEndPosition(ret.startLineNumber, ret.startColumn);
if (rawMarker.severity === MarkerSeverity.Hint) {
if (!rawMarker.tags || rawMarker.tags.indexOf(MarkerTag.Unnecessary) === -1) {
// * never render hints on multiple lines
// * make enough space for three dots
ret = ret.setEndPosition(ret.startLineNumber, ret.startColumn + 2);
}
}
ret = model.validateRange(ret);
@@ -124,10 +151,9 @@ class ModelMarkerHandler {
private static _createDecorationOption(marker: IMarker): IModelDecorationOptions {
let className: string;
let color: ThemeColor;
let darkColor: ThemeColor;
let color: ThemeColor | undefined = undefined;
let zIndex: number;
let inlineClassName: string;
let inlineClassName: string | undefined = undefined;
switch (marker.severity) {
case MarkerSeverity.Hint:
@@ -141,20 +167,17 @@ class ModelMarkerHandler {
case MarkerSeverity.Warning:
className = ClassName.EditorWarningDecoration;
color = themeColorFromId(overviewRulerWarning);
darkColor = themeColorFromId(overviewRulerWarning);
zIndex = 20;
break;
case MarkerSeverity.Info:
className = ClassName.EditorInfoDecoration;
color = themeColorFromId(overviewRulerInfo);
darkColor = themeColorFromId(overviewRulerInfo);
zIndex = 10;
break;
case MarkerSeverity.Error:
default:
className = ClassName.EditorErrorDecoration;
color = themeColorFromId(overviewRulerError);
darkColor = themeColorFromId(overviewRulerError);
zIndex = 30;
break;
}
@@ -165,32 +188,37 @@ class ModelMarkerHandler {
}
}
let hoverMessage: MarkdownString = null;
let { message, source, relatedInformation } = marker;
let hoverMessage: MarkdownString | null = null;
let { message, source, relatedInformation, code } = marker;
if (typeof message === 'string') {
message = message.trim();
hoverMessage = new MarkdownString();
// Disable markdown renderer sanitize to allow html
// Hence, escape all input strings
hoverMessage.sanitize = false;
hoverMessage.appendMarkdown(`<div>`);
hoverMessage.appendMarkdown(`<span style='font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback"; white-space: pre-wrap;'>${escape(message.trim())}</span>`);
if (source) {
if (/\n/g.test(message)) {
message = nls.localize('diagAndSourceMultiline', "[{0}]\n{1}", source, message);
} else {
message = nls.localize('diagAndSource', "[{0}] {1}", source, message);
hoverMessage.appendMarkdown(`<span style='opacity: 0.6; padding-left:6px;'>${escape(source)}</span>`);
if (code) {
hoverMessage.appendMarkdown(`<span style='opacity: 0.6; padding-left:2px;'>(${escape(code)})</span>`);
}
} else if (code) {
hoverMessage.appendMarkdown(`<span style='opacity: 0.6; padding-left:6px;'>(${escape(code)})</span>`);
}
hoverMessage.appendMarkdown(`</div>`);
hoverMessage = new MarkdownString().appendCodeblock('_', message);
if (!isFalsyOrEmpty(relatedInformation)) {
hoverMessage.appendMarkdown('\n');
if (isNonEmptyArray(relatedInformation)) {
hoverMessage.appendMarkdown(`<ul>`);
for (const { message, resource, startLineNumber, startColumn } of relatedInformation) {
hoverMessage.appendMarkdown(
`* [${basename(resource.path)}(${startLineNumber}, ${startColumn})](${resource.toString(false)}#${startLineNumber},${startColumn}): `
);
hoverMessage.appendText(`${message}`);
hoverMessage.appendMarkdown('\n');
hoverMessage.appendMarkdown(`<li>`);
hoverMessage.appendMarkdown(`<a href='#' data-href='${resource.toString(false)}#${startLineNumber},${startColumn}'>${escape(basename(resource.path))}(${startLineNumber}, ${startColumn})</a>`);
hoverMessage.appendMarkdown(`<span>: ${escape(message)}</span>`);
hoverMessage.appendMarkdown(`</li>`);
}
hoverMessage.appendMarkdown('\n');
hoverMessage.appendMarkdown(`</ul>`);
}
}
@@ -201,7 +229,6 @@ class ModelMarkerHandler {
showIfCollapsed: true,
overviewRuler: {
color,
darkColor,
position: OverviewRulerLane.Right
},
zIndex,
@@ -210,33 +237,39 @@ class ModelMarkerHandler {
}
}
interface IRawEditorConfig {
tabSize?: any;
insertSpaces?: any;
detectIndentation?: any;
trimAutoWhitespace?: any;
creationOptions?: any;
largeFileOptimizations?: any;
}
interface IRawConfig {
files?: {
eol?: any;
};
editor?: {
tabSize?: any;
insertSpaces?: any;
detectIndentation?: any;
trimAutoWhitespace?: any;
creationOptions?: any;
largeFileOptimizations?: any;
};
eol?: any;
editor?: IRawEditorConfig;
}
const DEFAULT_EOL = (platform.isLinux || platform.isMacintosh) ? DefaultEndOfLine.LF : DefaultEndOfLine.CRLF;
export class ModelServiceImpl implements IModelService {
export class ModelServiceImpl extends Disposable implements IModelService {
public _serviceBrand: any;
private _markerService: IMarkerService;
private _markerServiceSubscription: IDisposable;
private _configurationService: IConfigurationService;
private _configurationServiceSubscription: IDisposable;
private _resourcePropertiesService: ITextResourcePropertiesService;
private readonly _onModelAdded: Emitter<ITextModel>;
private readonly _onModelRemoved: Emitter<ITextModel>;
private readonly _onModelModeChanged: Emitter<{ model: ITextModel; oldModeId: string; }>;
private readonly _onModelAdded: Emitter<ITextModel> = this._register(new Emitter<ITextModel>());
public readonly onModelAdded: Event<ITextModel> = this._onModelAdded.event;
private readonly _onModelRemoved: Emitter<ITextModel> = this._register(new Emitter<ITextModel>());
public readonly onModelRemoved: Event<ITextModel> = this._onModelRemoved.event;
private readonly _onModelModeChanged: Emitter<{ model: ITextModel; oldModeId: string; }> = this._register(new Emitter<{ model: ITextModel; oldModeId: string; }>({ leakWarningThreshold: 500 }));
public readonly onModelModeChanged: Event<{ model: ITextModel; oldModeId: string; }> = this._onModelModeChanged.event;
private _modelCreationOptionsByLanguageAndResource: {
[languageAndResource: string]: ITextModelCreationOptions;
@@ -250,14 +283,14 @@ export class ModelServiceImpl implements IModelService {
constructor(
@IMarkerService markerService: IMarkerService,
@IConfigurationService configurationService: IConfigurationService,
@ITextResourcePropertiesService resourcePropertiesService: ITextResourcePropertiesService,
) {
super();
this._markerService = markerService;
this._configurationService = configurationService;
this._resourcePropertiesService = resourcePropertiesService;
this._models = {};
this._modelCreationOptionsByLanguageAndResource = Object.create(null);
this._onModelAdded = new Emitter<ITextModel>();
this._onModelRemoved = new Emitter<ITextModel>();
this._onModelModeChanged = new Emitter<{ model: ITextModel; oldModeId: string; }>();
if (this._markerService) {
this._markerServiceSubscription = this._markerService.onMarkerChanged(this._handleMarkerChange, this);
@@ -285,7 +318,7 @@ export class ModelServiceImpl implements IModelService {
}
let newDefaultEOL = DEFAULT_EOL;
const eol = config.files && config.files.eol;
const eol = config.eol;
if (eol === '\r\n') {
newDefaultEOL = DefaultEndOfLine.CRLF;
} else if (eol === '\n') {
@@ -321,7 +354,9 @@ export class ModelServiceImpl implements IModelService {
public getCreationOptions(language: string, resource: URI, isForSimpleWidget: boolean): ITextModelCreationOptions {
let creationOptions = this._modelCreationOptionsByLanguageAndResource[language + resource];
if (!creationOptions) {
creationOptions = ModelServiceImpl._readModelOptions(this._configurationService.getValue({ overrideIdentifier: language, resource }), isForSimpleWidget);
const editor = this._configurationService.getValue<IRawEditorConfig>('editor', { overrideIdentifier: language, resource });
const eol = this._resourcePropertiesService.getEOL(resource, language);
creationOptions = ModelServiceImpl._readModelOptions({ editor, eol }, isForSimpleWidget);
this._modelCreationOptionsByLanguageAndResource[language + resource] = creationOptions;
}
return creationOptions;
@@ -374,6 +409,7 @@ export class ModelServiceImpl implements IModelService {
this._markerServiceSubscription.dispose();
}
this._configurationServiceSubscription.dispose();
super.dispose();
}
private _handleMarkerChange(changedResources: URI[]): void {
@@ -494,14 +530,14 @@ export class ModelServiceImpl implements IModelService {
return [EditOperation.replaceMove(oldRange, textBuffer.getValueInRange(newRange, EndOfLinePreference.TextDefined))];
}
public createModel(value: string | ITextBufferFactory, modeOrPromise: TPromise<IMode> | IMode, resource: URI, isForSimpleWidget: boolean = false): ITextModel {
public createModel(value: string | ITextBufferFactory, languageSelection: ILanguageSelection | null, resource: URI, isForSimpleWidget: boolean = false): ITextModel {
let modelData: ModelData;
if (!modeOrPromise || TPromise.is(modeOrPromise)) {
modelData = this._createModelData(value, PLAINTEXT_LANGUAGE_IDENTIFIER, resource, isForSimpleWidget);
this.setMode(modelData.model, modeOrPromise);
if (languageSelection) {
modelData = this._createModelData(value, languageSelection.languageIdentifier, resource, isForSimpleWidget);
this.setMode(modelData.model, languageSelection);
} else {
modelData = this._createModelData(value, modeOrPromise.getLanguageIdentifier(), resource, isForSimpleWidget);
modelData = this._createModelData(value, PLAINTEXT_LANGUAGE_IDENTIFIER, resource, isForSimpleWidget);
}
// handle markers (marker service => model)
@@ -514,19 +550,15 @@ export class ModelServiceImpl implements IModelService {
return modelData.model;
}
public setMode(model: ITextModel, modeOrPromise: TPromise<IMode> | IMode): void {
if (!modeOrPromise) {
public setMode(model: ITextModel, languageSelection: ILanguageSelection): void {
if (!languageSelection) {
return;
}
if (TPromise.is(modeOrPromise)) {
modeOrPromise.then((mode) => {
if (!model.isDisposed()) {
model.setMode(mode.getLanguageIdentifier());
}
});
} else {
model.setMode(modeOrPromise.getLanguageIdentifier());
let modelData = this._models[MODEL_ID(model.uri)];
if (!modelData) {
return;
}
modelData.setLanguage(languageSelection);
}
public destroyModel(resource: URI): void {
@@ -550,7 +582,7 @@ export class ModelServiceImpl implements IModelService {
return ret;
}
public getModel(resource: URI): ITextModel {
public getModel(resource: URI): ITextModel | null {
let modelId = MODEL_ID(resource);
let modelData = this._models[modelId];
if (!modelData) {
@@ -559,18 +591,6 @@ export class ModelServiceImpl implements IModelService {
return modelData.model;
}
public get onModelAdded(): Event<ITextModel> {
return this._onModelAdded ? this._onModelAdded.event : null;
}
public get onModelRemoved(): Event<ITextModel> {
return this._onModelRemoved ? this._onModelRemoved.event : null;
}
public get onModelModeChanged(): Event<{ model: ITextModel; oldModeId: string; }> {
return this._onModelModeChanged ? this._onModelModeChanged.event : null;
}
// --- end IModelService
private _onWillDispose(model: ITextModel): void {