Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/vs/workbench/services/textfile/common/textFileEditorModel.ts')
-rw-r--r--src/vs/workbench/services/textfile/common/textFileEditorModel.ts74
1 files changed, 43 insertions, 31 deletions
diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts
index 02493a12664..4b5f8ac1838 100644
--- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts
+++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts
@@ -23,7 +23,7 @@ import { IWorkingCopyBackup, WorkingCopyCapabilities, NO_TYPE_ID, IWorkingCopyBa
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { ILabelService } from 'vs/platform/label/common/label';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
-import { UTF8 } from 'vs/workbench/services/textfile/common/encoding';
+import { UTF16be, UTF16le, UTF8, UTF8_with_bom } from 'vs/workbench/services/textfile/common/encoding';
import { createTextBufferFactoryFromStream } from 'vs/editor/common/model/textModel';
import { ILanguageDetectionService } from 'vs/workbench/services/languageDetection/common/languageDetectionWorkerService';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
@@ -272,11 +272,11 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
//#region Resolve
override async resolve(options?: ITextFileResolveOptions): Promise<void> {
- this.trace('[text file model] resolve() - enter');
+ this.trace('resolve() - enter');
// Return early if we are disposed
if (this.isDisposed()) {
- this.trace('[text file model] resolve() - exit - without resolving because model is disposed');
+ this.trace('resolve() - exit - without resolving because model is disposed');
return;
}
@@ -285,7 +285,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// resolve a model that is dirty or is in the process of saving to prevent data
// loss.
if (!options?.contents && (this.dirty || this.saveSequentializer.hasPending())) {
- this.trace('[text file model] resolve() - exit - without resolving because model is dirty or being saved');
+ this.trace('resolve() - exit - without resolving because model is dirty or being saved');
return;
}
@@ -314,7 +314,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}
private async resolveFromBuffer(buffer: ITextBufferFactory, options?: ITextFileResolveOptions): Promise<void> {
- this.trace('[text file model] resolveFromBuffer()');
+ this.trace('resolveFromBuffer()');
// Try to resolve metdata from disk
let mtime: number;
@@ -372,7 +372,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// Abort if someone else managed to resolve the model by now
let isNewModel = !this.isResolved();
if (!isNewModel) {
- this.trace('[text file model] resolveFromBackup() - exit - without resolving because previously new model got created meanwhile');
+ this.trace('resolveFromBackup() - exit - without resolving because previously new model got created meanwhile');
return true; // imply that resolving has happened in another operation
}
@@ -389,7 +389,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}
private async doResolveFromBackup(backup: IResolvedWorkingCopyBackup<IBackupMetaData>, encoding: string, options?: ITextFileResolveOptions): Promise<void> {
- this.trace('[text file model] doResolveFromBackup()');
+ this.trace('doResolveFromBackup()');
// Resolve with backup
this.resolveFromContent({
@@ -411,7 +411,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}
private async resolveFromFile(options?: ITextFileResolveOptions): Promise<void> {
- this.trace('[text file model] resolveFromFile()');
+ this.trace('resolveFromFile()');
const forceReadFromFile = options?.forceReadFromFile;
const allowBinary = this.isResolved() /* always allow if we resolved previously */ || options?.allowBinary;
@@ -438,7 +438,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// Return early if the model content has changed
// meanwhile to prevent loosing any changes
if (currentVersionId !== this.versionId) {
- this.trace('[text file model] resolveFromFile() - exit - without resolving because model content changed');
+ this.trace('resolveFromFile() - exit - without resolving because model content changed');
return;
}
@@ -475,11 +475,11 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}
private resolveFromContent(content: ITextFileStreamContent, dirty: boolean, options?: ITextFileResolveOptions): void {
- this.trace('[text file model] resolveFromContent() - enter');
+ this.trace('resolveFromContent() - enter');
// Return early if we are disposed
if (this.isDisposed()) {
- this.trace('[text file model] resolveFromContent() - exit - because model is disposed');
+ this.trace('resolveFromContent() - exit - because model is disposed');
return;
}
@@ -532,7 +532,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}
private doCreateTextModel(resource: URI, value: ITextBufferFactory): void {
- this.trace('[text file model] doCreateTextModel()');
+ this.trace('doCreateTextModel()');
// Create model
const textModel = this.createTextEditorModel(value, resource, this.preferredLanguageId);
@@ -545,7 +545,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}
private doUpdateTextModel(value: ITextBufferFactory): void {
- this.trace('[text file model] doUpdateTextModel()');
+ this.trace('doUpdateTextModel()');
// Update model value in a block that ignores content change events for dirty tracking
this.ignoreDirtyOnModelContentChange = true;
@@ -564,15 +564,15 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// Listen to text model events
this._register(model.onDidChangeContent(e => this.onModelContentChanged(model, e.isUndoing || e.isRedoing)));
- this._register(model.onDidChangeLanguage(e => this.onMaybeShouldChangeEncoding())); // detect possible encoding change via language specific settings
+ this._register(model.onDidChangeLanguage(() => this.onMaybeShouldChangeEncoding())); // detect possible encoding change via language specific settings
}
private onModelContentChanged(model: ITextModel, isUndoingOrRedoing: boolean): void {
- this.trace(`[text file model] onModelContentChanged() - enter`);
+ this.trace(`onModelContentChanged() - enter`);
// In any case increment the version id because it tracks the textual content state of the model at all times
this.versionId++;
- this.trace(`[text file model] onModelContentChanged() - new versionId ${this.versionId}`);
+ this.trace(`onModelContentChanged() - new versionId ${this.versionId}`);
// Remember when the user changed the model through a undo/redo operation.
// We need this information to throttle save participants to fix
@@ -589,7 +589,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// The contents changed as a matter of Undo and the version reached matches the saved one
// In this case we clear the dirty flag and emit a SAVED event to indicate this state.
if (model.getAlternativeVersionId() === this.bufferSavedVersionId) {
- this.trace('[text file model] onModelContentChanged() - model content changed back to last saved version');
+ this.trace('onModelContentChanged() - model content changed back to last saved version');
// Clear flags
const wasDirty = this.dirty;
@@ -603,7 +603,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// Otherwise the content has changed and we signal this as becoming dirty
else {
- this.trace('[text file model] onModelContentChanged() - model content changed and marked as dirty');
+ this.trace('onModelContentChanged() - model content changed and marked as dirty');
// Mark as dirty
this.setDirty(true);
@@ -707,7 +707,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}
if (this.isReadonly()) {
- this.trace('[text file model] save() - ignoring request for readonly resource');
+ this.trace('save() - ignoring request for readonly resource');
return false; // if model is readonly we do not attempt to save at all
}
@@ -716,15 +716,15 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
(this.hasState(TextFileEditorModelState.CONFLICT) || this.hasState(TextFileEditorModelState.ERROR)) &&
(options.reason === SaveReason.AUTO || options.reason === SaveReason.FOCUS_CHANGE || options.reason === SaveReason.WINDOW_CHANGE)
) {
- this.trace('[text file model] save() - ignoring auto save request for model that is in conflict or error');
+ this.trace('save() - ignoring auto save request for model that is in conflict or error');
return false; // if model is in save conflict or error, do not save unless save reason is explicit
}
// Actually do save and log
- this.trace('[text file model] save() - enter');
+ this.trace('save() - enter');
await this.doSave(options);
- this.trace('[text file model] save() - exit');
+ this.trace('save() - exit');
return this.hasState(TextFileEditorModelState.SAVED);
}
@@ -735,7 +735,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}
let versionId = this.versionId;
- this.trace(`[text file model] doSave(${versionId}) - enter with versionId ${versionId}`);
+ this.trace(`doSave(${versionId}) - enter with versionId ${versionId}`);
// Lookup any running pending save for this versionId and return it if found
//
@@ -743,7 +743,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// while the save was not yet finished to disk
//
if (this.saveSequentializer.hasPending(versionId)) {
- this.trace(`[text file model] doSave(${versionId}) - exit - found a pending save for versionId ${versionId}`);
+ this.trace(`doSave(${versionId}) - exit - found a pending save for versionId ${versionId}`);
return this.saveSequentializer.pending;
}
@@ -752,7 +752,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
//
// Scenario: user invoked save action even though the model is not dirty
if (!options.force && !this.dirty) {
- this.trace(`[text file model] doSave(${versionId}) - exit - because not dirty and/or versionId is different (this.isDirty: ${this.dirty}, this.versionId: ${this.versionId})`);
+ this.trace(`doSave(${versionId}) - exit - because not dirty and/or versionId is different (this.isDirty: ${this.dirty}, this.versionId: ${this.versionId})`);
return;
}
@@ -766,7 +766,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// while the first save has not returned yet.
//
if (this.saveSequentializer.hasPending()) {
- this.trace(`[text file model] doSave(${versionId}) - exit - because busy saving`);
+ this.trace(`doSave(${versionId}) - exit - because busy saving`);
// Indicate to the save sequentializer that we want to
// cancel the pending operation so that ours can run
@@ -862,7 +862,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// Save to Disk. We mark the save operation as currently pending with
// the latest versionId because it might have changed from a save
// participant triggering
- this.trace(`[text file model] doSave(${versionId}) - before write()`);
+ this.trace(`doSave(${versionId}) - before write()`);
const lastResolvedFileStat = assertIsDefined(this.lastResolvedFileStat);
const resolvedTextFileEditorModel = this;
return this.saveSequentializer.setPending(versionId, (async () => {
@@ -890,10 +890,10 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// Update dirty state unless model has changed meanwhile
if (versionId === this.versionId) {
- this.trace(`[text file model] handleSaveSuccess(${versionId}) - setting dirty to false because versionId did not change`);
+ this.trace(`handleSaveSuccess(${versionId}) - setting dirty to false because versionId did not change`);
this.setDirty(false);
} else {
- this.trace(`[text file model] handleSaveSuccess(${versionId}) - not setting dirty to false because versionId did change meanwhile`);
+ this.trace(`handleSaveSuccess(${versionId}) - not setting dirty to false because versionId did change meanwhile`);
}
// Update orphan state given save was successful
@@ -1019,15 +1019,27 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// (see https://github.com/microsoft/vscode/issues/127936)
if (this.hasEncodingSetExplicitly) {
+ this.trace('onMaybeShouldChangeEncoding() - ignoring because encoding was set explicitly');
+
return; // never change the user's choice of encoding
}
+ if (this.contentEncoding === UTF8_with_bom || this.contentEncoding === UTF16be || this.contentEncoding === UTF16le) {
+ this.trace('onMaybeShouldChangeEncoding() - ignoring because content encoding has a BOM');
+
+ return; // never change an encoding that we can detect 100% via BOMs
+ }
+
const { encoding } = await this.textFileService.encoding.getPreferredReadEncoding(this.resource);
if (typeof encoding !== 'string' || !this.isNewEncoding(encoding)) {
+ this.trace(`onMaybeShouldChangeEncoding() - ignoring because preferred encoding ${encoding} is not new`);
+
return; // return early if encoding is invalid or did not change
}
if (this.isDirty()) {
+ this.trace('onMaybeShouldChangeEncoding() - ignoring because model is dirty');
+
return; // return early to prevent accident saves in this case
}
@@ -1110,7 +1122,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
//#endregion
private trace(msg: string): void {
- this.logService.trace(msg, this.resource.toString());
+ this.logService.trace(`[text file model] ${msg}`, this.resource.toString());
}
override isResolved(): this is IResolvedTextFileEditorModel {
@@ -1122,7 +1134,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}
override dispose(): void {
- this.trace('[text file model] dispose()');
+ this.trace('dispose()');
this.inConflictMode = false;
this.inOrphanMode = false;