Merge from vscode 79a1f5a5ca0c6c53db617aa1fa5a2396d2caebe2

This commit is contained in:
ADS Merger
2020-05-31 19:47:51 +00:00
parent 84492049e8
commit 28be33cfea
913 changed files with 28242 additions and 15549 deletions

View File

@@ -8,11 +8,12 @@ import * as objects from 'vs/base/common/objects';
import { Registry } from 'vs/platform/registry/common/platform';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { ExtensionsRegistry, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { IConfigurationNode, IConfigurationRegistry, Extensions, resourceLanguageSettingsSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { IConfigurationNode, IConfigurationRegistry, Extensions, resourceLanguageSettingsSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { workspaceSettingsSchemaId, launchSchemaId, tasksSchemaId } from 'vs/workbench/services/configuration/common/configuration';
import { isObject } from 'vs/base/common/types';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IStringDictionary } from 'vs/base/common/collections';
const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
@@ -116,7 +117,13 @@ defaultConfigurationExtPoint.setHandler((extensions, { added, removed }) => {
const addedDefaultConfigurations = added.map(extension => {
const id = extension.description.identifier;
const name = extension.description.name;
const defaults = objects.deepClone(extension.value);
const defaults: IStringDictionary<any> = objects.deepClone(extension.value);
for (const key of Object.keys(defaults)) {
if (!OVERRIDE_PROPERTY_PATTERN.test(key) || typeof defaults[key] !== 'object') {
extension.collector.warn(nls.localize('config.property.defaultConfiguration.warning', "Cannot register configuration defaults for '{0}'. Only defaults for language specific settings are supported.", key));
delete defaults[key];
}
}
return <IDefaultConfigurationExtension>{
id, name, defaults
};

View File

@@ -135,7 +135,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol));
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors));
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, initData.environment));
const extHostTheming = rpcProtocol.set(ExtHostContext.ExtHostTheming, new ExtHostTheming(rpcProtocol));
const extHostAuthentication = rpcProtocol.set(ExtHostContext.ExtHostAuthentication, new ExtHostAuthentication(rpcProtocol));
const extHostTimeline = rpcProtocol.set(ExtHostContext.ExtHostTimeline, new ExtHostTimeline(rpcProtocol, extHostCommands));
@@ -196,9 +196,18 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
get onDidChangeAuthenticationProviders(): Event<vscode.AuthenticationProvidersChangeEvent> {
return extHostAuthentication.onDidChangeAuthenticationProviders;
},
getProviderIds(): Thenable<ReadonlyArray<string>> {
return extHostAuthentication.getProviderIds();
},
get providerIds(): string[] {
return extHostAuthentication.providerIds;
},
hasSessions(providerId: string, scopes: string[]): Thenable<boolean> {
return extHostAuthentication.hasSessions(providerId, scopes);
},
getSession(providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions) {
return extHostAuthentication.getSession(extension, providerId, scopes, options as any);
},
getSessions(providerId: string, scopes: string[]): Thenable<readonly vscode.AuthenticationSession[]> {
return extHostAuthentication.getSessions(extension, providerId, scopes);
},
@@ -265,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; },
get appRoot() { return initData.environment.appRoot?.fsPath ?? '<UNKNOWN_APP_ROOT>'; },
get uriScheme() { return initData.environment.appUriScheme; },
get logLevel() {
checkProposedApiEnabled(extension);
@@ -428,6 +437,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
},
setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => {
return extHostLanguageFeatures.setLanguageConfiguration(extension, language, configuration);
},
getTokenInformationAtPosition(doc: vscode.TextDocument, pos: vscode.Position) {
checkProposedApiEnabled(extension);
return extHostLanguages.tokenAtPosition(doc, pos);
}
};
@@ -528,12 +541,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
let id: string;
let name: string;
let alignment: number | undefined;
let accessibilityInformation: vscode.AccessibilityInformation | undefined = undefined;
if (alignmentOrOptions && typeof alignmentOrOptions !== 'number') {
id = alignmentOrOptions.id;
name = alignmentOrOptions.name;
alignment = alignmentOrOptions.alignment;
priority = alignmentOrOptions.priority;
accessibilityInformation = alignmentOrOptions.accessibilityInformation;
} else {
id = extension.identifier.value;
name = nls.localize('extensionLabel', "{0} (Extension)", extension.displayName || extension.name);
@@ -541,7 +556,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
priority = priority;
}
return extHostStatusBar.createStatusBarEntry(id, name, alignment, priority);
return extHostStatusBar.createStatusBarEntry(id, name, alignment, priority, accessibilityInformation);
},
setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable<any>): vscode.Disposable {
return extHostStatusBar.setStatusBarMessage(text, timeoutOrThenable);
@@ -703,8 +718,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
}
return uriPromise.then(uri => {
return extHostDocuments.ensureDocumentData(uri).then(() => {
return extHostDocuments.getDocument(uri);
return extHostDocuments.ensureDocumentData(uri).then(documentData => {
return documentData.document;
});
});
},
@@ -931,10 +946,20 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostNotebook.onDidCloseNotebookDocument;
},
get visibleNotebookEditors() {
return extHostNotebook.visibleNotebookEditors;
},
get onDidChangeVisibleNotebookEditors() {
return extHostNotebook.onDidChangeVisibleNotebookEditors;
},
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider);
},
registerNotebookKernel: (id: string, selector: vscode.GlobPattern[], kernel: vscode.NotebookKernel) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookKernel(extension, id, selector, kernel);
},
registerNotebookOutputRenderer: (type: string, outputFilter: vscode.NotebookOutputSelector, renderer: vscode.NotebookOutputRenderer) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookOutputRenderer(type, extension, outputFilter, renderer);
@@ -947,9 +972,21 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostNotebook.activeNotebookEditor;
},
onDidChangeNotebookDocument(listener, thisArgs?, disposables?) {
onDidChangeActiveNotebookEditor(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidChangeNotebookDocument(listener, thisArgs, disposables);
return extHostNotebook.onDidChangeActiveNotebookEditor(listener, thisArgs, disposables);
},
onDidChangeNotebookCells(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidChangeNotebookCells(listener, thisArgs, disposables);
},
onDidChangeCellOutputs(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidChangeCellOutputs(listener, thisArgs, disposables);
},
onDidChangeCellLanguage(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidChangeCellLanguage(listener, thisArgs, disposables);
},
createConcatTextDocument(notebook, selector) {
checkProposedApiEnabled(extension);
@@ -1050,6 +1087,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
SnippetString: extHostTypes.SnippetString,
SourceBreakpoint: extHostTypes.SourceBreakpoint,
SourceControlInputBoxValidationType: extHostTypes.SourceControlInputBoxValidationType,
StandardTokenType: extHostTypes.StandardTokenType,
StatusBarAlignment: extHostTypes.StatusBarAlignment,
SymbolInformation: extHostTypes.SymbolInformation,
SymbolKind: extHostTypes.SymbolKind,
@@ -1086,7 +1124,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
TimelineItem: extHostTypes.TimelineItem,
CellKind: extHostTypes.CellKind,
CellOutputKind: extHostTypes.CellOutputKind,
NotebookCellRunState: extHostTypes.NotebookCellRunState
NotebookCellRunState: extHostTypes.NotebookCellRunState,
AuthenticationSession2: extHostTypes.AuthenticationSession
};
};
}

View File

