From 6501e63703d8e69521f9dc337ebc97f4f1d98fc8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 10 Apr 2019 10:20:43 +0200 Subject: [PATCH] Refactorings --- src/vs/workbench/browser/nodeless.main.ts | 31 +- .../browser/nodeless.simpleservices.ts | 451 +----------------- src/vs/workbench/browser/workbench.ts | 6 +- .../services/files2/browser/fileService2.ts | 78 +++ .../services/files2/common/fileService2.ts | 6 +- 5 files changed, 124 insertions(+), 448 deletions(-) create mode 100644 src/vs/workbench/services/files2/browser/fileService2.ts diff --git a/src/vs/workbench/browser/nodeless.main.ts b/src/vs/workbench/browser/nodeless.main.ts index adf847dde15..c4140e914da 100644 --- a/src/vs/workbench/browser/nodeless.main.ts +++ b/src/vs/workbench/browser/nodeless.main.ts @@ -8,8 +8,14 @@ import { domContentLoaded, addDisposableListener, EventType } from 'vs/base/brow import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { ILogService } from 'vs/platform/log/common/log'; import { Disposable } from 'vs/base/common/lifecycle'; -import { SimpleLogService } from 'vs/workbench/browser/nodeless.simpleservices'; +import { SimpleLogService, SimpleProductService, SimpleWorkbenchEnvironmentService } from 'vs/workbench/browser/nodeless.simpleservices'; import { Workbench } from 'vs/workbench/browser/workbench'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { IProductService } from 'vs/platform/product/common/product'; +import { RemoteAuthorityResolverService } from 'vs/platform/remote/browser/remoteAuthorityResolverService'; +import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; +import { IFileService } from 'vs/platform/files/common/files'; +import { FileService3 } from 'vs/workbench/services/files2/browser/fileService2'; class CodeRendererMain extends Disposable { @@ -42,14 +48,31 @@ class CodeRendererMain extends Disposable { private initServices(): { serviceCollection: ServiceCollection, logService: ILogService } { const serviceCollection = new ServiceCollection(); - const logService = new SimpleLogService(); - serviceCollection.set(ILogService, logService); - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // NOTE: DO NOT ADD ANY OTHER SERVICE INTO THE COLLECTION HERE. // CONTRIBUTE IT VIA WORKBENCH.MAIN.TS AND registerSingleton(). // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // Log + const logService = new SimpleLogService(); + serviceCollection.set(ILogService, logService); + + // Environment + const environmentService = new SimpleWorkbenchEnvironmentService(); + serviceCollection.set(IWorkbenchEnvironmentService, environmentService); + + // Product + const productService = new SimpleProductService(); + serviceCollection.set(IProductService, productService); + + // Remote + const remoteAuthorityResolverService = new RemoteAuthorityResolverService(); + serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService); + + // Files + const fileService = this._register(new FileService3(logService)); + serviceCollection.set(IFileService, fileService); + return { serviceCollection, logService }; } } diff --git a/src/vs/workbench/browser/nodeless.simpleservices.ts b/src/vs/workbench/browser/nodeless.simpleservices.ts index 06f81a6784b..be406d6967b 100644 --- a/src/vs/workbench/browser/nodeless.simpleservices.ts +++ b/src/vs/workbench/browser/nodeless.simpleservices.ts @@ -5,7 +5,7 @@ import { URI } from 'vs/base/common/uri'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; -import { ITextSnapshot, IFileStat, IContent, IFileService, IResourceEncodings, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IStreamContent, IUpdateContentOptions, snapshotToString, ICreateFileOptions, IResourceEncoding, IFileStatWithMetadata, FileSystemProviderCapabilities, IWriteFileOptions } from 'vs/platform/files/common/files'; +import { ITextSnapshot } from 'vs/platform/files/common/files'; import { ITextBufferFactory } from 'vs/editor/common/model'; import { createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel'; import { keys, ResourceMap } from 'vs/base/common/map'; @@ -17,7 +17,7 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService import { SimpleConfigurationService as StandaloneEditorConfigurationService, StandaloneKeybindingService, SimpleResourcePropertiesService } from 'vs/editor/standalone/browser/simpleServices'; import { IDownloadService } from 'vs/platform/download/common/download'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { IEnvironmentService, IExtensionHostDebugParams, IDebugParams } from 'vs/platform/environment/common/environment'; +import { IExtensionHostDebugParams, IDebugParams } from 'vs/platform/environment/common/environment'; import { IExtensionGalleryService, IQueryOptions, IGalleryExtension, InstallOperation, StatisticType, ITranslation, IGalleryExtensionVersion, IExtensionIdentifier, IReportedExtension, IExtensionManagementService, ILocalExtension, IGalleryMetadata, IExtensionTipsService, ExtensionRecommendationReason, IExtensionRecommendation, IExtensionEnablementService, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IPager } from 'vs/base/common/paging'; import { IExtensionManifest, ExtensionType, ExtensionIdentifier, IExtension } from 'vs/platform/extensions/common/extensions'; @@ -32,9 +32,7 @@ import { ILogService, LogLevel, ConsoleLogService } from 'vs/platform/log/common import { ShutdownReason, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IMenubarService, IMenubarData } from 'vs/platform/menubar/common/menubar'; import { IProductService } from 'vs/platform/product/common/product'; -import { IRemoteAuthorityResolverService, ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityResolver'; -import { joinPath, isEqualOrParent, isEqual, dirname } from 'vs/base/common/resources'; -import { basename } from 'vs/base/common/path'; +import { isEqualOrParent, isEqual } from 'vs/base/common/resources'; import { ISearchService, ITextQueryProps, ISearchProgressItem, ISearchComplete, IFileQueryProps, SearchProviderType, ISearchResultProvider, ITextQuery, IFileMatch, QueryType, FileMatch, pathIncludedInQuery } from 'vs/workbench/services/search/common/search'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -48,7 +46,7 @@ import { ITextMateService, IGrammar as ITextMategrammar } from 'vs/workbench/ser import { LanguageId, TokenizationRegistry } from 'vs/editor/common/modes'; import { IUpdateService, State } from 'vs/platform/update/common/update'; import { IWindowConfiguration, IPath, IPathsToWaitFor, IWindowService, INativeOpenDialogOptions, IEnterWorkspaceResult, IURIToOpen, IMessageBoxResult, IWindowsService, IOpenSettings } from 'vs/platform/windows/common/windows'; -import { IProcessEnvironment, isWindows } from 'vs/base/common/platform'; +import { IProcessEnvironment } from 'vs/base/common/platform'; import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, IWorkspaceFolderCreationData, isSingleFolderWorkspaceIdentifier, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { ExportData } from 'vs/base/common/performance'; import { IRecentlyOpened, IRecent } from 'vs/platform/history/common/history'; @@ -59,12 +57,13 @@ import { ITextResourcePropertiesService } from 'vs/editor/common/services/resour import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { Color, RGBA } from 'vs/base/common/color'; -import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment'; -import { IRemoteAgentService, IRemoteAgentConnection } from 'vs/workbench/services/remote/common/remoteAgentService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { VSBuffer, VSBufferReadable } from 'vs/base/common/buffer'; -export const workspaceResource = URI.file(isWindows ? 'C:\\simpleWorkspace' : '/simpleWorkspace'); +export const workspaceResource = URI.from({ + scheme: 'vscode-remote', + authority: document.location.host, + path: (self).USER_HOME_DIR || '/' +}); //#region Backup File @@ -227,7 +226,7 @@ registerSingleton(IDownloadService, SimpleDownloadService, true); //#region Environment -export class SimpleEnvironmentService implements IWorkbenchEnvironmentService { +export class SimpleWorkbenchEnvironmentService implements IWorkbenchEnvironmentService { configuration: IWindowConfiguration = new SimpleWindowConfiguration(); untitledWorkspacesHome: URI; extensionTestsLocationURI?: URI; @@ -278,7 +277,6 @@ export class SimpleEnvironmentService implements IWorkbenchEnvironmentService { driverVerbose: boolean; } -registerSingleton(IEnvironmentService, SimpleEnvironmentService); //#endregion @@ -670,433 +668,6 @@ export class SimpleProductService implements IProductService { enableTelemetry: boolean = false; } -registerSingleton(IProductService, SimpleProductService, true); - -//#endregion - -//#region Remote Agent - -export class SimpleRemoteAgentService implements IRemoteAgentService { - - _serviceBrand: any; - - getConnection(): IRemoteAgentConnection | null { - return null; - } - - getEnvironment(): Promise { - return Promise.resolve(null); - } -} - -registerSingleton(IRemoteAgentService, SimpleRemoteAgentService); - -//#endregion - -//#region Remote Authority Resolver - -export class SimpleRemoteAuthorityResolverService implements IRemoteAuthorityResolverService { - - _serviceBrand: any; - - resolveAuthority(authority: string): Promise { - // @ts-ignore - return Promise.resolve(undefined); - } - - clearResolvedAuthority(authority: string): void { } - - setResolvedAuthority(resolvedAuthority: ResolvedAuthority): void { } - - setResolvedAuthorityError(authority: string, err: any): void { } -} - -registerSingleton(IRemoteAuthorityResolverService, SimpleRemoteAuthorityResolverService, true); - -//#endregion - -//#region File Servie - -const fileMap: ResourceMap = new ResourceMap(); -const contentMap: ResourceMap = new ResourceMap(); -initFakeFileSystem(); - -export class SimpleRemoteFileService implements IFileService { - - _serviceBrand: any; - - encoding: IResourceEncodings; - - readonly onFileChanges = Event.None; - readonly onAfterOperation = Event.None; - readonly onDidChangeFileSystemProviderRegistrations = Event.None; - readonly onWillActivateFileSystemProvider = Event.None; - readonly onError = Event.None; - - resolve(resource: URI, options?: IResolveFileOptions): Promise { - // @ts-ignore - return Promise.resolve(fileMap.get(resource)); - } - - resolveAll(toResolve: { resource: URI, options?: IResolveFileOptions }[]): Promise { - return Promise.all(toResolve.map(resourceAndOption => this.resolve(resourceAndOption.resource, resourceAndOption.options))).then(stats => stats.map(stat => ({ stat, success: true }))); - } - - exists(resource: URI): Promise { - return Promise.resolve(fileMap.has(resource)); - } - - resolveContent(resource: URI, _options?: IResolveContentOptions): Promise { - // @ts-ignore - return Promise.resolve(contentMap.get(resource)); - } - - resolveStreamContent(resource: URI, _options?: IResolveContentOptions): Promise { - return Promise.resolve(contentMap.get(resource)).then(content => { - return { - // @ts-ignore - resource: content.resource, - value: { - on: (event: string, callback: Function): void => { - if (event === 'data') { - // @ts-ignore - callback(content.value); - } - - if (event === 'end') { - callback(); - } - } - }, - // @ts-ignore - etag: content.etag, - // @ts-ignore - encoding: content.encoding, - // @ts-ignore - mtime: content.mtime, - // @ts-ignore - name: content.name, - // @ts-ignore - size: content.size - }; - }); - } - - updateContent(resource: URI, value: string | ITextSnapshot, _options?: IUpdateContentOptions): Promise { - // @ts-ignore - return Promise.resolve(fileMap.get(resource)).then(file => { - const content = contentMap.get(resource); - - if (typeof value === 'string') { - // @ts-ignore - content.value = value; - } else { - // @ts-ignore - content.value = snapshotToString(value); - } - - return file; - }); - } - - writeFile(resource: URI, bufferOrReadable: VSBuffer | VSBufferReadable, options?: IWriteFileOptions): Promise { - return this.updateContent(resource, bufferOrReadable.toString(), options); - } - - move(_source: URI, _target: URI, _overwrite?: boolean): Promise { return Promise.resolve(null!); } - - copy(_source: URI, _target: URI, _overwrite?: boolean): Promise { - const parent = fileMap.get(dirname(_target)); - if (!parent) { - return Promise.resolve(undefined); - } - - return this.resolveContent(_source).then(content => { - return Promise.resolve(createFile(parent, basename(_target.path), content.value)); - }); - } - - createFile(_resource: URI, _content?: string, _options?: ICreateFileOptions): Promise { - const parent = fileMap.get(dirname(_resource)); - if (!parent) { - return Promise.reject(new Error(`Unable to create file in ${dirname(_resource).path}`)); - } - - return Promise.resolve(createFile(parent, basename(_resource.path))); - } - - createFile2(_resource: URI, _content?: VSBuffer, _options?: ICreateFileOptions): Promise { - return this.createFile(_resource, undefined, _options); - } - - createFolder(_resource: URI): Promise { - const parent = fileMap.get(dirname(_resource)); - if (!parent) { - return Promise.reject(new Error(`Unable to create folder in ${dirname(_resource).path}`)); - } - - return Promise.resolve(createFolder(parent, basename(_resource.path))); - } - - registerProvider() { return { dispose() { } }; } - - activateProvider(_scheme: string): Promise { return Promise.resolve(undefined); } - - canHandleResource(resource: URI): boolean { return resource.scheme === 'file'; } - - hasCapability(resource: URI, capability: FileSystemProviderCapabilities): boolean { return false; } - - del(_resource: URI, _options?: { useTrash?: boolean, recursive?: boolean }): Promise { return Promise.resolve(); } - - watch(_resource: URI): IDisposable { return Disposable.None; } - - getWriteEncoding(_resource: URI): IResourceEncoding { return { encoding: 'utf8', hasBOM: false }; } - - dispose(): void { } -} - -function createFile(parent: IFileStat, name: string, content: string = ''): IFileStatWithMetadata { - const file: IFileStatWithMetadata = { - resource: joinPath(parent.resource, name), - etag: Date.now().toString(), - mtime: Date.now(), - isDirectory: false, - name, - size: -1 - }; - - // @ts-ignore - parent.children.push(file); - - fileMap.set(file.resource, file); - - contentMap.set(file.resource, { - resource: joinPath(parent.resource, name), - etag: Date.now().toString(), - mtime: Date.now(), - value: content, - encoding: 'utf8', - name - } as IContent); - - return file; -} - -function createFolder(parent: IFileStat, name: string): IFileStatWithMetadata { - const folder: IFileStatWithMetadata = { - resource: joinPath(parent.resource, name), - etag: Date.now().toString(), - mtime: Date.now(), - isDirectory: true, - name, - size: 0, - children: [] - }; - - // @ts-ignore - parent.children.push(folder); - - fileMap.set(folder.resource, folder); - - return folder; -} - -function initFakeFileSystem(): void { - - const root: IFileStat = { - resource: workspaceResource, - etag: Date.now().toString(), - mtime: Date.now(), - isDirectory: true, - name: basename(workspaceResource.fsPath), - children: [], - size: 0 - }; - - fileMap.set(root.resource, root); - - createFile(root, '.gitignore', `out -node_modules -.vscode-test/ -*.vsix -`); - createFile(root, '.vscodeignore', `.vscode/** -.vscode-test/** -out/test/** -src/** -.gitignore -vsc-extension-quickstart.md -**/tsconfig.json -**/tslint.json -**/*.map -**/*.ts`); - createFile(root, 'CHANGELOG.md', `# Change Log -All notable changes to the "test-ts" extension will be documented in this file. - -Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. - -## [Unreleased] -- Initial release`); - createFile(root, 'package.json', `{ - "name": "test-ts", - "displayName": "test-ts", - "description": "", - "version": "0.0.1", - "engines": { - "vscode": "^1.31.0" - }, - "categories": [ - "Other" - ], - "activationEvents": [ - "onCommand:extension.helloWorld" - ], - "main": "./out/extension.js", - "contributes": { - "commands": [ - { - "command": "extension.helloWorld", - "title": "Hello World" - } - ] - }, - "scripts": { - "vscode:prepublish": "npm run compile", - "compile": "tsc -p ./", - "watch": "tsc -watch -p ./", - "postinstall": "node ./node_modules/vscode/bin/install", - "test": "npm run compile && node ./node_modules/vscode/bin/test" - }, - "devDependencies": { - "typescript": "^3.3.1", - "vscode": "^1.1.28", - "tslint": "^5.12.1", - "@types/node": "^8.10.25", - "@types/mocha": "^2.2.42" - } -} -`); - createFile(root, 'tsconfig.json', `{ - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": [ - "es6" - ], - "sourceMap": true, - "rootDir": "src", - "strict": true /* enable all strict type-checking options */ - /* Additional Checks */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - }, - "exclude": [ - "node_modules", - ".vscode-test" - ] -} -`); - createFile(root, 'tslint.json', `{ - "rules": { - "no-string-throw": true, - "no-unused-expression": true, - "no-duplicate-variable": true, - "curly": true, - "class-name": true, - "semicolon": [ - true, - "always" - ], - "triple-equals": true - }, - "defaultSeverity": "warning" -} -`); - - const src = createFolder(root, 'src'); - createFile(src, 'extension.ts', `// The module 'vscode' contains the VS Code extensibility API -// Import the module and reference it with the alias vscode in your code below -import * as vscode from 'vscode'; - -// this method is called when your extension is activated -// your extension is activated the very first time the command is executed -export function activate(context: vscode.ExtensionContext) { - - // Use the console to output diagnostic information (console.log) and errors (console.error) - // This line of code will only be executed once when your extension is activated - console.log('Congratulations, your extension "test-ts" is now active!'); - - // The command has been defined in the package.json file - // Now provide the implementation of the command with registerCommand - // The commandId parameter must match the command field in package.json - let disposable = vscode.commands.registerCommand('extension.helloWorld', () => { - // The code you place here will be executed every time your command is executed - - // Display a message box to the user - vscode.window.showInformationMessage('Hello World!'); - }); - - context.subscriptions.push(disposable); -} - -// this method is called when your extension is deactivated -export function deactivate() {} -`); - - const test = createFolder(src, 'test'); - - createFile(test, 'extension.test.ts', `// -// Note: This example test is leveraging the Mocha test framework. -// Please refer to their documentation on https://mochajs.org/ for help. -// - -// The module 'assert' provides assertion methods from node -import * as assert from 'assert'; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it -// import * as vscode from 'vscode'; -// import * as myExtension from '../extension'; - -// Defines a Mocha test suite to group tests of similar kind together -suite("Extension Tests", function () { - - // Defines a Mocha unit test - test("Something 1", function() { - assert.equal(-1, [1, 2, 3].indexOf(5)); - assert.equal(-1, [1, 2, 3].indexOf(0)); - }); -});`); - - createFile(test, 'index.ts', `// -// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING -// -// This file is providing the test runner to use when running extension tests. -// By default the test runner in use is Mocha based. -// -// You can provide your own test runner if you want to override it by exporting -// a function run(testRoot: string, clb: (error:Error) => void) that the extension -// host can call to run the tests. The test runner is expected to use console.log -// to report the results back to the caller. When the tests are finished, return -// a possible error to the callback or null if none. - -import * as testRunner from 'vscode/lib/testrunner'; - -// You can directly control Mocha options by configuring the test runner below -// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options -// for more info -testRunner.configure({ - ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) - useColors: true // colored output from test results -}); - -module.exports = testRunner;`); -} - -registerSingleton(IFileService, SimpleRemoteFileService); - //#endregion //#region Request @@ -1791,7 +1362,7 @@ export class SimpleWorkspaceService implements IWorkspaceContextService { constructor() { this.workspace = new Workspace( workspaceResource.toString(), - toWorkspaceFolders([{ path: workspaceResource.fsPath }]) + toWorkspaceFolders([{ uri: workspaceResource.toString() }]) ); } diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts index 0f5f3e095e7..a802bb02b0b 100644 --- a/src/vs/workbench/browser/workbench.ts +++ b/src/vs/workbench/browser/workbench.ts @@ -193,7 +193,11 @@ export class Workbench extends Layout { // TODO@Ben legacy file service const fileService = accessor.get(IFileService) as any; if (typeof fileService.setLegacyService === 'function') { - fileService.setLegacyService(accessor.get(ILegacyFileService)); + try { + fileService.setLegacyService(accessor.get(ILegacyFileService)); + } catch (error) { + //ignore, legacy file service might not be registered + } } // TODO@Sandeep debt around cyclic dependencies diff --git a/src/vs/workbench/services/files2/browser/fileService2.ts b/src/vs/workbench/services/files2/browser/fileService2.ts new file mode 100644 index 00000000000..725b40098be --- /dev/null +++ b/src/vs/workbench/services/files2/browser/fileService2.ts @@ -0,0 +1,78 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { FileService2 } from 'vs/workbench/services/files2/common/fileService2'; +import { URI } from 'vs/base/common/uri'; +import { IResolveContentOptions, IStreamContent, IStringStream, IContent, IFileSystemProvider, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; +import { basename } from 'vs/base/common/resources'; +import { VSBuffer } from 'vs/base/common/buffer'; +import { localize } from 'vs/nls'; + +// TODO@ben temporary for testing only +export class FileService3 extends FileService2 { + + async resolveContent(resource: URI, options?: IResolveContentOptions): Promise { + return this.resolveStreamContent(resource, options).then(streamContent => { + return new Promise((resolve, reject) => { + + const result: IContent = { + resource: streamContent.resource, + name: streamContent.name, + mtime: streamContent.mtime, + etag: streamContent.etag, + encoding: streamContent.encoding, + isReadonly: streamContent.isReadonly, + size: streamContent.size, + value: '' + }; + + streamContent.value.on('data', chunk => result.value += chunk); + streamContent.value.on('error', err => reject(err)); + streamContent.value.on('end', () => resolve(result)); + + return result; + }); + }); + } + + async resolveStreamContent(resource: URI, options?: IResolveContentOptions): Promise { + const provider = await this.withProvider(resource); + if (provider && provider.readFile) { + const listeners: { [type: string]: any[]; } = Object.create(null); + const stringStream: IStringStream = { + on(event: string, callback: any): void { + listeners[event] = listeners[event] || []; + listeners[event].push(callback); + } + }; + const stat = await this.resolve(resource, { resolveMetadata: true }); + + const r: IStreamContent = { + mtime: stat.mtime, + size: stat.size, + etag: stat.etag, + value: stringStream, + resource: resource, + encoding: 'utf8', + name: basename(resource) + }; + + provider.readFile(resource).then((contents) => { + const str = VSBuffer.wrap(contents).toString(); + listeners['data'].forEach((listener) => listener(str)); + listeners['end'].forEach((listener) => listener()); + }); + + return r; + } + + return super.resolveStreamContent(resource, options); + } + + protected throwIfFileSystemIsReadonly(provider: IFileSystemProvider): IFileSystemProvider { + // we really do not want to allow for changes currently + throw new FileOperationError(localize('err.readonly', "Resource can not be modified."), FileOperationResult.FILE_PERMISSION_DENIED); + } +} \ No newline at end of file diff --git a/src/vs/workbench/services/files2/common/fileService2.ts b/src/vs/workbench/services/files2/common/fileService2.ts index 194a50b57f3..07d0971a211 100644 --- a/src/vs/workbench/services/files2/common/fileService2.ts +++ b/src/vs/workbench/services/files2/common/fileService2.ts @@ -129,7 +129,7 @@ export class FileService2 extends Disposable implements IFileService { return !!(provider && (provider.capabilities & capability)); } - private async withProvider(resource: URI): Promise { + protected async withProvider(resource: URI): Promise { // Assert path is absolute if (!isAbsolutePath(resource)) { @@ -378,7 +378,7 @@ export class FileService2 extends Disposable implements IFileService { return this.joinOnLegacy.then(legacy => legacy.resolveContent(resource, options)); } - resolveStreamContent(resource: URI, options?: IResolveContentOptions): Promise { + async resolveStreamContent(resource: URI, options?: IResolveContentOptions): Promise { return this.joinOnLegacy.then(legacy => legacy.resolveStreamContent(resource, options)); } @@ -836,7 +836,7 @@ export class FileService2 extends Disposable implements IFileService { } } - private throwIfFileSystemIsReadonly(provider: IFileSystemProvider): IFileSystemProvider { + protected throwIfFileSystemIsReadonly(provider: IFileSystemProvider): IFileSystemProvider { if (provider.capabilities & FileSystemProviderCapabilities.Readonly) { throw new FileOperationError(localize('err.readonly', "Resource can not be modified."), FileOperationResult.FILE_PERMISSION_DENIED); } -- GitLab