Merge from vscode 52dcb723a39ae75bee1bd56b3312d7fcdc87aeed (#6719)

This commit is contained in:
Anthony Dresser
2019-08-12 21:31:51 -07:00
committed by GitHub
parent 00250839fc
commit 7eba8c4c03
616 changed files with 9472 additions and 7087 deletions

View File

@@ -29,8 +29,10 @@ export interface ICompletionStats {
}
export class LineContext {
leadingLineContent: string;
characterCountDelta: number;
constructor(
readonly leadingLineContent: string,
readonly characterCountDelta: number,
) { }
}
const enum Refilter {
@@ -49,9 +51,9 @@ export class CompletionModel {
private _lineContext: LineContext;
private _refilterKind: Refilter;
private _filteredItems: StrictCompletionItem[];
private _isIncomplete: Set<CompletionItemProvider>;
private _stats: ICompletionStats;
private _filteredItems?: StrictCompletionItem[];
private _isIncomplete?: Set<CompletionItemProvider>;
private _stats?: ICompletionStats;
constructor(
items: CompletionItem[],
@@ -89,12 +91,12 @@ export class CompletionModel {
get items(): CompletionItem[] {
this._ensureCachedState();
return this._filteredItems;
return this._filteredItems!;
}
get incomplete(): Set<CompletionItemProvider> {
this._ensureCachedState();
return this._isIncomplete;
return this._isIncomplete!;
}
adopt(except: Set<CompletionItemProvider>): CompletionItem[] {
@@ -117,7 +119,7 @@ export class CompletionModel {
get stats(): ICompletionStats {
this._ensureCachedState();
return this._stats;
return this._stats!;
}
private _ensureCachedState(): void {
@@ -136,7 +138,7 @@ export class CompletionModel {
let wordLow = '';
// incrementally filter less
const source = this._refilterKind === Refilter.All ? this._items : this._filteredItems;
const source = this._refilterKind === Refilter.All ? this._items : this._filteredItems!;
const target: StrictCompletionItem[] = [];
// picks a score function based on the number of

View File

@@ -110,7 +110,9 @@
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .header > .close {
background-image: url('./close-light.svg');
float: right;
position: absolute;
top: 0px;
right: 0px;
margin-right: 5px;
}
@@ -251,7 +253,7 @@
text-overflow: ellipsis;
opacity: 0.7;
word-break: break-all;
margin: 0;
margin: 0px 24px 0 0;
padding: 4px 0 12px 5px;
}

View File

@@ -27,7 +27,7 @@ export const Context = {
export class CompletionItem {
_brand: 'ISuggestionItem';
_brand!: 'ISuggestionItem';
readonly resolve: (token: CancellationToken) => Promise<void>;

View File

@@ -15,7 +15,7 @@ export class SuggestAlternatives {
private readonly _ckOtherSuggestions: IContextKey<boolean>;
private _index: number;
private _index: number = 0;
private _model: CompletionModel | undefined;
private _acceptNext: ((selected: ISelectedSuggestion) => any) | undefined;
private _listener: IDisposable | undefined;

View File

@@ -370,6 +370,10 @@ export class SuggestController implements IEditorContribution {
this._widget.getValue().toggleDetails();
}
toggleExplainMode(): void {
this._widget.getValue().toggleExplainMode();
}
toggleSuggestionFocus(): void {
this._widget.getValue().toggleDetailsFocus();
}
@@ -521,6 +525,16 @@ registerEditorCommand(new SuggestCommand({
}
}));
registerEditorCommand(new SuggestCommand({
id: 'toggleExplainMode',
precondition: SuggestContext.Visible,
handler: x => x.toggleExplainMode(),
kbOpts: {
weight: KeybindingWeight.EditorContrib,
primary: KeyMod.CtrlCmd | KeyCode.US_SLASH,
}
}));
registerEditorCommand(new SuggestCommand({
id: 'toggleSuggestionFocus',
precondition: SuggestContext.Visible,

View File

@@ -22,10 +22,10 @@ export abstract class Memory {
if (items.length === 0) {
return 0;
}
let topScore = items[0].score;
let topScore = items[0].score[0];
for (let i = 1; i < items.length; i++) {
const { score, completion: suggestion } = items[i];
if (score !== topScore) {
if (score[0] !== topScore) {
// stop when leaving the group of top matches
break;
}
@@ -81,33 +81,42 @@ export class LRUMemory extends Memory {
}
select(model: ITextModel, pos: IPosition, items: CompletionItem[]): number {
// in order of completions, select the first
// that has been used in the past
let { word } = model.getWordUntilPosition(pos);
if (word.length !== 0) {
return super.select(model, pos, items);
if (items.length === 0) {
return 0;
}
let lineSuffix = model.getLineContent(pos.lineNumber).substr(pos.column - 10, pos.column - 1);
const lineSuffix = model.getLineContent(pos.lineNumber).substr(pos.column - 10, pos.column - 1);
if (/\s$/.test(lineSuffix)) {
return super.select(model, pos, items);
}
let res = -1;
let topScore = items[0].score[0];
let indexPreselect = -1;
let indexRecency = -1;
let seq = -1;
for (let i = 0; i < items.length; i++) {
const { completion: suggestion } = items[i];
const key = `${model.getLanguageIdentifier().language}/${suggestion.label}`;
const item = this._cache.get(key);
if (item && item.touch > seq && item.type === suggestion.kind && item.insertText === suggestion.insertText) {
if (items[i].score[0] !== topScore) {
// consider only top items
break;
}
const key = `${model.getLanguageIdentifier().language}/${items[i].completion.label}`;
const item = this._cache.peek(key);
if (item && item.touch > seq && item.type === items[i].completion.kind && item.insertText === items[i].completion.insertText) {
seq = item.touch;
res = i;
indexRecency = i;
}
if (items[i].completion.preselect && indexPreselect === -1) {
// stop when seeing an auto-select-item
return indexPreselect = i;
}
}
if (res === -1) {
return super.select(model, pos, items);
if (indexRecency !== -1) {
return indexRecency;
} else if (indexPreselect !== -1) {
return indexPreselect;
} else {
return res;
return 0;
}
}
@@ -204,9 +213,9 @@ export class SuggestMemoryService extends Disposable implements ISuggestMemorySe
private readonly _storagePrefix = 'suggest/memories';
private readonly _persistSoon: RunOnceScheduler;
private _mode: MemMode;
private _shareMem: boolean;
private _strategy: Memory;
private _mode!: MemMode;
private _shareMem!: boolean;
private _strategy!: Memory;
constructor(
@IStorageService private readonly _storageService: IStorageService,

View File

@@ -92,8 +92,8 @@ export const enum State {
export class SuggestModel implements IDisposable {
private readonly _toDispose = new DisposableStore();
private _quickSuggestDelay: number;
private _triggerCharacterListener: IDisposable;
private _quickSuggestDelay: number = 10;
private _triggerCharacterListener?: IDisposable;
private readonly _triggerQuickSuggest = new TimeoutTimer();
private _state: State = State.Idle;
@@ -161,7 +161,8 @@ export class SuggestModel implements IDisposable {
}
dispose(): void {
dispose([this._onDidCancel, this._onDidSuggest, this._onDidTrigger, this._triggerCharacterListener, this._triggerQuickSuggest]);
dispose(this._triggerCharacterListener);
dispose([this._onDidCancel, this._onDidSuggest, this._onDidTrigger, this._triggerQuickSuggest]);
this._toDispose.dispose();
this._completionDisposables.dispose();
this.cancel();

View File

@@ -38,8 +38,6 @@ import { URI } from 'vs/base/common/uri';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { FileKind } from 'vs/platform/files/common/files';
import { MarkdownString } from 'vs/base/common/htmlContent';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
const expandSuggestionDocsByDefault = false;
@@ -117,7 +115,7 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData>
const text = append(container, $('.contents'));
const main = append(text, $('.main'));
data.iconLabel = new IconLabel(main, { supportHighlights: true });
data.iconLabel = new IconLabel(main, { supportHighlights: true, supportOcticons: true });
data.disposables.add(data.iconLabel);
data.typeLabel = append(main, $('span.type-label'));
@@ -231,17 +229,6 @@ const enum State {
}
let _explainMode = false;
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'suggest.toggleExplainMode',
handler() {
_explainMode = !_explainMode;
},
when: SuggestContext.Visible,
weight: KeybindingWeight.EditorContrib,
primary: KeyMod.CtrlCmd | KeyCode.US_SLASH,
});
class SuggestionDetails {
private el: HTMLElement;
@@ -253,7 +240,7 @@ class SuggestionDetails {
private docs: HTMLElement;
private ariaLabel: string | null;
private readonly disposables: DisposableStore;
private renderDisposeable: IDisposable;
private renderDisposeable?: IDisposable;
private borderWidth: number = 1;
constructor(
@@ -300,13 +287,13 @@ class SuggestionDetails {
this.docs.textContent = '';
}
renderItem(item: CompletionItem): void {
renderItem(item: CompletionItem, explainMode: boolean): void {
this.renderDisposeable = dispose(this.renderDisposeable);
let { documentation, detail } = item.completion;
// --- documentation
if (_explainMode) {
if (explainMode) {
let md = '';
md += `score: ${item.score[0]}${item.word ? `, compared '${item.completion.filterText && (item.completion.filterText + ' (filterText)') || item.completion.label}' with '${item.word}'` : ' (no prefix)'}\n`;
md += `distance: ${item.distance}, see localityBonus-setting\n`;
@@ -315,7 +302,7 @@ class SuggestionDetails {
detail = `Provider: ${item.provider._debugDisplayName}`;
}
if (!_explainMode && !canExpandCompletionItem(item)) {
if (!explainMode && !canExpandCompletionItem(item)) {
this.type.textContent = '';
this.docs.textContent = '';
addClass(this.el, 'no-docs');
@@ -435,25 +422,24 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
readonly allowEditorOverflow = true;
readonly suppressMouseDown = true;
private state: State | null;
private isAuto: boolean;
private state: State | null = null;
private isAuto: boolean = false;
private loadingTimeout: IDisposable = Disposable.None;
private currentSuggestionDetails: CancelablePromise<void> | null;
private currentSuggestionDetails: CancelablePromise<void> | null = null;
private focusedItem: CompletionItem | null;
private ignoreFocusEvents = false;
private completionModel: CompletionModel | null;
private ignoreFocusEvents: boolean = false;
private completionModel: CompletionModel | null = null;
private element: HTMLElement;
private messageElement: HTMLElement;
private listElement: HTMLElement;
private details: SuggestionDetails;
private list: List<CompletionItem>;
private listHeight: number;
private listHeight?: number;
private readonly suggestWidgetVisible: IContextKey<boolean>;
private readonly suggestWidgetMultipleSuggestions: IContextKey<boolean>;
private readonly editorBlurTimeout = new TimeoutTimer();
private readonly showTimeout = new TimeoutTimer();
private readonly toDispose = new DisposableStore();
@@ -470,13 +456,14 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
private readonly maxWidgetWidth = 660;
private readonly listWidth = 330;
private readonly storageService: IStorageService;
private detailsFocusBorderColor: string;
private detailsBorderColor: string;
private detailsFocusBorderColor?: string;
private detailsBorderColor?: string;
private firstFocusInCurrentList: boolean = false;
private preferDocPositionTop: boolean = false;
private docsPositionPreviousWidgetY: number | null;
private docsPositionPreviousWidgetY: number | null = null;
private explainMode: boolean = false;
constructor(
private readonly editor: ICodeEditor,
@@ -594,7 +581,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
}
}
private _lastAriaAlertLabel: string | null;
private _lastAriaAlertLabel: string | null = null;
private _ariaAlert(newAriaAlertLabel: string | null): void {
if (this._lastAriaAlertLabel === newAriaAlertLabel) {
return;
@@ -974,12 +961,14 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.expandSideOrBelow();
show(this.details.element);
this.details.element.style.maxHeight = this.maxWidgetHeight + 'px';
if (loading) {
this.details.renderLoading();
} else {
this.details.renderItem(this.list.getFocusedElements()[0]);
this.details.renderItem(this.list.getFocusedElements()[0], this.explainMode);
}
this.details.element.style.maxHeight = this.maxWidgetHeight + 'px';
// Reset margin-top that was set as Fix for #26416
this.listElement.style.marginTop = '0px';
@@ -992,6 +981,13 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.editor.focus();
}
toggleExplainMode(): void {
if (this.list.getFocusedElements()[0] && this.expandDocsSettingFromStorage()) {
this.explainMode = !this.explainMode;
this.showDetails(false);
}
}
private show(): void {
const newHeight = this.updateListHeight();
if (newHeight !== this.listHeight) {
@@ -1162,7 +1158,6 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.list.dispose();
this.toDispose.dispose();
this.loadingTimeout.dispose();
this.editorBlurTimeout.dispose();
this.showTimeout.dispose();
}
}

View File

@@ -101,6 +101,29 @@ suite('SuggestMemories', function () {
]), 0);
});
test('`"editor.suggestSelection": "recentlyUsed"` should be a little more sticky #78571', function () {
let item1 = createSuggestItem('gamma', 0);
let item2 = createSuggestItem('game', 0);
items = [item1, item2];
let mem = new LRUMemory();
buffer.setValue(' foo.');
mem.memorize(buffer, { lineNumber: 1, column: 1 }, item2);
assert.equal(mem.select(buffer, { lineNumber: 1, column: 2 }, items), 0); // leading whitespace -> ignore recent items
mem.memorize(buffer, { lineNumber: 1, column: 9 }, item2);
assert.equal(mem.select(buffer, { lineNumber: 1, column: 9 }, items), 1); // foo.
buffer.setValue(' foo.g');
assert.equal(mem.select(buffer, { lineNumber: 1, column: 10 }, items), 1); // foo.g, 'gamma' and 'game' have the same score
item1.score = [10, 0, 0];
assert.equal(mem.select(buffer, { lineNumber: 1, column: 10 }, items), 0); // foo.g, 'gamma' has higher score
});
test('intellisense is not showing top options first #43429', function () {
// ensure we don't memorize for whitespace prefixes

View File

@@ -13,7 +13,7 @@ export class WordContextKey extends Disposable {
private readonly _ckAtEnd: IContextKey<boolean>;
private _enabled: boolean;
private _enabled: boolean = false;
private _selectionListener?: IDisposable;
constructor(