Skip to content

Commit

Permalink
Cleanup GlobPattern handling in extension host (#140689)
Browse files Browse the repository at this point in the history
* rewrite `NotebookExclusiveDocumentPattern` handling (#140491)

* 💄

* also fix #140707

* address feedback
  • Loading branch information
bpasero authored Jan 17, 2022
1 parent 9bba389 commit 579e0a3
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 82 deletions.
7 changes: 5 additions & 2 deletions src/vs/base/common/glob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,12 @@ function listToMap(list: string[]) {
}

export function isRelativePattern(obj: unknown): obj is IRelativePattern {
const rp = obj as IRelativePattern;
const rp = obj as IRelativePattern | undefined | null;
if (!rp) {
return false;
}

return rp && typeof rp.base === 'string' && typeof rp.pattern === 'string';
return typeof rp.base === 'string' && typeof rp.pattern === 'string';
}

export function getBasenameTerms(patternOrExpression: ParsedPattern | ParsedExpression): string[] {
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
},
findFiles: (include, exclude, maxResults?, token?) => {
// Note, undefined/null have different meanings on "exclude"
return extHostWorkspace.findFiles(typeConverters.GlobPattern.from(include), typeConverters.GlobPattern.from(exclude), maxResults, extension.identifier, token);
return extHostWorkspace.findFiles(include, exclude, maxResults, extension.identifier, token);
},
findTextInFiles: (query: vscode.TextSearchQuery, optionsOrCallback: vscode.FindTextInFilesOptions | ((result: vscode.TextSearchResult) => void), callbackOrToken?: vscode.CancellationToken | ((result: vscode.TextSearchResult) => void), token?: vscode.CancellationToken) => {
checkProposedApiEnabled(extension, 'findTextInFiles');
Expand All @@ -830,7 +830,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostBulkEdits.applyWorkspaceEdit(edit);
},
createFileSystemWatcher: (pattern, ignoreCreate, ignoreChange, ignoreDelete): vscode.FileSystemWatcher => {
return extHostFileSystemEvent.createFileSystemWatcher(extHostWorkspace, extension, typeConverters.GlobPattern.from(pattern), ignoreCreate, ignoreChange, ignoreDelete);
return extHostFileSystemEvent.createFileSystemWatcher(extHostWorkspace, extension, pattern, ignoreCreate, ignoreChange, ignoreDelete);
},
get textDocuments() {
return extHostDocuments.getAllDocumentData().map(data => data.document);
Expand Down
6 changes: 5 additions & 1 deletion src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,11 @@ export interface ILanguageConfigurationDto {
};
}

export type GlobPattern = string | { base: string; pattern: string; };
export type GlobPattern = string | IRelativePattern;

export interface IRelativePatternDto extends IRelativePattern {
baseUri: UriComponents;
}

export interface IDocumentFilterDto {
$serialized: true;
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHostApiCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ const newCommands: ApiCommand[] = [
viewType: string;
displayName: string;
options: { transientOutputs: boolean; transientCellMetadata: TransientCellMetadata; transientDocumentMetadata: TransientDocumentMetadata; };
filenamePattern: (string | types.RelativePattern | { include: string | types.RelativePattern, exclude: string | types.RelativePattern })[]
filenamePattern: (vscode.GlobPattern | { include: vscode.GlobPattern, exclude: vscode.GlobPattern })[]
}[], {
viewType: string;
displayName: string;
Expand Down
12 changes: 6 additions & 6 deletions src/vs/workbench/api/common/extHostFileSystemEventService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { GLOBSTAR, GLOB_SPLIT, parse } from 'vs/base/common/glob';
import { URI } from 'vs/base/common/uri';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import type * as vscode from 'vscode';
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, SourceTargetPair, IWorkspaceEditDto, IWillRunFileOperationParticipation, MainContext } from './extHost.protocol';
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, SourceTargetPair, IWorkspaceEditDto, IWillRunFileOperationParticipation, MainContext, IRelativePatternDto } from './extHost.protocol';
import * as typeConverter from './extHostTypeConverters';
import { Disposable, RelativePattern, WorkspaceEdit } from './extHostTypes';
import { Disposable, WorkspaceEdit } from './extHostTypes';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { FileOperation } from 'vs/platform/files/common/files';
import { CancellationToken } from 'vs/base/common/cancellation';
Expand Down Expand Up @@ -38,7 +38,7 @@ class FileSystemWatcher implements vscode.FileSystemWatcher {
return Boolean(this._config & 0b100);
}

constructor(mainContext: IMainContext, workspace: IExtHostWorkspace, extension: IExtensionDescription, dispatcher: Event<FileSystemEvents>, globPattern: string | RelativePattern, ignoreCreateEvents?: boolean, ignoreChangeEvents?: boolean, ignoreDeleteEvents?: boolean) {
constructor(mainContext: IMainContext, workspace: IExtHostWorkspace, extension: IExtensionDescription, dispatcher: Event<FileSystemEvents>, globPattern: string | IRelativePatternDto, ignoreCreateEvents?: boolean, ignoreChangeEvents?: boolean, ignoreDeleteEvents?: boolean) {
const watcherDisposable = this.ensureWatching(mainContext, extension, globPattern);

this._config = 0;
Expand Down Expand Up @@ -91,7 +91,7 @@ class FileSystemWatcher implements vscode.FileSystemWatcher {
this._disposable = Disposable.from(watcherDisposable, this._onDidCreate, this._onDidChange, this._onDidDelete, subscription);
}

private ensureWatching(mainContext: IMainContext, extension: IExtensionDescription, globPattern: string | RelativePattern): Disposable {
private ensureWatching(mainContext: IMainContext, extension: IExtensionDescription, globPattern: string | IRelativePatternDto): Disposable {
let disposable = Disposable.from();

if (typeof globPattern === 'string') {
Expand Down Expand Up @@ -158,8 +158,8 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ

//--- file events

createFileSystemWatcher(workspace: IExtHostWorkspace, extension: IExtensionDescription, globPattern: string | RelativePattern, ignoreCreateEvents?: boolean, ignoreChangeEvents?: boolean, ignoreDeleteEvents?: boolean): vscode.FileSystemWatcher {
return new FileSystemWatcher(this._mainContext, workspace, extension, this._onFileSystemEvent.event, globPattern, ignoreCreateEvents, ignoreChangeEvents, ignoreDeleteEvents);
createFileSystemWatcher(workspace: IExtHostWorkspace, extension: IExtensionDescription, globPattern: vscode.GlobPattern, ignoreCreateEvents?: boolean, ignoreChangeEvents?: boolean, ignoreDeleteEvents?: boolean): vscode.FileSystemWatcher {
return new FileSystemWatcher(this._mainContext, workspace, extension, this._onFileSystemEvent.event, typeConverter.GlobPattern.from(globPattern), ignoreCreateEvents, ignoreChangeEvents, ignoreDeleteEvents);
}

$onFileEvent(events: FileSystemEvents) {
Expand Down
115 changes: 54 additions & 61 deletions src/vs/workbench/api/common/extHostTypeConverters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
import * as marked from 'vs/base/common/marked/marked';
import { parse } from 'vs/base/common/marshalling';
import { cloneAndChange } from 'vs/base/common/objects';
import { isDefined, isEmptyObject, isNumber, isString } from 'vs/base/common/types';
import { isDefined, isEmptyObject, isNumber, isString, withNullAsUndefined } from 'vs/base/common/types';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IURITransformer } from 'vs/base/common/uriIpc';
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
Expand Down Expand Up @@ -142,7 +142,7 @@ export namespace DocumentSelector {
$serialized: true,
language: selector.language,
scheme: _transformScheme(selector.scheme, uriTransformer),
pattern: typeof selector.pattern === 'undefined' ? undefined : GlobPattern.from(selector.pattern),
pattern: GlobPattern.from(selector.pattern) ?? undefined,
exclusive: selector.exclusive
};
}
Expand Down Expand Up @@ -1379,39 +1379,60 @@ export namespace TextEditorOpenOptions {

export namespace GlobPattern {

export function from(pattern: vscode.GlobPattern): string | types.RelativePattern;
export function from(pattern: vscode.GlobPattern): string | extHostProtocol.IRelativePatternDto;
export function from(pattern: undefined): undefined;
export function from(pattern: null): null;
export function from(pattern: vscode.GlobPattern | undefined | null): string | types.RelativePattern | undefined | null;
export function from(pattern: vscode.GlobPattern | undefined | null): string | types.RelativePattern | undefined | null {
export function from(pattern: vscode.GlobPattern | undefined | null): string | extHostProtocol.IRelativePatternDto | undefined | null;
export function from(pattern: vscode.GlobPattern | undefined | null): string | extHostProtocol.IRelativePatternDto | undefined | null {
if (pattern instanceof types.RelativePattern) {
return pattern;
return pattern.toJSON();
}

if (typeof pattern === 'string') {
return pattern;
}

if (isRelativePattern(pattern) || isLegacyRelativePattern(pattern)) {
return new types.RelativePattern(pattern.baseUri ?? pattern.base, pattern.pattern);
// This is slightly bogus because we declare this method to accept
// `vscode.GlobPattern` which can be `vscode.RelativePattern` class,
// but given we cannot enforce classes from our vscode.d.ts, we have
// to probe for objects too
// Refs: https://github.com/microsoft/vscode/issues/140771
if (isRelativePatternShape(pattern) || isLegacyRelativePatternShape(pattern)) {
return new types.RelativePattern(pattern.baseUri ?? pattern.base, pattern.pattern).toJSON();
}

return pattern; // preserve `undefined` and `null`
}

export function isRelativePattern(obj: any): obj is vscode.RelativePattern {
const rp = obj as vscode.RelativePattern;
return rp && URI.isUri(rp.baseUri) && typeof rp.pattern === 'string';
function isRelativePatternShape(obj: unknown): obj is { base: string, baseUri: URI, pattern: string } {
const rp = obj as { base: string, baseUri: URI, pattern: string } | undefined | null;
if (!rp) {
return false;
}

return URI.isUri(rp.baseUri) && typeof rp.pattern === 'string';
}

function isLegacyRelativePattern(obj: any): obj is { base: string, pattern: string } {
function isLegacyRelativePatternShape(obj: unknown): obj is { base: string, pattern: string } {

// Before 1.64.x, `RelativePattern` did not have any `baseUri: Uri`
// property. To preserve backwards compatibility with older extensions
// we allow this old format when creating the `vscode.RelativePattern`.

const rp = obj as { base: string, pattern: string };
return rp && typeof rp.base === 'string' && typeof rp.pattern === 'string';
const rp = obj as { base: string, pattern: string } | undefined | null;
if (!rp) {
return false;
}

return typeof rp.base === 'string' && typeof rp.pattern === 'string';
}

export function to(pattern: string | extHostProtocol.IRelativePatternDto): vscode.GlobPattern {
if (typeof pattern === 'string') {
return pattern;
}

return new types.RelativePattern(URI.revive(pattern.baseUri), pattern.pattern);
}
}

Expand All @@ -1432,7 +1453,7 @@ export namespace LanguageSelector {
return <languageSelector.LanguageFilter>{
language: filter.language,
scheme: filter.scheme,
pattern: typeof filter.pattern === 'undefined' ? undefined : GlobPattern.from(filter.pattern),
pattern: GlobPattern.from(filter.pattern),
exclusive: filter.exclusive
};
}
Expand Down Expand Up @@ -1573,67 +1594,39 @@ export namespace NotebookCellOutput {


export namespace NotebookExclusiveDocumentPattern {
export function from(pattern: { include: vscode.GlobPattern | undefined, exclude: vscode.GlobPattern | undefined }): { include: string | types.RelativePattern | undefined, exclude: string | types.RelativePattern | undefined };
export function from(pattern: vscode.GlobPattern): string | types.RelativePattern;
export function from(pattern: { include: vscode.GlobPattern | undefined, exclude: vscode.GlobPattern | undefined }): { include: string | extHostProtocol.IRelativePatternDto | undefined, exclude: string | extHostProtocol.IRelativePatternDto | undefined };
export function from(pattern: vscode.GlobPattern): string | extHostProtocol.IRelativePatternDto;
export function from(pattern: undefined): undefined;
export function from(pattern: { include: vscode.GlobPattern | undefined | null, exclude: vscode.GlobPattern | undefined } | vscode.GlobPattern | undefined): string | types.RelativePattern | { include: string | types.RelativePattern | undefined, exclude: string | types.RelativePattern | undefined } | undefined;
export function from(pattern: { include: vscode.GlobPattern | undefined | null, exclude: vscode.GlobPattern | undefined } | vscode.GlobPattern | undefined): string | types.RelativePattern | { include: string | types.RelativePattern | undefined, exclude: string | types.RelativePattern | undefined } | undefined {
if (pattern === null || pattern === undefined) {
return undefined;
}

if (pattern instanceof types.RelativePattern) {
return pattern;
}

if (typeof pattern === 'string') {
return pattern;
}


if (GlobPattern.isRelativePattern(pattern)) {
return new types.RelativePattern(pattern.baseUri, pattern.pattern);
}

export function from(pattern: { include: vscode.GlobPattern | undefined | null, exclude: vscode.GlobPattern | undefined } | vscode.GlobPattern | undefined): string | extHostProtocol.IRelativePatternDto | { include: string | extHostProtocol.IRelativePatternDto | undefined, exclude: string | extHostProtocol.IRelativePatternDto | undefined } | undefined;
export function from(pattern: { include: vscode.GlobPattern | undefined | null, exclude: vscode.GlobPattern | undefined } | vscode.GlobPattern | undefined): string | extHostProtocol.IRelativePatternDto | { include: string | extHostProtocol.IRelativePatternDto | undefined, exclude: string | extHostProtocol.IRelativePatternDto | undefined } | undefined {
if (isExclusivePattern(pattern)) {
return {
include: GlobPattern.from(pattern.include) || undefined,
exclude: GlobPattern.from(pattern.exclude) || undefined
include: withNullAsUndefined(GlobPattern.from(pattern.include)),
exclude: withNullAsUndefined(GlobPattern.from(pattern.exclude))
};
}

return undefined; // preserve `undefined`

return withNullAsUndefined(GlobPattern.from(pattern));
}

export function to(pattern: string | types.RelativePattern | { include: string | types.RelativePattern, exclude: string | types.RelativePattern }): { include: vscode.GlobPattern, exclude: vscode.GlobPattern } | vscode.GlobPattern {
if (typeof pattern === 'string') {
return pattern;
}

if (GlobPattern.isRelativePattern(pattern)) {
return new types.RelativePattern(pattern.baseUri, pattern.pattern);
export function to(pattern: string | extHostProtocol.IRelativePatternDto | { include: string | extHostProtocol.IRelativePatternDto, exclude: string | extHostProtocol.IRelativePatternDto }): { include: vscode.GlobPattern, exclude: vscode.GlobPattern } | vscode.GlobPattern {
if (isExclusivePattern(pattern)) {
return {
include: GlobPattern.to(pattern.include),
exclude: GlobPattern.to(pattern.exclude)
};
}

return {
include: pattern.include,
exclude: pattern.exclude
};
return GlobPattern.to(pattern);
}

function isExclusivePattern(obj: any): obj is { include: types.RelativePattern | undefined | null, exclude: types.RelativePattern | undefined | null } {
const ep = obj as { include: vscode.GlobPattern, exclude: vscode.GlobPattern };
const include = GlobPattern.from(ep.include);
if (!(include && include instanceof types.RelativePattern || typeof include === 'string')) {
function isExclusivePattern<T>(obj: any): obj is { include?: T, exclude?: T } {
const ep = obj as { include?: T, exclude?: T } | undefined | null;
if (!ep) {
return false;
}

const exclude = GlobPattern.from(ep.exclude);
if (!(exclude && exclude instanceof types.RelativePattern || typeof exclude === 'string')) {
return false;
}

return true;
return !!ep.include && !!ep.exclude;
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/vs/workbench/api/common/extHostTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/platform/files/common/files';
import { RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { IRelativePatternDto } from 'vs/workbench/api/common/extHost.protocol';
import { CellEditType, ICellPartialMetadataEdit, IDocumentMetadataEdit } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import type * as vscode from 'vscode';

Expand Down Expand Up @@ -2413,10 +2414,11 @@ export class RelativePattern implements IRelativePattern {
this.pattern = pattern;
}

toJSON(): IRelativePattern {
toJSON(): IRelativePatternDto {
return {
pattern: this.pattern,
base: this.base
base: this.base,
baseUri: this.baseUri.toJSON()
};
}
}
Expand Down
Loading

0 comments on commit 579e0a3

Please sign in to comment.