From 74b25109853845db171280b7d0dbeaf18092db00 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 Nov 2020 12:44:46 +0100 Subject: [PATCH] word based completion includes words from other files of same language --- .../common/services/editorSimpleWorker.ts | 38 ++++++++----------- .../services/editorWorkerServiceImpl.ts | 38 +++++++++++-------- .../services/editorSimpleWorker.test.ts | 2 +- 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index 69592e735c6..68a3d125387 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -530,36 +530,30 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { private static readonly _suggestionsLimit = 10000; - public async textualSuggest(modelUrl: string, position: IPosition, wordDef: string, wordDefFlags: string): Promise<{ words: string[], duration: number } | null> { - const model = this._getModel(modelUrl); - if (!model) { - return null; - } + public async textualSuggest(modelUrls: string[], leadingWord: string | undefined, wordDef: string, wordDefFlags: string): Promise<{ words: string[], duration: number } | null> { const sw = new StopWatch(true); - const words: string[] = []; - const seen = new Set(); const wordDefRegExp = new RegExp(wordDef, wordDefFlags); + const seen = new Set(); - const wordAt = model.getWordAtPosition(position, wordDefRegExp); - if (wordAt) { - seen.add(model.getValueInRange(wordAt)); - } - - for (let word of model.words(wordDefRegExp)) { - if (seen.has(word)) { + outer: for (let url of modelUrls) { + const model = this._getModel(url); + if (!model) { continue; } - seen.add(word); - if (!isNaN(Number(word))) { - continue; - } - words.push(word); - if (seen.size > EditorSimpleWorker._suggestionsLimit) { - break; + + for (let word of model.words(wordDefRegExp)) { + if (word === leadingWord || !isNaN(Number(word))) { + continue; + } + seen.add(word); + if (seen.size > EditorSimpleWorker._suggestionsLimit) { + break outer; + } } } - return { words, duration: sw.elapsed() }; + + return { words: Array.from(seen), duration: sw.elapsed() }; } diff --git a/src/vs/editor/common/services/editorWorkerServiceImpl.ts b/src/vs/editor/common/services/editorWorkerServiceImpl.ts index 5099af91d90..55171bef77d 100644 --- a/src/vs/editor/common/services/editorWorkerServiceImpl.ts +++ b/src/vs/editor/common/services/editorWorkerServiceImpl.ts @@ -8,7 +8,7 @@ import { Disposable, IDisposable, dispose, toDisposable, DisposableStore } from import { URI } from 'vs/base/common/uri'; import { SimpleWorkerClient, logOnceWebWorkerWarning, IWorkerClient } from 'vs/base/common/worker/simpleWorker'; import { DefaultWorkerFactory } from 'vs/base/worker/defaultWorkerFactory'; -import { IPosition, Position } from 'vs/editor/common/core/position'; +import { Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { IChange } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; @@ -152,16 +152,30 @@ class WordBasedCompletionItemProvider implements modes.CompletionItemProvider { if (!wordBasedSuggestions) { return undefined; } - if (!canSyncModel(this._modelService, model.uri)) { - return undefined; // File too large + + const models: URI[] = []; + for (let candidate of this._modelService.getModels()) { + if (!canSyncModel(this._modelService, candidate.uri)) { + continue; + } + if (candidate === model) { + models.unshift(candidate.uri); + } else if (candidate.getLanguageIdentifier().id === model.getLanguageIdentifier().id) { + models.push(candidate.uri); + } + } + + if (models.length === 0) { + return undefined; // File too large, no other files } + const wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageIdentifier().id); const word = model.getWordAtPosition(position); const replace = !word ? Range.fromPositions(position) : new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn); const insert = replace.setEndPosition(position.lineNumber, position.column); const client = await this._workerManager.withWorker(); - const data = await client.textualSuggest(model.uri, position); + const data = await client.textualSuggest(models, word?.word, wordDefRegExp); if (!data) { return undefined; } @@ -463,17 +477,11 @@ export class EditorWorkerClient extends Disposable { }); } - public textualSuggest(resource: URI, position: IPosition): Promise<{ words: string[], duration: number } | null> { - return this._withSyncedResources([resource]).then(proxy => { - let model = this._modelService.getModel(resource); - if (!model) { - return null; - } - let wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageIdentifier().id); - let wordDef = wordDefRegExp.source; - let wordDefFlags = regExpFlags(wordDefRegExp); - return proxy.textualSuggest(resource.toString(), position, wordDef, wordDefFlags); - }); + public async textualSuggest(resources: URI[], leadingWord: string | undefined, wordDefRegExp: RegExp): Promise<{ words: string[], duration: number } | null> { + const proxy = await this._withSyncedResources(resources); + const wordDef = wordDefRegExp.source; + const wordDefFlags = regExpFlags(wordDefRegExp); + return proxy.textualSuggest(resources.map(r => r.toString()), leadingWord, wordDef, wordDefFlags); } computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] } | null> { diff --git a/src/vs/editor/test/common/services/editorSimpleWorker.test.ts b/src/vs/editor/test/common/services/editorSimpleWorker.test.ts index 2b2a748c662..54f73ed0ec2 100644 --- a/src/vs/editor/test/common/services/editorSimpleWorker.test.ts +++ b/src/vs/editor/test/common/services/editorSimpleWorker.test.ts @@ -162,7 +162,7 @@ suite('EditorSimpleWorker', () => { 'f f' // 2 ]); - return worker.textualSuggest(model.uri.toString(), { lineNumber: 2, column: 2 }, '[a-z]+', 'img').then((result) => { + return worker.textualSuggest([model.uri.toString()], 'f', '[a-z]+', 'img').then((result) => { if (!result) { assert.ok(false); return; -- GitLab