diff --git a/fsprovider-sample/src/extension.ts b/fsprovider-sample/src/extension.ts index f3c3cdef..d96fea37 100644 --- a/fsprovider-sample/src/extension.ts +++ b/fsprovider-sample/src/extension.ts @@ -6,7 +6,7 @@ import { MemFS } from './fileSystemProvider'; export function activate(context: vscode.ExtensionContext) { const memFs = new MemFS(); - const registration = vscode.workspace.registerFileSystemProvider2('memfs', memFs, { isCaseSensitive: true }); + const registration = vscode.workspace.registerFileSystemProvider('memfs', memFs, { isCaseSensitive: true }); let initialized = false; vscode.commands.registerCommand('memfs.reset', _ => { diff --git a/fsprovider-sample/src/fileSystemProvider.ts b/fsprovider-sample/src/fileSystemProvider.ts index 806e334b..889d05ca 100644 --- a/fsprovider-sample/src/fileSystemProvider.ts +++ b/fsprovider-sample/src/fileSystemProvider.ts @@ -48,28 +48,28 @@ class Directory { type Entry = File | Directory; -export class MemFS implements vscode.FileSystemProvider2 { +export class MemFS implements vscode.FileSystemProvider { _version: 9 = 9; private _root = new Directory(''); private _data = new WeakMap(); - private _emitter = new vscode.EventEmitter(); + private _emitter = new vscode.EventEmitter(); - readonly onDidChangeFile: vscode.Event = this._emitter.event; + readonly onDidChangeFile: vscode.Event = this._emitter.event; watch(resource: vscode.Uri, opts): vscode.Disposable { // ignore, fires for all changes... return new vscode.Disposable(() => { }); } - stat(uri: vscode.Uri): vscode.FileStat2 { + stat(uri: vscode.Uri): vscode.FileStat { return this._lookup(uri); } - readDirectory(uri: vscode.Uri): [string, vscode.FileStat2][] { + readDirectory(uri: vscode.Uri): [string, vscode.FileStat][] { const entry = this._lookupDir(uri); - let result: [string, vscode.FileStat2][] = []; + let result: [string, vscode.FileStat][] = []; for (const [name, child] of entry.entries) { result.push([name, child]); } @@ -94,15 +94,15 @@ export class MemFS implements vscode.FileSystemProvider2 { if (!entry) { entry = new File(basename); parent.entries.set(basename, entry); - this._fireSoon({ type: vscode.FileChangeType2.Created, uri }); + this._fireSoon({ type: vscode.FileChangeType.Created, uri }); } entry.mtime = Date.now(); entry.size = content.byteLength; this._data.set(entry, content); - this._fireSoon({ type: vscode.FileChangeType2.Changed, uri }); + this._fireSoon({ type: vscode.FileChangeType.Changed, uri }); } - rename(oldUri: vscode.Uri, newUri: vscode.Uri): vscode.FileStat2 { + rename(oldUri: vscode.Uri, newUri: vscode.Uri): vscode.FileStat { let entry = this._lookup(oldUri); let oldParent = this._lookupContainer(oldUri); @@ -114,8 +114,8 @@ export class MemFS implements vscode.FileSystemProvider2 { newParent.entries.set(newName, entry); this._fireSoon( - { type: vscode.FileChangeType2.Deleted, uri: oldUri }, - { type: vscode.FileChangeType2.Created, uri: newUri } + { type: vscode.FileChangeType.Deleted, uri: oldUri }, + { type: vscode.FileChangeType.Created, uri: newUri } ); return entry; } @@ -130,10 +130,10 @@ export class MemFS implements vscode.FileSystemProvider2 { parent.entries.delete(basename); parent.mtime = Date.now(); parent.size -= 1; - this._fireSoon({ type: vscode.FileChangeType2.Changed, uri: dirname }, { uri, type: vscode.FileChangeType2.Deleted }); + this._fireSoon({ type: vscode.FileChangeType.Changed, uri: dirname }, { uri, type: vscode.FileChangeType.Deleted }); } - createDirectory(uri: vscode.Uri): vscode.FileStat2 { + createDirectory(uri: vscode.Uri): vscode.FileStat { let basename = path.posix.basename(uri.path); let dirname = uri.with({ path: path.posix.dirname(uri.path) }); let parent = this._lookupDir(dirname); @@ -142,7 +142,7 @@ export class MemFS implements vscode.FileSystemProvider2 { parent.entries.set(entry.name, entry); parent.mtime = Date.now(); parent.size += 1; - this._fireSoon({ type: vscode.FileChangeType2.Changed, uri: dirname }, { type: vscode.FileChangeType2.Created, uri }); + this._fireSoon({ type: vscode.FileChangeType.Changed, uri: dirname }, { type: vscode.FileChangeType.Created, uri }); return entry; } @@ -182,15 +182,15 @@ export class MemFS implements vscode.FileSystemProvider2 { // --- events - private _bufferedEvents: vscode.FileChange2[] = []; + private _bufferedEvents: vscode.FileChangeEvent[] = []; private _fireSoonHandle: NodeJS.Timer; - private _fireSoon(...events: vscode.FileChange2[]): void { + private _fireSoon(...events: vscode.FileChangeEvent[]): void { this._bufferedEvents.push(...events); clearTimeout(this._fireSoonHandle); this._fireSoonHandle = setTimeout(() => { this._emitter.fire(this._bufferedEvents); this._bufferedEvents.length = 0; - }, 25); + }, 5); } } diff --git a/fsprovider-sample/src/vscode.proposed.d.ts b/fsprovider-sample/src/vscode.proposed.d.ts index 8158008c..4015a72c 100644 --- a/fsprovider-sample/src/vscode.proposed.d.ts +++ b/fsprovider-sample/src/vscode.proposed.d.ts @@ -13,86 +13,40 @@ declare module 'vscode' { //#region Joh: file system provider (OLD) - export enum FileChangeType { + export enum DeprecatedFileChangeType { Updated = 0, Added = 1, Deleted = 2 } - - export interface FileChange { - type: FileChangeType; + export interface DeprecatedFileChange { + type: DeprecatedFileChangeType; resource: Uri; } - - export enum FileType { + export enum DeprecatedFileType { File = 0, Dir = 1, Symlink = 2 } - - export interface FileStat { + export interface DeprecatedFileStat { id: number | string; mtime: number; - // atime: number; size: number; - type: FileType; + type: DeprecatedFileType; } - - // todo@joh discover files etc - // todo@joh CancellationToken everywhere - // todo@joh add open/close calls? - export interface FileSystemProvider { - - readonly onDidChange?: Event; - - // more... - // @deprecated - will go away - utimes(resource: Uri, mtime: number, atime: number): Thenable; - - stat(resource: Uri): Thenable; - + export interface DeprecatedFileSystemProvider { + readonly onDidChange?: Event; + utimes(resource: Uri, mtime: number, atime: number): Thenable; + stat(resource: Uri): Thenable; read(resource: Uri, offset: number, length: number, progress: Progress): Thenable; - - // todo@joh - have an option to create iff not exist - // todo@remote - // offset - byte offset to start - // count - number of bytes to write - // Thenable - number of bytes actually written write(resource: Uri, content: Uint8Array): Thenable; - - // todo@remote - // Thenable - move(resource: Uri, target: Uri): Thenable; - - // todo@remote - // helps with performance bigly - // copy?(from: Uri, to: Uri): Thenable; - - // todo@remote - // Thenable - mkdir(resource: Uri): Thenable; - - readdir(resource: Uri): Thenable<[Uri, FileStat][]>; - - // todo@remote - // ? merge both - // ? recursive del + move(resource: Uri, target: Uri): Thenable; + mkdir(resource: Uri): Thenable; + readdir(resource: Uri): Thenable<[Uri, DeprecatedFileStat][]>; rmdir(resource: Uri): Thenable; unlink(resource: Uri): Thenable; - - // todo@remote - // create(resource: Uri): Thenable; } - - export type DeprecatedFileChangeType = FileChangeType; - export type DeprecatedFileType = FileType; - export type DeprecatedFileChange = FileChange; - export type DeprecatedFileStat = FileStat; - export type DeprecatedFileSystemProvider = FileSystemProvider; - export namespace workspace { export function registerDeprecatedFileSystemProvider(scheme: string, provider: DeprecatedFileSystemProvider): Disposable; - export function registerFileSystemProvider(scheme: string, provider: FileSystemProvider, newProvider?: FileSystemProvider2): Disposable; } //#endregion @@ -100,39 +54,115 @@ declare module 'vscode' { //#region Joh: file system provider (new) /** + * A type that filesystem providers should use to signal errors. * + * This class has factory methods for common error-cases, like `EntryNotFound` when + * a file or folder doesn't exist, use them like so: `throw vscode.FileSystemError.EntryNotFound(someUri);` */ export class FileSystemError extends Error { - static EntryExists(message?: string): FileSystemError; - static EntryNotFound(message?: string): FileSystemError; - static EntryNotADirectory(message?: string): FileSystemError; - static EntryIsADirectory(message?: string): FileSystemError; + /** + * Create an error to signal that a file or folder wasn't found. + * @param messageOrUri Message or uri. + */ + static EntryNotFound(messageOrUri?: string | Uri): FileSystemError; - constructor(message?: string); + /** + * Create an error to signal that a file or folder already exists, e.g. when + * creating but not overwriting a file. + * @param messageOrUri Message or uri. + */ + static EntryExists(messageOrUri?: string | Uri): FileSystemError; + + /** + * Create an error to signal that a file is not a folder. + * @param messageOrUri Message or uri. + */ + static EntryNotADirectory(messageOrUri?: string | Uri): FileSystemError; + + /** + * Create an error to signal that a file is a folder. + * @param messageOrUri Message or uri. + */ + static EntryIsADirectory(messageOrUri?: string | Uri): FileSystemError; + + /** + * Creates a new filesystem error. + * + * @param messageOrUri Message or uri. + */ + constructor(messageOrUri?: string | Uri); } - export enum FileChangeType2 { + /** + * Enumeration of file change types. + */ + export enum FileChangeType { + + /** + * The contents or metadata of a file have changed. + */ Changed = 1, + + /** + * A file has been created. + */ Created = 2, + + /** + * A file has been deleted. + */ Deleted = 3, } - export interface FileChange2 { - type: FileChangeType2; + /** + * The event filesystem providers must use to signal a file change. + */ + export interface FileChangeEvent { + + /** + * The type of change. + */ + type: FileChangeType; + + /** + * The uri of the file that has changed. + */ uri: Uri; } - export interface FileStat2 { - isFile: boolean; - isDirectory: boolean; - isSymbolicLink: boolean; + /** + * The `FileStat`-type represents metadata about a file. + */ + export interface FileStat { + /** + * The file is a regular file. + */ + isFile?: boolean; + + /** + * The file is a directory. + */ + isDirectory?: boolean; + + /** + * The file is symbolic link to another file. + */ + isSymbolicLink?: boolean; + + /** + * The modification timestamp in milliseconds. + */ mtime: number; + + /** + * The size in bytes. + */ size: number; } /** - * + * Commonly used options when reading, writing, or stat'ing files or folders. */ export interface FileOptions { @@ -159,18 +189,20 @@ declare module 'vscode' { } /** - * + * loose notes: + * -activation event `onFileSystem:foo`, + * -paths are hierarchical and the identifier of a file + * -use posix-path-math + * -etc... */ - export interface FileSystemProvider2 { - - _version: 9; + export interface FileSystemProvider { /** * An event to signal that a resource has been created, changed, or deleted. This * event should fire for resources that are being [watched](#FileSystemProvider2.watch) * by clients of this provider. */ - readonly onDidChangeFile: Event; + readonly onDidChangeFile: Event; /** * Subscribe to events in the file or folder denoted by `uri`. @@ -187,7 +219,7 @@ declare module 'vscode' { * @param token A cancellation token. * @return The file metadata about the file. */ - stat(uri: Uri, options: { /*future: followSymlinks*/ }, token: CancellationToken): FileStat2 | Thenable; + stat(uri: Uri, options: { /*future: followSymlinks*/ }, token: CancellationToken): FileStat | Thenable; /** * Retrieve the meta data of all entries of a [directory](#FileType2.Directory) @@ -196,7 +228,7 @@ declare module 'vscode' { * @param token A cancellation token. * @return A thenable that resolves to an array of tuples of file names and files stats. */ - readDirectory(uri: Uri, options: { /*future: onlyType?*/ }, token: CancellationToken): [string, FileStat2][] | Thenable<[string, FileStat2][]>; + readDirectory(uri: Uri, options: { /*future: onlyType?*/ }, token: CancellationToken): [string, FileStat][] | Thenable<[string, FileStat][]>; /** * Create a new directory. *Note* that new files are created via `write`-calls. @@ -204,7 +236,7 @@ declare module 'vscode' { * @param uri The uri of the *new* folder. * @param token A cancellation token. */ - createDirectory(uri: Uri, options: { /*future: permissions?*/ }, token: CancellationToken): FileStat2 | Thenable; + createDirectory(uri: Uri, options: { /*future: permissions?*/ }, token: CancellationToken): FileStat | Thenable; /** * Read the entire contents of a file. @@ -240,7 +272,7 @@ declare module 'vscode' { * @param newUri The target location. * @param token A cancellation token. */ - rename(oldUri: Uri, newUri: Uri, options: FileOptions, token: CancellationToken): FileStat2 | Thenable; + rename(oldUri: Uri, newUri: Uri, options: FileOptions, token: CancellationToken): FileStat | Thenable; /** * Copy files or folders. Implementing this function is optional but it will speedup @@ -250,11 +282,11 @@ declare module 'vscode' { * @param target The target location. * @param token A cancellation token. */ - copy?(uri: Uri, target: Uri, options: FileOptions, token: CancellationToken): FileStat2 | Thenable; + copy?(uri: Uri, target: Uri, options: FileOptions, token: CancellationToken): FileStat | Thenable; } export namespace workspace { - export function registerFileSystemProvider2(scheme: string, provider: FileSystemProvider2, options: { isCaseSensitive?: boolean }): Disposable; + export function registerFileSystemProvider(scheme: string, provider: FileSystemProvider, options: { isCaseSensitive?: boolean }): Disposable; } //#endregion @@ -637,6 +669,10 @@ declare module 'vscode' { //#region Terminal + export interface Terminal { + onData: Event; + } + export namespace window { /** * The currently active terminals or an empty array. @@ -656,16 +692,34 @@ declare module 'vscode' { //#region URLs - export interface UrlHandler { - handleUrl(uri: Uri): void; + export interface ProtocolHandler { + handleUri(uri: Uri): void; } export namespace window { /** - * Registers a URL handler. + * Registers a protocol handler capable of handling system-wide URIs. */ - export function registerUrlHandler(handler: UrlHandler): Disposable; + export function registerProtocolHandler(handler: ProtocolHandler): Disposable; + } + + //#endregion + + //#region Joh: hierarchical document symbols, https://github.com/Microsoft/vscode/issues/34968 + + export class HierarchicalSymbolInformation { + name: string; + kind: SymbolKind; + location: Location; + range: Range; + children: HierarchicalSymbolInformation[]; + + constructor(name: string, kind: SymbolKind, location: Location, range: Range); + } + + export interface DocumentSymbolProvider { + provideDocumentSymbols(document: TextDocument, token: CancellationToken): ProviderResult; } //#endregion