@@ -51,11 +51,12 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
import { revive } from 'vs/base/common/marshalling';
import { INotebookMimeTypeSelector, IOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookMimeTypeSelector, IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, IOutputRenderRequest, IOutputRenderResponse, IRawOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { Dto } from 'vs/base/common/types';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/extHostTypes';
import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility';
// {{SQL CARBON EDIT}}
import { ITreeItem as sqlITreeItem } from 'sql/workbench/common/views';
@@ -161,12 +162,20 @@ export interface MainThreadCommentsShape extends IDisposable {
}
export interface MainThreadAuthenticationShape extends IDisposable {
$registerAuthenticationProvider(id: string, displayName: string): void;
$registerAuthenticationProvider(id: string, displayName: string, supportsMultipleAccounts: boolean): void;
$unregisterAuthenticationProvider(id: string): void;
$onDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void;
$getProviderIds(): Promise<string[]>;
$sendDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void;
$getSession(providerId: string, scopes: string[], extensionId: string, extensionName: string, options: { createIfNone?: boolean, clearSessionPreference?: boolean }): Promise<modes.AuthenticationSession | undefined>;
$selectSession(providerId: string, providerName: string, extensionId: string, extensionName: string, potentialSessions: modes.AuthenticationSession[], scopes: string[], clearSessionPreference: boolean): Promise<modes.AuthenticationSession>;
$getSessionsPrompt(providerId: string, accountName: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean>;
$loginPrompt(providerName: string, extensionName: string): Promise<boolean>;
$setTrustedExtension(providerId: string, accountName: string, extensionId: string, extensionName: string): Promise<void>;
$requestNewSession(providerId: string, scopes: string[], extensionId: string, extensionName: string): Promise<void>;
$getSessions(providerId: string): Promise<ReadonlyArray<modes.AuthenticationSession>>;
$login(providerId: string, scopes: string[]): Promise<modes.AuthenticationSession>;
$logout(providerId: string, sessionId: string): Promise<void>;
}
export interface MainThreadConfigurationShape extends IDisposable {
@@ -215,7 +224,7 @@ export interface MainThreadDocumentContentProvidersShape extends IDisposable {
export interface MainThreadDocumentsShape extends IDisposable {
$tryCreateDocument(options?: { language?: string; content?: string; }): Promise<UriComponents>;
$tryOpenDocument(uri: UriComponents): Promise<void>;
$tryOpenDocument(uri: UriComponents): Promise<UriComponents>;
$trySaveDocument(uri: UriComponents): Promise<boolean>;
}
@@ -394,6 +403,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
export interface MainThreadLanguagesShape extends IDisposable {
$getLanguages(): Promise<string[]>;
$changeLanguage(resource: UriComponents, languageId: string): Promise<void>;
$tokensAtPosition(resource: UriComponents, position: IPosition): Promise<undefined | { type: modes.StandardTokenType, range: IRange }>;
}
export interface MainThreadMessageOptions {
@@ -547,7 +557,7 @@ export interface MainThreadQuickOpenShape extends IDisposable {
}
export interface MainThreadStatusBarShape extends IDisposable {
$setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: ICommandDto | undefined, color: string | ThemeColor | undefined, alignment: statusbar.StatusbarAlignment, priority: number | undefined): void;
$setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: ICommandDto | undefined, color: string | ThemeColor | undefined, alignment: statusbar.StatusbarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): void;
$dispose(id: number): void;
}
@@ -674,7 +684,7 @@ export interface ICellDto {
source: string[];
language: string;
cellKind: CellKind;
outputs: IOutput[];
outputs: IProcessedOutput[];
metadata?: NotebookCellMetadata;
}
@@ -687,14 +697,17 @@ export type NotebookCellsSplice = [
export type NotebookCellOutputsSplice = [
number /* start */,
number /* delete count */,
IOutput[]
IRawOutput[]
];
export interface MainThreadNotebookShape extends IDisposable {
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string): Promise<void>;
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, kernelInfoDto: INotebookKernelInfoDto | undefined): Promise<void>;
$onNotebookChange(viewType: string, resource: UriComponents): Promise<void>;
$unregisterNotebookProvider(viewType: string): Promise<void>;
$registerNotebookRenderer(extension: NotebookExtensionDescription, type: string, selectors: INotebookMimeTypeSelector, handle: number, preloads: UriComponents[]): Promise<void>;
$unregisterNotebookRenderer(handle: number): Promise<void>;
$registerNotebookRenderer(extension: NotebookExtensionDescription, type: string, selectors: INotebookMimeTypeSelector, preloads: UriComponents[]): Promise<void>;
$unregisterNotebookRenderer(id: string): Promise<void>;
$registerNotebookKernel(extension: NotebookExtensionDescription, id: string, label: string, selectors: (string | IRelativePattern)[], preloads: UriComponents[]): Promise<void>;
$unregisterNotebookKernel(id: string): Promise<void>;
$tryApplyEdits(viewType: string, resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[], renderers: number[]): Promise<boolean>;
$updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void>;
$updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise<void>;
@@ -1006,6 +1019,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>;
}
export interface ExtHostSearchShape {
@@ -1539,30 +1554,44 @@ export interface INotebookSelectionChangeEvent {
export interface INotebookEditorPropertiesChangeData {
selections: INotebookSelectionChangeEvent | null;
metadata: NotebookDocumentMetadata | null;
}
export interface INotebookModelAddedData {
uri: UriComponents;
handle: number;
// versionId: number;
versionId: number;
cells: IMainCellDto[],
viewType: string;
metadata?: NotebookDocumentMetadata;
attachedEditor?: { id: string; selections: number[]; }
}
export interface INotebookEditorAddData {
id: string;
documentUri: UriComponents;
selections: number[];
}
export interface INotebookDocumentsAndEditorsDelta {
removedDocuments?: UriComponents[];
addedDocuments?: INotebookModelAddedData[];
// removedEditors?: string[];
// addedEditors?: ITextEditorAddData[];
newActiveEditor?: UriComponents | null;
removedEditors?: string[];
addedEditors?: INotebookEditorAddData[];
newActiveEditor?: string | null;
visibleEditors?: string[];
}
export interface ExtHostNotebookShape {
$resolveNotebookData(viewType: string, uri: UriComponents): Promise<NotebookDataDto | undefined>;
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, token: CancellationToken): Promise<void>;
$executeNotebook2(kernelId: string, viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
$saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean>;
$saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean>;
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
$onDidReceiveMessage(uri: UriComponents, message: any): void;
$renderOutputs(uriComponents: UriComponents, id: string, request: IOutputRenderRequest<UriComponents>): Promise<IOutputRenderResponse<UriComponents> | undefined>;
$renderOutputs2<T>(uriComponents: UriComponents, id: string, request: IOutputRenderRequest<T>): Promise<IOutputRenderResponse<T> | undefined>;
$onDidReceiveMessage(editorId: string, message: any): void;
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void;
$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void;
$acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): Promise<void>;

View File

@@ -24,6 +24,10 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
this._proxy = mainContext.getProxy(MainContext.MainThreadAuthentication);
}
getProviderIds(): Promise<ReadonlyArray<string>> {
return this._proxy.$getProviderIds();
}
get providerIds(): string[] {
const ids: string[] = [];
this._authenticationProviders.forEach(provider => {
@@ -33,16 +37,74 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
return ids;
}
async getSessions(requestingExtension: IExtensionDescription, providerId: string, scopes: string[]): Promise<readonly vscode.AuthenticationSession[]> {
private async resolveSessions(providerId: string): Promise<ReadonlyArray<modes.AuthenticationSession>> {
const provider = this._authenticationProviders.get(providerId);
let sessions;
if (!provider) {
throw new Error(`No authentication provider with id '${providerId}' is currently registered.`);
sessions = await this._proxy.$getSessions(providerId);
} else {
sessions = await provider.getSessions();
}
return sessions;
}
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);
}
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise<vscode.AuthenticationSession2>;
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions): Promise<vscode.AuthenticationSession2 | undefined> {
const provider = this._authenticationProviders.get(providerId);
const extensionName = requestingExtension.displayName || requestingExtension.name;
const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier);
if (!provider) {
return this._proxy.$getSession(providerId, scopes, extensionId, extensionName, options);
}
const orderedScopes = scopes.sort().join(' ');
const sessions = (await provider.getSessions()).filter(session => session.scopes.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);
if (allowed) {
return session;
} else {
throw new Error('User did not consent to login.');
}
}
// 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);
return sessions.find(session => session.id === selected.id);
} else {
if (options.createIfNone) {
const isAllowed = await this._proxy.$loginPrompt(provider.displayName, 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);
return session;
} else {
await this._proxy.$requestNewSession(providerId, scopes, extensionId, extensionName);
return undefined;
}
}
}
async getSessions(requestingExtension: IExtensionDescription, providerId: string, scopes: string[]): Promise<readonly vscode.AuthenticationSession[]> {
const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier);
const orderedScopes = scopes.sort().join(' ');
return (await provider.getSessions())
const sessions = await this.resolveSessions(providerId);
return sessions
.filter(session => session.scopes.sort().join(' ') === orderedScopes)
.map(session => {
return {
@@ -51,9 +113,10 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
scopes: session.scopes,
getAccessToken: async () => {
const isAllowed = await this._proxy.$getSessionsPrompt(
provider.id,
providerId,
session.account.displayName,
provider.displayName,
'', // TODO
// provider.displayName,
extensionId,
requestingExtension.displayName || requestingExtension.name);
@@ -61,7 +124,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
throw new Error('User did not consent to token access.');
}
return session.getAccessToken();
return session.accessToken;
}
};
});
@@ -97,7 +160,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
throw new Error('User did not consent to token access.');
}
return session.getAccessToken();
return session.accessToken;
}
};
}
@@ -105,7 +168,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
async logout(providerId: string, sessionId: string): Promise<void> {
const provider = this._authenticationProviders.get(providerId);
if (!provider) {
throw new Error(`No authentication provider with id '${providerId}' is currently registered.`);
return this._proxy.$logout(providerId, sessionId);
}
return provider.logout(sessionId);
@@ -119,18 +182,15 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
this._authenticationProviders.set(provider.id, provider);
const listener = provider.onDidChangeSessions(e => {
this._proxy.$onDidChangeSessions(provider.id, e);
this._onDidChangeSessions.fire({ [provider.id]: e });
this._proxy.$sendDidChangeSessions(provider.id, e);
});
this._proxy.$registerAuthenticationProvider(provider.id, provider.displayName);
this._onDidChangeAuthenticationProviders.fire({ added: [provider.id], removed: [] });
this._proxy.$registerAuthenticationProvider(provider.id, provider.displayName, provider.supportsMultipleAccounts);
return new Disposable(() => {
listener.dispose();
this._authenticationProviders.delete(provider.id);
this._proxy.$unregisterAuthenticationProvider(provider.id);
this._onDidChangeAuthenticationProviders.fire({ added: [], removed: [provider.id] });
});
}
@@ -167,7 +227,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
const sessions = await authProvider.getSessions();
const session = sessions.find(session => session.id === sessionId);
if (session) {
return session.getAccessToken();
return session.accessToken;
}
throw new Error(`Unable to find session with id: ${sessionId}`);
@@ -175,4 +235,14 @@ 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 });
return Promise.resolve();
}
$onDidChangeAuthenticationProviders(added: string[], removed: string[]) {
this._onDidChangeAuthenticationProviders.fire({ added, removed });
return Promise.resolve();
}
}

