From 2e27b5433ecf76c5933f1d58110d97fa77834103 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 2 Mar 2017 18:35:03 +0100 Subject: [PATCH] Clean up IRawText usage --- src/vs/editor/common/editorCommon.ts | 22 +-- .../editor/common/model/editableTextModel.ts | 6 +- src/vs/editor/common/model/model.ts | 10 +- src/vs/editor/common/model/textModel.ts | 161 +++-------------- .../common/model/textModelWithDecorations.ts | 6 +- .../common/model/textModelWithMarkers.ts | 8 +- .../common/model/textModelWithTokens.ts | 6 +- src/vs/editor/common/model/textSource.ts | 104 +++++++++++ .../common/services/editorSimpleWorker.ts | 13 +- .../services/editorSimpleWorkerCommon.ts | 13 -- .../services/editorWorkerServiceImpl.ts | 4 +- .../common/services/modelServiceImpl.ts | 13 +- .../test/common/smartSnippetInserter.test.ts | 3 +- .../test/common/commands/commandTestUtils.ts | 2 +- .../test/common/commands/sideEditing.test.ts | 2 +- .../common/model/editableTextModel.test.ts | 15 +- .../model/editableTextModelTestUtils.ts | 5 +- src/vs/editor/test/common/model/model.test.ts | 2 +- .../test/common/model/textModel.test.ts | 167 ++++++++++-------- .../test/common/model/textModelSearch.test.ts | 31 ++-- .../common/model/textModelWithTokens.test.ts | 3 +- .../services/editorSimpleWorker.test.ts | 11 +- src/vs/workbench/api/node/extHostDocuments.ts | 15 +- .../workbench/api/node/mainThreadDocuments.ts | 6 +- .../services/backup/node/backupFileService.ts | 9 +- 25 files changed, 306 insertions(+), 331 deletions(-) delete mode 100644 src/vs/editor/common/services/editorSimpleWorkerCommon.ts diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 7d1011c4a62..e175f08c86d 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -21,7 +21,7 @@ import { IndentRange } from 'vs/editor/common/model/indentRanges'; import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands'; import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { FontInfo } from 'vs/editor/common/config/fontInfo'; -import { ITextSource } from 'vs/editor/common/model/textSource'; +import { ITextSource, ITextModelData } from 'vs/editor/common/model/textSource'; /** * @internal @@ -1745,7 +1745,7 @@ export interface ITextModel { * Get the raw text stored in this model. * @internal */ - toRawText(): IRawText; + toRawText(): ITextModelData; /** * Check if the raw text stored in this model equals another raw text. @@ -2458,22 +2458,6 @@ export interface IModelContentChangedEvent { readonly isRedoing: boolean; } -/** - * The raw text backing a model. - * @internal - */ -export interface IRawText extends ITextSource { - /** - * The options associated with this text. - */ - readonly options: { - readonly tabSize: number; - readonly insertSpaces: boolean; - readonly defaultEOL: DefaultEndOfLine; - readonly trimAutoWhitespace: boolean; - }; -} - /** * An event describing that a model has been reset to a new value. * @internal @@ -2482,7 +2466,7 @@ export interface IModelContentChangedFlushEvent extends IModelContentChangedEven /** * The new text content of the model. */ - readonly detail: IRawText; + readonly detail: ITextModelData; } /** * An event describing that a line has changed in a model. diff --git a/src/vs/editor/common/model/editableTextModel.ts b/src/vs/editor/common/model/editableTextModel.ts index fcfc4a9a4e1..8c735a255fa 100644 --- a/src/vs/editor/common/model/editableTextModel.ts +++ b/src/vs/editor/common/model/editableTextModel.ts @@ -14,7 +14,7 @@ import { Selection } from 'vs/editor/common/core/selection'; import { Position } from 'vs/editor/common/core/position'; import { IDisposable } from 'vs/base/common/lifecycle'; import { LanguageIdentifier } from 'vs/editor/common/modes'; -import { ITextSource } from 'vs/editor/common/model/textSource'; +import { ITextModelData, ITextSource } from 'vs/editor/common/model/textSource'; export interface IValidatedEditOperation { sortIndex: number; @@ -51,9 +51,9 @@ export class EditableTextModel extends TextModelWithDecorations implements edito private _trimAutoWhitespaceLines: number[]; - constructor(allowedEventTypes: string[], rawText: editorCommon.IRawText, languageIdentifier: LanguageIdentifier) { + constructor(allowedEventTypes: string[], textModelData: ITextModelData, languageIdentifier: LanguageIdentifier) { allowedEventTypes.push(editorCommon.EventType.ModelRawContentChanged); - super(allowedEventTypes, rawText, languageIdentifier); + super(allowedEventTypes, textModelData, languageIdentifier); this._commandManager = new EditStack(this); diff --git a/src/vs/editor/common/model/model.ts b/src/vs/editor/common/model/model.ts index 54ee2733985..29d5d0627ce 100644 --- a/src/vs/editor/common/model/model.ts +++ b/src/vs/editor/common/model/model.ts @@ -7,13 +7,14 @@ import URI from 'vs/base/common/uri'; import { EventType, IModel, ITextModelCreationOptions, IModelDecorationsChangedEvent, - IModelOptionsChangedEvent, IModelLanguageChangedEvent, IRawText + IModelOptionsChangedEvent, IModelLanguageChangedEvent } from 'vs/editor/common/editorCommon'; import { EditableTextModel } from 'vs/editor/common/model/editableTextModel'; import { TextModel } from 'vs/editor/common/model/textModel'; import { IDisposable } from 'vs/base/common/lifecycle'; import { BulkListenerCallback } from 'vs/base/common/eventEmitter'; import { LanguageIdentifier } from 'vs/editor/common/modes'; +import { ITextModelData, TextModelData } from 'vs/editor/common/model/textSource'; // The hierarchy is: // Model -> EditableTextModel -> TextModelWithDecorations -> TextModelWithTrackedRanges -> TextModelWithMarkers -> TextModelWithTokens -> TextModel @@ -40,8 +41,7 @@ export class Model extends EditableTextModel implements IModel { } public static createFromString(text: string, options: ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier = null, uri: URI = null): Model { - let rawText = TextModel.toRawText(text, options); - return new Model(rawText, languageIdentifier, uri); + return new Model(TextModelData.fromString(text, options), languageIdentifier, uri); } public readonly id: string; @@ -49,8 +49,8 @@ export class Model extends EditableTextModel implements IModel { private readonly _associatedResource: URI; private _attachedEditorCount: number; - constructor(rawText: IRawText, languageIdentifier: LanguageIdentifier, associatedResource: URI = null) { - super([EventType.ModelDispose], rawText, languageIdentifier); + constructor(textModelData: ITextModelData, languageIdentifier: LanguageIdentifier, associatedResource: URI = null) { + super([EventType.ModelDispose], textModelData, languageIdentifier); // Generate a new unique model id MODEL_ID++; diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 7b0ebf7de54..f5709589f29 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -15,7 +15,7 @@ import { DEFAULT_INDENTATION, DEFAULT_TRIM_AUTO_WHITESPACE } from 'vs/editor/com import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { IndentRange, computeRanges } from 'vs/editor/common/model/indentRanges'; import { TextModelSearch, SearchParams } from 'vs/editor/common/model/textModelSearch'; -import { ITextSource, RawTextSource, IRawTextSource } from 'vs/editor/common/model/textSource'; +import { ITextModelData, TextSource, ITextSource } from 'vs/editor/common/model/textSource'; const LIMIT_FIND_COUNT = 999; export const LONG_LINE_BOUNDARY = 1000; @@ -52,15 +52,15 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo private _shouldSimplifyMode: boolean; private _shouldDenyMode: boolean; - constructor(allowedEventTypes: string[], rawText: editorCommon.IRawText) { + constructor(allowedEventTypes: string[], textModelData: ITextModelData) { allowedEventTypes.push(editorCommon.EventType.ModelRawContentChanged, editorCommon.EventType.ModelOptionsChanged, editorCommon.EventType.ModelContentChanged2); super(allowedEventTypes); - this._shouldSimplifyMode = (rawText.length > TextModel.MODEL_SYNC_LIMIT); - this._shouldDenyMode = (rawText.length > TextModel.MODEL_TOKENIZATION_LIMIT); + this._shouldSimplifyMode = (textModelData.text.length > TextModel.MODEL_SYNC_LIMIT); + this._shouldDenyMode = (textModelData.text.length > TextModel.MODEL_TOKENIZATION_LIMIT); - this._options = new editorCommon.TextModelResolvedOptions(rawText.options); - this._constructLines(rawText); + this._options = new editorCommon.TextModelResolvedOptions(textModelData.options); + this._constructLines(textModelData.text); this._setVersionId(1); this._isDisposed = false; this._isDisposing = false; @@ -291,15 +291,17 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo this._increaseVersionId(); } - public toRawText(): editorCommon.IRawText { + public toRawText(): ITextModelData { this._assertNotDisposed(); return { - BOM: this._BOM, - EOL: this._EOL, - lines: this.getLinesContent(), - length: this.getValueLength(), - containsRTL: this._mightContainRTL, - isBasicASCII: !this._mightContainNonBasicASCII, + text: { + BOM: this._BOM, + EOL: this._EOL, + lines: this.getLinesContent(), + length: this.getValueLength(), + containsRTL: this._mightContainRTL, + isBasicASCII: !this._mightContainNonBasicASCII + }, options: this._options }; } @@ -329,15 +331,8 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo // There's nothing to do return; } - let rawText: editorCommon.IRawText = null; - rawText = TextModel.toRawText(value, { - tabSize: this._options.tabSize, - insertSpaces: this._options.insertSpaces, - trimAutoWhitespace: this._options.trimAutoWhitespace, - detectIndentation: false, - defaultEOL: this._options.defaultEOL - }); - this.setValueFromRawText(rawText); + const textSource = TextSource.fromString(value, this._options.defaultEOL); + this.setValueFromRawText(textSource); } public setValueFromRawText(newValue: ITextSource): void { @@ -750,78 +745,18 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo } } - /** - * if text source is empty or with precisely one line, returns null. No end of line is detected. - * if text source contains more lines ending with '\r\n', returns '\r\n'. - * Otherwise returns '\n'. More lines end with '\n'. - */ - public static getEndOfLine(textSource: IRawTextSource): string { - const lineFeedCnt = textSource.lines.length - 1; - if (lineFeedCnt === 0) { - // This is an empty file or a file with precisely one line - return null; - } - if (textSource.totalCRCount > lineFeedCnt / 2) { - // More than half of the file contains \r\n ending lines - return '\r\n'; - } - // At least one line more ends in \n - return '\n'; - } - - public static toRawText(rawText: string, opts: editorCommon.ITextModelCreationOptions): editorCommon.IRawText { - const textSource = RawTextSource.fromString(rawText); - return TextModel.toRawTextFromTextSource(textSource, opts); - } - - public static toRawTextFromTextSource(textSource: IRawTextSource, opts: editorCommon.ITextModelCreationOptions): editorCommon.IRawText { - let EOL = TextModel.getEndOfLine(textSource); - if (!EOL) { - // This is an empty file or a file with precisely one line - EOL = (opts.defaultEOL === editorCommon.DefaultEndOfLine.LF ? '\n' : '\r\n'); - } - - let resolvedOpts: editorCommon.TextModelResolvedOptions; - if (opts.detectIndentation) { - let guessedIndentation = guessIndentation(textSource.lines, opts.tabSize, opts.insertSpaces); - resolvedOpts = new editorCommon.TextModelResolvedOptions({ - tabSize: guessedIndentation.tabSize, - insertSpaces: guessedIndentation.insertSpaces, - trimAutoWhitespace: opts.trimAutoWhitespace, - defaultEOL: opts.defaultEOL - }); - } else { - resolvedOpts = new editorCommon.TextModelResolvedOptions({ - tabSize: opts.tabSize, - insertSpaces: opts.insertSpaces, - trimAutoWhitespace: opts.trimAutoWhitespace, - defaultEOL: opts.defaultEOL - }); - } - - return { - BOM: textSource.BOM, - EOL: EOL, - lines: textSource.lines, - length: textSource.length, - containsRTL: textSource.containsRTL, - isBasicASCII: textSource.isBasicASCII, - options: resolvedOpts - }; - } - - private _constructLines(rawText: ITextSource): void { + private _constructLines(textSource: ITextSource): void { const tabSize = this._options.tabSize; - let rawLines = rawText.lines; + let rawLines = textSource.lines; let modelLines: ModelLine[] = []; for (let i = 0, len = rawLines.length; i < len; i++) { modelLines[i] = new ModelLine(i + 1, rawLines[i], tabSize); } - this._BOM = rawText.BOM; - this._mightContainRTL = rawText.containsRTL; - this._mightContainNonBasicASCII = !rawText.isBasicASCII; - this._EOL = rawText.EOL; + this._BOM = textSource.BOM; + this._mightContainRTL = textSource.containsRTL; + this._mightContainNonBasicASCII = !textSource.isBasicASCII; + this._EOL = textSource.EOL; this._lines = modelLines; this._lineStarts = null; this._resetIndentRanges(); @@ -864,53 +799,3 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return TextModelSearch.findPreviousMatch(this, new SearchParams(searchString, isRegex, matchCase, wholeWord), searchStart, captureMatches); } } - -export class RawText { - - public static toRawText(textSourceOrString: IRawTextSource | string, opts: editorCommon.ITextModelCreationOptions): editorCommon.IRawText { - if (typeof textSourceOrString === 'string') { - return RawText.fromString(textSourceOrString, opts); - } else { - return RawText.fromTextSource(textSourceOrString, opts); - } - } - - public static toRawTextWithModelOptions(textSourceOrString: IRawTextSource | string, model: editorCommon.IModel): editorCommon.IRawText { - if (typeof textSourceOrString === 'string') { - return RawText.fromStringWithModelOptions(textSourceOrString, model); - } else { - return RawText.fromTextSourceWithModelOptions(textSourceOrString, model); - } - } - - public static fromString(rawText: string, opts: editorCommon.ITextModelCreationOptions): editorCommon.IRawText { - return TextModel.toRawText(rawText, opts); - } - - public static fromTextSource(textSource: IRawTextSource, opts: editorCommon.ITextModelCreationOptions): editorCommon.IRawText { - return TextModel.toRawTextFromTextSource(textSource, opts); - } - - public static fromStringWithModelOptions(rawText: string, model: editorCommon.IModel): editorCommon.IRawText { - let opts = model.getOptions(); - return TextModel.toRawText(rawText, { - tabSize: opts.tabSize, - insertSpaces: opts.insertSpaces, - trimAutoWhitespace: opts.trimAutoWhitespace, - detectIndentation: false, - defaultEOL: opts.defaultEOL - }); - } - - public static fromTextSourceWithModelOptions(textSource: IRawTextSource, model: editorCommon.IModel): editorCommon.IRawText { - let opts = model.getOptions(); - return TextModel.toRawTextFromTextSource(textSource, { - tabSize: opts.tabSize, - insertSpaces: opts.insertSpaces, - trimAutoWhitespace: opts.trimAutoWhitespace, - detectIndentation: false, - defaultEOL: opts.defaultEOL - }); - } - -} diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 78e5f597d2b..30df8508cc0 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -14,7 +14,7 @@ import { MarkersTracker, LineMarker } from 'vs/editor/common/model/modelLine'; import { Position } from 'vs/editor/common/core/position'; import { INewMarker, TextModelWithMarkers } from 'vs/editor/common/model/textModelWithMarkers'; import { LanguageIdentifier } from 'vs/editor/common/modes'; -import { ITextSource } from 'vs/editor/common/model/textSource'; +import { ITextModelData, ITextSource } from 'vs/editor/common/model/textSource'; class DecorationsTracker { @@ -140,9 +140,9 @@ export class TextModelWithDecorations extends TextModelWithMarkers implements ed private _internalDecorations: { [internalDecorationId: number]: InternalDecoration; }; private _multiLineDecorationsMap: { [key: string]: InternalDecoration; }; - constructor(allowedEventTypes: string[], rawText: editorCommon.IRawText, languageIdentifier: LanguageIdentifier) { + constructor(allowedEventTypes: string[], textModelData: ITextModelData, languageIdentifier: LanguageIdentifier) { allowedEventTypes.push(editorCommon.EventType.ModelDecorationsChanged); - super(allowedEventTypes, rawText, languageIdentifier); + super(allowedEventTypes, textModelData, languageIdentifier); this._instanceId = nextInstanceId(); this._lastDecorationId = 0; diff --git a/src/vs/editor/common/model/textModelWithMarkers.ts b/src/vs/editor/common/model/textModelWithMarkers.ts index 0934f650ffa..da2a79efceb 100644 --- a/src/vs/editor/common/model/textModelWithMarkers.ts +++ b/src/vs/editor/common/model/textModelWithMarkers.ts @@ -6,11 +6,11 @@ import { IdGenerator } from 'vs/base/common/idGenerator'; import { Position } from 'vs/editor/common/core/position'; -import { IRawText, ITextModelWithMarkers } from 'vs/editor/common/editorCommon'; +import { ITextModelWithMarkers } from 'vs/editor/common/editorCommon'; import { LineMarker } from 'vs/editor/common/model/modelLine'; import { TextModelWithTokens } from 'vs/editor/common/model/textModelWithTokens'; import { LanguageIdentifier } from 'vs/editor/common/modes'; -import { ITextSource } from 'vs/editor/common/model/textSource'; +import { ITextModelData, ITextSource } from 'vs/editor/common/model/textSource'; export interface IMarkerIdToMarkerMap { [key: string]: LineMarker; @@ -29,8 +29,8 @@ export class TextModelWithMarkers extends TextModelWithTokens implements ITextMo private _markerIdGenerator: IdGenerator; protected _markerIdToMarker: IMarkerIdToMarkerMap; - constructor(allowedEventTypes: string[], rawText: IRawText, languageIdentifier: LanguageIdentifier) { - super(allowedEventTypes, rawText, languageIdentifier); + constructor(allowedEventTypes: string[], textModelData: ITextModelData, languageIdentifier: LanguageIdentifier) { + super(allowedEventTypes, textModelData, languageIdentifier); this._markerIdGenerator = new IdGenerator((++_INSTANCE_COUNT) + ';'); this._markerIdToMarker = Object.create(null); } diff --git a/src/vs/editor/common/model/textModelWithTokens.ts b/src/vs/editor/common/model/textModelWithTokens.ts index 63ee6c82976..501de624b1b 100644 --- a/src/vs/editor/common/model/textModelWithTokens.ts +++ b/src/vs/editor/common/model/textModelWithTokens.ts @@ -21,7 +21,7 @@ import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageCo import { LineTokens, LineToken } from 'vs/editor/common/core/lineTokens'; import { getWordAtText } from 'vs/editor/common/model/wordHelper'; import { TokenizationResult2 } from 'vs/editor/common/core/token'; -import { ITextSource } from 'vs/editor/common/model/textSource'; +import { ITextModelData, ITextSource } from 'vs/editor/common/model/textSource'; class ModelTokensChangedEventBuilder { @@ -71,10 +71,10 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke private _revalidateTokensTimeout: number; - constructor(allowedEventTypes: string[], rawText: editorCommon.IRawText, languageIdentifier: LanguageIdentifier) { + constructor(allowedEventTypes: string[], textModelData: ITextModelData, languageIdentifier: LanguageIdentifier) { allowedEventTypes.push(editorCommon.EventType.ModelTokensChanged); allowedEventTypes.push(editorCommon.EventType.ModelLanguageChanged); - super(allowedEventTypes, rawText); + super(allowedEventTypes, textModelData); this._languageIdentifier = languageIdentifier || NULL_LANGUAGE_IDENTIFIER; this._tokenizationListener = TokenizationRegistry.onDidChange((e) => { diff --git a/src/vs/editor/common/model/textSource.ts b/src/vs/editor/common/model/textSource.ts index ba6782dc8d4..a052ec9fb0c 100644 --- a/src/vs/editor/common/model/textSource.ts +++ b/src/vs/editor/common/model/textSource.ts @@ -5,6 +5,8 @@ 'use strict'; import * as strings from 'vs/base/common/strings'; +import { DefaultEndOfLine, ITextModelCreationOptions, TextModelResolvedOptions } from 'vs/editor/common/editorCommon'; +import { guessIndentation } from 'vs/editor/common/model/indentationGuesser'; /** * A processed string ready to be turned into an editor model. @@ -100,3 +102,105 @@ export interface ITextSource { */ readonly isBasicASCII: boolean; } + +export class TextSource { + + /** + * if text source is empty or with precisely one line, returns null. No end of line is detected. + * if text source contains more lines ending with '\r\n', returns '\r\n'. + * Otherwise returns '\n'. More lines end with '\n'. + */ + private static _getEOL(rawTextSource: IRawTextSource, defaultEOL: DefaultEndOfLine): '\r\n' | '\n' { + const lineFeedCnt = rawTextSource.lines.length - 1; + if (lineFeedCnt === 0) { + // This is an empty file or a file with precisely one line + return (defaultEOL === DefaultEndOfLine.LF ? '\n' : '\r\n'); + } + if (rawTextSource.totalCRCount > lineFeedCnt / 2) { + // More than half of the file contains \r\n ending lines + return '\r\n'; + } + // At least one line more ends in \n + return '\n'; + } + + public static fromRawTextSource(rawTextSource: IRawTextSource, defaultEOL: DefaultEndOfLine): ITextSource { + return { + length: rawTextSource.length, + lines: rawTextSource.lines, + BOM: rawTextSource.BOM, + EOL: this._getEOL(rawTextSource, defaultEOL), + containsRTL: rawTextSource.containsRTL, + isBasicASCII: rawTextSource.isBasicASCII, + }; + } + + public static fromString(text: string, defaultEOL: DefaultEndOfLine): ITextSource { + return this.fromRawTextSource(RawTextSource.fromString(text), defaultEOL); + } + + public static create(source: string | IRawTextSource, defaultEOL: DefaultEndOfLine): ITextSource { + if (typeof source === 'string') { + return this.fromString(source, defaultEOL); + } + + return this.fromRawTextSource(source, defaultEOL); + } + +} + +export interface ITextModelData { + readonly text: ITextSource; + readonly options: { + readonly tabSize: number; + readonly insertSpaces: boolean; + readonly defaultEOL: DefaultEndOfLine; + readonly trimAutoWhitespace: boolean; + }; +} + +export class TextModelData { + + private static _fromTextSource(textSource: ITextSource, opts: ITextModelCreationOptions): ITextModelData { + let resolvedOpts: TextModelResolvedOptions; + if (opts.detectIndentation) { + const guessedIndentation = guessIndentation(textSource.lines, opts.tabSize, opts.insertSpaces); + resolvedOpts = new TextModelResolvedOptions({ + tabSize: guessedIndentation.tabSize, + insertSpaces: guessedIndentation.insertSpaces, + trimAutoWhitespace: opts.trimAutoWhitespace, + defaultEOL: opts.defaultEOL + }); + } else { + resolvedOpts = new TextModelResolvedOptions({ + tabSize: opts.tabSize, + insertSpaces: opts.insertSpaces, + trimAutoWhitespace: opts.trimAutoWhitespace, + defaultEOL: opts.defaultEOL + }); + } + + return { + text: textSource, + options: resolvedOpts + }; + } + + public static fromRawTextSource(rawTextSource: IRawTextSource, opts: ITextModelCreationOptions): ITextModelData { + const textSource = TextSource.fromRawTextSource(rawTextSource, opts.defaultEOL); + return this._fromTextSource(textSource, opts); + } + + public static fromString(text: string, opts: ITextModelCreationOptions): ITextModelData { + const textSource = TextSource.fromString(text, opts.defaultEOL); + return this._fromTextSource(textSource, opts); + } + + public static create(source: string | IRawTextSource, opts: ITextModelCreationOptions): ITextModelData { + if (typeof source === 'string') { + return this.fromString(source, opts); + } + return this.fromRawTextSource(source, opts); + } + +} diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index c407ffbb54d..0096160bf17 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -18,7 +18,6 @@ import { MirrorModel2 } from 'vs/editor/common/model/mirrorModel2'; import { IInplaceReplaceSupportResult, ILink, ISuggestResult, ISuggestion } from 'vs/editor/common/modes'; import { computeLinks } from 'vs/editor/common/modes/linkComputer'; import { BasicInplaceReplace } from 'vs/editor/common/modes/supports/inplaceReplaceSupport'; -import { IRawModelData } from 'vs/editor/common/services/editorSimpleWorkerCommon'; import { getWordAtText, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper'; import { createMonacoBaseAPI } from 'vs/editor/common/standalone/standaloneBase'; @@ -35,6 +34,16 @@ export interface IWorkerContext { getMirrorModels(): IMirrorModel[]; } +/** + * @internal + */ +export interface IRawModelData { + url: string; + versionId: number; + lines: string[]; + EOL: string; +} + /** * @internal */ @@ -502,7 +511,7 @@ export class EditorSimpleWorkerImpl extends BaseEditorSimpleWorker implements IR } public acceptNewModel(data: IRawModelData): void { - this._models[data.url] = new MirrorModel(URI.parse(data.url), data.value.lines, data.value.EOL, data.versionId); + this._models[data.url] = new MirrorModel(URI.parse(data.url), data.lines, data.EOL, data.versionId); } public acceptModelChanged(strURL: string, events: editorCommon.IModelContentChangedEvent2[]): void { diff --git a/src/vs/editor/common/services/editorSimpleWorkerCommon.ts b/src/vs/editor/common/services/editorSimpleWorkerCommon.ts deleted file mode 100644 index 808341db694..00000000000 --- a/src/vs/editor/common/services/editorSimpleWorkerCommon.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as editorCommon from 'vs/editor/common/editorCommon'; - -export interface IRawModelData { - url: string; - versionId: number; - value: editorCommon.IRawText; -} diff --git a/src/vs/editor/common/services/editorWorkerServiceImpl.ts b/src/vs/editor/common/services/editorWorkerServiceImpl.ts index 63c5af6992b..9a85c0c2d29 100644 --- a/src/vs/editor/common/services/editorWorkerServiceImpl.ts +++ b/src/vs/editor/common/services/editorWorkerServiceImpl.ts @@ -215,9 +215,11 @@ class EditorModelManager extends Disposable { let modelUrl = resource.toString(); + const textModelData = model.toRawText(); this._proxy.acceptNewModel({ url: model.uri.toString(), - value: model.toRawText(), + lines: textModelData.text.lines, + EOL: textModelData.text.EOL, versionId: model.getVersionId() }); diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 4e43e55eb9e..b0943081360 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -23,8 +23,7 @@ import * as platform from 'vs/base/common/platform'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { DEFAULT_INDENTATION, DEFAULT_TRIM_AUTO_WHITESPACE } from 'vs/editor/common/config/defaultConfig'; import { PLAINTEXT_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/modesRegistry'; -import { RawText } from 'vs/editor/common/model/textModel'; -import { IRawTextSource } from 'vs/editor/common/model/textSource'; +import { IRawTextSource, TextModelData, TextSource } from 'vs/editor/common/model/textSource'; function MODEL_ID(resource: URI): string { return resource.toString(); @@ -342,9 +341,7 @@ export class ModelServiceImpl implements IModelService { private _createModelData(value: string | IRawTextSource, languageIdentifier: LanguageIdentifier, resource: URI): ModelData { // create & save the model const options = this.getCreationOptions(languageIdentifier.language); - - let rawText: editorCommon.IRawText = RawText.toRawText(value, options); - let model: Model = new Model(rawText, languageIdentifier, resource); + let model: Model = new Model(TextModelData.create(value, options), languageIdentifier, resource); let modelId = MODEL_ID(model.uri); if (this._models[modelId]) { @@ -360,15 +357,15 @@ export class ModelServiceImpl implements IModelService { public updateModel(model: editorCommon.IModel, value: string | IRawTextSource): void { let options = this.getCreationOptions(model.getLanguageIdentifier().language); - let rawText: editorCommon.IRawText = RawText.toRawText(value, options); + const textSource = TextSource.create(value, options.defaultEOL); // Return early if the text is already set in that form - if (model.equals(rawText)) { + if (model.equals(textSource)) { return; } // Otherwise update model - model.setValueFromRawText(rawText); + model.setValueFromRawText(textSource); } public createModel(value: string | IRawTextSource, modeOrPromise: TPromise | IMode, resource: URI): editorCommon.IModel { diff --git a/src/vs/editor/contrib/defineKeybinding/test/common/smartSnippetInserter.test.ts b/src/vs/editor/contrib/defineKeybinding/test/common/smartSnippetInserter.test.ts index 6f24fd01c52..0e0282739e7 100644 --- a/src/vs/editor/contrib/defineKeybinding/test/common/smartSnippetInserter.test.ts +++ b/src/vs/editor/contrib/defineKeybinding/test/common/smartSnippetInserter.test.ts @@ -9,11 +9,12 @@ import * as assert from 'assert'; import { SmartSnippetInserter } from 'vs/editor/contrib/defineKeybinding/common/smartSnippetInserter'; import { TextModel } from 'vs/editor/common/model/textModel'; import { Position } from 'vs/editor/common/core/position'; +import { TextModelData } from 'vs/editor/common/model/textSource'; suite('SmartSnippetInserter', () => { function testSmartSnippetInserter(text: string[], runner: (assert: (desiredPos: Position, pos: Position, prepend: string, append: string) => void) => void): void { - let model = new TextModel([], TextModel.toRawText(text.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString(text.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS)); runner((desiredPos, pos, prepend, append) => { let actual = SmartSnippetInserter.insertSnippet(model, desiredPos); let expected = { diff --git a/src/vs/editor/test/common/commands/commandTestUtils.ts b/src/vs/editor/test/common/commands/commandTestUtils.ts index 5452e102988..e143414d300 100644 --- a/src/vs/editor/test/common/commands/commandTestUtils.ts +++ b/src/vs/editor/test/common/commands/commandTestUtils.ts @@ -31,7 +31,7 @@ export function testCommand( cursor.trigger('tests', editorCommon.Handler.ExecuteCommand, commandFactory(cursor.getSelection())); - let actualValue = model.toRawText().lines; + let actualValue = model.toRawText().text.lines; assert.deepEqual(actualValue, expectedLines); let actualSelection = cursor.getSelection(); diff --git a/src/vs/editor/test/common/commands/sideEditing.test.ts b/src/vs/editor/test/common/commands/sideEditing.test.ts index 2a885d0c5cf..e492671d120 100644 --- a/src/vs/editor/test/common/commands/sideEditing.test.ts +++ b/src/vs/editor/test/common/commands/sideEditing.test.ts @@ -27,7 +27,7 @@ function testCommand(lines: string[], selections: Selection[], edits: IIdentifie model.applyEdits(edits); - let actualValue = model.toRawText().lines; + let actualValue = model.toRawText().text.lines; assert.deepEqual(actualValue, expectedLines); let actualSelections = cursor.getSelections(); diff --git a/src/vs/editor/test/common/model/editableTextModel.test.ts b/src/vs/editor/test/common/model/editableTextModel.test.ts index e31b2fa8f13..27a89b4196a 100644 --- a/src/vs/editor/test/common/model/editableTextModel.test.ts +++ b/src/vs/editor/test/common/model/editableTextModel.test.ts @@ -12,6 +12,7 @@ import { EditableTextModel, IValidatedEditOperation } from 'vs/editor/common/mod import { MirrorModel2 } from 'vs/editor/common/model/mirrorModel2'; import { TextModel } from 'vs/editor/common/model/textModel'; import { assertSyncedModels, testApplyEditsWithSyncedModels } from 'vs/editor/test/common/model/editableTextModelTestUtils'; +import { TextModelData } from 'vs/editor/common/model/textSource'; suite('EditorModel - EditableTextModel._getInverseEdits', () => { @@ -278,7 +279,7 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { } function testSimpleApplyEdits(original: string[], edits: IValidatedEditOperation[], expected: IValidatedEditOperation): void { - let model = new EditableTextModel([], TextModel.toRawText(original.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), null); + let model = new EditableTextModel([], TextModelData.fromString(original.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), null); model.setEOL(EndOfLineSequence.LF); let actual = model._toSingleEditOperation(edits); @@ -520,7 +521,7 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => { suite('EditorModel - EditableTextModel.applyEdits updates mightContainRTL', () => { function testApplyEdits(original: string[], edits: IIdentifiedSingleEditOperation[], before: boolean, after: boolean): void { - let model = new EditableTextModel([], TextModel.toRawText(original.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), null); + let model = new EditableTextModel([], TextModelData.fromString(original.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), null); model.setEOL(EndOfLineSequence.LF); assert.equal(model.mightContainRTL(), before); @@ -568,7 +569,7 @@ suite('EditorModel - EditableTextModel.applyEdits updates mightContainRTL', () = suite('EditorModel - EditableTextModel.applyEdits updates mightContainNonBasicASCII', () => { function testApplyEdits(original: string[], edits: IIdentifiedSingleEditOperation[], before: boolean, after: boolean): void { - let model = new EditableTextModel([], TextModel.toRawText(original.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), null); + let model = new EditableTextModel([], TextModelData.fromString(original.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), null); model.setEOL(EndOfLineSequence.LF); assert.equal(model.mightContainNonBasicASCII(), before); @@ -1363,7 +1364,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { }); function testApplyEditsFails(original: string[], edits: IIdentifiedSingleEditOperation[]): void { - let model = new EditableTextModel([], TextModel.toRawText(original.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), null); + let model = new EditableTextModel([], TextModelData.fromString(original.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), null); let hasThrown = false; try { @@ -1551,10 +1552,10 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { }); test('issue #1580: Changes in line endings are not correctly reflected in the extension host, leading to invalid offsets sent to external refactoring tools', () => { - let model = new EditableTextModel([], TextModel.toRawText('Hello\nWorld!', TextModel.DEFAULT_CREATION_OPTIONS), null); + let model = new EditableTextModel([], TextModelData.fromString('Hello\nWorld!', TextModel.DEFAULT_CREATION_OPTIONS), null); assert.equal(model.getEOL(), '\n'); - let mirrorModel2 = new MirrorModel2(null, model.toRawText().lines, model.toRawText().EOL, model.getVersionId()); + let mirrorModel2 = new MirrorModel2(null, model.toRawText().text.lines, model.getEOL(), model.getVersionId()); let mirrorModel2PrevVersionId = model.getVersionId(); model.onDidChangeContent((e: IModelContentChangedEvent2) => { @@ -1622,7 +1623,7 @@ suite('EditorModel - EditableTextModel.applyEdits & markers', () => { // var expectedMarkersMap = toMarkersMap(expectedMarkers); var markerId2ModelMarkerId = Object.create(null); - var model = new EditableTextModel([], TextModel.toRawText(textStr, TextModel.DEFAULT_CREATION_OPTIONS), null); + var model = new EditableTextModel([], TextModelData.fromString(textStr, TextModel.DEFAULT_CREATION_OPTIONS), null); model.setEOL(EndOfLineSequence.LF); // Add markers diff --git a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts index f2b8a8fdc8f..1d1f5c5bf67 100644 --- a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts +++ b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts @@ -10,6 +10,7 @@ import { EditableTextModel } from 'vs/editor/common/model/editableTextModel'; import { MirrorModel2 } from 'vs/editor/common/model/mirrorModel2'; import { TextModel } from 'vs/editor/common/model/textModel'; import { Position } from 'vs/editor/common/core/position'; +import { TextModelData } from 'vs/editor/common/model/textSource'; export function testApplyEditsWithSyncedModels(original: string[], edits: editorCommon.IIdentifiedSingleEditOperation[], expected: string[], inputEditsAreInvalid: boolean = false): void { var originalStr = original.join('\n'); @@ -80,7 +81,7 @@ function assertLineMapping(model: TextModel, msg: string): void { export function assertSyncedModels(text: string, callback: (model: EditableTextModel, assertMirrorModels: () => void) => void, setup: (model: EditableTextModel) => void = null): void { - var model = new EditableTextModel([], TextModel.toRawText(text, TextModel.DEFAULT_CREATION_OPTIONS), null); + var model = new EditableTextModel([], TextModelData.fromString(text, TextModel.DEFAULT_CREATION_OPTIONS), null); model.setEOL(editorCommon.EndOfLineSequence.LF); assertLineMapping(model, 'model'); @@ -89,7 +90,7 @@ export function assertSyncedModels(text: string, callback: (model: EditableTextM assertLineMapping(model, 'model'); } - var mirrorModel2 = new MirrorModel2(null, model.toRawText().lines, model.toRawText().EOL, model.getVersionId()); + var mirrorModel2 = new MirrorModel2(null, model.toRawText().text.lines, model.getEOL(), model.getVersionId()); var mirrorModel2PrevVersionId = model.getVersionId(); model.onDidChangeContent((e: editorCommon.IModelContentChangedEvent2) => { diff --git a/src/vs/editor/test/common/model/model.test.ts b/src/vs/editor/test/common/model/model.test.ts index ab43109d1dd..b62a950659f 100644 --- a/src/vs/editor/test/common/model/model.test.ts +++ b/src/vs/editor/test/common/model/model.test.ts @@ -313,7 +313,7 @@ suite('Editor Model - Model', () => { assert.equal(e.changeType, EventType.ModelRawContentChangedFlush); - assert.deepEqual((e).detail.lines, ['new value']); + assert.deepEqual((e).detail.text.lines, ['new value']); }); thisModel.setValue('new value'); assert.equal(listenerCalls, 1, 'listener calls'); diff --git a/src/vs/editor/test/common/model/textModel.test.ts b/src/vs/editor/test/common/model/textModel.test.ts index 760c59338f6..b59e84724d7 100644 --- a/src/vs/editor/test/common/model/textModel.test.ts +++ b/src/vs/editor/test/common/model/textModel.test.ts @@ -8,10 +8,11 @@ import * as assert from 'assert'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { TextModel } from 'vs/editor/common/model/textModel'; -import { DefaultEndOfLine, IRawText } from 'vs/editor/common/editorCommon'; +import { DefaultEndOfLine } from 'vs/editor/common/editorCommon'; +import { TextModelData, ITextModelData } from 'vs/editor/common/model/textSource'; function testGuessIndentation(defaultInsertSpaces: boolean, defaultTabSize: number, expectedInsertSpaces: boolean, expectedTabSize: number, text: string[], msg?: string): void { - var m = new TextModel([], TextModel.toRawText(text.join('\n'), { + var m = new TextModel([], TextModelData.fromString(text.join('\n'), { tabSize: defaultTabSize, insertSpaces: defaultInsertSpaces, detectIndentation: true, @@ -53,21 +54,23 @@ function assertGuess(expectedInsertSpaces: boolean, expectedTabSize: number, tex suite('TextModel.toRawText', () => { - function testToRawText(text: string, expected: IRawText): void { - let actual = TextModel.toRawText(text, TextModel.DEFAULT_CREATION_OPTIONS); + function testToRawText(text: string, expected: ITextModelData): void { + let actual = TextModelData.fromString(text, TextModel.DEFAULT_CREATION_OPTIONS); assert.deepEqual(actual, expected); } test('one line text', () => { testToRawText('Hello world!', { - BOM: '', - EOL: '\n', - length: 12, - 'lines': [ - 'Hello world!' - ], - containsRTL: false, - isBasicASCII: true, + text: { + BOM: '', + EOL: '\n', + length: 12, + 'lines': [ + 'Hello world!' + ], + containsRTL: false, + isBasicASCII: true + }, options: { defaultEOL: DefaultEndOfLine.LF, insertSpaces: true, @@ -79,18 +82,20 @@ suite('TextModel.toRawText', () => { test('multiline text', () => { testToRawText('Hello,\r\ndear friend\nHow\rare\r\nyou?', { - BOM: '', - EOL: '\r\n', - length: 33, - 'lines': [ - 'Hello,', - 'dear friend', - 'How', - 'are', - 'you?' - ], - containsRTL: false, - isBasicASCII: true, + text: { + BOM: '', + EOL: '\r\n', + length: 33, + 'lines': [ + 'Hello,', + 'dear friend', + 'How', + 'are', + 'you?' + ], + containsRTL: false, + isBasicASCII: true + }, options: { defaultEOL: DefaultEndOfLine.LF, insertSpaces: true, @@ -102,15 +107,17 @@ suite('TextModel.toRawText', () => { test('Non Basic ASCII 1', () => { testToRawText('Hello,\nZürich', { - BOM: '', - EOL: '\n', - length: 13, - 'lines': [ - 'Hello,', - 'Zürich' - ], - containsRTL: false, - isBasicASCII: false, + text: { + BOM: '', + EOL: '\n', + length: 13, + 'lines': [ + 'Hello,', + 'Zürich' + ], + containsRTL: false, + isBasicASCII: false + }, options: { defaultEOL: DefaultEndOfLine.LF, insertSpaces: true, @@ -122,15 +129,17 @@ suite('TextModel.toRawText', () => { test('containsRTL 1', () => { testToRawText('Hello,\nזוהי עובדה מבוססת שדעתו', { - BOM: '', - EOL: '\n', - length: 30, - 'lines': [ - 'Hello,', - 'זוהי עובדה מבוססת שדעתו' - ], - containsRTL: true, - isBasicASCII: false, + text: { + BOM: '', + EOL: '\n', + length: 30, + 'lines': [ + 'Hello,', + 'זוהי עובדה מבוססת שדעתו' + ], + containsRTL: true, + isBasicASCII: false + }, options: { defaultEOL: DefaultEndOfLine.LF, insertSpaces: true, @@ -142,15 +151,17 @@ suite('TextModel.toRawText', () => { test('containsRTL 2', () => { testToRawText('Hello,\nهناك حقيقة مثبتة منذ زمن طويل', { - BOM: '', - EOL: '\n', - length: 36, - 'lines': [ - 'Hello,', - 'هناك حقيقة مثبتة منذ زمن طويل' - ], - containsRTL: true, - isBasicASCII: false, + text: { + BOM: '', + EOL: '\n', + length: 36, + 'lines': [ + 'Hello,', + 'هناك حقيقة مثبتة منذ زمن طويل' + ], + containsRTL: true, + isBasicASCII: false + }, options: { defaultEOL: DefaultEndOfLine.LF, insertSpaces: true, @@ -166,7 +177,7 @@ suite('Editor Model - TextModel', () => { test('getValueLengthInRange', () => { - var m = new TextModel([], TextModel.toRawText('My First Line\r\nMy Second Line\r\nMy Third Line', TextModel.DEFAULT_CREATION_OPTIONS)); + var m = new TextModel([], TextModelData.fromString('My First Line\r\nMy Second Line\r\nMy Third Line', TextModel.DEFAULT_CREATION_OPTIONS)); assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 1)), ''.length); assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 2)), 'M'.length); assert.equal(m.getValueLengthInRange(new Range(1, 2, 1, 3)), 'y'.length); @@ -179,7 +190,7 @@ suite('Editor Model - TextModel', () => { assert.equal(m.getValueLengthInRange(new Range(1, 2, 3, 1000)), 'y First Line\r\nMy Second Line\r\nMy Third Line'.length); assert.equal(m.getValueLengthInRange(new Range(1, 1, 1000, 1000)), 'My First Line\r\nMy Second Line\r\nMy Third Line'.length); - m = new TextModel([], TextModel.toRawText('My First Line\nMy Second Line\nMy Third Line', TextModel.DEFAULT_CREATION_OPTIONS)); + m = new TextModel([], TextModelData.fromString('My First Line\nMy Second Line\nMy Third Line', TextModel.DEFAULT_CREATION_OPTIONS)); assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 1)), ''.length); assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 2)), 'M'.length); assert.equal(m.getValueLengthInRange(new Range(1, 2, 1, 3)), 'y'.length); @@ -548,7 +559,7 @@ suite('Editor Model - TextModel', () => { test('validatePosition', () => { - let m = new TextModel([], TextModel.toRawText('line one\nline two', TextModel.DEFAULT_CREATION_OPTIONS)); + let m = new TextModel([], TextModelData.fromString('line one\nline two', TextModel.DEFAULT_CREATION_OPTIONS)); assert.deepEqual(m.validatePosition(new Position(0, 0)), new Position(1, 1)); assert.deepEqual(m.validatePosition(new Position(0, 1)), new Position(1, 1)); @@ -577,7 +588,7 @@ suite('Editor Model - TextModel', () => { test('validatePosition around high-low surrogate pairs 1', () => { - let m = new TextModel([], TextModel.toRawText('a📚b', TextModel.DEFAULT_CREATION_OPTIONS)); + let m = new TextModel([], TextModelData.fromString('a📚b', TextModel.DEFAULT_CREATION_OPTIONS)); assert.deepEqual(m.validatePosition(new Position(0, 0)), new Position(1, 1)); assert.deepEqual(m.validatePosition(new Position(0, 1)), new Position(1, 1)); @@ -604,7 +615,7 @@ suite('Editor Model - TextModel', () => { test('validatePosition around high-low surrogate pairs 2', () => { - let m = new TextModel([], TextModel.toRawText('a📚📚b', TextModel.DEFAULT_CREATION_OPTIONS)); + let m = new TextModel([], TextModelData.fromString('a📚📚b', TextModel.DEFAULT_CREATION_OPTIONS)); assert.deepEqual(m.validatePosition(new Position(1, 1)), new Position(1, 1)); assert.deepEqual(m.validatePosition(new Position(1, 2)), new Position(1, 2)); @@ -618,7 +629,7 @@ suite('Editor Model - TextModel', () => { test('validateRange around high-low surrogate pairs 1', () => { - let m = new TextModel([], TextModel.toRawText('a📚b', TextModel.DEFAULT_CREATION_OPTIONS)); + let m = new TextModel([], TextModelData.fromString('a📚b', TextModel.DEFAULT_CREATION_OPTIONS)); assert.deepEqual(m.validateRange(new Range(0, 0, 0, 1)), new Range(1, 1, 1, 1)); assert.deepEqual(m.validateRange(new Range(0, 0, 0, 7)), new Range(1, 1, 1, 1)); @@ -646,7 +657,7 @@ suite('Editor Model - TextModel', () => { test('validateRange around high-low surrogate pairs 2', () => { - let m = new TextModel([], TextModel.toRawText('a📚📚b', TextModel.DEFAULT_CREATION_OPTIONS)); + let m = new TextModel([], TextModelData.fromString('a📚📚b', TextModel.DEFAULT_CREATION_OPTIONS)); assert.deepEqual(m.validateRange(new Range(0, 0, 0, 1)), new Range(1, 1, 1, 1)); assert.deepEqual(m.validateRange(new Range(0, 0, 0, 7)), new Range(1, 1, 1, 1)); @@ -689,7 +700,7 @@ suite('Editor Model - TextModel', () => { test('modifyPosition', () => { - var m = new TextModel([], TextModel.toRawText('line one\nline two', TextModel.DEFAULT_CREATION_OPTIONS)); + var m = new TextModel([], TextModelData.fromString('line one\nline two', TextModel.DEFAULT_CREATION_OPTIONS)); assert.deepEqual(m.modifyPosition(new Position(1, 1), 0), new Position(1, 1)); assert.deepEqual(m.modifyPosition(new Position(0, 0), 0), new Position(1, 1)); assert.deepEqual(m.modifyPosition(new Position(30, 1), 0), new Position(2, 9)); @@ -719,12 +730,14 @@ suite('Editor Model - TextModel', () => { test('normalizeIndentation 1', () => { let model = new TextModel([], { - length: 0, - lines: [], - BOM: '', - EOL: '\n', - containsRTL: false, - isBasicASCII: true, + text: { + length: 0, + lines: [], + BOM: '', + EOL: '\n', + containsRTL: false, + isBasicASCII: true + }, options: { tabSize: 4, insertSpaces: false, @@ -760,12 +773,14 @@ suite('Editor Model - TextModel', () => { test('normalizeIndentation 2', () => { let model = new TextModel([], { - length: 0, - lines: [], - BOM: '', - EOL: '\n', - containsRTL: false, - isBasicASCII: true, + text: { + length: 0, + lines: [], + BOM: '', + EOL: '\n', + containsRTL: false, + isBasicASCII: true + }, options: { tabSize: 4, insertSpaces: true, @@ -792,24 +807,24 @@ suite('Editor Model - TextModel', () => { suite('TextModel.mightContainRTL', () => { test('nope', () => { - let model = new TextModel([], TextModel.toRawText('hello world!', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('hello world!', TextModel.DEFAULT_CREATION_OPTIONS)); assert.equal(model.mightContainRTL(), false); }); test('yes', () => { - let model = new TextModel([], TextModel.toRawText('Hello,\nזוהי עובדה מבוססת שדעתו', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('Hello,\nזוהי עובדה מבוססת שדעתו', TextModel.DEFAULT_CREATION_OPTIONS)); assert.equal(model.mightContainRTL(), true); }); test('setValue resets 1', () => { - let model = new TextModel([], TextModel.toRawText('hello world!', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('hello world!', TextModel.DEFAULT_CREATION_OPTIONS)); assert.equal(model.mightContainRTL(), false); model.setValue('Hello,\nזוהי עובדה מבוססת שדעתו'); assert.equal(model.mightContainRTL(), true); }); test('setValue resets 2', () => { - let model = new TextModel([], TextModel.toRawText('Hello,\nهناك حقيقة مثبتة منذ زمن طويل', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('Hello,\nهناك حقيقة مثبتة منذ زمن طويل', TextModel.DEFAULT_CREATION_OPTIONS)); assert.equal(model.mightContainRTL(), true); model.setValue('hello world!'); assert.equal(model.mightContainRTL(), false); @@ -820,7 +835,7 @@ suite('TextModel.mightContainRTL', () => { suite('TextModel.getLineIndentGuide', () => { function assertIndentGuides(lines: [number, string][]): void { let text = lines.map(l => l[1]).join('\n'); - let model = new TextModel([], TextModel.toRawText(text, TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString(text, TextModel.DEFAULT_CREATION_OPTIONS)); let actual: [number, string][] = []; for (let line = 1; line <= model.getLineCount(); line++) { diff --git a/src/vs/editor/test/common/model/textModelSearch.test.ts b/src/vs/editor/test/common/model/textModelSearch.test.ts index 7352f9f3644..814032fc7d1 100644 --- a/src/vs/editor/test/common/model/textModelSearch.test.ts +++ b/src/vs/editor/test/common/model/textModelSearch.test.ts @@ -10,6 +10,7 @@ import { FindMatch, EndOfLineSequence } from 'vs/editor/common/editorCommon'; import { Range } from 'vs/editor/common/core/range'; import { TextModel } from 'vs/editor/common/model/textModel'; import { TextModelSearch, SearchParams } from 'vs/editor/common/model/textModelSearch'; +import { TextModelData } from 'vs/editor/common/model/textSource'; // --------- Find suite('TextModelSearch', () => { @@ -48,12 +49,12 @@ suite('TextModelSearch', () => { let expectedMatches = expectedRanges.map(entry => new FindMatch(entry, null)); let searchParams = new SearchParams(searchString, isRegex, matchCase, wholeWord); - let model = new TextModel([], TextModel.toRawText(text, TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString(text, TextModel.DEFAULT_CREATION_OPTIONS)); _assertFindMatches(model, searchParams, expectedMatches); model.dispose(); - let model2 = new TextModel([], TextModel.toRawText(text, TextModel.DEFAULT_CREATION_OPTIONS)); + let model2 = new TextModel([], TextModelData.fromString(text, TextModel.DEFAULT_CREATION_OPTIONS)); model2.setEOL(EndOfLineSequence.CRLF); _assertFindMatches(model2, searchParams, expectedMatches); model2.dispose(); @@ -334,7 +335,7 @@ suite('TextModelSearch', () => { }); test('findNextMatch without regex', () => { - let model = new TextModel([], TextModel.toRawText('line line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('line line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('line', false, false, false); @@ -357,7 +358,7 @@ suite('TextModelSearch', () => { }); test('findNextMatch with beginning boundary regex', () => { - let model = new TextModel([], TextModel.toRawText('line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('^line', true, false, false); @@ -377,7 +378,7 @@ suite('TextModelSearch', () => { }); test('findNextMatch with beginning boundary regex and line has repetitive beginnings', () => { - let model = new TextModel([], TextModel.toRawText('line line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('line line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('^line', true, false, false); @@ -397,7 +398,7 @@ suite('TextModelSearch', () => { }); test('findNextMatch with beginning boundary multiline regex and line has repetitive beginnings', () => { - let model = new TextModel([], TextModel.toRawText('line line one\nline two\nline three\nline four', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('line line one\nline two\nline three\nline four', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('^line.*\\nline', true, false, false); @@ -414,7 +415,7 @@ suite('TextModelSearch', () => { }); test('findNextMatch with ending boundary regex', () => { - let model = new TextModel([], TextModel.toRawText('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('line$', true, false, false); @@ -434,7 +435,7 @@ suite('TextModelSearch', () => { }); test('findMatches with capturing matches', () => { - let model = new TextModel([], TextModel.toRawText('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('(l(in)e)', true, false, false); @@ -449,7 +450,7 @@ suite('TextModelSearch', () => { }); test('findMatches multiline with capturing matches', () => { - let model = new TextModel([], TextModel.toRawText('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('(l(in)e)\\n', true, false, false); @@ -463,7 +464,7 @@ suite('TextModelSearch', () => { }); test('findNextMatch with capturing matches', () => { - let model = new TextModel([], TextModel.toRawText('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('(l(in)e)', true, false, false); @@ -474,7 +475,7 @@ suite('TextModelSearch', () => { }); test('findNextMatch multiline with capturing matches', () => { - let model = new TextModel([], TextModel.toRawText('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('(l(in)e)\\n', true, false, false); @@ -485,7 +486,7 @@ suite('TextModelSearch', () => { }); test('findPreviousMatch with capturing matches', () => { - let model = new TextModel([], TextModel.toRawText('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('(l(in)e)', true, false, false); @@ -496,7 +497,7 @@ suite('TextModelSearch', () => { }); test('findPreviousMatch multiline with capturing matches', () => { - let model = new TextModel([], TextModel.toRawText('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS)); let searchParams = new SearchParams('(l(in)e)\\n', true, false, false); @@ -507,7 +508,7 @@ suite('TextModelSearch', () => { }); test('\\n matches \\r\\n', () => { - let model = new TextModel([], TextModel.toRawText('a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni', TextModel.DEFAULT_CREATION_OPTIONS)); assert.equal(model.getEOL(), '\r\n'); @@ -530,7 +531,7 @@ suite('TextModelSearch', () => { }); test('\\r can never be found', () => { - let model = new TextModel([], TextModel.toRawText('a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni', TextModel.DEFAULT_CREATION_OPTIONS)); + let model = new TextModel([], TextModelData.fromString('a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni', TextModel.DEFAULT_CREATION_OPTIONS)); assert.equal(model.getEOL(), '\r\n'); diff --git a/src/vs/editor/test/common/model/textModelWithTokens.test.ts b/src/vs/editor/test/common/model/textModelWithTokens.test.ts index 494af12eea0..d1812572252 100644 --- a/src/vs/editor/test/common/model/textModelWithTokens.test.ts +++ b/src/vs/editor/test/common/model/textModelWithTokens.test.ts @@ -18,6 +18,7 @@ import { TextModelWithTokens } from 'vs/editor/common/model/textModelWithTokens' import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { NULL_STATE } from 'vs/editor/common/modes/nullMode'; import { TokenizationResult2 } from 'vs/editor/common/core/token'; +import { TextModelData } from 'vs/editor/common/model/textSource'; suite('TextModelWithTokens', () => { @@ -77,7 +78,7 @@ suite('TextModelWithTokens', () => { let model = new TextModelWithTokens( [], - TextModel.toRawText(contents.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), + TextModelData.fromString(contents.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), languageIdentifier ); diff --git a/src/vs/editor/test/common/services/editorSimpleWorker.test.ts b/src/vs/editor/test/common/services/editorSimpleWorker.test.ts index 0757f3f2046..a7d7838f18c 100644 --- a/src/vs/editor/test/common/services/editorSimpleWorker.test.ts +++ b/src/vs/editor/test/common/services/editorSimpleWorker.test.ts @@ -21,15 +21,8 @@ suite('EditorSimpleWorker', () => { this.acceptNewModel({ url: uri, versionId: 1, - value: { - EOL: eol, - lines, - BOM: undefined, - containsRTL: undefined, - isBasicASCII: undefined, - length: undefined, - options: undefined - } + lines: lines, + EOL: eol }); return this._getModel(uri); } diff --git a/src/vs/workbench/api/node/extHostDocuments.ts b/src/vs/workbench/api/node/extHostDocuments.ts index 3531ef3f3ab..3169769d16a 100644 --- a/src/vs/workbench/api/node/extHostDocuments.ts +++ b/src/vs/workbench/api/node/extHostDocuments.ts @@ -7,7 +7,6 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { RawText } from 'vs/editor/common/model/textModel'; import { MirrorModel2 } from 'vs/editor/common/model/mirrorModel2'; import { IThreadService } from 'vs/workbench/services/thread/common/threadService'; import Event, { Emitter } from 'vs/base/common/event'; @@ -20,7 +19,7 @@ import * as vscode from 'vscode'; import { asWinJsPromise } from 'vs/base/common/async'; import { getWordAtText, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper'; import { MainContext, MainThreadDocumentsShape, ExtHostDocumentsShape, IModelAddedData } from './extHost.protocol'; -import { ITextSource } from 'vs/editor/common/model/textSource'; +import { ITextSource, TextSource } from 'vs/editor/common/model/textSource'; const _modeId2WordDefinition = new Map(); @@ -137,17 +136,11 @@ export class ExtHostDocuments extends ExtHostDocumentsShape { } // create lines and compare - const raw = RawText.fromString(value, { - defaultEOL: editorCommon.DefaultEndOfLine.CRLF, - tabSize: 0, - detectIndentation: false, - insertSpaces: false, - trimAutoWhitespace: false - }); + const textSource = TextSource.fromString(value, editorCommon.DefaultEndOfLine.CRLF); // broadcast event when content changed - if (!document.equalLines(raw)) { - return this._proxy.$onVirtualDocumentChange(uri, raw); + if (!document.equalLines(textSource)) { + return this._proxy.$onVirtualDocumentChange(uri, textSource); } }, onUnexpectedError); diff --git a/src/vs/workbench/api/node/mainThreadDocuments.ts b/src/vs/workbench/api/node/mainThreadDocuments.ts index 946dc3f5556..c0bf3a30d8b 100644 --- a/src/vs/workbench/api/node/mainThreadDocuments.ts +++ b/src/vs/workbench/api/node/mainThreadDocuments.ts @@ -103,12 +103,12 @@ export class MainThreadDocuments extends MainThreadDocumentsShape { let modelUrl = model.uri; this._modelIsSynced[modelUrl.toString()] = true; this._modelToDisposeMap[modelUrl.toString()] = model.addBulkListener((events) => this._onModelEvents(modelUrl, events)); - const modelRawText = model.toRawText(); + const textModelData = model.toRawText(); this._proxy.$acceptModelAdd({ url: model.uri, versionId: model.getVersionId(), - lines: modelRawText.lines, - EOL: modelRawText.EOL, + lines: textModelData.text.lines, + EOL: textModelData.text.EOL, modeId: model.getLanguageIdentifier().language, isDirty: this._textFileService.isDirty(modelUrl) }); diff --git a/src/vs/workbench/services/backup/node/backupFileService.ts b/src/vs/workbench/services/backup/node/backupFileService.ts index 51e3feaa698..d2e76189349 100644 --- a/src/vs/workbench/services/backup/node/backupFileService.ts +++ b/src/vs/workbench/services/backup/node/backupFileService.ts @@ -17,9 +17,9 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IFileService } from 'vs/platform/files/common/files'; import { TPromise } from 'vs/base/common/winjs.base'; import { readToMatchingString } from 'vs/base/node/stream'; -import { TextModel } from 'vs/editor/common/model/textModel'; import { IWindowService } from 'vs/platform/windows/common/windows'; -import { IRawTextSource } from 'vs/editor/common/model/textSource'; +import { TextSource, IRawTextSource } from 'vs/editor/common/model/textSource'; +import { DefaultEndOfLine } from 'vs/editor/common/editorCommon'; export interface IBackupFilesModel { resolve(backupRoot: string): TPromise; @@ -239,8 +239,9 @@ export class BackupFileService implements IBackupFileService { }); } - public parseBackupContent(textSource: IRawTextSource): string { - return textSource.lines.slice(1).join(TextModel.getEndOfLine(textSource) || ''); // The first line of a backup text file is the file name + public parseBackupContent(rawTextSource: IRawTextSource): string { + const textSource = TextSource.fromRawTextSource(rawTextSource, DefaultEndOfLine.LF); + return textSource.lines.slice(1).join(textSource.EOL); // The first line of a backup text file is the file name } protected getBackupResource(resource: Uri): Uri {