From 6708b0214e28fc2def315350444384e373cd79b8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 4 Dec 2015 10:05:50 +0100 Subject: [PATCH] debt - remove ISuggestion#hightlights --- src/vs/editor/common/modes.ts | 34 ++---------- src/vs/editor/common/modes/abstractMode.ts | 2 +- .../editor/common/modes/abstractModeWorker.ts | 8 +-- src/vs/editor/common/modes/modesFilters.ts | 34 ++++++------ src/vs/editor/common/modes/supports.ts | 2 +- .../contrib/suggest/browser/suggestModel.ts | 54 ++++++++++--------- .../contrib/suggest/browser/suggestWidget.ts | 2 +- 7 files changed, 59 insertions(+), 77 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index e4f5458881f..75594911376 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -5,6 +5,7 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; +import {IMatch} from 'vs/base/common/filters'; import {IMarker, IMarkerService} from 'vs/platform/markers/common/markers'; import EditorCommon = require('vs/editor/common/editorCommon'); import {IHTMLContentElement} from 'vs/base/common/htmlContent'; @@ -29,7 +30,7 @@ export interface IValidateParticipant extends IWorkerParticipant { } export interface ISuggestParticipant extends IWorkerParticipant { - filter?:(word:string, suggestion:ISuggestion) => boolean; + filter?:(word:string, suggestion:ISuggestion) => IMatch[]; suggest?:(resource:URI, position:EditorCommon.IPosition, context?:any) => TPromise; } @@ -396,7 +397,6 @@ export interface ISuggestion { codeSnippet: string; type: string; textEdit?: EditorCommon.ISingleEditOperation; - highlights?: IHighlight[]; typeLabel?: string; documentationLabel?: string; filterText?: string; @@ -404,30 +404,6 @@ export interface ISuggestion { noAutoAccept?: boolean; } -/** - * Returns true if the provided object looks like - * an ISuggestion. That means they are structural - * compatible. - */ -export function isISuggestion(obj:any):boolean { - if(obj === null || typeof obj !== 'object') { - return false; - } - if(typeof obj.label !== 'string' || typeof obj.codeSnippet !== 'string' || typeof obj.type !== 'string') { - return false; - } - if(obj.highlights && !Array.isArray(obj.highlights)) { - return false; - } - if(obj.typeLabel && typeof obj.typeLabel !== 'string') { - return false; - } - if(obj.documentationLabel && typeof obj.documentationLabel !== 'string') { - return false; - } - return true; -} - export interface ISuggestResult { currentWord: string; suggestions:ISuggestion[]; @@ -436,9 +412,9 @@ export interface ISuggestResult { overwriteAfter?: number; } -export interface IFilter { +export interface ISuggestionFilter { // Should return whether `suggestion` is a good suggestion for `word` - (word:string, suggestion:ISuggestion):boolean; + (word: string, suggestion: ISuggestion): IMatch[]; } export interface ISorter { @@ -460,7 +436,7 @@ export interface ISuggestSupport { */ getSuggestionDetails?:(resource:URI, position:EditorCommon.IPosition, suggestion:ISuggestion)=>TPromise; - getFilter():IFilter; + getFilter():ISuggestionFilter; getSorter?():ISorter; getTriggerCharacters():string[]; shouldShowEmptySuggestionList():boolean; diff --git a/src/vs/editor/common/modes/abstractMode.ts b/src/vs/editor/common/modes/abstractMode.ts index fbb831df93d..040fac79b3f 100644 --- a/src/vs/editor/common/modes/abstractMode.ts +++ b/src/vs/editor/common/modes/abstractMode.ts @@ -138,7 +138,7 @@ export class AbstractMode implements Modes.IMode { return this._worker((w) => w.enableValidator()); } - public getFilter(): Modes.IFilter { + public getFilter(): Modes.ISuggestionFilter { return StrictPrefix; } diff --git a/src/vs/editor/common/modes/abstractModeWorker.ts b/src/vs/editor/common/modes/abstractModeWorker.ts index 858f8aa0fff..1115ba47ada 100644 --- a/src/vs/editor/common/modes/abstractModeWorker.ts +++ b/src/vs/editor/common/modes/abstractModeWorker.ts @@ -28,7 +28,7 @@ function isISuggestParticipant(thing:any):boolean { export class AbstractModeWorker { - static filter: Modes.IFilter = DefaultFilter; + static filter: Modes.ISuggestionFilter = DefaultFilter; private _validationParticipants:Modes.IValidateParticipant[] = []; private _suggestParticipants:Modes.ISuggestParticipant[] = []; @@ -152,7 +152,7 @@ export class AbstractModeWorker { } result.push( { currentWord: value.currentWord, - suggestions: value.suggestions.filter((element) => accept(values[i].currentWord, element)), + suggestions: value.suggestions.filter((element) => !!accept(values[i].currentWord, element)), incomplete: value.incomplete, overwriteBefore: value.overwriteBefore, overwriteAfter: value.overwriteAfter @@ -223,7 +223,7 @@ export class AbstractModeWorker { return []; } - private getSuggestionFilterMain():Modes.IFilter { + private getSuggestionFilterMain():Modes.ISuggestionFilter { var filter = this.getSuggestionFilter(); // Collect Suggestion Participants @@ -236,7 +236,7 @@ export class AbstractModeWorker { return filter; } - public getSuggestionFilter():Modes.IFilter { + public getSuggestionFilter():Modes.ISuggestionFilter { return AbstractModeWorker.filter; } diff --git a/src/vs/editor/common/modes/modesFilters.ts b/src/vs/editor/common/modes/modesFilters.ts index 671847fe071..d9276237c18 100644 --- a/src/vs/editor/common/modes/modesFilters.ts +++ b/src/vs/editor/common/modes/modesFilters.ts @@ -4,32 +4,34 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IFilter, ISuggestion} from 'vs/editor/common/modes'; -import Filters = require('vs/base/common/filters'); - -function wrapBaseFilter(filter:Filters.IFilter):IFilter { - return (word:string, suggestion:ISuggestion):boolean => { - var highlights = filter(word, suggestion.filterText || suggestion.label); - suggestion.highlights = highlights || []; - return !!highlights; +import {ISuggestionFilter, ISuggestion} from 'vs/editor/common/modes'; +import * as Filters from 'vs/base/common/filters'; +import {isFalsyOrEmpty} from 'vs/base/common/arrays'; + +export type IMatch = Filters.IMatch; + +function wrapBaseFilter(filter: Filters.IFilter): ISuggestionFilter { + return (word: string, suggestion: ISuggestion): Filters.IMatch[] => { + const result = filter(word, suggestion.filterText || suggestion.label); + return isFalsyOrEmpty(result) ? undefined : result; }; } -export var StrictPrefix: IFilter = wrapBaseFilter(Filters.matchesStrictPrefix); -export var Prefix:IFilter = wrapBaseFilter(Filters.matchesPrefix); -export var CamelCase: IFilter = wrapBaseFilter(Filters.matchesCamelCase); -export var ContiguousSubString:IFilter = wrapBaseFilter(Filters.matchesContiguousSubString); +export var StrictPrefix: ISuggestionFilter = wrapBaseFilter(Filters.matchesStrictPrefix); +export var Prefix: ISuggestionFilter = wrapBaseFilter(Filters.matchesPrefix); +export var CamelCase: ISuggestionFilter = wrapBaseFilter(Filters.matchesCamelCase); +export var ContiguousSubString: ISuggestionFilter = wrapBaseFilter(Filters.matchesContiguousSubString); // Combined Filters -export function or(first:IFilter, second:IFilter):IFilter { - return (word:string, suggestion:ISuggestion):boolean => { +export function or(first: ISuggestionFilter, second: ISuggestionFilter): ISuggestionFilter { + return (word: string, suggestion: ISuggestion): Filters.IMatch[] => { return first(word, suggestion) || second(word, suggestion); }; } -export function and(first:IFilter, second:IFilter):IFilter { - return (word:string, suggestion:ISuggestion):boolean => { +export function and(first: ISuggestionFilter, second: ISuggestionFilter): ISuggestionFilter { + return (word: string, suggestion: ISuggestion): Filters.IMatch[] => { return first(word, suggestion) && second(word, suggestion); }; } diff --git a/src/vs/editor/common/modes/supports.ts b/src/vs/editor/common/modes/supports.ts index bfd176affdc..55cbcddd391 100644 --- a/src/vs/editor/common/modes/supports.ts +++ b/src/vs/editor/common/modes/supports.ts @@ -772,7 +772,7 @@ export class SuggestSupport extends AbstractSupport implements Modes.ISuggestSup }); } - public getFilter(): Modes.IFilter { + public getFilter(): Modes.ISuggestionFilter { return DefaultFilter; } diff --git a/src/vs/editor/contrib/suggest/browser/suggestModel.ts b/src/vs/editor/contrib/suggest/browser/suggestModel.ts index 5d25cc9dcb8..0370a7288b7 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestModel.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestModel.ts @@ -11,11 +11,12 @@ import { EventEmitter, ListenerUnbind } from 'vs/base/common/eventEmitter'; import {onUnexpectedError, isPromiseCanceledError} from 'vs/base/common/errors'; import strings = require('vs/base/common/strings'); import URI from 'vs/base/common/uri'; +import {isFalsyOrEmpty} from 'vs/base/common/arrays'; import timer = require('vs/base/common/timer'); import { getSnippets } from 'vs/editor/common/modes/modesRegistry'; import EditorCommon = require('vs/editor/common/editorCommon'); import { ISuggestSupport, ISuggestResult, ISuggestion, ISorter } from 'vs/editor/common/modes'; -import {DefaultFilter} from 'vs/editor/common/modes/modesFilters'; +import {DefaultFilter, IMatch} from 'vs/editor/common/modes/modesFilters'; import { CodeSnippet } from 'vs/editor/contrib/snippet/common/snippet'; import { IDisposable, disposeAll } from 'vs/base/common/lifecycle'; import {SuggestRegistry, ISuggestResult2, suggest} from '../common/suggest'; @@ -36,9 +37,11 @@ export class CompletionItem { private static _idPool = 0; public id: string; - public support: ISuggestSupport; public suggestion: ISuggestion; + public highlights: IMatch[]; + public support: ISuggestSupport; public container: ISuggestResult; + private _resolveDetails:TPromise constructor(support: ISuggestSupport, suggestion: ISuggestion, container:ISuggestResult) { @@ -96,36 +99,37 @@ class RawModel { select(ctx: SuggestionContext): CompletionItem[] { let result: CompletionItem[] = []; - let seen: { [codeSnippet: string]: boolean } = Object.create(null); for (let item of this._items) { - RawModel._sortAndFilter(ctx, result, seen, item); + RawModel._sortAndFilter(item, ctx, result); } return result; } - private static _sortAndFilter(ctx: SuggestionContext, bucket: CompletionItem[], seen: { [codeSnippet: string]: boolean }, items: CompletionItem[]): void { - if (items && items.length) { - let compare = RawModel._compare; - let filter = DefaultFilter; - let [item] = items; - if (item.support) { - compare = item.support.getSorter && item.support.getSorter() || compare; - filter = item.support.getFilter && item.support.getFilter() || DefaultFilter; - } - - items = items - .filter(item => { - if (!seen[item.suggestion.codeSnippet]) { - seen[item.suggestion.codeSnippet] = true; - return filter(ctx.wordBefore, item.suggestion) - } - }) - .sort((a, b) => { - return compare(a.suggestion, b.suggestion) - }); + private static _sortAndFilter(items: CompletionItem[], ctx: SuggestionContext, bucket: CompletionItem[]): void { + if (isFalsyOrEmpty(items)) { + return; + } - bucket.push(...items); + // all items have the same (origin) support. derive sorter and filter + // from first + const [first] = items; + let compare = RawModel._compare; + let filter = DefaultFilter; + if (first.support) { + compare = first.support.getSorter && first.support.getSorter() || compare; + filter = first.support.getFilter && first.support.getFilter() || filter; } + + items = items.filter(item => { + // set hightlight and filter those that have none + item.highlights = filter(ctx.wordBefore, item.suggestion); + return !isFalsyOrEmpty(item.highlights); + }).sort((a, b) => { + // sort suggestions by custom strategy + return compare(a.suggestion, b.suggestion) + }); + + bucket.push(...items); } private static _compare(a: ISuggestion, b: ISuggestion):number { diff --git a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts index daae94af704..d435772aea0 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts @@ -203,7 +203,7 @@ class Renderer implements Tree.IRenderer { data.colorspan.style.backgroundColor = ''; } - data.highlightedLabel.set(suggestion.label, suggestion.highlights); + data.highlightedLabel.set(suggestion.label, ( element).highlights); data.typeLabel.textContent = suggestion.typeLabel || ''; data.documentationLabel.textContent = suggestion.documentationLabel || ''; } -- GitLab