Merge from vscode 2f984aad710215f4e4684a035bb02f55d1a9e2cc (#9819)

This commit is contained in:
Anthony Dresser
2020-04-01 00:44:39 -07:00
committed by GitHub
parent 0e27aaa61f
commit 0bfbdc62ed
247 changed files with 5402 additions and 3311 deletions

View File

@@ -12,7 +12,7 @@ import { ExtHostAuthenticationShape, ExtHostContext, IExtHostContext, MainContex
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import Severity from 'vs/base/common/severity';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { MenuRegistry, MenuId, IMenuItem } from 'vs/platform/actions/common/actions';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
@@ -53,6 +53,7 @@ export class MainThreadAuthenticationProvider extends Disposable {
private _sessionMenuItems = new Map<string, IDisposable[]>();
private _accounts = new Map<string, string[]>(); // Map account name to session ids
private _sessions = new Map<string, string>(); // Map account id to name
private _signInMenuItem: IMenuItem | undefined;
constructor(
private readonly _proxy: ExtHostAuthenticationShape,
@@ -94,7 +95,9 @@ export class MainThreadAuthenticationProvider extends Disposable {
quickPick.show();
}
private registerCommandsAndContextMenuItems(): void {
private async registerCommandsAndContextMenuItems(): Promise<void> {
const sessions = await this._proxy.$getSessions(this.id);
if (this.dependents.length) {
this._register(CommandsRegistry.registerCommand({
id: `signIn${this.id}`,
@@ -103,19 +106,21 @@ export class MainThreadAuthenticationProvider extends Disposable {
},
}));
this._register(MenuRegistry.appendMenuItem(MenuId.AccountsContext, {
this._signInMenuItem = {
group: '2_providers',
command: {
id: `signIn${this.id}`,
title: nls.localize('addAccount', "Sign in to {0}", this.displayName)
title: sessions.length
? nls.localize('addAnotherAccount', "Sign in to another {0} account", this.displayName)
: nls.localize('addAccount', "Sign in to {0}", this.displayName)
},
order: 3
}));
};
this._register(MenuRegistry.appendMenuItem(MenuId.AccountsContext, this._signInMenuItem));
}
this._proxy.$getSessions(this.id).then(sessions => {
sessions.forEach(session => this.registerSession(session));
});
sessions.forEach(session => this.registerSession(session));
}
private registerSession(session: modes.AuthenticationSession) {
@@ -205,11 +210,19 @@ export class MainThreadAuthenticationProvider extends Disposable {
this._sessionMenuItems.delete(accountName);
}
this._accounts.delete(accountName);
if (this._signInMenuItem) {
this._signInMenuItem.command.title = nls.localize('addAccount', "Sign in to {0}", this.displayName);
}
}
}
});
addedSessions.forEach(session => this.registerSession(session));
if (addedSessions.length && this._signInMenuItem) {
this._signInMenuItem.command.title = nls.localize('addAnotherAccount', "Sign in to another {0} account", this.displayName);
}
}
login(scopes: string[]): Promise<modes.AuthenticationSession> {

View File

@@ -21,7 +21,7 @@ import { Selection } from 'vs/editor/common/core/selection';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { mixin } from 'vs/base/common/objects';
import { decodeSemanticTokensDto } from 'vs/workbench/api/common/shared/semanticTokens';
import { decodeSemanticTokensDto } from 'vs/workbench/api/common/shared/semanticTokensDto';
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesShape {

View File

@@ -13,6 +13,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CancellationToken } from 'vs/base/common/cancellation';
export class MainThreadNotebookDocument extends Disposable {
private _textModel: NotebookTextModel;
@@ -163,8 +164,8 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
controller?.spliceNotebookCellOutputs(resource, cellHandle, splices, renderers);
}
async executeNotebook(viewType: string, uri: URI): Promise<void> {
return this._proxy.$executeNotebook(viewType, uri, undefined);
async executeNotebook(viewType: string, uri: URI, token: CancellationToken): Promise<void> {
return this._proxy.$executeNotebook(viewType, uri, undefined, token);
}
async $postMessage(handle: number, value: any): Promise<boolean> {
@@ -232,8 +233,8 @@ export class MainThreadNotebookController implements IMainNotebookController {
mainthreadNotebook?.textModel.$spliceNotebookCellOutputs(cellHandle, splices);
}
async executeNotebook(viewType: string, uri: URI): Promise<void> {
this._mainThreadNotebook.executeNotebook(viewType, uri);
async executeNotebook(viewType: string, uri: URI, token: CancellationToken): Promise<void> {
this._mainThreadNotebook.executeNotebook(viewType, uri, token);
}
onDidReceiveMessage(uri: UriComponents, message: any): void {
@@ -266,8 +267,8 @@ export class MainThreadNotebookController implements IMainNotebookController {
document?.textModel.updateRenderers(renderers);
}
async executeNotebookCell(uri: URI, handle: number): Promise<void> {
return this._proxy.$executeNotebook(this._viewType, uri, handle);
async executeNotebookCell(uri: URI, handle: number, token: CancellationToken): Promise<void> {
return this._proxy.$executeNotebook(this._viewType, uri, handle, token);
}
async destoryNotebookDocument(notebook: INotebookTextModel): Promise<void> {

View File

@@ -43,7 +43,7 @@ const configurationEntrySchema: IJSONSchema = {
default: 'window',
enumDescriptions: [
nls.localize('scope.application.description', "Configuration that can be configured only in the user settings."),
nls.localize('scope.machine.description', "Configuration that can be configured only in the user settings when the extension is running locally, or only in the remote settings when the extension is running remotely."),
nls.localize('scope.machine.description', "Configuration that can be configured only in the user settings or only in the remote settings."),
nls.localize('scope.window.description', "Configuration that can be configured in the user, remote or workspace settings."),
nls.localize('scope.resource.description', "Configuration that can be configured in the user, remote, workspace or folder settings."),
nls.localize('scope.language-overridable.description', "Resource configuration that can be configured in language specific settings."),

View File

@@ -391,11 +391,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostLanguageFeatures.registerOnTypeFormattingEditProvider(extension, checkSelector(selector), provider, [firstTriggerCharacter].concat(moreTriggerCharacters));
},
registerDocumentSemanticTokensProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSemanticTokensProvider, legend: vscode.SemanticTokensLegend): vscode.Disposable {
checkProposedApiEnabled(extension);
return extHostLanguageFeatures.registerDocumentSemanticTokensProvider(extension, checkSelector(selector), provider, legend);
},
registerDocumentRangeSemanticTokensProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeSemanticTokensProvider, legend: vscode.SemanticTokensLegend): vscode.Disposable {
checkProposedApiEnabled(extension);
return extHostLanguageFeatures.registerDocumentRangeSemanticTokensProvider(extension, checkSelector(selector), provider, legend);
},
registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, firstItem?: string | vscode.SignatureHelpProviderMetadata, ...remaining: string[]): vscode.Disposable {
@@ -588,7 +586,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostWebviews.registerWebviewPanelSerializer(extension, viewType, serializer);
},
registerCustomEditorProvider: (viewType: string, provider: vscode.CustomEditorProvider | vscode.CustomTextEditorProvider, options?: { webviewOptions?: vscode.WebviewPanelOptions }) => {
checkProposedApiEnabled(extension);
return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options?.webviewOptions);
},
registerDecorationProvider(provider: vscode.DecorationProvider) {

View File

@@ -1538,7 +1538,7 @@ export interface ExtHostCommentsShape {
export interface ExtHostNotebookShape {
$resolveNotebook(viewType: string, uri: UriComponents): Promise<number | undefined>;
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined): Promise<void>;
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
$saveNotebook(viewType: string, uri: UriComponents): Promise<boolean>;
$updateActiveEditor(viewType: string, uri: UriComponents): Promise<void>;
$destoryNotebookDocument(viewType: string, uri: UriComponents): Promise<boolean>;

View File

@@ -27,7 +27,7 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio
import { IURITransformer } from 'vs/base/common/uriIpc';
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
import { VSBuffer } from 'vs/base/common/buffer';
import { encodeSemanticTokensDto } from 'vs/workbench/api/common/shared/semanticTokens';
import { encodeSemanticTokensDto } from 'vs/workbench/api/common/shared/semanticTokensDto';
import { IdGenerator } from 'vs/base/common/idGenerator';
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
import { Cache } from './cache';

View File

@@ -13,8 +13,9 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'
import { CellKind, CellOutputKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice } 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 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
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';
interface IObservable<T> {
proxy: T;
@@ -37,12 +38,6 @@ function getObservable<T extends Object>(obj: T): IObservable<T> {
};
}
const notebookDocumentMetadataDefaults: vscode.NotebookDocumentMetadata = {
editable: true,
cellEditable: true,
cellRunnable: true
};
export class ExtHostCell extends Disposable implements vscode.NotebookCell {
private originalSource: string[];
@@ -80,7 +75,7 @@ export class ExtHostCell extends Disposable implements vscode.NotebookCell {
this.originalSource = this._content.split(/\r|\n|\r\n/g);
this._outputs = outputs;
const observableMetadata = getObservable(_metadata || {} as any);
const observableMetadata = getObservable(_metadata || {});
this._metadata = observableMetadata.proxy;
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
this.updateMetadata();
@@ -115,8 +110,9 @@ export class ExtHostCell extends Disposable implements vscode.NotebookCell {
}
set metadata(newMetadata: vscode.NotebookCellMetadata) {
// Don't apply metadata defaults here, 'undefined' means 'inherit from document metadata'
this._metadataChangeListener.dispose();
const observableMetadata = getObservable(newMetadata || {} as any); // TODO defaults
const observableMetadata = getObservable(newMetadata);
this._metadata = observableMetadata.proxy;
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
this.updateMetadata();
@@ -175,15 +171,24 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
this._proxy.$updateNotebookLanguages(this.viewType, this.uri, this._languages);
}
private _metadata: vscode.NotebookDocumentMetadata | undefined = notebookDocumentMetadataDefaults;
private _metadata: Required<vscode.NotebookDocumentMetadata> = notebookDocumentMetadataDefaults;
private _metadataChangeListener: IDisposable;
get metadata() {
return this._metadata;
}
set metadata(newMetadata: vscode.NotebookDocumentMetadata | undefined) {
this._metadata = newMetadata || notebookDocumentMetadataDefaults;
this._proxy.$updateNotebookMetadata(this.viewType, this.uri, this._metadata);
set metadata(newMetadata: Required<vscode.NotebookDocumentMetadata>) {
this._metadataChangeListener.dispose();
newMetadata = {
...notebookDocumentMetadataDefaults,
...newMetadata
};
const observableMetadata = getObservable(newMetadata);
this._metadata = observableMetadata.proxy;
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
this.updateMetadata();
}));
}
private _displayOrder: string[] = [];
@@ -210,6 +215,16 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
public renderingHandler: ExtHostNotebookOutputRenderingHandler
) {
super();
const observableMetadata = getObservable(notebookDocumentMetadataDefaults);
this._metadata = observableMetadata.proxy;
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
this.updateMetadata();
}));
}
private updateMetadata() {
this._proxy.$updateNotebookMetadata(this.viewType, this.uri, this._metadata);
}
dispose() {
@@ -686,7 +701,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
return Promise.resolve(undefined);
}
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined): Promise<void> {
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
let provider = this._notebookProviders.get(viewType);
if (!provider) {
@@ -700,7 +715,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
let cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
return provider.provider.executeCell(document!, cell);
return provider.provider.executeCell(document!, cell, token);
}
async $saveNotebook(viewType: string, uri: UriComponents): Promise<boolean> {

View File

@@ -20,12 +20,10 @@ import { assertIsDefined } from 'vs/base/common/types';
import { Schemas } from 'vs/base/common/network';
function es5ClassCompat(target: Function): any {
///@ts-ignore
///@ts-expect-error
function _() { return Reflect.construct(target, arguments, this.constructor); }
Object.defineProperty(_, 'name', Object.getOwnPropertyDescriptor(target, 'name')!);
///@ts-ignore
Object.setPrototypeOf(_, target);
///@ts-ignore
Object.setPrototypeOf(_.prototype, target.prototype);
return _;
}
@@ -2428,24 +2426,126 @@ export class SemanticTokensLegend {
}
}
function isStrArrayOrUndefined(arg: any): arg is string[] | undefined {
if (typeof arg === 'undefined') {
return true;
}
if (Array.isArray(arg)) {
for (const element of arg) {
if (typeof element !== 'string') {
return false;
}
}
return true;
}
return false;
}
export class SemanticTokensBuilder {
private _prevLine: number;
private _prevChar: number;
private _dataIsSortedAndDeltaEncoded: boolean;
private _data: number[];
private _dataLen: number;
private _tokenTypeStrToInt: Map<string, number>;
private _tokenModifierStrToInt: Map<string, number>;
private _hasLegend: boolean;
constructor() {
constructor(legend?: vscode.SemanticTokensLegend) {
this._prevLine = 0;
this._prevChar = 0;
this._dataIsSortedAndDeltaEncoded = true;
this._data = [];
this._dataLen = 0;
this._tokenTypeStrToInt = new Map<string, number>();
this._tokenModifierStrToInt = new Map<string, number>();
this._hasLegend = false;
if (legend) {
this._hasLegend = true;
for (let i = 0, len = legend.tokenTypes.length; i < len; i++) {
this._tokenTypeStrToInt.set(legend.tokenTypes[i], i);
}
for (let i = 0, len = legend.tokenModifiers.length; i < len; i++) {
this._tokenModifierStrToInt.set(legend.tokenModifiers[i], i);
}
}
}
public push(line: number, char: number, length: number, tokenType: number, tokenModifiers: number): void {
public push(line: number, char: number, length: number, tokenType: number, tokenModifiers: number): void;
public push(range: Range, tokenType: string, tokenModifiers?: string[]): void;
public push(arg0: any, arg1: any, arg2: any, arg3?: any, arg4?: any): void {
if (typeof arg0 === 'number' && typeof arg1 === 'number' && typeof arg2 === 'number' && typeof arg3 === 'number' && typeof arg4 === 'number') {
// 1st overload
return this._pushEncoded(arg0, arg1, arg2, arg3, arg4);
}
if (Range.isRange(arg0) && typeof arg1 === 'string' && isStrArrayOrUndefined(arg2)) {
// 2nd overload
return this._push(arg0, arg1, arg2);
}
throw illegalArgument();
}
private _push(range: vscode.Range, tokenType: string, tokenModifiers?: string[]): void {
if (!this._hasLegend) {
throw new Error('Legend must be provided in constructor');
}
if (range.start.line !== range.end.line) {
throw new Error('`range` cannot span multiple lines');
}
if (!this._tokenTypeStrToInt.has(tokenType)) {
throw new Error('`tokenType` is not in the provided legend');
}
const line = range.start.line;
const char = range.start.character;
const length = range.end.character - range.start.character;
const nTokenType = this._tokenTypeStrToInt.get(tokenType)!;
let nTokenModifiers = 0;
if (tokenModifiers) {
for (const tokenModifier of tokenModifiers) {
if (!this._tokenModifierStrToInt.has(tokenModifier)) {
throw new Error('`tokenModifier` is not in the provided legend');
}
const nTokenModifier = this._tokenModifierStrToInt.get(tokenModifier)!;
nTokenModifiers |= (1 << nTokenModifier) >>> 0;
}
}
this._pushEncoded(line, char, length, nTokenType, nTokenModifiers);
}
private _pushEncoded(line: number, char: number, length: number, tokenType: number, tokenModifiers: number): void {
if (this._dataIsSortedAndDeltaEncoded && (line < this._prevLine || (line === this._prevLine && char < this._prevChar))) {
// push calls were ordered and are no longer ordered
this._dataIsSortedAndDeltaEncoded = false;
// Remove delta encoding from data
const tokenCount = (this._data.length / 5) | 0;
let prevLine = 0;
let prevChar = 0;
for (let i = 0; i < tokenCount; i++) {
let line = this._data[5 * i];
let char = this._data[5 * i + 1];
if (line === 0) {
// on the same line as previous token
line = prevLine;
char += prevChar;
} else {
// on a different line than previous token
line += prevLine;
}
this._data[5 * i] = line;
this._data[5 * i + 1] = char;
prevLine = line;
prevChar = char;
}
}
let pushLine = line;
let pushChar = char;
if (this._dataLen > 0) {
if (this._dataIsSortedAndDeltaEncoded && this._dataLen > 0) {
pushLine -= this._prevLine;
if (pushLine === 0) {
pushChar -= this._prevChar;
@@ -2462,8 +2562,55 @@ export class SemanticTokensBuilder {
this._prevChar = char;
}
public build(): Uint32Array {
return new Uint32Array(this._data);
private static _sortAndDeltaEncode(data: number[]): Uint32Array {
let pos: number[] = [];
const tokenCount = (data.length / 5) | 0;
for (let i = 0; i < tokenCount; i++) {
pos[i] = i;
}
pos.sort((a, b) => {
const aLine = data[5 * a];
const bLine = data[5 * b];
if (aLine === bLine) {
const aChar = data[5 * a + 1];
const bChar = data[5 * b + 1];
return aChar - bChar;
}
return aLine - bLine;
});
const result = new Uint32Array(data.length);
let prevLine = 0;
let prevChar = 0;
for (let i = 0; i < tokenCount; i++) {
const srcOffset = 5 * pos[i];
const line = data[srcOffset + 0];
const char = data[srcOffset + 1];
const length = data[srcOffset + 2];
const tokenType = data[srcOffset + 3];
const tokenModifiers = data[srcOffset + 4];
const pushLine = line - prevLine;
const pushChar = (pushLine === 0 ? char - prevChar : char);
const dstOffset = 5 * i;
result[dstOffset + 0] = pushLine;
result[dstOffset + 1] = pushChar;
result[dstOffset + 2] = length;
result[dstOffset + 3] = tokenType;
result[dstOffset + 4] = tokenModifiers;
prevLine = line;
prevChar = char;
}
return result;
}
public build(resultId?: string): SemanticTokens {
if (!this._dataIsSortedAndDeltaEncoded) {
return new SemanticTokens(SemanticTokensBuilder._sortAndDeltaEncode(this._data), resultId);
}
return new SemanticTokens(new Uint32Array(this._data), resultId);
}
}
@@ -2600,7 +2747,6 @@ export class CustomDocument<EditType = unknown> implements vscode.CustomDocument
readonly #edits = new Cache<EditType>('edits');
readonly #viewType: string;
readonly #uri: vscode.Uri;
#editState: EditState = {
@@ -2611,15 +2757,12 @@ export class CustomDocument<EditType = unknown> implements vscode.CustomDocument
#isDisposed = false;
#version = 1;
constructor(viewType: string, uri: vscode.Uri) {
this.#viewType = viewType;
constructor(uri: vscode.Uri) {
this.#uri = uri;
}
//#region Public API
public get viewType(): string { return this.#viewType; }
public get uri(): vscode.Uri { return this.#uri; }
public get fileName(): string { return this.uri.fsPath; }
@@ -2672,11 +2815,11 @@ export class CustomDocument<EditType = unknown> implements vscode.CustomDocument
/** @internal*/ _addEdit(edit: EditType): number {
const id = this.#edits.add([edit]);
this.#editState = {
allEdits: [...this.#editState.allEdits.slice(0, this.#editState.currentIndex), id],
this._updateEditState({
allEdits: [...this.#editState.allEdits.slice(0, this.#editState.currentIndex + 1), id],
currentIndex: this.#editState.currentIndex + 1,
saveIndex: this.#editState.saveIndex,
};
});
return id;
}
}

View File

@@ -269,16 +269,16 @@ class WebviewDocumentStore {
return this._documents.get(this.key(viewType, resource));
}
public add(document: extHostTypes.CustomDocument) {
const key = this.key(document.viewType, document.uri);
public add(viewType: string, document: extHostTypes.CustomDocument) {
const key = this.key(viewType, document.uri);
if (this._documents.has(key)) {
throw new Error(`Document already exists for viewType:${document.viewType} resource:${document.uri}`);
throw new Error(`Document already exists for viewType:${viewType} resource:${document.uri}`);
}
this._documents.set(key, document);
}
public delete(document: extHostTypes.CustomDocument) {
const key = this.key(document.viewType, document.uri);
public delete(viewType: string, document: extHostTypes.CustomDocument) {
const key = this.key(viewType, document.uri);
this._documents.delete(key);
}
@@ -414,7 +414,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
disposables.add(provider.editingDelegate.onDidEdit(e => {
const document = e.document;
const editId = (document as extHostTypes.CustomDocument)._addEdit(e.edit);
this._proxy.$onDidEdit(document.uri, document.viewType, editId, e.label);
this._proxy.$onDidEdit(document.uri, viewType, editId, e.label);
}));
}
}
@@ -516,7 +516,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
const revivedResource = URI.revive(resource);
const document = await entry.provider.openCustomDocument(revivedResource, cancellation);
this._documents.add(document as extHostTypes.CustomDocument);
this._documents.add(viewType, document as extHostTypes.CustomDocument);
return {
editable: !!entry.provider.editingDelegate,
};
@@ -534,7 +534,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
const revivedResource = URI.revive(resource);
const document = this.getCustomDocument(viewType, revivedResource);
this._documents.delete(document);
this._documents.delete(viewType, document);
document._dispose();
}

View File

@@ -1,113 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { VSBuffer } from 'vs/base/common/buffer';
export interface IFullSemanticTokensDto {
id: number;
type: 'full';
data: Uint32Array;
}
export interface IDeltaSemanticTokensDto {
id: number;
type: 'delta';
deltas: { start: number; deleteCount: number; data?: Uint32Array; }[];
}
export type ISemanticTokensDto = IFullSemanticTokensDto | IDeltaSemanticTokensDto;
const enum EncodedSemanticTokensType {
Full = 1,
Delta = 2
}
export function encodeSemanticTokensDto(semanticTokens: ISemanticTokensDto): VSBuffer {
const buff = VSBuffer.alloc(encodedSize2(semanticTokens));
let offset = 0;
buff.writeUInt32BE(semanticTokens.id, offset); offset += 4;
if (semanticTokens.type === 'full') {
buff.writeUInt8(EncodedSemanticTokensType.Full, offset); offset += 1;
buff.writeUInt32BE(semanticTokens.data.length, offset); offset += 4;
for (const uint of semanticTokens.data) {
buff.writeUInt32BE(uint, offset); offset += 4;
}
} else {
buff.writeUInt8(EncodedSemanticTokensType.Delta, offset); offset += 1;
buff.writeUInt32BE(semanticTokens.deltas.length, offset); offset += 4;
for (const delta of semanticTokens.deltas) {
buff.writeUInt32BE(delta.start, offset); offset += 4;
buff.writeUInt32BE(delta.deleteCount, offset); offset += 4;
if (delta.data) {
buff.writeUInt32BE(delta.data.length, offset); offset += 4;
for (const uint of delta.data) {
buff.writeUInt32BE(uint, offset); offset += 4;
}
} else {
buff.writeUInt32BE(0, offset); offset += 4;
}
}
}
return buff;
}
function encodedSize2(semanticTokens: ISemanticTokensDto): number {
let result = 0;
result += 4; // id
result += 1; // type
if (semanticTokens.type === 'full') {
result += 4; // data length
result += semanticTokens.data.byteLength;
} else {
result += 4; // delta count
for (const delta of semanticTokens.deltas) {
result += 4; // start
result += 4; // deleteCount
result += 4; // data length
if (delta.data) {
result += delta.data.byteLength;
}
}
}
return result;
}
export function decodeSemanticTokensDto(buff: VSBuffer): ISemanticTokensDto {
let offset = 0;
const id = buff.readUInt32BE(offset); offset += 4;
const type: EncodedSemanticTokensType = buff.readUInt8(offset); offset += 1;
if (type === EncodedSemanticTokensType.Full) {
const length = buff.readUInt32BE(offset); offset += 4;
const data = new Uint32Array(length);
for (let j = 0; j < length; j++) {
data[j] = buff.readUInt32BE(offset); offset += 4;
}
return {
id: id,
type: 'full',
data: data
};
}
const deltaCount = buff.readUInt32BE(offset); offset += 4;
let deltas: { start: number; deleteCount: number; data?: Uint32Array; }[] = [];
for (let i = 0; i < deltaCount; i++) {
const start = buff.readUInt32BE(offset); offset += 4;
const deleteCount = buff.readUInt32BE(offset); offset += 4;
const length = buff.readUInt32BE(offset); offset += 4;
let data: Uint32Array | undefined;
if (length > 0) {
data = new Uint32Array(length);
for (let j = 0; j < length; j++) {
data[j] = buff.readUInt32BE(offset); offset += 4;
}
}
deltas[i] = { start, deleteCount, data };
}
return {
id: id,
type: 'delta',
deltas: deltas
};
}

View File

@@ -0,0 +1,152 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { VSBuffer } from 'vs/base/common/buffer';
import * as platform from 'vs/base/common/platform';
export interface IFullSemanticTokensDto {
id: number;
type: 'full';
data: Uint32Array;
}
export interface IDeltaSemanticTokensDto {
id: number;
type: 'delta';
deltas: { start: number; deleteCount: number; data?: Uint32Array; }[];
}
export type ISemanticTokensDto = IFullSemanticTokensDto | IDeltaSemanticTokensDto;
const enum EncodedSemanticTokensType {
Full = 1,
Delta = 2
}
function reverseEndianness(arr: Uint8Array): void {
for (let i = 0, len = arr.length; i < len; i += 4) {
// flip bytes 0<->3 and 1<->2
const b0 = arr[i + 0];
const b1 = arr[i + 1];
const b2 = arr[i + 2];
const b3 = arr[i + 3];
arr[i + 0] = b3;
arr[i + 1] = b2;
arr[i + 2] = b1;
arr[i + 3] = b0;
}
}
function toLittleEndianBuffer(arr: Uint32Array): VSBuffer {
const uint8Arr = new Uint8Array(arr.buffer, arr.byteOffset, arr.length * 4);
if (!platform.isLittleEndian()) {
// the byte order must be changed
reverseEndianness(uint8Arr);
}
return VSBuffer.wrap(uint8Arr);
}
function fromLittleEndianBuffer(buff: VSBuffer): Uint32Array {
const uint8Arr = buff.buffer;
if (!platform.isLittleEndian()) {
// the byte order must be changed
reverseEndianness(uint8Arr);
}
if (uint8Arr.byteOffset % 4 === 0) {
return new Uint32Array(uint8Arr.buffer, uint8Arr.byteOffset);
} else {
// unaligned memory access doesn't work on all platforms
const data = new Uint8Array(uint8Arr.byteLength);
data.set(uint8Arr);
return new Uint32Array(data.buffer, data.byteOffset);
}
}
export function encodeSemanticTokensDto(semanticTokens: ISemanticTokensDto): VSBuffer {
const dest = new Uint32Array(encodeSemanticTokensDtoSize(semanticTokens));
let offset = 0;
dest[offset++] = semanticTokens.id;
if (semanticTokens.type === 'full') {
dest[offset++] = EncodedSemanticTokensType.Full;
dest[offset++] = semanticTokens.data.length;
dest.set(semanticTokens.data, offset); offset += semanticTokens.data.length;
} else {
dest[offset++] = EncodedSemanticTokensType.Delta;
dest[offset++] = semanticTokens.deltas.length;
for (const delta of semanticTokens.deltas) {
dest[offset++] = delta.start;
dest[offset++] = delta.deleteCount;
if (delta.data) {
dest[offset++] = delta.data.length;
dest.set(delta.data, offset); offset += delta.data.length;
} else {
dest[offset++] = 0;
}
}
}
return toLittleEndianBuffer(dest);
}
function encodeSemanticTokensDtoSize(semanticTokens: ISemanticTokensDto): number {
let result = 0;
result += (
+ 1 // id
+ 1 // type
);
if (semanticTokens.type === 'full') {
result += (
+ 1 // data length
+ semanticTokens.data.length
);
} else {
result += (
+ 1 // delta count
);
result += (
+ 1 // start
+ 1 // deleteCount
+ 1 // data length
) * semanticTokens.deltas.length;
for (const delta of semanticTokens.deltas) {
if (delta.data) {
result += delta.data.length;
}
}
}
return result;
}
export function decodeSemanticTokensDto(_buff: VSBuffer): ISemanticTokensDto {
const src = fromLittleEndianBuffer(_buff);
let offset = 0;
const id = src[offset++];
const type: EncodedSemanticTokensType = src[offset++];
if (type === EncodedSemanticTokensType.Full) {
const length = src[offset++];
const data = src.subarray(offset, offset + length); offset += length;
return {
id: id,
type: 'full',
data: data
};
}
const deltaCount = src[offset++];
let deltas: { start: number; deleteCount: number; data?: Uint32Array; }[] = [];
for (let i = 0; i < deltaCount; i++) {
const start = src[offset++];
const deleteCount = src[offset++];
const length = src[offset++];
let data: Uint32Array | undefined;
if (length > 0) {
data = src.subarray(offset, offset + length); offset += length;
}
deltas[i] = { start, deleteCount, data };
}
return {
id: id,
type: 'delta',
deltas: deltas
};
}