mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-24 17:23:05 -05:00
Merge from vscode e5834d3280fcd04898efeac32b9cf1b893f9b127 (#9385)
* Merge from vscode e5834d3280fcd04898efeac32b9cf1b893f9b127 * distro
This commit is contained in:
@@ -25,7 +25,7 @@ export class MainThreadAuthenticationProvider {
|
||||
return {
|
||||
id: session.id,
|
||||
accountName: session.accountName,
|
||||
accessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id)
|
||||
getAccessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id)
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -35,7 +35,7 @@ export class MainThreadAuthenticationProvider {
|
||||
return {
|
||||
id: session.id,
|
||||
accountName: session.accountName,
|
||||
accessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id)
|
||||
getAccessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id)
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -75,48 +75,52 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
||||
async $getSessionsPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean> {
|
||||
const alwaysAllow = this.storageService.get(`${extensionId}-${providerId}`, StorageScope.GLOBAL);
|
||||
if (alwaysAllow) {
|
||||
return true;
|
||||
return alwaysAllow === 'true';
|
||||
}
|
||||
|
||||
const { choice } = await this.dialogService.show(
|
||||
const { choice, checkboxChecked } = await this.dialogService.show(
|
||||
Severity.Info,
|
||||
nls.localize('confirmAuthenticationAccess', "The extension '{0}' is trying to access authentication information from {1}.", extensionName, providerName),
|
||||
[nls.localize('cancel', "Cancel"), nls.localize('allow', "Allow"), nls.localize('alwaysAllow', "Always Allow"),],
|
||||
{ cancelId: 0 }
|
||||
[nls.localize('cancel', "Cancel"), nls.localize('allow', "Allow")],
|
||||
{
|
||||
cancelId: 0,
|
||||
checkbox: {
|
||||
label: nls.localize('neverAgain', "Don't Show Again")
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
switch (choice) {
|
||||
case 1/** Allow */:
|
||||
return true;
|
||||
case 2 /** Always Allow */:
|
||||
this.storageService.store(`${extensionId}-${providerId}`, 'true', StorageScope.GLOBAL);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
const allow = choice === 1;
|
||||
if (checkboxChecked) {
|
||||
this.storageService.store(`${extensionId}-${providerId}`, allow ? 'true' : 'false', StorageScope.GLOBAL);
|
||||
}
|
||||
|
||||
return allow;
|
||||
}
|
||||
|
||||
async $loginPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean> {
|
||||
const alwaysAllow = this.storageService.get(`${extensionId}-${providerId}`, StorageScope.GLOBAL);
|
||||
if (alwaysAllow) {
|
||||
return true;
|
||||
return alwaysAllow === 'true';
|
||||
}
|
||||
|
||||
const { choice } = await this.dialogService.show(
|
||||
const { choice, checkboxChecked } = await this.dialogService.show(
|
||||
Severity.Info,
|
||||
nls.localize('confirmLogin', "The extension '{0}' wants to sign in using {1}.", extensionName, providerName),
|
||||
[nls.localize('cancel', "Cancel"), nls.localize('continue', "Continue"), nls.localize('neverAgain', "Don't Show Again")],
|
||||
{ cancelId: 0 }
|
||||
[nls.localize('cancel', "Cancel"), nls.localize('continue', "Continue")],
|
||||
{
|
||||
cancelId: 0,
|
||||
checkbox: {
|
||||
label: nls.localize('neverAgain', "Don't Show Again")
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
switch (choice) {
|
||||
case 1/** Allow */:
|
||||
return true;
|
||||
case 2 /** Always Allow */:
|
||||
this.storageService.store(`${extensionId}-${providerId}`, 'true', StorageScope.GLOBAL);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
const allow = choice === 1;
|
||||
if (checkboxChecked) {
|
||||
this.storageService.store(`${extensionId}-${providerId}`, allow ? 'true' : 'false', StorageScope.GLOBAL);
|
||||
}
|
||||
|
||||
return allow;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
this._register(_webviewWorkbenchService.registerResolver({
|
||||
canResolve: (webview: WebviewInput) => {
|
||||
if (webview instanceof CustomEditorInput) {
|
||||
extensionService.activateByEvent(`onWebviewEditor:${webview.viewType}`);
|
||||
extensionService.activateByEvent(`onCustomEditor:${webview.viewType}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -624,7 +624,7 @@ export interface ExtHostWebviewsShape {
|
||||
$onSave(resource: UriComponents, viewType: string): Promise<void>;
|
||||
$onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents): Promise<void>;
|
||||
|
||||
$backup(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<boolean>;
|
||||
$backup(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void>;
|
||||
}
|
||||
|
||||
export interface MainThreadUrlsShape extends IDisposable {
|
||||
|
||||
@@ -34,7 +34,7 @@ export class AuthenticationProviderWrapper implements vscode.AuthenticationProvi
|
||||
id: session.id,
|
||||
accountName: session.accountName,
|
||||
scopes: session.scopes,
|
||||
accessToken: async () => {
|
||||
getAccessToken: async () => {
|
||||
const isAllowed = await this._proxy.$getSessionsPrompt(
|
||||
this._provider.id,
|
||||
this.displayName,
|
||||
@@ -45,7 +45,7 @@ export class AuthenticationProviderWrapper implements vscode.AuthenticationProvi
|
||||
throw new Error('User did not consent to token access.');
|
||||
}
|
||||
|
||||
return session.accessToken();
|
||||
return session.getAccessToken();
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -60,7 +60,7 @@ export class AuthenticationProviderWrapper implements vscode.AuthenticationProvi
|
||||
return this._provider.login(scopes);
|
||||
}
|
||||
|
||||
logout(sessionId: string): Promise<void> {
|
||||
logout(sessionId: string): Thenable<void> {
|
||||
return this._provider.logout(sessionId);
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
const sessions = await authProvider.getSessions();
|
||||
const session = sessions.find(session => session.id === sessionId);
|
||||
if (session) {
|
||||
return session.accessToken();
|
||||
return session.getAccessToken();
|
||||
}
|
||||
|
||||
throw new Error(`Unable to find session with id: ${sessionId}`);
|
||||
|
||||
@@ -71,11 +71,17 @@ export class ExtHostTimeline implements IExtHostTimeline {
|
||||
scheme: scheme,
|
||||
onDidChange: undefined,
|
||||
async provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: { cacheResults?: boolean }) {
|
||||
timelineDisposables.clear();
|
||||
|
||||
// For now, only allow the caching of a single Uri
|
||||
if (internalOptions?.cacheResults && !itemsBySourceByUriMap.has(getUriKey(uri))) {
|
||||
itemsBySourceByUriMap.clear();
|
||||
if (internalOptions?.cacheResults) {
|
||||
if (options.cursor === undefined) {
|
||||
timelineDisposables.clear();
|
||||
}
|
||||
|
||||
if (!itemsBySourceByUriMap.has(getUriKey(uri))) {
|
||||
itemsBySourceByUriMap.clear();
|
||||
}
|
||||
} else {
|
||||
timelineDisposables.clear();
|
||||
}
|
||||
|
||||
const result = await provider.provideTimeline(uri, options, token);
|
||||
|
||||
@@ -247,143 +247,160 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa
|
||||
|
||||
type EditType = unknown;
|
||||
|
||||
class WebviewEditorCustomDocument extends Disposable implements vscode.CustomDocument {
|
||||
private _currentEditIndex: number = -1;
|
||||
private _savePoint: number = -1;
|
||||
private readonly _edits: Array<EditType> = [];
|
||||
class CustomDocument extends Disposable implements vscode.CustomDocument {
|
||||
|
||||
public userData: unknown;
|
||||
|
||||
public _capabilities?: vscode.CustomEditorCapabilities = undefined;
|
||||
|
||||
constructor(
|
||||
private readonly _proxy: MainThreadWebviewsShape,
|
||||
public readonly viewType: string,
|
||||
public readonly uri: vscode.Uri,
|
||||
) {
|
||||
super();
|
||||
public static create(proxy: MainThreadWebviewsShape, viewType: string, uri: vscode.Uri) {
|
||||
return Object.seal(new CustomDocument(proxy, viewType, uri));
|
||||
}
|
||||
|
||||
_setCapabilities(capabilities: vscode.CustomEditorCapabilities) {
|
||||
if (this._capabilities) {
|
||||
throw new Error('Capabilities already provided');
|
||||
}
|
||||
// Explicitly initialize all properties as we seal the object after creation!
|
||||
|
||||
this._capabilities = capabilities;
|
||||
capabilities.editing?.onDidEdit(edit => {
|
||||
this.pushEdit(edit, this);
|
||||
});
|
||||
#currentEditIndex: number = -1;
|
||||
#savePoint: number = -1;
|
||||
readonly #edits: Array<EditType> = [];
|
||||
|
||||
readonly #proxy: MainThreadWebviewsShape;
|
||||
readonly #viewType: string;
|
||||
readonly #uri: vscode.Uri;
|
||||
|
||||
#capabilities: vscode.CustomEditorCapabilities | undefined = undefined;
|
||||
|
||||
private constructor(proxy: MainThreadWebviewsShape, viewType: string, uri: vscode.Uri) {
|
||||
super();
|
||||
this.#proxy = proxy;
|
||||
this.#viewType = viewType;
|
||||
this.#uri = uri;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.#onDidDispose.fire();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
//#region Public API
|
||||
|
||||
#_onDidDispose = this._register(new Emitter<void>());
|
||||
public readonly onDidDispose = this.#_onDidDispose.event;
|
||||
public get viewType(): string { return this.#viewType; }
|
||||
|
||||
public get uri(): vscode.Uri { return this.#uri; }
|
||||
|
||||
#onDidDispose = this._register(new Emitter<void>());
|
||||
public readonly onDidDispose = this.#onDidDispose.event;
|
||||
|
||||
public userData: unknown = undefined;
|
||||
|
||||
//#endregion
|
||||
|
||||
dispose() {
|
||||
this.#_onDidDispose.fire();
|
||||
super.dispose();
|
||||
//#region Internal
|
||||
|
||||
/** @internal*/ _setCapabilities(capabilities: vscode.CustomEditorCapabilities) {
|
||||
if (this.#capabilities) {
|
||||
throw new Error('Capabilities already provided');
|
||||
}
|
||||
|
||||
this.#capabilities = capabilities;
|
||||
capabilities.editing?.onDidEdit(edit => {
|
||||
this.pushEdit(edit);
|
||||
});
|
||||
}
|
||||
|
||||
private pushEdit(edit: EditType, trigger: any) {
|
||||
this.spliceEdits(edit);
|
||||
|
||||
this._currentEditIndex = this._edits.length - 1;
|
||||
this.updateState();
|
||||
// this._onApplyEdit.fire({ edits: [edit], trigger });
|
||||
}
|
||||
|
||||
private updateState() {
|
||||
const dirty = this._edits.length > 0 && this._savePoint !== this._currentEditIndex;
|
||||
this._proxy.$onDidChangeCustomDocumentState(this.uri, this.viewType, { dirty });
|
||||
}
|
||||
|
||||
private spliceEdits(editToInsert?: EditType) {
|
||||
const start = this._currentEditIndex + 1;
|
||||
const toRemove = this._edits.length - this._currentEditIndex;
|
||||
|
||||
editToInsert
|
||||
? this._edits.splice(start, toRemove, editToInsert)
|
||||
: this._edits.splice(start, toRemove);
|
||||
}
|
||||
|
||||
revert() {
|
||||
/** @internal*/ _revert() {
|
||||
const editing = this.getEditingCapability();
|
||||
if (this._currentEditIndex === this._savePoint) {
|
||||
if (this.#currentEditIndex === this.#savePoint) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this._currentEditIndex >= this._savePoint) {
|
||||
const editsToUndo = this._edits.slice(this._savePoint, this._currentEditIndex);
|
||||
if (this.#currentEditIndex >= this.#savePoint) {
|
||||
const editsToUndo = this.#edits.slice(this.#savePoint, this.#currentEditIndex);
|
||||
editing.undoEdits(editsToUndo.reverse());
|
||||
} else if (this._currentEditIndex < this._savePoint) {
|
||||
const editsToRedo = this._edits.slice(this._currentEditIndex, this._savePoint);
|
||||
} else if (this.#currentEditIndex < this.#savePoint) {
|
||||
const editsToRedo = this.#edits.slice(this.#currentEditIndex, this.#savePoint);
|
||||
editing.applyEdits(editsToRedo);
|
||||
}
|
||||
|
||||
this._currentEditIndex = this._savePoint;
|
||||
this.#currentEditIndex = this.#savePoint;
|
||||
this.spliceEdits();
|
||||
|
||||
this.updateState();
|
||||
return true;
|
||||
}
|
||||
|
||||
undo() {
|
||||
/** @internal*/ _undo() {
|
||||
const editing = this.getEditingCapability();
|
||||
if (this._currentEditIndex < 0) {
|
||||
if (this.#currentEditIndex < 0) {
|
||||
// nothing to undo
|
||||
return;
|
||||
}
|
||||
|
||||
const undoneEdit = this._edits[this._currentEditIndex];
|
||||
--this._currentEditIndex;
|
||||
const undoneEdit = this.#edits[this.#currentEditIndex];
|
||||
--this.#currentEditIndex;
|
||||
editing.undoEdits([undoneEdit]);
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
redo() {
|
||||
/** @internal*/ _redo() {
|
||||
const editing = this.getEditingCapability();
|
||||
if (this._currentEditIndex >= this._edits.length - 1) {
|
||||
if (this.#currentEditIndex >= this.#edits.length - 1) {
|
||||
// nothing to redo
|
||||
return;
|
||||
}
|
||||
|
||||
++this._currentEditIndex;
|
||||
const redoneEdit = this._edits[this._currentEditIndex];
|
||||
++this.#currentEditIndex;
|
||||
const redoneEdit = this.#edits[this.#currentEditIndex];
|
||||
editing.applyEdits([redoneEdit]);
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
save() {
|
||||
/** @internal*/ _save() {
|
||||
return this.getEditingCapability().save();
|
||||
}
|
||||
|
||||
saveAs(target: vscode.Uri) {
|
||||
/** @internal*/ _saveAs(target: vscode.Uri) {
|
||||
return this.getEditingCapability().saveAs(target);
|
||||
}
|
||||
|
||||
backup(cancellation: CancellationToken) {
|
||||
/** @internal*/ _backup(cancellation: CancellationToken) {
|
||||
return this.getEditingCapability().backup(cancellation);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
private pushEdit(edit: EditType) {
|
||||
this.spliceEdits(edit);
|
||||
|
||||
this.#currentEditIndex = this.#edits.length - 1;
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
private updateState() {
|
||||
const dirty = this.#edits.length > 0 && this.#savePoint !== this.#currentEditIndex;
|
||||
this.#proxy.$onDidChangeCustomDocumentState(this.uri, this.viewType, { dirty });
|
||||
}
|
||||
|
||||
private spliceEdits(editToInsert?: EditType) {
|
||||
const start = this.#currentEditIndex + 1;
|
||||
const toRemove = this.#edits.length - this.#currentEditIndex;
|
||||
|
||||
editToInsert
|
||||
? this.#edits.splice(start, toRemove, editToInsert)
|
||||
: this.#edits.splice(start, toRemove);
|
||||
}
|
||||
|
||||
private getEditingCapability(): vscode.CustomEditorEditingCapability {
|
||||
if (!this._capabilities?.editing) {
|
||||
if (!this.#capabilities?.editing) {
|
||||
throw new Error('Document is not editable');
|
||||
}
|
||||
return this._capabilities.editing;
|
||||
return this.#capabilities.editing;
|
||||
}
|
||||
}
|
||||
|
||||
class WebviewDocumentStore {
|
||||
private readonly _documents = new Map<string, WebviewEditorCustomDocument>();
|
||||
private readonly _documents = new Map<string, CustomDocument>();
|
||||
|
||||
public get(viewType: string, resource: vscode.Uri): WebviewEditorCustomDocument | undefined {
|
||||
public get(viewType: string, resource: vscode.Uri): CustomDocument | undefined {
|
||||
return this._documents.get(this.key(viewType, resource));
|
||||
}
|
||||
|
||||
public add(document: WebviewEditorCustomDocument) {
|
||||
public add(document: CustomDocument) {
|
||||
const key = this.key(document.viewType, document.uri);
|
||||
if (this._documents.has(key)) {
|
||||
throw new Error(`Document already exists for viewType:${document.viewType} resource:${document.uri}`);
|
||||
@@ -391,7 +408,7 @@ class WebviewDocumentStore {
|
||||
this._documents.set(key, document);
|
||||
}
|
||||
|
||||
public delete(document: WebviewEditorCustomDocument) {
|
||||
public delete(document: CustomDocument) {
|
||||
const key = this.key(document.viewType, document.uri);
|
||||
this._documents.delete(key);
|
||||
}
|
||||
@@ -622,7 +639,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
const revivedResource = URI.revive(resource);
|
||||
const document = Object.seal(new WebviewEditorCustomDocument(this._proxy, viewType, revivedResource));
|
||||
const document = CustomDocument.create(this._proxy, viewType, revivedResource);
|
||||
const capabilities = await entry.provider.resolveCustomDocument(document);
|
||||
document._setCapabilities(capabilities);
|
||||
this._documents.add(document);
|
||||
@@ -687,39 +704,39 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
|
||||
async $undo(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
||||
const document = this.getDocument(viewType, resourceComponents);
|
||||
document.undo();
|
||||
document._undo();
|
||||
}
|
||||
|
||||
async $redo(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
||||
const document = this.getDocument(viewType, resourceComponents);
|
||||
document.redo();
|
||||
document._redo();
|
||||
}
|
||||
|
||||
async $revert(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
||||
const document = this.getDocument(viewType, resourceComponents);
|
||||
document.revert();
|
||||
document._revert();
|
||||
}
|
||||
|
||||
async $onSave(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
||||
const document = this.getDocument(viewType, resourceComponents);
|
||||
document.save();
|
||||
document._save();
|
||||
}
|
||||
|
||||
async $onSaveAs(resourceComponents: UriComponents, viewType: string, targetResource: UriComponents): Promise<void> {
|
||||
const document = this.getDocument(viewType, resourceComponents);
|
||||
return document.saveAs(URI.revive(targetResource));
|
||||
return document._saveAs(URI.revive(targetResource));
|
||||
}
|
||||
|
||||
async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise<boolean> {
|
||||
async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void> {
|
||||
const document = this.getDocument(viewType, resourceComponents);
|
||||
return document.backup(cancellation);
|
||||
return document._backup(cancellation);
|
||||
}
|
||||
|
||||
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewEditor | undefined {
|
||||
return this._webviewPanels.get(handle);
|
||||
}
|
||||
|
||||
private getDocument(viewType: string, resource: UriComponents): WebviewEditorCustomDocument {
|
||||
private getDocument(viewType: string, resource: UriComponents): CustomDocument {
|
||||
const document = this._documents.get(viewType, URI.revive(resource));
|
||||
if (!document) {
|
||||
throw new Error('No webview editor custom document found');
|
||||
|
||||
Reference in New Issue
Block a user