mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-13 03:28:33 -05:00
Merge from vscode 2e5312cd61ff99c570299ecc122c52584265eda2
This commit is contained in:
committed by
Anthony Dresser
parent
3603f55d97
commit
7f1d8fc32f
@@ -53,7 +53,7 @@ import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyId
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { originalFSPath, joinPath } from 'vs/base/common/resources';
|
||||
import { originalFSPath } from 'vs/base/common/resources';
|
||||
import { values } from 'vs/base/common/collections';
|
||||
import { ExtHostEditorInsets } from 'vs/workbench/api/common/extHostCodeInsets';
|
||||
import { ExtHostLabelService } from 'vs/workbench/api/common/extHostLabelService';
|
||||
@@ -74,6 +74,7 @@ import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelServ
|
||||
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
||||
import { ExtHostAuthentication } from 'vs/workbench/api/common/extHostAuthentication';
|
||||
import { ExtHostTimeline } from 'vs/workbench/api/common/extHostTimeline';
|
||||
import { ExtHostNotebookConcatDocument } from 'vs/workbench/api/common/extHostNotebookConcatDocument';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
|
||||
@@ -585,12 +586,12 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
registerWebviewPanelSerializer: (viewType: string, serializer: vscode.WebviewPanelSerializer) => {
|
||||
return extHostWebviews.registerWebviewPanelSerializer(extension, viewType, serializer);
|
||||
},
|
||||
registerCustomEditorProvider: (viewType: string, provider: vscode.CustomTextEditorProvider, options?: { webviewOptions?: vscode.WebviewPanelOptions }) => {
|
||||
return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options?.webviewOptions);
|
||||
registerCustomEditorProvider: (viewType: string, provider: vscode.CustomTextEditorProvider, options: { webviewOptions?: vscode.WebviewPanelOptions } = {}) => {
|
||||
return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options);
|
||||
},
|
||||
registerCustomEditorProvider2: (viewType: string, provider: vscode.CustomEditorProvider, options?: { webviewOptions?: vscode.WebviewPanelOptions }) => {
|
||||
registerCustomEditorProvider2: (viewType: string, provider: vscode.CustomEditorProvider, options: { webviewOptions?: vscode.WebviewPanelOptions, supportsMultipleEditorsPerResource?: boolean } = {}) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options?.webviewOptions);
|
||||
return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options);
|
||||
},
|
||||
registerDecorationProvider(provider: vscode.DecorationProvider) {
|
||||
checkProposedApiEnabled(extension);
|
||||
@@ -606,11 +607,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostQuickOpen.createInputBox(extension.identifier);
|
||||
},
|
||||
get activeColorTheme(): vscode.ColorTheme {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTheming.activeColorTheme;
|
||||
},
|
||||
onDidChangeActiveColorTheme(listener, thisArg?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTheming.onDidChangeActiveColorTheme(listener, thisArg, disposables);
|
||||
}
|
||||
};
|
||||
@@ -856,7 +855,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
},
|
||||
registerDebugConfigurationProvider(debugType: string, provider: vscode.DebugConfigurationProvider) {
|
||||
registerDebugConfigurationProvider(debugType: string, provider: vscode.DebugConfigurationProvider, scope?: vscode.DebugConfigurationProviderScope) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
},
|
||||
@@ -924,13 +923,24 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
// namespace: notebook
|
||||
const notebook: typeof vscode.notebook = {
|
||||
registerNotebookProvider: (viewType: string, provider: vscode.NotebookProvider) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.registerNotebookProvider(extension, viewType, provider);
|
||||
},
|
||||
registerNotebookOutputRenderer: (type: string, outputFilter: vscode.NotebookOutputSelector, renderer: vscode.NotebookOutputRenderer) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.registerNotebookOutputRenderer(type, extension, outputFilter, renderer);
|
||||
},
|
||||
get activeNotebookDocument(): vscode.NotebookDocument | undefined {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.activeNotebookDocument;
|
||||
},
|
||||
get activeNotebookEditor(): vscode.NotebookEditor | undefined {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.activeNotebookEditor;
|
||||
},
|
||||
createConcatTextDocument(notebook, selector) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return new ExtHostNotebookConcatDocument(extHostNotebook, extHostDocuments, notebook, selector);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1055,13 +1065,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
CallHierarchyIncomingCall: extHostTypes.CallHierarchyIncomingCall,
|
||||
CallHierarchyItem: extHostTypes.CallHierarchyItem,
|
||||
DebugConsoleMode: extHostTypes.DebugConsoleMode,
|
||||
DebugConfigurationProviderScope: extHostTypes.DebugConfigurationProviderScope,
|
||||
Decoration: extHostTypes.Decoration,
|
||||
UIKind: UIKind,
|
||||
ColorThemeKind: extHostTypes.ColorThemeKind,
|
||||
TimelineItem: extHostTypes.TimelineItem,
|
||||
CellKind: extHostTypes.CellKind,
|
||||
CellOutputKind: extHostTypes.CellOutputKind,
|
||||
CustomDocument: extHostTypes.CustomDocument,
|
||||
NotebookCellRunState: extHostTypes.NotebookCellRunState
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1089,11 +1100,6 @@ class Extension<T> implements vscode.Extension<T> {
|
||||
this.extensionKind = kind;
|
||||
}
|
||||
|
||||
asExtensionUri(relativePath: string): URI {
|
||||
checkProposedApiEnabled(this.packageJSON);
|
||||
return joinPath(this.packageJSON.extensionLocation, relativePath);
|
||||
}
|
||||
|
||||
get isActive(): boolean {
|
||||
return this._extensionService.isActivated(this._identifier);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ import { INotebookMimeTypeSelector, IOutput, INotebookDisplayOrder, NotebookCell
|
||||
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 { DebugConfigurationProviderScope } from 'vs/workbench/api/common/extHostTypes';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { ITreeItem as sqlITreeItem } from 'sql/workbench/common/views';
|
||||
@@ -164,6 +165,7 @@ export interface MainThreadAuthenticationShape extends IDisposable {
|
||||
$onDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void;
|
||||
$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>;
|
||||
}
|
||||
|
||||
export interface MainThreadConfigurationShape extends IDisposable {
|
||||
@@ -538,7 +540,7 @@ export interface MainThreadQuickOpenShape extends IDisposable {
|
||||
$show(instance: number, options: quickInput.IPickOptions<TransferQuickPickItems>, token: CancellationToken): Promise<number | number[] | undefined>;
|
||||
$setItems(instance: number, items: TransferQuickPickItems[]): Promise<void>;
|
||||
$setError(instance: number, error: Error): Promise<void>;
|
||||
$input(options: IInputBoxOptions | undefined, validateInput: boolean, token: CancellationToken): Promise<string>;
|
||||
$input(options: IInputBoxOptions | undefined, validateInput: boolean, token: CancellationToken): Promise<string | undefined>;
|
||||
$createOrUpdate(params: TransferQuickInput): Promise<void>;
|
||||
$dispose(id: number): Promise<void>;
|
||||
}
|
||||
@@ -614,10 +616,11 @@ export interface MainThreadWebviewsShape extends IDisposable {
|
||||
$unregisterSerializer(viewType: string): void;
|
||||
|
||||
$registerTextEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, capabilities: CustomTextEditorCapabilities): void;
|
||||
$registerCustomEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions): void;
|
||||
$registerCustomEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, supportsMultipleEditorsPerResource: boolean): void;
|
||||
$unregisterEditorProvider(viewType: string): void;
|
||||
|
||||
$onDidEdit(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void;
|
||||
$onContentChange(resource: UriComponents, viewType: string): void;
|
||||
}
|
||||
|
||||
export interface WebviewPanelViewStateData {
|
||||
@@ -628,12 +631,6 @@ export interface WebviewPanelViewStateData {
|
||||
};
|
||||
}
|
||||
|
||||
export interface CustomDocumentEditState {
|
||||
readonly allEdits: readonly number[];
|
||||
readonly currentIndex: number;
|
||||
readonly saveIndex: number;
|
||||
}
|
||||
|
||||
export interface ExtHostWebviewsShape {
|
||||
$onMessage(handle: WebviewPanelHandle, message: any): void;
|
||||
$onMissingCsp(handle: WebviewPanelHandle, extensionId: string): void;
|
||||
@@ -643,18 +640,18 @@ export interface ExtHostWebviewsShape {
|
||||
$deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions): Promise<void>;
|
||||
|
||||
$resolveWebviewEditor(resource: UriComponents, newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions, cancellation: CancellationToken): Promise<void>;
|
||||
$createWebviewCustomEditorDocument(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<{ editable: boolean }>;
|
||||
$disposeWebviewCustomEditorDocument(resource: UriComponents, viewType: string): Promise<void>;
|
||||
$createCustomDocument(resource: UriComponents, viewType: string, backupId: string | undefined, cancellation: CancellationToken): Promise<{ editable: boolean }>;
|
||||
$disposeCustomDocument(resource: UriComponents, viewType: string): Promise<void>;
|
||||
|
||||
$undo(resource: UriComponents, viewType: string, editId: number, state: CustomDocumentEditState): Promise<void>;
|
||||
$redo(resource: UriComponents, viewType: string, editId: number, state: CustomDocumentEditState): Promise<void>;
|
||||
$revert(resource: UriComponents, viewType: string, changes: { undoneEdits: number[], redoneEdits: number[] }, state: CustomDocumentEditState): Promise<void>;
|
||||
$undo(resource: UriComponents, viewType: string, editId: number, isDirty: boolean): Promise<void>;
|
||||
$redo(resource: UriComponents, viewType: string, editId: number, isDirty: boolean): Promise<void>;
|
||||
$revert(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void>;
|
||||
$disposeEdits(resourceComponents: UriComponents, viewType: string, editIds: number[]): void;
|
||||
|
||||
$onSave(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void>;
|
||||
$onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents, cancellation: CancellationToken): Promise<void>;
|
||||
|
||||
$backup(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void>;
|
||||
$backup(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<string>;
|
||||
|
||||
$onMoveCustomEditor(handle: WebviewPanelHandle, newResource: UriComponents, viewType: string): Promise<void>;
|
||||
}
|
||||
@@ -853,7 +850,7 @@ export interface MainThreadDebugServiceShape extends IDisposable {
|
||||
$acceptDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): void;
|
||||
$acceptDAError(handle: number, name: string, message: string, stack: string | undefined): void;
|
||||
$acceptDAExit(handle: number, code: number | undefined, signal: string | undefined): void;
|
||||
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, hasResolve2Method: boolean, hasProvideDaMethod: boolean, handle: number): Promise<void>;
|
||||
$registerDebugConfigurationProvider(type: string, scope: DebugConfigurationProviderScope, hasProvideMethod: boolean, hasResolveMethod: boolean, hasResolve2Method: boolean, hasProvideDaMethod: boolean, handle: number): Promise<void>;
|
||||
$registerDebugAdapterDescriptorFactory(type: string, handle: number): Promise<void>;
|
||||
$unregisterDebugConfigurationProvider(handle: number): void;
|
||||
$unregisterDebugAdapterDescriptorFactory(handle: number): void;
|
||||
@@ -1114,7 +1111,7 @@ export const enum ISuggestDataDtoField {
|
||||
export interface ISuggestDataDto {
|
||||
[ISuggestDataDtoField.label]: string;
|
||||
[ISuggestDataDtoField.label2]?: string | modes.CompletionItemLabel;
|
||||
[ISuggestDataDtoField.kind]: modes.CompletionItemKind;
|
||||
[ISuggestDataDtoField.kind]?: modes.CompletionItemKind;
|
||||
[ISuggestDataDtoField.detail]?: string;
|
||||
[ISuggestDataDtoField.documentation]?: string | IMarkdownString;
|
||||
[ISuggestDataDtoField.sortText]?: string;
|
||||
@@ -1399,7 +1396,7 @@ export interface ExtHostTerminalServiceShape {
|
||||
export interface ExtHostSCMShape {
|
||||
$provideOriginalResource(sourceControlHandle: number, uri: UriComponents, token: CancellationToken): Promise<UriComponents | null>;
|
||||
$onInputBoxValueChange(sourceControlHandle: number, value: string): void;
|
||||
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number): Promise<void>;
|
||||
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number, preserveFocus: boolean): Promise<void>;
|
||||
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string, number] | undefined>;
|
||||
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise<void>;
|
||||
}
|
||||
@@ -1535,6 +1532,15 @@ export interface ExtHostCommentsShape {
|
||||
$toggleReaction(commentControllerHandle: number, threadHandle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void>;
|
||||
}
|
||||
|
||||
export interface INotebookSelectionChangeEvent {
|
||||
// handles
|
||||
selections: number[];
|
||||
}
|
||||
|
||||
export interface INotebookEditorPropertiesChangeData {
|
||||
selections: INotebookSelectionChangeEvent | null;
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookShape {
|
||||
$resolveNotebook(viewType: string, uri: UriComponents): Promise<number | undefined>;
|
||||
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
|
||||
@@ -1544,6 +1550,7 @@ export interface ExtHostNotebookShape {
|
||||
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
|
||||
$onDidReceiveMessage(uri: UriComponents, message: any): void;
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void;
|
||||
$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void;
|
||||
}
|
||||
|
||||
export interface ExtHostStorageShape {
|
||||
|
||||
@@ -143,22 +143,22 @@ const newCommands: ApiCommand[] = [
|
||||
new ApiCommand(
|
||||
'vscode.executeDefinitionProvider', '_executeDefinitionProvider', 'Execute all definition providers.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
|
||||
new ApiCommandResult<(modes.Location | modes.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location-instances.', mapLocationOrLocationLink)
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.executeTypeDefinitionProvider', '_executeTypeDefinitionProvider', 'Execute all type definition providers.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
|
||||
new ApiCommandResult<(modes.Location | modes.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location-instances.', mapLocationOrLocationLink)
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.executeDeclarationProvider', '_executeDeclarationProvider', 'Execute all declaration providers.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
|
||||
new ApiCommandResult<(modes.Location | modes.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location-instances.', mapLocationOrLocationLink)
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.executeImplementationProvider', '_executeImplementationProvider', 'Execute all implementation providers.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
|
||||
new ApiCommandResult<(modes.Location | modes.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location-instances.', mapLocationOrLocationLink)
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.executeReferenceProvider', '_executeReferenceProvider', 'Execute all reference providers.',
|
||||
@@ -507,3 +507,18 @@ function tryMapWith<T, R>(f: (x: T) => R) {
|
||||
return undefined;
|
||||
};
|
||||
}
|
||||
|
||||
function mapLocationOrLocationLink(values: (modes.Location | modes.LocationLink)[]): (types.Location | vscode.LocationLink)[] | undefined {
|
||||
if (!Array.isArray(values)) {
|
||||
return undefined;
|
||||
}
|
||||
const result: (types.Location | vscode.LocationLink)[] = [];
|
||||
for (const item of values) {
|
||||
if (modes.isLocationLink(item)) {
|
||||
result.push(typeConverters.DefinitionLink.to(item));
|
||||
} else {
|
||||
result.push(typeConverters.location.to(item));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -47,12 +47,12 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
.map(session => {
|
||||
return {
|
||||
id: session.id,
|
||||
accountName: session.accountName,
|
||||
account: session.account,
|
||||
scopes: session.scopes,
|
||||
getAccessToken: async () => {
|
||||
const isAllowed = await this._proxy.$getSessionsPrompt(
|
||||
provider.id,
|
||||
session.accountName,
|
||||
session.account.displayName,
|
||||
provider.displayName,
|
||||
extensionId,
|
||||
requestingExtension.displayName || requestingExtension.name);
|
||||
@@ -80,14 +80,15 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
}
|
||||
|
||||
const session = await provider.login(scopes);
|
||||
await this._proxy.$setTrustedExtension(provider.id, session.account.displayName, ExtensionIdentifier.toKey(requestingExtension.identifier), extensionName);
|
||||
return {
|
||||
id: session.id,
|
||||
accountName: session.accountName,
|
||||
account: session.account,
|
||||
scopes: session.scopes,
|
||||
getAccessToken: async () => {
|
||||
const isAllowed = await this._proxy.$getSessionsPrompt(
|
||||
provider.id,
|
||||
session.accountName,
|
||||
session.account.displayName,
|
||||
provider.displayName,
|
||||
ExtensionIdentifier.toKey(requestingExtension.identifier),
|
||||
requestingExtension.displayName || requestingExtension.name);
|
||||
|
||||
@@ -51,7 +51,7 @@ export interface IExtHostDebugService extends ExtHostDebugServiceShape {
|
||||
addBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>;
|
||||
removeBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>;
|
||||
startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, options: vscode.DebugSessionOptions): Promise<boolean>;
|
||||
registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable;
|
||||
registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider, scope: vscode.DebugConfigurationProviderScope): vscode.Disposable;
|
||||
registerDebugAdapterDescriptorFactory(extension: IExtensionDescription, type: string, factory: vscode.DebugAdapterDescriptorFactory): vscode.Disposable;
|
||||
registerDebugAdapterTrackerFactory(type: string, factory: vscode.DebugAdapterTrackerFactory): vscode.Disposable;
|
||||
asDebugSourceUri(source: vscode.DebugProtocolSource, session?: vscode.DebugSession): vscode.Uri;
|
||||
@@ -299,7 +299,7 @@ export class ExtHostDebugServiceBase implements IExtHostDebugService, ExtHostDeb
|
||||
});
|
||||
}
|
||||
|
||||
public registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable {
|
||||
public registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider, scope: vscode.DebugConfigurationProviderScope): vscode.Disposable {
|
||||
|
||||
if (!provider) {
|
||||
return new Disposable(() => { });
|
||||
@@ -312,7 +312,7 @@ export class ExtHostDebugServiceBase implements IExtHostDebugService, ExtHostDeb
|
||||
const handle = this._configProviderHandleCounter++;
|
||||
this._configProviders.push({ type, handle, provider });
|
||||
|
||||
this._debugServiceProxy.$registerDebugConfigurationProvider(type,
|
||||
this._debugServiceProxy.$registerDebugConfigurationProvider(type, scope,
|
||||
!!provider.provideDebugConfigurations,
|
||||
!!provider.resolveDebugConfiguration,
|
||||
!!provider.resolveDebugConfigurationWithSubstitutedVariables,
|
||||
@@ -1072,11 +1072,9 @@ class DirectDebugAdapter extends AbstractDebugAdapter {
|
||||
constructor(private implementation: vscode.DebugAdapter) {
|
||||
super();
|
||||
|
||||
if (this.implementation.onDidSendMessage) {
|
||||
implementation.onDidSendMessage((message: vscode.DebugProtocolMessage) => {
|
||||
this.acceptMessage(message as DebugProtocol.ProtocolMessage);
|
||||
});
|
||||
}
|
||||
implementation.onDidSendMessage((message: vscode.DebugProtocolMessage) => {
|
||||
this.acceptMessage(message as DebugProtocol.ProtocolMessage);
|
||||
});
|
||||
}
|
||||
|
||||
startSession(): Promise<void> {
|
||||
@@ -1084,15 +1082,11 @@ class DirectDebugAdapter extends AbstractDebugAdapter {
|
||||
}
|
||||
|
||||
sendMessage(message: DebugProtocol.ProtocolMessage): void {
|
||||
if (this.implementation.handleMessage) {
|
||||
this.implementation.handleMessage(message);
|
||||
}
|
||||
this.implementation.handleMessage(message);
|
||||
}
|
||||
|
||||
stopSession(): Promise<void> {
|
||||
if (this.implementation.dispose) {
|
||||
this.implementation.dispose();
|
||||
}
|
||||
this.implementation.dispose();
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,6 +181,10 @@ export class ExtHostDocumentData extends MirrorTextModel {
|
||||
throw new Error('Invalid argument');
|
||||
}
|
||||
|
||||
if (this._lines.length === 0) {
|
||||
return position.with(0, 0);
|
||||
}
|
||||
|
||||
let { line, character } = position;
|
||||
let hasChanged = false;
|
||||
|
||||
|
||||
@@ -371,7 +371,6 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
||||
get storagePath() { return that._storagePath.workspaceValue(extensionDescription); },
|
||||
get globalStoragePath() { return that._storagePath.globalValue(extensionDescription); },
|
||||
asAbsolutePath(relativePath: string) { return path.join(extensionDescription.extensionLocation.fsPath, relativePath); },
|
||||
asExtensionUri(relativePath: string) { return joinPath(extensionDescription.extensionLocation, relativePath); },
|
||||
get logPath() { return path.join(that._initData.logsLocation.fsPath, extensionDescription.identifier.value); }
|
||||
});
|
||||
});
|
||||
|
||||
@@ -834,7 +834,7 @@ class SuggestAdapter {
|
||||
private readonly _extension: IExtensionDescription,
|
||||
) { }
|
||||
|
||||
provideCompletionItems(resource: URI, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<extHostProtocol.ISuggestResultDto | undefined> {
|
||||
async provideCompletionItems(resource: URI, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<extHostProtocol.ISuggestResultDto | undefined> {
|
||||
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
@@ -845,48 +845,47 @@ class SuggestAdapter {
|
||||
const replaceRange = doc.getWordRangeAtPosition(pos) || new Range(pos, pos);
|
||||
const insertRange = replaceRange.with({ end: pos });
|
||||
|
||||
return asPromise(() => this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context))).then(value => {
|
||||
const itemsOrList = await asPromise(() => this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context)));
|
||||
|
||||
if (!value) {
|
||||
// undefined and null are valid results
|
||||
return undefined;
|
||||
if (!itemsOrList) {
|
||||
// undefined and null are valid results
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (token.isCancellationRequested) {
|
||||
// cancelled -> return without further ado, esp no caching
|
||||
// of results as they will leak
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const list = Array.isArray(itemsOrList) ? new CompletionList(itemsOrList) : itemsOrList;
|
||||
|
||||
// keep result for providers that support resolving
|
||||
const pid: number = SuggestAdapter.supportsResolving(this._provider) ? this._cache.add(list.items) : this._cache.add([]);
|
||||
const disposables = new DisposableStore();
|
||||
this._disposables.set(pid, disposables);
|
||||
|
||||
const completions: extHostProtocol.ISuggestDataDto[] = [];
|
||||
const result: extHostProtocol.ISuggestResultDto = {
|
||||
x: pid,
|
||||
[extHostProtocol.ISuggestResultDtoField.completions]: completions,
|
||||
[extHostProtocol.ISuggestResultDtoField.defaultRanges]: { replace: typeConvert.Range.from(replaceRange), insert: typeConvert.Range.from(insertRange) },
|
||||
[extHostProtocol.ISuggestResultDtoField.isIncomplete]: list.isIncomplete || undefined
|
||||
};
|
||||
|
||||
for (let i = 0; i < list.items.length; i++) {
|
||||
const item = list.items[i];
|
||||
// check for bad completion item first
|
||||
if (this._validateCompletionItem(item, pos)) {
|
||||
const dto = this._convertCompletionItem(item, [pid, i], insertRange, replaceRange);
|
||||
completions.push(dto);
|
||||
}
|
||||
}
|
||||
|
||||
if (token.isCancellationRequested) {
|
||||
// cancelled -> return without further ado, esp no caching
|
||||
// of results as they will leak
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const list = Array.isArray(value) ? new CompletionList(value) : value;
|
||||
|
||||
// keep result for providers that support resolving
|
||||
const pid: number = SuggestAdapter.supportsResolving(this._provider) ? this._cache.add(list.items) : this._cache.add([]);
|
||||
const disposables = new DisposableStore();
|
||||
this._disposables.set(pid, disposables);
|
||||
|
||||
const completions: extHostProtocol.ISuggestDataDto[] = [];
|
||||
const result: extHostProtocol.ISuggestResultDto = {
|
||||
x: pid,
|
||||
[extHostProtocol.ISuggestResultDtoField.completions]: completions,
|
||||
[extHostProtocol.ISuggestResultDtoField.defaultRanges]: { replace: typeConvert.Range.from(replaceRange), insert: typeConvert.Range.from(insertRange) },
|
||||
[extHostProtocol.ISuggestResultDtoField.isIncomplete]: list.isIncomplete || undefined
|
||||
};
|
||||
|
||||
for (let i = 0; i < list.items.length; i++) {
|
||||
const item = list.items[i];
|
||||
// check for bad completion item first
|
||||
if (this._validateCompletionItem(item, pos)) {
|
||||
const dto = this._convertCompletionItem(item, [pid, i], insertRange, replaceRange);
|
||||
completions.push(dto);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
resolveCompletionItem(_resource: URI, position: IPosition, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ISuggestDataDto | undefined> {
|
||||
async resolveCompletionItem(_resource: URI, position: IPosition, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ISuggestDataDto | undefined> {
|
||||
|
||||
if (typeof this._provider.resolveCompletionItem !== 'function') {
|
||||
return Promise.resolve(undefined);
|
||||
@@ -901,40 +900,39 @@ class SuggestAdapter {
|
||||
const _mustNotChange = SuggestAdapter._mustNotChangeHash(item);
|
||||
const _mayNotChange = SuggestAdapter._mayNotChangeHash(item);
|
||||
|
||||
return asPromise(() => this._provider.resolveCompletionItem!(item, token)).then(resolvedItem => {
|
||||
const resolvedItem = await asPromise(() => this._provider.resolveCompletionItem!(item, token));
|
||||
|
||||
if (!resolvedItem || !this._validateCompletionItem(resolvedItem, pos)) {
|
||||
return undefined;
|
||||
}
|
||||
if (!resolvedItem || !this._validateCompletionItem(resolvedItem, pos)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
type BlameExtension = {
|
||||
extensionId: string;
|
||||
kind: string;
|
||||
index: string;
|
||||
};
|
||||
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' };
|
||||
};
|
||||
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 _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;
|
||||
}
|
||||
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);
|
||||
});
|
||||
return this._convertCompletionItem(resolvedItem, id);
|
||||
}
|
||||
|
||||
releaseCompletionItems(id: number): any {
|
||||
@@ -956,7 +954,7 @@ class SuggestAdapter {
|
||||
//
|
||||
[extHostProtocol.ISuggestDataDtoField.label]: item.label,
|
||||
[extHostProtocol.ISuggestDataDtoField.label2]: item.label2,
|
||||
[extHostProtocol.ISuggestDataDtoField.kind]: typeConvert.CompletionItemKind.from(item.kind),
|
||||
[extHostProtocol.ISuggestDataDtoField.kind]: item.kind !== undefined ? typeConvert.CompletionItemKind.from(item.kind) : undefined,
|
||||
[extHostProtocol.ISuggestDataDtoField.kindModifier]: item.tags && item.tags.map(typeConvert.CompletionItemTag.from),
|
||||
[extHostProtocol.ISuggestDataDtoField.detail]: item.detail,
|
||||
[extHostProtocol.ISuggestDataDtoField.documentation]: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation),
|
||||
@@ -994,7 +992,7 @@ class SuggestAdapter {
|
||||
// "old" range
|
||||
result[extHostProtocol.ISuggestDataDtoField.range] = typeConvert.Range.from(range);
|
||||
|
||||
} else if (range && !defaultInsertRange?.isEqual(range.inserting) && !defaultReplaceRange?.isEqual(range.replacing)) {
|
||||
} else if (range && (!defaultInsertRange?.isEqual(range.inserting) || !defaultReplaceRange?.isEqual(range.replacing))) {
|
||||
// ONLY send range when it's different from the default ranges (safe bandwidth)
|
||||
result[extHostProtocol.ISuggestDataDtoField.range] = {
|
||||
insert: typeConvert.Range.from(range.inserting),
|
||||
|
||||
@@ -10,12 +10,14 @@ 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 } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { CellKind, CellOutputKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData } 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 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { Disposable as VSCodeDisposable } from './extHostTypes';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
|
||||
import { NotImplementedProxy } from 'vs/base/common/types';
|
||||
|
||||
interface IObservable<T> {
|
||||
proxy: T;
|
||||
@@ -40,39 +42,48 @@ function getObservable<T extends Object>(obj: T): IObservable<T> {
|
||||
|
||||
export class ExtHostCell extends Disposable implements vscode.NotebookCell {
|
||||
|
||||
private originalSource: string[];
|
||||
// private originalSource: string[];
|
||||
private _outputs: any[];
|
||||
private _onDidChangeOutputs = new Emitter<ISplice<vscode.CellOutput>[]>();
|
||||
onDidChangeOutputs: Event<ISplice<vscode.CellOutput>[]> = this._onDidChangeOutputs.event;
|
||||
private _textDocument: vscode.TextDocument | undefined;
|
||||
private _initalVersion: number = -1;
|
||||
// private _textDocument: vscode.TextDocument | undefined;
|
||||
// private _initalVersion: number = -1;
|
||||
private _outputMapping = new Set<vscode.CellOutput>();
|
||||
private _metadata: vscode.NotebookCellMetadata;
|
||||
|
||||
private _metadataChangeListener: IDisposable;
|
||||
|
||||
private _documentData: ExtHostDocumentData;
|
||||
|
||||
get document(): vscode.TextDocument {
|
||||
return this._documentData.document;
|
||||
}
|
||||
|
||||
get source() {
|
||||
if (this._textDocument && this._initalVersion !== this._textDocument?.version) {
|
||||
return this._textDocument.getText();
|
||||
} else {
|
||||
return this.originalSource.join('\n');
|
||||
}
|
||||
// todo@jrieken remove this
|
||||
return this._documentData.getText();
|
||||
}
|
||||
|
||||
constructor(
|
||||
private viewType: string,
|
||||
private documentUri: URI,
|
||||
private readonly viewType: string,
|
||||
private readonly documentUri: URI,
|
||||
readonly handle: number,
|
||||
readonly uri: URI,
|
||||
private _content: string,
|
||||
content: string,
|
||||
public readonly cellKind: CellKind,
|
||||
public language: string,
|
||||
outputs: any[],
|
||||
_metadata: vscode.NotebookCellMetadata | undefined,
|
||||
private _proxy: MainThreadNotebookShape
|
||||
private _proxy: MainThreadNotebookShape,
|
||||
) {
|
||||
super();
|
||||
this.originalSource = this._content.split(/\r|\n|\r\n/g);
|
||||
this._documentData = new ExtHostDocumentData(
|
||||
new class extends NotImplementedProxy<MainThreadDocumentsShape>('document') { },
|
||||
uri,
|
||||
content.split(/\r|\n|\r\n/g), '\n',
|
||||
language, 0, false
|
||||
);
|
||||
|
||||
this._outputs = outputs;
|
||||
|
||||
const observableMetadata = getObservable(_metadata || {});
|
||||
@@ -125,26 +136,19 @@ export class ExtHostCell extends Disposable implements vscode.NotebookCell {
|
||||
return this._proxy.$updateNotebookCellMetadata(this.viewType, this.documentUri, this.handle, this._metadata);
|
||||
}
|
||||
|
||||
getContent(): string {
|
||||
if (this._textDocument && this._initalVersion !== this._textDocument?.version) {
|
||||
return this._textDocument.getText();
|
||||
} else {
|
||||
return this.originalSource.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
attachTextDocument(document: vscode.TextDocument) {
|
||||
this._textDocument = document;
|
||||
this._initalVersion = this._textDocument.version;
|
||||
attachTextDocument(document: ExtHostDocumentData) {
|
||||
this._documentData = document;
|
||||
// this._initalVersion = this._documentData.version;
|
||||
}
|
||||
|
||||
detachTextDocument() {
|
||||
if (this._textDocument && this._textDocument.version !== this._initalVersion) {
|
||||
this.originalSource = this._textDocument.getText().split(/\r|\n|\r\n/g);
|
||||
}
|
||||
// no-op? keep stale document until new comes along?
|
||||
|
||||
this._textDocument = undefined;
|
||||
this._initalVersion = -1;
|
||||
// if (this._textDocument && this._textDocument.version !== this._initalVersion) {
|
||||
// this.originalSource = this._textDocument.getText().split(/\r|\n|\r\n/g);
|
||||
// }
|
||||
// this._textDocument = undefined;
|
||||
// this._initalVersion = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,10 +260,10 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
|
||||
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 document = this._documentsAndEditors.getDocument(URI.revive(cell.uri));
|
||||
const documentData = this._documentsAndEditors.getDocument(URI.revive(cell.uri));
|
||||
|
||||
if (document) {
|
||||
extCell.attachTextDocument(document.document);
|
||||
if (documentData) {
|
||||
extCell.attachTextDocument(documentData);
|
||||
}
|
||||
|
||||
if (!this._cellDisposableMapping.has(extCell.handle)) {
|
||||
@@ -366,15 +370,15 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
|
||||
return this.cells.find(cell => cell.handle === cellHandle);
|
||||
}
|
||||
|
||||
attachCellTextDocument(textDocument: vscode.TextDocument) {
|
||||
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.uri.toString());
|
||||
attachCellTextDocument(textDocument: ExtHostDocumentData) {
|
||||
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.document.uri.toString());
|
||||
if (cell) {
|
||||
cell.attachTextDocument(textDocument);
|
||||
}
|
||||
}
|
||||
|
||||
detachCellTextDocument(textDocument: vscode.TextDocument) {
|
||||
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.uri.toString());
|
||||
detachCellTextDocument(textDocument: ExtHostDocumentData) {
|
||||
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.document.uri.toString());
|
||||
if (cell) {
|
||||
cell.detachTextDocument();
|
||||
}
|
||||
@@ -455,6 +459,8 @@ export class NotebookEditorCellEdit {
|
||||
|
||||
export class ExtHostNotebookEditor extends Disposable implements vscode.NotebookEditor {
|
||||
private _viewColumn: vscode.ViewColumn | undefined;
|
||||
|
||||
selection?: ExtHostCell = undefined;
|
||||
onDidReceiveMessage: vscode.Event<any> = this._onDidReceiveMessage.event;
|
||||
|
||||
constructor(
|
||||
@@ -468,22 +474,22 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
) {
|
||||
super();
|
||||
this._register(this._documentsAndEditors.onDidAddDocuments(documents => {
|
||||
for (const { document: textDocument } of documents) {
|
||||
let data = CellUri.parse(textDocument.uri);
|
||||
for (const documentData of documents) {
|
||||
let data = CellUri.parse(documentData.document.uri);
|
||||
if (data) {
|
||||
if (this.document.uri.toString() === data.notebook.toString()) {
|
||||
document.attachCellTextDocument(textDocument);
|
||||
document.attachCellTextDocument(documentData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this._documentsAndEditors.onDidRemoveDocuments(documents => {
|
||||
for (const { document: textDocument } of documents) {
|
||||
let data = CellUri.parse(textDocument.uri);
|
||||
for (const documentData of documents) {
|
||||
let data = CellUri.parse(documentData.document.uri);
|
||||
if (data) {
|
||||
if (this.document.uri.toString() === data.notebook.toString()) {
|
||||
document.detachCellTextDocument(textDocument);
|
||||
document.detachCellTextDocument(documentData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -593,6 +599,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
private readonly _documents = 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: NotebookCellsSplice2[] }>();
|
||||
readonly onDidChangeNotebookDocument: Event<{ document: ExtHostNotebookDocument, changes: NotebookCellsSplice2[] }> = this._onDidChangeNotebookDocument.event;
|
||||
|
||||
private _outputDisplayOrder: INotebookDisplayOrder | undefined;
|
||||
|
||||
get outputDisplayOrder(): INotebookDisplayOrder | undefined {
|
||||
@@ -605,6 +615,12 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
return this._activeNotebookDocument;
|
||||
}
|
||||
|
||||
private _activeNotebookEditor: ExtHostNotebookEditor | undefined;
|
||||
|
||||
get activeNotebookEditor() {
|
||||
return this._activeNotebookEditor;
|
||||
}
|
||||
|
||||
constructor(mainContext: IMainContext, commands: ExtHostCommands, private _documentsAndEditors: ExtHostDocumentsAndEditors) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadNotebook);
|
||||
|
||||
@@ -738,6 +754,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
|
||||
async $updateActiveEditor(viewType: string, uri: UriComponents): Promise<void> {
|
||||
this._activeNotebookDocument = this._documents.get(URI.revive(uri).toString());
|
||||
this._activeNotebookEditor = this._editors.get(URI.revive(uri).toString())?.editor;
|
||||
}
|
||||
|
||||
async $destoryNotebookDocument(viewType: string, uri: UriComponents): Promise<boolean> {
|
||||
@@ -782,7 +799,30 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
|
||||
if (editor) {
|
||||
editor.editor.document.accpetModelChanged(event);
|
||||
this._onDidChangeNotebookDocument.fire({
|
||||
document: editor.editor.document,
|
||||
changes: event.changes
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void {
|
||||
let editor = this._editors.get(URI.revive(uriComponents).toString());
|
||||
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.selections) {
|
||||
const cells = editor.editor.document.cells;
|
||||
|
||||
if (data.selections.selections.length) {
|
||||
const firstCell = data.selections.selections[0];
|
||||
editor.editor.selection = cells.find(cell => cell.handle === firstCell);
|
||||
} else {
|
||||
editor.editor.selection = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
158
src/vs/workbench/api/common/extHostNotebookConcatDocument.ts
Normal file
158
src/vs/workbench/api/common/extHostNotebookConcatDocument.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as vscode from 'vscode';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostNotebookController, ExtHostCell } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { score } from 'vs/editor/common/modes/languageSelector';
|
||||
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
|
||||
export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextDocument {
|
||||
|
||||
private _disposables = new DisposableStore();
|
||||
private _isClosed = false;
|
||||
|
||||
private _cells!: ExtHostCell[];
|
||||
private _cellLengths!: PrefixSumComputer;
|
||||
private _cellLines!: PrefixSumComputer;
|
||||
private _versionId = 0;
|
||||
|
||||
private readonly _onDidChange = new Emitter<void>();
|
||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
constructor(
|
||||
extHostNotebooks: ExtHostNotebookController,
|
||||
extHostDocuments: ExtHostDocuments,
|
||||
private readonly _notebook: vscode.NotebookDocument,
|
||||
private readonly _selector: vscode.DocumentSelector | undefined,
|
||||
) {
|
||||
this._init();
|
||||
|
||||
this._disposables.add(extHostDocuments.onDidChangeDocument(e => {
|
||||
let cellIdx = this._cells.findIndex(cell => isEqual(cell.uri, e.document.uri));
|
||||
if (cellIdx >= 0) {
|
||||
this._cellLengths.changeValue(cellIdx, this._cells[cellIdx].document.getText().length + 1);
|
||||
this._cellLines.changeValue(cellIdx, this._cells[cellIdx].document.lineCount);
|
||||
this._versionId += 1;
|
||||
this._onDidChange.fire(undefined);
|
||||
}
|
||||
}));
|
||||
this._disposables.add(extHostNotebooks.onDidChangeNotebookDocument(e => {
|
||||
if (e.document === this._notebook) {
|
||||
this._init();
|
||||
this._versionId += 1;
|
||||
this._onDidChange.fire(undefined);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._disposables.dispose();
|
||||
this._isClosed = true;
|
||||
}
|
||||
|
||||
get isClosed() {
|
||||
return this._isClosed;
|
||||
}
|
||||
|
||||
private _init() {
|
||||
this._cells = [];
|
||||
const cellLengths: number[] = [];
|
||||
const cellLineCounts: number[] = [];
|
||||
for (let cell of this._notebook.cells) {
|
||||
if (cell.cellKind === CellKind.Code && (!this._selector || score(this._selector, cell.uri, cell.language, true))) {
|
||||
this._cells.push(<ExtHostCell>cell);
|
||||
cellLengths.push(cell.document.getText().length + 1);
|
||||
cellLineCounts.push(cell.document.lineCount);
|
||||
}
|
||||
}
|
||||
this._cellLengths = new PrefixSumComputer(new Uint32Array(cellLengths));
|
||||
this._cellLines = new PrefixSumComputer(new Uint32Array(cellLineCounts));
|
||||
}
|
||||
|
||||
get version(): number {
|
||||
return this._versionId;
|
||||
}
|
||||
|
||||
getText(range?: vscode.Range): string {
|
||||
if (!range) {
|
||||
let result = '';
|
||||
for (let cell of this._cells) {
|
||||
result += cell.document.getText() + '\n';
|
||||
}
|
||||
// remove last newline again
|
||||
result = result.slice(0, -1);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (range.isEmpty) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// get start and end locations and create substrings
|
||||
const start = this.locationAt(range.start);
|
||||
const end = this.locationAt(range.end);
|
||||
const startCell = this._cells.find(cell => isEqual(cell.uri, start.uri));
|
||||
const endCell = this._cells.find(cell => isEqual(cell.uri, end.uri));
|
||||
|
||||
if (!startCell || !endCell) {
|
||||
return '';
|
||||
} else if (startCell === endCell) {
|
||||
return startCell.document.getText(new types.Range(start.range.start, end.range.end));
|
||||
} else {
|
||||
let a = startCell.document.getText(new types.Range(start.range.start, new types.Position(startCell.document.lineCount, 0)));
|
||||
let b = endCell.document.getText(new types.Range(new types.Position(0, 0), end.range.end));
|
||||
return a + '\n' + b;
|
||||
}
|
||||
}
|
||||
|
||||
offsetAt(position: vscode.Position): number {
|
||||
const idx = this._cellLines.getIndexOf(position.line);
|
||||
const offset1 = this._cellLengths.getAccumulatedValue(idx.index - 1);
|
||||
const offset2 = this._cells[idx.index].document.offsetAt(position.with(idx.remainder));
|
||||
return offset1 + offset2;
|
||||
}
|
||||
|
||||
positionAt(locationOrOffset: vscode.Location | number): vscode.Position {
|
||||
if (typeof locationOrOffset === 'number') {
|
||||
const idx = this._cellLengths.getIndexOf(locationOrOffset);
|
||||
const lineCount = this._cellLines.getAccumulatedValue(idx.index - 1);
|
||||
return this._cells[idx.index].document.positionAt(idx.remainder).translate(lineCount);
|
||||
}
|
||||
|
||||
const idx = this._cells.findIndex(cell => isEqual(cell.uri, locationOrOffset.uri));
|
||||
if (idx >= 0) {
|
||||
let line = this._cellLines.getAccumulatedValue(idx - 1);
|
||||
return new types.Position(line + locationOrOffset.range.start.line, locationOrOffset.range.start.character);
|
||||
}
|
||||
// do better?
|
||||
// return undefined;
|
||||
return new types.Position(0, 0);
|
||||
}
|
||||
|
||||
locationAt(positionOrRange: vscode.Range | vscode.Position): types.Location {
|
||||
if (!types.Range.isRange(positionOrRange)) {
|
||||
positionOrRange = new types.Range(<types.Position>positionOrRange, <types.Position>positionOrRange);
|
||||
}
|
||||
|
||||
const startIdx = this._cellLines.getIndexOf(positionOrRange.start.line);
|
||||
let endIdx = startIdx;
|
||||
if (!positionOrRange.isEmpty) {
|
||||
endIdx = this._cellLines.getIndexOf(positionOrRange.end.line);
|
||||
}
|
||||
|
||||
let startPos = new types.Position(startIdx.remainder, positionOrRange.start.character);
|
||||
let endPos = new types.Position(endIdx.remainder, positionOrRange.end.character);
|
||||
let range = new types.Range(startPos, endPos);
|
||||
|
||||
const startCell = this._cells[startIdx.index];
|
||||
return new types.Location(startCell.uri, <types.Range>startCell.document.validateRange(range));
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { debounce } from 'vs/base/common/decorators';
|
||||
import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { asPromise } from 'vs/base/common/async';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto } from './extHost.protocol';
|
||||
import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto, MainThreadTelemetryShape } from './extHost.protocol';
|
||||
import { sortedDiff, equals } from 'vs/base/common/arrays';
|
||||
import { comparePaths } from 'vs/base/common/comparers';
|
||||
import type * as vscode from 'vscode';
|
||||
@@ -194,6 +194,11 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
|
||||
|
||||
set visible(visible: boolean) {
|
||||
visible = !!visible;
|
||||
|
||||
if (this._visible === visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._visible = visible;
|
||||
this._proxy.$setInputBoxVisibility(this._sourceControlHandle, visible);
|
||||
}
|
||||
@@ -266,14 +271,14 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
|
||||
return this._resourceStatesMap.get(handle);
|
||||
}
|
||||
|
||||
$executeResourceCommand(handle: number): Promise<void> {
|
||||
$executeResourceCommand(handle: number, preserveFocus: boolean): Promise<void> {
|
||||
const command = this._resourceStatesCommandsMap.get(handle);
|
||||
|
||||
if (!command) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return asPromise(() => this._commands.executeCommand(command.command, ...(command.arguments || [])));
|
||||
return asPromise(() => this._commands.executeCommand(command.command, ...(command.arguments || []), preserveFocus));
|
||||
}
|
||||
|
||||
_takeResourceStateSnapshot(): SCMRawResourceSplice[] {
|
||||
@@ -524,6 +529,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
private static _handlePool: number = 0;
|
||||
|
||||
private _proxy: MainThreadSCMShape;
|
||||
private readonly _telemetry: MainThreadTelemetryShape;
|
||||
private _sourceControls: Map<ProviderHandle, ExtHostSourceControl> = new Map<ProviderHandle, ExtHostSourceControl>();
|
||||
private _sourceControlsByExtension: Map<string, ExtHostSourceControl[]> = new Map<string, ExtHostSourceControl[]>();
|
||||
|
||||
@@ -538,6 +544,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadSCM);
|
||||
this._telemetry = mainContext.getProxy(MainContext.MainThreadTelemetry);
|
||||
|
||||
_commands.registerArgumentProcessor({
|
||||
processArgument: arg => {
|
||||
@@ -581,6 +588,12 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
createSourceControl(extension: IExtensionDescription, id: string, label: string, rootUri: vscode.Uri | undefined): vscode.SourceControl {
|
||||
this.logService.trace('ExtHostSCM#createSourceControl', extension.identifier.value, id, label, rootUri);
|
||||
|
||||
type TEvent = { extensionId: string; };
|
||||
type TMeta = { extensionId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; };
|
||||
this._telemetry.$publicLog2<TEvent, TMeta>('api/scm/createSourceControl', {
|
||||
extensionId: extension.identifier.value,
|
||||
});
|
||||
|
||||
const handle = ExtHostSCM._handlePool++;
|
||||
const sourceControl = new ExtHostSourceControl(extension, this._proxy, this._commands, id, label, rootUri);
|
||||
this._sourceControls.set(handle, sourceControl);
|
||||
@@ -628,7 +641,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number): Promise<void> {
|
||||
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number, preserveFocus: boolean): Promise<void> {
|
||||
this.logService.trace('ExtHostSCM#$executeResourceCommand', sourceControlHandle, groupHandle, handle);
|
||||
|
||||
const sourceControl = this._sourceControls.get(sourceControlHandle);
|
||||
@@ -643,7 +656,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return group.$executeResourceCommand(handle);
|
||||
return group.$executeResourceCommand(handle, preserveFocus);
|
||||
}
|
||||
|
||||
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string, number] | undefined> {
|
||||
|
||||
@@ -692,7 +692,7 @@ export class EnvironmentVariableCollection implements vscode.EnvironmentVariable
|
||||
|
||||
forEach(callback: (variable: string, mutator: vscode.EnvironmentVariableMutator, collection: vscode.EnvironmentVariableCollection) => any, thisArg?: any): void {
|
||||
this._checkDisposed();
|
||||
this.map.forEach((value, key) => callback(key, value, this));
|
||||
this.map.forEach((value, key) => callback.call(thisArg, key, value, this));
|
||||
}
|
||||
|
||||
delete(variable: string): void {
|
||||
|
||||
@@ -728,6 +728,18 @@ export namespace DefinitionLink {
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
export function to(value: modes.LocationLink): vscode.LocationLink {
|
||||
return {
|
||||
targetUri: value.uri,
|
||||
targetRange: Range.to(value.range),
|
||||
targetSelectionRange: value.targetSelectionRange
|
||||
? Range.to(value.targetSelectionRange)
|
||||
: undefined,
|
||||
originSelectionRange: value.originSelectionRange
|
||||
? Range.to(value.originSelectionRange)
|
||||
: undefined
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Hover {
|
||||
@@ -808,70 +820,72 @@ export namespace CompletionItemTag {
|
||||
|
||||
export namespace CompletionItemKind {
|
||||
|
||||
export function from(kind: types.CompletionItemKind | undefined): modes.CompletionItemKind {
|
||||
switch (kind) {
|
||||
case types.CompletionItemKind.Method: return modes.CompletionItemKind.Method;
|
||||
case types.CompletionItemKind.Function: return modes.CompletionItemKind.Function;
|
||||
case types.CompletionItemKind.Constructor: return modes.CompletionItemKind.Constructor;
|
||||
case types.CompletionItemKind.Field: return modes.CompletionItemKind.Field;
|
||||
case types.CompletionItemKind.Variable: return modes.CompletionItemKind.Variable;
|
||||
case types.CompletionItemKind.Class: return modes.CompletionItemKind.Class;
|
||||
case types.CompletionItemKind.Interface: return modes.CompletionItemKind.Interface;
|
||||
case types.CompletionItemKind.Struct: return modes.CompletionItemKind.Struct;
|
||||
case types.CompletionItemKind.Module: return modes.CompletionItemKind.Module;
|
||||
case types.CompletionItemKind.Property: return modes.CompletionItemKind.Property;
|
||||
case types.CompletionItemKind.Unit: return modes.CompletionItemKind.Unit;
|
||||
case types.CompletionItemKind.Value: return modes.CompletionItemKind.Value;
|
||||
case types.CompletionItemKind.Constant: return modes.CompletionItemKind.Constant;
|
||||
case types.CompletionItemKind.Enum: return modes.CompletionItemKind.Enum;
|
||||
case types.CompletionItemKind.EnumMember: return modes.CompletionItemKind.EnumMember;
|
||||
case types.CompletionItemKind.Keyword: return modes.CompletionItemKind.Keyword;
|
||||
case types.CompletionItemKind.Snippet: return modes.CompletionItemKind.Snippet;
|
||||
case types.CompletionItemKind.Text: return modes.CompletionItemKind.Text;
|
||||
case types.CompletionItemKind.Color: return modes.CompletionItemKind.Color;
|
||||
case types.CompletionItemKind.File: return modes.CompletionItemKind.File;
|
||||
case types.CompletionItemKind.Reference: return modes.CompletionItemKind.Reference;
|
||||
case types.CompletionItemKind.Folder: return modes.CompletionItemKind.Folder;
|
||||
case types.CompletionItemKind.Event: return modes.CompletionItemKind.Event;
|
||||
case types.CompletionItemKind.Operator: return modes.CompletionItemKind.Operator;
|
||||
case types.CompletionItemKind.TypeParameter: return modes.CompletionItemKind.TypeParameter;
|
||||
case types.CompletionItemKind.Issue: return modes.CompletionItemKind.Issue;
|
||||
case types.CompletionItemKind.User: return modes.CompletionItemKind.User;
|
||||
}
|
||||
return modes.CompletionItemKind.Property;
|
||||
const _from = new Map<types.CompletionItemKind, modes.CompletionItemKind>([
|
||||
[types.CompletionItemKind.Method, modes.CompletionItemKind.Method],
|
||||
[types.CompletionItemKind.Function, modes.CompletionItemKind.Function],
|
||||
[types.CompletionItemKind.Constructor, modes.CompletionItemKind.Constructor],
|
||||
[types.CompletionItemKind.Field, modes.CompletionItemKind.Field],
|
||||
[types.CompletionItemKind.Variable, modes.CompletionItemKind.Variable],
|
||||
[types.CompletionItemKind.Class, modes.CompletionItemKind.Class],
|
||||
[types.CompletionItemKind.Interface, modes.CompletionItemKind.Interface],
|
||||
[types.CompletionItemKind.Struct, modes.CompletionItemKind.Struct],
|
||||
[types.CompletionItemKind.Module, modes.CompletionItemKind.Module],
|
||||
[types.CompletionItemKind.Property, modes.CompletionItemKind.Property],
|
||||
[types.CompletionItemKind.Unit, modes.CompletionItemKind.Unit],
|
||||
[types.CompletionItemKind.Value, modes.CompletionItemKind.Value],
|
||||
[types.CompletionItemKind.Constant, modes.CompletionItemKind.Constant],
|
||||
[types.CompletionItemKind.Enum, modes.CompletionItemKind.Enum],
|
||||
[types.CompletionItemKind.EnumMember, modes.CompletionItemKind.EnumMember],
|
||||
[types.CompletionItemKind.Keyword, modes.CompletionItemKind.Keyword],
|
||||
[types.CompletionItemKind.Snippet, modes.CompletionItemKind.Snippet],
|
||||
[types.CompletionItemKind.Text, modes.CompletionItemKind.Text],
|
||||
[types.CompletionItemKind.Color, modes.CompletionItemKind.Color],
|
||||
[types.CompletionItemKind.File, modes.CompletionItemKind.File],
|
||||
[types.CompletionItemKind.Reference, modes.CompletionItemKind.Reference],
|
||||
[types.CompletionItemKind.Folder, modes.CompletionItemKind.Folder],
|
||||
[types.CompletionItemKind.Event, modes.CompletionItemKind.Event],
|
||||
[types.CompletionItemKind.Operator, modes.CompletionItemKind.Operator],
|
||||
[types.CompletionItemKind.TypeParameter, modes.CompletionItemKind.TypeParameter],
|
||||
[types.CompletionItemKind.Issue, modes.CompletionItemKind.Issue],
|
||||
[types.CompletionItemKind.User, modes.CompletionItemKind.User],
|
||||
]);
|
||||
|
||||
export function from(kind: types.CompletionItemKind): modes.CompletionItemKind {
|
||||
return _from.get(kind) ?? modes.CompletionItemKind.Property;
|
||||
}
|
||||
|
||||
const _to = new Map<modes.CompletionItemKind, types.CompletionItemKind>([
|
||||
[modes.CompletionItemKind.Method, types.CompletionItemKind.Method],
|
||||
[modes.CompletionItemKind.Function, types.CompletionItemKind.Function],
|
||||
[modes.CompletionItemKind.Constructor, types.CompletionItemKind.Constructor],
|
||||
[modes.CompletionItemKind.Field, types.CompletionItemKind.Field],
|
||||
[modes.CompletionItemKind.Variable, types.CompletionItemKind.Variable],
|
||||
[modes.CompletionItemKind.Class, types.CompletionItemKind.Class],
|
||||
[modes.CompletionItemKind.Interface, types.CompletionItemKind.Interface],
|
||||
[modes.CompletionItemKind.Struct, types.CompletionItemKind.Struct],
|
||||
[modes.CompletionItemKind.Module, types.CompletionItemKind.Module],
|
||||
[modes.CompletionItemKind.Property, types.CompletionItemKind.Property],
|
||||
[modes.CompletionItemKind.Unit, types.CompletionItemKind.Unit],
|
||||
[modes.CompletionItemKind.Value, types.CompletionItemKind.Value],
|
||||
[modes.CompletionItemKind.Constant, types.CompletionItemKind.Constant],
|
||||
[modes.CompletionItemKind.Enum, types.CompletionItemKind.Enum],
|
||||
[modes.CompletionItemKind.EnumMember, types.CompletionItemKind.EnumMember],
|
||||
[modes.CompletionItemKind.Keyword, types.CompletionItemKind.Keyword],
|
||||
[modes.CompletionItemKind.Snippet, types.CompletionItemKind.Snippet],
|
||||
[modes.CompletionItemKind.Text, types.CompletionItemKind.Text],
|
||||
[modes.CompletionItemKind.Color, types.CompletionItemKind.Color],
|
||||
[modes.CompletionItemKind.File, types.CompletionItemKind.File],
|
||||
[modes.CompletionItemKind.Reference, types.CompletionItemKind.Reference],
|
||||
[modes.CompletionItemKind.Folder, types.CompletionItemKind.Folder],
|
||||
[modes.CompletionItemKind.Event, types.CompletionItemKind.Event],
|
||||
[modes.CompletionItemKind.Operator, types.CompletionItemKind.Operator],
|
||||
[modes.CompletionItemKind.TypeParameter, types.CompletionItemKind.TypeParameter],
|
||||
[modes.CompletionItemKind.User, types.CompletionItemKind.User],
|
||||
[modes.CompletionItemKind.Issue, types.CompletionItemKind.Issue],
|
||||
]);
|
||||
|
||||
export function to(kind: modes.CompletionItemKind): types.CompletionItemKind {
|
||||
switch (kind) {
|
||||
case modes.CompletionItemKind.Method: return types.CompletionItemKind.Method;
|
||||
case modes.CompletionItemKind.Function: return types.CompletionItemKind.Function;
|
||||
case modes.CompletionItemKind.Constructor: return types.CompletionItemKind.Constructor;
|
||||
case modes.CompletionItemKind.Field: return types.CompletionItemKind.Field;
|
||||
case modes.CompletionItemKind.Variable: return types.CompletionItemKind.Variable;
|
||||
case modes.CompletionItemKind.Class: return types.CompletionItemKind.Class;
|
||||
case modes.CompletionItemKind.Interface: return types.CompletionItemKind.Interface;
|
||||
case modes.CompletionItemKind.Struct: return types.CompletionItemKind.Struct;
|
||||
case modes.CompletionItemKind.Module: return types.CompletionItemKind.Module;
|
||||
case modes.CompletionItemKind.Property: return types.CompletionItemKind.Property;
|
||||
case modes.CompletionItemKind.Unit: return types.CompletionItemKind.Unit;
|
||||
case modes.CompletionItemKind.Value: return types.CompletionItemKind.Value;
|
||||
case modes.CompletionItemKind.Constant: return types.CompletionItemKind.Constant;
|
||||
case modes.CompletionItemKind.Enum: return types.CompletionItemKind.Enum;
|
||||
case modes.CompletionItemKind.EnumMember: return types.CompletionItemKind.EnumMember;
|
||||
case modes.CompletionItemKind.Keyword: return types.CompletionItemKind.Keyword;
|
||||
case modes.CompletionItemKind.Snippet: return types.CompletionItemKind.Snippet;
|
||||
case modes.CompletionItemKind.Text: return types.CompletionItemKind.Text;
|
||||
case modes.CompletionItemKind.Color: return types.CompletionItemKind.Color;
|
||||
case modes.CompletionItemKind.File: return types.CompletionItemKind.File;
|
||||
case modes.CompletionItemKind.Reference: return types.CompletionItemKind.Reference;
|
||||
case modes.CompletionItemKind.Folder: return types.CompletionItemKind.Folder;
|
||||
case modes.CompletionItemKind.Event: return types.CompletionItemKind.Event;
|
||||
case modes.CompletionItemKind.Operator: return types.CompletionItemKind.Operator;
|
||||
case modes.CompletionItemKind.TypeParameter: return types.CompletionItemKind.TypeParameter;
|
||||
case modes.CompletionItemKind.User: return types.CompletionItemKind.User;
|
||||
case modes.CompletionItemKind.Issue: return types.CompletionItemKind.Issue;
|
||||
}
|
||||
return types.CompletionItemKind.Property;
|
||||
return _to.get(kind) ?? types.CompletionItemKind.Property;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -939,7 +953,8 @@ export namespace SignatureInformation {
|
||||
return {
|
||||
label: info.label,
|
||||
documentation: info.documentation ? MarkdownString.fromStrict(info.documentation) : undefined,
|
||||
parameters: Array.isArray(info.parameters) ? info.parameters.map(ParameterInformation.from) : []
|
||||
parameters: Array.isArray(info.parameters) ? info.parameters.map(ParameterInformation.from) : [],
|
||||
activeParameter: info.activeParameter,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -947,7 +962,8 @@ export namespace SignatureInformation {
|
||||
return {
|
||||
label: info.label,
|
||||
documentation: htmlContent.isMarkdownString(info.documentation) ? MarkdownString.to(info.documentation) : info.documentation,
|
||||
parameters: Array.isArray(info.parameters) ? info.parameters.map(ParameterInformation.to) : []
|
||||
parameters: Array.isArray(info.parameters) ? info.parameters.map(ParameterInformation.to) : [],
|
||||
activeParameter: info.activeParameter,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,15 @@
|
||||
import { coalesce, equals } from 'vs/base/common/arrays';
|
||||
import { escapeCodicons } from 'vs/base/common/codicons';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { isMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
import { isStringArray } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/platform/files/common/files';
|
||||
import { RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import type * as vscode from 'vscode';
|
||||
import { Cache } from './cache';
|
||||
import { assertIsDefined, isStringArray } from 'vs/base/common/types';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
function es5ClassCompat(target: Function): any {
|
||||
///@ts-expect-error
|
||||
@@ -1294,6 +1291,7 @@ export class SignatureInformation {
|
||||
label: string;
|
||||
documentation?: string | MarkdownString;
|
||||
parameters: ParameterInformation[];
|
||||
activeParameter?: number;
|
||||
|
||||
constructor(label: string, documentation?: string | MarkdownString) {
|
||||
this.label = label;
|
||||
@@ -2654,6 +2652,22 @@ export enum DebugConsoleMode {
|
||||
MergeWithParent = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* VS Code can call the `provideDebugConfigurations` method of a `DebugConfigurationProvider` in two situations (aka 'scopes'):
|
||||
* to provide the initial debug configurations for a newly create launch.json or to provide debug configurations dynamically based on context.
|
||||
* A scope value is used when registering a `DebugConfigurationProvider` with `debug.registerDebugConfigurationProvider`.
|
||||
*/
|
||||
export enum DebugConfigurationProviderScope {
|
||||
/**
|
||||
* The 'initial' scope denotes a context where all debug configurations for a newly created launch.json are needed.
|
||||
*/
|
||||
Initial = 1,
|
||||
/**
|
||||
* The 'dynamic' scope denotes a context where all debug configurations for the current context are needed.
|
||||
*/
|
||||
Dynamic = 2
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@es5ClassCompat
|
||||
@@ -2716,6 +2730,13 @@ export enum CellOutputKind {
|
||||
Rich = 3
|
||||
}
|
||||
|
||||
export enum NotebookCellRunState {
|
||||
Running = 1,
|
||||
Idle = 2,
|
||||
Success = 3,
|
||||
Error = 4
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Timeline
|
||||
@@ -2726,94 +2747,3 @@ export class TimelineItem implements vscode.TimelineItem {
|
||||
}
|
||||
|
||||
//#endregion Timeline
|
||||
|
||||
//#region Custom Editors
|
||||
|
||||
interface EditState {
|
||||
readonly allEdits: readonly number[];
|
||||
readonly currentIndex: number;
|
||||
readonly saveIndex: number;
|
||||
}
|
||||
|
||||
export class CustomDocument<EditType = unknown> implements vscode.CustomDocument<EditType> {
|
||||
|
||||
readonly #edits = new Cache<EditType>('edits');
|
||||
|
||||
readonly #uri: vscode.Uri;
|
||||
|
||||
#editState: EditState = {
|
||||
allEdits: [],
|
||||
currentIndex: -1,
|
||||
saveIndex: -1,
|
||||
};
|
||||
#isDisposed = false;
|
||||
#version = 1;
|
||||
|
||||
constructor(uri: vscode.Uri) {
|
||||
this.#uri = uri;
|
||||
}
|
||||
|
||||
//#region Public API
|
||||
|
||||
public get uri(): vscode.Uri { return this.#uri; }
|
||||
|
||||
public get fileName(): string { return this.uri.fsPath; }
|
||||
|
||||
public get isUntitled() { return this.uri.scheme === Schemas.untitled; }
|
||||
|
||||
#onDidDispose = new Emitter<void>();
|
||||
public readonly onDidDispose = this.#onDidDispose.event;
|
||||
|
||||
public get isClosed() { return this.#isDisposed; }
|
||||
|
||||
public get version() { return this.#version; }
|
||||
|
||||
public get isDirty() {
|
||||
return this.#editState.currentIndex !== this.#editState.saveIndex;
|
||||
}
|
||||
|
||||
public get appliedEdits() {
|
||||
return this.#editState.allEdits.slice(0, this.#editState.currentIndex + 1)
|
||||
.map(id => this._getEdit(id));
|
||||
}
|
||||
|
||||
public get savedEdits() {
|
||||
return this.#editState.allEdits.slice(0, this.#editState.saveIndex + 1)
|
||||
.map(id => this._getEdit(id));
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
/** @internal */ _dispose(): void {
|
||||
this.#isDisposed = true;
|
||||
this.#onDidDispose.fire();
|
||||
this.#onDidDispose.dispose();
|
||||
}
|
||||
|
||||
/** @internal */ _updateEditState(state: EditState) {
|
||||
++this.#version;
|
||||
this.#editState = state;
|
||||
}
|
||||
|
||||
/** @internal*/ _getEdit(editId: number): EditType {
|
||||
return assertIsDefined(this.#edits.get(editId, 0));
|
||||
}
|
||||
|
||||
/** @internal*/ _disposeEdits(editIds: number[]) {
|
||||
for (const editId of editIds) {
|
||||
this.#edits.delete(editId);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal*/ _addEdit(edit: EditType): number {
|
||||
const id = this.#edits.add([edit]);
|
||||
this._updateEditState({
|
||||
allEdits: [...this.#editState.allEdits.slice(0, this.#editState.currentIndex + 1), id],
|
||||
currentIndex: this.#editState.currentIndex + 1,
|
||||
saveIndex: this.#editState.saveIndex,
|
||||
});
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
@@ -18,6 +18,7 @@ import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
|
||||
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
|
||||
import type * as vscode from 'vscode';
|
||||
import { Cache } from './cache';
|
||||
import * as extHostProtocol from './extHost.protocol';
|
||||
import * as extHostTypes from './extHostTypes';
|
||||
|
||||
@@ -262,22 +263,78 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa
|
||||
}
|
||||
}
|
||||
|
||||
class WebviewDocumentStore {
|
||||
private readonly _documents = new Map<string, extHostTypes.CustomDocument>();
|
||||
class CustomDocumentStoreEntry {
|
||||
|
||||
public get(viewType: string, resource: vscode.Uri): extHostTypes.CustomDocument | undefined {
|
||||
constructor(
|
||||
public readonly document: vscode.CustomDocument,
|
||||
) { }
|
||||
|
||||
private readonly _edits = new Cache<vscode.CustomDocumentEditEvent>('custom documents');
|
||||
|
||||
private _backup?: vscode.CustomDocumentBackup;
|
||||
|
||||
|
||||
addEdit(item: vscode.CustomDocumentEditEvent): number {
|
||||
return this._edits.add([item]);
|
||||
}
|
||||
|
||||
async undo(editId: number, isDirty: boolean): Promise<void> {
|
||||
await this.getEdit(editId).undo();
|
||||
if (!isDirty) {
|
||||
this.disposeBackup();
|
||||
}
|
||||
}
|
||||
|
||||
async redo(editId: number, isDirty: boolean): Promise<void> {
|
||||
await this.getEdit(editId).redo();
|
||||
if (!isDirty) {
|
||||
this.disposeBackup();
|
||||
}
|
||||
}
|
||||
|
||||
disposeEdits(editIds: number[]): void {
|
||||
for (const id of editIds) {
|
||||
this._edits.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
updateBackup(backup: vscode.CustomDocumentBackup): void {
|
||||
this._backup?.dispose();
|
||||
this._backup = backup;
|
||||
}
|
||||
|
||||
disposeBackup(): void {
|
||||
this._backup?.dispose();
|
||||
this._backup = undefined;
|
||||
}
|
||||
|
||||
private getEdit(editId: number): vscode.CustomDocumentEditEvent {
|
||||
const edit = this._edits.get(editId, 0);
|
||||
if (!edit) {
|
||||
throw new Error('No edit found');
|
||||
}
|
||||
return edit;
|
||||
}
|
||||
}
|
||||
|
||||
class CustomDocumentStore {
|
||||
private readonly _documents = new Map<string, CustomDocumentStoreEntry>();
|
||||
|
||||
public get(viewType: string, resource: vscode.Uri): CustomDocumentStoreEntry | undefined {
|
||||
return this._documents.get(this.key(viewType, resource));
|
||||
}
|
||||
|
||||
public add(viewType: string, document: extHostTypes.CustomDocument) {
|
||||
public add(viewType: string, document: vscode.CustomDocument): CustomDocumentStoreEntry {
|
||||
const key = this.key(viewType, document.uri);
|
||||
if (this._documents.has(key)) {
|
||||
throw new Error(`Document already exists for viewType:${viewType} resource:${document.uri}`);
|
||||
}
|
||||
this._documents.set(key, document);
|
||||
const entry = new CustomDocumentStoreEntry(document);
|
||||
this._documents.set(key, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
public delete(viewType: string, document: extHostTypes.CustomDocument) {
|
||||
public delete(viewType: string, document: vscode.CustomDocument) {
|
||||
const key = this.key(viewType, document.uri);
|
||||
this._documents.delete(key);
|
||||
}
|
||||
@@ -285,6 +342,7 @@ class WebviewDocumentStore {
|
||||
private key(viewType: string, resource: vscode.Uri): string {
|
||||
return `${viewType}@@@${resource}`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const enum WebviewEditorType {
|
||||
@@ -342,7 +400,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
|
||||
private readonly _editorProviders = new EditorProviderStore();
|
||||
|
||||
private readonly _documents = new WebviewDocumentStore();
|
||||
private readonly _documents = new CustomDocumentStore();
|
||||
|
||||
constructor(
|
||||
mainContext: extHostProtocol.IMainContext,
|
||||
@@ -399,24 +457,17 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
extension: IExtensionDescription,
|
||||
viewType: string,
|
||||
provider: vscode.CustomEditorProvider | vscode.CustomTextEditorProvider,
|
||||
options: vscode.WebviewPanelOptions | undefined = {}
|
||||
options: { webviewOptions?: vscode.WebviewPanelOptions, supportsMultipleEditorsPerResource?: boolean },
|
||||
): vscode.Disposable {
|
||||
const disposables = new DisposableStore();
|
||||
if ('resolveCustomTextEditor' in provider) {
|
||||
disposables.add(this._editorProviders.addTextProvider(viewType, extension, provider));
|
||||
this._proxy.$registerTextEditorProvider(toExtensionData(extension), viewType, options, {
|
||||
this._proxy.$registerTextEditorProvider(toExtensionData(extension), viewType, options.webviewOptions || {}, {
|
||||
supportsMove: !!provider.moveCustomTextEditor,
|
||||
});
|
||||
} else {
|
||||
disposables.add(this._editorProviders.addCustomProvider(viewType, extension, provider));
|
||||
this._proxy.$registerCustomEditorProvider(toExtensionData(extension), viewType, options);
|
||||
if (provider.editingDelegate) {
|
||||
disposables.add(provider.editingDelegate.onDidEdit(e => {
|
||||
const document = e.document;
|
||||
const editId = (document as extHostTypes.CustomDocument)._addEdit(e.edit);
|
||||
this._proxy.$onDidEdit(document.uri, viewType, editId, e.label);
|
||||
}));
|
||||
}
|
||||
this._proxy.$registerCustomEditorProvider(toExtensionData(extension), viewType, options.webviewOptions || {}, !!options.supportsMultipleEditorsPerResource);
|
||||
}
|
||||
|
||||
return extHostTypes.Disposable.from(
|
||||
@@ -504,7 +555,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
await serializer.deserializeWebviewPanel(revivedPanel, state);
|
||||
}
|
||||
|
||||
async $createWebviewCustomEditorDocument(resource: UriComponents, viewType: string, cancellation: CancellationToken) {
|
||||
async $createCustomDocument(resource: UriComponents, viewType: string, backupId: string | undefined, cancellation: CancellationToken) {
|
||||
const entry = this._editorProviders.get(viewType);
|
||||
if (!entry) {
|
||||
throw new Error(`No provider found for '${viewType}'`);
|
||||
@@ -515,14 +566,24 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
const revivedResource = URI.revive(resource);
|
||||
const document = await entry.provider.openCustomDocument(revivedResource, cancellation);
|
||||
this._documents.add(viewType, document as extHostTypes.CustomDocument);
|
||||
return {
|
||||
editable: !!entry.provider.editingDelegate,
|
||||
};
|
||||
const document = await entry.provider.openCustomDocument(revivedResource, { backupId }, cancellation);
|
||||
const documentEntry = this._documents.add(viewType, document);
|
||||
|
||||
if (this.isEditable(document)) {
|
||||
document.onDidChange(e => {
|
||||
if (isEditEvent(e)) {
|
||||
const editId = documentEntry.addEdit(e);
|
||||
this._proxy.$onDidEdit(document.uri, viewType, editId, e.label);
|
||||
} else {
|
||||
this._proxy.$onContentChange(document.uri, viewType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return { editable: this.isEditable(document) };
|
||||
}
|
||||
|
||||
async $disposeWebviewCustomEditorDocument(resource: UriComponents, viewType: string): Promise<void> {
|
||||
async $disposeCustomDocument(resource: UriComponents, viewType: string): Promise<void> {
|
||||
const entry = this._editorProviders.get(viewType);
|
||||
if (!entry) {
|
||||
throw new Error(`No provider found for '${viewType}'`);
|
||||
@@ -533,9 +594,9 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
const revivedResource = URI.revive(resource);
|
||||
const document = this.getCustomDocument(viewType, revivedResource);
|
||||
const { document } = this.getCustomDocumentEntry(viewType, revivedResource);
|
||||
this._documents.delete(viewType, document);
|
||||
document._dispose();
|
||||
document.dispose();
|
||||
}
|
||||
|
||||
async $resolveWebviewEditor(
|
||||
@@ -561,7 +622,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
switch (entry.type) {
|
||||
case WebviewEditorType.Custom:
|
||||
{
|
||||
const document = this.getCustomDocument(viewType, revivedResource);
|
||||
const { document } = this.getCustomDocumentEntry(viewType, revivedResource);
|
||||
return entry.provider.resolveCustomEditor(document, revivedPanel, cancellation);
|
||||
}
|
||||
case WebviewEditorType.Text:
|
||||
@@ -577,8 +638,8 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
$disposeEdits(resourceComponents: UriComponents, viewType: string, editIds: number[]): void {
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
document._disposeEdits(editIds);
|
||||
const document = this.getCustomDocumentEntry(viewType, resourceComponents);
|
||||
document.disposeEdits(editIds);
|
||||
}
|
||||
|
||||
async $onMoveCustomEditor(handle: string, newResourceComponents: UriComponents, viewType: string): Promise<void> {
|
||||
@@ -601,69 +662,65 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
await (entry.provider as vscode.CustomTextEditorProvider).moveCustomTextEditor!(document, webview, CancellationToken.None);
|
||||
}
|
||||
|
||||
async $undo(resourceComponents: UriComponents, viewType: string, editId: number, state: extHostProtocol.CustomDocumentEditState): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
document._updateEditState(state);
|
||||
return delegate.undoEdits(document, [document._getEdit(editId)]);
|
||||
async $undo(resourceComponents: UriComponents, viewType: string, editId: number, isDirty: boolean): Promise<void> {
|
||||
const entry = this.getCustomDocumentEntry(viewType, resourceComponents);
|
||||
return entry.undo(editId, isDirty);
|
||||
}
|
||||
|
||||
async $redo(resourceComponents: UriComponents, viewType: string, editId: number, state: extHostProtocol.CustomDocumentEditState): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
document._updateEditState(state);
|
||||
return delegate.applyEdits(document, [document._getEdit(editId)]);
|
||||
async $redo(resourceComponents: UriComponents, viewType: string, editId: number, isDirty: boolean): Promise<void> {
|
||||
const entry = this.getCustomDocumentEntry(viewType, resourceComponents);
|
||||
return entry.redo(editId, isDirty);
|
||||
}
|
||||
|
||||
async $revert(resourceComponents: UriComponents, viewType: string, changes: { undoneEdits: number[], redoneEdits: number[] }, state: extHostProtocol.CustomDocumentEditState): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
const undoneEdits = changes.undoneEdits.map(id => document._getEdit(id));
|
||||
const appliedEdits = changes.redoneEdits.map(id => document._getEdit(id));
|
||||
document._updateEditState(state);
|
||||
return delegate.revert(document, { undoneEdits, appliedEdits });
|
||||
async $revert(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void> {
|
||||
const entry = this.getCustomDocumentEntry(viewType, resourceComponents);
|
||||
const document = this.getEditableCustomDocument(viewType, resourceComponents);
|
||||
await document.revert(cancellation);
|
||||
entry.disposeBackup();
|
||||
}
|
||||
|
||||
async $onSave(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
return delegate.save(document, cancellation);
|
||||
const entry = this.getCustomDocumentEntry(viewType, resourceComponents);
|
||||
const document = this.getEditableCustomDocument(viewType, resourceComponents);
|
||||
await document.save(cancellation);
|
||||
entry.disposeBackup();
|
||||
}
|
||||
|
||||
async $onSaveAs(resourceComponents: UriComponents, viewType: string, targetResource: UriComponents, cancellation: CancellationToken): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
return delegate.saveAs(document, URI.revive(targetResource), cancellation);
|
||||
const document = this.getEditableCustomDocument(viewType, resourceComponents);
|
||||
return document.saveAs(URI.revive(targetResource), cancellation);
|
||||
}
|
||||
|
||||
async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
return delegate.backup(document, cancellation);
|
||||
async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise<string> {
|
||||
const entry = this.getCustomDocumentEntry(viewType, resourceComponents);
|
||||
const document = this.getEditableCustomDocument(viewType, resourceComponents);
|
||||
const backup = await document.backup(cancellation);
|
||||
entry.updateBackup(backup);
|
||||
return backup.backupId;
|
||||
}
|
||||
|
||||
private getWebviewPanel(handle: extHostProtocol.WebviewPanelHandle): ExtHostWebviewEditor | undefined {
|
||||
return this._webviewPanels.get(handle);
|
||||
}
|
||||
|
||||
private getCustomDocument(viewType: string, resource: UriComponents): extHostTypes.CustomDocument {
|
||||
const document = this._documents.get(viewType, URI.revive(resource));
|
||||
if (!document) {
|
||||
throw new Error('No webview editor custom document found');
|
||||
private getCustomDocumentEntry(viewType: string, resource: UriComponents): CustomDocumentStoreEntry {
|
||||
const entry = this._documents.get(viewType, URI.revive(resource));
|
||||
if (!entry) {
|
||||
throw new Error('No custom document found');
|
||||
}
|
||||
return document;
|
||||
return entry;
|
||||
}
|
||||
|
||||
private getEditingDelegate(viewType: string): vscode.CustomEditorEditingDelegate {
|
||||
const entry = this._editorProviders.get(viewType);
|
||||
if (!entry) {
|
||||
throw new Error(`No provider found for '${viewType}'`);
|
||||
private isEditable(document: vscode.CustomDocument): document is vscode.EditableCustomDocument {
|
||||
return !!(document as vscode.EditableCustomDocument).onDidChange;
|
||||
}
|
||||
|
||||
private getEditableCustomDocument(viewType: string, resource: UriComponents): vscode.EditableCustomDocument {
|
||||
const { document } = this.getCustomDocumentEntry(viewType, resource);
|
||||
if (!this.isEditable(document)) {
|
||||
throw new Error('Custom document is not editable');
|
||||
}
|
||||
const delegate = (entry.provider as vscode.CustomEditorProvider).editingDelegate;
|
||||
if (!delegate) {
|
||||
throw new Error(`Provider for ${viewType}' does not support editing`);
|
||||
}
|
||||
return delegate;
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,3 +748,8 @@ function getDefaultLocalResourceRoots(
|
||||
extension.extensionLocation,
|
||||
];
|
||||
}
|
||||
|
||||
function isEditEvent(e: vscode.CustomDocumentContentChangeEvent | vscode.CustomDocumentEditEvent): e is vscode.CustomDocumentEditEvent {
|
||||
return typeof (e as vscode.CustomDocumentEditEvent).undo === 'function'
|
||||
&& typeof (e as vscode.CustomDocumentEditEvent).redo === 'function';
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ class ExtHostWorkspaceImpl extends Workspace {
|
||||
}
|
||||
|
||||
private readonly _workspaceFolders: vscode.WorkspaceFolder[] = [];
|
||||
private readonly _structure = TernarySearchTree.forPaths<vscode.WorkspaceFolder>();
|
||||
private readonly _structure = TernarySearchTree.forUris<vscode.WorkspaceFolder>();
|
||||
|
||||
constructor(id: string, private _name: string, folders: vscode.WorkspaceFolder[], configuration: URI | null, private _isUntitled: boolean) {
|
||||
super(id, folders.map(f => new WorkspaceFolder(f)), configuration);
|
||||
@@ -124,7 +124,7 @@ class ExtHostWorkspaceImpl extends Workspace {
|
||||
// setup the workspace folder data structure
|
||||
folders.forEach(folder => {
|
||||
this._workspaceFolders.push(folder);
|
||||
this._structure.set(folder.uri.toString(), folder);
|
||||
this._structure.set(folder.uri, folder);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -141,15 +141,15 @@ class ExtHostWorkspaceImpl extends Workspace {
|
||||
}
|
||||
|
||||
getWorkspaceFolder(uri: URI, resolveParent?: boolean): vscode.WorkspaceFolder | undefined {
|
||||
if (resolveParent && this._structure.get(uri.toString())) {
|
||||
if (resolveParent && this._structure.get(uri)) {
|
||||
// `uri` is a workspace folder so we check for its parent
|
||||
uri = dirname(uri);
|
||||
}
|
||||
return this._structure.findSubstr(uri.toString());
|
||||
return this._structure.findSubstr(uri);
|
||||
}
|
||||
|
||||
resolveWorkspaceFolder(uri: URI): vscode.WorkspaceFolder | undefined {
|
||||
return this._structure.get(uri.toString());
|
||||
return this._structure.get(uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user