View File

@@ -9,10 +9,10 @@ import { MainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, Decor
import { Disposable, Decoration } from 'vs/workbench/api/common/extHostTypes';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { asArray } from 'vs/base/common/arrays';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { ILogService } from 'vs/platform/log/common/log';
import { asArray } from 'vs/base/common/arrays';
interface ProviderData {
provider: vscode.DecorationProvider;
@@ -40,7 +40,9 @@ export class ExtHostDecorations implements IExtHostDecorations {
this._proxy.$registerDecorationProvider(handle, extensionId.value);
const listener = provider.onDidChangeDecorations(e => {
this._proxy.$onDidChange(handle, !e ? null : asArray(e));
this._proxy.$onDidChange(handle, !e || (Array.isArray(e) && e.length > 250)
? null
: asArray(e));
});
return new Disposable(() => {

View File

@@ -84,9 +84,10 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
let promise = this._documentLoader.get(uri.toString());
if (!promise) {
promise = this._proxy.$tryOpenDocument(uri).then(() => {
promise = this._proxy.$tryOpenDocument(uri).then(uriData => {
this._documentLoader.delete(uri.toString());
return assertIsDefined(this._documentsAndEditors.getDocument(uri));
const canonicalUri = URI.revive(uriData);
return assertIsDefined(this._documentsAndEditors.getDocument(canonicalUri));
}, err => {
this._documentLoader.delete(uri.toString());
return Promise.reject(err);

View File

@@ -857,16 +857,11 @@ class SuggestAdapter {
private _cache = new Cache<vscode.CompletionItem>('CompletionItem');
private _disposables = new Map<number, DisposableStore>();
private _didWarnMust: boolean = false;
private _didWarnShould: boolean = false;
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _commands: CommandsConverter,
private readonly _provider: vscode.CompletionItemProvider,
private readonly _logService: ILogService,
private readonly _apiDeprecation: IExtHostApiDeprecationService,
private readonly _telemetry: extHostProtocol.MainThreadTelemetryShape,
private readonly _extension: IExtensionDescription,
) { }
@@ -930,41 +925,12 @@ class SuggestAdapter {
return undefined;
}
const _mustNotChange = SuggestAdapter._mustNotChangeHash(item);
const _mayNotChange = SuggestAdapter._mayNotChangeHash(item);
const resolvedItem = await asPromise(() => this._provider.resolveCompletionItem!(item, token));
if (!resolvedItem) {
return undefined;
}
type BlameExtension = {
extensionId: string;
kind: string;
index: string;
};
type BlameExtensionMeta = {
extensionId: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' };
kind: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' };
index: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' };
};
let _mustNotChangeIndex = !this._didWarnMust && SuggestAdapter._mustNotChangeDiff(_mustNotChange, resolvedItem);
if (typeof _mustNotChangeIndex === 'string') {
this._logService.warn(`[${this._extension.identifier.value}] INVALID result from 'resolveCompletionItem', extension MUST NOT change any of: label, sortText, filterText, insertText, or textEdit`);
this._telemetry.$publicLog2<BlameExtension, BlameExtensionMeta>('badresolvecompletion', { extensionId: this._extension.identifier.value, kind: 'must', index: _mustNotChangeIndex });
this._didWarnMust = true;
}
let _mayNotChangeIndex = !this._didWarnShould && SuggestAdapter._mayNotChangeDiff(_mayNotChange, resolvedItem);
if (typeof _mayNotChangeIndex === 'string') {
this._logService.info(`[${this._extension.identifier.value}] UNSAVE result from 'resolveCompletionItem', extension SHOULD NOT change any of: additionalTextEdits, or command`);
this._telemetry.$publicLog2<BlameExtension, BlameExtensionMeta>('badresolvecompletion', { extensionId: this._extension.identifier.value, kind: 'should', index: _mayNotChangeIndex });
this._didWarnShould = true;
}
return this._convertCompletionItem(resolvedItem, id);
}
@@ -1035,45 +1001,6 @@ class SuggestAdapter {
return result;
}
private static _mustNotChangeHash(item: vscode.CompletionItem) {
const res = JSON.stringify([item.label, item.sortText, item.filterText, item.insertText, item.range]);
return res;
}
private static _mustNotChangeDiff(hash: string, item: vscode.CompletionItem): string | void {
const thisArr = [item.label, item.sortText, item.filterText, item.insertText, item.range];
const thisHash = JSON.stringify(thisArr);
if (hash === thisHash) {
return;
}
const arr = JSON.parse(hash);
for (let i = 0; i < 6; i++) {
if (JSON.stringify(arr[i] !== JSON.stringify(thisArr[i]))) {
return i.toString();
}
}
return 'unknown';
}
private static _mayNotChangeHash(item: vscode.CompletionItem) {
return JSON.stringify([item.additionalTextEdits, item.command]);
}
private static _mayNotChangeDiff(hash: string, item: vscode.CompletionItem): string | void {
const thisArr = [item.additionalTextEdits, item.command];
const thisHash = JSON.stringify(thisArr);
if (hash === thisHash) {
return;
}
const arr = JSON.parse(hash);
for (let i = 0; i < 6; i++) {
if (JSON.stringify(arr[i] !== JSON.stringify(thisArr[i]))) {
return i.toString();
}
}
return 'unknown';
}
}
class SignatureHelpAdapter {
@@ -1392,7 +1319,6 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
private readonly _uriTransformer: IURITransformer | null;
private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape;
private readonly _telemetryShape: extHostProtocol.MainThreadTelemetryShape;
private _documents: ExtHostDocuments;
private _commands: ExtHostCommands;
private _diagnostics: ExtHostDiagnostics;
@@ -1411,7 +1337,6 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
) {
this._uriTransformer = uriTransformer;
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadLanguageFeatures);
this._telemetryShape = mainContext.getProxy(extHostProtocol.MainContext.MainThreadTelemetry);
this._documents = documents;
this._commands = commands;
this._diagnostics = diagnostics;
@@ -1780,7 +1705,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
// --- suggestion
registerCompletionItemProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider, this._logService, this._apiDeprecation, this._telemetryShape, extension), extension);
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider, this._apiDeprecation, extension), extension);
this._proxy.$registerSuggestSupport(handle, this._transformDocumentSelector(selector), triggerCharacters, SuggestAdapter.supportsResolving(provider), extension.identifier);
return this._createDisposable(handle);
}

View File

@@ -6,6 +6,8 @@
import { MainContext, MainThreadLanguagesShape, IMainContext } from './extHost.protocol';
import type * as vscode from 'vscode';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
import { StandardTokenType, Range, Position } from 'vs/workbench/api/common/extHostTypes';
export class ExtHostLanguages {
@@ -32,4 +34,31 @@ export class ExtHostLanguages {
}
return data.document;
}
async tokenAtPosition(document: vscode.TextDocument, position: vscode.Position): Promise<vscode.TokenInformation> {
const versionNow = document.version;
const pos = typeConvert.Position.from(position);
const info = await this._proxy.$tokensAtPosition(document.uri, pos);
const defaultRange = {
type: StandardTokenType.Other,
range: document.getWordRangeAtPosition(position) ?? new Range(position.line, position.character, position.line, position.character)
};
if (!info) {
// no result
return defaultRange;
}
const result = {
range: typeConvert.Range.to(info.range),
type: typeConvert.TokenType.to(info.type)
};
if (!result.range.contains(<Position>position)) {
// bogous result
return defaultRange;
}
if (versionNow !== document.version) {
// concurrent change
return defaultRange;
}
return result;
}
}

View File

@@ -10,14 +10,16 @@ import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecyc
import { ISplice } from 'vs/base/common/sequence';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { CellKind, CellOutputKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData, INotebookDocumentsAndEditorsDelta } from 'vs/workbench/api/common/extHost.protocol';
import { CellKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData, INotebookDocumentsAndEditorsDelta } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { CellEditType, CellUri, diff, ICellEditOperation, ICellInsertEdit, IErrorOutput, INotebookDisplayOrder, INotebookEditData, IOrderedMimeType, IStreamOutput, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, NotebookCellsChangedEvent, NotebookCellsSplice2, sortMimeTypes, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { Disposable as VSCodeDisposable } from './extHostTypes';
import { CellEditType, CellUri, diff, ICellEditOperation, ICellInsertEdit, INotebookDisplayOrder, INotebookEditData, NotebookCellsChangedEvent, NotebookCellsSplice2, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto, IOutputRenderRequest, IOutputRenderResponse, IOutputRenderResponseOutputInfo, IOutputRenderResponseCellInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
import { NotImplementedProxy } from 'vs/base/common/types';
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
interface IObservable<T> {
proxy: T;
@@ -40,6 +42,12 @@ function getObservable<T extends Object>(obj: T): IObservable<T> {
};
}
interface INotebookEventEmitter {
emitModelChange(events: vscode.NotebookCellsChangeEvent): void;
emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void;
emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void;
}
export class ExtHostCell extends Disposable implements vscode.NotebookCell {
// private originalSource: string[];
@@ -59,14 +67,17 @@ export class ExtHostCell extends Disposable implements vscode.NotebookCell {
return this._documentData.document;
}
get notebook(): vscode.NotebookDocument {
return this._notebook;
}
get source() {
// todo@jrieken remove this
return this._documentData.getText();
}
constructor(
private readonly viewType: string,
private readonly documentUri: URI,
private readonly _notebook: ExtHostNotebookDocument,
readonly handle: number,
readonly uri: URI,
content: string,
@@ -133,7 +144,7 @@ export class ExtHostCell extends Disposable implements vscode.NotebookCell {
}
private updateMetadata(): Promise<void> {
return this._proxy.$updateNotebookCellMetadata(this.viewType, this.documentUri, this.handle, this._metadata);
return this._proxy.$updateNotebookCellMetadata(this._notebook.viewType, this._notebook.uri, this.handle, this._metadata);
}
attachTextDocument(document: ExtHostDocumentData) {
@@ -217,9 +228,12 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
return this._versionId;
}
private _disposed = false;
constructor(
private readonly _proxy: MainThreadNotebookShape,
private _documentsAndEditors: ExtHostDocumentsAndEditors,
private _emitter: INotebookEventEmitter,
public viewType: string,
public uri: URI,
public renderingHandler: ExtHostNotebookOutputRenderingHandler
@@ -238,6 +252,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
}
dispose() {
this._disposed = true;
super.dispose();
this._cellDisposableMapping.forEach(cell => cell.dispose());
}
@@ -246,7 +261,8 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
get isDirty() { return false; }
accpetModelChanged(event: NotebookCellsChangedEvent) {
accpetModelChanged(event: NotebookCellsChangedEvent): void {
this._versionId = event.versionId;
if (event.kind === NotebookCellsChangeType.ModelChange) {
this.$spliceNotebookCells(event.changes);
} else if (event.kind === NotebookCellsChangeType.Move) {
@@ -258,19 +274,19 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
} else if (event.kind === NotebookCellsChangeType.ChangeLanguage) {
this.$changeCellLanguage(event.index, event.language);
}
this._versionId = event.versionId;
}
private $spliceNotebookCells(splices: NotebookCellsSplice2[]): void {
if (!splices.length) {
if (this._disposed) {
return;
}
let contentChangeEvents: vscode.NotebookCellsChangeData[] = [];
splices.reverse().forEach(splice => {
let cellDtos = splice[2];
let newCells = cellDtos.map(cell => {
const extCell = new ExtHostCell(this.viewType, this.uri, cell.handle, URI.revive(cell.uri), cell.source.join('\n'), cell.cellKind, cell.language, cell.outputs, cell.metadata, this._proxy);
const extCell = new ExtHostCell(this, cell.handle, URI.revive(cell.uri), cell.source.join('\n'), cell.cellKind, cell.language, cell.outputs, cell.metadata, this._proxy);
const documentData = this._documentsAndEditors.getDocument(URI.revive(cell.uri));
if (documentData) {
@@ -297,107 +313,88 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
}
this.cells.splice(splice[0], splice[1], ...newCells);
const event: vscode.NotebookCellsChangeData = {
start: splice[0],
deletedCount: splice[1],
items: newCells
};
contentChangeEvents.push(event);
});
this._emitter.emitModelChange({
document: this,
changes: contentChangeEvents
});
}
private $moveCell(index: number, newIdx: number) {
private $moveCell(index: number, newIdx: number): void {
const cells = this.cells.splice(index, 1);
this.cells.splice(newIdx, 0, ...cells);
const changes: vscode.NotebookCellsChangeData[] = [{
start: index,
deletedCount: 1,
items: []
}, {
start: newIdx,
deletedCount: 0,
items: cells
}];
this._emitter.emitModelChange({
document: this,
changes
});
}
private $clearCellOutputs(index: number) {
private $clearCellOutputs(index: number): void {
const cell = this.cells[index];
cell.outputs = [];
const event: vscode.NotebookCellOutputsChangeEvent = { document: this, cells: [cell] };
this._emitter.emitCellOutputsChange(event);
}
private $clearAllCellOutputs() {
this.cells.forEach(cell => cell.outputs = []);
private $clearAllCellOutputs(): void {
const modifedCells: vscode.NotebookCell[] = [];
this.cells.forEach(cell => {
if (cell.outputs.length !== 0) {
cell.outputs = [];
modifedCells.push(cell);
}
});
const event: vscode.NotebookCellOutputsChangeEvent = { document: this, cells: modifedCells };
this._emitter.emitCellOutputsChange(event);
}
private $changeCellLanguage(index: number, language: string) {
private $changeCellLanguage(index: number, language: string): void {
const cell = this.cells[index];
cell.language = language;
const event: vscode.NotebookCellLanguageChangeEvent = { document: this, cell, language };
this._emitter.emitCellLanguageChange(event);
}
eventuallyUpdateCellOutputs(cell: ExtHostCell, diffs: ISplice<vscode.CellOutput>[]) {
async eventuallyUpdateCellOutputs(cell: ExtHostCell, diffs: ISplice<vscode.CellOutput>[]) {
let renderers = new Set<number>();
let outputDtos: NotebookCellOutputsSplice[] = diffs.map(diff => {
let outputs = diff.toInsert;
let transformedOutputs = outputs.map(output => {
if (output.outputKind === CellOutputKind.Rich) {
const ret = this.transformMimeTypes(output);
if (ret.orderedMimeTypes[ret.pickedMimeTypeIndex].isResolved) {
renderers.add(ret.orderedMimeTypes[ret.pickedMimeTypeIndex].rendererId!);
}
return ret;
} else {
return output as IStreamOutput | IErrorOutput;
}
});
return [diff.start, diff.deleteCount, transformedOutputs];
return [diff.start, diff.deleteCount, outputs];
});
this._proxy.$spliceNotebookCellOutputs(this.viewType, this.uri, cell.handle, outputDtos, Array.from(renderers));
}
transformMimeTypes(output: vscode.CellDisplayOutput): ITransformedDisplayOutputDto {
let mimeTypes = Object.keys(output.data);
let coreDisplayOrder = this.renderingHandler.outputDisplayOrder;
const sorted = sortMimeTypes(mimeTypes, coreDisplayOrder?.userOrder || [], this._displayOrder, coreDisplayOrder?.defaultOrder || []);
let orderMimeTypes: IOrderedMimeType[] = [];
sorted.forEach(mimeType => {
let handlers = this.renderingHandler.findBestMatchedRenderer(mimeType);
if (handlers.length) {
let renderedOutput = handlers[0].render(this, output, mimeType);
orderMimeTypes.push({
mimeType: mimeType,
isResolved: true,
rendererId: handlers[0].handle,
output: renderedOutput
});
for (let i = 1; i < handlers.length; i++) {
orderMimeTypes.push({
mimeType: mimeType,
isResolved: false,
rendererId: handlers[i].handle
});
}
if (mimeTypeSupportedByCore(mimeType)) {
orderMimeTypes.push({
mimeType: mimeType,
isResolved: false,
rendererId: -1
});
}
} else {
orderMimeTypes.push({
mimeType: mimeType,
isResolved: false
});
}
await this._proxy.$spliceNotebookCellOutputs(this.viewType, this.uri, cell.handle, outputDtos, Array.from(renderers));
this._emitter.emitCellOutputsChange({
document: this,
cells: [cell]
});
return {
outputKind: output.outputKind,
data: output.data,
orderedMimeTypes: orderMimeTypes,
pickedMimeTypeIndex: 0
};
}
getCell(cellHandle: number) {
return this.cells.find(cell => cell.handle === cellHandle);
}
getCell2(cellUri: UriComponents) {
return this.cells.find(cell => cell.uri.fragment === cellUri.fragment);
}
attachCellTextDocument(textDocument: ExtHostDocumentData) {
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.document.uri.toString());
if (cell) {
@@ -448,25 +445,10 @@ export class NotebookEditorCellEditBuilder implements vscode.NotebookEditorCellE
source: sourceArr,
language,
cellKind: type,
outputs: (outputs as any[]), // TODO@rebornix
outputs: outputs,
metadata
};
const transformedOutputs = outputs.map(output => {
if (output.outputKind === CellOutputKind.Rich) {
const ret = this.editor.document.transformMimeTypes(output);
if (ret.orderedMimeTypes[ret.pickedMimeTypeIndex].isResolved) {
this._renderers.add(ret.orderedMimeTypes[ret.pickedMimeTypeIndex].rendererId!);
}
return ret;
} else {
return output as IStreamOutput | IErrorOutput;
}
});
cell.outputs = transformedOutputs;
this._collectedEdits.push({
editType: CellEditType.Insert,
index,
@@ -489,6 +471,35 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
private _viewColumn: vscode.ViewColumn | undefined;
selection?: ExtHostCell = undefined;
private _active: boolean = false;
get active(): boolean {
return this._active;
}
set active(_state: boolean) {
throw readonly('active');
}
private _visible: boolean = false;
get visible(): boolean {
return this._visible;
}
set visible(_state: boolean) {
throw readonly('visible');
}
_acceptVisibility(value: boolean) {
this._visible = value;
}
_acceptActive(value: boolean) {
this._active = value;
}
private _onDidDispose = new Emitter<void>();
readonly onDidDispose: Event<void> = this._onDidDispose.event;
onDidReceiveMessage: vscode.Event<any> = this._onDidReceiveMessage.event;
constructor(
@@ -497,6 +508,7 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
public uri: URI,
private _proxy: MainThreadNotebookShape,
private _onDidReceiveMessage: Emitter<any>,
private _webviewInitData: WebviewInitData,
public document: ExtHostNotebookDocument,
private _documentsAndEditors: ExtHostDocumentsAndEditors
) {
@@ -584,6 +596,13 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
return this._proxy.$postMessage(this.document.handle, message);
}
asWebviewUri(localResource: vscode.Uri): vscode.Uri {
return asWebviewUri(this._webviewInitData, this.id, localResource);
}
dispose() {
this._onDidDispose.fire();
super.dispose();
}
}
export class ExtHostNotebookOutputRenderer {
@@ -620,16 +639,21 @@ export interface ExtHostNotebookOutputRenderingHandler {
}
export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostNotebookOutputRenderingHandler {
private static _handlePool: number = 0;
private readonly _proxy: MainThreadNotebookShape;
private readonly _notebookContentProviders = new Map<string, { readonly provider: vscode.NotebookContentProvider, readonly extension: IExtensionDescription; }>();
private readonly _notebookKernels = new Map<string, { readonly kernel: vscode.NotebookKernel, readonly extension: IExtensionDescription; }>();
private readonly _documents = new Map<string, ExtHostNotebookDocument>();
private readonly _unInitializedDocuments = new Map<string, ExtHostNotebookDocument>();
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; }>();
private readonly _notebookOutputRenderers = new Map<number, ExtHostNotebookOutputRenderer>();
private readonly _onDidChangeNotebookDocument = new Emitter<{ document: ExtHostNotebookDocument, changes: NotebookCellsChangedEvent[]; }>();
readonly onDidChangeNotebookDocument: Event<{ document: ExtHostNotebookDocument, changes: NotebookCellsChangedEvent[]; }> = this._onDidChangeNotebookDocument.event;
private readonly _notebookOutputRenderers = new Map<string, ExtHostNotebookOutputRenderer>();
private readonly _onDidChangeNotebookCells = new Emitter<vscode.NotebookCellsChangeEvent>();
readonly onDidChangeNotebookCells = this._onDidChangeNotebookCells.event;
private readonly _onDidChangeCellOutputs = new Emitter<vscode.NotebookCellOutputsChangeEvent>();
readonly onDidChangeCellOutputs = this._onDidChangeCellOutputs.event;
private readonly _onDidChangeCellLanguage = new Emitter<vscode.NotebookCellLanguageChangeEvent>();
readonly onDidChangeCellLanguage = this._onDidChangeCellLanguage.event;
private readonly _onDidChangeActiveNotebookEditor = new Emitter<vscode.NotebookEditor | undefined>();
readonly onDidChangeActiveNotebookEditor = this._onDidChangeActiveNotebookEditor.event;
private _outputDisplayOrder: INotebookDisplayOrder | undefined;
@@ -653,8 +677,11 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
onDidOpenNotebookDocument: Event<vscode.NotebookDocument> = this._onDidOpenNotebookDocument.event;
private _onDidCloseNotebookDocument = new Emitter<vscode.NotebookDocument>();
onDidCloseNotebookDocument: Event<vscode.NotebookDocument> = this._onDidCloseNotebookDocument.event;
visibleNotebookEditors: ExtHostNotebookEditor[] = [];
private _onDidChangeVisibleNotebookEditors = new Emitter<vscode.NotebookEditor[]>();
onDidChangeVisibleNotebookEditors = this._onDidChangeVisibleNotebookEditors.event;
constructor(mainContext: IMainContext, commands: ExtHostCommands, private _documentsAndEditors: ExtHostDocumentsAndEditors) {
constructor(mainContext: IMainContext, commands: ExtHostCommands, private _documentsAndEditors: ExtHostDocumentsAndEditors, private readonly _webviewInitData: WebviewInitData) {
this._proxy = mainContext.getProxy(MainContext.MainThreadNotebook);
commands.registerArgumentProcessor({
@@ -683,15 +710,85 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
filter: vscode.NotebookOutputSelector,
renderer: vscode.NotebookOutputRenderer
): vscode.Disposable {
if (this._notebookKernels.has(type)) {
throw new Error(`Notebook renderer for '${type}' already registered`);
}
let extHostRenderer = new ExtHostNotebookOutputRenderer(type, filter, renderer);
this._notebookOutputRenderers.set(extHostRenderer.handle, extHostRenderer);
this._proxy.$registerNotebookRenderer({ id: extension.identifier, location: extension.extensionLocation }, type, filter, extHostRenderer.handle, renderer.preloads || []);
return new VSCodeDisposable(() => {
this._notebookOutputRenderers.delete(extHostRenderer.handle);
this._proxy.$unregisterNotebookRenderer(extHostRenderer.handle);
this._notebookOutputRenderers.set(extHostRenderer.type, extHostRenderer);
this._proxy.$registerNotebookRenderer({ id: extension.identifier, location: extension.extensionLocation }, type, filter, renderer.preloads || []);
return new extHostTypes.Disposable(() => {
this._notebookOutputRenderers.delete(extHostRenderer.type);
this._proxy.$unregisterNotebookRenderer(extHostRenderer.type);
});
}
async $renderOutputs(uriComponents: UriComponents, id: string, request: IOutputRenderRequest<UriComponents>): Promise<IOutputRenderResponse<UriComponents> | undefined> {
if (!this._notebookOutputRenderers.has(id)) {
throw new Error(`Notebook renderer for '${id}' is not registered`);
}
const document = this._documents.get(URI.revive(uriComponents).toString());
if (!document) {
return undefined; // {{SQL CARBON EDIT}} strict-null-checks
}
const renderer = this._notebookOutputRenderers.get(id)!;
const cellsResponse: IOutputRenderResponseCellInfo<UriComponents>[] = request.items.map(cellInfo => {
const cell = document.getCell2(cellInfo.key);
const outputResponse: IOutputRenderResponseOutputInfo[] = cellInfo.outputs.map(output => {
return {
index: output.index,
mimeType: output.mimeType,
handlerId: id,
transformedOutput: renderer.render(document, cell!.outputs[output.index] as vscode.CellDisplayOutput, output.mimeType)
};
});
return {
key: cellInfo.key,
outputs: outputResponse
};
});
return { items: cellsResponse };
}
/**
* The request carry the raw data for outputs so we don't look up in the existing document
*/
async $renderOutputs2<T>(uriComponents: UriComponents, id: string, request: IOutputRenderRequest<T>): Promise<IOutputRenderResponse<T> | undefined> {
if (!this._notebookOutputRenderers.has(id)) {
throw new Error(`Notebook renderer for '${id}' is not registered`);
}
const document = this._documents.get(URI.revive(uriComponents).toString());
if (!document) {
return undefined; // {{SQL CARBON EDIT}} strict-null-checks
}
const renderer = this._notebookOutputRenderers.get(id)!;
const cellsResponse: IOutputRenderResponseCellInfo<T>[] = request.items.map(cellInfo => {
const outputResponse: IOutputRenderResponseOutputInfo[] = cellInfo.outputs.map(output => {
return {
index: output.index,
mimeType: output.mimeType,
handlerId: id,
transformedOutput: renderer.render(document, output.output! as vscode.CellDisplayOutput, output.mimeType)
};
});
return {
key: cellInfo.key,
outputs: outputResponse
};
});
return { items: cellsResponse };
}
findBestMatchedRenderer(mimeType: string): ExtHostNotebookOutputRenderer[] {
let matches: ExtHostNotebookOutputRenderer[] = [];
for (let renderer of this._notebookOutputRenderers) {
@@ -713,50 +810,70 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
throw new Error(`Notebook provider for '${viewType}' already registered`);
}
// if ((<any>provider).executeCell) {
// throw new Error('NotebookContentKernel.executeCell is removed, please use vscode.notebook.registerNotebookKernel instead.');
// }
this._notebookContentProviders.set(viewType, { extension, provider });
this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType);
return new VSCodeDisposable(() => {
const listener = provider.onDidChangeNotebook
? provider.onDidChangeNotebook(e => this._proxy.$onNotebookChange(viewType, e.document.uri))
: Disposable.None;
this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType, provider.kernel ? { id: viewType, label: provider.kernel.label, extensionLocation: extension.extensionLocation, preloads: provider.kernel.preloads } : undefined);
return new extHostTypes.Disposable(() => {
listener.dispose();
this._notebookContentProviders.delete(viewType);
this._proxy.$unregisterNotebookProvider(viewType);
});
}
async $resolveNotebookData(viewType: string, uri: UriComponents): Promise<NotebookDataDto | undefined> {
let provider = this._notebookContentProviders.get(viewType);
let document = this._documents.get(URI.revive(uri).toString());
registerNotebookKernel(extension: IExtensionDescription, id: string, selectors: vscode.GlobPattern[], kernel: vscode.NotebookKernel): vscode.Disposable {
if (this._notebookKernels.has(id)) {
throw new Error(`Notebook kernel for '${id}' already registered`);
}
this._notebookKernels.set(id, { kernel, extension });
const transformedSelectors = selectors.map(selector => typeConverters.GlobPattern.from(selector));
this._proxy.$registerNotebookKernel({ id: extension.identifier, location: extension.extensionLocation }, id, kernel.label, transformedSelectors, kernel.preloads || []);
return new extHostTypes.Disposable(() => {
this._notebookKernels.delete(id);
this._proxy.$unregisterNotebookKernel(id);
});
}
async $resolveNotebookData(viewType: string, uri: UriComponents): Promise<NotebookDataDto | undefined> {
const provider = this._notebookContentProviders.get(viewType);
const revivedUri = URI.revive(uri);
if (provider) {
let document = this._documents.get(URI.revive(uri).toString());
if (!document) {
const that = this;
document = this._unInitializedDocuments.get(revivedUri.toString()) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, {
emitModelChange(event: vscode.NotebookCellsChangeEvent): void {
that._onDidChangeNotebookCells.fire(event);
},
emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void {
that._onDidChangeCellOutputs.fire(event);
},
emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void {
that._onDidChangeCellLanguage.fire(event);
}
}, viewType, revivedUri, this);
this._unInitializedDocuments.set(revivedUri.toString(), document);
}
if (provider && document) {
const rawCells = await provider.provider.openNotebook(URI.revive(uri));
const renderers = new Set<number>();
const dto = {
metadata: {
...notebookDocumentMetadataDefaults,
...rawCells.metadata
},
languages: rawCells.languages,
cells: rawCells.cells.map(cell => {
let transformedOutputs = cell.outputs.map(output => {
if (output.outputKind === CellOutputKind.Rich) {
// TODO display string[]
const ret = this._transformMimeTypes(document!, (rawCells.metadata.displayOrder as string[]) || [], output);
if (ret.orderedMimeTypes[ret.pickedMimeTypeIndex].isResolved) {
renderers.add(ret.orderedMimeTypes[ret.pickedMimeTypeIndex].rendererId!);
}
return ret;
} else {
return output as IStreamOutput | IErrorOutput;
}
});
return {
language: cell.language,
cellKind: cell.cellKind,
metadata: cell.metadata,
source: cell.source,
outputs: transformedOutputs
};
})
cells: rawCells.cells,
};
return dto;
@@ -765,58 +882,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
return undefined; // {{SQL CARBON EDIT}}
}
private _transformMimeTypes(document: ExtHostNotebookDocument, displayOrder: string[], output: vscode.CellDisplayOutput): ITransformedDisplayOutputDto {
let mimeTypes = Object.keys(output.data);
let coreDisplayOrder = this.outputDisplayOrder;
const sorted = sortMimeTypes(mimeTypes, coreDisplayOrder?.userOrder || [], displayOrder, coreDisplayOrder?.defaultOrder || []);
let orderMimeTypes: IOrderedMimeType[] = [];
sorted.forEach(mimeType => {
let handlers = this.findBestMatchedRenderer(mimeType);
if (handlers.length) {
let renderedOutput = handlers[0].render(document, output, mimeType);
orderMimeTypes.push({
mimeType: mimeType,
isResolved: true,
rendererId: handlers[0].handle,
output: renderedOutput
});
for (let i = 1; i < handlers.length; i++) {
orderMimeTypes.push({
mimeType: mimeType,
isResolved: false,
rendererId: handlers[i].handle
});
}
if (mimeTypeSupportedByCore(mimeType)) {
orderMimeTypes.push({
mimeType: mimeType,
isResolved: false,
rendererId: -1
});
}
} else {
orderMimeTypes.push({
mimeType: mimeType,
isResolved: false
});
}
});
return {
outputKind: output.outputKind,
data: output.data,
orderedMimeTypes: orderMimeTypes,
pickedMimeTypeIndex: 0
};
}
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
let document = this._documents.get(URI.revive(uri).toString());
if (!document) {
@@ -824,9 +890,38 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
if (this._notebookContentProviders.has(viewType)) {
let cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
const cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
const provider = this._notebookContentProviders.get(viewType)!.provider;
return this._notebookContentProviders.get(viewType)!.provider.executeCell(document, cell, token);
if (provider.kernel && useAttachedKernel) {
if (cell) {
return provider.kernel.executeCell(document, cell, token);
} else {
return provider.kernel.executeAllCells(document, token);
}
}
}
}
async $executeNotebook2(kernelId: string, viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
let document = this._documents.get(URI.revive(uri).toString());
if (!document || document.viewType !== viewType) {
return;
}
let kernelInfo = this._notebookKernels.get(kernelId);
if (!kernelInfo) {
return;
}
let cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
if (cell) {
return kernelInfo.kernel.executeCell(document, cell, token);
} else {
return kernelInfo.kernel.executeAllCells(document, token);
}
}
@@ -872,8 +967,21 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
this._outputDisplayOrder = displayOrder;
}
$onDidReceiveMessage(uri: UriComponents, message: any): void {
let editor = this._editors.get(URI.revive(uri).toString());
// TODO: remove document - editor one on one mapping
private _getEditorFromURI(uriComponents: UriComponents) {
const uriStr = URI.revive(uriComponents).toString();
let editor: { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; } | undefined;
this._editors.forEach(e => {
if (e.editor.uri.toString() === uriStr) {
editor = e;
}
});
return editor;
}
$onDidReceiveMessage(editorId: string, message: any): void {
let editor = this._editors.get(editorId);
if (editor) {
editor.onDidReceiveMessage.fire(message);
@@ -881,20 +989,15 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void {
let editor = this._editors.get(URI.revive(uriComponents).toString());
const document = this._documents.get(URI.revive(uriComponents).toString());
if (editor) {
editor.editor.document.accpetModelChanged(event);
this._onDidChangeNotebookDocument.fire({
document: editor.editor.document,
changes: [event]
});
if (document) {
document.accpetModelChanged(event);
}
}
$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void {
let editor = this._editors.get(URI.revive(uriComponents).toString());
let editor = this._getEditorFromURI(uriComponents);
if (!editor) {
return;
@@ -910,61 +1013,196 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
editor.editor.selection = undefined;
}
}
if (data.metadata) {
editor.editor.document.metadata = {
...notebookDocumentMetadataDefaults,
...data.metadata
};
}
}
private _createExtHostEditor(document: ExtHostNotebookDocument, editorId: string, selections: number[]) {
const onDidReceiveMessage = new Emitter<any>();
const revivedUri = document.uri;
let editor = new ExtHostNotebookEditor(
document.viewType,
editorId,
revivedUri,
this._proxy,
onDidReceiveMessage,
this._webviewInitData,
document,
this._documentsAndEditors
);
const cells = editor.document.cells;
if (selections.length) {
const firstCell = selections[0];
editor.selection = cells.find(cell => cell.handle === firstCell);
} else {
editor.selection = undefined;
}
this._editors.get(editorId)?.editor.dispose();
this._editors.set(editorId, { editor, onDidReceiveMessage });
}
async $acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta) {
let editorChanged = false;
if (delta.removedDocuments) {
delta.removedDocuments.forEach((uri) => {
let document = this._documents.get(URI.revive(uri).toString());
const revivedUri = URI.revive(uri);
const revivedUriStr = revivedUri.toString();
let document = this._documents.get(revivedUriStr);
if (document) {
document.dispose();
this._documents.delete(URI.revive(uri).toString());
this._documents.delete(revivedUriStr);
this._onDidCloseNotebookDocument.fire(document);
}
let editor = this._editors.get(URI.revive(uri).toString());
if (editor) {
editor.editor.dispose();
editor.onDidReceiveMessage.dispose();
this._editors.delete(URI.revive(uri).toString());
}
[...this._editors.values()].forEach((e) => {
if (e.editor.uri.toString() === revivedUriStr) {
e.editor.dispose();
e.onDidReceiveMessage.dispose();
this._editors.delete(e.editor.id);
editorChanged = true;
}
});
});
}
if (delta.addedDocuments) {
delta.addedDocuments.forEach(modelData => {
const revivedUri = URI.revive(modelData.uri);
const revivedUriStr = revivedUri.toString();
const viewType = modelData.viewType;
if (!this._documents.has(revivedUri.toString())) {
let document = new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, viewType, revivedUri, this);
this._documents.set(revivedUri.toString(), document);
if (!this._documents.has(revivedUriStr)) {
const that = this;
let document = this._unInitializedDocuments.get(revivedUriStr) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, {
emitModelChange(event: vscode.NotebookCellsChangeEvent): void {
that._onDidChangeNotebookCells.fire(event);
},
emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void {
that._onDidChangeCellOutputs.fire(event);
},
emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void {
that._onDidChangeCellLanguage.fire(event);
}
}, viewType, revivedUri, this);
this._unInitializedDocuments.delete(revivedUriStr);
if (modelData.metadata) {
document.metadata = {
...notebookDocumentMetadataDefaults,
...modelData.metadata
};
}
document.accpetModelChanged({
kind: NotebookCellsChangeType.ModelChange,
versionId: modelData.versionId,
changes: [[
0,
0,
modelData.cells
]]
});
this._documents.get(revivedUriStr)?.dispose();
this._documents.set(revivedUriStr, document);
// create editor if populated
if (modelData.attachedEditor) {
this._createExtHostEditor(document, modelData.attachedEditor.id, modelData.attachedEditor.selections);
editorChanged = true;
}
}
const onDidReceiveMessage = new Emitter<any>();
const document = this._documents.get(revivedUri.toString())!;
let editor = new ExtHostNotebookEditor(
viewType,
`${ExtHostNotebookController._handlePool++}`,
revivedUri,
this._proxy,
onDidReceiveMessage,
document,
this._documentsAndEditors
);
const document = this._documents.get(revivedUriStr)!;
this._onDidOpenNotebookDocument.fire(document);
// TODO, does it already exist?
this._editors.set(revivedUri.toString(), { editor, onDidReceiveMessage });
});
}
if (delta.newActiveEditor) {
this._activeNotebookDocument = this._documents.get(URI.revive(delta.newActiveEditor).toString());
this._activeNotebookEditor = this._editors.get(URI.revive(delta.newActiveEditor).toString())?.editor;
if (delta.addedEditors) {
delta.addedEditors.forEach(editorModelData => {
if (this._editors.has(editorModelData.id)) {
return;
}
const revivedUri = URI.revive(editorModelData.documentUri);
const document = this._documents.get(revivedUri.toString());
if (document) {
this._createExtHostEditor(document, editorModelData.id, editorModelData.selections);
editorChanged = true;
}
});
}
const removedEditors: { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; }[] = [];
if (delta.removedEditors) {
delta.removedEditors.forEach(editorid => {
const editor = this._editors.get(editorid);
if (editor) {
editorChanged = true;
this._editors.delete(editorid);
if (this.activeNotebookEditor?.id === editor.editor.id) {
this._activeNotebookEditor = undefined;
this._activeNotebookDocument = undefined;
}
removedEditors.push(editor);
}
});
}
if (editorChanged) {
removedEditors.forEach(e => {
e.editor.dispose();
e.onDidReceiveMessage.dispose();
});
}
if (delta.visibleEditors) {
this.visibleNotebookEditors = delta.visibleEditors.map(id => this._editors.get(id)?.editor).filter(editor => !!editor) as ExtHostNotebookEditor[];
const visibleEditorsSet = new Set<string>();
this.visibleNotebookEditors.forEach(editor => visibleEditorsSet.add(editor.id));
[...this._editors.values()].forEach((e) => {
const newValue = visibleEditorsSet.has(e.editor.id);
e.editor._acceptVisibility(newValue);
});
this.visibleNotebookEditors = [...this._editors.values()].map(e => e.editor).filter(e => e.visible);
this._onDidChangeVisibleNotebookEditors.fire(this.visibleNotebookEditors);
}
if (delta.newActiveEditor !== undefined) {
if (delta.newActiveEditor) {
this._activeNotebookEditor = this._editors.get(delta.newActiveEditor)?.editor;
this._activeNotebookEditor?._acceptActive(true);
this._activeNotebookDocument = this._activeNotebookEditor ? this._documents.get(this._activeNotebookEditor!.uri.toString()) : undefined;
} else {
this._activeNotebookEditor = undefined;
this._activeNotebookDocument = undefined;
}
this._onDidChangeActiveNotebookEditor.fire(this._activeNotebookEditor);
}
[...this._editors.values()].forEach((e) => {
if (e.editor !== this.activeNotebookEditor) {
e.editor._acceptActive(false);
}
});
}
}

View File

@@ -44,13 +44,17 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
this._onDidChange.fire(undefined);
}
}));
this._disposables.add(extHostNotebooks.onDidChangeNotebookDocument(e => {
if (e.document === this._notebook) {
const documentChange = (document: vscode.NotebookDocument) => {
if (document === this._notebook) {
this._init();
this._versionId += 1;
this._onDidChange.fire(undefined);
}
}));
};
this._disposables.add(extHostNotebooks.onDidChangeCellLanguage(e => documentChange(e.document)));
this._disposables.add(extHostNotebooks.onDidChangeCellOutputs(e => documentChange(e.document)));
this._disposables.add(extHostNotebooks.onDidChangeNotebookCells(e => documentChange(e.document)));
}
dispose(): void {

View File

@@ -35,8 +35,9 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
private _timeoutHandle: any;
private _proxy: MainThreadStatusBarShape;
private _commands: CommandsConverter;
private _accessibilityInformation?: vscode.AccessibilityInformation;
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, id: string, name: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number) {
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, id: string, name: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation) {
this._id = ExtHostStatusBarEntry.ID_GEN++;
this._proxy = proxy;
this._commands = commands;
@@ -44,6 +45,7 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
this._statusName = name;
this._alignment = alignment;
this._priority = priority;
this._accessibilityInformation = accessibilityInformation;
}
public get id(): number {
@@ -74,6 +76,10 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
return this._command?.fromApi;
}
public get accessibilityInformation(): vscode.AccessibilityInformation | undefined {
return this._accessibilityInformation;
}
public set text(text: string) {
this._text = text;
this.update();
@@ -136,7 +142,7 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
// Set to status bar
this._proxy.$setEntry(this.id, this._statusId, this._statusName, this.text, this.tooltip, this._command?.internal, this.color,
this._alignment === ExtHostStatusBarAlignment.Left ? MainThreadStatusBarAlignment.LEFT : MainThreadStatusBarAlignment.RIGHT,
this._priority);
this._priority, this._accessibilityInformation);
}, 0);
}
@@ -196,8 +202,8 @@ export class ExtHostStatusBar {
this._statusMessage = new StatusBarMessage(this);
}
createStatusBarEntry(id: string, name: string, alignment?: ExtHostStatusBarAlignment, priority?: number): vscode.StatusBarItem {
return new ExtHostStatusBarEntry(this._proxy, this._commands, id, name, alignment, priority);
createStatusBarEntry(id: string, name: string, alignment?: ExtHostStatusBarAlignment, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation): vscode.StatusBarItem {
return new ExtHostStatusBarEntry(this._proxy, this._commands, id, name, alignment, priority, accessibilityInformation);
}
setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable<any>): Disposable {

View File

@@ -384,6 +384,7 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape {
protected _handleCounter: number;
protected _handlers: Map<number, HandlerData>;
protected _taskExecutions: Map<string, TaskExecutionImpl>;
protected _taskExecutionPromises: Map<string, Promise<TaskExecutionImpl>>;
protected _providedCustomExecutions2: Map<string, types.CustomExecution>;
private _notProvidedCustomExecutions: Set<string>; // Used for custom executions tasks that are created and run through executeTask.
protected _activeCustomExecutions2: Map<string, types.CustomExecution>;
@@ -412,6 +413,7 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape {
this._handleCounter = 0;
this._handlers = new Map<number, HandlerData>();
this._taskExecutions = new Map<string, TaskExecutionImpl>();
this._taskExecutionPromises = new Map<string, Promise<TaskExecutionImpl>>();
this._providedCustomExecutions2 = new Map<string, types.CustomExecution>();
this._notProvidedCustomExecutions = new Set<string>();
this._activeCustomExecutions2 = new Map<string, types.CustomExecution>();
@@ -496,6 +498,7 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape {
public async $OnDidEndTask(execution: tasks.TaskExecutionDTO): Promise<void> {
const _execution = await this.getTaskExecution(execution);
this._taskExecutionPromises.delete(execution.id);
this._taskExecutions.delete(execution.id);
this.customExecutionComplete(execution);
this._onDidTerminateTask.fire({
@@ -626,17 +629,24 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape {
return taskExecution;
}
let result: TaskExecutionImpl | undefined = this._taskExecutions.get(execution.id);
let result: Promise<TaskExecutionImpl> | undefined = this._taskExecutionPromises.get(execution.id);
if (result) {
return result;
}
const taskToCreate = task ? task : await TaskDTO.to(execution.task, this._workspaceProvider);
if (!taskToCreate) {
throw new Error('Unexpected: Task does not exist.');
}
const createdResult: TaskExecutionImpl = new TaskExecutionImpl(this, execution.id, taskToCreate);
this._taskExecutions.set(execution.id, createdResult);
return createdResult;
const createdResult: Promise<TaskExecutionImpl> = new Promise(async (resolve, reject) => {
const taskToCreate = task ? task : await TaskDTO.to(execution.task, this._workspaceProvider);
if (!taskToCreate) {
reject('Unexpected: Task does not exist.');
} else {
resolve(new TaskExecutionImpl(this, execution.id, taskToCreate));
}
});
this._taskExecutionPromises.set(execution.id, createdResult);
return createdResult.then(result => {
this._taskExecutions.set(execution.id, result);
return result;
});
}
protected checkDeprecation(task: vscode.Task, handler: HandlerData) {

View File

@@ -152,7 +152,8 @@ export class ExtHostTimeline implements IExtHostTimeline {
command: item.command ? commandConverter.toInternal(item.command, disposables) : undefined,
icon: icon,
iconDark: iconDark,
themeIcon: themeIcon
themeIcon: themeIcon,
accessibilityInformation: item.accessibilityInformation
};
};
};
@@ -188,4 +189,3 @@ export class ExtHostTimeline implements IExtHostTimeline {
function getUriKey(uri: URI | undefined): string | undefined {
return uri?.toString();
}

View File

@@ -498,7 +498,7 @@ export class ExtHostTreeView<T> extends Disposable {
return node;
}
protected createTreeNode(element: T, extensionTreeItem: azdata.TreeItem, parent: TreeNode | Root): TreeNode { // {{SQL CARBON EDIT}} change to protected, change to azdata.TreeItem
protected createTreeNode(element: T, extensionTreeItem: azdata.TreeItem2, parent: TreeNode | Root): TreeNode { // {{SQL CARBON EDIT}} change to protected, change to azdata.TreeItem
const disposable = new DisposableStore();
const handle = this.createHandle(element, extensionTreeItem, parent);
const icon = this.getLightIconPath(extensionTreeItem);
@@ -515,10 +515,10 @@ export class ExtHostTreeView<T> extends Disposable {
iconDark: this.getDarkIconPath(extensionTreeItem) || icon,
themeIcon: extensionTreeItem.iconPath instanceof ThemeIcon ? { id: extensionTreeItem.iconPath.id } : undefined,
collapsibleState: isUndefinedOrNull(extensionTreeItem.collapsibleState) ? TreeItemCollapsibleState.None : extensionTreeItem.collapsibleState,
// {{SQL CARBON EDIT}}
payload: extensionTreeItem.payload,
childProvider: extensionTreeItem.childProvider,
type: extensionTreeItem.type
accessibilityInformation: extensionTreeItem.accessibilityInformation,
payload: extensionTreeItem.payload, // {{SQL CARBON EDIT}}
childProvider: extensionTreeItem.childProvider, // {{SQL CARBON EDIT}}
type: extensionTreeItem.type // {{SQL CARBON EDIT}}
};
return {

View File

@@ -95,11 +95,22 @@ export namespace Range {
}
}
export namespace TokenType {
export function to(type: modes.StandardTokenType): types.StandardTokenType {
switch (type) {
case modes.StandardTokenType.Comment: return types.StandardTokenType.Comment;
case modes.StandardTokenType.Other: return types.StandardTokenType.Other;
case modes.StandardTokenType.RegEx: return types.StandardTokenType.RegEx;
case modes.StandardTokenType.String: return types.StandardTokenType.String;
}
}
}
export namespace Position {
export function to(position: IPosition): types.Position {
return new types.Position(position.lineNumber - 1, position.column - 1);
}
export function from(position: types.Position): IPosition {
export function from(position: types.Position | vscode.Position): IPosition {
return { lineNumber: position.line + 1, column: position.character + 1 };
}
}

View File

@@ -2766,3 +2766,17 @@ export enum ExtensionMode {
}
//#endregion ExtensionContext
//#region Authentication
export class AuthenticationSession implements vscode.AuthenticationSession2 {
constructor(public id: string, public accessToken: string, public account: { displayName: string, id: string }, public scopes: string[]) { }
}
//#endregion Authentication
export enum StandardTokenType {
Other = 0,
Comment = 1,
String = 2,
RegEx = 4
}

View File

@@ -573,7 +573,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
}
const { serializer, extension } = entry;
const webview = new ExtHostWebview(webviewHandle, this._proxy, options, this.initData, this.workspace, extension, this._deprecationService);
const webview = new ExtHostWebview(webviewHandle, this._proxy, reviveOptions(options), this.initData, this.workspace, extension, this._deprecationService);
const revivedPanel = new ExtHostWebviewEditor(webviewHandle, this._proxy, viewType, title, typeof position === 'number' && position >= 0 ? typeConverters.ViewColumn.to(position) : undefined, options, webview);
this._webviewPanels.set(webviewHandle, revivedPanel);
await serializer.deserializeWebviewPanel(revivedPanel, state);
@@ -628,7 +628,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
throw new Error(`No provider found for '${viewType}'`);
}
const webview = new ExtHostWebview(handle, this._proxy, options, this.initData, this.workspace, entry.extension, this._deprecationService);
const webview = new ExtHostWebview(handle, this._proxy, reviveOptions(options), this.initData, this.workspace, entry.extension, this._deprecationService);
const revivedPanel = new ExtHostWebviewEditor(handle, this._proxy, viewType, title, typeof position === 'number' && position >= 0 ? typeConverters.ViewColumn.to(position) : undefined, options, webview);
this._webviewPanels.set(handle, revivedPanel);
@@ -761,6 +761,15 @@ function convertWebviewOptions(
};
}
function reviveOptions(
options: modes.IWebviewOptions & modes.IWebviewPanelOptions
): vscode.WebviewOptions {
return {
...options,
localResourceRoots: options.localResourceRoots?.map(components => URI.from(components)),
};
}
function getDefaultLocalResourceRoots(
extension: IExtensionDescription,
workspace: IExtHostWorkspace | undefined,