Implement and adopt edit session identifier API proposal (#157733)

* Add canonical workspace identifier proposed API

* Use canonical id to store and resume edit sessions

* Add git extension workspace identity provider

* Fix warning incorrectly showing up

* Make auto resume behavior opt in

* * Create a separate service
* Accept WorkspaceFolder instead of URI
* Return string instead of object

* Make edit session restores resilient to provider registration races

* Introduce an activation event
* Activate contributing extension before using provider

* `CanonicalWorkspaceIdentity` -> `EditSessionIdentity`

* Show progress while resuming edit session

* Store edit session even if extension will take care of opening target workspace

* Address most of PR feedback

* `IEditSessionsWorkbenchService` -> `IEditSessionsStorageService`

* Unregister provider in renderer

* Split out proposal into new `editSessionIdentityProvider.d.ts`

* Fix bad merge

* Always show progress in window

* Convert URI schemes
This commit is contained in:
Joyce Er
2022-08-19 08:01:43 -07:00
committed by GitHub
parent 4291d2b9d9
commit fa4ff1519d
23 changed files with 412 additions and 84 deletions

View File

@@ -7,13 +7,14 @@ import { delta as arrayDelta, mapArrayOrNot } from 'vs/base/common/arrays';
import { Barrier } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Emitter, Event } from 'vs/base/common/event';
import { toDisposable } from 'vs/base/common/lifecycle';
import { TernarySearchTree } from 'vs/base/common/map';
import { Schemas } from 'vs/base/common/network';
import { Counter } from 'vs/base/common/numbers';
import { basename, basenameOrAuthority, dirname, ExtUri, relativePath } from 'vs/base/common/resources';
import { compare } from 'vs/base/common/strings';
import { withUndefinedAsNull } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { URI, UriComponents } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
@@ -26,6 +27,7 @@ import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitData
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { GlobPattern } from 'vs/workbench/api/common/extHostTypeConverters';
import { Range } from 'vs/workbench/api/common/extHostTypes';
import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
import { ITextQueryBuilderOptions } from 'vs/workbench/services/search/common/queryBuilder';
import { IRawFileMatch2, resultIsMatch } from 'vs/workbench/services/search/common/search';
import * as vscode from 'vscode';
@@ -182,19 +184,24 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
private readonly _proxy: MainThreadWorkspaceShape;
private readonly _messageService: MainThreadMessageServiceShape;
private readonly _extHostFileSystemInfo: IExtHostFileSystemInfo;
private readonly _uriTransformerService: IURITransformerService;
private readonly _activeSearchCallbacks: ((match: IRawFileMatch2) => any)[] = [];
private _trusted: boolean = false;
private readonly _editSessionIdentityProviders = new Map<string, vscode.EditSessionIdentityProvider>();
constructor(
@IExtHostRpcService extHostRpc: IExtHostRpcService,
@IExtHostInitDataService initData: IExtHostInitDataService,
@IExtHostFileSystemInfo extHostFileSystemInfo: IExtHostFileSystemInfo,
@ILogService logService: ILogService,
@IURITransformerService uriTransformerService: IURITransformerService,
) {
this._logService = logService;
this._extHostFileSystemInfo = extHostFileSystemInfo;
this._uriTransformerService = uriTransformerService;
this._requestIdProvider = new Counter();
this._barrier = new Barrier();
@@ -573,6 +580,50 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
this._onDidGrantWorkspaceTrust.fire();
}
}
// --- edit sessions ---
// called by ext host
registerEditSessionIdentityProvider(scheme: string, provider: vscode.EditSessionIdentityProvider) {
if (this._editSessionIdentityProviders.has(scheme)) {
throw new Error(`A provider has already been registered for scheme ${scheme}`);
}
this._editSessionIdentityProviders.set(scheme, provider);
const outgoingScheme = this._uriTransformerService.transformOutgoingScheme(scheme);
this._proxy.$registerEditSessionIdentityProvider(outgoingScheme);
return toDisposable(() => {
this._editSessionIdentityProviders.delete(scheme);
this._proxy.$unregisterEditSessionIdentityProvider(outgoingScheme);
});
}
// called by main thread
async $getEditSessionIdentifier(workspaceFolder: UriComponents, cancellationToken: CancellationToken): Promise<string | undefined> {
this._logService.info('Getting edit session identifier for workspaceFolder', workspaceFolder);
const folder = await this.resolveWorkspaceFolder(URI.revive(workspaceFolder));
if (!folder) {
this._logService.warn('Unable to resolve workspace folder');
return undefined;
}
this._logService.info('Invoking #provideEditSessionIdentity for workspaceFolder', folder);
const provider = this._editSessionIdentityProviders.get(folder.uri.scheme);
this._logService.info(`Provider for scheme ${folder.uri.scheme} is defined: `, !!provider);
if (!provider) {
return undefined;
}
const result = await provider.provideEditSessionIdentity(folder, cancellationToken);
this._logService.info('Provider returned edit session identifier: ', result);
if (!result) {
return undefined;
}
return result;
}
}
export const IExtHostWorkspace = createDecorator<IExtHostWorkspace>('IExtHostWorkspace');