Skip to content

Commit

Permalink
Plug-ins leaking CodeLens, etc. #4472
Browse files Browse the repository at this point in the history
Fixes: #4472

Signed-off-by: Victor Rubezhny <vrubezhny@redhat.com>
  • Loading branch information
vrubezhny authored and akosyakov committed Mar 4, 2020
1 parent 8dfde42 commit 02b0969
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 12 deletions.
2 changes: 2 additions & 0 deletions packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1175,8 +1175,10 @@ export interface LanguagesExt {
): Promise<TextEdit[] | undefined>;
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<DocumentLink[] | undefined>;
$resolveDocumentLink(handle: number, link: DocumentLink, token: CancellationToken): Promise<DocumentLink | undefined>;
$releaseDocumentLinks(handle: number, ids: number[]): void;
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<CodeLensSymbol[] | undefined>;
$resolveCodeLens(handle: number, resource: UriComponents, symbol: CodeLensSymbol, token: CancellationToken): Promise<CodeLensSymbol | undefined>;
$releaseCodeLenses(handle: number, ids: number[]): void;
$provideCodeActions(
handle: number,
resource: UriComponents,
Expand Down
9 changes: 7 additions & 2 deletions packages/plugin-ext/src/main/browser/languages-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import { LanguageSelector } from '@theia/languages/lib/common/language-selector'
import { CallHierarchyService, CallHierarchyServiceProvider, Caller, Definition } from '@theia/callhierarchy/lib/browser';
import { toDefinition, toUriComponents, fromDefinition, fromPosition, toCaller } from './callhierarchy/callhierarchy-type-converters';
import { Position, DocumentUri } from 'vscode-languageserver-types';
import { ObjectIdentifier } from '../../common/object-identifier';

@injectable()
export class LanguagesMainImpl implements LanguagesMain, Disposable {
Expand Down Expand Up @@ -380,7 +381,9 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
return {
links: links.map(link => this.toMonacoLink(link)),
dispose: () => {
// TODO this.proxy.$releaseDocumentLinks(handle, links.cacheId);
if (links && Array.isArray(links)) {
this.proxy.$releaseDocumentLinks(handle, links.map(link => ObjectIdentifier.of(link)));
}
}
};
}
Expand Down Expand Up @@ -427,7 +430,9 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
return {
lenses,
dispose: () => {
// TODO this.proxy.$releaseCodeLenses
if (lenses && Array.isArray(lenses)) {
this.proxy.$releaseCodeLenses(handle, lenses.map(symbol => ObjectIdentifier.of(symbol)));
}
}
};
}
Expand Down
9 changes: 9 additions & 0 deletions packages/plugin-ext/src/plugin/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,11 @@ export class LanguagesExtImpl implements LanguagesExt {
this.proxy.$registerDocumentLinkProvider(callId, pluginInfo, this.transformDocumentSelector(selector));
return this.createDisposable(callId);
}

$releaseDocumentLinks(handle: number, ids: number[]): void {
this.withAdapter(handle, LinkProviderAdapter, async adapter => adapter.releaseDocumentLinks(ids));
}

// ### Document Link Provider end

// ### Code Actions Provider begin
Expand Down Expand Up @@ -474,6 +479,10 @@ export class LanguagesExtImpl implements LanguagesExt {
$resolveCodeLens(handle: number, resource: UriComponents, symbol: CodeLensSymbol, token: theia.CancellationToken): Promise<CodeLensSymbol | undefined> {
return this.withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(URI.revive(resource), symbol, token));
}

$releaseCodeLenses(handle: number, ids: number[]): void {
this.withAdapter(handle, CodeLensAdapter, async adapter => adapter.releaseCodeLenses(ids));
}
// ### Code Lens Provider end

// ### Code Reference Provider begin
Expand Down
12 changes: 11 additions & 1 deletion packages/plugin-ext/src/plugin/languages/lens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export class CodeLensAdapter {
range: Converter.fromRange(lens.range)!,
command: this.commands.converter.toSafeCommand(lens.command, toDispose)
}, cacheId);
// TODO: invalidate caches and dispose command handlers
this.cache.set(cacheId, lens);
this.disposables.set(cacheId, toDispose);
return lensSymbol;
Expand Down Expand Up @@ -89,4 +88,15 @@ export class CodeLensAdapter {
symbol.command = this.commands.converter.toSafeCommand(newLens.command ? newLens.command : CodeLensAdapter.BAD_CMD, disposables);
return symbol;
}

releaseCodeLenses(ids: number[]): void {
ids.forEach(id => {
this.cache.delete(id);
const toDispose = this.disposables.get(id);
if (toDispose) {
toDispose.dispose();
this.disposables.delete(id);
}
});
}
}
6 changes: 6 additions & 0 deletions packages/plugin-ext/src/plugin/languages/link-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,10 @@ export class LinkProviderAdapter {
return undefined;
});
}

releaseDocumentLinks(ids: number[]): void {
ids.forEach(id => {
this.cache.delete(id);
});
}
}
11 changes: 2 additions & 9 deletions packages/plugin-ext/src/plugin/tasks/task-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@

import * as theia from '@theia/plugin';
import * as Converter from '../type-converters';
import { ObjectIdentifier } from '../../common/object-identifier';
import { TaskDto } from '../../common';

export class TaskProviderAdapter {
private cacheId = 0;
private cache = new Map<number, theia.Task>();

constructor(private readonly provider: theia.TaskProvider) { }

Expand All @@ -37,9 +34,6 @@ export class TaskProviderAdapter {
continue;
}

const id = this.cacheId++;
ObjectIdentifier.mixin(data, id);
this.cache.set(id, task);
result.push(data);
}
return result;
Expand All @@ -50,9 +44,8 @@ export class TaskProviderAdapter {
if (typeof this.provider.resolveTask !== 'function') {
return Promise.resolve(undefined);
}
const id = ObjectIdentifier.of(task);
const cached = this.cache.get(id);
const item = cached ? cached : Converter.toTask(task);

const item = Converter.toTask(task);
if (!item) {
return Promise.resolve(undefined);
}
Expand Down

0 comments on commit 02b0969

Please sign in to comment.