提交 fb590e65 编写于 作者: J Johannes Rieken

have a FileType and make readDirectory slimmer, #48527

上级 c2493d71
......@@ -155,12 +155,6 @@ export interface IFileService {
dispose(): void;
}
export enum FileType2 {
File = 1,
Directory = 2,
SymbolicLink = 4,
}
export interface FileOptions {
/**
* Create a file when it doesn't exists.
......@@ -184,11 +178,17 @@ export interface FileOptions {
write?: boolean;
}
export enum FileType {
Unknown = 0,
File = 1,
Directory = 2,
SymbolicLink = 64
}
export interface IStat {
isFile?: boolean;
isDirectory?: boolean;
isSymbolicLink?: boolean;
type: FileType;
mtime: number;
ctime: number;
size: number;
}
......@@ -214,7 +214,7 @@ export interface IFileSystemProvider {
stat(resource: URI): TPromise<IStat>;
mkdir(resource: URI): TPromise<IStat>;
readdir(resource: URI): TPromise<[string, IStat][]>;
readdir(resource: URI): TPromise<[string, FileType][]>;
delete(resource: URI): TPromise<void>;
rename(from: URI, to: URI, opts: FileOptions): TPromise<IStat>;
......
......@@ -4824,23 +4824,41 @@ declare module 'vscode' {
}
/**
* The `FileStat`-type represents metadata about a file.
* Enumeration of file types.
*/
export interface FileStat {
export enum FileType {
/**
* The file type is unknown.
*/
Unknown = 0,
/**
* The file is a regular file.
* A regular file.
*/
isFile?: boolean;
File = 1,
/**
* A directory.
*/
Directory = 2,
/**
* A symbolic link to a file.
*/
SymbolicLink = 64
}
/**
* The `FileStat`-type represents metadata about a file.
*/
export interface FileStat {
/**
* The file is a directory.
* The type of the file, e.g. is a regular file, a directory, or symbolic link
* to a file.
*/
isDirectory?: boolean;
type: FileType;
/**
* The file is symbolic link to another file.
* The creation timestamp in milliseconds.
*/
isSymbolicLink?: boolean;
ctime: number;
/**
* The modification timestamp in milliseconds.
......@@ -5001,7 +5019,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, FileStat][] | Thenable<[string, FileStat][]>;
readDirectory(uri: Uri, options: { /*future: onlyType?*/ }, token: CancellationToken): [string, FileType][] | Thenable<[string, FileType][]>;
/**
* Create a new directory. *Note* that new files are created via `write`-calls.
......
......@@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { FileOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IFileSystemProvider, IStat, IWatchOptions } from 'vs/platform/files/common/files';
import { FileOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IFileSystemProvider, IStat, IWatchOptions, FileType } from 'vs/platform/files/common/files';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { ExtHostContext, ExtHostFileSystemShape, IExtHostContext, IFileChangeDto, MainContext, MainThreadFileSystemShape } from '../node/extHost.protocol';
......@@ -115,7 +115,7 @@ class RemoteFileSystemProvider implements IFileSystemProvider {
return this._proxy.$mkdir(this._handle, resource);
}
readdir(resource: URI): TPromise<[string, IStat][], any> {
readdir(resource: URI): TPromise<[string, FileType][], any> {
return this._proxy.$readdir(this._handle, resource);
}
......
......@@ -45,6 +45,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as vscode from 'vscode';
import * as paths from 'vs/base/common/paths';
import * as files from 'vs/platform/files/common/files';
import { MainContext, ExtHostContext, IInitData, IExtHostContext } from './extHost.protocol';
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
......@@ -700,6 +701,7 @@ export function createApiFactory(
DeprecatedFileChangeType: extHostTypes.DeprecatedFileChangeType,
DeprecatedFileType: extHostTypes.DeprecatedFileType,
FileChangeType: extHostTypes.FileChangeType,
FileType: files.FileType,
FileSystemError: extHostTypes.FileSystemError,
FoldingRange: extHostTypes.FoldingRange,
FoldingRangeKind: extHostTypes.FoldingRangeKind
......
......@@ -42,7 +42,7 @@ import { ITreeItem } from 'vs/workbench/common/views';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { SerializedError } from 'vs/base/common/errors';
import { IStat, FileChangeType, IWatchOptions, FileSystemProviderCapabilities, FileOptions } from 'vs/platform/files/common/files';
import { IStat, FileChangeType, IWatchOptions, FileSystemProviderCapabilities, FileOptions, FileType } from 'vs/platform/files/common/files';
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { CommentRule, CharacterPair, EnterAction } from 'vs/editor/common/modes/languageConfiguration';
import { ISingleEditOperation } from 'vs/editor/common/model';
......@@ -582,12 +582,12 @@ export interface ExtHostWorkspaceShape {
export interface ExtHostFileSystemShape {
$stat(handle: number, resource: UriComponents): TPromise<IStat>;
$readdir(handle: number, resource: UriComponents): TPromise<[string, FileType][]>;
$readFile(handle: number, resource: UriComponents, opts: FileOptions): TPromise<string>;
$writeFile(handle: number, resource: UriComponents, base64Encoded: string, opts: FileOptions): TPromise<void>;
$rename(handle: number, resource: UriComponents, target: UriComponents, opts: FileOptions): TPromise<IStat>;
$copy(handle: number, resource: UriComponents, target: UriComponents, opts: FileOptions): TPromise<IStat>;
$mkdir(handle: number, resource: UriComponents): TPromise<IStat>;
$readdir(handle: number, resource: UriComponents): TPromise<[string, IStat][]>;
$delete(handle: number, resource: UriComponents): TPromise<void>;
$watch(handle: number, session: number, resource: UriComponents, opts: IWatchOptions): void;
$unwatch(handle: number, session: number): void;
......
......@@ -81,31 +81,29 @@ class FileSystemProviderShim implements vscode.FileSystemProvider {
rename(oldUri: vscode.Uri, newUri: vscode.Uri): Thenable<vscode.FileStat> {
return this._delegate.move(oldUri, newUri).then(stat => FileSystemProviderShim._modernizeFileStat(stat));
}
readDirectory(resource: vscode.Uri): Thenable<[string, vscode.FileStat][]> {
readDirectory(resource: vscode.Uri): Thenable<[string, vscode.FileType][]> {
return this._delegate.readdir(resource).then(tuples => {
return tuples.map(tuple => <[string, vscode.FileStat]>[path.posix.basename(tuple[0].path), FileSystemProviderShim._modernizeFileStat(tuple[1])]);
return tuples.map(tuple => <[string, vscode.FileType]>[path.posix.basename(tuple[0].path), FileSystemProviderShim._modernizeFileStat(tuple[1]).type]);
});
}
private static _modernizeFileStat(stat: vscode.DeprecatedFileStat): vscode.FileStat {
let { mtime, size, type } = stat;
let isFile = false;
let isDirectory = false;
let isSymbolicLink = false;
let newType: files.FileType;
// no support for bitmask, effectively no support for symlinks
switch (type) {
case DeprecatedFileType.Dir:
isDirectory = true;
newType = files.FileType.Directory;
break;
case DeprecatedFileType.File:
isFile = true;
newType = files.FileType.File;
break;
case DeprecatedFileType.Symlink:
isSymbolicLink = true;
newType = files.FileType.File & files.FileType.SymbolicLink;
break;
}
return { mtime, size, isFile, isDirectory, isSymbolicLink };
return { type: newType, ctime: 0, mtime, size };
}
private static _modernizeFileChange(e: vscode.DeprecatedFileChange): vscode.FileChangeEvent {
......@@ -246,18 +244,16 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
}
private static _asIStat(stat: vscode.FileStat): files.IStat {
const { isFile, isDirectory, isSymbolicLink, mtime, size } = stat;
return { isFile, isDirectory, isSymbolicLink, mtime, size };
const { type, ctime, mtime, size } = stat;
return { type, ctime, mtime, size };
}
$stat(handle: number, resource: UriComponents): TPromise<files.IStat, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).stat(URI.revive(resource), {}, token)).then(ExtHostFileSystem._asIStat);
}
$readdir(handle: number, resource: UriComponents): TPromise<[string, files.IStat][], any> {
return asWinJsPromise(token => this._fsProvider.get(handle).readDirectory(URI.revive(resource), {}, token)).then(tuples => {
return tuples.map(([name, stat]) => <[string, files.IStat]>[name, ExtHostFileSystem._asIStat(stat)]);
});
$readdir(handle: number, resource: UriComponents): TPromise<[string, files.FileType][], any> {
return asWinJsPromise(token => this._fsProvider.get(handle).readDirectory(URI.revive(resource), {}, token));
}
$readFile(handle: number, resource: UriComponents, opts: files.FileOptions): TPromise<string> {
......
......@@ -16,7 +16,7 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res
import { localize } from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { FileChangesEvent, FileOperation, FileOperationError, FileOperationEvent, FileOperationResult, FileOptions, FileSystemProviderCapabilities, IContent, ICreateFileOptions, IFileStat, IFileSystemProvider, IFilesConfiguration, IResolveContentOptions, IResolveFileOptions, IResolveFileResult, IStat, IStreamContent, ITextSnapshot, IUpdateContentOptions, StringSnapshot, IWatchOptions } from 'vs/platform/files/common/files';
import { FileChangesEvent, FileOperation, FileOperationError, FileOperationEvent, FileOperationResult, FileOptions, FileSystemProviderCapabilities, IContent, ICreateFileOptions, IFileStat, IFileSystemProvider, IFilesConfiguration, IResolveContentOptions, IResolveFileOptions, IResolveFileResult, IStat, IStreamContent, ITextSnapshot, IUpdateContentOptions, StringSnapshot, IWatchOptions, FileType } from 'vs/platform/files/common/files';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IStorageService } from 'vs/platform/storage/common/storage';
......@@ -25,13 +25,26 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
import { FileService } from 'vs/workbench/services/files/electron-browser/fileService';
import { createReadableOfProvider, createReadableOfSnapshot, createWritableOfProvider } from 'vs/workbench/services/files/electron-browser/streams';
class TypeOnlyStat implements IStat {
constructor(readonly type: FileType) {
//
}
// todo@remote -> make a getter and warn when
// being used in development.
mtime: number = 0;
ctime: number = 0;
size: number = 0;
}
function toIFileStat(provider: IFileSystemProvider, tuple: [URI, IStat], recurse?: (tuple: [URI, IStat]) => boolean): TPromise<IFileStat> {
const [resource, stat] = tuple;
const fileStat: IFileStat = {
resource,
name: posix.basename(resource.path),
isDirectory: stat.isDirectory,
isSymbolicLink: stat.isSymbolicLink,
isDirectory: (stat.type & FileType.Directory) !== 0,
isSymbolicLink: (stat.type & FileType.SymbolicLink) !== 0,
mtime: stat.mtime,
size: stat.size,
etag: stat.mtime.toString(29) + stat.size.toString(31),
......@@ -43,9 +56,9 @@ function toIFileStat(provider: IFileSystemProvider, tuple: [URI, IStat], recurse
return provider.readdir(resource).then(entries => {
// resolve children if requested
return TPromise.join(entries.map(tuple => {
const [name, stat] = tuple;
const [name, type] = tuple;
const childResource = resource.with({ path: posix.join(resource.path, name) });
return toIFileStat(provider, [childResource, stat], recurse);
return toIFileStat(provider, [childResource, new TypeOnlyStat(type)], recurse);
})).then(children => {
fileStat.children = children;
return fileStat;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册