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

speed up getSnippets, getSnippetsSync, and updateSnippets, #36427

上级 1a4f6b9f
......@@ -95,13 +95,15 @@ class SnippetsService implements ISnippetsService {
private readonly _extensionSnippets = new Map<LanguageId, Snippet[]>();
private readonly _userSnippets = new Map<LanguageId, Snippet[]>();
private readonly _userSnippetsFolder: string;
private readonly _wait: Promise<any>;
private readonly _disposables: IDisposable[] = [];
constructor(
@IModeService readonly _modeService: IModeService,
@IExtensionService readonly _extensionService: IExtensionService,
@IExtensionService extensionService: IExtensionService,
@IEnvironmentService environmentService: IEnvironmentService,
) {
this._wait = Promise.resolve(extensionService.onReady());
this._userSnippetsFolder = join(environmentService.appSettingsHome, 'snippets');
this._prepUserSnippetsWatching();
this._prepExtensionSnippets();
......@@ -115,25 +117,34 @@ class SnippetsService implements ISnippetsService {
getSnippets(languageId: LanguageId): Promise<Snippet[]> {
let result: Snippet[] = [];
return Promise.all([
this._extensionService.onReady(),
this._getOrLoadUserSnippets(languageId, result),
this._getOrLoadExtensionSnippets(languageId, result)
]).then(() => {
return this._wait.then(() => {
return this._getOrLoadUserSnippets(languageId, result);
}).then(() => {
return this._getOrLoadExtensionSnippets(languageId, result);
}).then(() => {
return result;
});
}
getSnippetsSync(languageId: LanguageId): Snippet[] {
// just kick off snippet loading for this language such
// that subseqent calls to this method return more
// that subsequent calls to this method return more
// correct results
this.getSnippets(languageId).catch(undefined);
// collect and return what we already have
let userSnippets = this._userSnippets.get(languageId);
let extensionSnippets = this._extensionSnippets.get(languageId);
return (userSnippets || []).concat(extensionSnippets || []);
const userSnippets = this._userSnippets.get(languageId);
const extensionSnippets = this._extensionSnippets.get(languageId);
if (userSnippets && extensionSnippets) {
return userSnippets.concat(extensionSnippets);
} else if (!userSnippets) {
return extensionSnippets;
} else if (!extensionSnippets) {
return userSnippets;
} else {
return undefined;
}
}
// --- extension snippet logic ---
......
......@@ -15,6 +15,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { endsWith } from 'vs/base/common/strings';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { Range } from 'vs/editor/common/core/range';
import { CommonEditorRegistry, commonEditorContribution, EditorCommand } from 'vs/editor/common/editorCommonExtensions';
import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetController2';
import { showSimpleSuggestions } from 'vs/editor/contrib/suggest/browser/suggest';
......@@ -32,9 +33,8 @@ export class TabCompletionController implements editorCommon.IEditorContribution
return editor.getContribution<TabCompletionController>(TabCompletionController.ID);
}
private readonly _hasSnippets: IContextKey<boolean>;
private _snippets: Snippet[] = [];
private _hasSnippets: IContextKey<boolean>;
private _activeSnippets: Snippet[] = [];
private _selectionListener: IDisposable;
private _configListener: IDisposable;
......@@ -68,53 +68,66 @@ export class TabCompletionController implements editorCommon.IEditorContribution
dispose(this._selectionListener);
} else {
this._selectionListener = this._editor.onDidChangeCursorSelection(e => this._updateSnippets());
this._updateSnippets();
if (this._editor.getModel()) {
this._updateSnippets();
}
}
}
private _updateSnippets(): void {
let selection = this._editor.getSelection();
let model = this._editor.getModel();
let selectFn: (snippet: Snippet) => boolean;
// reset first
this._activeSnippets = [];
if (!selection || !model) {
// too early
// lots of dance for getting the
const selection = this._editor.getSelection();
const model = this._editor.getModel();
model.tokenizeIfCheap(selection.positionLineNumber);
const id = model.getLanguageIdAtPosition(selection.positionLineNumber, selection.positionColumn);
const snippets = this._snippetService.getSnippetsSync(id);
if (!snippets) {
// nothing for this language
this._hasSnippets.set(false);
this._snippets = undefined;
return;
}
if (selection.isEmpty()) {
if (Range.isEmpty(selection)) {
// empty selection -> real text (no whitespace) left of cursor
const prefix = getNonWhitespacePrefix(model, this._editor.getPosition());
selectFn = prefix && (snippet => endsWith(prefix, snippet.prefix));
const prefix = getNonWhitespacePrefix(model, selection.getPosition());
if (prefix) {
for (const snippet of snippets) {
if (endsWith(prefix, snippet.prefix)) {
this._activeSnippets.push(snippet);
}
}
}
} else if (selection.startLineNumber === selection.endLineNumber && model.getValueLengthInRange(selection) <= 100) {
} else if (!Range.spansMultipleLines(selection) && model.getValueLengthInRange(selection) <= 100) {
// actual selection -> snippet must be a full match
const selected = model.getValueInRange(selection);
selectFn = snippet => selected === snippet.prefix;
}
if (selectFn) {
model.tokenizeIfCheap(selection.positionLineNumber);
const id = model.getLanguageIdAtPosition(selection.positionLineNumber, selection.positionColumn);
this._snippets = this._snippetService.getSnippetsSync(id).filter(selectFn);
if (selected) {
for (const snippet of snippets) {
if (selected === snippet.prefix) {
this._activeSnippets.push(snippet);
}
}
}
}
this._hasSnippets.set(this._snippets && this._snippets.length > 0);
this._hasSnippets.set(this._activeSnippets.length > 0);
}
performSnippetCompletions(): void {
if (this._snippets.length === 1) {
if (this._activeSnippets.length === 1) {
// one -> just insert
const [snippet] = this._snippets;
const [snippet] = this._activeSnippets;
SnippetController2.get(this._editor).insert(snippet.codeSnippet, snippet.prefix.length, 0);
} else if (this._snippets.length > 1) {
} else if (this._activeSnippets.length > 1) {
// two or more -> show IntelliSense box
showSimpleSuggestions(this._editor, this._snippets.map(snippet => new SnippetSuggestion(snippet, snippet.prefix.length)));
showSimpleSuggestions(this._editor, this._activeSnippets.map(snippet => new SnippetSuggestion(snippet, snippet.prefix.length)));
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册