mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 1b314ab317fbff7d799b21754326b7d849889ceb
This commit is contained in:
@@ -76,6 +76,7 @@ import { ExtHostAuthentication } from 'vs/workbench/api/common/extHostAuthentica
|
||||
import { ExtHostTimeline } from 'vs/workbench/api/common/extHostTimeline';
|
||||
import { ExtHostNotebookConcatDocument } from 'vs/workbench/api/common/extHostNotebookConcatDocument';
|
||||
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { IExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
|
||||
@@ -88,6 +89,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
|
||||
// services
|
||||
const initData = accessor.get(IExtHostInitDataService);
|
||||
const extHostConsumerFileSystem = accessor.get(IExtHostConsumerFileSystem);
|
||||
const extensionService = accessor.get(IExtHostExtensionService);
|
||||
const extHostWorkspace = accessor.get(IExtHostWorkspace);
|
||||
const extHostConfiguration = accessor.get(IExtHostConfiguration);
|
||||
@@ -203,6 +205,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
get providerIds(): string[] {
|
||||
return extHostAuthentication.providerIds;
|
||||
},
|
||||
get providers(): ReadonlyArray<vscode.AuthenticationProviderInformation> {
|
||||
return extHostAuthentication.providers;
|
||||
},
|
||||
hasSessions(providerId: string, scopes: string[]): Thenable<boolean> {
|
||||
return extHostAuthentication.hasSessions(providerId, scopes);
|
||||
},
|
||||
@@ -212,7 +217,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
logout(providerId: string, sessionId: string): Thenable<void> {
|
||||
return extHostAuthentication.logout(providerId, sessionId);
|
||||
},
|
||||
get onDidChangeSessions(): Event<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }> {
|
||||
get onDidChangeSessions(): Event<vscode.AuthenticationProviderAuthenticationSessionsChangeEvent> {
|
||||
return extHostAuthentication.onDidChangeSessions;
|
||||
},
|
||||
};
|
||||
@@ -269,7 +274,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
get sessionId() { return initData.telemetryInfo.sessionId; },
|
||||
get language() { return initData.environment.appLanguage; },
|
||||
get appName() { return initData.environment.appName; },
|
||||
get appRoot() { return initData.environment.appRoot?.fsPath ?? '<UNKNOWN_APP_ROOT>'; },
|
||||
get appRoot() { return initData.environment.appRoot?.fsPath ?? ''; },
|
||||
get uriScheme() { return initData.environment.appUriScheme; },
|
||||
get logLevel() {
|
||||
checkProposedApiEnabled(extension);
|
||||
@@ -746,7 +751,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostFileSystem.registerFileSystemProvider(scheme, provider, options);
|
||||
},
|
||||
get fs() {
|
||||
return extHostFileSystem.fileSystem;
|
||||
return extHostConsumerFileSystem;
|
||||
},
|
||||
registerFileSearchProvider: (scheme: string, provider: vscode.FileSearchProvider) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
@@ -878,6 +883,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
},
|
||||
stopDebugging(session: vscode.DebugSession | undefined) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
},
|
||||
addBreakpoints(breakpoints: vscode.Breakpoint[]) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
|
||||
39
src/vs/workbench/api/common/extHost.common.services.ts
Normal file
39
src/vs/workbench/api/common/extHost.common.services.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IExtHostOutputService, ExtHostOutputService } from 'vs/workbench/api/common/extHostOutput';
|
||||
import { IExtHostWorkspace, ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { IExtHostDecorations, ExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations';
|
||||
import { IExtHostConfiguration, ExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { IExtHostCommands, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtHostTerminalService, WorkerExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
// import { IExtHostTask, WorkerExtHostTask } from 'vs/workbench/api/common/extHostTask';
|
||||
// import { IExtHostDebugService, WorkerExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
import { IExtHostSearch, ExtHostSearch } from 'vs/workbench/api/common/extHostSearch';
|
||||
import { IExtensionStoragePaths, ExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { IExtHostStorage, ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
import { IExtHostTunnelService, ExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { IExtHostApiDeprecationService, ExtHostApiDeprecationService, } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
||||
import { IExtHostWindow, ExtHostWindow } from 'vs/workbench/api/common/extHostWindow';
|
||||
import { ExtHostConsumerFileSystem, IExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer';
|
||||
|
||||
registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);
|
||||
registerSingleton(IExtHostApiDeprecationService, ExtHostApiDeprecationService);
|
||||
registerSingleton(IExtHostCommands, ExtHostCommands);
|
||||
registerSingleton(IExtHostConfiguration, ExtHostConfiguration);
|
||||
registerSingleton(IExtHostConsumerFileSystem, ExtHostConsumerFileSystem);
|
||||
// registerSingleton(IExtHostDebugService, WorkerExtHostDebugService);
|
||||
registerSingleton(IExtHostDecorations, ExtHostDecorations);
|
||||
registerSingleton(IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors);
|
||||
registerSingleton(IExtHostOutputService, ExtHostOutputService);
|
||||
registerSingleton(IExtHostSearch, ExtHostSearch);
|
||||
registerSingleton(IExtHostStorage, ExtHostStorage);
|
||||
// registerSingleton(IExtHostTask, WorkerExtHostTask);
|
||||
registerSingleton(IExtHostTerminalService, WorkerExtHostTerminalService);
|
||||
registerSingleton(IExtHostTunnelService, ExtHostTunnelService);
|
||||
registerSingleton(IExtHostWindow, ExtHostWindow);
|
||||
registerSingleton(IExtHostWorkspace, ExtHostWorkspace);
|
||||
@@ -67,11 +67,10 @@ export interface IEnvironment {
|
||||
appRoot?: URI;
|
||||
appLanguage: string;
|
||||
appUriScheme: string;
|
||||
appSettingsHome?: URI;
|
||||
extensionDevelopmentLocationURI?: URI[];
|
||||
extensionTestsLocationURI?: URI;
|
||||
globalStorageHome: URI;
|
||||
userHome: URI;
|
||||
workspaceStorageHome: URI;
|
||||
webviewResourceRoot: string;
|
||||
webviewCspSource: string;
|
||||
useHostProxy?: boolean;
|
||||
@@ -162,7 +161,7 @@ export interface MainThreadCommentsShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface MainThreadAuthenticationShape extends IDisposable {
|
||||
$registerAuthenticationProvider(id: string, displayName: string, supportsMultipleAccounts: boolean): void;
|
||||
$registerAuthenticationProvider(id: string, label: string, supportsMultipleAccounts: boolean): void;
|
||||
$unregisterAuthenticationProvider(id: string): void;
|
||||
$getProviderIds(): Promise<string[]>;
|
||||
$sendDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void;
|
||||
@@ -206,8 +205,8 @@ export interface MainThreadDialogSaveOptions {
|
||||
}
|
||||
|
||||
export interface MainThreadDiaglogsShape extends IDisposable {
|
||||
$showOpenDialog(options: MainThreadDialogOpenOptions): Promise<UriComponents[] | undefined>;
|
||||
$showSaveDialog(options: MainThreadDialogSaveOptions): Promise<UriComponents | undefined>;
|
||||
$showOpenDialog(options?: MainThreadDialogOpenOptions): Promise<UriComponents[] | undefined>;
|
||||
$showSaveDialog(options?: MainThreadDialogSaveOptions): Promise<UriComponents | undefined>;
|
||||
}
|
||||
|
||||
export interface MainThreadDecorationsShape extends IDisposable {
|
||||
@@ -738,7 +737,7 @@ export interface ITextSearchComplete {
|
||||
export interface MainThreadWorkspaceShape extends IDisposable {
|
||||
$startFileSearch(includePattern: string | null, includeFolder: UriComponents | null, excludePatternOrDisregardExcludes: string | false | null, maxResults: number | null, token: CancellationToken): Promise<UriComponents[] | null>;
|
||||
$startTextSearch(query: search.IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null>;
|
||||
$checkExists(folders: UriComponents[], includes: string[], token: CancellationToken): Promise<boolean>;
|
||||
$checkExists(folders: readonly UriComponents[], includes: string[], token: CancellationToken): Promise<boolean>;
|
||||
$saveAll(includeUntitled?: boolean): Promise<boolean>;
|
||||
$updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, workspaceFoldersToAdd: { uri: UriComponents, name?: string; }[]): Promise<void>;
|
||||
$resolveProxy(url: string): Promise<string | undefined>;
|
||||
@@ -784,7 +783,7 @@ export interface MainThreadTaskShape extends IDisposable {
|
||||
$unregisterTaskProvider(handle: number): Promise<void>;
|
||||
$fetchTasks(filter?: tasks.TaskFilterDTO): Promise<tasks.TaskDTO[]>;
|
||||
$getTaskExecution(value: tasks.TaskHandleDTO | tasks.TaskDTO): Promise<tasks.TaskExecutionDTO>;
|
||||
$executeTask(task: tasks.TaskDTO): Promise<tasks.TaskExecutionDTO>;
|
||||
$executeTask(task: tasks.TaskHandleDTO | tasks.TaskDTO): Promise<tasks.TaskExecutionDTO>;
|
||||
$terminateTask(id: string): Promise<void>;
|
||||
$registerTaskSystem(scheme: string, info: tasks.TaskSystemInfoDTO): void;
|
||||
$customExecutionComplete(id: string, result?: number): Promise<void>;
|
||||
@@ -862,7 +861,7 @@ export interface IStartDebuggingOptions {
|
||||
parentSessionID?: DebugSessionUUID;
|
||||
repl?: IDebugSessionReplMode;
|
||||
noDebug?: boolean;
|
||||
noCompact?: boolean;
|
||||
compact?: boolean;
|
||||
}
|
||||
|
||||
export interface MainThreadDebugServiceShape extends IDisposable {
|
||||
@@ -876,8 +875,10 @@ export interface MainThreadDebugServiceShape extends IDisposable {
|
||||
$unregisterDebugConfigurationProvider(handle: number): void;
|
||||
$unregisterDebugAdapterDescriptorFactory(handle: number): void;
|
||||
$startDebugging(folder: UriComponents | undefined, nameOrConfig: string | IDebugConfiguration, options: IStartDebuggingOptions): Promise<boolean>;
|
||||
$stopDebugging(sessionId: DebugSessionUUID | undefined): Promise<void>;
|
||||
$setDebugSessionName(id: DebugSessionUUID, name: string): void;
|
||||
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): Promise<any>;
|
||||
$terminateDebugSession(id: DebugSessionUUID): Promise<void>;
|
||||
$appendDebugConsole(value: string): void;
|
||||
$startBreakpointEvents(): void;
|
||||
$registerBreakpoints(breakpoints: Array<ISourceMultiBreakpointDto | IFunctionBreakpointDto | IDataBreakpointDto>): Promise<void>;
|
||||
@@ -1029,8 +1030,8 @@ export interface ExtHostAuthenticationShape {
|
||||
$getSessionAccessToken(id: string, sessionId: string): Promise<string>;
|
||||
$login(id: string, scopes: string[]): Promise<modes.AuthenticationSession>;
|
||||
$logout(id: string, sessionId: string): Promise<void>;
|
||||
$onDidChangeAuthenticationSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): Promise<void>;
|
||||
$onDidChangeAuthenticationProviders(added: string[], removed: string[]): Promise<void>;
|
||||
$onDidChangeAuthenticationSessions(id: string, label: string, event: modes.AuthenticationSessionsChangeEvent): Promise<void>;
|
||||
$onDidChangeAuthenticationProviders(added: modes.AuthenticationProviderInformation[], removed: modes.AuthenticationProviderInformation[]): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ExtHostSearchShape {
|
||||
@@ -1455,6 +1456,7 @@ export interface ExtHostTaskShape {
|
||||
$resolveVariables(workspaceFolder: UriComponents, toResolve: { process?: { name: string; cwd?: string; }, variables: string[]; }): Promise<{ process?: string; variables: { [key: string]: string; }; }>;
|
||||
$getDefaultShellAndArgs(): Thenable<{ shell: string, args: string[] | string | undefined; }>;
|
||||
$jsonTasksSupported(): Thenable<boolean>;
|
||||
$findExecutable(command: string, cwd?: string, paths?: string[]): Promise<string | undefined>;
|
||||
}
|
||||
|
||||
export interface IBreakpointDto {
|
||||
|
||||
@@ -14,11 +14,15 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
private _proxy: MainThreadAuthenticationShape;
|
||||
private _authenticationProviders: Map<string, vscode.AuthenticationProvider> = new Map<string, vscode.AuthenticationProvider>();
|
||||
|
||||
private _providerIds: string[] = [];
|
||||
|
||||
private _providers: vscode.AuthenticationProviderInformation[] = [];
|
||||
|
||||
private _onDidChangeAuthenticationProviders = new Emitter<vscode.AuthenticationProvidersChangeEvent>();
|
||||
readonly onDidChangeAuthenticationProviders: Event<vscode.AuthenticationProvidersChangeEvent> = this._onDidChangeAuthenticationProviders.event;
|
||||
|
||||
private _onDidChangeSessions = new Emitter<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }>();
|
||||
readonly onDidChangeSessions: Event<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }> = this._onDidChangeSessions.event;
|
||||
private _onDidChangeSessions = new Emitter<vscode.AuthenticationProviderAuthenticationSessionsChangeEvent>();
|
||||
readonly onDidChangeSessions: Event<vscode.AuthenticationProviderAuthenticationSessionsChangeEvent> = this._onDidChangeSessions.event;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadAuthentication);
|
||||
@@ -29,12 +33,11 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
}
|
||||
|
||||
get providerIds(): string[] {
|
||||
const ids: string[] = [];
|
||||
this._authenticationProviders.forEach(provider => {
|
||||
ids.push(provider.id);
|
||||
});
|
||||
return this._providerIds;
|
||||
}
|
||||
|
||||
return ids;
|
||||
get providers(): ReadonlyArray<vscode.AuthenticationProviderInformation> {
|
||||
return Object.freeze(this._providers);
|
||||
}
|
||||
|
||||
private async resolveSessions(providerId: string): Promise<ReadonlyArray<modes.AuthenticationSession>> {
|
||||
@@ -53,7 +56,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
async hasSessions(providerId: string, scopes: string[]): Promise<boolean> {
|
||||
const orderedScopes = scopes.sort().join(' ');
|
||||
const sessions = await this.resolveSessions(providerId);
|
||||
return !!(sessions.filter(session => session.scopes.sort().join(' ') === orderedScopes).length);
|
||||
return !!(sessions.filter(session => session.scopes.slice().sort().join(' ') === orderedScopes).length);
|
||||
}
|
||||
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise<vscode.AuthenticationSession>;
|
||||
@@ -67,12 +70,12 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
}
|
||||
|
||||
const orderedScopes = scopes.sort().join(' ');
|
||||
const sessions = (await provider.getSessions()).filter(session => session.scopes.sort().join(' ') === orderedScopes);
|
||||
const sessions = (await provider.getSessions()).filter(session => session.scopes.slice().sort().join(' ') === orderedScopes);
|
||||
|
||||
if (sessions.length) {
|
||||
if (!provider.supportsMultipleAccounts) {
|
||||
const session = sessions[0];
|
||||
const allowed = await this._proxy.$getSessionsPrompt(providerId, session.account.displayName, provider.displayName, extensionId, extensionName);
|
||||
const allowed = await this._proxy.$getSessionsPrompt(providerId, session.account.label, provider.label, extensionId, extensionName);
|
||||
if (allowed) {
|
||||
return session;
|
||||
} else {
|
||||
@@ -81,17 +84,17 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
}
|
||||
|
||||
// On renderer side, confirm consent, ask user to choose between accounts if multiple sessions are valid
|
||||
const selected = await this._proxy.$selectSession(providerId, provider.displayName, extensionId, extensionName, sessions, scopes, !!options.clearSessionPreference);
|
||||
const selected = await this._proxy.$selectSession(providerId, provider.label, extensionId, extensionName, sessions, scopes, !!options.clearSessionPreference);
|
||||
return sessions.find(session => session.id === selected.id);
|
||||
} else {
|
||||
if (options.createIfNone) {
|
||||
const isAllowed = await this._proxy.$loginPrompt(provider.displayName, extensionName);
|
||||
const isAllowed = await this._proxy.$loginPrompt(provider.label, extensionName);
|
||||
if (!isAllowed) {
|
||||
throw new Error('User did not consent to login.');
|
||||
}
|
||||
|
||||
const session = await provider.login(scopes);
|
||||
await this._proxy.$setTrustedExtension(providerId, session.account.displayName, extensionId, extensionName);
|
||||
await this._proxy.$setTrustedExtension(providerId, session.account.label, extensionId, extensionName);
|
||||
return session;
|
||||
} else {
|
||||
await this._proxy.$requestNewSession(providerId, scopes, extensionId, extensionName);
|
||||
@@ -115,16 +118,36 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
}
|
||||
|
||||
this._authenticationProviders.set(provider.id, provider);
|
||||
if (!this._providerIds.includes(provider.id)) {
|
||||
this._providerIds.push(provider.id);
|
||||
}
|
||||
|
||||
if (!this._providers.find(p => p.id === provider.id)) {
|
||||
this._providers.push({
|
||||
id: provider.id,
|
||||
label: provider.label
|
||||
});
|
||||
}
|
||||
|
||||
const listener = provider.onDidChangeSessions(e => {
|
||||
this._proxy.$sendDidChangeSessions(provider.id, e);
|
||||
});
|
||||
|
||||
this._proxy.$registerAuthenticationProvider(provider.id, provider.displayName, provider.supportsMultipleAccounts);
|
||||
this._proxy.$registerAuthenticationProvider(provider.id, provider.label, provider.supportsMultipleAccounts);
|
||||
|
||||
return new Disposable(() => {
|
||||
listener.dispose();
|
||||
this._authenticationProviders.delete(provider.id);
|
||||
const index = this._providerIds.findIndex(id => id === provider.id);
|
||||
if (index > -1) {
|
||||
this._providerIds.splice(index);
|
||||
}
|
||||
|
||||
const i = this._providers.findIndex(p => p.id === provider.id);
|
||||
if (i > -1) {
|
||||
this._providers.splice(i);
|
||||
}
|
||||
|
||||
this._proxy.$unregisterAuthenticationProvider(provider.id);
|
||||
});
|
||||
}
|
||||
@@ -171,12 +194,25 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
throw new Error(`Unable to find authentication provider with handle: ${providerId}`);
|
||||
}
|
||||
|
||||
$onDidChangeAuthenticationSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent) {
|
||||
this._onDidChangeSessions.fire({ [providerId]: event });
|
||||
$onDidChangeAuthenticationSessions(id: string, label: string, event: modes.AuthenticationSessionsChangeEvent) {
|
||||
this._onDidChangeSessions.fire({ provider: { id, label }, ...event });
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
$onDidChangeAuthenticationProviders(added: string[], removed: string[]) {
|
||||
$onDidChangeAuthenticationProviders(added: modes.AuthenticationProviderInformation[], removed: modes.AuthenticationProviderInformation[]) {
|
||||
added.forEach(id => {
|
||||
if (!this._providers.includes(id)) {
|
||||
this._providers.push(id);
|
||||
}
|
||||
});
|
||||
|
||||
removed.forEach(p => {
|
||||
const index = this._providers.findIndex(provider => provider.id === p.id);
|
||||
if (index > -1) {
|
||||
this._providers.splice(index);
|
||||
}
|
||||
});
|
||||
|
||||
this._onDidChangeAuthenticationProviders.fire({ added, removed });
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ export interface IExtHostDebugService extends ExtHostDebugServiceShape {
|
||||
addBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>;
|
||||
removeBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>;
|
||||
startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, options: vscode.DebugSessionOptions): Promise<boolean>;
|
||||
stopDebugging(session: vscode.DebugSession | undefined): Promise<void>;
|
||||
registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider, trigger: vscode.DebugConfigurationProviderTriggerKind): vscode.Disposable;
|
||||
registerDebugAdapterDescriptorFactory(extension: IExtensionDescription, type: string, factory: vscode.DebugAdapterDescriptorFactory): vscode.Disposable;
|
||||
registerDebugAdapterTrackerFactory(type: string, factory: vscode.DebugAdapterTrackerFactory): vscode.Disposable;
|
||||
@@ -297,10 +298,14 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E
|
||||
parentSessionID: options.parentSession ? options.parentSession.id : undefined,
|
||||
repl: options.consoleMode === DebugConsoleMode.MergeWithParent ? 'mergeWithParent' : 'separate',
|
||||
noDebug: options.noDebug,
|
||||
noCompact: options.noCompact
|
||||
compact: options.compact
|
||||
});
|
||||
}
|
||||
|
||||
public stopDebugging(session: vscode.DebugSession | undefined): Promise<void> {
|
||||
return this._debugServiceProxy.$stopDebugging(session ? session.id : undefined);
|
||||
}
|
||||
|
||||
public registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider, trigger: vscode.DebugConfigurationProviderTriggerKind): vscode.Disposable {
|
||||
|
||||
if (!provider) {
|
||||
@@ -952,6 +957,10 @@ export class ExtHostDebugSession implements vscode.DebugSession {
|
||||
public customRequest(command: string, args: any): Promise<any> {
|
||||
return this._debugServiceProxy.$customDebugAdapterRequest(this._id, command, args);
|
||||
}
|
||||
|
||||
public terminate(): Promise<void> {
|
||||
return this._debugServiceProxy.$terminateDebugSession(this._id);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostDebugConsole implements vscode.DebugConsole {
|
||||
|
||||
@@ -15,13 +15,13 @@ export class ExtHostDialogs {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDialogs);
|
||||
}
|
||||
|
||||
showOpenDialog(options: vscode.OpenDialogOptions): Promise<URI[] | undefined> {
|
||||
showOpenDialog(options?: vscode.OpenDialogOptions): Promise<URI[] | undefined> {
|
||||
return this._proxy.$showOpenDialog(options).then(filepaths => {
|
||||
return filepaths ? filepaths.map(p => URI.revive(p)) : undefined;
|
||||
});
|
||||
}
|
||||
|
||||
showSaveDialog(options: vscode.SaveDialogOptions): Promise<URI | undefined> {
|
||||
showSaveDialog(options?: vscode.SaveDialogOptions): Promise<URI | undefined> {
|
||||
return this._proxy.$showSaveDialog(options).then(filepath => {
|
||||
return filepath ? URI.revive(filepath) : undefined;
|
||||
});
|
||||
|
||||
@@ -16,9 +16,8 @@ import { ExtHostConfiguration, IExtHostConfiguration } from 'vs/workbench/api/co
|
||||
import { ActivatedExtension, EmptyExtension, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionModule, HostExtension, ExtensionActivationTimesFragment } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { ExtHostStorage, IExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtensionActivationError, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import type * as vscode from 'vscode';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -35,6 +34,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
|
||||
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IExtensionActivationHost, checkActivateWorkspaceContainsExtension } from 'vs/workbench/api/common/shared/workspaceContains';
|
||||
|
||||
interface ITestRunner {
|
||||
/** Old test runner API, as exported from `vscode/lib/testrunner` */
|
||||
@@ -70,7 +70,6 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
private static readonly WORKSPACE_CONTAINS_TIMEOUT = 7000;
|
||||
|
||||
private readonly _onDidChangeRemoteConnectionData = this._register(new Emitter<void>());
|
||||
public readonly onDidChangeRemoteConnectionData = this._onDidChangeRemoteConnectionData.event;
|
||||
@@ -387,10 +386,22 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
subscriptions: [],
|
||||
get extensionUri() { return extensionDescription.extensionLocation; },
|
||||
get extensionPath() { return extensionDescription.extensionLocation.fsPath; },
|
||||
get storagePath() { return that._storagePath.workspaceValue(extensionDescription); },
|
||||
get globalStoragePath() { return that._storagePath.globalValue(extensionDescription); },
|
||||
asAbsolutePath(relativePath: string) { return path.join(extensionDescription.extensionLocation.fsPath, relativePath); },
|
||||
get storagePath() { return that._storagePath.workspaceValue(extensionDescription)?.fsPath; },
|
||||
get globalStoragePath() { return that._storagePath.globalValue(extensionDescription).fsPath; },
|
||||
get logPath() { return path.join(that._initData.logsLocation.fsPath, extensionDescription.identifier.value); },
|
||||
get logUri() {
|
||||
checkProposedApiEnabled(extensionDescription);
|
||||
return URI.joinPath(that._initData.logsLocation, extensionDescription.identifier.value);
|
||||
},
|
||||
get storageUri() {
|
||||
checkProposedApiEnabled(extensionDescription);
|
||||
return that._storagePath.workspaceValue(extensionDescription);
|
||||
},
|
||||
get globalStorageUri() {
|
||||
checkProposedApiEnabled(extensionDescription);
|
||||
return that._storagePath.globalValue(extensionDescription);
|
||||
},
|
||||
get extensionMode() { return extensionMode; },
|
||||
get environmentVariableCollection() { return that._extHostTerminalService.getEnvironmentVariableCollection(extensionDescription); }
|
||||
});
|
||||
@@ -486,94 +497,28 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
).then(() => { });
|
||||
}
|
||||
|
||||
private _handleWorkspaceContainsEagerExtension(folders: ReadonlyArray<vscode.WorkspaceFolder>, desc: IExtensionDescription): Promise<void> {
|
||||
const activationEvents = desc.activationEvents;
|
||||
if (!activationEvents) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
private async _handleWorkspaceContainsEagerExtension(folders: ReadonlyArray<vscode.WorkspaceFolder>, desc: IExtensionDescription): Promise<void> {
|
||||
if (this.isActivated(desc.identifier)) {
|
||||
return Promise.resolve(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
const fileNames: string[] = [];
|
||||
const globPatterns: string[] = [];
|
||||
|
||||
const localWithRemote = !this._initData.remote.isRemote && !!this._initData.remote.authority;
|
||||
for (const activationEvent of activationEvents) {
|
||||
if (/^workspaceContains:/.test(activationEvent)) {
|
||||
const fileNameOrGlob = activationEvent.substr('workspaceContains:'.length);
|
||||
if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0 || localWithRemote) {
|
||||
globPatterns.push(fileNameOrGlob);
|
||||
} else {
|
||||
fileNames.push(fileNameOrGlob);
|
||||
}
|
||||
}
|
||||
const host: IExtensionActivationHost = {
|
||||
folders: folders.map(folder => folder.uri),
|
||||
forceUsingSearch: localWithRemote,
|
||||
exists: (path) => this._hostUtils.exists(path),
|
||||
checkExists: (folders, includes, token) => this._mainThreadWorkspaceProxy.$checkExists(folders, includes, token)
|
||||
};
|
||||
|
||||
const result = await checkActivateWorkspaceContainsExtension(host, desc);
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileNames.length === 0 && globPatterns.length === 0) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const fileNamePromise = Promise.all(fileNames.map((fileName) => this._activateIfFileName(folders, desc.identifier, fileName))).then(() => { });
|
||||
const globPatternPromise = this._activateIfGlobPatterns(folders, desc.identifier, globPatterns);
|
||||
|
||||
return Promise.all([fileNamePromise, globPatternPromise]).then(() => { });
|
||||
}
|
||||
|
||||
private async _activateIfFileName(folders: ReadonlyArray<vscode.WorkspaceFolder>, extensionId: ExtensionIdentifier, fileName: string): Promise<void> {
|
||||
|
||||
// find exact path
|
||||
for (const { uri } of folders) {
|
||||
if (await this._hostUtils.exists(path.join(URI.revive(uri).fsPath, fileName))) {
|
||||
// the file was found
|
||||
return (
|
||||
this._activateById(extensionId, { startup: true, extensionId, activationEvent: `workspaceContains:${fileName}` })
|
||||
.then(undefined, err => this._logService.error(err))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async _activateIfGlobPatterns(folders: ReadonlyArray<vscode.WorkspaceFolder>, extensionId: ExtensionIdentifier, globPatterns: string[]): Promise<void> {
|
||||
this._logService.trace(`extensionHostMain#activateIfGlobPatterns: fileSearch, extension: ${extensionId.value}, entryPoint: workspaceContains`);
|
||||
|
||||
if (globPatterns.length === 0) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const tokenSource = new CancellationTokenSource();
|
||||
const searchP = this._mainThreadWorkspaceProxy.$checkExists(folders.map(folder => folder.uri), globPatterns, tokenSource.token);
|
||||
|
||||
const timer = setTimeout(async () => {
|
||||
tokenSource.cancel();
|
||||
this._activateById(extensionId, { startup: true, extensionId, activationEvent: `workspaceContainsTimeout:${globPatterns.join(',')}` })
|
||||
.then(undefined, err => this._logService.error(err));
|
||||
}, AbstractExtHostExtensionService.WORKSPACE_CONTAINS_TIMEOUT);
|
||||
|
||||
let exists: boolean = false;
|
||||
try {
|
||||
exists = await searchP;
|
||||
} catch (err) {
|
||||
if (!errors.isPromiseCanceledError(err)) {
|
||||
this._logService.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
tokenSource.dispose();
|
||||
clearTimeout(timer);
|
||||
|
||||
if (exists) {
|
||||
// a file was found matching one of the glob patterns
|
||||
return (
|
||||
this._activateById(extensionId, { startup: true, extensionId, activationEvent: `workspaceContains:${globPatterns.join(',')}` })
|
||||
.then(undefined, err => this._logService.error(err))
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.resolve(undefined);
|
||||
return (
|
||||
this._activateById(desc.identifier, { startup: true, extensionId: desc.identifier, activationEvent: result.activationEvent })
|
||||
.then(undefined, err => this._logService.error(err))
|
||||
);
|
||||
}
|
||||
|
||||
private _handleExtensionTests(): Promise<void> {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { MainContext, IMainContext, ExtHostFileSystemShape, MainThreadFileSystem
|
||||
import type * as vscode from 'vscode';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { FileChangeType, FileSystemError } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { FileChangeType } from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as typeConverter from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { ExtHostLanguageFeatures } from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
@@ -108,59 +108,6 @@ class FsLinkProvider {
|
||||
}
|
||||
}
|
||||
|
||||
class ConsumerFileSystem implements vscode.FileSystem {
|
||||
|
||||
constructor(private _proxy: MainThreadFileSystemShape) { }
|
||||
|
||||
stat(uri: vscode.Uri): Promise<vscode.FileStat> {
|
||||
return this._proxy.$stat(uri).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> {
|
||||
return this._proxy.$readdir(uri).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
createDirectory(uri: vscode.Uri): Promise<void> {
|
||||
return this._proxy.$mkdir(uri).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
async readFile(uri: vscode.Uri): Promise<Uint8Array> {
|
||||
return this._proxy.$readFile(uri).then(buff => buff.buffer).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
writeFile(uri: vscode.Uri, content: Uint8Array): Promise<void> {
|
||||
return this._proxy.$writeFile(uri, VSBuffer.wrap(content)).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
delete(uri: vscode.Uri, options?: { recursive?: boolean; useTrash?: boolean; }): Promise<void> {
|
||||
return this._proxy.$delete(uri, { ...{ recursive: false, useTrash: false }, ...options }).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
rename(oldUri: vscode.Uri, newUri: vscode.Uri, options?: { overwrite?: boolean; }): Promise<void> {
|
||||
return this._proxy.$rename(oldUri, newUri, { ...{ overwrite: false }, ...options }).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
copy(source: vscode.Uri, destination: vscode.Uri, options?: { overwrite?: boolean }): Promise<void> {
|
||||
return this._proxy.$copy(source, destination, { ...{ overwrite: false }, ...options }).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
private static _handleError(err: any): never {
|
||||
// generic error
|
||||
if (!(err instanceof Error)) {
|
||||
throw new FileSystemError(String(err));
|
||||
}
|
||||
|
||||
// no provider (unknown scheme) error
|
||||
if (err.name === 'ENOPRO') {
|
||||
throw FileSystemError.Unavailable(err.message);
|
||||
}
|
||||
|
||||
// file system error
|
||||
switch (err.name) {
|
||||
case files.FileSystemProviderErrorCode.FileExists: throw FileSystemError.FileExists(err.message);
|
||||
case files.FileSystemProviderErrorCode.FileNotFound: throw FileSystemError.FileNotFound(err.message);
|
||||
case files.FileSystemProviderErrorCode.FileNotADirectory: throw FileSystemError.FileNotADirectory(err.message);
|
||||
case files.FileSystemProviderErrorCode.FileIsADirectory: throw FileSystemError.FileIsADirectory(err.message);
|
||||
case files.FileSystemProviderErrorCode.NoPermissions: throw FileSystemError.NoPermissions(err.message);
|
||||
case files.FileSystemProviderErrorCode.Unavailable: throw FileSystemError.Unavailable(err.message);
|
||||
|
||||
default: throw new FileSystemError(err.message, err.name as files.FileSystemProviderErrorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
|
||||
private readonly _proxy: MainThreadFileSystemShape;
|
||||
@@ -172,11 +119,8 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
private _linkProviderRegistration?: IDisposable;
|
||||
private _handlePool: number = 0;
|
||||
|
||||
readonly fileSystem: vscode.FileSystem;
|
||||
|
||||
constructor(mainContext: IMainContext, private _extHostLanguageFeatures: ExtHostLanguageFeatures) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadFileSystem);
|
||||
this.fileSystem = new ConsumerFileSystem(this._proxy);
|
||||
|
||||
// register used schemes
|
||||
Object.keys(Schemas).forEach(scheme => this._usedSchemes.add(scheme));
|
||||
|
||||
74
src/vs/workbench/api/common/extHostFileSystemConsumer.ts
Normal file
74
src/vs/workbench/api/common/extHostFileSystemConsumer.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MainThreadFileSystemShape, MainContext } from './extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
import { FileSystemError } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
export class ExtHostConsumerFileSystem implements vscode.FileSystem {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _proxy: MainThreadFileSystemShape;
|
||||
|
||||
constructor(@IExtHostRpcService extHostRpc: IExtHostRpcService) {
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadFileSystem);
|
||||
}
|
||||
|
||||
stat(uri: vscode.Uri): Promise<vscode.FileStat> {
|
||||
return this._proxy.$stat(uri).catch(ExtHostConsumerFileSystem._handleError);
|
||||
}
|
||||
readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> {
|
||||
return this._proxy.$readdir(uri).catch(ExtHostConsumerFileSystem._handleError);
|
||||
}
|
||||
createDirectory(uri: vscode.Uri): Promise<void> {
|
||||
return this._proxy.$mkdir(uri).catch(ExtHostConsumerFileSystem._handleError);
|
||||
}
|
||||
async readFile(uri: vscode.Uri): Promise<Uint8Array> {
|
||||
return this._proxy.$readFile(uri).then(buff => buff.buffer).catch(ExtHostConsumerFileSystem._handleError);
|
||||
}
|
||||
writeFile(uri: vscode.Uri, content: Uint8Array): Promise<void> {
|
||||
return this._proxy.$writeFile(uri, VSBuffer.wrap(content)).catch(ExtHostConsumerFileSystem._handleError);
|
||||
}
|
||||
delete(uri: vscode.Uri, options?: { recursive?: boolean; useTrash?: boolean; }): Promise<void> {
|
||||
return this._proxy.$delete(uri, { ...{ recursive: false, useTrash: false }, ...options }).catch(ExtHostConsumerFileSystem._handleError);
|
||||
}
|
||||
rename(oldUri: vscode.Uri, newUri: vscode.Uri, options?: { overwrite?: boolean; }): Promise<void> {
|
||||
return this._proxy.$rename(oldUri, newUri, { ...{ overwrite: false }, ...options }).catch(ExtHostConsumerFileSystem._handleError);
|
||||
}
|
||||
copy(source: vscode.Uri, destination: vscode.Uri, options?: { overwrite?: boolean; }): Promise<void> {
|
||||
return this._proxy.$copy(source, destination, { ...{ overwrite: false }, ...options }).catch(ExtHostConsumerFileSystem._handleError);
|
||||
}
|
||||
private static _handleError(err: any): never {
|
||||
// generic error
|
||||
if (!(err instanceof Error)) {
|
||||
throw new FileSystemError(String(err));
|
||||
}
|
||||
|
||||
// no provider (unknown scheme) error
|
||||
if (err.name === 'ENOPRO') {
|
||||
throw FileSystemError.Unavailable(err.message);
|
||||
}
|
||||
|
||||
// file system error
|
||||
switch (err.name) {
|
||||
case files.FileSystemProviderErrorCode.FileExists: throw FileSystemError.FileExists(err.message);
|
||||
case files.FileSystemProviderErrorCode.FileNotFound: throw FileSystemError.FileNotFound(err.message);
|
||||
case files.FileSystemProviderErrorCode.FileNotADirectory: throw FileSystemError.FileNotADirectory(err.message);
|
||||
case files.FileSystemProviderErrorCode.FileIsADirectory: throw FileSystemError.FileIsADirectory(err.message);
|
||||
case files.FileSystemProviderErrorCode.NoPermissions: throw FileSystemError.NoPermissions(err.message);
|
||||
case files.FileSystemProviderErrorCode.Unavailable: throw FileSystemError.Unavailable(err.message);
|
||||
|
||||
default: throw new FileSystemError(err.message, err.name as files.FileSystemProviderErrorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface IExtHostConsumerFileSystem extends ExtHostConsumerFileSystem { }
|
||||
export const IExtHostConsumerFileSystem = createDecorator<IExtHostConsumerFileSystem>('IExtHostConsumerFileSystem');
|
||||
@@ -1020,7 +1020,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
if (provider) {
|
||||
let storageRoot: URI | undefined;
|
||||
if (this._extensionStoragePaths) {
|
||||
storageRoot = URI.file(this._extensionStoragePaths.workspaceValue(provider.extension) ?? this._extensionStoragePaths.globalValue(provider.extension));
|
||||
storageRoot = this._extensionStoragePaths.workspaceValue(provider.extension) ?? this._extensionStoragePaths.globalValue(provider.extension);
|
||||
}
|
||||
|
||||
let document = this._documents.get(URI.revive(uri).toString());
|
||||
@@ -1330,7 +1330,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
const entry = this._notebookContentProviders.get(viewType);
|
||||
let storageRoot: URI | undefined;
|
||||
if (entry && this._extensionStoragePaths) {
|
||||
storageRoot = URI.file(this._extensionStoragePaths.workspaceValue(entry.extension) ?? this._extensionStoragePaths.globalValue(entry.extension));
|
||||
storageRoot = this._extensionStoragePaths.workspaceValue(entry.extension) ?? this._extensionStoragePaths.globalValue(entry.extension);
|
||||
}
|
||||
|
||||
if (!this._documents.has(revivedUriStr)) {
|
||||
|
||||
@@ -117,6 +117,11 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
this.update();
|
||||
}
|
||||
|
||||
public set accessibilityInformation(accessibilityInformation: vscode.AccessibilityInformation | undefined) {
|
||||
this._accessibilityInformation = accessibilityInformation;
|
||||
this.update();
|
||||
}
|
||||
|
||||
public show(): void {
|
||||
this._visible = true;
|
||||
this.update();
|
||||
|
||||
@@ -5,12 +5,83 @@
|
||||
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IEnvironment, IStaticWorkspaceData } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
export const IExtensionStoragePaths = createDecorator<IExtensionStoragePaths>('IExtensionStoragePaths');
|
||||
|
||||
export interface IExtensionStoragePaths {
|
||||
readonly _serviceBrand: undefined;
|
||||
whenReady: Promise<any>;
|
||||
workspaceValue(extension: IExtensionDescription): string | undefined;
|
||||
globalValue(extension: IExtensionDescription): string;
|
||||
workspaceValue(extension: IExtensionDescription): URI | undefined;
|
||||
globalValue(extension: IExtensionDescription): URI;
|
||||
}
|
||||
|
||||
export class ExtensionStoragePaths implements IExtensionStoragePaths {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _workspace?: IStaticWorkspaceData;
|
||||
private readonly _environment: IEnvironment;
|
||||
|
||||
readonly whenReady: Promise<URI | undefined>;
|
||||
private _value?: URI;
|
||||
|
||||
constructor(
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IExtHostConsumerFileSystem private readonly _extHostFileSystem: IExtHostConsumerFileSystem
|
||||
) {
|
||||
this._workspace = initData.workspace ?? undefined;
|
||||
this._environment = initData.environment;
|
||||
this.whenReady = this._getOrCreateWorkspaceStoragePath().then(value => this._value = value);
|
||||
}
|
||||
|
||||
private async _getOrCreateWorkspaceStoragePath(): Promise<URI | undefined> {
|
||||
if (!this._workspace) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
const storageName = this._workspace.id;
|
||||
const storageUri = URI.joinPath(this._environment.workspaceStorageHome, storageName);
|
||||
|
||||
try {
|
||||
await this._extHostFileSystem.stat(storageUri);
|
||||
this._logService.trace('[ExtHostStorage] storage dir already exists', storageUri);
|
||||
return storageUri;
|
||||
} catch {
|
||||
// doesn't exist, that's OK
|
||||
}
|
||||
|
||||
try {
|
||||
this._logService.trace('[ExtHostStorage] creating dir and metadata-file', storageUri);
|
||||
await this._extHostFileSystem.createDirectory(storageUri);
|
||||
await this._extHostFileSystem.writeFile(
|
||||
URI.joinPath(storageUri, 'meta.json'),
|
||||
new TextEncoder().encode(JSON.stringify({
|
||||
id: this._workspace.id,
|
||||
configuration: URI.revive(this._workspace.configuration)?.toString(),
|
||||
name: this._workspace.name
|
||||
}, undefined, 2))
|
||||
);
|
||||
return storageUri;
|
||||
|
||||
} catch (e) {
|
||||
this._logService.error('[ExtHostStorage]', e);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
workspaceValue(extension: IExtensionDescription): URI | undefined {
|
||||
if (this._value) {
|
||||
return URI.joinPath(this._value, extension.identifier.value);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
globalValue(extension: IExtensionDescription): URI {
|
||||
return URI.joinPath(this._environment.globalStorageHome, extension.identifier.value.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import * as Objects from 'vs/base/common/objects';
|
||||
import { asPromise } from 'vs/base/common/async';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
|
||||
@@ -27,6 +26,7 @@ import * as Platform from 'vs/base/common/platform';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
||||
import { USER_TASKS_GROUP_KEY } from 'vs/workbench/contrib/tasks/common/taskService';
|
||||
import { NotSupportedError } from 'vs/base/common/errors';
|
||||
|
||||
export interface IExtHostTask extends ExtHostTaskShape {
|
||||
|
||||
@@ -325,7 +325,7 @@ export namespace TaskFilterDTO {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
return Objects.assign(Object.create(null), value);
|
||||
return Object.assign(Object.create(null), value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ export interface HandlerData {
|
||||
extension: IExtensionDescription;
|
||||
}
|
||||
|
||||
export abstract class ExtHostTaskBase implements ExtHostTaskShape {
|
||||
export abstract class ExtHostTaskBase implements ExtHostTaskShape, IExtHostTask {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
protected readonly _proxy: MainThreadTaskShape;
|
||||
@@ -679,7 +679,9 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract async $jsonTasksSupported(): Promise<boolean>;
|
||||
public abstract $jsonTasksSupported(): Promise<boolean>;
|
||||
|
||||
public abstract $findExecutable(command: string, cwd?: string | undefined, paths?: string[] | undefined): Promise<string | undefined>;
|
||||
}
|
||||
|
||||
export class WorkerExtHostTask extends ExtHostTaskBase {
|
||||
@@ -715,7 +717,7 @@ export class WorkerExtHostTask extends ExtHostTaskBase {
|
||||
if (CustomExecutionDTO.is(dto.execution)) {
|
||||
await this.addCustomExecution(dto, task, false);
|
||||
} else {
|
||||
throw new Error('Not implemented');
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
// Always get the task execution first to prevent timing issues when retrieving it later
|
||||
@@ -775,6 +777,10 @@ export class WorkerExtHostTask extends ExtHostTaskBase {
|
||||
public async $jsonTasksSupported(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public async $findExecutable(command: string, cwd?: string | undefined, paths?: string[] | undefined): Promise<string | undefined> {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export const IExtHostTask = createDecorator<IExtHostTask>('IExtHostTask');
|
||||
|
||||
@@ -18,6 +18,8 @@ import { Disposable as VSCodeDisposable, EnvironmentVariableMutatorType } from '
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { localize } from 'vs/nls';
|
||||
import { NotSupportedError } from 'vs/base/common/errors';
|
||||
import { serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared';
|
||||
|
||||
export interface IExtHostTerminalService extends ExtHostTerminalServiceShape {
|
||||
|
||||
@@ -312,6 +314,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
protected _terminalProcessDisposables: { [id: number]: IDisposable } = {};
|
||||
protected _extensionTerminalAwaitingStart: { [id: number]: { initialDimensions: ITerminalDimensionsDto | undefined } | undefined } = {};
|
||||
protected _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {};
|
||||
protected _environmentVariableCollections: Map<string, EnvironmentVariableCollection> = new Map();
|
||||
|
||||
private readonly _bufferer: TerminalDataBufferer;
|
||||
private readonly _linkHandlers: Set<vscode.TerminalLinkHandler> = new Set();
|
||||
@@ -351,8 +354,6 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
public abstract $getAvailableShells(): Promise<IShellDefinitionDto[]>;
|
||||
public abstract $getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto>;
|
||||
public abstract $acceptWorkspacePermissionsChanged(isAllowed: boolean): void;
|
||||
public abstract getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection;
|
||||
public abstract $initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void;
|
||||
|
||||
public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal {
|
||||
const terminal = new ExtHostTerminal(this._proxy, options, options.name);
|
||||
@@ -625,11 +626,10 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
for (const provideResult of provideResults) {
|
||||
if (provideResult && provideResult.links.length > 0) {
|
||||
result.push(...provideResult.links.map(providerLink => {
|
||||
const endIndex = Math.max(providerLink.endIndex, providerLink.startIndex + 1);
|
||||
const link = {
|
||||
id: nextLinkId++,
|
||||
startIndex: providerLink.startIndex,
|
||||
length: endIndex - providerLink.startIndex,
|
||||
length: providerLink.length,
|
||||
label: providerLink.tooltip
|
||||
};
|
||||
cacheLinkMap.set(link.id, {
|
||||
@@ -719,6 +719,39 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
});
|
||||
return index;
|
||||
}
|
||||
|
||||
public getEnvironmentVariableCollection(extension: IExtensionDescription): vscode.EnvironmentVariableCollection {
|
||||
let collection = this._environmentVariableCollections.get(extension.identifier.value);
|
||||
if (!collection) {
|
||||
collection = new EnvironmentVariableCollection();
|
||||
this._setEnvironmentVariableCollection(extension.identifier.value, collection);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
private _syncEnvironmentVariableCollection(extensionIdentifier: string, collection: EnvironmentVariableCollection): void {
|
||||
const serialized = serializeEnvironmentVariableCollection(collection.map);
|
||||
this._proxy.$setEnvironmentVariableCollection(extensionIdentifier, collection.persistent, serialized.length === 0 ? undefined : serialized);
|
||||
}
|
||||
|
||||
public $initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void {
|
||||
collections.forEach(entry => {
|
||||
const extensionIdentifier = entry[0];
|
||||
const collection = new EnvironmentVariableCollection(entry[1]);
|
||||
this._setEnvironmentVariableCollection(extensionIdentifier, collection);
|
||||
});
|
||||
}
|
||||
|
||||
private _setEnvironmentVariableCollection(extensionIdentifier: string, collection: EnvironmentVariableCollection): void {
|
||||
this._environmentVariableCollections.set(extensionIdentifier, collection);
|
||||
collection.onDidChangeCollection(() => {
|
||||
// When any collection value changes send this immediately, this is done to ensure
|
||||
// following calls to createTerminal will be created with the new environment. It will
|
||||
// result in more noise by sending multiple updates when called but collections are
|
||||
// expected to be small.
|
||||
this._syncEnvironmentVariableCollection(extensionIdentifier, collection!);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class EnvironmentVariableCollection implements vscode.EnvironmentVariableCollection {
|
||||
@@ -785,43 +818,35 @@ export class EnvironmentVariableCollection implements vscode.EnvironmentVariable
|
||||
|
||||
export class WorkerExtHostTerminalService extends BaseExtHostTerminalService {
|
||||
public createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal {
|
||||
throw new Error('Not implemented');
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal {
|
||||
throw new Error('Not implemented');
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string {
|
||||
throw new Error('Not implemented');
|
||||
// Return the empty string to avoid throwing
|
||||
return '';
|
||||
}
|
||||
|
||||
public getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string {
|
||||
throw new Error('Not implemented');
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<ITerminalLaunchError | undefined> {
|
||||
throw new Error('Not implemented');
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public $getAvailableShells(): Promise<IShellDefinitionDto[]> {
|
||||
throw new Error('Not implemented');
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public async $getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto> {
|
||||
throw new Error('Not implemented');
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public $acceptWorkspacePermissionsChanged(isAllowed: boolean): void {
|
||||
// No-op for web worker ext host as workspace permissions aren't used
|
||||
}
|
||||
|
||||
public getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection {
|
||||
// This is not implemented so worker ext host extensions cannot influence terminal envs
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
public $initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void {
|
||||
// No-op for web worker ext host as collections aren't used
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,9 +78,7 @@ export class ExtHostTimeline implements IExtHostTimeline {
|
||||
}
|
||||
|
||||
const result = await provider.provideTimeline(uri, options, token);
|
||||
// Intentional == we don't know how a provider will respond
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (result == null) {
|
||||
if (result === undefined || result === null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.proto
|
||||
import { ITreeItem, TreeViewItemHandleArg, ITreeItemLabel, IRevealOptions } from 'vs/workbench/common/views';
|
||||
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { asPromise } from 'vs/base/common/async';
|
||||
import { TreeItemCollapsibleState, ThemeIcon } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { TreeItemCollapsibleState, ThemeIcon, MarkdownString as MarkdownStringType } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { isUndefinedOrNull, isString } from 'vs/base/common/types';
|
||||
import { equals, coalesce } from 'vs/base/common/arrays';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
@@ -367,7 +367,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
if (node) {
|
||||
const resolve = await this.dataProvider.resolveTreeItem(element, node.extensionItem);
|
||||
// Resolvable elements. Currently only tooltip.
|
||||
node.item.tooltip = resolve.tooltip;
|
||||
node.item.tooltip = this.getTooltip(resolve.tooltip);
|
||||
return node.item;
|
||||
}
|
||||
}
|
||||
@@ -538,14 +538,11 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
}
|
||||
|
||||
private getTooltip(tooltip?: string | vscode.MarkdownString): string | IMarkdownString | undefined {
|
||||
if (typeof tooltip === 'string') {
|
||||
return tooltip;
|
||||
} else if (tooltip === undefined) {
|
||||
return undefined;
|
||||
} else {
|
||||
if (MarkdownStringType.isMarkdownString(tooltip)) {
|
||||
checkProposedApiEnabled(this.extension);
|
||||
return MarkdownString.from(tooltip);
|
||||
}
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
protected createTreeNode(element: T, extensionTreeItem: azdata.TreeItem2, parent: TreeNode | Root): TreeNode { // {{SQL CARBON EDIT}} change to protected, change to azdata.TreeItem
|
||||
|
||||
@@ -1271,6 +1271,13 @@ export class MarkdownString {
|
||||
this.value += '\n```\n';
|
||||
return this;
|
||||
}
|
||||
|
||||
static isMarkdownString(thing: any): thing is vscode.MarkdownString {
|
||||
if (thing instanceof MarkdownString) {
|
||||
return true;
|
||||
}
|
||||
return thing && thing.appendCodeblock && thing.appendMarkdown && thing.appendText && (thing.value !== undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
@@ -2770,7 +2777,7 @@ export enum ExtensionMode {
|
||||
|
||||
//#region Authentication
|
||||
export class AuthenticationSession implements vscode.AuthenticationSession {
|
||||
constructor(public id: string, public accessToken: string, public account: { displayName: string, id: string }, public scopes: string[]) { }
|
||||
constructor(public id: string, public accessToken: string, public account: { label: string, id: string }, public scopes: string[]) { }
|
||||
}
|
||||
|
||||
//#endregion Authentication
|
||||
|
||||
@@ -598,7 +598,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
|
||||
let storageRoot: URI | undefined;
|
||||
if (this.supportEditing(entry.provider) && this._extensionStoragePaths) {
|
||||
storageRoot = URI.file(this._extensionStoragePaths.workspaceValue(entry.extension) ?? this._extensionStoragePaths.globalValue(entry.extension));
|
||||
storageRoot = this._extensionStoragePaths.workspaceValue(entry.extension) ?? this._extensionStoragePaths.globalValue(entry.extension);
|
||||
}
|
||||
this._documents.add(viewType, document, storageRoot);
|
||||
|
||||
|
||||
@@ -345,7 +345,7 @@ namespace schema {
|
||||
type: 'string'
|
||||
},
|
||||
icon: {
|
||||
description: localize('vscode.extension.contributes.commandType.icon', '(Optional) Icon which is used to represent the command in the UI. Either a file path, an object with file paths for dark and light themes, or a theme icon references, like `$(zap)`'),
|
||||
description: localize('vscode.extension.contributes.commandType.icon', '(Optional) Icon which is used to represent the command in the UI. Either a file path, an object with file paths for dark and light themes, or a theme icon references, like `\\$(zap)`'),
|
||||
anyOf: [{
|
||||
type: 'string'
|
||||
},
|
||||
|
||||
138
src/vs/workbench/api/common/shared/workspaceContains.ts
Normal file
138
src/vs/workbench/api/common/shared/workspaceContains.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as path from 'vs/base/common/path';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { QueryBuilder } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
import { ISearchService } from 'vs/workbench/services/search/common/search';
|
||||
import { toWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
|
||||
const WORKSPACE_CONTAINS_TIMEOUT = 7000;
|
||||
|
||||
export interface IExtensionActivationHost {
|
||||
readonly folders: readonly UriComponents[];
|
||||
readonly forceUsingSearch: boolean;
|
||||
|
||||
exists(path: string): Promise<boolean>;
|
||||
checkExists(folders: readonly UriComponents[], includes: string[], token: CancellationToken): Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface IExtensionActivationResult {
|
||||
activationEvent: string;
|
||||
}
|
||||
|
||||
export function checkActivateWorkspaceContainsExtension(host: IExtensionActivationHost, desc: IExtensionDescription): Promise<IExtensionActivationResult | undefined> {
|
||||
const activationEvents = desc.activationEvents;
|
||||
if (!activationEvents) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const fileNames: string[] = [];
|
||||
const globPatterns: string[] = [];
|
||||
|
||||
for (const activationEvent of activationEvents) {
|
||||
if (/^workspaceContains:/.test(activationEvent)) {
|
||||
const fileNameOrGlob = activationEvent.substr('workspaceContains:'.length);
|
||||
if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0 || host.forceUsingSearch) {
|
||||
globPatterns.push(fileNameOrGlob);
|
||||
} else {
|
||||
fileNames.push(fileNameOrGlob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fileNames.length === 0 && globPatterns.length === 0) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
let resolveResult: (value: IExtensionActivationResult | undefined) => void;
|
||||
const result = new Promise<IExtensionActivationResult | undefined>((resolve, reject) => { resolveResult = resolve; });
|
||||
const activate = (activationEvent: string) => resolveResult({ activationEvent });
|
||||
|
||||
const fileNamePromise = Promise.all(fileNames.map((fileName) => _activateIfFileName(host, fileName, activate))).then(() => { });
|
||||
const globPatternPromise = _activateIfGlobPatterns(host, desc.identifier, globPatterns, activate);
|
||||
|
||||
Promise.all([fileNamePromise, globPatternPromise]).then(() => {
|
||||
// when all are done, resolve with undefined (relevant only if it was not activated so far)
|
||||
resolveResult(undefined);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async function _activateIfFileName(host: IExtensionActivationHost, fileName: string, activate: (activationEvent: string) => void): Promise<void> {
|
||||
// find exact path
|
||||
for (const uri of host.folders) {
|
||||
if (await host.exists(path.join(URI.revive(uri).fsPath, fileName))) {
|
||||
// the file was found
|
||||
activate(`workspaceContains:${fileName}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function _activateIfGlobPatterns(host: IExtensionActivationHost, extensionId: ExtensionIdentifier, globPatterns: string[], activate: (activationEvent: string) => void): Promise<void> {
|
||||
if (globPatterns.length === 0) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const tokenSource = new CancellationTokenSource();
|
||||
const searchP = host.checkExists(host.folders, globPatterns, tokenSource.token);
|
||||
|
||||
const timer = setTimeout(async () => {
|
||||
tokenSource.cancel();
|
||||
activate(`workspaceContainsTimeout:${globPatterns.join(',')}`);
|
||||
}, WORKSPACE_CONTAINS_TIMEOUT);
|
||||
|
||||
let exists: boolean = false;
|
||||
try {
|
||||
exists = await searchP;
|
||||
} catch (err) {
|
||||
if (!errors.isPromiseCanceledError(err)) {
|
||||
errors.onUnexpectedError(err);
|
||||
}
|
||||
}
|
||||
|
||||
tokenSource.dispose();
|
||||
clearTimeout(timer);
|
||||
|
||||
if (exists) {
|
||||
// a file was found matching one of the glob patterns
|
||||
activate(`workspaceContains:${globPatterns.join(',')}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function checkGlobFileExists(
|
||||
accessor: ServicesAccessor,
|
||||
folders: readonly UriComponents[],
|
||||
includes: string[],
|
||||
token: CancellationToken,
|
||||
): Promise<boolean> {
|
||||
const instantiationService = accessor.get(IInstantiationService);
|
||||
const searchService = accessor.get(ISearchService);
|
||||
const queryBuilder = instantiationService.createInstance(QueryBuilder);
|
||||
const query = queryBuilder.file(folders.map(folder => toWorkspaceFolder(URI.revive(folder))), {
|
||||
_reason: 'checkExists',
|
||||
includePattern: includes.join(', '),
|
||||
expandPatterns: true,
|
||||
exists: true
|
||||
});
|
||||
|
||||
return searchService.fileSearch(query, token).then(
|
||||
result => {
|
||||
return !!result.limitHit;
|
||||
},
|
||||
err => {
|
||||
if (!errors.isPromiseCanceledError(err)) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user