This commit is contained in:
Johannes Rieken
2019-04-03 14:36:33 +02:00
parent 1ddbe37c23
commit cd7a1069c0
3 changed files with 74 additions and 19 deletions
@@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ITextModel } from 'vs/editor/common/model';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ICodeLensData } from 'vs/editor/contrib/codelens/codelens';
import { LRUCache } from 'vs/base/common/map';
import { ICodeLensSymbol, CodeLensProvider } from 'vs/editor/common/modes';
export const ICodeLensCache = createDecorator<ICodeLensCache>('ICodeLensCache');
export interface ICodeLensCache {
_serviceBrand: any;
put(model: ITextModel, data: ICodeLensData[]): void;
get(model: ITextModel): ICodeLensData[] | undefined;
}
registerSingleton(ICodeLensCache, class implements ICodeLensCache {
_serviceBrand: any;
private readonly _cache = new LRUCache<string, ICodeLensData[]>(15, 0.75);
private readonly _fakeProvider = new class implements CodeLensProvider {
provideCodeLenses(): ICodeLensSymbol[] {
throw new Error('not supported');
}
};
put(model: ITextModel, data: ICodeLensData[]): void {
this._cache.set(this._makeKey(model), data.map(item => {
return {
symbol: item.symbol,
provider: this._fakeProvider
};
}));
}
get(model: ITextModel) {
return this._cache.get(this._makeKey(model));
}
private _makeKey(model: ITextModel): string {
return model.id + model.getVersionId;
}
}, true);
@@ -17,6 +17,7 @@ import { ICodeLensData, getCodeLensData } from 'vs/editor/contrib/codelens/codel
import { CodeLens, CodeLensHelper } from 'vs/editor/contrib/codelens/codelensWidget';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ICodeLensCache } from 'vs/editor/contrib/codelens/codeLensCache';
export class CodeLensContribution implements editorCommon.IEditorContribution {
@@ -35,7 +36,8 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
constructor(
private readonly _editor: editorBrowser.ICodeEditor,
@ICommandService private readonly _commandService: ICommandService,
@INotificationService private readonly _notificationService: INotificationService
@INotificationService private readonly _notificationService: INotificationService,
@ICodeLensCache private readonly _codeLensCache: ICodeLensCache
) {
this._isEnabled = this._editor.getConfiguration().contribInfo.codeLens;
@@ -104,6 +106,11 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
}
}
const cachedLenses = this._codeLensCache.get(model);
if (cachedLenses) {
this._renderCodeLensSymbols(cachedLenses);
}
this._detectVisibleLenses = new RunOnceScheduler(() => {
this._onViewportChanged();
}, 500);
@@ -116,8 +123,9 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
this._currentFindCodeLensSymbolsPromise = createCancelablePromise(token => getCodeLensData(model, token));
this._currentFindCodeLensSymbolsPromise.then((result) => {
this._currentFindCodeLensSymbolsPromise.then(result => {
if (counterValue === this._modelChangeCounter) { // only the last one wins
this._codeLensCache.put(model, result);
this._renderCodeLensSymbols(result);
this._detectVisibleLenses.schedule();
}
@@ -58,13 +58,14 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
private readonly _id: string;
private readonly _domNode: HTMLElement;
private readonly _editor: editorBrowser.ICodeEditor;
private readonly _commands = new Map<string, Command>();
private _widgetPosition: editorBrowser.IContentWidgetPosition;
private _commands: { [id: string]: Command } = Object.create(null);
constructor(
editor: editorBrowser.ICodeEditor,
symbolRange: Range
symbolRange: Range,
data: ICodeLensData[]
) {
this._id = 'codeLensWidget' + (++CodeLensContentWidget._idPool);
this._editor = editor;
@@ -74,9 +75,8 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
this._domNode = document.createElement('span');
this._domNode.innerHTML = '&nbsp;';
dom.addClass(this._domNode, 'codelens-decoration');
dom.addClass(this._domNode, 'invisible-cl');
this.updateHeight();
this.updateVisibility();
this.withCommands(data.map(data => data.symbol), false);
}
updateHeight(): void {
@@ -88,15 +88,9 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
this._domNode.innerHTML = '&nbsp;';
}
updateVisibility(): void {
if (this.isVisible()) {
dom.removeClass(this._domNode, 'invisible-cl');
dom.addClass(this._domNode, 'fadein');
}
}
withCommands(inSymbols: Array<ICodeLensSymbol | undefined | null>, animate: boolean): void {
this._commands.clear();
withCommands(inSymbols: Array<ICodeLensSymbol | undefined | null>): void {
this._commands = Object.create(null);
const symbols = coalesce(inSymbols);
if (isFalsyOrEmpty(symbols)) {
this._domNode.innerHTML = '<span>no commands</span>';
@@ -111,7 +105,7 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
let part: string;
if (command.id) {
part = `<a id=${i}>${title}</a>`;
this._commands[i] = command;
this._commands.set(String(i), command);
} else {
part = `<span>${title}</span>`;
}
@@ -119,13 +113,17 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
}
}
const wasEmpty = this._domNode.innerHTML === '' || this._domNode.innerHTML === '&nbsp;';
this._domNode.innerHTML = html.join('<span>&nbsp;|&nbsp;</span>');
this._editor.layoutContentWidget(this);
if (wasEmpty && animate) {
dom.addClass(this._domNode, 'fadein');
}
}
getCommand(link: HTMLLinkElement): Command | undefined {
return link.parentElement === this._domNode
? this._commands[link.id]
? this._commands.get(link.id)
: undefined;
}
@@ -228,7 +226,7 @@ export class CodeLens {
});
if (range) {
this._contentWidget = new CodeLensContentWidget(editor, range);
this._contentWidget = new CodeLensContentWidget(editor, range, this._data);
this._viewZone = new CodeLensViewZone(range.startLineNumber - 1, updateCallback);
this._viewZoneId = viewZoneChangeAccessor.addZone(this._viewZone);
@@ -273,7 +271,6 @@ export class CodeLens {
}
computeIfNecessary(model: ITextModel): ICodeLensData[] | null {
this._contentWidget.updateVisibility(); // trigger the fade in
if (!this._contentWidget.isVisible()) {
return null;
}
@@ -289,7 +286,7 @@ export class CodeLens {
}
updateCommands(symbols: Array<ICodeLensSymbol | undefined | null>): void {
this._contentWidget.withCommands(symbols);
this._contentWidget.withCommands(symbols, true);
for (let i = 0; i < this._data.length; i++) {
const resolved = symbols[i];
if (resolved) {