mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-27 03:54:24 +01:00
Merge branch 'master' into rebornix/separate-textmodel-selection
This commit is contained in:
@@ -18,7 +18,7 @@ import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { fromNow } from 'vs/base/common/date';
|
||||
|
||||
const VSO_ALLOWED_EXTENSIONS = ['github.vscode-pull-request-github', 'github.vscode-pull-request-github-insiders', 'vscode.git', 'ms-vsonline.vsonline'];
|
||||
const VSO_ALLOWED_EXTENSIONS = ['github.vscode-pull-request-github', 'github.vscode-pull-request-github-insiders', 'vscode.git', 'ms-vsonline.vsonline', 'vscode.github-browser'];
|
||||
|
||||
interface IAccountUsage {
|
||||
extensionId: string;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { keys } from 'vs/base/common/map';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
@@ -284,7 +283,7 @@ export class MainThreadCommentController {
|
||||
|
||||
async getDocumentComments(resource: URI, token: CancellationToken) {
|
||||
let ret: modes.CommentThread[] = [];
|
||||
for (let thread of keys(this._threads)) {
|
||||
for (let thread of [...this._threads.keys()]) {
|
||||
const commentThread = this._threads.get(thread)!;
|
||||
if (commentThread.resource === resource.toString()) {
|
||||
ret.push(commentThread);
|
||||
@@ -315,7 +314,7 @@ export class MainThreadCommentController {
|
||||
|
||||
getAllComments(): MainThreadCommentThread[] {
|
||||
let ret: MainThreadCommentThread[] = [];
|
||||
for (let thread of keys(this._threads)) {
|
||||
for (let thread of [...this._threads.keys()]) {
|
||||
ret.push(this._threads.get(thread)!);
|
||||
}
|
||||
|
||||
@@ -486,7 +485,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments
|
||||
if (!commentsPanelAlreadyConstructed && !this._openViewListener) {
|
||||
this._openViewListener = this._viewsService.onDidChangeViewVisibility(e => {
|
||||
if (e.id === COMMENTS_VIEW_ID && e.visible) {
|
||||
keys(this._commentControllers).forEach(handle => {
|
||||
[...this._commentControllers.keys()].forEach(handle => {
|
||||
let threads = this._commentControllers.get(handle)!.getAllComments();
|
||||
|
||||
if (threads.length) {
|
||||
|
||||
@@ -231,7 +231,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
const debugOptions: IDebugSessionOptions = {
|
||||
noDebug: options.noDebug,
|
||||
parentSession: this.getSession(options.parentSessionID),
|
||||
repl: options.repl
|
||||
repl: options.repl,
|
||||
noCompact: options.noCompact
|
||||
};
|
||||
return this.debugService.startDebugging(launch, nameOrConfig, debugOptions).then(success => {
|
||||
return success;
|
||||
|
||||
@@ -50,8 +50,8 @@ class DecorationRequestsQueue {
|
||||
const requests = this._requests;
|
||||
const resolver = this._resolver;
|
||||
this._proxy.$provideDecorations(this._handle, [...requests.values()], CancellationToken.None).then(data => {
|
||||
for (const id in resolver) {
|
||||
resolver.get(Number(id))!(data[Number(id)]);
|
||||
for (let [id, resolve] of resolver) {
|
||||
resolve(data[id]);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -126,8 +126,12 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
|
||||
}));
|
||||
|
||||
this._toDispose.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => {
|
||||
if (e.source && (e.operation === FileOperation.MOVE || e.operation === FileOperation.DELETE)) {
|
||||
this._modelReferenceCollection.remove(e.source);
|
||||
if (e.operation === FileOperation.MOVE || e.operation === FileOperation.DELETE) {
|
||||
for (const { source } of e.files) {
|
||||
if (source) {
|
||||
this._modelReferenceCollection.remove(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -57,14 +57,14 @@ export class MainThreadFileSystemEventService {
|
||||
|
||||
// BEFORE file operation
|
||||
workingCopyFileService.addFileOperationParticipant({
|
||||
participate: (target, source, operation, progress, timeout, token) => {
|
||||
return proxy.$onWillRunFileOperation(operation, target, source, timeout, token);
|
||||
participate: (files, operation, progress, timeout, token) => {
|
||||
return proxy.$onWillRunFileOperation(operation, files, timeout, token);
|
||||
}
|
||||
});
|
||||
|
||||
// AFTER file operation
|
||||
this._listener.add(textFileService.onDidCreateTextFile(e => proxy.$onDidRunFileOperation(FileOperation.CREATE, e.resource, undefined)));
|
||||
this._listener.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => proxy.$onDidRunFileOperation(e.operation, e.target, e.source)));
|
||||
this._listener.add(textFileService.onDidCreateTextFile(e => proxy.$onDidRunFileOperation(FileOperation.CREATE, [{ target: e.resource }])));
|
||||
this._listener.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => proxy.$onDidRunFileOperation(e.operation, e.files)));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
||||
@@ -15,6 +15,7 @@ import { IAccessibilityInformation } from 'vs/platform/accessibility/common/acce
|
||||
export class MainThreadStatusBar implements MainThreadStatusBarShape {
|
||||
|
||||
private readonly entries: Map<number, { accessor: IStatusbarEntryAccessor, alignment: MainThreadStatusBarAlignment, priority: number }> = new Map();
|
||||
static readonly CODICON_REGEXP = /\$\((.*?)\)/g;
|
||||
|
||||
constructor(
|
||||
_extHostContext: IExtHostContext,
|
||||
@@ -32,7 +33,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape {
|
||||
if (accessibilityInformation) {
|
||||
ariaLabel = accessibilityInformation.label;
|
||||
} else {
|
||||
ariaLabel = text && text.indexOf('$(') === -1 ? text : tooltip || text;
|
||||
ariaLabel = text ? text.replace(MainThreadStatusBar.CODICON_REGEXP, (_match, codiconName) => codiconName) : '';
|
||||
}
|
||||
const entry: IStatusbarEntry = { text, tooltip, command, color, ariaLabel };
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostContext, MainThreadTreeViewsShape, ExtHostTreeViewsShape, MainContext, IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ITreeViewDataProvider, ITreeItem, IViewsService, ITreeView, IViewsRegistry, ITreeViewDescriptor, IRevealOptions, Extensions } from 'vs/workbench/common/views';
|
||||
import { ITreeViewDataProvider, ITreeItem, IViewsService, ITreeView, IViewsRegistry, ITreeViewDescriptor, IRevealOptions, Extensions, ResolvableTreeItem } from 'vs/workbench/common/views';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
@@ -163,11 +163,13 @@ type TreeItemHandle = string;
|
||||
class TreeViewDataProvider implements ITreeViewDataProvider {
|
||||
|
||||
private readonly itemsMap: Map<TreeItemHandle, ITreeItem> = new Map<TreeItemHandle, ITreeItem>();
|
||||
private hasResolve: Promise<boolean>;
|
||||
|
||||
constructor(private readonly treeViewId: string,
|
||||
private readonly _proxy: ExtHostTreeViewsShape,
|
||||
private readonly notificationService: INotificationService
|
||||
) {
|
||||
this.hasResolve = this._proxy.$hasResolve(this.treeViewId);
|
||||
}
|
||||
|
||||
getChildren(treeItem?: ITreeItem): Promise<ITreeItem[]> {
|
||||
@@ -214,12 +216,16 @@ class TreeViewDataProvider implements ITreeViewDataProvider {
|
||||
return this.itemsMap.size === 0;
|
||||
}
|
||||
|
||||
private postGetChildren(elements: ITreeItem[]): ITreeItem[] {
|
||||
const result: ITreeItem[] = [];
|
||||
private async postGetChildren(elements: ITreeItem[]): Promise<ResolvableTreeItem[]> {
|
||||
const result: ResolvableTreeItem[] = [];
|
||||
const hasResolve = await this.hasResolve;
|
||||
if (elements) {
|
||||
for (const element of elements) {
|
||||
const resolvable = new ResolvableTreeItem(element, hasResolve ? () => {
|
||||
return this._proxy.$resolve(this.treeViewId, element.handle);
|
||||
} : undefined);
|
||||
this.itemsMap.set(element.handle, element);
|
||||
result.push(element);
|
||||
result.push(resolvable);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -206,12 +206,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
getSession(providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions) {
|
||||
return extHostAuthentication.getSession(extension, providerId, scopes, options as any);
|
||||
},
|
||||
getSessions(providerId: string, scopes: string[]): Thenable<readonly vscode.AuthenticationSession[]> {
|
||||
return extHostAuthentication.getSessions(extension, providerId, scopes);
|
||||
},
|
||||
login(providerId: string, scopes: string[]): Thenable<vscode.AuthenticationSession> {
|
||||
return extHostAuthentication.login(extension, providerId, scopes);
|
||||
},
|
||||
logout(providerId: string, sessionId: string): Thenable<void> {
|
||||
return extHostAuthentication.logout(providerId, sessionId);
|
||||
},
|
||||
@@ -1102,7 +1096,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
CellKind: extHostTypes.CellKind,
|
||||
CellOutputKind: extHostTypes.CellOutputKind,
|
||||
NotebookCellRunState: extHostTypes.NotebookCellRunState,
|
||||
AuthenticationSession2: extHostTypes.AuthenticationSession
|
||||
AuthenticationSession: extHostTypes.AuthenticationSession
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -858,6 +858,7 @@ export interface IStartDebuggingOptions {
|
||||
parentSessionID?: DebugSessionUUID;
|
||||
repl?: IDebugSessionReplMode;
|
||||
noDebug?: boolean;
|
||||
noCompact?: boolean;
|
||||
}
|
||||
|
||||
export interface MainThreadDebugServiceShape extends IDisposable {
|
||||
@@ -987,6 +988,8 @@ export interface ExtHostTreeViewsShape {
|
||||
$setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void;
|
||||
$setSelection(treeViewId: string, treeItemHandles: string[]): void;
|
||||
$setVisible(treeViewId: string, visible: boolean): void;
|
||||
$hasResolve(treeViewId: string): Promise<boolean>;
|
||||
$resolve(treeViewId: string, treeItemHandle: string): Promise<ITreeItem | undefined>;
|
||||
}
|
||||
|
||||
export interface ExtHostWorkspaceShape {
|
||||
@@ -1068,10 +1071,15 @@ export interface FileSystemEvents {
|
||||
deleted: UriComponents[];
|
||||
}
|
||||
|
||||
export interface SourceTargetPair {
|
||||
source?: UriComponents;
|
||||
target: UriComponents;
|
||||
}
|
||||
|
||||
export interface ExtHostFileSystemEventServiceShape {
|
||||
$onFileEvent(events: FileSystemEvents): void;
|
||||
$onWillRunFileOperation(operation: files.FileOperation, target: UriComponents, source: UriComponents | undefined, timeout: number, token: CancellationToken): Promise<any>;
|
||||
$onDidRunFileOperation(operation: files.FileOperation, target: UriComponents, source: UriComponents | undefined): void;
|
||||
$onWillRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise<any>;
|
||||
$onDidRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[]): void;
|
||||
}
|
||||
|
||||
export interface ObjectIdentifier {
|
||||
|
||||
@@ -56,8 +56,8 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
return !!(sessions.filter(session => session.scopes.sort().join(' ') === orderedScopes).length);
|
||||
}
|
||||
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise<vscode.AuthenticationSession2>;
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions): Promise<vscode.AuthenticationSession2 | undefined> {
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise<vscode.AuthenticationSession>;
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions): Promise<vscode.AuthenticationSession | undefined> {
|
||||
const provider = this._authenticationProviders.get(providerId);
|
||||
const extensionName = requestingExtension.displayName || requestingExtension.name;
|
||||
const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier);
|
||||
@@ -100,71 +100,6 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
}
|
||||
}
|
||||
|
||||
async getSessions(requestingExtension: IExtensionDescription, providerId: string, scopes: string[]): Promise<readonly vscode.AuthenticationSession[]> {
|
||||
const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier);
|
||||
const orderedScopes = scopes.sort().join(' ');
|
||||
const sessions = await this.resolveSessions(providerId);
|
||||
return sessions
|
||||
.filter(session => session.scopes.sort().join(' ') === orderedScopes)
|
||||
.map(session => {
|
||||
return {
|
||||
id: session.id,
|
||||
account: session.account,
|
||||
scopes: session.scopes,
|
||||
getAccessToken: async () => {
|
||||
const isAllowed = await this._proxy.$getSessionsPrompt(
|
||||
providerId,
|
||||
session.account.displayName,
|
||||
'', // TODO
|
||||
// provider.displayName,
|
||||
extensionId,
|
||||
requestingExtension.displayName || requestingExtension.name);
|
||||
|
||||
if (!isAllowed) {
|
||||
throw new Error('User did not consent to token access.');
|
||||
}
|
||||
|
||||
return session.accessToken;
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async login(requestingExtension: IExtensionDescription, providerId: string, scopes: string[]): Promise<vscode.AuthenticationSession> {
|
||||
const provider = this._authenticationProviders.get(providerId);
|
||||
if (!provider) {
|
||||
throw new Error(`No authentication provider with id '${providerId}' is currently registered.`);
|
||||
}
|
||||
|
||||
const extensionName = requestingExtension.displayName || requestingExtension.name;
|
||||
const isAllowed = await this._proxy.$loginPrompt(provider.displayName, extensionName);
|
||||
if (!isAllowed) {
|
||||
throw new Error('User did not consent to login.');
|
||||
}
|
||||
|
||||
const session = await provider.login(scopes);
|
||||
await this._proxy.$setTrustedExtension(provider.id, session.account.displayName, ExtensionIdentifier.toKey(requestingExtension.identifier), extensionName);
|
||||
return {
|
||||
id: session.id,
|
||||
account: session.account,
|
||||
scopes: session.scopes,
|
||||
getAccessToken: async () => {
|
||||
const isAllowed = await this._proxy.$getSessionsPrompt(
|
||||
provider.id,
|
||||
session.account.displayName,
|
||||
provider.displayName,
|
||||
ExtensionIdentifier.toKey(requestingExtension.identifier),
|
||||
requestingExtension.displayName || requestingExtension.name);
|
||||
|
||||
if (!isAllowed) {
|
||||
throw new Error('User did not consent to token access.');
|
||||
}
|
||||
|
||||
return session.accessToken;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async logout(providerId: string, sessionId: string): Promise<void> {
|
||||
const provider = this._authenticationProviders.get(providerId);
|
||||
if (!provider) {
|
||||
|
||||
@@ -296,7 +296,8 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E
|
||||
return this._debugServiceProxy.$startDebugging(folder ? folder.uri : undefined, nameOrConfig, {
|
||||
parentSessionID: options.parentSession ? options.parentSession.id : undefined,
|
||||
repl: options.consoleMode === DebugConsoleMode.MergeWithParent ? 'mergeWithParent' : 'separate',
|
||||
noDebug: options.noDebug
|
||||
noDebug: options.noDebug,
|
||||
noCompact: options.noCompact
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
import { AsyncEmitter, Emitter, Event, IWaitUntil } from 'vs/base/common/event';
|
||||
import { IRelativePattern, parse } from 'vs/base/common/glob';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import type * as vscode from 'vscode';
|
||||
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, MainThreadTextEditorsShape, IWorkspaceFileEditDto, IWorkspaceTextEditDto } from './extHost.protocol';
|
||||
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, MainThreadTextEditorsShape, IWorkspaceFileEditDto, IWorkspaceTextEditDto, SourceTargetPair } from './extHost.protocol';
|
||||
import * as typeConverter from './extHostTypeConverters';
|
||||
import { Disposable, WorkspaceEdit } from './extHostTypes';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -142,16 +142,16 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
|
||||
//--- file operations
|
||||
|
||||
$onDidRunFileOperation(operation: FileOperation, target: UriComponents, source: UriComponents | undefined): void {
|
||||
$onDidRunFileOperation(operation: FileOperation, files: SourceTargetPair[]): void {
|
||||
switch (operation) {
|
||||
case FileOperation.MOVE:
|
||||
this._onDidRenameFile.fire(Object.freeze({ files: [{ oldUri: URI.revive(source!), newUri: URI.revive(target) }] }));
|
||||
this._onDidRenameFile.fire(Object.freeze({ files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }));
|
||||
break;
|
||||
case FileOperation.DELETE:
|
||||
this._onDidDeleteFile.fire(Object.freeze({ files: [URI.revive(target)] }));
|
||||
this._onDidDeleteFile.fire(Object.freeze({ files: files.map(f => URI.revive(f.target)) }));
|
||||
break;
|
||||
case FileOperation.CREATE:
|
||||
this._onDidCreateFile.fire(Object.freeze({ files: [URI.revive(target)] }));
|
||||
this._onDidCreateFile.fire(Object.freeze({ files: files.map(f => URI.revive(f.target)) }));
|
||||
break;
|
||||
default:
|
||||
//ignore, dont send
|
||||
@@ -179,16 +179,16 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
};
|
||||
}
|
||||
|
||||
async $onWillRunFileOperation(operation: FileOperation, target: UriComponents, source: UriComponents | undefined, timeout: number, token: CancellationToken): Promise<any> {
|
||||
async $onWillRunFileOperation(operation: FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise<any> {
|
||||
switch (operation) {
|
||||
case FileOperation.MOVE:
|
||||
await this._fireWillEvent(this._onWillRenameFile, { files: [{ oldUri: URI.revive(source!), newUri: URI.revive(target) }] }, timeout, token);
|
||||
await this._fireWillEvent(this._onWillRenameFile, { files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }, timeout, token);
|
||||
break;
|
||||
case FileOperation.DELETE:
|
||||
await this._fireWillEvent(this._onWillDeleteFile, { files: [URI.revive(target)] }, timeout, token);
|
||||
await this._fireWillEvent(this._onWillDeleteFile, { files: files.map(f => URI.revive(f.target)) }, timeout, token);
|
||||
break;
|
||||
case FileOperation.CREATE:
|
||||
await this._fireWillEvent(this._onWillCreateFile, { files: [URI.revive(target)] }, timeout, token);
|
||||
await this._fireWillEvent(this._onWillCreateFile, { files: files.map(f => URI.revive(f.target)) }, timeout, token);
|
||||
break;
|
||||
default:
|
||||
//ignore, dont send
|
||||
|
||||
@@ -12,17 +12,15 @@ 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 { basename } from 'vs/base/common/resources';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { ExtHostDocumentLine } from 'vs/workbench/api/common/extHostDocumentData';
|
||||
|
||||
export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextDocument, vscode.TextDocument {
|
||||
export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextDocument {
|
||||
|
||||
private _disposables = new DisposableStore();
|
||||
private _isClosed = false;
|
||||
|
||||
private _cells!: ExtHostCell[];
|
||||
private _cellByUri!: ResourceMap<number>;
|
||||
private _cellUris!: ResourceMap<number>;
|
||||
private _cellLengths!: PrefixSumComputer;
|
||||
private _cellLines!: PrefixSumComputer;
|
||||
private _versionId = 0;
|
||||
@@ -30,27 +28,17 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
private readonly _onDidChange = new Emitter<void>();
|
||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
readonly uri: vscode.Uri;
|
||||
readonly fileName: string;
|
||||
readonly languageId: string;
|
||||
readonly isUntitled: boolean = false;
|
||||
readonly isDirty: boolean = false;
|
||||
|
||||
constructor(
|
||||
extHostNotebooks: ExtHostNotebookController,
|
||||
extHostDocuments: ExtHostDocuments,
|
||||
private readonly _notebook: vscode.NotebookDocument,
|
||||
private readonly _selector: vscode.DocumentSelector | undefined,
|
||||
) {
|
||||
this.uri = _notebook.uri.with({ scheme: 'vscode-notebook-concat-doc' });
|
||||
this.fileName = basename(this.uri);
|
||||
this.languageId = this._createLanguageId();
|
||||
|
||||
this._init();
|
||||
|
||||
this._disposables.add(extHostDocuments.onDidChangeDocument(e => {
|
||||
const cellIdx = this._cellByUri.get(e.document.uri);
|
||||
if (typeof cellIdx === 'number') {
|
||||
let cellIdx = this._cellUris.get(e.document.uri);
|
||||
if (cellIdx !== undefined) {
|
||||
this._cellLengths.changeValue(cellIdx, this._cells[cellIdx].document.getText().length + 1);
|
||||
this._cellLines.changeValue(cellIdx, this._cells[cellIdx].document.lineCount);
|
||||
this._versionId += 1;
|
||||
@@ -66,7 +54,6 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
};
|
||||
|
||||
this._disposables.add(extHostNotebooks.onDidChangeCellLanguage(e => documentChange(e.document)));
|
||||
this._disposables.add(extHostNotebooks.onDidChangeCellOutputs(e => documentChange(e.document)));
|
||||
this._disposables.add(extHostNotebooks.onDidChangeNotebookCells(e => documentChange(e.document)));
|
||||
}
|
||||
|
||||
@@ -81,12 +68,12 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
|
||||
private _init() {
|
||||
this._cells = [];
|
||||
this._cellByUri = new ResourceMap();
|
||||
this._cellUris = new ResourceMap();
|
||||
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._cellByUri.set(cell.uri, this._cells.length);
|
||||
this._cellUris.set(cell.uri, this._cells.length);
|
||||
this._cells.push(<ExtHostCell>cell);
|
||||
cellLengths.push(cell.document.getText().length + 1);
|
||||
cellLineCounts.push(cell.document.lineCount);
|
||||
@@ -96,67 +83,6 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
this._cellLines = new PrefixSumComputer(new Uint32Array(cellLineCounts));
|
||||
}
|
||||
|
||||
private _createLanguageId(): string {
|
||||
const languageIds = new Set<string>();
|
||||
(function fillInLanguageIds(selector: vscode.DocumentSelector | undefined) {
|
||||
if (Array.isArray(selector)) {
|
||||
selector.forEach(fillInLanguageIds);
|
||||
} else if (typeof selector === 'string') {
|
||||
languageIds.add(selector);
|
||||
} else if (selector?.language) {
|
||||
languageIds.add(selector.language);
|
||||
}
|
||||
})(this._selector);
|
||||
|
||||
if (languageIds.size === 0) {
|
||||
return 'unknown';
|
||||
}
|
||||
return [...languageIds.values()].sort().join(';');
|
||||
}
|
||||
|
||||
save(): Thenable<boolean> {
|
||||
// todo@jrieken throw error instead?
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
get eol(): vscode.EndOfLine {
|
||||
return types.EndOfLine.LF;
|
||||
}
|
||||
|
||||
get lineCount(): number {
|
||||
let total = 0;
|
||||
for (let cell of this._cells) {
|
||||
total += cell.document.lineCount;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
lineAt(lineOrPosition: number | vscode.Position): vscode.TextLine {
|
||||
const line = typeof lineOrPosition === 'number' ? lineOrPosition : lineOrPosition.line;
|
||||
const cellIdx = this._cellLines.getIndexOf(line);
|
||||
return new ExtHostDocumentLine(
|
||||
line,
|
||||
this._cells[cellIdx.index].document.lineAt(cellIdx.remainder).text,
|
||||
line >= this.lineCount
|
||||
);
|
||||
}
|
||||
|
||||
getWordRangeAtPosition(position: vscode.Position, regex?: RegExp | undefined): vscode.Range | undefined {
|
||||
const cellIdx = this._cellLines.getIndexOf(position.line);
|
||||
return this._cells[cellIdx.index].document.getWordRangeAtPosition(position.with({ line: cellIdx.remainder }), regex);
|
||||
}
|
||||
|
||||
validateRange(range: vscode.Range): vscode.Range {
|
||||
const start = this.validatePosition(range.start);
|
||||
const end = this.validatePosition(range.end);
|
||||
return range.with({ start, end });
|
||||
}
|
||||
|
||||
validatePosition(position: vscode.Position): vscode.Position {
|
||||
const cellIdx = this._cellLines.getIndexOf(position.line);
|
||||
return this._cells[cellIdx.index].document.validatePosition(position.with({ line: cellIdx.remainder }));
|
||||
}
|
||||
|
||||
get version(): number {
|
||||
return this._versionId;
|
||||
}
|
||||
@@ -179,8 +105,8 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
// get start and end locations and create substrings
|
||||
const start = this.locationAt(range.start);
|
||||
const end = this.locationAt(range.end);
|
||||
const startCell = this._cells[this._cellByUri.get(start.uri) ?? -1];
|
||||
const endCell = this._cells[this._cellByUri.get(end.uri) ?? -1];
|
||||
const startCell = this._cells[this._cellUris.get(start.uri) ?? -1];
|
||||
const endCell = this._cells[this._cellUris.get(end.uri) ?? -1];
|
||||
|
||||
if (!startCell || !endCell) {
|
||||
return '';
|
||||
@@ -207,8 +133,8 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
return this._cells[idx.index].document.positionAt(idx.remainder).translate(lineCount);
|
||||
}
|
||||
|
||||
const idx = this._cellByUri.get(locationOrOffset.uri);
|
||||
if (typeof idx === 'number') {
|
||||
const idx = this._cellUris.get(locationOrOffset.uri);
|
||||
if (idx !== undefined) {
|
||||
let line = this._cellLines.getAccumulatedValue(idx - 1);
|
||||
return new types.Position(line + locationOrOffset.range.start.line, locationOrOffset.range.start.character);
|
||||
}
|
||||
@@ -235,4 +161,24 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
const startCell = this._cells[startIdx.index];
|
||||
return new types.Location(startCell.uri, <types.Range>startCell.document.validateRange(range));
|
||||
}
|
||||
|
||||
contains(uri: vscode.Uri): boolean {
|
||||
return this._cellUris.has(uri);
|
||||
}
|
||||
|
||||
validateRange(range: vscode.Range): vscode.Range {
|
||||
const start = this.validatePosition(range.start);
|
||||
const end = this.validatePosition(range.end);
|
||||
return range.with(start, end);
|
||||
}
|
||||
|
||||
validatePosition(position: vscode.Position): vscode.Position {
|
||||
const startIdx = this._cellLines.getIndexOf(position.line);
|
||||
|
||||
const cellPosition = new types.Position(startIdx.remainder, position.character);
|
||||
const validCellPosition = this._cells[startIdx.index].document.validatePosition(cellPosition);
|
||||
|
||||
const line = this._cellLines.getAccumulatedValue(startIdx.index - 1);
|
||||
return new types.Position(line + validCellPosition.line, validCellPosition.character);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,10 +625,11 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
for (const provideResult of provideResults) {
|
||||
if (provideResult && provideResult.links.length > 0) {
|
||||
result.push(...provideResult.links.map(providerLink => {
|
||||
const endIndex = Math.max(providerLink.endIndex, providerLink.startIndex + 1);
|
||||
const link = {
|
||||
id: nextLinkId++,
|
||||
startIndex: providerLink.startIndex,
|
||||
length: providerLink.length,
|
||||
length: endIndex - providerLink.startIndex,
|
||||
label: providerLink.tooltip
|
||||
};
|
||||
cacheLinkMap.set(link.id, {
|
||||
@@ -651,9 +652,6 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
return;
|
||||
}
|
||||
cachedLink.provider.handleTerminalLink(cachedLink.link);
|
||||
// TODO: Handle when result is false? Should this be return void instead and remove
|
||||
// TerminalLink.target? It's a simple call to window.openUri for the extension otherwise
|
||||
// and would simplify the API.
|
||||
}
|
||||
|
||||
private _onProcessExit(id: number, exitCode: number | undefined): void {
|
||||
|
||||
@@ -119,6 +119,22 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
return treeView.getChildren(treeItemHandle);
|
||||
}
|
||||
|
||||
async $hasResolve(treeViewId: string): Promise<boolean> {
|
||||
const treeView = this.treeViews.get(treeViewId);
|
||||
if (!treeView) {
|
||||
throw new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId));
|
||||
}
|
||||
return treeView.hasResolve;
|
||||
}
|
||||
|
||||
$resolve(treeViewId: string, treeItemHandle: string): Promise<ITreeItem | undefined> {
|
||||
const treeView = this.treeViews.get(treeViewId);
|
||||
if (!treeView) {
|
||||
throw new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId));
|
||||
}
|
||||
return treeView.resolveTreeItem(treeItemHandle);
|
||||
}
|
||||
|
||||
$setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void {
|
||||
const treeView = this.treeViews.get(treeViewId);
|
||||
if (!treeView) {
|
||||
@@ -160,6 +176,7 @@ type TreeData<T> = { message: boolean, element: T | Root | false };
|
||||
|
||||
interface TreeNode extends IDisposable {
|
||||
item: ITreeItem;
|
||||
extensionItem: vscode.TreeItem2;
|
||||
parent: TreeNode | Root;
|
||||
children?: TreeNode[];
|
||||
}
|
||||
@@ -329,6 +346,27 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
get hasResolve(): boolean {
|
||||
return !!this.dataProvider.resolveTreeItem;
|
||||
}
|
||||
|
||||
async resolveTreeItem(treeItemHandle: string): Promise<ITreeItem | undefined> {
|
||||
if (!this.dataProvider.resolveTreeItem) {
|
||||
return;
|
||||
}
|
||||
const element = this.elements.get(treeItemHandle);
|
||||
if (element) {
|
||||
const node = this.nodes.get(element);
|
||||
if (node) {
|
||||
const resolve = await this.dataProvider.resolveTreeItem(element, node.extensionItem);
|
||||
// Resolvable elements. Currently only tooltip.
|
||||
node.item.tooltip = resolve.tooltip;
|
||||
return node.item;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
private resolveUnknownParentChain(element: T): Promise<TreeNode[]> {
|
||||
return this.resolveParent(element)
|
||||
.then((parent) => {
|
||||
@@ -521,6 +559,7 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
|
||||
return {
|
||||
item,
|
||||
extensionItem: extensionTreeItem,
|
||||
parent,
|
||||
children: undefined,
|
||||
dispose(): void { disposable.dispose(); }
|
||||
|
||||
@@ -2769,7 +2769,7 @@ export enum ExtensionMode {
|
||||
|
||||
|
||||
//#region Authentication
|
||||
export class AuthenticationSession implements vscode.AuthenticationSession2 {
|
||||
export class AuthenticationSession implements vscode.AuthenticationSession {
|
||||
constructor(public id: string, public accessToken: string, public account: { displayName: string, id: string }, public scopes: string[]) { }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user