提交 44b75883 编写于 作者: J Johannes Rieken

remove getNamedCustomer, connect MainThreadWebview with CodeInsetController

上级 aa204b03
......@@ -51,7 +51,7 @@ declare module 'vscode' {
export interface CodeInsetProvider {
onDidChangeCodeInsets?: Event<void>;
provideCodeInsets(document: TextDocument, token: CancellationToken): ProviderResult<CodeInset[]>;
resolveCodeInset?(codeInset: CodeInset, webview: Webview, token: CancellationToken): ProviderResult<CodeInset>;
resolveCodeInset(codeInset: CodeInset, webview: Webview, token: CancellationToken): ProviderResult<CodeInset>;
}
export namespace languages {
......
......@@ -8,7 +8,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { ExtHostContext, ExtHostWebviewsShape, IExtHostContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelShowOptions } from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostContext, ExtHostWebviewsShape, IExtHostContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelShowOptions, WebviewInsetHandle } from 'vs/workbench/api/node/extHost.protocol';
import { editorGroupToViewColumn, EditorViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/shared/editor';
import { WebviewEditor } from 'vs/workbench/contrib/webview/electron-browser/webviewEditor';
import { WebviewEditorInput } from 'vs/workbench/contrib/webview/electron-browser/webviewEditorInput';
......@@ -21,7 +21,11 @@ import { extHostNamedCustomer } from './extHostCustomers';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { WebviewElement } from 'vs/workbench/contrib/webview/electron-browser/webviewElement';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { CodeInsetController } from 'vs/workbench/contrib/codeinset/codeInset.contribution';
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
@extHostNamedCustomer(MainContext.MainThreadWebviews)
export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviver {
......@@ -38,6 +42,7 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
private readonly _proxy: ExtHostWebviewsShape;
private readonly _webviews = new Map<WebviewPanelHandle, WebviewEditorInput>();
private readonly _webviewsElements = new Map<WebviewInsetHandle, WebviewElement>();
private readonly _revivers = new Set<string>();
private _activeWebview: WebviewPanelHandle | undefined = undefined;
......@@ -50,7 +55,10 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
@IWebviewEditorService private readonly _webviewService: IWebviewEditorService,
@IOpenerService private readonly _openerService: IOpenerService,
@IExtensionService private readonly _extensionService: IExtensionService,
@ITelemetryService private readonly _telemetryService: ITelemetryService
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ICodeEditorService private readonly _codeEditorService: ICodeEditorService,
@IPartService private readonly _partService: IPartService,
) {
this._proxy = context.getProxy(ExtHostContext.ExtHostWebviews);
_editorService.onDidActiveEditorChange(this.onActiveEditorChanged, this, this._toDispose);
......@@ -67,7 +75,7 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
this._toDispose = dispose(this._toDispose);
}
public $createWebview(
public $createWebviewPanel(
handle: WebviewPanelHandle,
viewType: string,
title: string,
......@@ -99,21 +107,42 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
this._telemetryService.publicLog('webviews:createWebviewPanel', { extensionId: extensionId.value });
}
public createInsetWebview(
handle: WebviewPanelHandle,
parent: HTMLElement,
options: WebviewInputOptions,
extensionLocation: UriComponents
): WebviewEditorInput {
const webview = this._webviewService.createInsetWebview(parent, reviveWebviewOptions(options), URI.revive(extensionLocation), this.createWebviewEventDelegate(handle));
webview.state = {
viewType: webview.viewType,
state: undefined
};
$createWebviewCodeInset(handle: WebviewInsetHandle, symbolId: string, options: vscode.WebviewOptions, extensionLocation: UriComponents): void {
// todo@joh main is for the lack of a code-inset service
// which we maybe wanna have... this is how it now works
// 1) create webview element
// 2) find the code inset controller that request it
// 3) let the controller adopt the widget
// 4) continue to forward messages to the webview
const webview = this._instantiationService.createInstance(
WebviewElement,
this._partService.getContainer(Parts.EDITOR_PART),
{
useSameOriginForRoot: true,
extensionLocation: URI.revive(extensionLocation)
},
{
allowScripts: options.enableScripts
}
);
let found = false;
for (const editor of this._codeEditorService.listCodeEditors()) {
const ctrl = CodeInsetController.get(editor);
if (ctrl && ctrl.acceptWebview(symbolId, webview)) {
found = true;
break;
}
}
this._webviews.set(handle, webview);
this._activeWebview = handle;
return webview;
if (!found) {
webview.dispose();
return;
}
// this will leak... the adopted webview will be disposed by the
// code inset controller. we might need a dispose-event here so that
// we can clean up things.
this._webviewsElements.set(handle, webview);
}
public $disposeWebview(handle: WebviewPanelHandle): void {
......@@ -131,14 +160,22 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
webview.iconPath = reviveWebviewIcon(value);
}
public $setHtml(handle: WebviewPanelHandle, value: string): void {
const webview = this.getWebview(handle);
webview.html = value;
public $setHtml(handle: WebviewPanelHandle | WebviewInsetHandle, value: string): void {
if (typeof handle === 'number') {
this._webviewsElements.get(handle).contents = value;
} else {
const webview = this.getWebview(handle);
webview.html = value;
}
}
public $setOptions(handle: WebviewPanelHandle, options: vscode.WebviewOptions): void {
const webview = this.getWebview(handle);
webview.setOptions(reviveWebviewOptions(options));
public $setOptions(handle: WebviewPanelHandle | WebviewInsetHandle, options: vscode.WebviewOptions): void {
if (typeof handle === 'number') {
this._webviewsElements.get(handle).options = reviveWebviewOptions(options);
} else {
const webview = this.getWebview(handle);
webview.setOptions(reviveWebviewOptions(options));
}
}
public $reveal(handle: WebviewPanelHandle, showOptions: WebviewPanelShowOptions): void {
......@@ -152,18 +189,24 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
this._webviewService.revealWebview(webview, targetGroup || this._editorGroupService.getGroup(webview.group), !!showOptions.preserveFocus);
}
public $postMessage(handle: WebviewPanelHandle, message: any): Promise<boolean> {
const webview = this.getWebview(handle);
const editors = this._editorService.visibleControls
.filter(e => e instanceof WebviewEditor)
.map(e => e as WebviewEditor)
.filter(e => e.input!.matches(webview));
public $postMessage(handle: WebviewPanelHandle | WebviewInsetHandle, message: any): Promise<boolean> {
if (typeof handle === 'number') {
this._webviewsElements.get(handle).sendMessage(message);
return Promise.resolve(true);
for (const editor of editors) {
editor.sendMessage(message);
}
} else {
const webview = this.getWebview(handle);
const editors = this._editorService.visibleControls
.filter(e => e instanceof WebviewEditor)
.map(e => e as WebviewEditor)
.filter(e => e.input!.matches(webview));
for (const editor of editors) {
editor.sendMessage(message);
}
return Promise.resolve(editors.length > 0);
return Promise.resolve(editors.length > 0);
}
}
public $registerSerializer(viewType: string): void {
......
......@@ -478,7 +478,7 @@ export function createApiFactory(
return extHostOutputService.createOutputChannel(name);
},
createWebviewPanel(viewType: string, title: string, showOptions: vscode.ViewColumn | { viewColumn: vscode.ViewColumn, preserveFocus?: boolean }, options: vscode.WebviewPanelOptions & vscode.WebviewOptions): vscode.WebviewPanel {
return extHostWebviews.createWebview(extension, viewType, title, showOptions, options);
return extHostWebviews.createWebviewPanel(extension, viewType, title, showOptions, options);
},
createTerminal(nameOrOptions: vscode.TerminalOptions | string, shellPath?: string, shellArgs?: string[]): vscode.Terminal {
if (typeof nameOrOptions === 'object') {
......
......@@ -469,20 +469,24 @@ export interface MainThreadTelemetryShape extends IDisposable {
export type WebviewPanelHandle = string;
export type WebviewInsetHandle = number;
export interface WebviewPanelShowOptions {
readonly viewColumn?: EditorViewColumn;
readonly preserveFocus?: boolean;
}
export interface MainThreadWebviewsShape extends IDisposable {
$createWebview(handle: WebviewPanelHandle, viewType: string, title: string, showOptions: WebviewPanelShowOptions, options: vscode.WebviewPanelOptions & vscode.WebviewOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): void;
$createWebviewPanel(handle: WebviewPanelHandle, viewType: string, title: string, showOptions: WebviewPanelShowOptions, options: vscode.WebviewPanelOptions & vscode.WebviewOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): void;
$createWebviewCodeInset(handle: WebviewInsetHandle, symbolId: string, options: vscode.WebviewOptions, extensionLocation: UriComponents): void;
$disposeWebview(handle: WebviewPanelHandle): void;
$reveal(handle: WebviewPanelHandle, showOptions: WebviewPanelShowOptions): void;
$setTitle(handle: WebviewPanelHandle, value: string): void;
$setIconPath(handle: WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents } | undefined): void;
$setHtml(handle: WebviewPanelHandle, value: string): void;
$setOptions(handle: WebviewPanelHandle, options: vscode.WebviewOptions): void;
$postMessage(handle: WebviewPanelHandle, value: any): Promise<boolean>;
$setHtml(handle: WebviewPanelHandle | WebviewInsetHandle, value: string): void;
$setOptions(handle: WebviewPanelHandle | WebviewInsetHandle, options: vscode.WebviewOptions): void;
$postMessage(handle: WebviewPanelHandle | WebviewInsetHandle, value: any): Promise<boolean>;
$registerSerializer(viewType: string): void;
$unregisterSerializer(viewType: string): void;
......
......@@ -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 } from './extHost.protocol';
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 './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';
......@@ -28,6 +28,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { ExtHostWebview } from 'vs/workbench/api/node/extHostWebview';
import * as codeInset from 'vs/workbench/contrib/codeinset/codeInset';
import { generateUuid } from 'vs/base/common/uuid';
// --- adapter
......@@ -154,38 +155,33 @@ class CodeInsetAdapter {
private readonly _provider: vscode.CodeInsetProvider
) { }
provideCodeInsets(resource: URI, token: CancellationToken): Promise<codeInset.ICodeInsetSymbol[]> {
provideCodeInsets(resource: URI, token: CancellationToken): Promise<CodeInsetDto[]> {
const doc = this._documents.getDocumentData(resource).document;
return asPromise(() => this._provider.provideCodeInsets(doc, token)).then(insets => {
if (Array.isArray(insets)) {
return insets.map(inset => {
const id = this._heapService.keep(inset);
return ObjectIdentifier.mixin({
const $ident = this._heapService.keep(inset);
const id = generateUuid();
return {
$ident,
id,
range: typeConvert.Range.from(inset.range),
height: inset.height
}, id);
};
});
} else {
return undefined;
}
return undefined;
});
}
resolveCodeInset(symbol: codeInset.ICodeInsetSymbol, webview: vscode.Webview, token: CancellationToken): Promise<codeInset.ICodeInsetSymbol> {
resolveCodeInset(symbol: CodeInsetDto, webview: vscode.Webview, token: CancellationToken): Promise<CodeInsetDto> {
const inset = this._heapService.get<vscode.CodeInset>(ObjectIdentifier.of(symbol));
if (!inset) {
return undefined;
}
let resolve: Promise<vscode.CodeInset>;
if (typeof this._provider.resolveCodeInset !== 'function') {
resolve = Promise.resolve(inset);
} else {
resolve = asPromise(() => this._provider.resolveCodeInset(inset, webview, token));
return Promise.resolve(symbol);
}
return resolve.then(newInset => {
return asPromise(() => this._provider.resolveCodeInset(inset, webview, token)).then(newInset => {
newInset = newInset || inset;
return symbol;
});
......@@ -1057,7 +1053,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return ExtHostLanguageFeatures._handlePool++;
}
private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A) => Promise<R>): Promise<R> {
private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A, extenson: IExtensionDescription) => Promise<R>): Promise<R> {
const data = this._adapter.get(handle);
if (!data) {
return Promise.reject(new Error('no adapter found'));
......@@ -1069,7 +1065,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
t1 = Date.now();
this._logService.trace(`[${data.extension.identifier.value}] INVOKE provider '${(ctor as any).name}'`);
}
let p = callback(data.adapter);
let p = callback(data.adapter, data.extension);
const extension = data.extension;
if (extension) {
Promise.resolve(p).then(
......@@ -1156,14 +1152,13 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, CodeInsetAdapter, adapter => adapter.provideCodeInsets(URI.revive(resource), token));
}
$resolveCodeInset(handle: number, resource: UriComponents, symbol: codeInset.ICodeInsetSymbol, token: CancellationToken): Promise<codeInset.ICodeInsetSymbol> {
const webview = new ExtHostWebview(symbol.webviewHandle, this._webviewProxy, { enableScripts: true });
webview.html = '<html><body></body></html>';
const x = this._withAdapter(handle, CodeInsetAdapter, adapter => adapter.resolveCodeInset(symbol, webview, token));
return x;
}
$createCodeInsetWebview(handle: number) {
$resolveCodeInset(handle: number, _resource: UriComponents, symbol: codeInset.ICodeInsetSymbol, token: CancellationToken): Promise<codeInset.ICodeInsetSymbol> {
const webviewHandle = Math.random();
const webview = new ExtHostWebview(webviewHandle, this._webviewProxy, { enableScripts: true });
return this._withAdapter(handle, CodeInsetAdapter, async (adapter, extension) => {
await this._webviewProxy.$createWebviewCodeInset(webviewHandle, symbol.id, { enableCommandUris: true, enableScripts: true }, extension.extensionLocation);
return adapter.resolveCodeInset(symbol, webview, token);
});
}
// --- declaration
......
......@@ -8,14 +8,14 @@ import { URI } from 'vs/base/common/uri';
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import { EditorViewColumn } from 'vs/workbench/api/shared/editor';
import * as vscode from 'vscode';
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelViewState } from './extHost.protocol';
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelViewState, WebviewInsetHandle } from './extHost.protocol';
import { Disposable } from './extHostTypes';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
type IconPath = URI | { light: URI, dark: URI };
export class ExtHostWebview implements vscode.Webview {
private readonly _handle: WebviewPanelHandle;
private readonly _handle: WebviewPanelHandle | WebviewInsetHandle;
private readonly _proxy: MainThreadWebviewsShape;
private _html: string;
private _options: vscode.WebviewOptions;
......@@ -25,7 +25,7 @@ export class ExtHostWebview implements vscode.Webview {
public readonly onDidReceiveMessage: Event<any> = this._onMessageEmitter.event;
constructor(
handle: WebviewPanelHandle,
handle: WebviewPanelHandle | WebviewInsetHandle,
proxy: MainThreadWebviewsShape,
options: vscode.WebviewOptions
) {
......@@ -243,7 +243,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
this._proxy = mainContext.getProxy(MainContext.MainThreadWebviews);
}
public createWebview(
public createWebviewPanel(
extension: IExtensionDescription,
viewType: string,
title: string,
......@@ -257,7 +257,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
};
const handle = ExtHostWebviews.newHandle();
this._proxy.$createWebview(handle, viewType, title, webviewShowOptions, options, extension.identifier, extension.extensionLocation);
this._proxy.$createWebviewPanel(handle, viewType, title, webviewShowOptions, options, extension.identifier, extension.extensionLocation);
const webview = new ExtHostWebview(handle, this._proxy, options);
const panel = new ExtHostWebviewPanel(handle, this._proxy, viewType, title, viewColumn, options, webview);
......
......@@ -12,18 +12,19 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
import { IModelDecorationsChangeAccessor } from 'vs/editor/common/model';
import { CodeInsetProviderRegistry, getCodeInsetData, ICodeInsetData } from './codeInset';
import { CodeInsetWidget, CodeInsetHelper } from './codeInsetWidget';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { MainThreadWebviews } from 'vs/workbench/api/electron-browser/mainThreadWebview';
import { Registry } from 'vs/platform/registry/common/platform';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { localize } from 'vs/nls.mock';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { WebviewElement } from 'vs/workbench/contrib/webview/electron-browser/webviewElement';
export class CodeInsetController implements editorCommon.IEditorContribution {
static get(editor: editorBrowser.ICodeEditor): CodeInsetController {
return editor.getContribution(CodeInsetController.ID);
}
private static readonly ID: string = 'css.editor.codeInset';
private _isEnabled: boolean;
......@@ -31,17 +32,14 @@ export class CodeInsetController implements editorCommon.IEditorContribution {
private _globalToDispose: IDisposable[];
private _localToDispose: IDisposable[];
private _insetWidgets: CodeInsetWidget[];
private _pendingWebviews = new Map<string, (element: WebviewElement) => any>();
private _currentFindCodeInsetSymbolsPromise: CancelablePromise<ICodeInsetData[]>;
private _modelChangeCounter: number;
private _currentResolveCodeInsetSymbolsPromise: CancelablePromise<any>;
private _detectVisibleInsets: RunOnceScheduler;
private _mainThreadWebviews: MainThreadWebviews;
constructor(
private _editor: editorBrowser.ICodeEditor,
@ICommandService private readonly _commandService: ICommandService,
@INotificationService private readonly _notificationService: INotificationService,
@IExtensionService private readonly _extensionService: IExtensionService,
@IConfigurationService private readonly _configService: IConfigurationService,
) {
this._isEnabled = this._configService.getValue<boolean>('editor.codeInsets');
......@@ -72,6 +70,15 @@ export class CodeInsetController implements editorCommon.IEditorContribution {
this._globalToDispose = dispose(this._globalToDispose);
}
acceptWebview(symbolId: string, webviewElement: WebviewElement): boolean {
if (this._pendingWebviews.has(symbolId)) {
this._pendingWebviews.get(symbolId)(webviewElement);
this._pendingWebviews.delete(symbolId);
return true;
}
return false;
}
private _localDispose(): void {
if (this._currentFindCodeInsetSymbolsPromise) {
this._currentFindCodeInsetSymbolsPromise.cancel();
......@@ -239,11 +246,11 @@ export class CodeInsetController implements editorCommon.IEditorContribution {
groupsIndex++;
codeInsetIndex++;
} else {
this._insetWidgets.splice(codeInsetIndex, 0,
new CodeInsetWidget(groups[groupsIndex],
this._editor, helper,
this._commandService, this._notificationService,
() => this._detectVisibleInsets.schedule()));
this._insetWidgets.splice(
codeInsetIndex,
0,
new CodeInsetWidget(groups[groupsIndex], this._editor, helper)
);
codeInsetIndex++;
groupsIndex++;
}
......@@ -257,11 +264,10 @@ export class CodeInsetController implements editorCommon.IEditorContribution {
// Create extra symbols
while (groupsIndex < groups.length) {
this._insetWidgets.push(
new CodeInsetWidget(groups[groupsIndex],
this._editor, helper,
this._commandService, this._notificationService,
() => this._detectVisibleInsets.schedule()));
this._insetWidgets.push(new CodeInsetWidget(
groups[groupsIndex],
this._editor, helper
));
groupsIndex++;
}
......@@ -272,15 +278,6 @@ export class CodeInsetController implements editorCommon.IEditorContribution {
scrollState.restore(this._editor);
}
private getWebviewService(): MainThreadWebviews {
if (!this._mainThreadWebviews) {
this._mainThreadWebviews = this._extensionService.getNamedCustomer('MainThreadWebviews');
}
return this._mainThreadWebviews;
}
private _onViewportChanged(): void {
if (this._currentResolveCodeInsetSymbolsPromise) {
this._currentResolveCodeInsetSymbolsPromise.cancel();
......@@ -311,13 +308,18 @@ export class CodeInsetController implements editorCommon.IEditorContribution {
const allPromises = allWidgetRequests.map((widgetRequests, r) => {
const widgetPromises = widgetRequests.map(request => {
const symbol = request.symbol;
if (!symbol.webviewHandle && typeof request.provider.resolveCodeInset === 'function') {
const mainThreadWebviews = this.getWebviewService();
symbol.webviewHandle = insetWidgets[r].createWebview(mainThreadWebviews, request.provider.extensionLocation);
return request.provider.resolveCodeInset(model, symbol, token);
if (request.resolved) {
return Promise.resolve(void 0);
}
return Promise.resolve(void 0);
let a = new Promise(resolve => {
this._pendingWebviews.set(request.symbol.id, element => {
request.resolved = true;
insetWidgets[r].adoptWebview(element);
resolve();
});
});
let b = request.provider.resolveCodeInset(model, request.symbol, token);
return Promise.all([a, b]);
});
return Promise.all(widgetPromises);
......
......@@ -16,17 +16,16 @@ import { ProviderResult } from 'vs/editor/common/modes';
import { IRange } from 'vs/editor/common/core/range';
export interface ICodeInsetSymbol {
id: string;
range: IRange;
id?: string;
height?: number;
webviewHandle?: string;
}
export interface CodeInsetProvider {
onDidChange?: Event<this>;
extensionLocation: UriComponents;
provideCodeInsets(model: ITextModel, token: CancellationToken): ProviderResult<ICodeInsetSymbol[]>;
resolveCodeInset?(model: ITextModel, codeInset: ICodeInsetSymbol, token: CancellationToken): ProviderResult<ICodeInsetSymbol>;
resolveCodeInset(model: ITextModel, codeInset: ICodeInsetSymbol, token: CancellationToken): ProviderResult<ICodeInsetSymbol>;
}
export const CodeInsetProviderRegistry = new LanguageFeatureRegistry<CodeInsetProvider>();
......@@ -34,6 +33,7 @@ export const CodeInsetProviderRegistry = new LanguageFeatureRegistry<CodeInsetPr
export interface ICodeInsetData {
symbol: ICodeInsetSymbol;
provider: CodeInsetProvider;
resolved?: boolean;
}
export function getCodeInsetData(model: ITextModel, token: CancellationToken): Promise<ICodeInsetData[]> {
......
......@@ -4,16 +4,12 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./codeInsetWidget';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { Range } from 'vs/editor/common/core/range';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { ICodeInsetData } from './codeInset';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
import { IModelDeltaDecoration, IModelDecorationsChangeAccessor, ITextModel } from 'vs/editor/common/model';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { WebviewEditorInput } from 'vs/workbench/contrib/webview/electron-browser/webviewEditorInput';
import { MainThreadWebviews } from 'vs/workbench/api/electron-browser/mainThreadWebview';
import { UriComponents } from 'vs/base/common/uri';
import { WebviewElement } from 'vs/workbench/contrib/webview/electron-browser/webviewElement';
export interface IDecorationIdCallback {
......@@ -52,21 +48,17 @@ export class CodeInsetHelper {
export class CodeInsetWidget {
private readonly _editor: editorBrowser.ICodeEditor;
private _webview: WebviewElement;
private _viewZone: editorBrowser.IViewZone;
private _viewZoneId?: number = undefined;
private _decorationIds: string[];
private _data: ICodeInsetData[];
private _webview: WebviewEditorInput | undefined;
private _webviewHandle: string | undefined;
private _range: Range;
constructor(
data: ICodeInsetData[], // all the insets on the same line (often just one)
editor: editorBrowser.ICodeEditor,
helper: CodeInsetHelper,
commandService: ICommandService,
notificationService: INotificationService,
updateCallabck: Function
helper: CodeInsetHelper
) {
this._editor = editor;
this._data = data;
......@@ -89,7 +81,6 @@ export class CodeInsetWidget {
}
public dispose(helper: CodeInsetHelper, viewZoneChangeAccessor: editorBrowser.IViewZoneChangeAccessor): void {
console.log('DISPOSE');
while (this._decorationIds.length) {
helper.removeDecoration(this._decorationIds.pop());
}
......@@ -97,6 +88,9 @@ export class CodeInsetWidget {
viewZoneChangeAccessor.removeZone(this._viewZoneId);
this._viewZone = undefined;
}
if (this._webview) {
this._webview.dispose();
}
}
public isValid(): boolean {
......@@ -140,25 +134,17 @@ export class CodeInsetWidget {
return -1;
}
public get webview() { return this._webview; }
static webviewPool = 1;
public createWebview(mainThreadWebviews: MainThreadWebviews, extensionLocation: UriComponents) {
if (this._webviewHandle) { return this._webviewHandle; }
public adoptWebview(webview: WebviewElement): void {
const lineNumber = this._range.endLineNumber;
this._editor.changeViewZones(accessor => {
if (this._viewZoneId) {
this._webview.dispose();
accessor.removeZone(this._viewZoneId);
this._webview.dispose();
}
const div = document.createElement('div');
this._webviewHandle = CodeInsetWidget.webviewPool++ + '';
this._webview = mainThreadWebviews.createInsetWebview(this._webviewHandle, div, { enableScripts: true }, extensionLocation);
const webview = this._webview.webview;
const div = document.createElement('div');
webview.mountTo(div);
webview.onMessage((e: { type: string, payload: any }) => {
// The webview contents can use a "size-info" message to report its size.
......@@ -170,15 +156,14 @@ export class CodeInsetWidget {
});
}
});
this._viewZone = {
afterLineNumber: lineNumber,
heightInPx: 50,
domNode: div
};
this._viewZoneId = accessor.addZone(this._viewZone);
this._webview = webview;
});
return this._webviewHandle;
}
public reposition(viewZoneChangeAccessor: editorBrowser.IViewZoneChangeAccessor): void {
......
......@@ -12,8 +12,6 @@ import * as vscode from 'vscode';
import { WebviewEditorInput } from './webviewEditorInput';
import { GroupIdentifier } from 'vs/workbench/common/editor';
import { equals } from 'vs/base/common/arrays';
import { WebviewElement } from 'vs/workbench/contrib/webview/electron-browser/webviewElement';
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
export const IWebviewEditorService = createDecorator<IWebviewEditorService>('webviewEditorService');
......@@ -34,13 +32,6 @@ export interface IWebviewEditorService {
events: WebviewEvents
): WebviewEditorInput;
createInsetWebview(
parent: HTMLElement,
options: vscode.WebviewOptions,
extensionLocation: URI,
events: WebviewEvents
): WebviewEditorInput;
reviveWebview(
viewType: string,
id: number,
......@@ -105,8 +96,7 @@ export class WebviewEditorService implements IWebviewEditorService {
constructor(
@IEditorService private readonly _editorService: IEditorService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService,
@IPartService private readonly _partService: IPartService,
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService
) { }
createWebview(
......@@ -122,21 +112,6 @@ export class WebviewEditorService implements IWebviewEditorService {
return webviewInput;
}
createInsetWebview(
parent: HTMLElement,
options: vscode.WebviewOptions,
extensionLocation: URI,
events: WebviewEvents
): WebviewEditorInput {
const webviewEditorInput = this._instantiationService.createInstance(WebviewEditorInput, 'codeinset', undefined, '', options, {}, events, extensionLocation, undefined);
webviewEditorInput.webview = this._instantiationService.createInstance(WebviewElement,
this._partService.getContainer(Parts.EDITOR_PART),
{ allowSvgs: true, useSameOriginForRoot: true },
{ allowScripts: true, disableFindView: true });
webviewEditorInput.webview.mountTo(parent);
return webviewEditorInput;
}
revealWebview(
webview: WebviewEditorInput,
group: IEditorGroup,
......
......@@ -222,9 +222,6 @@ export interface IExtensionService extends ICpuProfilerTarget {
* Stops the extension host.
*/
stopExtensionHost(): void;
getNamedCustomer?(sid: string): any;
}
export interface ICpuProfilerTarget {
......@@ -285,4 +282,4 @@ export class NullExtensionService implements IExtensionService {
stopExtensionHost(): void { }
canAddExtension(): boolean { return false; }
canRemoveExtension(): boolean { return false; }
}
\ No newline at end of file
}
......@@ -417,11 +417,6 @@ export class ExtensionService extends Disposable implements IExtensionService {
this._stopExtensionHostProcess();
}
public getNamedCustomer(sid: string): any {
const ncs = this._extensionHostProcessManagers.map(m => m.getNamedCustomer(sid)).filter(c => c);
return ncs.length ? ncs[0] : undefined;
}
private _stopExtensionHostProcess(): void {
let previouslyActivatedExtensionIds: ExtensionIdentifier[] = [];
this._extensionHostActiveExtensions.forEach((value) => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册