Vscode merge (#4582)

* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd

* fix issues with merges

* bump node version in azpipe

* replace license headers

* remove duplicate launch task

* fix build errors

* fix build errors

* fix tslint issues

* working through package and linux build issues

* more work

* wip

* fix packaged builds

* working through linux build errors

* wip

* wip

* wip

* fix mac and linux file limits

* iterate linux pipeline

* disable editor typing

* revert series to parallel

* remove optimize vscode from linux

* fix linting issues

* revert testing change

* add work round for new node

* readd packaging for extensions

* fix issue with angular not resolving decorator dependencies
This commit is contained in:
Anthony Dresser
2019-03-19 17:44:35 -07:00
committed by GitHub
parent 833d197412
commit 87765e8673
1879 changed files with 54505 additions and 38058 deletions

View File

@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import { first } from 'vs/base/common/async';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { assign } from 'vs/base/common/objects';
import { onUnexpectedExternalError, canceled, isPromiseCanceledError } from 'vs/base/common/errors';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
@@ -87,7 +86,20 @@ export class CompletionItem {
}
}
export type SnippetConfig = 'top' | 'bottom' | 'inline' | 'none';
export const enum SnippetSortOrder {
Top, Inline, Bottom
}
export class CompletionOptions {
static readonly default = new CompletionOptions();
constructor(
readonly snippetSortOrder = SnippetSortOrder.Bottom,
readonly kindFilter = new Set<modes.CompletionItemKind>(),
readonly providerFilter = new Set<modes.CompletionItemProvider>(),
) { }
}
let _snippetSuggestSupport: modes.CompletionItemProvider;
@@ -104,15 +116,12 @@ export function setSnippetSuggestSupport(support: modes.CompletionItemProvider):
export function provideSuggestionItems(
model: ITextModel,
position: Position,
snippetConfig: SnippetConfig = 'bottom',
onlyFrom?: modes.CompletionItemProvider[],
context?: modes.CompletionContext,
options: CompletionOptions = CompletionOptions.default,
context: modes.CompletionContext = { triggerKind: modes.CompletionTriggerKind.Invoke },
token: CancellationToken = CancellationToken.None
): Promise<CompletionItem[]> {
const allSuggestions: CompletionItem[] = [];
const acceptSuggestion = createSuggesionFilter(snippetConfig);
const wordUntil = model.getWordUntilPosition(position);
const defaultRange = new Range(position.lineNumber, wordUntil.startColumn, position.lineNumber, wordUntil.endColumn);
@@ -122,12 +131,10 @@ export function provideSuggestionItems(
const supports = modes.CompletionProviderRegistry.orderedGroups(model);
// add snippets provider unless turned off
if (snippetConfig !== 'none' && _snippetSuggestSupport) {
if (!options.kindFilter.has(modes.CompletionItemKind.Snippet) && _snippetSuggestSupport) {
supports.unshift([_snippetSuggestSupport]);
}
const suggestConext = context || { triggerKind: modes.CompletionTriggerKind.Invoke };
// add suggestions from contributed providers - providers are ordered in groups of
// equal score and once a group produces a result the process stops
let hasResult = false;
@@ -135,17 +142,17 @@ export function provideSuggestionItems(
// for each support in the group ask for suggestions
return Promise.all(supports.map(provider => {
if (isNonEmptyArray(onlyFrom) && onlyFrom.indexOf(provider) < 0) {
if (options.providerFilter.size > 0 && !options.providerFilter.has(provider)) {
return undefined;
}
return Promise.resolve(provider.provideCompletionItems(model, position, suggestConext, token)).then(container => {
return Promise.resolve(provider.provideCompletionItems(model, position, context, token)).then(container => {
const len = allSuggestions.length;
if (container) {
for (let suggestion of container.suggestions || []) {
if (acceptSuggestion(suggestion)) {
if (!options.kindFilter.has(suggestion.kind)) {
// fill in default range when missing
if (!suggestion.range) {
@@ -170,9 +177,9 @@ export function provideSuggestionItems(
return hasResult || token.isCancellationRequested;
}).then(() => {
if (token.isCancellationRequested) {
return Promise.reject(canceled());
return Promise.reject<any>(canceled());
}
return allSuggestions.sort(getSuggestionComparator(snippetConfig));
return allSuggestions.sort(getSuggestionComparator(options.snippetSortOrder));
});
// result.then(items => {
@@ -185,13 +192,7 @@ export function provideSuggestionItems(
return result;
}
function createSuggesionFilter(snippetConfig: SnippetConfig): (candidate: modes.CompletionItem) => boolean {
if (snippetConfig === 'none') {
return suggestion => suggestion.kind !== modes.CompletionItemKind.Snippet;
} else {
return () => true;
}
}
function defaultComparator(a: CompletionItem, b: CompletionItem): number {
// check with 'sortText'
if (a.sortTextLow && b.sortTextLow) {
@@ -233,14 +234,14 @@ function snippetDownComparator(a: CompletionItem, b: CompletionItem): number {
return defaultComparator(a, b);
}
export function getSuggestionComparator(snippetConfig: SnippetConfig): (a: CompletionItem, b: CompletionItem) => number {
if (snippetConfig === 'top') {
return snippetUpComparator;
} else if (snippetConfig === 'bottom') {
return snippetDownComparator;
} else {
return defaultComparator;
}
interface Comparator<T> { (a: T, b: T): number; }
const _snippetComparators = new Map<SnippetSortOrder, Comparator<CompletionItem>>();
_snippetComparators.set(SnippetSortOrder.Top, snippetUpComparator);
_snippetComparators.set(SnippetSortOrder.Bottom, snippetDownComparator);
_snippetComparators.set(SnippetSortOrder.Inline, defaultComparator);
export function getSuggestionComparator(snippetConfig: SnippetSortOrder): (a: CompletionItem, b: CompletionItem) => number {
return _snippetComparators.get(snippetConfig)!;
}
registerDefaultLanguageCommand('_executeCompletionItemProvider', (model, position, args) => {
@@ -269,11 +270,10 @@ registerDefaultLanguageCommand('_executeCompletionItemProvider', (model, positio
});
interface SuggestController extends IEditorContribution {
triggerSuggest(onlyFrom?: modes.CompletionItemProvider[]): void;
triggerSuggest(onlyFrom?: Set<modes.CompletionItemProvider>): void;
}
let _provider = new class implements modes.CompletionItemProvider {
const _provider = new class implements modes.CompletionItemProvider {
onlyOnceSuggestions: modes.CompletionItem[] = [];
@@ -290,6 +290,6 @@ modes.CompletionProviderRegistry.register('*', _provider);
export function showSimpleSuggestions(editor: ICodeEditor, suggestions: modes.CompletionItem[]) {
setTimeout(() => {
_provider.onlyOnceSuggestions.push(...suggestions);
editor.getContribution<SuggestController>('editor.contrib.suggestController').triggerSuggest([_provider]);
editor.getContribution<SuggestController>('editor.contrib.suggestController').triggerSuggest(new Set<modes.CompletionItemProvider>().add(_provider));
}, 0);
}

View File

@@ -181,7 +181,7 @@ export class SuggestController implements IEditorContribution {
this._widget.getValue().hideWidget();
}
}));
this._toDispose.push(this._editor.onDidBlurEditorText(() => {
this._toDispose.push(this._editor.onDidBlurEditorWidget(() => {
if (!this._sticky) {
this._model.cancel();
}
@@ -292,11 +292,13 @@ export class SuggestController implements IEditorContribution {
}
private _alertCompletionItem({ completion: suggestion }: CompletionItem): void {
let msg = nls.localize('arai.alert.snippet', "Accepting '{0}' did insert the following text: {1}", suggestion.label, suggestion.insertText);
alert(msg);
if (isNonEmptyArray(suggestion.additionalTextEdits)) {
let msg = nls.localize('arai.alert.snippet', "Accepting '{0}' made {1} additional edits", suggestion.label, suggestion.additionalTextEdits.length);
alert(msg);
}
}
triggerSuggest(onlyFrom?: CompletionItemProvider[]): void {
triggerSuggest(onlyFrom?: Set<CompletionItemProvider>): void {
if (this._editor.hasModel()) {
this._model.trigger({ auto: false, shy: false }, false, onlyFrom);
this._editor.revealLine(this._editor.getPosition().lineNumber, ScrollType.Smooth);

View File

@@ -8,7 +8,7 @@ import { LRUCache, TernarySearchTree } from 'vs/base/common/map';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ITextModel } from 'vs/editor/common/model';
import { IPosition } from 'vs/editor/common/core/position';
import { CompletionItemKind, completionKindFromLegacyString } from 'vs/editor/common/modes';
import { CompletionItemKind, completionKindFromString } from 'vs/editor/common/modes';
import { Disposable } from 'vs/base/common/lifecycle';
import { RunOnceScheduler } from 'vs/base/common/async';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
@@ -124,7 +124,7 @@ export class LRUMemory extends Memory {
let seq = 0;
for (const [key, value] of data) {
value.touch = seq;
value.type = typeof value.type === 'number' ? value.type : completionKindFromLegacyString(value.type);
value.type = typeof value.type === 'number' ? value.type : completionKindFromString(value.type);
this._cache.set(key, value);
}
this._seq = this._cache.size;
@@ -188,7 +188,7 @@ export class PrefixMemory extends Memory {
if (data.length > 0) {
this._seq = data[0][1].touch + 1;
for (const [key, value] of data) {
value.type = typeof value.type === 'number' ? value.type : completionKindFromLegacyString(value.type);
value.type = typeof value.type === 'number' ? value.type : completionKindFromString(value.type);
this._trie.set(key, value);
}
}

View File

@@ -8,15 +8,14 @@ import { TimeoutTimer } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { values } from 'vs/base/common/map';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { CursorChangeReason, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { Position } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
import { ITextModel, IWordAtPosition } from 'vs/editor/common/model';
import { CompletionItemProvider, StandardTokenType, CompletionContext, CompletionProviderRegistry, CompletionTriggerKind } from 'vs/editor/common/modes';
import { CompletionItemProvider, StandardTokenType, CompletionContext, CompletionProviderRegistry, CompletionTriggerKind, CompletionItemKind, completionKindFromString } from 'vs/editor/common/modes';
import { CompletionModel } from './completionModel';
import { CompletionItem, getSuggestionComparator, provideSuggestionItems, getSnippetSuggestSupport } from './suggest';
import { CompletionItem, getSuggestionComparator, provideSuggestionItems, getSnippetSuggestSupport, SnippetSortOrder, CompletionOptions } from './suggest';
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
@@ -209,7 +208,7 @@ export class SuggestModel implements IDisposable {
// keep existing items that where not computed by the
// supports/providers that want to trigger now
const items: CompletionItem[] | undefined = this._completionModel ? this._completionModel.adopt(supports) : undefined;
this.trigger({ auto: true, shy: false, triggerCharacter: lastChar }, Boolean(this._completionModel), values(supports), items);
this.trigger({ auto: true, shy: false, triggerCharacter: lastChar }, Boolean(this._completionModel), supports, items);
}
});
}
@@ -347,7 +346,7 @@ export class SuggestModel implements IDisposable {
}, 25);
}
trigger(context: SuggestTriggerContext, retrigger: boolean = false, onlyFrom?: CompletionItemProvider[], existingItems?: CompletionItem[]): void {
trigger(context: SuggestTriggerContext, retrigger: boolean = false, onlyFrom?: Set<CompletionItemProvider>, existingItems?: CompletionItem[]): void {
if (!this._editor.hasModel()) {
return;
}
@@ -371,7 +370,7 @@ export class SuggestModel implements IDisposable {
triggerKind: CompletionTriggerKind.TriggerCharacter,
triggerCharacter: context.triggerCharacter
};
} else if (onlyFrom && onlyFrom.length) {
} else if (onlyFrom && onlyFrom.size > 0) {
suggestCtx = { triggerKind: CompletionTriggerKind.TriggerForIncompleteCompletions };
} else {
suggestCtx = { triggerKind: CompletionTriggerKind.Invoke };
@@ -379,13 +378,40 @@ export class SuggestModel implements IDisposable {
this._requestToken = new CancellationTokenSource();
// kind filter and snippet sort rules
const { contribInfo } = this._editor.getConfiguration();
let itemKindFilter = new Set<CompletionItemKind>();
let snippetSortOrder = SnippetSortOrder.Inline;
switch (contribInfo.suggest.snippets) {
case 'top':
snippetSortOrder = SnippetSortOrder.Top;
break;
// ↓ that's the default anyways...
// case 'inline':
// snippetSortOrder = SnippetSortOrder.Inline;
// break;
case 'bottom':
snippetSortOrder = SnippetSortOrder.Bottom;
break;
case 'none':
itemKindFilter.add(CompletionItemKind.Snippet);
break;
}
// kind filter
for (const key in contribInfo.suggest.filteredTypes) {
const kind = completionKindFromString(key, true);
if (typeof kind !== 'undefined' && contribInfo.suggest.filteredTypes[key] === false) {
itemKindFilter.add(kind);
}
}
let wordDistance = WordDistance.create(this._editorWorker, this._editor);
let items = provideSuggestionItems(
model,
this._editor.getPosition(),
this._editor.getConfiguration().contribInfo.suggest.snippets,
onlyFrom,
new CompletionOptions(snippetSortOrder, itemKindFilter, onlyFrom),
suggestCtx,
this._requestToken.token
);
@@ -405,7 +431,7 @@ export class SuggestModel implements IDisposable {
const model = this._editor.getModel();
if (isNonEmptyArray(existingItems)) {
const cmpFn = getSuggestionComparator(this._editor.getConfiguration().contribInfo.suggest.snippets);
const cmpFn = getSuggestionComparator(snippetSortOrder);
items = items.concat(existingItems).sort(cmpFn);
}
@@ -461,7 +487,7 @@ export class SuggestModel implements IDisposable {
// typed -> moved cursor RIGHT & incomple model & still on a word -> retrigger
const { incomplete } = this._completionModel;
const adopted = this._completionModel.adopt(incomplete);
this.trigger({ auto: this._state === State.Auto, shy: false }, true, values(incomplete), adopted);
this.trigger({ auto: this._state === State.Auto, shy: false }, true, incomplete, adopted);
} else {
// typed -> moved cursor RIGHT -> update UI

View File

@@ -40,7 +40,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { FileKind } from 'vs/platform/files/common/files';
const expandSuggestionDocsByDefault = false;
const maxSuggestionsToShow = 12;
interface ISuggestionTemplateData {
root: HTMLElement;
@@ -63,8 +62,16 @@ export const editorSuggestWidgetHighlightForeground = registerColor('editorSugge
const colorRegExp = /^(#([\da-f]{3}){1,2}|(rgb|hsl)a\(\s*(\d{1,3}%?\s*,\s*){3}(1|0?\.\d+)\)|(rgb|hsl)\(\s*\d{1,3}%?(\s*,\s*\d{1,3}%?){2}\s*\))$/i;
function matchesColor(text: string): string | null {
return text && text.match(colorRegExp) ? text : null;
function extractColor(item: CompletionItem, out: string[]): boolean {
if (item.completion.label.match(colorRegExp)) {
out[0] = item.completion.label;
return true;
}
if (typeof item.completion.documentation === 'string' && item.completion.documentation.match(colorRegExp)) {
out[0] = item.completion.documentation;
return true;
}
return false;
}
function canExpandCompletionItem(item: CompletionItem | null) {
@@ -156,11 +163,11 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData>
matches: createMatches(element.score)
};
let color: string | null = null;
if (suggestion.kind === CompletionItemKind.Color && ((color = matchesColor(suggestion.label) || typeof suggestion.documentation === 'string' ? matchesColor(suggestion.documentation as any) : null))) {
let color: string[] = [];
if (suggestion.kind === CompletionItemKind.Color && extractColor(element, color)) {
// special logic for 'color' completion items
data.icon.className = 'icon customcolor';
data.colorspan.style.backgroundColor = color;
data.colorspan.style.backgroundColor = color[0];
} else if (suggestion.kind === CompletionItemKind.File && this._themeService.getIconTheme().hasFileIcons) {
// special logic for 'file' completion items
@@ -243,10 +250,10 @@ class SuggestionDetails {
constructor(
container: HTMLElement,
private widget: SuggestWidget,
private editor: ICodeEditor,
private markdownRenderer: MarkdownRenderer,
private triggerKeybindingLabel: string
private readonly widget: SuggestWidget,
private readonly editor: ICodeEditor,
private readonly markdownRenderer: MarkdownRenderer,
private readonly triggerKeybindingLabel: string
) {
this.disposables = [];
@@ -416,8 +423,8 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
private list: List<CompletionItem>;
private listHeight: number;
private suggestWidgetVisible: IContextKey<boolean>;
private suggestWidgetMultipleSuggestions: IContextKey<boolean>;
private readonly suggestWidgetVisible: IContextKey<boolean>;
private readonly suggestWidgetMultipleSuggestions: IContextKey<boolean>;
private readonly editorBlurTimeout = new TimeoutTimer();
private readonly showTimeout = new TimeoutTimer();
@@ -436,7 +443,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
private readonly maxWidgetWidth = 660;
private readonly listWidth = 330;
private storageService: IStorageService;
private readonly storageService: IStorageService;
private detailsFocusBorderColor: string;
private detailsBorderColor: string;
@@ -446,7 +453,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
private docsPositionPreviousWidgetY: number | null;
constructor(
private editor: ICodeEditor,
private readonly editor: ICodeEditor,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
@@ -465,14 +472,14 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.storageService = storageService;
this.element = $('.editor-widget.suggest-widget');
if (!this.editor.getConfiguration().contribInfo.iconsInSuggestions) {
addClass(this.element, 'no-icons');
}
this.messageElement = append(this.element, $('.message'));
this.listElement = append(this.element, $('.tree'));
this.details = new SuggestionDetails(this.element, this, this.editor, markdownRenderer, triggerKeybindingLabel);
const applyIconStyle = () => toggleClass(this.element, 'no-icons', !this.editor.getConfiguration().contribInfo.suggest.showIcons);
applyIconStyle();
let renderer = instantiationService.createInstance(Renderer, this, this.editor, triggerKeybindingLabel);
this.list = new List(this.listElement, this, [renderer], {
@@ -491,7 +498,8 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.list.onMouseDown(e => this.onListMouseDown(e)),
this.list.onSelectionChange(e => this.onListSelection(e)),
this.list.onFocusChange(e => this.onListFocus(e)),
this.editor.onDidChangeCursorSelection(() => this.onCursorSelectionChanged())
this.editor.onDidChangeCursorSelection(() => this.onCursorSelectionChanged()),
this.editor.onDidChangeConfiguration(e => e.contribInfo && applyIconStyle())
];
this.suggestWidgetVisible = SuggestContext.Visible.bindTo(contextKeyService);
@@ -522,6 +530,10 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
return;
}
// prevent stealing browser focus from the editor
e.browserEvent.preventDefault();
e.browserEvent.stopPropagation();
this.select(e.element, e.index);
}
@@ -542,23 +554,15 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
item.resolve(CancellationToken.None).then(() => {
this.onDidSelectEmitter.fire({ item, index, model: completionModel });
alert(nls.localize('suggestionAriaAccepted', "{0}, accepted", item.completion.label));
this.editor.focus();
});
}
private _getSuggestionAriaAlertLabel(item: CompletionItem): string {
const isSnippet = item.completion.kind === CompletionItemKind.Snippet;
if (!canExpandCompletionItem(item)) {
return isSnippet ? nls.localize('ariaCurrentSnippetSuggestion', "{0}, snippet suggestion", item.completion.label)
: nls.localize('ariaCurrentSuggestion', "{0}, suggestion", item.completion.label);
} else if (this.expandDocsSettingFromStorage()) {
return isSnippet ? nls.localize('ariaCurrentSnippeSuggestionReadDetails', "{0}, snippet suggestion. Reading details. {1}", item.completion.label, this.details.getAriaLabel())
: nls.localize('ariaCurrenttSuggestionReadDetails', "{0}, suggestion. Reading details. {1}", item.completion.label, this.details.getAriaLabel());
if (this.expandDocsSettingFromStorage()) {
return nls.localize('ariaCurrenttSuggestionReadDetails', "Item {0}, docs: {1}", item.completion.label, this.details.getAriaLabel());
} else {
return isSnippet ? nls.localize('ariaCurrentSnippetSuggestionWithDetails', "{0}, snippet suggestion, has details", item.completion.label)
: nls.localize('ariaCurrentSuggestionWithDetails', "{0}, suggestion, has details", item.completion.label);
return item.completion.label;
}
}
@@ -569,7 +573,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
}
this._lastAriaAlertLabel = newAriaAlertLabel;
if (this._lastAriaAlertLabel) {
alert(this._lastAriaAlertLabel);
alert(this._lastAriaAlertLabel, true);
}
}
@@ -1040,7 +1044,8 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
height = this.unfocusedHeight;
} else {
const suggestionCount = this.list.contentHeight / this.unfocusedHeight;
height = Math.min(suggestionCount, maxSuggestionsToShow) * this.unfocusedHeight;
const { maxVisibleSuggestions } = this.editor.getConfiguration().contribInfo.suggest;
height = Math.min(suggestionCount, maxVisibleSuggestions) * this.unfocusedHeight;
}
this.element.style.lineHeight = `${this.unfocusedHeight}px`;
@@ -1120,7 +1125,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
// Heights
private get maxWidgetHeight(): number {
return this.unfocusedHeight * maxSuggestionsToShow;
return this.unfocusedHeight * this.editor.getConfiguration().contribInfo.suggest.maxVisibleSuggestions;
}
private get unfocusedHeight(): number {

View File

@@ -6,7 +6,7 @@ import * as assert from 'assert';
import { IPosition } from 'vs/editor/common/core/position';
import * as modes from 'vs/editor/common/modes';
import { CompletionModel } from 'vs/editor/contrib/suggest/completionModel';
import { CompletionItem, getSuggestionComparator } from 'vs/editor/contrib/suggest/suggest';
import { CompletionItem, getSuggestionComparator, SnippetSortOrder } from 'vs/editor/contrib/suggest/suggest';
import { WordDistance } from 'vs/editor/contrib/suggest/wordDistance';
export function createSuggestItem(label: string, overwriteBefore: number, kind = modes.CompletionItemKind.Property, incomplete: boolean = false, position: IPosition = { lineNumber: 1, column: 1 }, sortText?: string, filterText?: string): CompletionItem {
@@ -157,7 +157,16 @@ suite('CompletionModel', function () {
], 1, {
leadingLineContent: 's',
characterCountDelta: 0
}, WordDistance.None, { snippets: 'top', snippetsPreventQuickSuggestions: true, filterGraceful: true, localityBonus: false, shareSuggestSelections: false });
}, WordDistance.None, {
snippets: 'top',
snippetsPreventQuickSuggestions: true,
filterGraceful: true,
localityBonus: false,
shareSuggestSelections: false,
showIcons: true,
maxVisibleSuggestions: 12,
filteredTypes: Object.create(null)
});
assert.equal(model.items.length, 2);
const [a, b] = model.items;
@@ -176,7 +185,16 @@ suite('CompletionModel', function () {
], 1, {
leadingLineContent: 's',
characterCountDelta: 0
}, WordDistance.None, { snippets: 'bottom', snippetsPreventQuickSuggestions: true, filterGraceful: true, localityBonus: false, shareSuggestSelections: false });
}, WordDistance.None, {
snippets: 'bottom',
snippetsPreventQuickSuggestions: true,
filterGraceful: true,
localityBonus: false,
shareSuggestSelections: false,
showIcons: true,
maxVisibleSuggestions: 12,
filteredTypes: Object.create(null)
});
assert.equal(model.items.length, 2);
const [a, b] = model.items;
@@ -194,7 +212,16 @@ suite('CompletionModel', function () {
], 1, {
leadingLineContent: 's',
characterCountDelta: 0
}, WordDistance.None, { snippets: 'inline', snippetsPreventQuickSuggestions: true, filterGraceful: true, localityBonus: false, shareSuggestSelections: false });
}, WordDistance.None, {
snippets: 'inline',
snippetsPreventQuickSuggestions: true,
filterGraceful: true,
localityBonus: false,
shareSuggestSelections: false,
showIcons: true,
maxVisibleSuggestions: 12,
filteredTypes: Object.create(null)
});
assert.equal(model.items.length, 2);
const [a, b] = model.items;
@@ -226,7 +253,7 @@ suite('CompletionModel', function () {
const item1 = createSuggestItem('<- groups', 2, modes.CompletionItemKind.Property, false, { lineNumber: 1, column: 3 }, '00002', ' groups');
const item2 = createSuggestItem('source', 0, modes.CompletionItemKind.Property, false, { lineNumber: 1, column: 3 }, '00001', 'source');
const items = [item1, item2].sort(getSuggestionComparator('inline'));
const items = [item1, item2].sort(getSuggestionComparator(SnippetSortOrder.Inline));
model = new CompletionModel(items, 3, {
leadingLineContent: ' ',

View File

@@ -5,8 +5,8 @@
import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { IDisposable } from 'vs/base/common/lifecycle';
import { CompletionProviderRegistry, CompletionItemKind } from 'vs/editor/common/modes';
import { provideSuggestionItems } from 'vs/editor/contrib/suggest/suggest';
import { CompletionProviderRegistry, CompletionItemKind, CompletionItemProvider } from 'vs/editor/common/modes';
import { provideSuggestionItems, SnippetSortOrder, CompletionOptions } from 'vs/editor/contrib/suggest/suggest';
import { Position } from 'vs/editor/common/core/position';
import { TextModel } from 'vs/editor/common/model/textModel';
import { Range } from 'vs/editor/common/core/range';
@@ -51,7 +51,7 @@ suite('Suggest', function () {
});
test('sort - snippet inline', async function () {
const items = await provideSuggestionItems(model, new Position(1, 1), 'inline');
const items = await provideSuggestionItems(model, new Position(1, 1), new CompletionOptions(SnippetSortOrder.Inline));
assert.equal(items.length, 3);
assert.equal(items[0].completion.label, 'aaa');
assert.equal(items[1].completion.label, 'fff');
@@ -59,7 +59,7 @@ suite('Suggest', function () {
});
test('sort - snippet top', async function () {
const items = await provideSuggestionItems(model, new Position(1, 1), 'top');
const items = await provideSuggestionItems(model, new Position(1, 1), new CompletionOptions(SnippetSortOrder.Top));
assert.equal(items.length, 3);
assert.equal(items[0].completion.label, 'aaa');
assert.equal(items[1].completion.label, 'zzz');
@@ -67,7 +67,7 @@ suite('Suggest', function () {
});
test('sort - snippet bottom', async function () {
const items = await provideSuggestionItems(model, new Position(1, 1), 'bottom');
const items = await provideSuggestionItems(model, new Position(1, 1), new CompletionOptions(SnippetSortOrder.Bottom));
assert.equal(items.length, 3);
assert.equal(items[0].completion.label, 'fff');
assert.equal(items[1].completion.label, 'aaa');
@@ -75,7 +75,7 @@ suite('Suggest', function () {
});
test('sort - snippet none', async function () {
const items = await provideSuggestionItems(model, new Position(1, 1), 'none');
const items = await provideSuggestionItems(model, new Position(1, 1), new CompletionOptions(undefined, new Set<CompletionItemKind>().add(CompletionItemKind.Snippet)));
assert.equal(items.length, 1);
assert.equal(items[0].completion.label, 'fff');
});
@@ -98,7 +98,7 @@ suite('Suggest', function () {
};
const registration = CompletionProviderRegistry.register({ pattern: 'bar/path', scheme: 'foo' }, foo);
provideSuggestionItems(model, new Position(1, 1), undefined, [foo]).then(items => {
provideSuggestionItems(model, new Position(1, 1), new CompletionOptions(undefined, undefined, new Set<CompletionItemProvider>().add(foo))).then(items => {
registration.dispose();
assert.equal(items.length, 1);

View File

@@ -34,11 +34,11 @@ export abstract class WordDistance {
return Promise.resolve(WordDistance.None);
}
return new BracketSelectionRangeProvider().provideSelectionRanges(model, position).then(ranges => {
if (!ranges || ranges.length === 0) {
return new BracketSelectionRangeProvider().provideSelectionRanges(model, [position]).then(ranges => {
if (!ranges || ranges.length === 0 || ranges[0].length === 0) {
return WordDistance.None;
}
return service.computeWordRanges(model.uri, ranges[0].range).then(wordRanges => {
return service.computeWordRanges(model.uri, ranges[0][0].range).then(wordRanges => {
return new class extends WordDistance {
distance(anchor: IPosition, suggestion: CompletionItem) {
if (!wordRanges || !position.equals(editor.getPosition())) {
@@ -55,7 +55,7 @@ export abstract class WordDistance {
let idx = binarySearch(wordLines, Range.fromPositions(anchor), Range.compareRangesUsingStarts);
let bestWordRange = idx >= 0 ? wordLines[idx] : wordLines[Math.max(0, ~idx - 1)];
let blockDistance = ranges.length;
for (const range of ranges) {
for (const range of ranges[0]) {
if (!Range.containsRange(range.range, bestWordRange)) {
break;
}