diff --git a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts index 29b277207b22f..8ec1880198aa1 100644 --- a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts +++ b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts @@ -15,7 +15,7 @@ import { EncodingMode, ConfirmResult, EditorInput, IFileEditorInput, ITextEditor import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; -import { ITextFileService, AutoSaveMode, ModelState, TextFileModelChangeEvent } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileService, AutoSaveMode, ModelState, TextFileModelChangeEvent, LoadReason } from 'vs/workbench/services/textfile/common/textfiles'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IReference } from 'vs/base/common/lifecycle'; @@ -260,7 +260,8 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { return this.textFileService.models.loadOrCreate(this.resource, { encoding: this.preferredEncoding, reload: { async: true }, // trigger a reload of the model if it exists already but do not wait to show the model - allowBinary: this.forceOpenAsText + allowBinary: this.forceOpenAsText, + reason: LoadReason.EDITOR }).then(model => { // This is a bit ugly, because we first resolve the model and then resolve a model reference. the reason being that binary diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index f9e41489ea97d..9274591570983 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -13,11 +13,11 @@ import { guessMimeTypes } from 'vs/base/common/mime'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import URI from 'vs/base/common/uri'; import * as diagnostics from 'vs/base/common/diagnostics'; -import * as types from 'vs/base/common/types'; +import { isUndefinedOrNull } from 'vs/base/common/types'; import { IMode } from 'vs/editor/common/modes'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent, ILoadOptions } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent, ILoadOptions, LoadReason } from 'vs/workbench/services/textfile/common/textfiles'; import { EncodingMode } from 'vs/workbench/common/editor'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; @@ -275,7 +275,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil isReadonly: false }; - return this.loadWithContent(content, backup); + return this.loadWithContent(content, options, backup); } // Otherwise load from file @@ -313,7 +313,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // Guard against the model having changed in the meantime if (currentVersionId === this.versionId) { - return this.loadWithContent(content); + return this.loadWithContent(content, options); } return this; @@ -346,7 +346,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil }); } - private loadWithContent(content: IRawTextContent, backup?: URI): TPromise { + private loadWithContent(content: IRawTextContent, options?: ILoadOptions, backup?: URI): TPromise { return this.doLoadWithContent(content, backup).then(model => { // Telemetry: We log the fileGet telemetry event after the model has been loaded to ensure a good mimetype @@ -360,10 +360,16 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil "fileGet" : { "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "path": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "path": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "reason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ - this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: path.extname(this.resource.fsPath), path: this.hashService.createSHA1(this.resource.fsPath) }); + this.telemetryService.publicLog('fileGet', { + mimeType: guessMimeTypes(this.resource.fsPath).join(', '), + ext: path.extname(this.resource.fsPath), + path: this.hashService.createSHA1(this.resource.fsPath), + reason: options && options.reason ? options.reason : LoadReason.OTHER + }); } return model; @@ -592,7 +598,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } private doSave(versionId: number, options: ISaveOptions): TPromise { - if (types.isUndefinedOrNull(options.reason)) { + if (isUndefinedOrNull(options.reason)) { options.reason = SaveReason.EXPLICIT; } @@ -718,10 +724,15 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil /* __GDPR__ "filePUT" : { "mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "reason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ - this.telemetryService.publicLog('filePUT', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: path.extname(this.lastResolvedDiskStat.resource.fsPath) }); + this.telemetryService.publicLog('filePUT', { + mimeType: guessMimeTypes(this.resource.fsPath).join(', '), + ext: path.extname(this.resource.fsPath), + reason: options.reason + }); } // Update dirty state unless model has changed meanwhile @@ -761,6 +772,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } private isSettingsFile(): boolean { + if (path.extname(this.resource.fsPath) !== '.json') { + return false; + } // Check for global settings file if (path.isEqual(this.resource.fsPath, this.environmentService.appSettingsPath, !isLinux)) { @@ -940,7 +954,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } isResolved(): boolean { - return !types.isUndefinedOrNull(this.lastResolvedDiskStat); + return !isUndefinedOrNull(this.lastResolvedDiskStat); } isReadonly(): boolean { diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts b/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts index 32e0164ecaef2..c8fbce69d0a3f 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts @@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { dispose, IDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { ITextFileEditorModel, ITextFileEditorModelManager, TextFileModelChangeEvent, StateChange, IModelLoadOrCreateOptions, ILoadOptions } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileEditorModel, ITextFileEditorModelManager, TextFileModelChangeEvent, StateChange, IModelLoadOrCreateOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ResourceMap } from 'vs/base/common/map'; @@ -132,11 +132,6 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE return pendingLoad; } - let modelLoadOptions: ILoadOptions; - if (options && options.allowBinary) { - modelLoadOptions = { allowBinary: true }; - } - let modelPromise: TPromise; // Model exists @@ -152,7 +147,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE // sync reload: do not return until model reloaded else { - modelPromise = model.load(modelLoadOptions); + modelPromise = model.load(options); } } else { modelPromise = TPromise.as(model); @@ -162,7 +157,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE // Model does not exist else { model = this.instantiationService.createInstance(TextFileEditorModel, resource, options ? options.encoding : void 0); - modelPromise = model.load(modelLoadOptions); + modelPromise = model.load(options); // Install state change listener this.mapResourceToStateChangeListener.set(resource, model.onDidStateChange(state => { diff --git a/src/vs/workbench/services/textfile/common/textfiles.ts b/src/vs/workbench/services/textfile/common/textfiles.ts index 737fbaed9c4cb..132e8b15c477c 100644 --- a/src/vs/workbench/services/textfile/common/textfiles.ts +++ b/src/vs/workbench/services/textfile/common/textfiles.ts @@ -123,6 +123,12 @@ export enum SaveReason { WINDOW_CHANGE = 4 } +export enum LoadReason { + EDITOR = 1, + REFERENCE = 2, + OTHER = 3 +} + export const ITextFileService = createDecorator(TEXT_FILE_SERVICE_ID); export interface IRawTextContent extends IBaseStat { @@ -140,6 +146,10 @@ export interface IRawTextContent extends IBaseStat { export interface IModelLoadOrCreateOptions { + /** + * Context why the model is being loaded or created. + */ + reason?: LoadReason; /** * The encoding to use when resolving the model text content. @@ -210,6 +220,11 @@ export interface ILoadOptions { * Allow to load a model even if we think it is a binary file. */ allowBinary?: boolean; + + /** + * Context why the model is being loaded. + */ + reason?: LoadReason; } export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport { diff --git a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts index 792ade9778b08..c7e655da6e1da 100644 --- a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts +++ b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts @@ -12,7 +12,7 @@ import { ITextModel } from 'vs/editor/common/model'; import { IDisposable, toDisposable, IReference, ReferenceCollection, ImmortalReference } from 'vs/base/common/lifecycle'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; -import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileService, LoadReason } from 'vs/workbench/services/textfile/common/textfiles'; import * as network from 'vs/base/common/network'; import { ITextModelService, ITextModelContentProvider, ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; @@ -34,7 +34,7 @@ class ResourceModelCollection extends ReferenceCollection { const resource = URI.parse(key); if (this.fileService.canHandleResource(resource)) { - return this.textFileService.models.loadOrCreate(resource); + return this.textFileService.models.loadOrCreate(resource, { reason: LoadReason.REFERENCE }); } return this.resolveTextModelContent(key).then(() => this.instantiationService.createInstance(ResourceEditorModel, resource));