mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 17:22:45 -05:00
Merge from vscode 2b0b9136329c181a9e381463a1f7dc3a2d105a34 (#4880)
This commit is contained in:
@@ -11,9 +11,9 @@ import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
|
||||
import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWindowsService, IOpenSettings } from 'vs/platform/windows/common/windows';
|
||||
import { IWindowsService, IOpenSettings, IURIToOpen } from 'vs/platform/windows/common/windows';
|
||||
import { IDownloadService } from 'vs/platform/download/common/download';
|
||||
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWorkspacesService, hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IRecent } from 'vs/platform/history/common/history';
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@@ -51,7 +51,8 @@ export class OpenFolderAPICommand {
|
||||
}
|
||||
const options: IOpenSettings = { forceNewWindow: arg.forceNewWindow, noRecentEntry: arg.noRecentEntry };
|
||||
uri = URI.revive(uri);
|
||||
return executor.executeCommand('_files.windowOpen', [{ uri }], options);
|
||||
const uriToOpen: IURIToOpen = hasWorkspaceFileExtension(uri.path) ? { workspaceUri: uri } : { folderUri: uri };
|
||||
return executor.executeCommand('_files.windowOpen', [uriToOpen], options);
|
||||
}
|
||||
}
|
||||
CommandsRegistry.registerCommand({
|
||||
|
||||
@@ -19,7 +19,7 @@ import { score } from 'vs/editor/common/modes/languageSelector';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
import pkg from 'vs/platform/product/node/package';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { ExtHostContext, IInitData, IMainContext, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostContext, IInitData, IMainContext, MainContext, MainThreadKeytarShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostApiCommands } from 'vs/workbench/api/node/extHostApiCommands';
|
||||
import { ExtHostClipboard } from 'vs/workbench/api/node/extHostClipboard';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
|
||||
@@ -237,6 +237,7 @@ export function createApiFactory(
|
||||
get language() { return platform.language!; },
|
||||
get appName() { return product.nameLong; },
|
||||
get appRoot() { return initData.environment.appRoot!.fsPath; },
|
||||
get uriScheme() { return product.urlProtocol; },
|
||||
get logLevel() {
|
||||
checkProposedApiEnabled(extension);
|
||||
return typeConverters.LogLevel.to(extHostLogService.getLevel());
|
||||
@@ -883,41 +884,105 @@ class Extension<T> implements vscode.Extension<T> {
|
||||
}
|
||||
}
|
||||
|
||||
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): Promise<void> {
|
||||
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry, configProvider));
|
||||
interface INodeModuleFactory {
|
||||
readonly nodeModuleName: string;
|
||||
load(request: string, parent: { filename: string; }): any;
|
||||
}
|
||||
|
||||
function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree<IExtensionDescription>, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): void {
|
||||
export class NodeModuleRequireInterceptor {
|
||||
public static INSTANCE = new NodeModuleRequireInterceptor();
|
||||
|
||||
// each extension is meant to get its own api implementation
|
||||
const extApiImpl = new Map<string, typeof vscode>();
|
||||
let defaultApiImpl: typeof vscode;
|
||||
private readonly _factories: Map<string, INodeModuleFactory>;
|
||||
|
||||
const node_module = <any>require.__$__nodeRequire('module');
|
||||
const original = node_module._load;
|
||||
node_module._load = function load(request: string, parent: any, isMain: any) {
|
||||
if (request !== 'vscode') {
|
||||
return original.apply(this, arguments);
|
||||
}
|
||||
constructor() {
|
||||
this._factories = new Map<string, INodeModuleFactory>();
|
||||
this._installInterceptor(this._factories);
|
||||
}
|
||||
|
||||
private _installInterceptor(factories: Map<string, INodeModuleFactory>): void {
|
||||
const node_module = <any>require.__$__nodeRequire('module');
|
||||
const original = node_module._load;
|
||||
node_module._load = function load(request: string, parent: { filename: string; }, isMain: any) {
|
||||
if (!factories.has(request)) {
|
||||
return original.apply(this, arguments);
|
||||
}
|
||||
return factories.get(request)!.load(request, parent);
|
||||
};
|
||||
}
|
||||
|
||||
public register(interceptor: INodeModuleFactory): void {
|
||||
this._factories.set(interceptor.nodeModuleName, interceptor);
|
||||
}
|
||||
}
|
||||
|
||||
export class VSCodeNodeModuleFactory implements INodeModuleFactory {
|
||||
public readonly nodeModuleName = 'vscode';
|
||||
|
||||
private readonly _extApiImpl = new Map<string, typeof vscode>();
|
||||
private _defaultApiImpl: typeof vscode;
|
||||
|
||||
constructor(
|
||||
private readonly _apiFactory: IExtensionApiFactory,
|
||||
private readonly _extensionPaths: TernarySearchTree<IExtensionDescription>,
|
||||
private readonly _extensionRegistry: ExtensionDescriptionRegistry,
|
||||
private readonly _configProvider: ExtHostConfigProvider
|
||||
) {
|
||||
}
|
||||
|
||||
public load(request: string, parent: { filename: string; }): any {
|
||||
|
||||
// get extension id from filename and api for extension
|
||||
const ext = extensionPaths.findSubstr(URI.file(parent.filename).fsPath);
|
||||
const ext = this._extensionPaths.findSubstr(URI.file(parent.filename).fsPath);
|
||||
if (ext) {
|
||||
let apiImpl = extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier));
|
||||
let apiImpl = this._extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier));
|
||||
if (!apiImpl) {
|
||||
apiImpl = factory(ext, extensionRegistry, configProvider);
|
||||
extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl);
|
||||
apiImpl = this._apiFactory(ext, this._extensionRegistry, this._configProvider);
|
||||
this._extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl);
|
||||
}
|
||||
return apiImpl;
|
||||
}
|
||||
|
||||
// fall back to a default implementation
|
||||
if (!defaultApiImpl) {
|
||||
if (!this._defaultApiImpl) {
|
||||
let extensionPathsPretty = '';
|
||||
extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.identifier.value}\n`);
|
||||
this._extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.identifier.value}\n`);
|
||||
console.warn(`Could not identify extension for 'vscode' require call from ${parent.filename}. These are the extension path mappings: \n${extensionPathsPretty}`);
|
||||
defaultApiImpl = factory(nullExtensionDescription, extensionRegistry, configProvider);
|
||||
this._defaultApiImpl = this._apiFactory(nullExtensionDescription, this._extensionRegistry, this._configProvider);
|
||||
}
|
||||
return defaultApiImpl;
|
||||
};
|
||||
return this._defaultApiImpl;
|
||||
}
|
||||
}
|
||||
|
||||
interface IKeytarModule {
|
||||
getPassword(service: string, account: string): Promise<string | null>;
|
||||
setPassword(service: string, account: string, password: string): Promise<void>;
|
||||
deletePassword(service: string, account: string): Promise<boolean>;
|
||||
findPassword(service: string): Promise<string | null>;
|
||||
}
|
||||
|
||||
export class KeytarNodeModuleFactory implements INodeModuleFactory {
|
||||
public readonly nodeModuleName = 'keytar';
|
||||
|
||||
private _impl: IKeytarModule;
|
||||
|
||||
constructor(mainThreadKeytar: MainThreadKeytarShape) {
|
||||
this._impl = {
|
||||
getPassword: (service: string, account: string): Promise<string | null> => {
|
||||
return mainThreadKeytar.$getPassword(service, account);
|
||||
},
|
||||
setPassword: (service: string, account: string, password: string): Promise<void> => {
|
||||
return mainThreadKeytar.$setPassword(service, account, password);
|
||||
},
|
||||
deletePassword: (service: string, account: string): Promise<boolean> => {
|
||||
return mainThreadKeytar.$deletePassword(service, account);
|
||||
},
|
||||
findPassword: (service: string): Promise<string | null> => {
|
||||
return mainThreadKeytar.$findPassword(service);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public load(request: string, parent: { filename: string; }): any {
|
||||
return this._impl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { generateRandomPipeName } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import * as http from 'http';
|
||||
import * as fs from 'fs';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { IURIToOpen, URIType, IOpenSettings } from 'vs/platform/windows/common/windows';
|
||||
import { IURIToOpen, IOpenSettings } from 'vs/platform/windows/common/windows';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
|
||||
|
||||
@@ -55,17 +55,6 @@ export class CLIServer {
|
||||
|
||||
return this._ipcHandlePath;
|
||||
}
|
||||
private collectURIToOpen(strs: string[] | undefined, typeHint: URIType, result: IURIToOpen[]): void {
|
||||
if (Array.isArray(strs)) {
|
||||
for (const s of strs) {
|
||||
try {
|
||||
result.push({ uri: URI.parse(s), typeHint });
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
|
||||
const chunks: string[] = [];
|
||||
@@ -95,13 +84,32 @@ export class CLIServer {
|
||||
|
||||
private open(data: OpenCommandPipeArgs, res: http.ServerResponse) {
|
||||
let { fileURIs, folderURIs, forceNewWindow, diffMode, addMode, forceReuseWindow, waitMarkerFilePath } = data;
|
||||
if (folderURIs && folderURIs.length || fileURIs && fileURIs.length) {
|
||||
const urisToOpen: IURIToOpen[] = [];
|
||||
this.collectURIToOpen(folderURIs, 'folder', urisToOpen);
|
||||
this.collectURIToOpen(fileURIs, 'file', urisToOpen);
|
||||
if (!forceReuseWindow && urisToOpen.some(o => o.typeHint === 'folder' || (o.typeHint === 'file' && hasWorkspaceFileExtension(o.uri.path)))) {
|
||||
forceNewWindow = true;
|
||||
const urisToOpen: IURIToOpen[] = [];
|
||||
if (Array.isArray(folderURIs)) {
|
||||
for (const s of folderURIs) {
|
||||
try {
|
||||
urisToOpen.push({ folderUri: URI.parse(s) });
|
||||
forceNewWindow = true;
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Array.isArray(fileURIs)) {
|
||||
for (const s of fileURIs) {
|
||||
try {
|
||||
if (hasWorkspaceFileExtension(s)) {
|
||||
urisToOpen.push({ workspaceUri: URI.parse(s) });
|
||||
forceNewWindow = true;
|
||||
} else {
|
||||
urisToOpen.push({ fileUri: URI.parse(s) });
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
if (urisToOpen.length) {
|
||||
const waitMarkerFileURI = waitMarkerFilePath ? URI.file(waitMarkerFilePath) : undefined;
|
||||
const windowOpenArgs: IOpenSettings = { forceNewWindow, diffMode, addMode, forceReuseWindow, waitMarkerFileURI };
|
||||
this._commands.executeCommand('_files.windowOpen', urisToOpen, windowOpenArgs);
|
||||
|
||||
@@ -16,6 +16,7 @@ import { IRange } from 'vs/editor/common/core/range';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
|
||||
interface HandlerData<T> {
|
||||
|
||||
@@ -360,10 +361,13 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
return this._resource;
|
||||
}
|
||||
|
||||
private _onDidUpdateCommentThread = new Emitter<void>();
|
||||
readonly onDidUpdateCommentThread = this._onDidUpdateCommentThread.event;
|
||||
|
||||
set range(range: vscode.Range) {
|
||||
if (range.isEqual(this._range)) {
|
||||
this._range = range;
|
||||
this._proxy.$updateCommentThreadRange(this._commentController.handle, this.handle, extHostTypeConverter.Range.from(this._range));
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,7 +383,7 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
|
||||
set label(label: string) {
|
||||
this._label = label;
|
||||
this._proxy.$updateCommentThreadLabel(this._commentController.handle, this.handle, this._label);
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
get comments(): vscode.Comment[] {
|
||||
@@ -387,8 +391,8 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
}
|
||||
|
||||
set comments(newComments: vscode.Comment[]) {
|
||||
this._proxy.$updateComments(this._commentController.handle, this.handle, newComments.map(cmt => { return convertToModeComment(this._commentController, cmt, this._commandsConverter); }));
|
||||
this._comments = newComments;
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
private _acceptInputCommand: vscode.Command;
|
||||
@@ -398,9 +402,7 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
|
||||
set acceptInputCommand(acceptInputCommand: vscode.Command) {
|
||||
this._acceptInputCommand = acceptInputCommand;
|
||||
|
||||
const internal = this._commandsConverter.toInternal(acceptInputCommand);
|
||||
this._proxy.$updateCommentThreadAcceptInputCommand(this._commentController.handle, this.handle, internal);
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
private _additionalCommands: vscode.Command[] = [];
|
||||
@@ -410,9 +412,7 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
|
||||
set additionalCommands(additionalCommands: vscode.Command[]) {
|
||||
this._additionalCommands = additionalCommands;
|
||||
|
||||
const internals = additionalCommands.map(x => this._commandsConverter.toInternal(x));
|
||||
this._proxy.$updateCommentThreadAdditionalCommands(this._commentController.handle, this.handle, internals);
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
private _deleteCommand?: vscode.Command;
|
||||
@@ -422,9 +422,7 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
|
||||
set deleteCommand(deleteCommand: vscode.Command) {
|
||||
this._deleteCommand = deleteCommand;
|
||||
|
||||
const internal = this._commandsConverter.toInternal(deleteCommand);
|
||||
this._proxy.$updateCommentThreadDeleteCommand(this._commentController.handle, this.handle, internal);
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
private _collapseState?: vscode.CommentThreadCollapsibleState;
|
||||
@@ -435,9 +433,11 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
|
||||
set collapsibleState(newState: vscode.CommentThreadCollapsibleState) {
|
||||
this._collapseState = newState;
|
||||
this._proxy.$updateCommentThreadCollapsibleState(this._commentController.handle, this.handle, convertToCollapsibleState(newState));
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
private _localDisposables: types.Disposable[];
|
||||
|
||||
constructor(
|
||||
private _proxy: MainThreadCommentsShape,
|
||||
private readonly _commandsConverter: CommandsConverter,
|
||||
@@ -452,12 +452,41 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
this.handle,
|
||||
this._threadId,
|
||||
this._resource,
|
||||
extHostTypeConverter.Range.from(this._range),
|
||||
this._comments.map(comment => { return convertToModeComment(this._commentController, comment, this._commandsConverter); }),
|
||||
this._acceptInputCommand ? this._commandsConverter.toInternal(this._acceptInputCommand) : undefined,
|
||||
this._additionalCommands ? this._additionalCommands.map(x => this._commandsConverter.toInternal(x)) : [],
|
||||
this._deleteCommand ? this._commandsConverter.toInternal(this._deleteCommand) : undefined,
|
||||
this._collapseState!
|
||||
extHostTypeConverter.Range.from(this._range)
|
||||
);
|
||||
|
||||
this._localDisposables = [];
|
||||
|
||||
this._localDisposables.push(this.onDidUpdateCommentThread(() => {
|
||||
this.eventuallyUpdateCommentThread();
|
||||
}));
|
||||
|
||||
// set up comments after ctor to batch update events.
|
||||
this.comments = _comments;
|
||||
}
|
||||
|
||||
@debounce(100)
|
||||
eventuallyUpdateCommentThread(): void {
|
||||
const commentThreadRange = extHostTypeConverter.Range.from(this._range);
|
||||
const label = this.label;
|
||||
const comments = this._comments.map(cmt => { return convertToModeComment(this._commentController, cmt, this._commandsConverter); });
|
||||
const acceptInputCommand = this._acceptInputCommand ? this._commandsConverter.toInternal(this._acceptInputCommand) : undefined;
|
||||
const additionalCommands = this._additionalCommands ? this._additionalCommands.map(x => this._commandsConverter.toInternal(x)) : [];
|
||||
const deleteCommand = this._deleteCommand ? this._commandsConverter.toInternal(this._deleteCommand) : undefined;
|
||||
const collapsibleState = convertToCollapsibleState(this._collapseState);
|
||||
|
||||
this._proxy.$updateCommentThread(
|
||||
this._commentController.handle,
|
||||
this.handle,
|
||||
this._threadId,
|
||||
this._resource,
|
||||
commentThreadRange,
|
||||
label,
|
||||
comments,
|
||||
acceptInputCommand,
|
||||
additionalCommands,
|
||||
deleteCommand,
|
||||
collapsibleState
|
||||
);
|
||||
}
|
||||
|
||||
@@ -472,6 +501,7 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._localDisposables.forEach(disposable => disposable.dispose());
|
||||
this._proxy.$deleteCommentThread(
|
||||
this._commentController.handle,
|
||||
this.handle
|
||||
@@ -607,7 +637,7 @@ function convertFromCommentThread(commentThread: modes.CommentThread): vscode.Co
|
||||
threadId: commentThread.threadId!,
|
||||
resource: URI.parse(commentThread.resource!),
|
||||
range: extHostTypeConverter.Range.to(commentThread.range),
|
||||
comments: commentThread.comments.map(convertFromComment),
|
||||
comments: commentThread.comments ? commentThread.comments.map(convertFromComment) : [],
|
||||
collapsibleState: commentThread.collapsibleState
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import { URI } from 'vs/base/common/uri';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
// {{SQL CARBON EDIT}} - Remove createApiFactory initializeExtensionApi, and IExtensionApiFactory imports
|
||||
//import { createApiFactory, IExtensionApiFactory, NodeModuleRequireInterceptor, VSCodeNodeModuleFactory } from 'vs/workbench/api/node/extHost.api.impl';
|
||||
import { NodeModuleRequireInterceptor, VSCodeNodeModuleFactory, KeytarNodeModuleFactory } from 'vs/workbench/api/node/extHost.api.impl';
|
||||
import { ExtHostExtensionServiceShape, IEnvironment, IInitData, IMainContext, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape, IStaticWorkspaceData } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
|
||||
import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionContext, IExtensionMemento, IExtensionModule, HostExtension } from 'vs/workbench/api/node/extHostExtensionActivator';
|
||||
@@ -32,6 +34,7 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio
|
||||
import { IWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { realpath } from 'vs/base/node/extpath';
|
||||
|
||||
class ExtensionMemento implements IExtensionMemento {
|
||||
|
||||
@@ -243,7 +246,13 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
private async _initialize(): Promise<void> {
|
||||
try {
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
|
||||
// {{SQL CARBON EDIT}} - disable VSCodeNodeModuleFactory and use older initializeExtensionApi
|
||||
// const extensionPaths = await this.getExtensionPathIndex();
|
||||
// NodeModuleRequireInterceptor.INSTANCE.register(new VSCodeNodeModuleFactory(this._extensionApiFactory, extensionPaths, this._registry, configProvider));
|
||||
await initializeExtensionApi(this, this._extensionApiFactory, this._registry, configProvider);
|
||||
NodeModuleRequireInterceptor.INSTANCE.register(new KeytarNodeModuleFactory(this._extHostContext.getProxy(MainContext.MainThreadKeytar)));
|
||||
|
||||
// Do this when extension service exists, but extensions are not being activated yet.
|
||||
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy);
|
||||
this._almostReadyToRunExtensions.open();
|
||||
@@ -318,7 +327,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
if (!ext.main) {
|
||||
return undefined;
|
||||
}
|
||||
return pfs.realpath(ext.extensionLocation.fsPath).then(value => tree.set(URI.file(value).fsPath, ext));
|
||||
return realpath(ext.extensionLocation.fsPath).then(value => tree.set(URI.file(value).fsPath, ext));
|
||||
});
|
||||
this._extensionPathIndex = Promise.all(extensions).then(() => tree);
|
||||
}
|
||||
@@ -735,13 +744,13 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
if (!extensionDescription) {
|
||||
return;
|
||||
}
|
||||
const realpath = await pfs.realpath(extensionDescription.extensionLocation.fsPath);
|
||||
trie.delete(URI.file(realpath).fsPath);
|
||||
const realpathValue = await realpath(extensionDescription.extensionLocation.fsPath);
|
||||
trie.delete(URI.file(realpathValue).fsPath);
|
||||
}));
|
||||
|
||||
await Promise.all(toAdd.map(async (extensionDescription) => {
|
||||
const realpath = await pfs.realpath(extensionDescription.extensionLocation.fsPath);
|
||||
trie.set(URI.file(realpath).fsPath, extensionDescription);
|
||||
const realpathValue = await realpath(extensionDescription.extensionLocation.fsPath);
|
||||
trie.set(URI.file(realpathValue).fsPath, extensionDescription);
|
||||
}));
|
||||
|
||||
this._registry.deltaExtensions(toAdd, toRemove);
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
|
||||
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { asPromise } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto, ISerializedDocumentFilter, WorkspaceEditDto, ISerializedSignatureHelpProviderMetadata, LinkDto, CodeLensDto, MainThreadWebviewsShape, CodeInsetDto } from '../common/extHost.protocol';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, CodeActionDto, ISerializedDocumentFilter, WorkspaceEditDto, ISerializedSignatureHelpProviderMetadata, LinkDto, CodeLensDto, MainThreadWebviewsShape, CodeInsetDto, SuggestDataDto } from '../common/extHost.protocol';
|
||||
import { regExpLeadsToEndlessLoop, regExpFlags } from 'vs/base/common/strings';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange, Range as EditorRange } from 'vs/editor/common/core/range';
|
||||
@@ -129,7 +129,7 @@ class CodeLensAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
resolveCodeLens(resource: URI, symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto | undefined> {
|
||||
resolveCodeLens(symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto | undefined> {
|
||||
|
||||
const lens = this._heapService.get<vscode.CodeLens>(ObjectIdentifier.of(symbol));
|
||||
if (!lens) {
|
||||
@@ -637,15 +637,18 @@ class SuggestAdapter {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
|
||||
return asPromise<vscode.CompletionItem[] | vscode.CompletionList | null | undefined>(
|
||||
() => this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context))
|
||||
).then(value => {
|
||||
return asPromise(() => this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context))).then(value => {
|
||||
|
||||
const _id = this._idPool++;
|
||||
|
||||
// the default text edit range
|
||||
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos))
|
||||
.with({ end: pos });
|
||||
|
||||
const result: SuggestResultDto = {
|
||||
_id,
|
||||
suggestions: [],
|
||||
x: _id,
|
||||
b: [],
|
||||
a: typeConvert.Range.from(wordRangeBeforePos),
|
||||
};
|
||||
|
||||
let list: CompletionList;
|
||||
@@ -658,54 +661,45 @@ class SuggestAdapter {
|
||||
|
||||
} else {
|
||||
list = value;
|
||||
result.incomplete = list.isIncomplete;
|
||||
result.c = list.isIncomplete;
|
||||
}
|
||||
|
||||
// the default text edit range
|
||||
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos))
|
||||
.with({ end: pos });
|
||||
|
||||
for (let i = 0; i < list.items.length; i++) {
|
||||
const suggestion = this._convertCompletionItem(list.items[i], pos, wordRangeBeforePos, i, _id);
|
||||
const suggestion = this._convertCompletionItem2(list.items[i], pos, i, _id);
|
||||
// check for bad completion item
|
||||
// for the converter did warn
|
||||
if (suggestion) {
|
||||
result.suggestions.push(suggestion);
|
||||
result.b.push(suggestion);
|
||||
}
|
||||
}
|
||||
this._cache.set(_id, list.items);
|
||||
|
||||
if (SuggestAdapter.supportsResolving(this._provider)) {
|
||||
this._cache.set(_id, list.items);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
resolveCompletionItem(resource: URI, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Promise<modes.CompletionItem> {
|
||||
resolveCompletionItem(_resource: URI, position: IPosition, id: number, pid: number, token: CancellationToken): Promise<SuggestDataDto | undefined> {
|
||||
|
||||
if (typeof this._provider.resolveCompletionItem !== 'function') {
|
||||
return Promise.resolve(suggestion);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const { _parentId, _id } = (<SuggestionDto>suggestion);
|
||||
const item = this._cache.has(_parentId) ? this._cache.get(_parentId)![_id] : undefined;
|
||||
const item = this._cache.has(pid) ? this._cache.get(pid)![id] : undefined;
|
||||
if (!item) {
|
||||
return Promise.resolve(suggestion);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return asPromise(() => this._provider.resolveCompletionItem!(item, token)).then(resolvedItem => {
|
||||
|
||||
if (!resolvedItem) {
|
||||
return suggestion;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos)).with({ end: pos });
|
||||
const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos, _id, _parentId);
|
||||
if (newSuggestion) {
|
||||
mixin(suggestion, newSuggestion, true);
|
||||
}
|
||||
|
||||
return suggestion;
|
||||
return this._convertCompletionItem2(resolvedItem, pos, id, pid);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -713,60 +707,52 @@ class SuggestAdapter {
|
||||
this._cache.delete(id);
|
||||
}
|
||||
|
||||
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range, _id: number, _parentId: number): SuggestionDto | undefined {
|
||||
private _convertCompletionItem2(item: vscode.CompletionItem, position: vscode.Position, id: number, pid: number): SuggestDataDto | undefined {
|
||||
if (typeof item.label !== 'string' || item.label.length === 0) {
|
||||
console.warn('INVALID text edit -> must have at least a label');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result: SuggestionDto = {
|
||||
const result: SuggestDataDto = {
|
||||
//
|
||||
_id,
|
||||
_parentId,
|
||||
x: id,
|
||||
y: pid,
|
||||
//
|
||||
label: item.label,
|
||||
kind: typeConvert.CompletionItemKind.from(item.kind),
|
||||
detail: item.detail,
|
||||
documentation: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation),
|
||||
filterText: item.filterText,
|
||||
sortText: item.sortText,
|
||||
preselect: item.preselect,
|
||||
//
|
||||
range: undefined!, // populated below
|
||||
insertText: undefined!, // populated below
|
||||
insertTextRules: item.keepWhitespace ? modes.CompletionItemInsertTextRule.KeepWhitespace : 0,
|
||||
additionalTextEdits: item.additionalTextEdits && item.additionalTextEdits.map(typeConvert.TextEdit.from),
|
||||
command: this._commands.toInternal(item.command),
|
||||
commitCharacters: item.commitCharacters
|
||||
a: item.label,
|
||||
b: typeConvert.CompletionItemKind.from(item.kind),
|
||||
c: item.detail,
|
||||
d: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation),
|
||||
e: item.sortText,
|
||||
f: item.filterText,
|
||||
g: item.preselect,
|
||||
i: item.keepWhitespace ? modes.CompletionItemInsertTextRule.KeepWhitespace : 0,
|
||||
k: item.commitCharacters,
|
||||
l: item.additionalTextEdits && item.additionalTextEdits.map(typeConvert.TextEdit.from),
|
||||
m: this._commands.toInternal(item.command),
|
||||
};
|
||||
|
||||
// 'insertText'-logic
|
||||
if (item.textEdit) {
|
||||
result.insertText = item.textEdit.newText;
|
||||
result.h = item.textEdit.newText;
|
||||
|
||||
} else if (typeof item.insertText === 'string') {
|
||||
result.insertText = item.insertText;
|
||||
result.h = item.insertText;
|
||||
|
||||
} else if (item.insertText instanceof SnippetString) {
|
||||
result.insertText = item.insertText.value;
|
||||
result.insertTextRules! |= modes.CompletionItemInsertTextRule.InsertAsSnippet;
|
||||
|
||||
} else {
|
||||
result.insertText = item.label;
|
||||
result.h = item.insertText.value;
|
||||
result.i! |= modes.CompletionItemInsertTextRule.InsertAsSnippet;
|
||||
}
|
||||
|
||||
// 'overwrite[Before|After]'-logic
|
||||
let range: vscode.Range;
|
||||
let range: vscode.Range | undefined;
|
||||
if (item.textEdit) {
|
||||
range = item.textEdit.range;
|
||||
} else if (item.range) {
|
||||
range = item.range;
|
||||
} else {
|
||||
range = defaultRange;
|
||||
}
|
||||
result.range = typeConvert.Range.from(range);
|
||||
result.j = typeConvert.Range.from(range);
|
||||
|
||||
if (!range.isSingleLine || range.start.line !== position.line) {
|
||||
if (range && (!range.isSingleLine || range.start.line !== position.line)) {
|
||||
console.warn('INVALID text edit -> must be single line and on the same line');
|
||||
return undefined;
|
||||
}
|
||||
@@ -1181,8 +1167,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(URI.revive(resource), token), []);
|
||||
}
|
||||
|
||||
$resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol, token: CancellationToken): Promise<modes.ICodeLensSymbol | undefined> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(URI.revive(resource), symbol, token), undefined);
|
||||
$resolveCodeLens(handle: number, symbol: modes.ICodeLensSymbol, token: CancellationToken): Promise<modes.ICodeLensSymbol | undefined> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(symbol, token), undefined);
|
||||
}
|
||||
|
||||
// --- code insets
|
||||
@@ -1387,8 +1373,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context, token), undefined);
|
||||
}
|
||||
|
||||
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Promise<modes.CompletionItem> {
|
||||
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, suggestion, token), suggestion);
|
||||
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: number, pid: number, token: CancellationToken): Promise<SuggestDataDto | undefined> {
|
||||
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, id, pid, token), undefined);
|
||||
}
|
||||
|
||||
$releaseCompletionItems(handle: number, id: number): void {
|
||||
|
||||
@@ -163,7 +163,7 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
|
||||
|
||||
constructor(logsLocation: URI, mainContext: IMainContext) {
|
||||
const outputDirPath = join(logsLocation.fsPath, `output_logging_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`);
|
||||
this._outputDir = dirExists(outputDirPath).then(exists => exists ? exists : mkdirp(outputDirPath)).then(() => outputDirPath);
|
||||
this._outputDir = dirExists(outputDirPath).then(exists => exists ? exists : mkdirp(outputDirPath).then(() => true)).then(() => outputDirPath);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadOutputService);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import * as extfs from 'vs/base/node/extfs';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IFileQuery, IFolderQuery, IRawFileQuery, IRawQuery, IRawTextQuery, ISearchCompleteStats, ITextQuery, isSerializedFileMatch, ISerializedSearchProgressItem } from 'vs/workbench/services/search/common/search';
|
||||
import { FileSearchManager } from 'vs/workbench/services/search/node/fileSearchManager';
|
||||
@@ -35,7 +35,7 @@ export class ExtHostSearch implements ExtHostSearchShape {
|
||||
|
||||
private _fileSearchManager: FileSearchManager;
|
||||
|
||||
constructor(mainContext: IMainContext, private _schemeTransformer: ISchemeTransformer | null, private _logService: ILogService, private _extfs = extfs) {
|
||||
constructor(mainContext: IMainContext, private _schemeTransformer: ISchemeTransformer | null, private _logService: ILogService, private _pfs = pfs) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadSearch);
|
||||
this._fileSearchManager = new FileSearchManager();
|
||||
}
|
||||
@@ -146,7 +146,7 @@ export class ExtHostSearch implements ExtHostSearchShape {
|
||||
}
|
||||
|
||||
const query = reviveQuery(rawQuery);
|
||||
const engine = new TextSearchManager(query, provider, this._extfs);
|
||||
const engine = new TextSearchManager(query, provider, this._pfs);
|
||||
return engine.search(progress => this._proxy.$handleTextMatch(handle, session, progress), token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as crypto from 'crypto';
|
||||
import { coalesce, equals } from 'vs/base/common/arrays';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
@@ -1545,6 +1544,14 @@ export class TaskGroup implements vscode.TaskGroup {
|
||||
}
|
||||
}
|
||||
|
||||
function computeTaskExecutionId(values: string[]): string {
|
||||
let id: string = '';
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
id += values[i].replace(/,/g, ',,') + ',';
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class ProcessExecution implements vscode.ProcessExecution {
|
||||
|
||||
@@ -1604,17 +1611,17 @@ export class ProcessExecution implements vscode.ProcessExecution {
|
||||
}
|
||||
|
||||
public computeId(): string {
|
||||
const hash = crypto.createHash('md5');
|
||||
hash.update('process');
|
||||
const props: string[] = [];
|
||||
props.push('process');
|
||||
if (this._process !== undefined) {
|
||||
hash.update(this._process);
|
||||
props.push(this._process);
|
||||
}
|
||||
if (this._args && this._args.length > 0) {
|
||||
for (let arg of this._args) {
|
||||
hash.update(arg);
|
||||
props.push(arg);
|
||||
}
|
||||
}
|
||||
return hash.digest('hex');
|
||||
return computeTaskExecutionId(props);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1687,20 +1694,20 @@ export class ShellExecution implements vscode.ShellExecution {
|
||||
}
|
||||
|
||||
public computeId(): string {
|
||||
const hash = crypto.createHash('md5');
|
||||
hash.update('shell');
|
||||
const props: string[] = [];
|
||||
props.push('shell');
|
||||
if (this._commandLine !== undefined) {
|
||||
hash.update(this._commandLine);
|
||||
props.push(this._commandLine);
|
||||
}
|
||||
if (this._command !== undefined) {
|
||||
hash.update(typeof this._command === 'string' ? this._command : this._command.value);
|
||||
props.push(typeof this._command === 'string' ? this._command : this._command.value);
|
||||
}
|
||||
if (this._args && this._args.length > 0) {
|
||||
for (let arg of this._args) {
|
||||
hash.update(typeof arg === 'string' ? arg : arg.value);
|
||||
props.push(typeof arg === 'string' ? arg : arg.value);
|
||||
}
|
||||
}
|
||||
return hash.digest('hex');
|
||||
return computeTaskExecutionId(props);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1723,10 +1730,7 @@ export class CustomExecution implements vscode.CustomExecution {
|
||||
}
|
||||
|
||||
public computeId(): string {
|
||||
const hash = crypto.createHash('md5');
|
||||
hash.update('customExecution');
|
||||
hash.update(generateUuid());
|
||||
return hash.digest('hex');
|
||||
return 'customExecution' + generateUuid();
|
||||
}
|
||||
|
||||
public set callback(value: (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<number>) {
|
||||
|
||||
Reference in New Issue
Block a user