mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-26 11:38:51 +01:00
debt - no guessing-caching, better use of gc-signals, command converter using gc-signals, main side heap service
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
|
||||
import * as vscode from 'vscode';
|
||||
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
@@ -15,10 +14,10 @@ import { IPosition, IRange, ISingleEditOperation } from 'vs/editor/common/editor
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { IWorkspaceSymbolProvider, IWorkspaceSymbol } from 'vs/workbench/parts/search/common/search';
|
||||
import { asWinJsPromise, ShallowCancelThenPromise } from 'vs/base/common/async';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier } from './extHost.protocol';
|
||||
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
|
||||
|
||||
@@ -44,112 +43,57 @@ class OutlineAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
interface CachedCodeLens {
|
||||
symbols: modes.ICodeLensSymbol[];
|
||||
lenses: vscode.CodeLens[];
|
||||
disposables: IDisposable[];
|
||||
}
|
||||
|
||||
class CodeLensAdapter {
|
||||
|
||||
private static _badCmd: vscode.Command = { command: 'missing', title: '<<MISSING COMMAND>>' };
|
||||
|
||||
private _documents: ExtHostDocuments;
|
||||
private _commands: ExtHostCommands;
|
||||
private _commands: CommandsConverter;
|
||||
private _heapService: ExtHostHeapService;
|
||||
private _provider: vscode.CodeLensProvider;
|
||||
|
||||
private _cache: { [uri: string]: { version: number; data: TPromise<CachedCodeLens>; } } = Object.create(null);
|
||||
|
||||
constructor(documents: ExtHostDocuments, commands: ExtHostCommands, provider: vscode.CodeLensProvider) {
|
||||
constructor(documents: ExtHostDocuments, commands: CommandsConverter, heapService: ExtHostHeapService, provider: vscode.CodeLensProvider) {
|
||||
this._documents = documents;
|
||||
this._commands = commands;
|
||||
this._heapService = heapService;
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
provideCodeLenses(resource: URI): TPromise<modes.ICodeLensSymbol[]> {
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
const version = doc.version;
|
||||
const key = resource.toString();
|
||||
|
||||
// from cache
|
||||
let entry = this._cache[key];
|
||||
if (entry && entry.version === version) {
|
||||
return new ShallowCancelThenPromise(entry.data.then(cached => cached.symbols));
|
||||
}
|
||||
return asWinJsPromise(token => this._provider.provideCodeLenses(doc, token)).then(lenses => {
|
||||
|
||||
const newCodeLensData = asWinJsPromise(token => this._provider.provideCodeLenses(doc, token)).then(lenses => {
|
||||
if (!Array.isArray(lenses)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const data: CachedCodeLens = {
|
||||
lenses,
|
||||
symbols: [],
|
||||
disposables: [],
|
||||
};
|
||||
|
||||
lenses.forEach((lens, i) => {
|
||||
data.symbols.push(<modes.ICodeLensSymbol>{
|
||||
id: String(i),
|
||||
range: TypeConverters.fromRange(lens.range),
|
||||
command: TypeConverters.Command.from(lens.command, data.disposables)
|
||||
if (Array.isArray(lenses)) {
|
||||
return lenses.map(lens => {
|
||||
const id = this._heapService.keep(lens);
|
||||
return ObjectIdentifier.mixin({
|
||||
range: TypeConverters.fromRange(lens.range),
|
||||
command: this._commands.toInternal(lens.command)
|
||||
}, id);
|
||||
});
|
||||
});
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
this._cache[key] = {
|
||||
version,
|
||||
data: newCodeLensData
|
||||
};
|
||||
|
||||
return new ShallowCancelThenPromise(newCodeLensData.then(newCached => {
|
||||
if (entry) {
|
||||
// only now dispose old commands et al
|
||||
entry.data.then(oldCached => dispose(oldCached.disposables));
|
||||
}
|
||||
return newCached && newCached.symbols;
|
||||
}));
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
resolveCodeLens(resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
|
||||
|
||||
const entry = this._cache[resource.toString()];
|
||||
if (!entry) {
|
||||
const lens = this._heapService.get<vscode.CodeLens>(ObjectIdentifier.of(symbol));
|
||||
if (!lens) {
|
||||
return;
|
||||
}
|
||||
|
||||
return entry.data.then(cachedData => {
|
||||
let resolve: TPromise<vscode.CodeLens>;
|
||||
if (typeof this._provider.resolveCodeLens !== 'function' || lens.isResolved) {
|
||||
resolve = TPromise.as(lens);
|
||||
} else {
|
||||
resolve = asWinJsPromise(token => this._provider.resolveCodeLens(lens, token));
|
||||
}
|
||||
|
||||
if (!cachedData) {
|
||||
return;
|
||||
}
|
||||
|
||||
let lens = cachedData.lenses[Number(symbol.id)];
|
||||
if (!lens) {
|
||||
return;
|
||||
}
|
||||
|
||||
let resolve: TPromise<vscode.CodeLens>;
|
||||
if (typeof this._provider.resolveCodeLens !== 'function' || lens.isResolved) {
|
||||
resolve = TPromise.as(lens);
|
||||
} else {
|
||||
resolve = asWinJsPromise(token => this._provider.resolveCodeLens(lens, token));
|
||||
}
|
||||
|
||||
return resolve.then(newLens => {
|
||||
lens = newLens || lens;
|
||||
let command = lens.command;
|
||||
if (!command) {
|
||||
command = {
|
||||
title: '<<MISSING COMMAND>>',
|
||||
command: 'missing',
|
||||
};
|
||||
}
|
||||
|
||||
symbol.command = TypeConverters.Command.from(command, cachedData.disposables);
|
||||
return symbol;
|
||||
});
|
||||
return resolve.then(newLens => {
|
||||
newLens = newLens || lens;
|
||||
symbol.command = this._commands.toInternal(newLens.command || CodeLensAdapter._badCmd);
|
||||
return symbol;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -280,13 +224,11 @@ class ReferenceAdapter {
|
||||
class QuickFixAdapter {
|
||||
|
||||
private _documents: ExtHostDocuments;
|
||||
private _commands: ExtHostCommands;
|
||||
private _commands: CommandsConverter;
|
||||
private _diagnostics: ExtHostDiagnostics;
|
||||
private _provider: vscode.CodeActionProvider;
|
||||
|
||||
private _cachedCommands: IDisposable[][] = [];
|
||||
|
||||
constructor(documents: ExtHostDocuments, commands: ExtHostCommands, diagnostics: ExtHostDiagnostics, provider: vscode.CodeActionProvider) {
|
||||
constructor(documents: ExtHostDocuments, commands: CommandsConverter, diagnostics: ExtHostDiagnostics, heapService: ExtHostHeapService, provider: vscode.CodeActionProvider) {
|
||||
this._documents = documents;
|
||||
this._commands = commands;
|
||||
this._diagnostics = diagnostics;
|
||||
@@ -309,23 +251,13 @@ class QuickFixAdapter {
|
||||
}
|
||||
});
|
||||
|
||||
// we cache the last 10 commands that might have been
|
||||
// created during type conversion. when as have more
|
||||
// than 10 we drop the first three
|
||||
const cachedCommands: IDisposable[] = [];
|
||||
if (this._cachedCommands.push(cachedCommands) > 10) {
|
||||
dispose(...this._cachedCommands.shift());
|
||||
dispose(...this._cachedCommands.shift());
|
||||
dispose(...this._cachedCommands.shift());
|
||||
}
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)).then(commands => {
|
||||
if (!Array.isArray(commands)) {
|
||||
return;
|
||||
}
|
||||
return commands.map((command, i) => {
|
||||
return <modes.CodeAction>{
|
||||
command: TypeConverters.Command.from(command, cachedCommands),
|
||||
command: this._commands.toInternal(command),
|
||||
score: i
|
||||
};
|
||||
});
|
||||
@@ -433,7 +365,7 @@ class NavigateTypeAdapter implements IWorkspaceSymbolProvider {
|
||||
return TPromise.as(item);
|
||||
}
|
||||
|
||||
const symbolInfo = this._heapService.get<vscode.SymbolInformation>(ObjectIdentifier.get(item));
|
||||
const symbolInfo = this._heapService.get<vscode.SymbolInformation>(ObjectIdentifier.of(item));
|
||||
if (symbolInfo) {
|
||||
return asWinJsPromise(token => this._provider.resolveWorkspaceSymbol(symbolInfo, token)).then(value => {
|
||||
return value && TypeConverters.fromSymbolInformation(value);
|
||||
@@ -494,12 +426,13 @@ class RenameAdapter {
|
||||
class SuggestAdapter {
|
||||
|
||||
private _documents: ExtHostDocuments;
|
||||
private _commands: CommandsConverter;
|
||||
private _heapService: ExtHostHeapService;
|
||||
private _provider: vscode.CompletionItemProvider;
|
||||
private _disposables: { [id: number]: IDisposable[] } = [];
|
||||
|
||||
constructor(documents: ExtHostDocuments, heapService: ExtHostHeapService, provider: vscode.CompletionItemProvider) {
|
||||
constructor(documents: ExtHostDocuments, commands: CommandsConverter, heapService: ExtHostHeapService, provider: vscode.CompletionItemProvider) {
|
||||
this._documents = documents;
|
||||
this._commands = commands;
|
||||
this._heapService = heapService;
|
||||
this._provider = provider;
|
||||
}
|
||||
@@ -535,11 +468,9 @@ class SuggestAdapter {
|
||||
for (let i = 0; i < list.items.length; i++) {
|
||||
|
||||
const item = list.items[i];
|
||||
const disposables: IDisposable[] = [];
|
||||
const suggestion = TypeConverters.Suggest.from(item, disposables);
|
||||
const id = this._heapService.keep(item, () => dispose(this._disposables[id]));
|
||||
this._disposables[id] = disposables;
|
||||
ObjectIdentifier.mixin(suggestion, id);
|
||||
const suggestion = TypeConverters.Suggest.from(item);
|
||||
suggestion.command = this._commands.toInternal(item.command);
|
||||
ObjectIdentifier.mixin(suggestion, this._heapService.keep(item));
|
||||
|
||||
if (item.textEdit) {
|
||||
|
||||
@@ -577,13 +508,16 @@ class SuggestAdapter {
|
||||
return TPromise.as(suggestion);
|
||||
}
|
||||
|
||||
const id = ObjectIdentifier.get(suggestion);
|
||||
const id = ObjectIdentifier.of(suggestion);
|
||||
const item = this._heapService.get<CompletionItem>(id);
|
||||
if (!item) {
|
||||
return TPromise.as(suggestion);
|
||||
}
|
||||
return asWinJsPromise(token => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
|
||||
return TypeConverters.Suggest.from(resolvedItem || item, this._disposables[id]);
|
||||
resolvedItem = resolvedItem || item;
|
||||
const suggestion = TypeConverters.Suggest.from(resolvedItem);
|
||||
suggestion.command = this._commands.toInternal(resolvedItem.command);
|
||||
return suggestion;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -709,7 +643,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new CodeLensAdapter(this._documents, this._commands, provider);
|
||||
this._adapter[handle] = new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider);
|
||||
this._proxy.$registerCodeLensSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
@@ -778,7 +712,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new QuickFixAdapter(this._documents, this._commands, this._diagnostics, provider);
|
||||
this._adapter[handle] = new QuickFixAdapter(this._documents, this._commands.converter, this._diagnostics, this._heapService, provider);
|
||||
this._proxy.$registerQuickFixSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
@@ -856,7 +790,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new SuggestAdapter(this._documents, this._heapService, provider);
|
||||
this._adapter[handle] = new SuggestAdapter(this._documents, this._commands.converter, this._heapService, provider);
|
||||
this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user