提交 a6435b1c 编写于 作者: J Johannes Rieken

add CodeLensProvider#onDidUpdateCodeLenses, #10648

上级 7ad16683
......@@ -647,6 +647,7 @@ export interface ICodeLensSymbol {
command?: Command;
}
export interface CodeLensProvider {
onDidChange?: Event<this>;
provideCodeLenses(model: editorCommon.IReadOnlyModel, token: CancellationToken): ICodeLensSymbol[] | Thenable<ICodeLensSymbol[]>;
resolveCodeLens?(model: editorCommon.IReadOnlyModel, codeLens: ICodeLensSymbol, token: CancellationToken): ICodeLensSymbol | Thenable<ICodeLensSymbol>;
}
......
......@@ -8,7 +8,7 @@
import 'vs/css!./codelens';
import { RunOnceScheduler, asWinJsPromise } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Disposables, IDisposable, dispose } from 'vs/base/common/lifecycle';
import Severity from 'vs/base/common/severity';
import { format, escape } from 'vs/base/common/strings';
import { TPromise } from 'vs/base/common/winjs.base';
......@@ -17,8 +17,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
import { IMessageService } from 'vs/platform/message/common/message';
import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { CodeLensProviderRegistry, ICodeLensSymbol, Command } from 'vs/editor/common/modes';
import { IModelService } from 'vs/editor/common/services/modelService';
import { CodeLensProviderRegistry, CodeLensProvider, ICodeLensSymbol, Command } from 'vs/editor/common/modes';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { ICodeLensData, getCodeLensData } from '../common/codelens';
......@@ -157,33 +156,6 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
}
}
function modelsVersionId(modelService: IModelService, modeId: string): number {
let result = 1;
let models = modelService.getModels()
.filter(model => model.getMode().getId() === modeId)
.map((model) => {
return {
url: model.uri.toString(),
versionId: model.getVersionId()
};
})
.sort((a, b) => {
if (a.url < b.url) {
return -1;
}
if (a.url > b.url) {
return 1;
}
return 0;
});
for (let i = 0; i < models.length; i++) {
result = (((31 * result) | 0) + models[i].versionId) | 0;
}
return result;
}
interface IDecorationIdCallback {
(decorationId: string): void;
}
......@@ -215,7 +187,6 @@ class CodeLensHelper {
this._addDecorationsCallbacks[i](resultingDecorations[i]);
}
}
}
class CodeLens {
......@@ -226,7 +197,6 @@ class CodeLens {
private _decorationIds: string[];
private _data: ICodeLensData[];
private _editor: editorBrowser.ICodeEditor;
private _lastUpdateModelsVersionId: number;
public constructor(data: ICodeLensData[], editor: editorBrowser.ICodeEditor,
helper: CodeLensHelper,
......@@ -258,8 +228,6 @@ class CodeLens {
this._viewZoneId = viewZoneChangeAccessor.addZone(this._viewZone);
this._editor.addContentWidget(this._contentWidget);
this._lastUpdateModelsVersionId = -1;
}
public dispose(helper: CodeLensHelper, viewZoneChangeAccessor: editorBrowser.IViewZoneChangeAccessor): void {
......@@ -296,16 +264,12 @@ class CodeLens {
});
}
public computeIfNecessary(currentModelsVersionId: number, model: editorCommon.IModel): ICodeLensData[] {
public computeIfNecessary(model: editorCommon.IModel): ICodeLensData[] {
this._contentWidget.updateVisibility(); // trigger the fade in
if (!this._contentWidget.isVisible()) {
return null;
}
if (this._lastUpdateModelsVersionId === currentModelsVersionId) {
return null;
}
// Read editor current state
for (let i = 0; i < this._decorationIds.length; i++) {
this._data[i].symbol.range = model.getDecorationRange(this._decorationIds[i]);
......@@ -313,9 +277,8 @@ class CodeLens {
return this._data;
}
public updateCommands(symbols: ICodeLensSymbol[], currentModelsVersionId: number): void {
public updateCommands(symbols: ICodeLensSymbol[]): void {
this._contentWidget.withCommands(symbols);
this._lastUpdateModelsVersionId = currentModelsVersionId;
}
public getLineNumber(): number {
......@@ -355,7 +318,6 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
constructor(
private _editor: editorBrowser.ICodeEditor,
@IModelService private _modelService: IModelService,
@ICommandService private _commandService: ICommandService,
@IMessageService private _messageService: IMessageService
) {
......@@ -419,9 +381,29 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
return;
}
const providerSubscriptions = new Disposables();
this._localToDispose.push(providerSubscriptions);
const onEvent = () => {
providerSubscriptions.dispose();
scheduler.schedule();
};
const subscribeToProviders = (result: ICodeLensData[]) => {
const seen = new Set<CodeLensProvider>();
for (const {provider} of result) {
if (provider.onDidChange && !seen.has(provider)) {
providerSubscriptions.add(provider.onDidChange(onEvent));
seen.add(provider);
}
}
};
const detectVisible = new RunOnceScheduler(() => {
this._onViewportChanged(model.getMode().getId());
}, 500);
const scheduler = new RunOnceScheduler(() => {
if (this._currentFindCodeLensSymbolsPromise) {
this._currentFindCodeLensSymbolsPromise.cancel();
......@@ -433,6 +415,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
this._currentFindCodeLensSymbolsPromise.then((result) => {
if (counterValue === this._modelChangeCounter) { // only the last one wins
this.renderCodeLensSymbols(result);
subscribeToProviders(result);
detectVisible.schedule();
}
}, (error) => {
......@@ -590,12 +573,10 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
return;
}
const currentModelsVersionId = modelsVersionId(this._modelService, modeId);
const toResolve: ICodeLensData[][] = [];
const lenses: CodeLens[] = [];
this._lenses.forEach((lens) => {
const request = lens.computeIfNecessary(currentModelsVersionId, model);
const request = lens.computeIfNecessary(model);
if (request) {
toResolve.push(request);
lenses.push(lens);
......@@ -618,7 +599,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
});
return TPromise.join(promises).then(() => {
lenses[i].updateCommands(resolvedSymbols, currentModelsVersionId);
lenses[i].updateCommands(resolvedSymbols);
});
});
......
......@@ -4658,6 +4658,7 @@ declare module monaco.languages {
}
export interface CodeLensProvider {
onDidChange?: IEvent<this>;
provideCodeLenses(model: editor.IReadOnlyModel, token: CancellationToken): ICodeLensSymbol[] | Thenable<ICodeLensSymbol[]>;
resolveCodeLens?(model: editor.IReadOnlyModel, codeLens: ICodeLensSymbol, token: CancellationToken): ICodeLensSymbol | Thenable<ICodeLensSymbol>;
}
......
......@@ -1613,6 +1613,11 @@ declare module 'vscode' {
*/
export interface CodeLensProvider {
/**
* An optional event to signal that the code lenses from this provider have changed.
*/
onDidChangeCodeLenses?: Event<this>;
/**
* Compute a list of [lenses](#CodeLens). This call should return as fast as possible and if
* computing the commands is expensive implementors should only return code lens objects with the
......
......@@ -150,7 +150,8 @@ export abstract class MainThreadErrorsShape {
export abstract class MainThreadLanguageFeaturesShape {
$unregister(handle: number): TPromise<any> { throw ni(); }
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): TPromise<any> { throw ni(); }
$emitCodeLensEvent(eventHandle: number, event?: any): TPromise<any> { throw ni(); }
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
......
......@@ -677,9 +677,18 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
const handle = this._nextHandle();
const eventHandle = typeof provider.onDidChangeCodeLenses === 'function' ? this._nextHandle() : undefined;
this._adapter[handle] = new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider);
this._proxy.$registerCodeLensSupport(handle, selector);
return this._createDisposable(handle);
this._proxy.$registerCodeLensSupport(handle, selector, eventHandle);
let result = this._createDisposable(handle);
if (eventHandle !== undefined) {
const subscription = provider.onDidChangeCodeLenses(_ => this._proxy.$emitCodeLensEvent(eventHandle));
result = Disposable.from(result, subscription);
}
return result;
}
$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]> {
......
......@@ -6,6 +6,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import * as vscode from 'vscode';
import { IReadOnlyModel, ISingleEditOperation } from 'vs/editor/common/editorCommon';
......@@ -57,15 +58,32 @@ export class MainThreadLanguageFeatures extends MainThreadLanguageFeaturesShape
// --- code lens
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.CodeLensProviderRegistry.register(selector, <modes.CodeLensProvider>{
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): TPromise<any> {
const provider = <modes.CodeLensProvider>{
provideCodeLenses: (model: IReadOnlyModel, token: CancellationToken): modes.ICodeLensSymbol[] | Thenable<modes.ICodeLensSymbol[]> => {
return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideCodeLenses(handle, model.uri)));
},
resolveCodeLens: (model: IReadOnlyModel, codeLens: modes.ICodeLensSymbol, token: CancellationToken): modes.ICodeLensSymbol | Thenable<modes.ICodeLensSymbol> => {
return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$resolveCodeLens(handle, model.uri, codeLens)));
}
});
};
if (typeof eventHandle === 'number') {
const emitter = new Emitter<modes.CodeLensProvider>();
this._registrations[eventHandle] = emitter;
provider.onDidChange = emitter.event;
}
this._registrations[handle] = modes.CodeLensProviderRegistry.register(selector, provider);
return undefined;
}
$emitCodeLensEvent(eventHandle: number, event?: any): TPromise<any> {
const obj = this._registrations[eventHandle];
if (obj instanceof Emitter) {
obj.fire(event);
}
return undefined;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册