Merge from vscode a4177f50c475fc0fa278a78235e3bee9ffdec781 (#8649)

* Merge from vscode a4177f50c475fc0fa278a78235e3bee9ffdec781

* distro

* fix tests
This commit is contained in:
Anthony Dresser
2019-12-11 22:42:23 -08:00
committed by GitHub
parent 82974a2135
commit 4ba6a979ba
280 changed files with 10898 additions and 14231 deletions

View File

@@ -68,6 +68,7 @@ import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransf
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { find } from 'vs/base/common/arrays';
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
export interface IExtensionApiFactory {
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
@@ -87,6 +88,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const rpcProtocol = accessor.get(IExtHostRpcService);
const extHostStorage = accessor.get(IExtHostStorage);
const extHostLogService = accessor.get(ILogService);
const extHostTunnelService = accessor.get(IExtHostTunnelService);
// register addressable instances
rpcProtocol.set(ExtHostContext.ExtHostLogService, <ExtHostLogServiceShape><any>extHostLogService);
@@ -94,6 +96,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
rpcProtocol.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration);
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
rpcProtocol.set(ExtHostContext.ExtHostTunnelService, extHostTunnelService);
// automatically create and register addressable instances
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, accessor.get(IExtHostDecorations));
@@ -228,10 +231,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
get appName() { return initData.environment.appName; },
get appRoot() { return initData.environment.appRoot!.fsPath; },
get uriScheme() { return initData.environment.appUriScheme; },
createAppUri(options?) {
checkProposedApiEnabled(extension);
return extHostUrls.proposedCreateAppUri(extension.identifier, options);
},
get logLevel() {
checkProposedApiEnabled(extension);
return typeConverters.LogLevel.to(extHostLogService.getLevel());
@@ -506,7 +505,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostStatusBar.setStatusBarMessage(text, timeoutOrThenable);
},
withScmProgress<R>(task: (progress: vscode.Progress<number>) => Thenable<R>) {
console.warn(`[Deprecation Warning] function 'withScmProgress' is deprecated and should no longer be used. Use 'withProgress' instead.`);
return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, (progress, token) => task({ report(n: number) { /*noop*/ } }));
},
withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; worked?: number }>, token: vscode.CancellationToken) => Thenable<R>) {
@@ -565,7 +563,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
get rootPath() {
if (extension.isUnderDevelopment && !warnedRootPathDeprecated) {
warnedRootPathDeprecated = true;
console.warn(`[Deprecation Warning] 'workspace.rootPath' is deprecated and should no longer be used. Please use 'workspace.workspaceFolders' instead. More details: https://aka.ms/vscode-eliminating-rootpath`);
extHostLogService.warn(`[Deprecation Warning] 'workspace.rootPath' is deprecated and should no longer be used. Please use 'workspace.workspaceFolders' instead. More details: https://aka.ms/vscode-eliminating-rootpath`);
}
return extHostWorkspace.getPath();
@@ -721,6 +719,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
},
onWillRenameFiles: (listener: (e: vscode.FileWillRenameEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => {
return extHostFileSystemEvent.getOnWillRenameFileEvent(extension)(listener, thisArg, disposables);
},
makeTunnel: (forward: vscode.TunnelOptions) => {
checkProposedApiEnabled(extension);
return extHostTunnelService.makeTunnel(forward);
}
};

View File

@@ -47,6 +47,7 @@ import { createExtHostContextProxyIdentifier as createExtId, createMainContextPr
import * as search from 'vs/workbench/services/search/common/search';
import { SaveReason } from 'vs/workbench/common/editor';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
import { TunnelOptions, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
// {{SQL CARBON EDIT}}
import { ITreeItem as sqlITreeItem } from 'sql/workbench/common/views';
@@ -90,6 +91,7 @@ export interface IInitData {
telemetryInfo: ITelemetryInfo;
logLevel: LogLevel;
logsLocation: URI;
logFile: URI;
autoStart: boolean;
remote: { isRemote: boolean; authority: string | undefined; };
uiKind: UIKind;
@@ -614,7 +616,6 @@ export interface MainThreadUrlsShape extends IDisposable {
$registerUriHandler(handle: number, extensionId: ExtensionIdentifier): Promise<void>;
$unregisterUriHandler(handle: number): Promise<void>;
$createAppUri(uri: UriComponents): Promise<UriComponents>;
$proposedCreateAppUri(extensionId: ExtensionIdentifier, options?: { payload?: Partial<UriComponents>; }): Promise<UriComponents>;
}
export interface ExtHostUrlsShape {
@@ -781,6 +782,12 @@ export interface MainThreadWindowShape extends IDisposable {
$asExternalUri(uri: UriComponents, options: IOpenUriOptions): Promise<UriComponents>;
}
export interface MainThreadTunnelServiceShape extends IDisposable {
$openTunnel(tunnelOptions: TunnelOptions): Promise<TunnelDto | undefined>;
$closeTunnel(remotePort: number): Promise<void>;
$addDetected(tunnels: { remote: { port: number, host: string }, localAddress: string }[]): Promise<void>;
}
// -- extension host
export interface ExtHostCommandsShape {
@@ -1395,6 +1402,11 @@ export interface ExtHostStorageShape {
$acceptValue(shared: boolean, key: string, value: object | undefined): void;
}
export interface ExtHostTunnelServiceShape {
}
// --- proxy identifiers
export const MainContext = {
@@ -1435,7 +1447,8 @@ export const MainContext = {
MainThreadSearch: createMainId<MainThreadSearchShape>('MainThreadSearch'),
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask'),
MainThreadWindow: createMainId<MainThreadWindowShape>('MainThreadWindow'),
MainThreadLabelService: createMainId<MainThreadLabelServiceShape>('MainThreadLabelService')
MainThreadLabelService: createMainId<MainThreadLabelServiceShape>('MainThreadLabelService'),
MainThreadTunnelService: createMainId<MainThreadTunnelServiceShape>('MainThreadTunnelService')
};
export const ExtHostContext = {
@@ -1469,5 +1482,6 @@ export const ExtHostContext = {
ExtHostStorage: createMainId<ExtHostStorageShape>('ExtHostStorage'),
ExtHostUrls: createExtId<ExtHostUrlsShape>('ExtHostUrls'),
ExtHostOutputService: createMainId<ExtHostOutputServiceShape>('ExtHostOutputService'),
ExtHosLabelService: createMainId<ExtHostLabelServiceShape>('ExtHostLabelService')
ExtHosLabelService: createMainId<ExtHostLabelServiceShape>('ExtHostLabelService'),
ExtHostTunnelService: createMainId<ExtHostTunnelServiceShape>('ExtHostTunnelService')
};

View File

@@ -27,6 +27,7 @@ export class ApiCommandArgument<V, O = V> {
static readonly Uri = new ApiCommandArgument<URI>('uri', 'Uri of a text document', v => URI.isUri(v), v => v);
static readonly Position = new ApiCommandArgument<types.Position, IPosition>('position', 'A position in a text document', v => types.Position.isPosition(v), typeConverters.Position.from);
static readonly Range = new ApiCommandArgument<types.Range, IRange>('range', 'A range in a text document', v => types.Range.isRange(v), typeConverters.Range.from);
static readonly CallHierarchyItem = new ApiCommandArgument('item', 'A call hierarchy item', v => v instanceof types.CallHierarchyItem, typeConverters.CallHierarchyItem.to);
@@ -42,7 +43,7 @@ export class ApiCommandResult<V, O = V> {
constructor(
readonly description: string,
readonly convert: (v: V) => O
readonly convert: (v: V, apiArgs: any[]) => O
) { }
}
@@ -68,7 +69,7 @@ export class ApiCommand {
});
const internalResult = await commands.executeCommand(this.internalId, ...internalArgs);
return this.result.convert(internalResult);
return this.result.convert(internalResult, apiArgs);
}, undefined, this._getCommandHandlerDesc());
}
@@ -83,6 +84,123 @@ export class ApiCommand {
const newCommands: ApiCommand[] = [
// -- document highlights
new ApiCommand(
'vscode.executeDocumentHighlights', '_executeDocumentHighlights', 'Execute document highlight provider.',
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
new ApiCommandResult<modes.DocumentHighlight[], types.DocumentHighlight[] | undefined>('A promise that resolves to an array of SymbolInformation and DocumentSymbol instances.', tryMapWith(typeConverters.DocumentHighlight.to))
),
// -- document symbols
new ApiCommand(
'vscode.executeDocumentSymbolProvider', '_executeDocumentSymbolProvider', 'Execute document symbol provider.',
[ApiCommandArgument.Uri],
new ApiCommandResult<modes.DocumentSymbol[], vscode.SymbolInformation[] | undefined>('A promise that resolves to an array of DocumentHighlight-instances.', (value, apiArgs) => {
if (isFalsyOrEmpty(value)) {
return undefined;
}
class MergedInfo extends types.SymbolInformation implements vscode.DocumentSymbol {
static to(symbol: modes.DocumentSymbol): MergedInfo {
const res = new MergedInfo(
symbol.name,
typeConverters.SymbolKind.to(symbol.kind),
symbol.containerName || '',
new types.Location(apiArgs[0], typeConverters.Range.to(symbol.range))
);
res.detail = symbol.detail;
res.range = res.location.range;
res.selectionRange = typeConverters.Range.to(symbol.selectionRange);
res.children = symbol.children ? symbol.children.map(MergedInfo.to) : [];
return res;
}
detail!: string;
range!: vscode.Range;
selectionRange!: vscode.Range;
children!: vscode.DocumentSymbol[];
containerName!: string;
}
return value.map(MergedInfo.to);
})
),
// -- formatting
new ApiCommand(
'vscode.executeFormatDocumentProvider', '_executeFormatDocumentProvider', 'Execute document format provider.',
[ApiCommandArgument.Uri, new ApiCommandArgument('options', 'Formatting options', _ => true, v => v)],
new ApiCommandResult<ISingleEditOperation[], types.TextEdit[] | undefined>('A promise that resolves to an array of TextEdits.', tryMapWith(typeConverters.TextEdit.to))
),
new ApiCommand(
'vscode.executeFormatRangeProvider', '_executeFormatRangeProvider', 'Execute range format provider.',
[ApiCommandArgument.Uri, ApiCommandArgument.Range, new ApiCommandArgument('options', 'Formatting options', _ => true, v => v)],
new ApiCommandResult<ISingleEditOperation[], types.TextEdit[] | undefined>('A promise that resolves to an array of TextEdits.', tryMapWith(typeConverters.TextEdit.to))
),
new ApiCommand(
'vscode.executeFormatOnTypeProvider', '_executeFormatOnTypeProvider', 'Execute format on type provider.',
[ApiCommandArgument.Uri, ApiCommandArgument.Position, new ApiCommandArgument('ch', 'Trigger character', v => typeof v === 'string', v => v), new ApiCommandArgument('options', 'Formatting options', _ => true, v => v)],
new ApiCommandResult<ISingleEditOperation[], types.TextEdit[] | undefined>('A promise that resolves to an array of TextEdits.', tryMapWith(typeConverters.TextEdit.to))
),
// -- go to symbol (definition, type definition, declaration, impl, references)
new ApiCommand(
'vscode.executeDefinitionProvider', '_executeDefinitionProvider', 'Execute all definition provider.',
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
),
new ApiCommand(
'vscode.executeTypeDefinitionProvider', '_executeTypeDefinitionProvider', 'Execute all type definition providers.',
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
),
new ApiCommand(
'vscode.executeDeclarationProvider', '_executeDeclarationProvider', 'Execute all declaration providers.',
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
),
new ApiCommand(
'vscode.executeImplementationProvider', '_executeImplementationProvider', 'Execute all implementation providers.',
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
),
new ApiCommand(
'vscode.executeReferenceProvider', '_executeReferenceProvider', 'Execute all reference providers.',
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
),
// -- hover
new ApiCommand(
'vscode.executeHoverProvider', '_executeHoverProvider', 'Execute all hover provider.',
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
new ApiCommandResult<modes.Hover[], types.Hover[] | undefined>('A promise that resolves to an array of Hover-instances.', tryMapWith(typeConverters.Hover.to))
),
// -- selection range
new ApiCommand(
'vscode.executeSelectionRangeProvider', '_executeSelectionRangeProvider', 'Execute selection range provider.',
[ApiCommandArgument.Uri, new ApiCommandArgument('position', 'A positions in a text document', v => Array.isArray(v) && v.every(v => types.Position.isPosition(v)), v => v.map(typeConverters.Position.from))],
new ApiCommandResult<IRange[][], types.SelectionRange[]>('A promise that resolves to an array of ranges.', result => {
return result.map(ranges => {
let node: types.SelectionRange | undefined;
for (const range of ranges.reverse()) {
node = new types.SelectionRange(typeConverters.Range.to(range), node);
}
return node!;
});
})
),
// -- symbol search
new ApiCommand(
'vscode.executeWorkspaceSymbolProvider', '_executeWorkspaceSymbolProvider', 'Execute all workspace symbol provider.',
[new ApiCommandArgument('query', 'Search string', v => typeof v === 'string', v => v)],
new ApiCommandResult<[search.IWorkspaceSymbolProvider, search.IWorkspaceSymbol[]][], types.SymbolInformation[]>('A promise that resolves to an array of SymbolInformation-instances.', value => {
const result: types.SymbolInformation[] = [];
if (Array.isArray(value)) {
for (let tuple of value) {
result.push(...tuple[1].map(typeConverters.WorkspaceSymbol.to));
}
}
return result;
})
),
// --- call hierarchy
new ApiCommand(
'vscode.prepareCallHierarchy', '_executePrepareCallHierarchy', 'Prepare call hierarchy at a position inside a document',
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
@@ -121,68 +239,6 @@ export class ExtHostApiCommands {
}
registerCommands() {
this._register('vscode.executeWorkspaceSymbolProvider', this._executeWorkspaceSymbolProvider, {
description: 'Execute all workspace symbol provider.',
args: [{ name: 'query', description: 'Search string', constraint: String }],
returns: 'A promise that resolves to an array of SymbolInformation-instances.'
});
this._register('vscode.executeDefinitionProvider', this._executeDefinitionProvider, {
description: 'Execute all definition provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
],
returns: 'A promise that resolves to an array of Location-instances.'
});
this._register('vscode.executeDeclarationProvider', this._executeDeclaraionProvider, {
description: 'Execute all declaration provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
],
returns: 'A promise that resolves to an array of Location-instances.'
});
this._register('vscode.executeTypeDefinitionProvider', this._executeTypeDefinitionProvider, {
description: 'Execute all type definition providers.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
],
returns: 'A promise that resolves to an array of Location-instances.'
});
this._register('vscode.executeImplementationProvider', this._executeImplementationProvider, {
description: 'Execute all implementation providers.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
],
returns: 'A promise that resolves to an array of Location-instance.'
});
this._register('vscode.executeHoverProvider', this._executeHoverProvider, {
description: 'Execute all hover provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
],
returns: 'A promise that resolves to an array of Hover-instances.'
});
this._register('vscode.executeDocumentHighlights', this._executeDocumentHighlights, {
description: 'Execute document highlight provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position in a text document', constraint: types.Position }
],
returns: 'A promise that resolves to an array of DocumentHighlight-instances.'
});
this._register('vscode.executeReferenceProvider', this._executeReferenceProvider, {
description: 'Execute reference provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position in a text document', constraint: types.Position }
],
returns: 'A promise that resolves to an array of Location-instances.'
});
this._register('vscode.executeDocumentRenameProvider', this._executeDocumentRenameProvider, {
description: 'Execute rename provider.',
args: [
@@ -201,13 +257,6 @@ export class ExtHostApiCommands {
],
returns: 'A promise that resolves to SignatureHelp.'
});
this._register('vscode.executeDocumentSymbolProvider', this._executeDocumentSymbolProvider, {
description: 'Execute document symbol provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI }
],
returns: 'A promise that resolves to an array of SymbolInformation and DocumentSymbol instances.'
});
this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider, {
description: 'Execute completion item provider.',
args: [
@@ -235,33 +284,7 @@ export class ExtHostApiCommands {
],
returns: 'A promise that resolves to an array of CodeLens-instances.'
});
this._register('vscode.executeFormatDocumentProvider', this._executeFormatDocumentProvider, {
description: 'Execute document format provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'options', description: 'Formatting options' }
],
returns: 'A promise that resolves to an array of TextEdits.'
});
this._register('vscode.executeFormatRangeProvider', this._executeFormatRangeProvider, {
description: 'Execute range format provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'range', description: 'Range in a text document', constraint: types.Range },
{ name: 'options', description: 'Formatting options' }
],
returns: 'A promise that resolves to an array of TextEdits.'
});
this._register('vscode.executeFormatOnTypeProvider', this._executeFormatOnTypeProvider, {
description: 'Execute document format provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position in a text document', constraint: types.Position },
{ name: 'ch', description: 'Character that got typed', constraint: String },
{ name: 'options', description: 'Formatting options' }
],
returns: 'A promise that resolves to an array of TextEdits.'
});
this._register('vscode.executeLinkProvider', this._executeDocumentLinkProvider, {
description: 'Execute document link provider.',
args: [
@@ -284,14 +307,6 @@ export class ExtHostApiCommands {
],
returns: 'A promise that resolves to an array of ColorPresentation objects.'
});
this._register('vscode.executeSelectionRangeProvider', this._executeSelectionRangeProvider, {
description: 'Execute selection range provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'positions', description: 'Positions in a text document', constraint: Array.isArray }
],
returns: 'A promise that resolves to an array of ranges.'
});
// -----------------------------------------------------------------
// The following commands are registered on both sides separately.
@@ -362,87 +377,6 @@ export class ExtHostApiCommands {
this._disposables.add(disposable);
}
/**
* Execute workspace symbol provider.
*
* @param query Search string to match query symbol names
* @return A promise that resolves to an array of symbol information.
*/
private _executeWorkspaceSymbolProvider(query: string): Promise<types.SymbolInformation[]> {
return this._commands.executeCommand<[search.IWorkspaceSymbolProvider, search.IWorkspaceSymbol[]][]>('_executeWorkspaceSymbolProvider', { query }).then(value => {
const result: types.SymbolInformation[] = [];
if (Array.isArray(value)) {
for (let tuple of value) {
result.push(...tuple[1].map(typeConverters.WorkspaceSymbol.to));
}
}
return result;
});
}
private _executeDefinitionProvider(resource: URI, position: types.Position): Promise<types.Location[] | undefined> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
};
return this._commands.executeCommand<modes.Location[]>('_executeDefinitionProvider', args)
.then(tryMapWith(typeConverters.location.to));
}
private _executeDeclaraionProvider(resource: URI, position: types.Position): Promise<types.Location[] | undefined> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
};
return this._commands.executeCommand<modes.Location[]>('_executeDeclarationProvider', args)
.then(tryMapWith(typeConverters.location.to));
}
private _executeTypeDefinitionProvider(resource: URI, position: types.Position): Promise<types.Location[] | undefined> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
};
return this._commands.executeCommand<modes.Location[]>('_executeTypeDefinitionProvider', args)
.then(tryMapWith(typeConverters.location.to));
}
private _executeImplementationProvider(resource: URI, position: types.Position): Promise<types.Location[] | undefined> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
};
return this._commands.executeCommand<modes.Location[]>('_executeImplementationProvider', args)
.then(tryMapWith(typeConverters.location.to));
}
private _executeHoverProvider(resource: URI, position: types.Position): Promise<types.Hover[] | undefined> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
};
return this._commands.executeCommand<modes.Hover[]>('_executeHoverProvider', args)
.then(tryMapWith(typeConverters.Hover.to));
}
private _executeDocumentHighlights(resource: URI, position: types.Position): Promise<types.DocumentHighlight[] | undefined> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
};
return this._commands.executeCommand<modes.DocumentHighlight[]>('_executeDocumentHighlights', args)
.then(tryMapWith(typeConverters.DocumentHighlight.to));
}
private _executeReferenceProvider(resource: URI, position: types.Position): Promise<types.Location[] | undefined> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
};
return this._commands.executeCommand<modes.Location[]>('_executeReferenceProvider', args)
.then(tryMapWith(typeConverters.location.to));
}
private _executeDocumentRenameProvider(resource: URI, position: types.Position, newName: string): Promise<types.WorkspaceEdit> {
const args = {
resource,
@@ -502,24 +436,6 @@ export class ExtHostApiCommands {
});
}
private _executeSelectionRangeProvider(resource: URI, positions: types.Position[]): Promise<vscode.SelectionRange[]> {
const pos = positions.map(typeConverters.Position.from);
const args = {
resource,
position: pos[0],
positions: pos
};
return this._commands.executeCommand<IRange[][]>('_executeSelectionRangeProvider', args).then(result => {
return result.map(ranges => {
let node: types.SelectionRange | undefined;
for (const range of ranges.reverse()) {
node = new types.SelectionRange(typeConverters.Range.to(range), node);
}
return node!;
});
});
}
private _executeColorPresentationProvider(color: types.Color, context: { uri: URI, range: types.Range; }): Promise<types.ColorPresentation[]> {
const args = {
resource: context.uri,
@@ -534,38 +450,6 @@ export class ExtHostApiCommands {
});
}
private _executeDocumentSymbolProvider(resource: URI): Promise<vscode.SymbolInformation[] | undefined> {
const args = {
resource
};
return this._commands.executeCommand<modes.DocumentSymbol[]>('_executeDocumentSymbolProvider', args).then((value): vscode.SymbolInformation[] | undefined => {
if (isFalsyOrEmpty(value)) {
return undefined;
}
class MergedInfo extends types.SymbolInformation implements vscode.DocumentSymbol {
static to(symbol: modes.DocumentSymbol): MergedInfo {
const res = new MergedInfo(
symbol.name,
typeConverters.SymbolKind.to(symbol.kind),
symbol.containerName || '',
new types.Location(resource, typeConverters.Range.to(symbol.range))
);
res.detail = symbol.detail;
res.range = res.location.range;
res.selectionRange = typeConverters.Range.to(symbol.selectionRange);
res.children = symbol.children ? symbol.children.map(MergedInfo.to) : [];
return res;
}
detail!: string;
range!: vscode.Range;
selectionRange!: vscode.Range;
children!: vscode.DocumentSymbol[];
containerName!: string;
}
return value.map(MergedInfo.to);
});
}
private _executeCodeActionProvider(resource: URI, rangeOrSelection: types.Range | types.Selection, kind?: string): Promise<(vscode.CodeAction | vscode.Command | undefined)[] | undefined> {
const args = {
@@ -610,36 +494,6 @@ export class ExtHostApiCommands {
}
private _executeFormatDocumentProvider(resource: URI, options: vscode.FormattingOptions): Promise<vscode.TextEdit[] | undefined> {
const args = {
resource,
options
};
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatDocumentProvider', args)
.then(tryMapWith(edit => new types.TextEdit(typeConverters.Range.to(edit.range), edit.text)));
}
private _executeFormatRangeProvider(resource: URI, range: types.Range, options: vscode.FormattingOptions): Promise<vscode.TextEdit[] | undefined> {
const args = {
resource,
range: typeConverters.Range.from(range),
options
};
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatRangeProvider', args)
.then(tryMapWith(edit => new types.TextEdit(typeConverters.Range.to(edit.range), edit.text)));
}
private _executeFormatOnTypeProvider(resource: URI, position: types.Position, ch: string, options: vscode.FormattingOptions): Promise<vscode.TextEdit[] | undefined> {
const args = {
resource,
position: typeConverters.Position.from(position),
ch,
options
};
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatOnTypeProvider', args)
.then(tryMapWith(edit => new types.TextEdit(typeConverters.Range.to(edit.range), edit.text)));
}
private _executeDocumentLinkProvider(resource: URI): Promise<vscode.DocumentLink[] | undefined> {
return this._commands.executeCommand<modes.ILink[]>('_executeLinkProvider', resource)
.then(tryMapWith(typeConverters.DocumentLink.to));

View File

@@ -13,6 +13,7 @@ import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { ExtHostTextEditor } from 'vs/workbench/api/common/extHostTextEditor';
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import { ILogService } from 'vs/platform/log/common/log';
export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsShape {
@@ -35,6 +36,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
constructor(
@IExtHostRpcService private readonly _extHostRpc: IExtHostRpcService,
@ILogService private readonly _logService: ILogService
) { }
$acceptDocumentsAndEditorsDelta(delta: IDocumentsAndEditorsDelta): void {
@@ -92,8 +94,9 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
const documentData = this._documents.get(resource.toString())!;
const editor = new ExtHostTextEditor(
this._extHostRpc.getProxy(MainContext.MainThreadTextEditors),
data.id,
this._extHostRpc.getProxy(MainContext.MainThreadTextEditors),
this._logService,
documentData,
data.selections.map(typeConverters.Selection.to),
data.options,

View File

@@ -32,6 +32,7 @@ import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitData
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
interface ITestRunner {
/** Old test runner API, as exported from `vscode/lib/testrunner` */
@@ -76,6 +77,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
protected readonly _extHostWorkspace: ExtHostWorkspace;
protected readonly _extHostConfiguration: ExtHostConfiguration;
protected readonly _logService: ILogService;
protected readonly _extHostTunnelService: IExtHostTunnelService;
protected readonly _mainThreadWorkspaceProxy: MainThreadWorkspaceShape;
protected readonly _mainThreadTelemetryProxy: MainThreadTelemetryShape;
@@ -104,7 +106,8 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
@IExtHostConfiguration extHostConfiguration: IExtHostConfiguration,
@ILogService logService: ILogService,
@IExtHostInitDataService initData: IExtHostInitDataService,
@IExtensionStoragePaths storagePath: IExtensionStoragePaths
@IExtensionStoragePaths storagePath: IExtensionStoragePaths,
@IExtHostTunnelService extHostTunnelService: IExtHostTunnelService
) {
this._hostUtils = hostUtils;
this._extHostContext = extHostContext;
@@ -113,6 +116,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
this._extHostWorkspace = extHostWorkspace;
this._extHostConfiguration = extHostConfiguration;
this._logService = logService;
this._extHostTunnelService = extHostTunnelService;
this._disposables = new DisposableStore();
this._mainThreadWorkspaceProxy = this._extHostContext.getProxy(MainContext.MainThreadWorkspace);
@@ -652,6 +656,8 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
extensionHostEnv: result.extensionHostEnv
};
await this._extHostTunnelService.addDetected(result.detectedTunnels);
return {
type: 'ok',
value: {

View File

@@ -389,7 +389,7 @@ class CodeActionAdapter {
edit: candidate.edit && typeConvert.WorkspaceEdit.from(candidate.edit),
kind: candidate.kind && candidate.kind.value,
isPreferred: candidate.isPreferred,
disabled: candidate.disabled
disabled: candidate.disabled?.reason
});
}
}
@@ -740,11 +740,16 @@ class SuggestAdapter {
private _cache = new Cache<vscode.CompletionItem>('CompletionItem');
private _disposables = new Map<number, DisposableStore>();
private _didWarnMust: boolean = false;
private _didWarnShould: boolean = false;
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _commands: CommandsConverter,
private readonly _provider: vscode.CompletionItemProvider,
private readonly _logService: ILogService
private readonly _logService: ILogService,
private readonly _telemetry: extHostProtocol.MainThreadTelemetryShape,
private readonly _extensionId: ExtensionIdentifier
) { }
provideCompletionItems(resource: URI, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<extHostProtocol.ISuggestResultDto | undefined> {
@@ -809,12 +814,37 @@ class SuggestAdapter {
return Promise.resolve(undefined);
}
const _mustNotChange = SuggestAdapter._mustNotChangeHash(item);
const _mayNotChange = SuggestAdapter._mayNotChangeHash(item);
return asPromise(() => this._provider.resolveCompletionItem!(item, token)).then(resolvedItem => {
if (!resolvedItem) {
return undefined;
}
type BlameExtension = {
extensionId: string;
kind: string
};
type BlameExtensionMeta = {
extensionId: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' };
kind: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' };
};
if (!this._didWarnMust && _mustNotChange !== SuggestAdapter._mustNotChangeHash(resolvedItem)) {
this._logService.warn(`[${this._extensionId.value}] INVALID result from 'resolveCompletionItem', extension MUST NOT change any of: label, sortText, filterText, insertText, or textEdit`);
this._telemetry.$publicLog2<BlameExtension, BlameExtensionMeta>('resolveCompletionItem/invalid', { extensionId: this._extensionId.value, kind: 'must' });
this._didWarnMust = true;
}
if (!this._didWarnShould && _mayNotChange !== SuggestAdapter._mayNotChangeHash(resolvedItem)) {
this._logService.info(`[${this._extensionId.value}] UNSAVE result from 'resolveCompletionItem', extension SHOULD NOT change any of: additionalTextEdits, or command`);
this._telemetry.$publicLog2<BlameExtension, BlameExtensionMeta>('resolveCompletionItem/invalid', { extensionId: this._extensionId.value, kind: 'should' });
this._didWarnShould = true;
}
const pos = typeConvert.Position.to(position);
return this._convertCompletionItem(resolvedItem, pos, id);
});
@@ -908,6 +938,16 @@ class SuggestAdapter {
private static _isValidRangeForCompletion(range: vscode.Range, position: vscode.Position): boolean {
return range.isSingleLine || range.start.line === position.line;
}
private static _mustNotChangeHash(item: vscode.CompletionItem) {
const args = [item.label, item.sortText, item.filterText, item.insertText, item.range, item.range2];
const res = JSON.stringify(args);
return res;
}
private static _mayNotChangeHash(item: vscode.CompletionItem) {
return JSON.stringify([item.additionalTextEdits, item.command]);
}
}
class SignatureHelpAdapter {
@@ -1253,7 +1293,8 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
private static _handlePool: number = 0;
private readonly _uriTransformer: IURITransformer | null;
private _proxy: extHostProtocol.MainThreadLanguageFeaturesShape;
private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape;
private readonly _telemetryShape: extHostProtocol.MainThreadTelemetryShape;
private _documents: ExtHostDocuments;
private _commands: ExtHostCommands;
private _diagnostics: ExtHostDiagnostics;
@@ -1270,6 +1311,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
) {
this._uriTransformer = uriTransformer;
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadLanguageFeatures);
this._telemetryShape = mainContext.getProxy(extHostProtocol.MainContext.MainThreadTelemetry);
this._documents = documents;
this._commands = commands;
this._diagnostics = diagnostics;
@@ -1584,7 +1626,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
// --- suggestion
registerCompletionItemProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider, this._logService), extension);
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider, this._logService, this._telemetryShape, extension.identifier), extension);
this._proxy.$registerSuggestSupport(handle, this._transformDocumentSelector(selector), triggerCharacters, SuggestAdapter.supportsResolving(provider), extension.identifier);
return this._createDisposable(handle);
}

View File

@@ -9,7 +9,7 @@ import { ProgressLocation } from './extHostTypeConverters';
import { Progress, IProgressStep } from 'vs/platform/progress/common/progress';
import { localize } from 'vs/nls';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import { debounce } from 'vs/base/common/decorators';
import { throttle } from 'vs/base/common/decorators';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
export class ExtHostProgress implements ExtHostProgressShape {
@@ -85,7 +85,7 @@ class ProgressCallback extends Progress<IProgressStep> {
super(p => this.throttledReport(p));
}
@debounce(100, (result: IProgressStep, currentValue: IProgressStep) => mergeProgress(result, currentValue), () => Object.create(null))
@throttle(100, (result: IProgressStep, currentValue: IProgressStep) => mergeProgress(result, currentValue), () => Object.create(null))
throttledReport(p: IProgressStep): void {
this._proxy.$progressReport(this._handle, p);
}

View File

@@ -14,6 +14,7 @@ import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData
import * as TypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import { EndOfLine, Position, Range, Selection, SnippetString, TextEditorLineNumbersStyle, TextEditorRevealType } from 'vs/workbench/api/common/extHostTypes';
import * as vscode from 'vscode';
import { ILogService } from 'vs/platform/log/common/log';
export class TextEditorDecorationType implements vscode.TextEditorDecorationType {
@@ -133,23 +134,11 @@ export class TextEditorEdit {
}
}
function deprecated(name: string, message: string = 'Refer to the documentation for further details.') {
return (target: Object, key: string, descriptor: TypedPropertyDescriptor<any>) => {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.warn(`[Deprecation Warning] method '${name}' is deprecated and should no longer be used. ${message}`);
return originalMethod.apply(this, args);
};
return descriptor;
};
}
export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
private _proxy: MainThreadTextEditorsShape;
private _id: string;
private _logService: ILogService;
private _tabSize!: number;
private _indentSize!: number;
@@ -157,10 +146,11 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
private _cursorStyle!: TextEditorCursorStyle;
private _lineNumbers!: TextEditorLineNumbersStyle;
constructor(proxy: MainThreadTextEditorsShape, id: string, source: IResolvedTextEditorConfiguration) {
constructor(proxy: MainThreadTextEditorsShape, id: string, source: IResolvedTextEditorConfiguration, logService: ILogService) {
this._proxy = proxy;
this._id = id;
this._accept(source);
this._logService = logService;
}
public _accept(source: IResolvedTextEditorConfiguration): void {
@@ -207,7 +197,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
// reflect the new tabSize value immediately
this._tabSize = tabSize;
}
warnOnError(this._proxy.$trySetOptions(this._id, {
this._warnOnError(this._proxy.$trySetOptions(this._id, {
tabSize: tabSize
}));
}
@@ -248,7 +238,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
// reflect the new indentSize value immediately
this._indentSize = indentSize;
}
warnOnError(this._proxy.$trySetOptions(this._id, {
this._warnOnError(this._proxy.$trySetOptions(this._id, {
indentSize: indentSize
}));
}
@@ -274,7 +264,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
// reflect the new insertSpaces value immediately
this._insertSpaces = insertSpaces;
}
warnOnError(this._proxy.$trySetOptions(this._id, {
this._warnOnError(this._proxy.$trySetOptions(this._id, {
insertSpaces: insertSpaces
}));
}
@@ -289,7 +279,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
return;
}
this._cursorStyle = value;
warnOnError(this._proxy.$trySetOptions(this._id, {
this._warnOnError(this._proxy.$trySetOptions(this._id, {
cursorStyle: value
}));
}
@@ -304,7 +294,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
return;
}
this._lineNumbers = value;
warnOnError(this._proxy.$trySetOptions(this._id, {
this._warnOnError(this._proxy.$trySetOptions(this._id, {
lineNumbers: TypeConverters.TextEditorLineNumbersStyle.from(value)
}));
}
@@ -369,15 +359,17 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
}
if (hasUpdate) {
warnOnError(this._proxy.$trySetOptions(this._id, bulkConfigurationUpdate));
this._warnOnError(this._proxy.$trySetOptions(this._id, bulkConfigurationUpdate));
}
}
private _warnOnError(promise: Promise<any>): void {
promise.catch(err => this._logService.warn(err));
}
}
export class ExtHostTextEditor implements vscode.TextEditor {
private readonly _proxy: MainThreadTextEditorsShape;
private readonly _id: string;
private readonly _documentData: ExtHostDocumentData;
private _selections: Selection[];
@@ -387,18 +379,17 @@ export class ExtHostTextEditor implements vscode.TextEditor {
private _disposed: boolean = false;
private _hasDecorationsForKey: { [key: string]: boolean; };
get id(): string { return this._id; }
constructor(
proxy: MainThreadTextEditorsShape, id: string, document: ExtHostDocumentData,
readonly id: string,
private readonly _proxy: MainThreadTextEditorsShape,
private readonly _logService: ILogService,
document: ExtHostDocumentData,
selections: Selection[], options: IResolvedTextEditorConfiguration,
visibleRanges: Range[], viewColumn: vscode.ViewColumn | undefined
) {
this._proxy = proxy;
this._id = id;
this._documentData = document;
this._selections = selections;
this._options = new ExtHostTextEditorOptions(this._proxy, this._id, options);
this._options = new ExtHostTextEditorOptions(this._proxy, this.id, options, _logService);
this._visibleRanges = visibleRanges;
this._viewColumn = viewColumn;
this._hasDecorationsForKey = Object.create(null);
@@ -409,12 +400,12 @@ export class ExtHostTextEditor implements vscode.TextEditor {
this._disposed = true;
}
@deprecated('TextEditor.show') show(column: vscode.ViewColumn) {
this._proxy.$tryShowEditor(this._id, TypeConverters.ViewColumn.from(column));
show(column: vscode.ViewColumn) {
this._proxy.$tryShowEditor(this.id, TypeConverters.ViewColumn.from(column));
}
@deprecated('TextEditor.hide') hide() {
this._proxy.$tryHideEditor(this._id);
hide() {
this._proxy.$tryHideEditor(this.id);
}
// ---- the document
@@ -515,7 +506,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
() => {
if (TypeConverters.isDecorationOptionsArr(ranges)) {
return this._proxy.$trySetDecorations(
this._id,
this.id,
decorationType.key,
TypeConverters.fromRangeOrRangeWithMessage(ranges)
);
@@ -529,7 +520,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
_ranges[4 * i + 3] = range.end.character + 1;
}
return this._proxy.$trySetDecorationsFast(
this._id,
this.id,
decorationType.key,
_ranges
);
@@ -541,7 +532,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
revealRange(range: Range, revealType: vscode.TextEditorRevealType): void {
this._runOnProxy(
() => this._proxy.$tryRevealRange(
this._id,
this.id,
TypeConverters.Range.from(range),
(revealType || TextEditorRevealType.Default)
)
@@ -550,7 +541,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
private _trySetSelection(): Promise<vscode.TextEditor | null | undefined> {
const selection = this._selections.map(TypeConverters.Selection.from);
return this._runOnProxy(() => this._proxy.$trySetSelections(this._id, selection));
return this._runOnProxy(() => this._proxy.$trySetSelections(this.id, selection));
}
_acceptSelections(selections: Selection[]): void {
@@ -616,7 +607,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
};
});
return this._proxy.$tryApplyEdits(this._id, editData.documentVersionId, edits, {
return this._proxy.$tryApplyEdits(this.id, editData.documentVersionId, edits, {
setEndOfLine: typeof editData.setEndOfLine === 'number' ? TypeConverters.EndOfLine.from(editData.setEndOfLine) : undefined,
undoStopBefore: editData.undoStopBefore,
undoStopAfter: editData.undoStopAfter
@@ -650,27 +641,22 @@ export class ExtHostTextEditor implements vscode.TextEditor {
}
}
return this._proxy.$tryInsertSnippet(this._id, snippet.value, ranges, options);
return this._proxy.$tryInsertSnippet(this.id, snippet.value, ranges, options);
}
// ---- util
private _runOnProxy(callback: () => Promise<any>): Promise<ExtHostTextEditor | undefined | null> {
if (this._disposed) {
console.warn('TextEditor is closed/disposed');
this._logService.warn('TextEditor is closed/disposed');
return Promise.resolve(undefined);
}
return callback().then(() => this, err => {
if (!(err instanceof Error && err.name === 'DISPOSED')) {
console.warn(err);
this._logService.warn(err);
}
return null;
});
}
}
function warnOnError(promise: Promise<any>): void {
promise.then(undefined, (err) => {
console.warn(err);
});
}

View File

@@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtHostTunnelServiceShape, MainThreadTunnelServiceShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import * as vscode from 'vscode';
import { Disposable } from 'vs/base/common/lifecycle';
export interface TunnelOptions {
remote: { port: number, host: string };
localPort?: number;
name?: string;
closeable?: boolean;
}
export interface TunnelDto {
remote: { port: number, host: string };
localAddress: string;
}
export interface IExtHostTunnelService extends ExtHostTunnelServiceShape {
readonly _serviceBrand: undefined;
makeTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined>;
addDetected(tunnels: { remote: { port: number, host: string }, localAddress: string }[] | undefined): Promise<void>;
}
export const IExtHostTunnelService = createDecorator<IExtHostTunnelService>('IExtHostTunnelService');
export class ExtHostTunnelService extends Disposable implements IExtHostTunnelService {
readonly _serviceBrand: undefined;
private readonly _proxy: MainThreadTunnelServiceShape;
constructor(
@IExtHostRpcService extHostRpc: IExtHostRpcService
) {
super();
this._proxy = extHostRpc.getProxy(MainContext.MainThreadTunnelService);
}
async makeTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
const tunnel = await this._proxy.$openTunnel(forward);
if (tunnel) {
const disposableTunnel: vscode.Tunnel = {
remote: tunnel.remote,
localAddress: tunnel.localAddress,
dispose: () => {
return this._proxy.$closeTunnel(tunnel.remote.port);
}
};
this._register(disposableTunnel);
return disposableTunnel;
}
return undefined;
}
async addDetected(tunnels: { remote: { port: number, host: string }, localAddress: string }[] | undefined): Promise<void> {
if (tunnels) {
return this._proxy.$addDetected(tunnels);
}
}
}

View File

@@ -309,7 +309,7 @@ export namespace MarkdownString {
}
export function to(value: htmlContent.IMarkdownString): vscode.MarkdownString {
return new htmlContent.MarkdownString(value.value, value.isTrusted);
return new htmlContent.MarkdownString(value.value, { isTrusted: value.isTrusted, supportThemeIcons: value.supportThemeIcons });
}
export function fromStrict(value: string | types.MarkdownString): undefined | string | htmlContent.IMarkdownString {

View File

@@ -14,6 +14,7 @@ import { generateUuid } from 'vs/base/common/uuid';
import * as vscode from 'vscode';
import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/platform/files/common/files';
import { RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { markdownUnescapeCodicons, escapeCodicons } from 'vs/base/common/codicons';
function es5ClassCompat(target: Function): any {
///@ts-ignore
@@ -1231,21 +1232,26 @@ export class MarkdownString {
value: string;
isTrusted?: boolean;
readonly supportThemeIcons?: boolean;
constructor(value?: string) {
this.value = value || '';
constructor(value?: string, { supportThemeIcons }: { supportThemeIcons?: boolean } = {}) {
this.value = value ?? '';
this.supportThemeIcons = supportThemeIcons ?? false;
}
appendText(value: string): MarkdownString {
// escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
this.value += value
value = value
.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&')
.replace('\n', '\n\n');
this.value += this.supportThemeIcons ? markdownUnescapeCodicons(value) : value;
return this;
}
appendMarkdown(value: string): MarkdownString {
this.value += value;
return this;
}
@@ -1257,6 +1263,10 @@ export class MarkdownString {
this.value += '\n```\n';
return this;
}
static escapeThemeIcons(value: string): string {
return escapeCodicons(value);
}
}
@es5ClassCompat

View File

@@ -59,8 +59,4 @@ export class ExtHostUrls implements ExtHostUrlsShape {
async createAppUri(uri: URI): Promise<vscode.Uri> {
return URI.revive(await this._proxy.$createAppUri(uri));
}
async proposedCreateAppUri(extensionId: ExtensionIdentifier, options?: vscode.AppUriOptions): Promise<vscode.Uri> {
return URI.revive(await this._proxy.$proposedCreateAppUri(extensionId, options));
}
}

View File

@@ -339,11 +339,6 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
if (folders.length === 0) {
return undefined;
}
if (folders.length > 1) {
return undefined;
}
// #54483 @Joh Why are we still using fsPath?
return folders[0].uri.fsPath;
}