Merge from vscode 2e5312cd61ff99c570299ecc122c52584265eda2

This commit is contained in:
ADS Merger
2020-04-23 02:50:35 +00:00
committed by Anthony Dresser
parent 3603f55d97
commit 7f1d8fc32f
659 changed files with 22709 additions and 12497 deletions

View File

@@ -822,6 +822,7 @@ export const EventType = {
MOUSE_OUT: 'mouseout',
MOUSE_ENTER: 'mouseenter',
MOUSE_LEAVE: 'mouseleave',
MOUSE_WHEEL: browser.isEdge ? 'mousewheel' : 'wheel',
POINTER_UP: 'pointerup',
POINTER_DOWN: 'pointerdown',
POINTER_MOVE: 'pointermove',

View File

@@ -197,8 +197,8 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
const renderedMarkdown = marked.parse(
markdown.supportThemeIcons
? markdownEscapeEscapedCodicons(markdown.value)
: markdown.value,
? markdownEscapeEscapedCodicons(markdown.value || '')
: (markdown.value || ''),
markedOptions
);

View File

@@ -80,15 +80,11 @@ export class StandardMouseEvent implements IMouseEvent {
}
public preventDefault(): void {
if (this.browserEvent.preventDefault) {
this.browserEvent.preventDefault();
}
this.browserEvent.preventDefault();
}
public stopPropagation(): void {
if (this.browserEvent.stopPropagation) {
this.browserEvent.stopPropagation();
}
this.browserEvent.stopPropagation();
}
}
@@ -208,17 +204,13 @@ export class StandardWheelEvent {
public preventDefault(): void {
if (this.browserEvent) {
if (this.browserEvent.preventDefault) {
this.browserEvent.preventDefault();
}
this.browserEvent.preventDefault();
}
}
public stopPropagation(): void {
if (this.browserEvent) {
if (this.browserEvent.stopPropagation) {
this.browserEvent.stopPropagation();
}
this.browserEvent.stopPropagation();
}
}
}

View File

@@ -136,7 +136,7 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
if (platform.isMacintosh) {
// macOS: allow to trigger the button when holding Ctrl+key and pressing the
// main mouse button. This is for scenarios where e.g. some interaction forces
// main mouse button. This is for scenarios where e.g. some interaction forces
// the Ctrl+key to be pressed and hold but the user still wants to interact
// with the actions (for example quick access in quick navigation mode).
this._register(DOM.addDisposableListener(element, DOM.EventType.CONTEXT_MENU, e => {
@@ -276,7 +276,6 @@ export class ActionViewItem extends BaseActionViewItem {
this.label = DOM.append(this.element, DOM.$('a.action-label'));
}
if (this.label) {
if (this._action.id === Separator.ID) {
this.label.setAttribute('role', 'presentation'); // A separator is a presentation item

View File

@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./aria';
import * as nls from 'vs/nls';
import { isMacintosh } from 'vs/base/common/platform';
import * as dom from 'vs/base/browser/dom';
@@ -23,7 +22,8 @@ export function setARIAContainer(parent: HTMLElement) {
statusContainer = document.createElement('div');
statusContainer.className = 'monaco-status';
statusContainer.setAttribute('role', 'status');
statusContainer.setAttribute('role', 'complementary');
statusContainer.setAttribute('aria-live', 'polite');
statusContainer.setAttribute('aria-atomic', 'true');
ariaContainer.appendChild(statusContainer);
@@ -33,51 +33,30 @@ export function setARIAContainer(parent: HTMLElement) {
/**
* Given the provided message, will make sure that it is read as alert to screen readers.
*/
export function alert(msg: string, disableRepeat?: boolean): void {
insertMessage(alertContainer, msg, disableRepeat);
export function alert(msg: string): void {
insertMessage(alertContainer, msg);
}
/**
* Given the provided message, will make sure that it is read as status to screen readers.
*/
export function status(msg: string, disableRepeat?: boolean): void {
export function status(msg: string): void {
if (isMacintosh) {
alert(msg, disableRepeat); // VoiceOver does not seem to support status role
alert(msg); // VoiceOver does not seem to support status role
} else {
insertMessage(statusContainer, msg, disableRepeat);
insertMessage(statusContainer, msg);
}
}
let repeatedTimes = 0;
let prevText: string | undefined = undefined;
function insertMessage(target: HTMLElement, msg: string, disableRepeat?: boolean): void {
function insertMessage(target: HTMLElement, msg: string): void {
if (!ariaContainer) {
return;
}
// If the same message should be inserted that is already present, a screen reader would
// not announce this message because it matches the previous one. As a workaround, we
// alter the message with the number of occurences unless this is explicitly disabled
// via the disableRepeat flag.
if (!disableRepeat) {
if (prevText === msg) {
repeatedTimes++;
} else {
prevText = msg;
repeatedTimes = 0;
}
switch (repeatedTimes) {
case 0: break;
case 1: msg = nls.localize('repeated', "{0} (occurred again)", msg); break;
default: msg = nls.localize('repeatedNtimes', "{0} (occurred {1} times)", msg, repeatedTimes); break;
}
}
dom.clearNode(target);
target.textContent = msg;
// See https://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/
target.style.visibility = 'hidden';
target.style.visibility = 'visible';
}
}

View File

@@ -25,7 +25,7 @@
outline: none;
}
.monaco-breadcrumbs .monaco-breadcrumb-item .codicon-chevron-right {
.monaco-breadcrumbs .monaco-breadcrumb-item .codicon-breadcrumb-separator {
color: inherit;
}

View File

@@ -11,6 +11,7 @@ import { Color } from 'vs/base/common/color';
import { Emitter, Event } from 'vs/base/common/event';
import { dispose, IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { Codicon, registerIcon } from 'vs/base/common/codicons';
import 'vs/css!./breadcrumbsWidget';
export abstract class BreadcrumbsItem {
@@ -55,6 +56,8 @@ export interface IBreadcrumbsItemEvent {
payload: any;
}
const breadcrumbSeparatorIcon = registerIcon('breadcrumb-separator', Codicon.chevronRight);
export class BreadcrumbsWidget {
private readonly _disposables = new DisposableStore();
@@ -336,7 +339,7 @@ export class BreadcrumbsWidget {
container.tabIndex = -1;
container.setAttribute('role', 'listitem');
dom.addClasses(container, 'monaco-breadcrumb-item');
const iconContainer = dom.$('.codicon.codicon-chevron-right');
const iconContainer = dom.$(breadcrumbSeparatorIcon.cssSelector);
container.appendChild(iconContainer);
}

View File

@@ -10,12 +10,13 @@ import { Widget } from 'vs/base/browser/ui/widget';
import { Color } from 'vs/base/common/color';
import { Emitter, Event } from 'vs/base/common/event';
import { KeyCode } from 'vs/base/common/keyCodes';
import * as objects from 'vs/base/common/objects';
import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { Codicon } from 'vs/base/common/codicons';
export interface ICheckboxOpts extends ICheckboxStyles {
readonly actionClassName?: string;
readonly icon?: Codicon;
readonly title: string;
readonly isChecked: boolean;
}
@@ -93,13 +94,23 @@ export class Checkbox extends Widget {
constructor(opts: ICheckboxOpts) {
super();
this._opts = objects.deepClone(opts);
objects.mixin(this._opts, defaultOpts, false);
this._opts = { ...defaultOpts, ...opts };
this._checked = this._opts.isChecked;
const classes = ['monaco-custom-checkbox'];
if (this._opts.icon) {
classes.push(this._opts.icon.classNames);
} else {
classes.push('codicon'); // todo@aeschli: remove once codicon fully adopted
}
if (this._opts.actionClassName) {
classes.push(this._opts.actionClassName);
}
classes.push(this._checked ? 'checked' : 'unchecked');
this.domNode = document.createElement('div');
this.domNode.title = this._opts.title;
this.domNode.className = 'monaco-custom-checkbox codicon ' + (this._opts.actionClassName || '') + ' ' + (this._checked ? 'checked' : 'unchecked');
this.domNode.className = classes.join(' ');
this.domNode.tabIndex = 0;
this.domNode.setAttribute('role', 'checkbox');
this.domNode.setAttribute('aria-checked', String(this._checked));
@@ -192,7 +203,7 @@ export class SimpleCheckbox extends Widget {
constructor(private title: string, private isChecked: boolean) {
super();
this.checkbox = new Checkbox({ title: this.title, isChecked: this.isChecked, actionClassName: 'monaco-simple-checkbox codicon-check' });
this.checkbox = new Checkbox({ title: this.title, isChecked: this.isChecked, icon: Codicon.check, actionClassName: 'monaco-simple-checkbox' });
this.domNode = this.checkbox.domNode;

View File

@@ -1,427 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
@font-face {
font-family: "codicon";
src: url("./codicon.ttf?a76e99e42eab7c1a55601640b708d820") format("truetype");
}
.codicon[class*='codicon-'] {
font: normal normal normal 16px/1 codicon;
display: inline-block;
text-decoration: none;
text-rendering: auto;
text-align: center;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.codicon-add:before { content: "\ea60" }
.codicon-plus:before { content: "\ea60" }
.codicon-gist-new:before { content: "\ea60" }
.codicon-repo-create:before { content: "\ea60" }
.codicon-lightbulb:before { content: "\ea61" }
.codicon-light-bulb:before { content: "\ea61" }
.codicon-repo:before { content: "\ea62" }
.codicon-repo-delete:before { content: "\ea62" }
.codicon-gist-fork:before { content: "\ea63" }
.codicon-repo-forked:before { content: "\ea63" }
.codicon-git-pull-request:before { content: "\ea64" }
.codicon-git-pull-request-abandoned:before { content: "\ea64" }
.codicon-record-keys:before { content: "\ea65" }
.codicon-keyboard:before { content: "\ea65" }
.codicon-tag:before { content: "\ea66" }
.codicon-tag-add:before { content: "\ea66" }
.codicon-tag-remove:before { content: "\ea66" }
.codicon-person:before { content: "\ea67" }
.codicon-person-add:before { content: "\ea67" }
.codicon-person-follow:before { content: "\ea67" }
.codicon-person-outline:before { content: "\ea67" }
.codicon-person-filled:before { content: "\ea67" }
.codicon-git-branch:before { content: "\ea68" }
.codicon-git-branch-create:before { content: "\ea68" }
.codicon-git-branch-delete:before { content: "\ea68" }
.codicon-source-control:before { content: "\ea68" }
.codicon-mirror:before { content: "\ea69" }
.codicon-mirror-public:before { content: "\ea69" }
.codicon-star:before { content: "\ea6a" }
.codicon-star-add:before { content: "\ea6a" }
.codicon-star-delete:before { content: "\ea6a" }
.codicon-star-empty:before { content: "\ea6a" }
.codicon-comment:before { content: "\ea6b" }
.codicon-comment-add:before { content: "\ea6b" }
.codicon-alert:before { content: "\ea6c" }
.codicon-warning:before { content: "\ea6c" }
.codicon-search:before { content: "\ea6d" }
.codicon-search-save:before { content: "\ea6d" }
.codicon-log-out:before { content: "\ea6e" }
.codicon-sign-out:before { content: "\ea6e" }
.codicon-log-in:before { content: "\ea6f" }
.codicon-sign-in:before { content: "\ea6f" }
.codicon-eye:before { content: "\ea70" }
.codicon-eye-unwatch:before { content: "\ea70" }
.codicon-eye-watch:before { content: "\ea70" }
.codicon-circle-filled:before { content: "\ea71" }
.codicon-primitive-dot:before { content: "\ea71" }
.codicon-close-dirty:before { content: "\ea71" }
.codicon-debug-breakpoint:before { content: "\ea71" }
.codicon-debug-breakpoint-disabled:before { content: "\ea71" }
.codicon-debug-hint:before { content: "\ea71" }
.codicon-primitive-square:before { content: "\ea72" }
.codicon-edit:before { content: "\ea73" }
.codicon-pencil:before { content: "\ea73" }
.codicon-info:before { content: "\ea74" }
.codicon-issue-opened:before { content: "\ea74" }
.codicon-gist-private:before { content: "\ea75" }
.codicon-git-fork-private:before { content: "\ea75" }
.codicon-lock:before { content: "\ea75" }
.codicon-mirror-private:before { content: "\ea75" }
.codicon-close:before { content: "\ea76" }
.codicon-remove-close:before { content: "\ea76" }
.codicon-x:before { content: "\ea76" }
.codicon-repo-sync:before { content: "\ea77" }
.codicon-sync:before { content: "\ea77" }
.codicon-clone:before { content: "\ea78" }
.codicon-desktop-download:before { content: "\ea78" }
.codicon-beaker:before { content: "\ea79" }
.codicon-microscope:before { content: "\ea79" }
.codicon-vm:before { content: "\ea7a" }
.codicon-device-desktop:before { content: "\ea7a" }
.codicon-file:before { content: "\ea7b" }
.codicon-file-text:before { content: "\ea7b" }
.codicon-more:before { content: "\ea7c" }
.codicon-ellipsis:before { content: "\ea7c" }
.codicon-kebab-horizontal:before { content: "\ea7c" }
.codicon-mail-reply:before { content: "\ea7d" }
.codicon-reply:before { content: "\ea7d" }
.codicon-organization:before { content: "\ea7e" }
.codicon-organization-filled:before { content: "\ea7e" }
.codicon-organization-outline:before { content: "\ea7e" }
.codicon-new-file:before { content: "\ea7f" }
.codicon-file-add:before { content: "\ea7f" }
.codicon-new-folder:before { content: "\ea80" }
.codicon-file-directory-create:before { content: "\ea80" }
.codicon-trash:before { content: "\ea81" }
.codicon-trashcan:before { content: "\ea81" }
.codicon-history:before { content: "\ea82" }
.codicon-clock:before { content: "\ea82" }
.codicon-folder:before { content: "\ea83" }
.codicon-file-directory:before { content: "\ea83" }
.codicon-symbol-folder:before { content: "\ea83" }
.codicon-logo-github:before { content: "\ea84" }
.codicon-mark-github:before { content: "\ea84" }
.codicon-github:before { content: "\ea84" }
.codicon-terminal:before { content: "\ea85" }
.codicon-console:before { content: "\ea85" }
.codicon-repl:before { content: "\ea85" }
.codicon-zap:before { content: "\ea86" }
.codicon-symbol-event:before { content: "\ea86" }
.codicon-error:before { content: "\ea87" }
.codicon-stop:before { content: "\ea87" }
.codicon-variable:before { content: "\ea88" }
.codicon-symbol-variable:before { content: "\ea88" }
.codicon-array:before { content: "\ea8a" }
.codicon-symbol-array:before { content: "\ea8a" }
.codicon-symbol-module:before { content: "\ea8b" }
.codicon-symbol-package:before { content: "\ea8b" }
.codicon-symbol-namespace:before { content: "\ea8b" }
.codicon-symbol-object:before { content: "\ea8b" }
.codicon-symbol-method:before { content: "\ea8c" }
.codicon-symbol-function:before { content: "\ea8c" }
.codicon-symbol-constructor:before { content: "\ea8c" }
.codicon-symbol-boolean:before { content: "\ea8f" }
.codicon-symbol-null:before { content: "\ea8f" }
.codicon-symbol-numeric:before { content: "\ea90" }
.codicon-symbol-number:before { content: "\ea90" }
.codicon-symbol-structure:before { content: "\ea91" }
.codicon-symbol-struct:before { content: "\ea91" }
.codicon-symbol-parameter:before { content: "\ea92" }
.codicon-symbol-type-parameter:before { content: "\ea92" }
.codicon-symbol-key:before { content: "\ea93" }
.codicon-symbol-text:before { content: "\ea93" }
.codicon-symbol-reference:before { content: "\ea94" }
.codicon-go-to-file:before { content: "\ea94" }
.codicon-symbol-enum:before { content: "\ea95" }
.codicon-symbol-value:before { content: "\ea95" }
.codicon-symbol-ruler:before { content: "\ea96" }
.codicon-symbol-unit:before { content: "\ea96" }
.codicon-activate-breakpoints:before { content: "\ea97" }
.codicon-archive:before { content: "\ea98" }
.codicon-arrow-both:before { content: "\ea99" }
.codicon-arrow-down:before { content: "\ea9a" }
.codicon-arrow-left:before { content: "\ea9b" }
.codicon-arrow-right:before { content: "\ea9c" }
.codicon-arrow-small-down:before { content: "\ea9d" }
.codicon-arrow-small-left:before { content: "\ea9e" }
.codicon-arrow-small-right:before { content: "\ea9f" }
.codicon-arrow-small-up:before { content: "\eaa0" }
.codicon-arrow-up:before { content: "\eaa1" }
.codicon-bell:before { content: "\eaa2" }
.codicon-bold:before { content: "\eaa3" }
.codicon-book:before { content: "\eaa4" }
.codicon-bookmark:before { content: "\eaa5" }
.codicon-debug-breakpoint-conditional-unverified:before { content: "\eaa6" }
.codicon-debug-breakpoint-conditional:before { content: "\eaa7" }
.codicon-debug-breakpoint-conditional-disabled:before { content: "\eaa7" }
.codicon-debug-breakpoint-data-unverified:before { content: "\eaa8" }
.codicon-debug-breakpoint-data:before { content: "\eaa9" }
.codicon-debug-breakpoint-data-disabled:before { content: "\eaa9" }
.codicon-debug-breakpoint-log-unverified:before { content: "\eaaa" }
.codicon-debug-breakpoint-log:before { content: "\eaab" }
.codicon-debug-breakpoint-log-disabled:before { content: "\eaab" }
.codicon-briefcase:before { content: "\eaac" }
.codicon-broadcast:before { content: "\eaad" }
.codicon-browser:before { content: "\eaae" }
.codicon-bug:before { content: "\eaaf" }
.codicon-calendar:before { content: "\eab0" }
.codicon-case-sensitive:before { content: "\eab1" }
.codicon-check:before { content: "\eab2" }
.codicon-checklist:before { content: "\eab3" }
.codicon-chevron-down:before { content: "\eab4" }
.codicon-chevron-left:before { content: "\eab5" }
.codicon-chevron-right:before { content: "\eab6" }
.codicon-chevron-up:before { content: "\eab7" }
.codicon-chrome-close:before { content: "\eab8" }
.codicon-chrome-maximize:before { content: "\eab9" }
.codicon-chrome-minimize:before { content: "\eaba" }
.codicon-chrome-restore:before { content: "\eabb" }
.codicon-circle-outline:before { content: "\eabc" }
.codicon-debug-breakpoint-unverified:before { content: "\eabc" }
.codicon-circle-slash:before { content: "\eabd" }
.codicon-circuit-board:before { content: "\eabe" }
.codicon-clear-all:before { content: "\eabf" }
.codicon-clippy:before { content: "\eac0" }
.codicon-close-all:before { content: "\eac1" }
.codicon-cloud-download:before { content: "\eac2" }
.codicon-cloud-upload:before { content: "\eac3" }
.codicon-code:before { content: "\eac4" }
.codicon-collapse-all:before { content: "\eac5" }
.codicon-color-mode:before { content: "\eac6" }
.codicon-comment-discussion:before { content: "\eac7" }
.codicon-compare-changes:before { content: "\eac8" }
.codicon-credit-card:before { content: "\eac9" }
.codicon-dash:before { content: "\eacc" }
.codicon-dashboard:before { content: "\eacd" }
.codicon-database:before { content: "\eace" }
.codicon-debug-continue:before { content: "\eacf" }
.codicon-debug-disconnect:before { content: "\ead0" }
.codicon-debug-pause:before { content: "\ead1" }
.codicon-debug-restart:before { content: "\ead2" }
.codicon-debug-start:before { content: "\ead3" }
.codicon-debug-step-into:before { content: "\ead4" }
.codicon-debug-step-out:before { content: "\ead5" }
.codicon-debug-step-over:before { content: "\ead6" }
.codicon-debug-stop:before { content: "\ead7" }
.codicon-debug:before { content: "\ead8" }
.codicon-device-camera-video:before { content: "\ead9" }
.codicon-device-camera:before { content: "\eada" }
.codicon-device-mobile:before { content: "\eadb" }
.codicon-diff-added:before { content: "\eadc" }
.codicon-diff-ignored:before { content: "\eadd" }
.codicon-diff-modified:before { content: "\eade" }
.codicon-diff-removed:before { content: "\eadf" }
.codicon-diff-renamed:before { content: "\eae0" }
.codicon-diff:before { content: "\eae1" }
.codicon-discard:before { content: "\eae2" }
.codicon-editor-layout:before { content: "\eae3" }
.codicon-empty-window:before { content: "\eae4" }
.codicon-exclude:before { content: "\eae5" }
.codicon-extensions:before { content: "\eae6" }
.codicon-eye-closed:before { content: "\eae7" }
.codicon-file-binary:before { content: "\eae8" }
.codicon-file-code:before { content: "\eae9" }
.codicon-file-media:before { content: "\eaea" }
.codicon-file-pdf:before { content: "\eaeb" }
.codicon-file-submodule:before { content: "\eaec" }
.codicon-file-symlink-directory:before { content: "\eaed" }
.codicon-file-symlink-file:before { content: "\eaee" }
.codicon-file-zip:before { content: "\eaef" }
.codicon-files:before { content: "\eaf0" }
.codicon-filter:before { content: "\eaf1" }
.codicon-flame:before { content: "\eaf2" }
.codicon-fold-down:before { content: "\eaf3" }
.codicon-fold-up:before { content: "\eaf4" }
.codicon-fold:before { content: "\eaf5" }
.codicon-folder-active:before { content: "\eaf6" }
.codicon-folder-opened:before { content: "\eaf7" }
.codicon-gear:before { content: "\eaf8" }
.codicon-gift:before { content: "\eaf9" }
.codicon-gist-secret:before { content: "\eafa" }
.codicon-gist:before { content: "\eafb" }
.codicon-git-commit:before { content: "\eafc" }
.codicon-git-compare:before { content: "\eafd" }
.codicon-git-merge:before { content: "\eafe" }
.codicon-github-action:before { content: "\eaff" }
.codicon-github-alt:before { content: "\eb00" }
.codicon-globe:before { content: "\eb01" }
.codicon-grabber:before { content: "\eb02" }
.codicon-graph:before { content: "\eb03" }
.codicon-gripper:before { content: "\eb04" }
.codicon-heart:before { content: "\eb05" }
.codicon-home:before { content: "\eb06" }
.codicon-horizontal-rule:before { content: "\eb07" }
.codicon-hubot:before { content: "\eb08" }
.codicon-inbox:before { content: "\eb09" }
.codicon-issue-closed:before { content: "\eb0a" }
.codicon-issue-reopened:before { content: "\eb0b" }
.codicon-issues:before { content: "\eb0c" }
.codicon-italic:before { content: "\eb0d" }
.codicon-jersey:before { content: "\eb0e" }
.codicon-json:before { content: "\eb0f" }
.codicon-kebab-vertical:before { content: "\eb10" }
.codicon-key:before { content: "\eb11" }
.codicon-law:before { content: "\eb12" }
.codicon-lightbulb-autofix:before { content: "\eb13" }
.codicon-link-external:before { content: "\eb14" }
.codicon-link:before { content: "\eb15" }
.codicon-list-ordered:before { content: "\eb16" }
.codicon-list-unordered:before { content: "\eb17" }
.codicon-live-share:before { content: "\eb18" }
.codicon-loading:before { content: "\eb19" }
.codicon-location:before { content: "\eb1a" }
.codicon-mail-read:before { content: "\eb1b" }
.codicon-mail:before { content: "\eb1c" }
.codicon-markdown:before { content: "\eb1d" }
.codicon-megaphone:before { content: "\eb1e" }
.codicon-mention:before { content: "\eb1f" }
.codicon-milestone:before { content: "\eb20" }
.codicon-mortar-board:before { content: "\eb21" }
.codicon-move:before { content: "\eb22" }
.codicon-multiple-windows:before { content: "\eb23" }
.codicon-mute:before { content: "\eb24" }
.codicon-no-newline:before { content: "\eb25" }
.codicon-note:before { content: "\eb26" }
.codicon-octoface:before { content: "\eb27" }
.codicon-open-preview:before { content: "\eb28" }
.codicon-package:before { content: "\eb29" }
.codicon-paintcan:before { content: "\eb2a" }
.codicon-pin:before { content: "\eb2b" }
.codicon-play:before { content: "\eb2c" }
.codicon-run:before { content: "\eb2c" }
.codicon-plug:before { content: "\eb2d" }
.codicon-preserve-case:before { content: "\eb2e" }
.codicon-preview:before { content: "\eb2f" }
.codicon-project:before { content: "\eb30" }
.codicon-pulse:before { content: "\eb31" }
.codicon-question:before { content: "\eb32" }
.codicon-quote:before { content: "\eb33" }
.codicon-radio-tower:before { content: "\eb34" }
.codicon-reactions:before { content: "\eb35" }
.codicon-references:before { content: "\eb36" }
.codicon-refresh:before { content: "\eb37" }
.codicon-regex:before { content: "\eb38" }
.codicon-remote-explorer:before { content: "\eb39" }
.codicon-remote:before { content: "\eb3a" }
.codicon-remove:before { content: "\eb3b" }
.codicon-replace-all:before { content: "\eb3c" }
.codicon-replace:before { content: "\eb3d" }
.codicon-repo-clone:before { content: "\eb3e" }
.codicon-repo-force-push:before { content: "\eb3f" }
.codicon-repo-pull:before { content: "\eb40" }
.codicon-repo-push:before { content: "\eb41" }
.codicon-report:before { content: "\eb42" }
.codicon-request-changes:before { content: "\eb43" }
.codicon-rocket:before { content: "\eb44" }
.codicon-root-folder-opened:before { content: "\eb45" }
.codicon-root-folder:before { content: "\eb46" }
.codicon-rss:before { content: "\eb47" }
.codicon-ruby:before { content: "\eb48" }
.codicon-save-all:before { content: "\eb49" }
.codicon-save-as:before { content: "\eb4a" }
.codicon-save:before { content: "\eb4b" }
.codicon-screen-full:before { content: "\eb4c" }
.codicon-screen-normal:before { content: "\eb4d" }
.codicon-search-stop:before { content: "\eb4e" }
.codicon-server:before { content: "\eb50" }
.codicon-settings-gear:before { content: "\eb51" }
.codicon-settings:before { content: "\eb52" }
.codicon-shield:before { content: "\eb53" }
.codicon-smiley:before { content: "\eb54" }
.codicon-sort-precedence:before { content: "\eb55" }
.codicon-split-horizontal:before { content: "\eb56" }
.codicon-split-vertical:before { content: "\eb57" }
.codicon-squirrel:before { content: "\eb58" }
.codicon-star-full:before { content: "\eb59" }
.codicon-star-half:before { content: "\eb5a" }
.codicon-symbol-class:before { content: "\eb5b" }
.codicon-symbol-color:before { content: "\eb5c" }
.codicon-symbol-constant:before { content: "\eb5d" }
.codicon-symbol-enum-member:before { content: "\eb5e" }
.codicon-symbol-field:before { content: "\eb5f" }
.codicon-symbol-file:before { content: "\eb60" }
.codicon-symbol-interface:before { content: "\eb61" }
.codicon-symbol-keyword:before { content: "\eb62" }
.codicon-symbol-misc:before { content: "\eb63" }
.codicon-symbol-operator:before { content: "\eb64" }
.codicon-symbol-property:before { content: "\eb65" }
.codicon-wrench:before { content: "\eb65" }
.codicon-wrench-subaction:before { content: "\eb65" }
.codicon-symbol-snippet:before { content: "\eb66" }
.codicon-tasklist:before { content: "\eb67" }
.codicon-telescope:before { content: "\eb68" }
.codicon-text-size:before { content: "\eb69" }
.codicon-three-bars:before { content: "\eb6a" }
.codicon-thumbsdown:before { content: "\eb6b" }
.codicon-thumbsup:before { content: "\eb6c" }
.codicon-tools:before { content: "\eb6d" }
.codicon-triangle-down:before { content: "\eb6e" }
.codicon-triangle-left:before { content: "\eb6f" }
.codicon-triangle-right:before { content: "\eb70" }
.codicon-triangle-up:before { content: "\eb71" }
.codicon-twitter:before { content: "\eb72" }
.codicon-unfold:before { content: "\eb73" }
.codicon-unlock:before { content: "\eb74" }
.codicon-unmute:before { content: "\eb75" }
.codicon-unverified:before { content: "\eb76" }
.codicon-verified:before { content: "\eb77" }
.codicon-versions:before { content: "\eb78" }
.codicon-vm-active:before { content: "\eb79" }
.codicon-vm-outline:before { content: "\eb7a" }
.codicon-vm-running:before { content: "\eb7b" }
.codicon-watch:before { content: "\eb7c" }
.codicon-whitespace:before { content: "\eb7d" }
.codicon-whole-word:before { content: "\eb7e" }
.codicon-window:before { content: "\eb7f" }
.codicon-word-wrap:before { content: "\eb80" }
.codicon-zoom-in:before { content: "\eb81" }
.codicon-zoom-out:before { content: "\eb82" }
.codicon-list-filter:before { content: "\eb83" }
.codicon-list-flat:before { content: "\eb84" }
.codicon-list-selection:before { content: "\eb85" }
.codicon-selection:before { content: "\eb85" }
.codicon-list-tree:before { content: "\eb86" }
.codicon-debug-breakpoint-function-unverified:before { content: "\eb87" }
.codicon-debug-breakpoint-function:before { content: "\eb88" }
.codicon-debug-breakpoint-function-disabled:before { content: "\eb88" }
.codicon-debug-stackframe-active:before { content: "\eb89" }
.codicon-debug-stackframe-dot:before { content: "\eb8a" }
.codicon-debug-stackframe:before { content: "\eb8b" }
.codicon-debug-stackframe-focused:before { content: "\eb8b" }
.codicon-debug-breakpoint-unsupported:before { content: "\eb8c" }
.codicon-symbol-string:before { content: "\eb8d" }
.codicon-debug-reverse-continue:before { content: "\eb8e" }
.codicon-debug-step-back:before { content: "\eb8f" }
.codicon-debug-restart-frame:before { content: "\eb90" }
.codicon-debug-alternate:before { content: "\eb91" }
.codicon-call-incoming:before { content: "\eb92" }
.codicon-call-outgoing:before { content: "\eb93" }
.codicon-menu:before { content: "\eb94" }
.codicon-expand-all:before { content: "\eb95" }
.codicon-feedback:before { content: "\eb96" }
.codicon-group-by-ref-type:before { content: "\eb97" }
.codicon-ungroup-by-ref-type:before { content: "\eb98" }
.codicon-account:before { content: "\eb99" }
.codicon-bell-dot:before { content: "\eb9a" }
.codicon-debug-console:before { content: "\eb9b" }
.codicon-library:before { content: "\eb9c" }
.codicon-output:before { content: "\eb9d" }
.codicon-run-all:before { content: "\eb9e" }
.codicon-sync-ignored:before { content: "\eb9f" }
.codicon-debug-alt-2:before { content: "\f101" }
.codicon-debug-alt:before { content: "\f102" }

View File

@@ -0,0 +1,24 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
@font-face {
font-family: "codicon";
src: url("./codicon.ttf?5d4d76ab2ce5108968ad644d591a16a6") format("truetype");
}
.codicon[class*='codicon-'] {
font: normal normal normal 16px/1 codicon;
display: inline-block;
text-decoration: none;
text-rendering: auto;
text-align: center;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
/* icon rules are dynamically created in codiconStyles */

View File

@@ -3,9 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./codicon/codicon';
import 'vs/css!./codicon/codicon-modifications';
import 'vs/css!./codicon/codicon-animations';
import { escape } from 'vs/base/common/strings';
import { renderCodicons } from 'vs/base/common/codicons';

View File

@@ -0,0 +1,39 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./codicon/codicon';
import 'vs/css!./codicon/codicon-modifications';
import 'vs/css!./codicon/codicon-animations';
import { Codicon, iconRegistry } from 'vs/base/common/codicons';
import { createStyleSheet } from 'vs/base/browser/dom';
import { RunOnceScheduler } from 'vs/base/common/async';
function initialize() {
let codiconStyleSheet = createStyleSheet();
codiconStyleSheet.id = 'codiconStyles';
function updateAll() {
const rules = [];
for (let c of iconRegistry.all) {
rules.push(formatRule(c));
}
codiconStyleSheet.innerHTML = rules.join('\n');
}
const delayer = new RunOnceScheduler(updateAll, 0);
iconRegistry.onDidRegister(() => delayer.schedule());
delayer.schedule();
}
function formatRule(c: Codicon) {
let def = c.definition;
while (def instanceof Codicon) {
def = def.definition;
}
return `.codicon-${c.id}:before { content: '${def.character}'; }`;
}
initialize();

View File

@@ -6,7 +6,7 @@
import 'vs/css!./dialog';
import * as nls from 'vs/nls';
import { Disposable } from 'vs/base/common/lifecycle';
import { $, hide, show, EventHelper, clearNode, removeClasses, addClass, addClasses, removeNode, isAncestor, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { $, hide, show, EventHelper, clearNode, removeClasses, addClasses, removeNode, isAncestor, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { domEvent } from 'vs/base/browser/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
@@ -17,6 +17,7 @@ import { Action } from 'vs/base/common/actions';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { isMacintosh, isLinux } from 'vs/base/common/platform';
import { SimpleCheckbox, ISimpleCheckboxStyles } from 'vs/base/browser/ui/checkbox/checkbox';
import { Codicon, registerIcon } from 'vs/base/common/codicons';
export interface IDialogOptions {
cancelId?: number;
@@ -37,6 +38,9 @@ export interface IDialogStyles extends IButtonStyles, ISimpleCheckboxStyles {
dialogBackground?: Color;
dialogShadow?: Color;
dialogBorder?: Color;
errorIconForeground?: Color;
warningIconForeground?: Color;
infoIconForeground?: Color;
}
interface ButtonMapEntry {
@@ -44,6 +48,11 @@ interface ButtonMapEntry {
index: number;
}
const dialogErrorIcon = registerIcon('dialog-error', Codicon.error);
const dialogWarningIcon = registerIcon('dialog-warning', Codicon.warning);
const dialogInfoIcon = registerIcon('dialog-info', Codicon.info);
const dialogCloseIcon = registerIcon('dialog-close', Codicon.close);
export class Dialog extends Disposable {
private element: HTMLElement | undefined;
private shadowElement: HTMLElement | undefined;
@@ -202,30 +211,29 @@ export class Dialog extends Disposable {
}
}));
addClass(this.iconElement, 'codicon');
removeClasses(this.iconElement, 'codicon-alert', 'codicon-warning', 'codicon-info');
removeClasses(this.iconElement, dialogErrorIcon.classNames, dialogWarningIcon.classNames, dialogInfoIcon.classNames, Codicon.loading.classNames);
switch (this.options.type) {
case 'error':
addClass(this.iconElement, 'codicon-error');
addClasses(this.iconElement, dialogErrorIcon.classNames);
break;
case 'warning':
addClass(this.iconElement, 'codicon-warning');
addClasses(this.iconElement, dialogWarningIcon.classNames);
break;
case 'pending':
addClasses(this.iconElement, 'codicon-loading', 'codicon-animation-spin');
addClasses(this.iconElement, Codicon.loading.classNames, 'codicon-animation-spin');
break;
case 'none':
case 'info':
case 'question':
default:
addClass(this.iconElement, 'codicon-info');
addClasses(this.iconElement, dialogInfoIcon.classNames);
break;
}
const actionBar = new ActionBar(this.toolbarContainer, {});
const action = new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), 'codicon codicon-close', true, () => {
const action = new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), dialogCloseIcon.classNames, true, () => {
resolve({ button: this.options.cancelId || 0, checkboxChecked: this.checkbox ? this.checkbox.checked : undefined });
return Promise.resolve();
});
@@ -268,10 +276,28 @@ export class Dialog extends Disposable {
this.checkbox.style(style);
}
if (this.messageDetailElement) {
if (this.messageDetailElement && fgColor && bgColor) {
const messageDetailColor = Color.fromHex(fgColor).transparent(.9);
this.messageDetailElement.style.color = messageDetailColor.makeOpaque(Color.fromHex(bgColor)).toString();
}
if (this.iconElement) {
let color;
switch (this.options.type) {
case 'error':
color = style.errorIconForeground;
break;
case 'warning':
color = style.warningIconForeground;
break;
default:
color = style.infoIconForeground;
break;
}
if (color) {
this.iconElement.style.color = color.toString();
}
}
}
}

View File

@@ -295,7 +295,7 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
render(container: HTMLElement): void {
const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => {
this.element = append(el, $('a.action-label.codicon'));
this.element = append(el, $('a.action-label.codicon')); // todo@aeschli: remove codicon, should come through `this.clazz`
if (this.clazz) {
addClasses(this.element, this.clazz);
}

View File

@@ -6,6 +6,7 @@
import { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox';
import { Color } from 'vs/base/common/color';
import * as nls from 'vs/nls';
import { Codicon } from 'vs/base/common/codicons';
export interface IFindInputCheckboxOpts {
readonly appendTitle: string;
@@ -21,7 +22,7 @@ const NLS_REGEX_CHECKBOX_LABEL = nls.localize('regexDescription', "Use Regular E
export class CaseSensitiveCheckbox extends Checkbox {
constructor(opts: IFindInputCheckboxOpts) {
super({
actionClassName: 'codicon-case-sensitive',
icon: Codicon.caseSensitive,
title: NLS_CASE_SENSITIVE_CHECKBOX_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
inputActiveOptionBorder: opts.inputActiveOptionBorder,
@@ -33,7 +34,7 @@ export class CaseSensitiveCheckbox extends Checkbox {
export class WholeWordsCheckbox extends Checkbox {
constructor(opts: IFindInputCheckboxOpts) {
super({
actionClassName: 'codicon-whole-word',
icon: Codicon.wholeWord,
title: NLS_WHOLE_WORD_CHECKBOX_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
inputActiveOptionBorder: opts.inputActiveOptionBorder,
@@ -45,7 +46,7 @@ export class WholeWordsCheckbox extends Checkbox {
export class RegexCheckbox extends Checkbox {
constructor(opts: IFindInputCheckboxOpts) {
super({
actionClassName: 'codicon-regex',
icon: Codicon.regex,
title: NLS_REGEX_CHECKBOX_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
inputActiveOptionBorder: opts.inputActiveOptionBorder,

View File

@@ -17,6 +17,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
import { Color } from 'vs/base/common/color';
import { ICheckboxStyles, Checkbox } from 'vs/base/browser/ui/checkbox/checkbox';
import { IFindInputCheckboxOpts } from 'vs/base/browser/ui/findinput/findInputCheckboxes';
import { Codicon } from 'vs/base/common/codicons';
export interface IReplaceInputOptions extends IReplaceInputStyles {
readonly placeholder?: string;
@@ -42,7 +43,7 @@ export class PreserveCaseCheckbox extends Checkbox {
constructor(opts: IFindInputCheckboxOpts) {
super({
// TODO: does this need its own icon?
actionClassName: 'codicon-preserve-case',
icon: Codicon.preserveCase,
title: NLS_PRESERVE_CASE_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
inputActiveOptionBorder: opts.inputActiveOptionBorder,

View File

@@ -594,7 +594,7 @@ export class InputBox extends Widget {
this.element.style.backgroundColor = background;
this.element.style.color = foreground;
this.input.style.backgroundColor = background;
this.input.style.backgroundColor = 'inherit';
this.input.style.color = foreground;
this.element.style.borderWidth = border ? '1px' : '';

View File

@@ -129,10 +129,6 @@
cursor: pointer;
}
.monaco-list-type-filter > .controls > .filter:checked::before {
content: "\eb83" !important; /* codicon-list-filter */
}
.monaco-list-type-filter > .controls > .filter {
margin-left: 4px;
}

View File

@@ -63,17 +63,6 @@ export interface IIdentityProvider<T> {
getId(element: T): { toString(): string; };
}
export enum ListAriaRootRole {
/** default list structure role */
LIST = 'list',
/** default tree structure role */
TREE = 'tree',
/** role='tree' can interfere with screenreaders reading nested elements inside the tree row. Use FORM in that case. */
FORM = 'form'
}
export interface IKeyboardNavigationLabelProvider<T> {
/**

View File

@@ -7,10 +7,11 @@ import 'vs/css!./list';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { range } from 'vs/base/common/arrays';
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent } from './list';
import { List, IListStyles, IListOptions } from './listWidget';
import { List, IListStyles, IListOptions, IListAccessibilityProvider } from './listWidget';
import { IPagedModel } from 'vs/base/common/paging';
import { Event } from 'vs/base/common/event';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
export interface IPagedRenderer<TElement, TTemplateData> extends IListRenderer<TElement, TTemplateData> {
renderPlaceholder(index: number, templateData: TTemplateData): void;
@@ -70,6 +71,54 @@ class PagedRenderer<TElement, TTemplateData> implements IListRenderer<number, IT
}
}
class PagedAccessibilityProvider<T> implements IListAccessibilityProvider<number> {
constructor(
private modelProvider: () => IPagedModel<T>,
private accessibilityProvider: IListAccessibilityProvider<T>
) { }
getWidgetAriaLabel(): string {
return this.accessibilityProvider.getWidgetAriaLabel();
}
getAriaLabel(index: number): string | null {
const model = this.modelProvider();
if (!model.isResolved(index)) {
return null;
}
return this.accessibilityProvider.getAriaLabel(model.get(index));
}
}
export interface IPagedListOptions<T> {
readonly enableKeyboardNavigation?: boolean;
readonly automaticKeyboardNavigation?: boolean;
readonly ariaLabel?: string;
readonly keyboardSupport?: boolean;
readonly multipleSelectionSupport?: boolean;
readonly accessibilityProvider?: IListAccessibilityProvider<T>;
// list view options
readonly useShadows?: boolean;
readonly verticalScrollMode?: ScrollbarVisibility;
readonly setRowLineHeight?: boolean;
readonly setRowHeight?: boolean;
readonly supportDynamicHeights?: boolean;
readonly mouseSupport?: boolean;
readonly horizontalScrolling?: boolean;
readonly additionalScrollHeight?: number;
}
function fromPagedListOptions<T>(modelProvider: () => IPagedModel<T>, options: IPagedListOptions<T>): IListOptions<number> {
return {
...options,
accessibilityProvider: options.accessibilityProvider && new PagedAccessibilityProvider(modelProvider, options.accessibilityProvider)
};
}
export class PagedList<T> implements IDisposable {
private list: List<number>;
@@ -80,10 +129,11 @@ export class PagedList<T> implements IDisposable {
container: HTMLElement,
virtualDelegate: IListVirtualDelegate<number>,
renderers: IPagedRenderer<T, any>[],
options: IListOptions<any> = {}
options: IPagedListOptions<T> = {}
) {
const pagedRenderers = renderers.map(r => new PagedRenderer<T, ITemplateData<T>>(r, () => this.model));
this.list = new List(user, container, virtualDelegate, pagedRenderers, options);
const modelProvider = () => this.model;
const pagedRenderers = renderers.map(r => new PagedRenderer<T, ITemplateData<T>>(r, modelProvider));
this.list = new List(user, container, virtualDelegate, pagedRenderers, fromPagedListOptions(modelProvider, options));
}
getHTMLElement(): HTMLElement {

View File

@@ -41,11 +41,11 @@ export interface IListViewDragAndDrop<T> extends IListDragAndDrop<T> {
getDragElements(element: T): T[];
}
export interface IAriaProvider<T> {
getSetSize(element: T, index: number, listLength: number): number;
getPosInSet(element: T, index: number): number;
export interface IListViewAccessibilityProvider<T> {
getSetSize?(element: T, index: number, listLength: number): number;
getPosInSet?(element: T, index: number): number;
getRole?(element: T): string;
isChecked?(element: T): boolean;
isChecked?(element: T): boolean | undefined;
}
export interface IListViewOptions<T> {
@@ -57,7 +57,7 @@ export interface IListViewOptions<T> {
readonly supportDynamicHeights?: boolean;
readonly mouseSupport?: boolean;
readonly horizontalScrolling?: boolean;
readonly ariaProvider?: IAriaProvider<T>;
readonly accessibilityProvider?: IListViewAccessibilityProvider<T>;
readonly additionalScrollHeight?: number;
}
@@ -152,6 +152,40 @@ function equalsDragFeedback(f1: number[] | undefined, f2: number[] | undefined):
return f1 === f2;
}
class ListViewAccessibilityProvider<T> implements Required<IListViewAccessibilityProvider<T>> {
readonly getSetSize: (element: any, index: number, listLength: number) => number;
readonly getPosInSet: (element: any, index: number) => number;
readonly getRole: (element: T) => string;
readonly isChecked: (element: T) => boolean | undefined;
constructor(accessibilityProvider?: IListViewAccessibilityProvider<T>) {
if (accessibilityProvider?.getSetSize) {
this.getSetSize = accessibilityProvider.getSetSize.bind(accessibilityProvider);
} else {
this.getSetSize = (e, i, l) => l;
}
if (accessibilityProvider?.getPosInSet) {
this.getPosInSet = accessibilityProvider.getPosInSet.bind(accessibilityProvider);
} else {
this.getPosInSet = (e, i) => i + 1;
}
if (accessibilityProvider?.getRole) {
this.getRole = accessibilityProvider.getRole.bind(accessibilityProvider);
} else {
this.getRole = _ => 'listitem';
}
if (accessibilityProvider?.isChecked) {
this.isChecked = accessibilityProvider.isChecked.bind(accessibilityProvider);
} else {
this.isChecked = _ => undefined;
}
}
}
export class ListView<T> implements ISpliceable<T>, IDisposable {
private static InstanceCount = 0;
@@ -181,7 +215,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
private supportDynamicHeights: boolean;
private horizontalScrolling: boolean;
private additionalScrollHeight: number;
private ariaProvider: IAriaProvider<T>;
private accessibilityProvider: ListViewAccessibilityProvider<T>;
private scrollWidth: number | undefined;
private dnd: IListViewDragAndDrop<T>;
@@ -237,7 +271,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.additionalScrollHeight = typeof options.additionalScrollHeight === 'undefined' ? 0 : options.additionalScrollHeight;
this.ariaProvider = options.ariaProvider || { getSetSize: (e, i, length) => length, getPosInSet: (_, index) => index + 1 };
this.accessibilityProvider = new ListViewAccessibilityProvider(options.accessibilityProvider);
this.rowsContainer = document.createElement('div');
this.rowsContainer.className = 'monaco-list-rows';
@@ -611,11 +645,11 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
if (!item.row) {
item.row = this.cache.alloc(item.templateId);
const role = this.ariaProvider.getRole ? this.ariaProvider.getRole(item.element) : 'listitem';
const role = this.accessibilityProvider.getRole(item.element);
item.row!.domNode!.setAttribute('role', role);
const checked = this.ariaProvider.isChecked ? this.ariaProvider.isChecked(item.element) : undefined;
const checked = this.accessibilityProvider.isChecked(item.element);
if (typeof checked !== 'undefined') {
item.row!.domNode!.setAttribute('aria-checked', String(checked));
item.row!.domNode!.setAttribute('aria-checked', String(!!checked));
}
}
@@ -687,8 +721,8 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
item.row!.domNode!.setAttribute('data-index', `${index}`);
item.row!.domNode!.setAttribute('data-last-element', index === this.length - 1 ? 'true' : 'false');
item.row!.domNode!.setAttribute('aria-setsize', String(this.ariaProvider.getSetSize(item.element, index, this.length)));
item.row!.domNode!.setAttribute('aria-posinset', String(this.ariaProvider.getPosInSet(item.element, index)));
item.row!.domNode!.setAttribute('aria-setsize', String(this.accessibilityProvider.getSetSize(item.element, index, this.length)));
item.row!.domNode!.setAttribute('aria-posinset', String(this.accessibilityProvider.getPosInSet(item.element, index)));
item.row!.domNode!.setAttribute('id', this.getElementDomId(index));
DOM.toggleClass(item.row!.domNode!, 'drop-target', item.dropTarget);

View File

@@ -16,8 +16,8 @@ import { KeyCode } from 'vs/base/common/keyCodes';
import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Event, Emitter, EventBufferer } from 'vs/base/common/event';
import { domEvent } from 'vs/base/browser/event';
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, ListAriaRootRole, ListError, IKeyboardNavigationDelegate } from './list';
import { ListView, IListViewOptions, IListViewDragAndDrop, IAriaProvider } from './listView';
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, ListError, IKeyboardNavigationDelegate } from './list';
import { ListView, IListViewOptions, IListViewDragAndDrop, IListViewAccessibilityProvider } from './listView';
import { Color } from 'vs/base/common/color';
import { mixin } from 'vs/base/common/objects';
import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';
@@ -686,25 +686,11 @@ export interface IStyleController {
style(styles: IListStyles): void;
}
export interface IAccessibilityProvider<T> {
/**
* Given an element in the tree, return the ARIA label that should be associated with the
* item. This helps screen readers to provide a meaningful label for the currently focused
* tree element.
*
* Returning null will not disable ARIA for the element. Instead it is up to the screen reader
* to compute a meaningful label based on the contents of the element in the DOM
*
* See also: https://www.w3.org/TR/wai-aria/#aria-label
*/
export interface IListAccessibilityProvider<T> extends IListViewAccessibilityProvider<T> {
getAriaLabel(element: T): string | null;
/**
* https://www.w3.org/TR/wai-aria/#aria-level
*/
getWidgetAriaLabel(): string;
getWidgetRole?(): string;
getAriaLevel?(element: T): number | undefined;
onDidChangeActiveDescendant?: Event<void>;
getActiveDescendantId?(element: T): string | undefined;
}
@@ -836,14 +822,12 @@ export interface IListOptions<T> {
readonly automaticKeyboardNavigation?: boolean;
readonly keyboardNavigationLabelProvider?: IKeyboardNavigationLabelProvider<T>;
readonly keyboardNavigationDelegate?: IKeyboardNavigationDelegate;
readonly ariaRole?: ListAriaRootRole | string;
readonly ariaLabel?: string;
readonly keyboardSupport?: boolean;
readonly multipleSelectionSupport?: boolean;
readonly multipleSelectionController?: IMultipleSelectionController<T>;
readonly openController?: IOpenController;
readonly styleController?: (suffix: string) => IStyleController;
readonly accessibilityProvider?: IAccessibilityProvider<T>;
readonly accessibilityProvider?: IListAccessibilityProvider<T>;
// list view options
readonly useShadows?: boolean;
@@ -853,7 +837,6 @@ export interface IListOptions<T> {
readonly supportDynamicHeights?: boolean;
readonly mouseSupport?: boolean;
readonly horizontalScrolling?: boolean;
readonly ariaProvider?: IAriaProvider<T>;
readonly additionalScrollHeight?: number;
}
@@ -894,7 +877,7 @@ const defaultStyles: IListStyles = {
treeIndentGuidesStroke: Color.fromHex('#a9a9a9')
};
const DefaultOptions = {
const DefaultOptions: IListOptions<any> = {
keyboardSupport: true,
mouseSupport: true,
multipleSelectionSupport: true,
@@ -903,8 +886,7 @@ const DefaultOptions = {
onDragStart(): void { },
onDragOver() { return false; },
drop() { }
},
ariaRootRole: ListAriaRootRole.LIST
}
};
// TODO@Joao: move these utils into a SortedArray class
@@ -1036,7 +1018,7 @@ class AccessibiltyRenderer<T> implements IListRenderer<T, HTMLElement> {
templateId: string = 'a18n';
constructor(private accessibilityProvider: IAccessibilityProvider<T>) { }
constructor(private accessibilityProvider: IListAccessibilityProvider<T>) { }
renderTemplate(container: HTMLElement): HTMLElement {
return container;
@@ -1123,7 +1105,8 @@ export class List<T> implements ISpliceable<T>, IDisposable {
private spliceable: ISpliceable<T>;
private styleController: IStyleController;
private typeLabelController?: TypeLabelController<T>;
private accessibilityProvider?: IAccessibilityProvider<T>;
private accessibilityProvider?: IListAccessibilityProvider<T>;
private _ariaLabel: string = '';
protected readonly disposables = new DisposableStore();
@@ -1202,7 +1185,8 @@ export class List<T> implements ISpliceable<T>, IDisposable {
renderers: IListRenderer<any /* TODO@joao */, any>[],
private _options: IListOptions<T> = DefaultOptions
) {
this.selection = new SelectionTrait(this._options.ariaRole !== 'listbox');
const role = this._options.accessibilityProvider && this._options.accessibilityProvider.getWidgetRole ? this._options.accessibilityProvider?.getWidgetRole() : 'list';
this.selection = new SelectionTrait(role !== 'listbox');
this.focus = new Trait('focused');
mixin(_options, defaultStyles, false);
@@ -1227,12 +1211,7 @@ export class List<T> implements ISpliceable<T>, IDisposable {
};
this.view = new ListView(container, virtualDelegate, renderers, viewOptions);
if (typeof _options.ariaRole !== 'string') {
this.view.domNode.setAttribute('role', ListAriaRootRole.LIST);
} else {
this.view.domNode.setAttribute('role', _options.ariaRole);
}
this.view.domNode.setAttribute('role', role);
if (_options.styleController) {
this.styleController = _options.styleController(this.view.domId);
@@ -1273,8 +1252,8 @@ export class List<T> implements ISpliceable<T>, IDisposable {
this.onDidChangeFocus(this._onFocusChange, this, this.disposables);
this.onDidChangeSelection(this._onSelectionChange, this, this.disposables);
if (_options.ariaLabel) {
this.view.domNode.setAttribute('aria-label', localize('aria list', "{0}. Use the navigation keys to navigate.", _options.ariaLabel));
if (this.accessibilityProvider) {
this.ariaLabel = this.accessibilityProvider.getWidgetAriaLabel();
}
if (_options.multipleSelectionSupport) {
this.view.domNode.setAttribute('aria-multiselectable', 'true');
@@ -1377,6 +1356,15 @@ export class List<T> implements ISpliceable<T>, IDisposable {
return this.view.lastVisibleIndex;
}
get ariaLabel(): string {
return this._ariaLabel;
}
set ariaLabel(value: string) {
this._ariaLabel = value;
this.view.domNode.setAttribute('aria-label', localize('aria list', "{0}. Use the navigation keys to navigate.", value));
}
domFocus(): void {
this.view.domNode.focus();
}

View File

@@ -171,6 +171,7 @@
.menubar.compact {
flex-shrink: 0;
overflow: visible; /* to avoid the compact menu to be repositioned when clicking */
}
.menubar.compact > .menubar-menu-button {
@@ -201,7 +202,7 @@
}
.menubar.compact .toolbar-toggle-more {
position: absolute;
position: relative;
left: 0px;
top: 0px;
cursor: pointer;

View File

@@ -1,3 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 5.625H0V4.5H18V5.625ZM18 14.625H0V13.5H18V14.625ZM18 10.1162H0V9H18V10.1162Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 209 B

View File

@@ -19,11 +19,14 @@ import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';
import { Event } from 'vs/base/common/event';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { isLinux, isMacintosh } from 'vs/base/common/platform';
import { stripCodicons } from 'vs/base/common/codicons';
import { Codicon, registerIcon, stripCodicons } from 'vs/base/common/codicons';
export const MENU_MNEMONIC_REGEX = /\(&([^\s&])\)|(^|[^&])&([^\s&])/;
export const MENU_ESCAPED_MNEMONIC_REGEX = /(&amp;)?(&amp;)([^\s&])/g;
const menuSelectionIcon = registerIcon('menu-selection', Codicon.check);
const menuSubmenuIcon = registerIcon('menu-submenu', Codicon.chevronRight);
export enum Direction {
Right,
Left
@@ -423,7 +426,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
}
}
this.check = append(this.item, $('span.menu-item-check.codicon.codicon-check'));
this.check = append(this.item, $('span.menu-item-check' + menuSelectionIcon.cssSelector));
this.check.setAttribute('role', 'none');
this.label = append(this.item, $('span.action-label'));
@@ -670,7 +673,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
addClass(this.item, 'monaco-submenu-item');
this.item.setAttribute('aria-haspopup', 'true');
this.updateAriaExpanded('false');
this.submenuIndicator = append(this.item, $('span.submenu-indicator.codicon.codicon-chevron-right'));
this.submenuIndicator = append(this.item, $('span.submenu-indicator' + menuSubmenuIcon.cssSelector));
this.submenuIndicator.setAttribute('aria-hidden', 'true');
}

View File

@@ -22,9 +22,12 @@ import { ScanCodeUtils, ScanCode } from 'vs/base/common/scanCode';
import { isMacintosh } from 'vs/base/common/platform';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { Codicon, registerIcon } from 'vs/base/common/codicons';
const $ = DOM.$;
const menuBarMoreIcon = registerIcon('menubar-more', Codicon.more);
export interface IMenuBarOptions {
enableMnemonics?: boolean;
disableAltFocus?: boolean;
@@ -313,7 +316,7 @@ export class MenuBar extends Disposable {
const label = this.options.compactMode !== undefined ? nls.localize('mAppMenu', 'Application Menu') : nls.localize('mMore', 'More');
const title = this.options.compactMode !== undefined ? label : undefined;
const buttonElement = $('div.menubar-menu-button', { 'role': 'menuitem', 'tabindex': -1, 'aria-label': label, 'title': title, 'aria-haspopup': true });
const titleElement = $('div.menubar-menu-title.toolbar-toggle-more.codicon.codicon-more', { 'role': 'none', 'aria-hidden': true });
const titleElement = $('div.menubar-menu-title.toolbar-toggle-more' + menuBarMoreIcon.cssSelector, { 'role': 'none', 'aria-hidden': true });
buttonElement.appendChild(titleElement);
this.container.appendChild(buttonElement);

View File

@@ -9,6 +9,11 @@ import { ScrollableElementResolvedOptions } from 'vs/base/browser/ui/scrollbar/s
import { ARROW_IMG_SIZE } from 'vs/base/browser/ui/scrollbar/scrollbarArrow';
import { ScrollbarState } from 'vs/base/browser/ui/scrollbar/scrollbarState';
import { INewScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility } from 'vs/base/common/scrollable';
import { Codicon, registerIcon } from 'vs/base/common/codicons';
const scrollbarButtonLeftIcon = registerIcon('scrollbar-button-left', Codicon.triangleLeft);
const scrollbarButtonRightIcon = registerIcon('scrollbar-button-right', Codicon.triangleRight);
export class HorizontalScrollbar extends AbstractScrollbar {
@@ -36,7 +41,8 @@ export class HorizontalScrollbar extends AbstractScrollbar {
let scrollbarDelta = (options.horizontalScrollbarSize - ARROW_IMG_SIZE) / 2;
this._createArrow({
className: 'scra codicon codicon-triangle-left',
className: 'scra',
icon: scrollbarButtonLeftIcon,
top: scrollbarDelta,
left: arrowDelta,
bottom: undefined,
@@ -47,7 +53,8 @@ export class HorizontalScrollbar extends AbstractScrollbar {
});
this._createArrow({
className: 'scra codicon codicon-triangle-right',
className: 'scra',
icon: scrollbarButtonRightIcon,
top: scrollbarDelta,
left: undefined,
bottom: undefined,

View File

@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/scrollbars';
import { isEdge } from 'vs/base/browser/browser';
import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { IMouseEvent, StandardWheelEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
@@ -266,7 +265,7 @@ export abstract class AbstractScrollableElement extends Widget {
}
public setScrollDimensions(dimensions: INewScrollDimensions): void {
this._scrollable.setScrollDimensions(dimensions);
this._scrollable.setScrollDimensions(dimensions, false);
}
/**
@@ -336,7 +335,7 @@ export abstract class AbstractScrollableElement extends Widget {
this._onMouseWheel(new StandardWheelEvent(browserEvent));
};
this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, isEdge ? 'mousewheel' : 'wheel', onMouseWheel, { passive: false }));
this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, dom.EventType.MOUSE_WHEEL, onMouseWheel, { passive: false }));
}
}

View File

@@ -7,6 +7,8 @@ import { GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveM
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { Widget } from 'vs/base/browser/ui/widget';
import { IntervalTimer, TimeoutTimer } from 'vs/base/common/async';
import { Codicon } from 'vs/base/common/codicons';
import { addClasses } from 'vs/base/browser/dom';
/**
* The arrow image size.
@@ -16,6 +18,7 @@ export const ARROW_IMG_SIZE = 11;
export interface ScrollbarArrowOptions {
onActivate: () => void;
className: string;
icon: Codicon;
bgWidth: number;
bgHeight: number;
@@ -59,6 +62,8 @@ export class ScrollbarArrow extends Widget {
this.domNode = document.createElement('div');
this.domNode.className = opts.className;
addClasses(this.domNode, opts.icon.classNames);
this.domNode.style.position = 'absolute';
this.domNode.style.width = ARROW_IMG_SIZE + 'px';
this.domNode.style.height = ARROW_IMG_SIZE + 'px';

View File

@@ -9,6 +9,10 @@ import { ScrollableElementResolvedOptions } from 'vs/base/browser/ui/scrollbar/s
import { ARROW_IMG_SIZE } from 'vs/base/browser/ui/scrollbar/scrollbarArrow';
import { ScrollbarState } from 'vs/base/browser/ui/scrollbar/scrollbarState';
import { INewScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility } from 'vs/base/common/scrollable';
import { Codicon, registerIcon } from 'vs/base/common/codicons';
const scrollbarButtonUpIcon = registerIcon('scrollbar-button-up', Codicon.triangleUp);
const scrollbarButtonDownIcon = registerIcon('scrollbar-button-down', Codicon.triangleDown);
export class VerticalScrollbar extends AbstractScrollbar {
@@ -37,7 +41,8 @@ export class VerticalScrollbar extends AbstractScrollbar {
let scrollbarDelta = (options.verticalScrollbarSize - ARROW_IMG_SIZE) / 2;
this._createArrow({
className: 'scra codicon codicon-triangle-up',
className: 'scra',
icon: scrollbarButtonUpIcon,
top: arrowDelta,
left: scrollbarDelta,
bottom: undefined,
@@ -48,7 +53,8 @@ export class VerticalScrollbar extends AbstractScrollbar {
});
this._createArrow({
className: 'scra codicon codicon-triangle-down',
className: 'scra',
icon: scrollbarButtonDownIcon,
top: undefined,
left: scrollbarDelta,
bottom: arrowDelta,

View File

@@ -20,6 +20,7 @@ import { ISelectBoxDelegate, ISelectOptionItem, ISelectBoxOptions, ISelectBoxSty
import { isMacintosh } from 'vs/base/common/platform';
import { renderMarkdown } from 'vs/base/browser/markdownRenderer';
import { IContentActionHandler } from 'vs/base/browser/formattedTextRenderer';
import { localize } from 'vs/nls';
const $ = dom.$;
@@ -732,12 +733,20 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this.listRenderer = new SelectListRenderer();
this.selectList = new List('SelectBoxCustom', this.selectDropDownListContainer, this, [this.listRenderer], {
ariaLabel: this.selectBoxOptions.ariaLabel,
useShadows: false,
verticalScrollMode: ScrollbarVisibility.Visible,
keyboardSupport: false,
mouseSupport: false
mouseSupport: false,
accessibilityProvider: {
getAriaLabel: (element) => element.text,
getWidgetAriaLabel: () => localize('selectBox', "Select Box"),
getRole: () => 'option',
getWidgetRole: () => 'listbox'
}
});
if (this.selectBoxOptions.ariaLabel) {
this.selectList.ariaLabel = this.selectBoxOptions.ariaLabel;
}
// SetUp list keyboard controller - control navigation, disabled items, focus
const onSelectDropDownKeyDown = Event.chain(domEvent(this.selectDropDownListContainer, 'keydown'))

View File

@@ -236,6 +236,7 @@ export abstract class Pane extends Disposable implements IView {
const height = this._orientation === Orientation.VERTICAL ? size - headerSize : this.orthogonalSize - headerSize;
if (this.isExpanded()) {
toggleClass(this.body, 'wide', width >= 600);
this.layoutBody(height, width);
this.expandedSize = size;
}

View File

@@ -12,9 +12,12 @@ import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { withNullAsUndefined } from 'vs/base/common/types';
import { Codicon, registerIcon } from 'vs/base/common/codicons';
export const CONTEXT = 'context.toolbar';
const toolBarMoreIcon = registerIcon('toolbar-more', Codicon.more);
export interface IToolBarOptions {
orientation?: ActionsOrientation;
actionViewItemProvider?: IActionViewItemProvider;
@@ -65,7 +68,7 @@ export class ToolBar extends Disposable {
this.options.actionViewItemProvider,
this.actionRunner,
this.options.getKeyBinding,
'codicon-more',
toolBarMoreIcon.classNames,
this.options.anchorAlignmentProvider
);
this.toggleMenuActionViewItem.value.setActionContext(this.actionBar.context);

View File

@@ -6,7 +6,7 @@
import 'vs/css!./media/tree';
import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IListOptions, List, IListStyles, MouseController, DefaultKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/listWidget';
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider, IKeyboardNavigationDelegate, ListAriaRootRole } from 'vs/base/browser/ui/list/list';
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider, IKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/list';
import { append, $, toggleClass, getDomNodePagePosition, removeClass, addClass, hasClass, hasParentWithClass, createStyleSheet, clearNode, addClasses, removeClasses } from 'vs/base/browser/dom';
import { Event, Relay, Emitter, EventBufferer } from 'vs/base/common/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
@@ -26,6 +26,7 @@ import { values } from 'vs/base/common/map';
import { clamp } from 'vs/base/common/numbers';
import { ScrollEvent } from 'vs/base/common/scrollable';
import { SetMap } from 'vs/base/common/collections';
import { treeItemExpandedIcon, treeFilterOnTypeOnIcon, treeFilterOnTypeOffIcon, treeFilterClearIcon } from 'vs/base/browser/ui/tree/treeIcons';
class TreeElementsDragAndDropData<T, TFilterData, TContext> extends ElementsDragAndDropData<T, TContext> {
@@ -162,9 +163,30 @@ function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T,
},
accessibilityProvider: options.accessibilityProvider && {
...options.accessibilityProvider,
getSetSize(node) {
const model = modelProvider();
const ref = model.getNodeLocation(node);
const parentRef = model.getParentNodeLocation(ref);
const parentNode = model.getNode(parentRef);
return parentNode.visibleChildrenCount;
},
getPosInSet(node) {
return node.visibleChildIndex + 1;
},
isChecked: options.accessibilityProvider && options.accessibilityProvider.isChecked ? (node) => {
return options.accessibilityProvider!.isChecked!(node.element);
} : undefined,
getRole: options.accessibilityProvider && options.accessibilityProvider.getRole ? (node) => {
return options.accessibilityProvider!.getRole!(node.element);
} : () => 'treeitem',
getAriaLabel(e) {
return options.accessibilityProvider!.getAriaLabel(e.element);
},
getWidgetAriaLabel() {
return options.accessibilityProvider!.getWidgetAriaLabel();
},
getWidgetRole: options.accessibilityProvider && options.accessibilityProvider.getWidgetRole ? () => options.accessibilityProvider!.getWidgetRole!() : () => 'tree',
getAriaLevel(node) {
return node.depth;
},
@@ -178,27 +200,7 @@ function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T,
return options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(node.element);
}
},
enableKeyboardNavigation: options.simpleKeyboardNavigation,
ariaProvider: {
getSetSize(node) {
const model = modelProvider();
const ref = model.getNodeLocation(node);
const parentRef = model.getParentNodeLocation(ref);
const parentNode = model.getNode(parentRef);
return parentNode.visibleChildrenCount;
},
getPosInSet(node) {
return node.visibleChildIndex + 1;
},
isChecked: options.ariaProvider && options.ariaProvider.isChecked ? (node) => {
return options.ariaProvider!.isChecked!(node.element);
} : undefined,
getRole: options.ariaProvider && options.ariaProvider.getRole ? (node) => {
return options.ariaProvider!.getRole!(node.element);
} : () => 'treeitem'
},
ariaRole: ListAriaRootRole.TREE
enableKeyboardNavigation: options.simpleKeyboardNavigation
};
}
@@ -404,10 +406,10 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
}
if (node.collapsible && (!this.hideTwistiesOfChildlessElements || node.visibleChildrenCount > 0)) {
addClasses(templateData.twistie, 'codicon', 'codicon-chevron-down', 'collapsible');
addClasses(templateData.twistie, treeItemExpandedIcon.classNames, 'collapsible');
toggleClass(templateData.twistie, 'collapsed', node.collapsed);
} else {
removeClasses(templateData.twistie, 'codicon', 'codicon-chevron-down', 'collapsible', 'collapsed');
removeClasses(templateData.twistie, treeItemExpandedIcon.classNames, 'collapsible', 'collapsed');
}
if (node.collapsible) {
@@ -645,14 +647,14 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
const controls = append(this.domNode, $('.controls'));
this._filterOnType = !!tree.options.filterOnType;
this.filterOnTypeDomNode = append(controls, $<HTMLInputElement>('input.filter.codicon.codicon-list-selection'));
this.filterOnTypeDomNode = append(controls, $<HTMLInputElement>('input.filter'));
this.filterOnTypeDomNode.type = 'checkbox';
this.filterOnTypeDomNode.checked = this._filterOnType;
this.filterOnTypeDomNode.tabIndex = -1;
this.updateFilterOnTypeTitle();
this.updateFilterOnTypeTitleAndIcon();
domEvent(this.filterOnTypeDomNode, 'input')(this.onDidChangeFilterOnType, this, this.disposables);
this.clearDomNode = append(controls, $<HTMLInputElement>('button.clear.codicon.codicon-close'));
this.clearDomNode = append(controls, $<HTMLInputElement>('button.clear' + treeFilterClearIcon.cssSelector));
this.clearDomNode.tabIndex = -1;
this.clearDomNode.title = localize('clear', "Clear");
@@ -858,13 +860,17 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
this.tree.refilter();
this.tree.domFocus();
this.render();
this.updateFilterOnTypeTitle();
this.updateFilterOnTypeTitleAndIcon();
}
private updateFilterOnTypeTitle(): void {
private updateFilterOnTypeTitleAndIcon(): void {
if (this.filterOnType) {
removeClasses(this.filterOnTypeDomNode, treeFilterOnTypeOffIcon.classNames);
addClasses(this.filterOnTypeDomNode, treeFilterOnTypeOnIcon.classNames);
this.filterOnTypeDomNode.title = localize('disable filter on type', "Disable Filter on Type");
} else {
removeClasses(this.filterOnTypeDomNode, treeFilterOnTypeOnIcon.classNames);
addClasses(this.filterOnTypeDomNode, treeFilterOnTypeOffIcon.classNames);
this.filterOnTypeDomNode.title = localize('enable filter on type', "Enable Filter on Type");
}
}
@@ -1445,6 +1451,14 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
return node.element;
}
get ariaLabel(): string {
return this.view.ariaLabel;
}
set ariaLabel(value: string) {
this.view.ariaLabel = value;
}
domFocus(): void {
this.view.domFocus();
}

View File

@@ -5,7 +5,7 @@
import { ComposedTreeDelegate, IAbstractTreeOptions, IAbstractTreeOptionsUpdate } from 'vs/base/browser/ui/tree/abstractTree';
import { ObjectTree, IObjectTreeOptions, CompressibleObjectTree, ICompressibleTreeRenderer, ICompressibleKeyboardNavigationLabelProvider, ICompressibleObjectTreeOptions } from 'vs/base/browser/ui/tree/objectTree';
import { IListVirtualDelegate, IIdentityProvider, IListDragAndDrop, IListDragOverReaction, ListAriaRootRole } from 'vs/base/browser/ui/list/list';
import { IListVirtualDelegate, IIdentityProvider, IListDragAndDrop, IListDragOverReaction } from 'vs/base/browser/ui/list/list';
import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource, ITreeDragAndDrop, TreeError, WeakMapper, ITreeFilter, TreeVisibility, TreeFilterResult } from 'vs/base/browser/ui/tree/tree';
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event';
@@ -15,12 +15,13 @@ import { Iterable } from 'vs/base/common/iterator';
import { IDragAndDropData } from 'vs/base/browser/dnd';
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
import { toggleClass } from 'vs/base/browser/dom';
import { removeClasses, addClasses } from 'vs/base/browser/dom';
import { values } from 'vs/base/common/map';
import { ScrollEvent } from 'vs/base/common/scrollable';
import { ICompressedTreeNode, ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
import { IThemable } from 'vs/base/common/styler';
import { isFilterResult, getVisibleState } from 'vs/base/browser/ui/tree/indexTreeModel';
import { treeItemLoadingIcon } from 'vs/base/browser/ui/tree/treeIcons';
interface IAsyncDataTreeNode<TInput, T> {
element: TInput | T;
@@ -109,7 +110,11 @@ class AsyncDataTreeRenderer<TInput, T, TFilterData, TTemplateData> implements IT
}
renderTwistie(element: IAsyncDataTreeNode<TInput, T>, twistieElement: HTMLElement): boolean {
toggleClass(twistieElement, 'codicon-loading', element.slow);
if (element.slow) {
addClasses(twistieElement, treeItemLoadingIcon.classNames);
} else {
removeClasses(twistieElement, treeItemLoadingIcon.classNames);
}
return false;
}
@@ -231,9 +236,21 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
},
accessibilityProvider: options.accessibilityProvider && {
...options.accessibilityProvider,
getPosInSet: undefined,
getSetSize: undefined,
getRole: options.accessibilityProvider!.getRole ? (el) => {
return options.accessibilityProvider!.getRole!(el.element as T);
} : () => 'treeitem',
isChecked: options.accessibilityProvider!.isChecked ? (e) => {
return !!(options.accessibilityProvider?.isChecked!(e.element as T));
} : undefined,
getAriaLabel(e) {
return options.accessibilityProvider!.getAriaLabel(e.element as T);
},
getWidgetAriaLabel() {
return options.accessibilityProvider!.getWidgetAriaLabel();
},
getWidgetRole: options.accessibilityProvider!.getWidgetRole ? () => options.accessibilityProvider!.getWidgetRole!() : () => 'tree',
getAriaLevel: options.accessibilityProvider!.getAriaLevel && (node => {
return options.accessibilityProvider!.getAriaLevel!(node.element as T);
}),
@@ -258,21 +275,6 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
e => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T)
)
),
ariaProvider: options.ariaProvider && {
getPosInSet(el, index) {
return options.ariaProvider!.getPosInSet(el.element as T, index);
},
getSetSize(el, index, listLength) {
return options.ariaProvider!.getSetSize(el.element as T, index, listLength);
},
getRole: options.ariaProvider!.getRole ? (el) => {
return options.ariaProvider!.getRole!(el.element as T);
} : () => 'treeitem',
isChecked: options.ariaProvider!.isChecked ? (e) => {
return !!(options.ariaProvider?.isChecked!(e.element as T));
} : undefined
},
ariaRole: ListAriaRootRole.TREE,
additionalScrollHeight: options.additionalScrollHeight
};
}
@@ -448,6 +450,14 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return this.tree.lastVisibleElement!.element as T;
}
get ariaLabel(): string {
return this.tree.ariaLabel;
}
set ariaLabel(value: string) {
this.tree.ariaLabel = value;
}
domFocus(): void {
this.tree.domFocus();
}
@@ -1044,7 +1054,11 @@ class CompressibleAsyncDataTreeRenderer<TInput, T, TFilterData, TTemplateData> i
}
renderTwistie(element: IAsyncDataTreeNode<TInput, T>, twistieElement: HTMLElement): boolean {
toggleClass(twistieElement, 'codicon-loading', element.slow);
if (element.slow) {
addClasses(twistieElement, treeItemLoadingIcon.classNames);
} else {
removeClasses(twistieElement, treeItemLoadingIcon.classNames);
}
return false;
}

View File

@@ -60,6 +60,6 @@
transform: rotate(-90deg);
}
.monaco-tl-twistie.codicon-loading::before {
.monaco-tl-twistie.codicon-tree-item-loading::before {
animation: codicon-spin 1.25s linear infinite;
}

View File

@@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Codicon, registerIcon } from 'vs/base/common/codicons';
export const treeItemExpandedIcon = registerIcon('tree-item-expanded', Codicon.chevronDown); // collapsed is done with rotation
export const treeFilterOnTypeOnIcon = registerIcon('tree-filter-on-type-on', Codicon.listFilter);
export const treeFilterOnTypeOffIcon = registerIcon('tree-filter-on-type-off', Codicon.listSelection);
export const treeFilterClearIcon = registerIcon('tree-filter-clear', Codicon.close);
export const treeItemLoadingIcon = registerIcon('tree-item-loading', Codicon.loading);

View File

@@ -4,6 +4,473 @@
*--------------------------------------------------------------------------------------------*/
import { codiconStartMarker } from 'vs/base/common/codicon';
import { Emitter, Event } from 'vs/base/common/event';
export interface IIconRegistry {
readonly all: IterableIterator<Codicon>;
readonly onDidRegister: Event<Codicon>;
get(id: string): Codicon | undefined;
}
class Registry implements IIconRegistry {
private readonly _icons = new Map<string, Codicon>();
private readonly _onDidRegister = new Emitter<Codicon>();
public add(icon: Codicon) {
if (!this._icons.has(icon.id)) {
this._icons.set(icon.id, icon);
this._onDidRegister.fire(icon);
} else {
console.error(`Duplicate registration of codicon ${icon.id}`);
}
}
public get(id: string): Codicon | undefined {
return this._icons.get(id);
}
public get all(): IterableIterator<Codicon> {
return this._icons.values();
}
public get onDidRegister(): Event<Codicon> {
return this._onDidRegister.event;
}
}
const _registry = new Registry();
export const iconRegistry: IIconRegistry = _registry;
export function registerIcon(id: string, def: Codicon) {
return new Codicon(id, def);
}
export class Codicon {
constructor(public readonly id: string, public readonly definition: Codicon | IconDefinition) {
_registry.add(this);
}
public get classNames() { return 'codicon codicon-' + this.id; }
public get cssSelector() { return '.codicon.codicon-' + this.id; }
}
interface IconDefinition {
character: string;
}
export namespace Codicon {
// built-in icons, with image name
export const add = new Codicon('add', { character: '\\ea60' });
export const plus = new Codicon('plus', { character: '\\ea60' });
export const gistNew = new Codicon('gist-new', { character: '\\ea60' });
export const repoCreate = new Codicon('repo-create', { character: '\\ea60' });
export const lightbulb = new Codicon('lightbulb', { character: '\\ea61' });
export const lightBulb = new Codicon('light-bulb', { character: '\\ea61' });
export const repo = new Codicon('repo', { character: '\\ea62' });
export const repoDelete = new Codicon('repo-delete', { character: '\\ea62' });
export const gistFork = new Codicon('gist-fork', { character: '\\ea63' });
export const repoForked = new Codicon('repo-forked', { character: '\\ea63' });
export const gitPullRequest = new Codicon('git-pull-request', { character: '\\ea64' });
export const gitPullRequestAbandoned = new Codicon('git-pull-request-abandoned', { character: '\\ea64' });
export const recordKeys = new Codicon('record-keys', { character: '\\ea65' });
export const keyboard = new Codicon('keyboard', { character: '\\ea65' });
export const tag = new Codicon('tag', { character: '\\ea66' });
export const tagAdd = new Codicon('tag-add', { character: '\\ea66' });
export const tagRemove = new Codicon('tag-remove', { character: '\\ea66' });
export const person = new Codicon('person', { character: '\\ea67' });
export const personAdd = new Codicon('person-add', { character: '\\ea67' });
export const personFollow = new Codicon('person-follow', { character: '\\ea67' });
export const personOutline = new Codicon('person-outline', { character: '\\ea67' });
export const personFilled = new Codicon('person-filled', { character: '\\ea67' });
export const gitBranch = new Codicon('git-branch', { character: '\\ea68' });
export const gitBranchCreate = new Codicon('git-branch-create', { character: '\\ea68' });
export const gitBranchDelete = new Codicon('git-branch-delete', { character: '\\ea68' });
export const sourceControl = new Codicon('source-control', { character: '\\ea68' });
export const mirror = new Codicon('mirror', { character: '\\ea69' });
export const mirrorPublic = new Codicon('mirror-public', { character: '\\ea69' });
export const star = new Codicon('star', { character: '\\ea6a' });
export const starAdd = new Codicon('star-add', { character: '\\ea6a' });
export const starDelete = new Codicon('star-delete', { character: '\\ea6a' });
export const starEmpty = new Codicon('star-empty', { character: '\\ea6a' });
export const comment = new Codicon('comment', { character: '\\ea6b' });
export const commentAdd = new Codicon('comment-add', { character: '\\ea6b' });
export const alert = new Codicon('alert', { character: '\\ea6c' });
export const warning = new Codicon('warning', { character: '\\ea6c' });
export const search = new Codicon('search', { character: '\\ea6d' });
export const searchSave = new Codicon('search-save', { character: '\\ea6d' });
export const logOut = new Codicon('log-out', { character: '\\ea6e' });
export const signOut = new Codicon('sign-out', { character: '\\ea6e' });
export const logIn = new Codicon('log-in', { character: '\\ea6f' });
export const signIn = new Codicon('sign-in', { character: '\\ea6f' });
export const eye = new Codicon('eye', { character: '\\ea70' });
export const eyeUnwatch = new Codicon('eye-unwatch', { character: '\\ea70' });
export const eyeWatch = new Codicon('eye-watch', { character: '\\ea70' });
export const circleFilled = new Codicon('circle-filled', { character: '\\ea71' });
export const primitiveDot = new Codicon('primitive-dot', { character: '\\ea71' });
export const closeDirty = new Codicon('close-dirty', { character: '\\ea71' });
export const debugBreakpoint = new Codicon('debug-breakpoint', { character: '\\ea71' });
export const debugBreakpointDisabled = new Codicon('debug-breakpoint-disabled', { character: '\\ea71' });
export const debugHint = new Codicon('debug-hint', { character: '\\ea71' });
export const primitiveSquare = new Codicon('primitive-square', { character: '\\ea72' });
export const edit = new Codicon('edit', { character: '\\ea73' });
export const pencil = new Codicon('pencil', { character: '\\ea73' });
export const info = new Codicon('info', { character: '\\ea74' });
export const issueOpened = new Codicon('issue-opened', { character: '\\ea74' });
export const gistPrivate = new Codicon('gist-private', { character: '\\ea75' });
export const gitForkPrivate = new Codicon('git-fork-private', { character: '\\ea75' });
export const lock = new Codicon('lock', { character: '\\ea75' });
export const mirrorPrivate = new Codicon('mirror-private', { character: '\\ea75' });
export const close = new Codicon('close', { character: '\\ea76' });
export const removeClose = new Codicon('remove-close', { character: '\\ea76' });
export const x = new Codicon('x', { character: '\\ea76' });
export const repoSync = new Codicon('repo-sync', { character: '\\ea77' });
export const sync = new Codicon('sync', { character: '\\ea77' });
export const clone = new Codicon('clone', { character: '\\ea78' });
export const desktopDownload = new Codicon('desktop-download', { character: '\\ea78' });
export const beaker = new Codicon('beaker', { character: '\\ea79' });
export const microscope = new Codicon('microscope', { character: '\\ea79' });
export const vm = new Codicon('vm', { character: '\\ea7a' });
export const deviceDesktop = new Codicon('device-desktop', { character: '\\ea7a' });
export const file = new Codicon('file', { character: '\\ea7b' });
export const fileText = new Codicon('file-text', { character: '\\ea7b' });
export const more = new Codicon('more', { character: '\\ea7c' });
export const ellipsis = new Codicon('ellipsis', { character: '\\ea7c' });
export const kebabHorizontal = new Codicon('kebab-horizontal', { character: '\\ea7c' });
export const mailReply = new Codicon('mail-reply', { character: '\\ea7d' });
export const reply = new Codicon('reply', { character: '\\ea7d' });
export const organization = new Codicon('organization', { character: '\\ea7e' });
export const organizationFilled = new Codicon('organization-filled', { character: '\\ea7e' });
export const organizationOutline = new Codicon('organization-outline', { character: '\\ea7e' });
export const newFile = new Codicon('new-file', { character: '\\ea7f' });
export const fileAdd = new Codicon('file-add', { character: '\\ea7f' });
export const newFolder = new Codicon('new-folder', { character: '\\ea80' });
export const fileDirectoryCreate = new Codicon('file-directory-create', { character: '\\ea80' });
export const trash = new Codicon('trash', { character: '\\ea81' });
export const trashcan = new Codicon('trashcan', { character: '\\ea81' });
export const history = new Codicon('history', { character: '\\ea82' });
export const clock = new Codicon('clock', { character: '\\ea82' });
export const folder = new Codicon('folder', { character: '\\ea83' });
export const fileDirectory = new Codicon('file-directory', { character: '\\ea83' });
export const symbolFolder = new Codicon('symbol-folder', { character: '\\ea83' });
export const logoGithub = new Codicon('logo-github', { character: '\\ea84' });
export const markGithub = new Codicon('mark-github', { character: '\\ea84' });
export const github = new Codicon('github', { character: '\\ea84' });
export const terminal = new Codicon('terminal', { character: '\\ea85' });
export const console = new Codicon('console', { character: '\\ea85' });
export const repl = new Codicon('repl', { character: '\\ea85' });
export const zap = new Codicon('zap', { character: '\\ea86' });
export const symbolEvent = new Codicon('symbol-event', { character: '\\ea86' });
export const error = new Codicon('error', { character: '\\ea87' });
export const stop = new Codicon('stop', { character: '\\ea87' });
export const variable = new Codicon('variable', { character: '\\ea88' });
export const symbolVariable = new Codicon('symbol-variable', { character: '\\ea88' });
export const array = new Codicon('array', { character: '\\ea8a' });
export const symbolArray = new Codicon('symbol-array', { character: '\\ea8a' });
export const symbolModule = new Codicon('symbol-module', { character: '\\ea8b' });
export const symbolPackage = new Codicon('symbol-package', { character: '\\ea8b' });
export const symbolNamespace = new Codicon('symbol-namespace', { character: '\\ea8b' });
export const symbolObject = new Codicon('symbol-object', { character: '\\ea8b' });
export const symbolMethod = new Codicon('symbol-method', { character: '\\ea8c' });
export const symbolFunction = new Codicon('symbol-function', { character: '\\ea8c' });
export const symbolConstructor = new Codicon('symbol-constructor', { character: '\\ea8c' });
export const symbolBoolean = new Codicon('symbol-boolean', { character: '\\ea8f' });
export const symbolNull = new Codicon('symbol-null', { character: '\\ea8f' });
export const symbolNumeric = new Codicon('symbol-numeric', { character: '\\ea90' });
export const symbolNumber = new Codicon('symbol-number', { character: '\\ea90' });
export const symbolStructure = new Codicon('symbol-structure', { character: '\\ea91' });
export const symbolStruct = new Codicon('symbol-struct', { character: '\\ea91' });
export const symbolParameter = new Codicon('symbol-parameter', { character: '\\ea92' });
export const symbolTypeParameter = new Codicon('symbol-type-parameter', { character: '\\ea92' });
export const symbolKey = new Codicon('symbol-key', { character: '\\ea93' });
export const symbolText = new Codicon('symbol-text', { character: '\\ea93' });
export const symbolReference = new Codicon('symbol-reference', { character: '\\ea94' });
export const goToFile = new Codicon('go-to-file', { character: '\\ea94' });
export const symbolEnum = new Codicon('symbol-enum', { character: '\\ea95' });
export const symbolValue = new Codicon('symbol-value', { character: '\\ea95' });
export const symbolRuler = new Codicon('symbol-ruler', { character: '\\ea96' });
export const symbolUnit = new Codicon('symbol-unit', { character: '\\ea96' });
export const activateBreakpoints = new Codicon('activate-breakpoints', { character: '\\ea97' });
export const archive = new Codicon('archive', { character: '\\ea98' });
export const arrowBoth = new Codicon('arrow-both', { character: '\\ea99' });
export const arrowDown = new Codicon('arrow-down', { character: '\\ea9a' });
export const arrowLeft = new Codicon('arrow-left', { character: '\\ea9b' });
export const arrowRight = new Codicon('arrow-right', { character: '\\ea9c' });
export const arrowSmallDown = new Codicon('arrow-small-down', { character: '\\ea9d' });
export const arrowSmallLeft = new Codicon('arrow-small-left', { character: '\\ea9e' });
export const arrowSmallRight = new Codicon('arrow-small-right', { character: '\\ea9f' });
export const arrowSmallUp = new Codicon('arrow-small-up', { character: '\\eaa0' });
export const arrowUp = new Codicon('arrow-up', { character: '\\eaa1' });
export const bell = new Codicon('bell', { character: '\\eaa2' });
export const bold = new Codicon('bold', { character: '\\eaa3' });
export const book = new Codicon('book', { character: '\\eaa4' });
export const bookmark = new Codicon('bookmark', { character: '\\eaa5' });
export const debugBreakpointConditionalUnverified = new Codicon('debug-breakpoint-conditional-unverified', { character: '\\eaa6' });
export const debugBreakpointConditional = new Codicon('debug-breakpoint-conditional', { character: '\\eaa7' });
export const debugBreakpointConditionalDisabled = new Codicon('debug-breakpoint-conditional-disabled', { character: '\\eaa7' });
export const debugBreakpointDataUnverified = new Codicon('debug-breakpoint-data-unverified', { character: '\\eaa8' });
export const debugBreakpointData = new Codicon('debug-breakpoint-data', { character: '\\eaa9' });
export const debugBreakpointDataDisabled = new Codicon('debug-breakpoint-data-disabled', { character: '\\eaa9' });
export const debugBreakpointLogUnverified = new Codicon('debug-breakpoint-log-unverified', { character: '\\eaaa' });
export const debugBreakpointLog = new Codicon('debug-breakpoint-log', { character: '\\eaab' });
export const debugBreakpointLogDisabled = new Codicon('debug-breakpoint-log-disabled', { character: '\\eaab' });
export const briefcase = new Codicon('briefcase', { character: '\\eaac' });
export const broadcast = new Codicon('broadcast', { character: '\\eaad' });
export const browser = new Codicon('browser', { character: '\\eaae' });
export const bug = new Codicon('bug', { character: '\\eaaf' });
export const calendar = new Codicon('calendar', { character: '\\eab0' });
export const caseSensitive = new Codicon('case-sensitive', { character: '\\eab1' });
export const check = new Codicon('check', { character: '\\eab2' });
export const checklist = new Codicon('checklist', { character: '\\eab3' });
export const chevronDown = new Codicon('chevron-down', { character: '\\eab4' });
export const chevronLeft = new Codicon('chevron-left', { character: '\\eab5' });
export const chevronRight = new Codicon('chevron-right', { character: '\\eab6' });
export const chevronUp = new Codicon('chevron-up', { character: '\\eab7' });
export const chromeClose = new Codicon('chrome-close', { character: '\\eab8' });
export const chromeMaximize = new Codicon('chrome-maximize', { character: '\\eab9' });
export const chromeMinimize = new Codicon('chrome-minimize', { character: '\\eaba' });
export const chromeRestore = new Codicon('chrome-restore', { character: '\\eabb' });
export const circleOutline = new Codicon('circle-outline', { character: '\\eabc' });
export const debugBreakpointUnverified = new Codicon('debug-breakpoint-unverified', { character: '\\eabc' });
export const circleSlash = new Codicon('circle-slash', { character: '\\eabd' });
export const circuitBoard = new Codicon('circuit-board', { character: '\\eabe' });
export const clearAll = new Codicon('clear-all', { character: '\\eabf' });
export const clippy = new Codicon('clippy', { character: '\\eac0' });
export const closeAll = new Codicon('close-all', { character: '\\eac1' });
export const cloudDownload = new Codicon('cloud-download', { character: '\\eac2' });
export const cloudUpload = new Codicon('cloud-upload', { character: '\\eac3' });
export const code = new Codicon('code', { character: '\\eac4' });
export const collapseAll = new Codicon('collapse-all', { character: '\\eac5' });
export const colorMode = new Codicon('color-mode', { character: '\\eac6' });
export const commentDiscussion = new Codicon('comment-discussion', { character: '\\eac7' });
export const compareChanges = new Codicon('compare-changes', { character: '\\eac8' });
export const creditCard = new Codicon('credit-card', { character: '\\eac9' });
export const dash = new Codicon('dash', { character: '\\eacc' });
export const dashboard = new Codicon('dashboard', { character: '\\eacd' });
export const database = new Codicon('database', { character: '\\eace' });
export const debugContinue = new Codicon('debug-continue', { character: '\\eacf' });
export const debugDisconnect = new Codicon('debug-disconnect', { character: '\\ead0' });
export const debugPause = new Codicon('debug-pause', { character: '\\ead1' });
export const debugRestart = new Codicon('debug-restart', { character: '\\ead2' });
export const debugStart = new Codicon('debug-start', { character: '\\ead3' });
export const debugStepInto = new Codicon('debug-step-into', { character: '\\ead4' });
export const debugStepOut = new Codicon('debug-step-out', { character: '\\ead5' });
export const debugStepOver = new Codicon('debug-step-over', { character: '\\ead6' });
export const debugStop = new Codicon('debug-stop', { character: '\\ead7' });
export const debug = new Codicon('debug', { character: '\\ead8' });
export const deviceCameraVideo = new Codicon('device-camera-video', { character: '\\ead9' });
export const deviceCamera = new Codicon('device-camera', { character: '\\eada' });
export const deviceMobile = new Codicon('device-mobile', { character: '\\eadb' });
export const diffAdded = new Codicon('diff-added', { character: '\\eadc' });
export const diffIgnored = new Codicon('diff-ignored', { character: '\\eadd' });
export const diffModified = new Codicon('diff-modified', { character: '\\eade' });
export const diffRemoved = new Codicon('diff-removed', { character: '\\eadf' });
export const diffRenamed = new Codicon('diff-renamed', { character: '\\eae0' });
export const diff = new Codicon('diff', { character: '\\eae1' });
export const discard = new Codicon('discard', { character: '\\eae2' });
export const editorLayout = new Codicon('editor-layout', { character: '\\eae3' });
export const emptyWindow = new Codicon('empty-window', { character: '\\eae4' });
export const exclude = new Codicon('exclude', { character: '\\eae5' });
export const extensions = new Codicon('extensions', { character: '\\eae6' });
export const eyeClosed = new Codicon('eye-closed', { character: '\\eae7' });
export const fileBinary = new Codicon('file-binary', { character: '\\eae8' });
export const fileCode = new Codicon('file-code', { character: '\\eae9' });
export const fileMedia = new Codicon('file-media', { character: '\\eaea' });
export const filePdf = new Codicon('file-pdf', { character: '\\eaeb' });
export const fileSubmodule = new Codicon('file-submodule', { character: '\\eaec' });
export const fileSymlinkDirectory = new Codicon('file-symlink-directory', { character: '\\eaed' });
export const fileSymlinkFile = new Codicon('file-symlink-file', { character: '\\eaee' });
export const fileZip = new Codicon('file-zip', { character: '\\eaef' });
export const files = new Codicon('files', { character: '\\eaf0' });
export const filter = new Codicon('filter', { character: '\\eaf1' });
export const flame = new Codicon('flame', { character: '\\eaf2' });
export const foldDown = new Codicon('fold-down', { character: '\\eaf3' });
export const foldUp = new Codicon('fold-up', { character: '\\eaf4' });
export const fold = new Codicon('fold', { character: '\\eaf5' });
export const folderActive = new Codicon('folder-active', { character: '\\eaf6' });
export const folderOpened = new Codicon('folder-opened', { character: '\\eaf7' });
export const gear = new Codicon('gear', { character: '\\eaf8' });
export const gift = new Codicon('gift', { character: '\\eaf9' });
export const gistSecret = new Codicon('gist-secret', { character: '\\eafa' });
export const gist = new Codicon('gist', { character: '\\eafb' });
export const gitCommit = new Codicon('git-commit', { character: '\\eafc' });
export const gitCompare = new Codicon('git-compare', { character: '\\eafd' });
export const gitMerge = new Codicon('git-merge', { character: '\\eafe' });
export const githubAction = new Codicon('github-action', { character: '\\eaff' });
export const githubAlt = new Codicon('github-alt', { character: '\\eb00' });
export const globe = new Codicon('globe', { character: '\\eb01' });
export const grabber = new Codicon('grabber', { character: '\\eb02' });
export const graph = new Codicon('graph', { character: '\\eb03' });
export const gripper = new Codicon('gripper', { character: '\\eb04' });
export const heart = new Codicon('heart', { character: '\\eb05' });
export const home = new Codicon('home', { character: '\\eb06' });
export const horizontalRule = new Codicon('horizontal-rule', { character: '\\eb07' });
export const hubot = new Codicon('hubot', { character: '\\eb08' });
export const inbox = new Codicon('inbox', { character: '\\eb09' });
export const issueClosed = new Codicon('issue-closed', { character: '\\eb0a' });
export const issueReopened = new Codicon('issue-reopened', { character: '\\eb0b' });
export const issues = new Codicon('issues', { character: '\\eb0c' });
export const italic = new Codicon('italic', { character: '\\eb0d' });
export const jersey = new Codicon('jersey', { character: '\\eb0e' });
export const json = new Codicon('json', { character: '\\eb0f' });
export const kebabVertical = new Codicon('kebab-vertical', { character: '\\eb10' });
export const key = new Codicon('key', { character: '\\eb11' });
export const law = new Codicon('law', { character: '\\eb12' });
export const lightbulbAutofix = new Codicon('lightbulb-autofix', { character: '\\eb13' });
export const linkExternal = new Codicon('link-external', { character: '\\eb14' });
export const link = new Codicon('link', { character: '\\eb15' });
export const listOrdered = new Codicon('list-ordered', { character: '\\eb16' });
export const listUnordered = new Codicon('list-unordered', { character: '\\eb17' });
export const liveShare = new Codicon('live-share', { character: '\\eb18' });
export const loading = new Codicon('loading', { character: '\\eb19' });
export const location = new Codicon('location', { character: '\\eb1a' });
export const mailRead = new Codicon('mail-read', { character: '\\eb1b' });
export const mail = new Codicon('mail', { character: '\\eb1c' });
export const markdown = new Codicon('markdown', { character: '\\eb1d' });
export const megaphone = new Codicon('megaphone', { character: '\\eb1e' });
export const mention = new Codicon('mention', { character: '\\eb1f' });
export const milestone = new Codicon('milestone', { character: '\\eb20' });
export const mortarBoard = new Codicon('mortar-board', { character: '\\eb21' });
export const move = new Codicon('move', { character: '\\eb22' });
export const multipleWindows = new Codicon('multiple-windows', { character: '\\eb23' });
export const mute = new Codicon('mute', { character: '\\eb24' });
export const noNewline = new Codicon('no-newline', { character: '\\eb25' });
export const note = new Codicon('note', { character: '\\eb26' });
export const octoface = new Codicon('octoface', { character: '\\eb27' });
export const openPreview = new Codicon('open-preview', { character: '\\eb28' });
export const package_ = new Codicon('package', { character: '\\eb29' });
export const paintcan = new Codicon('paintcan', { character: '\\eb2a' });
export const pin = new Codicon('pin', { character: '\\eb2b' });
export const play = new Codicon('play', { character: '\\eb2c' });
export const run = new Codicon('run', { character: '\\eb2c' });
export const plug = new Codicon('plug', { character: '\\eb2d' });
export const preserveCase = new Codicon('preserve-case', { character: '\\eb2e' });
export const preview = new Codicon('preview', { character: '\\eb2f' });
export const project = new Codicon('project', { character: '\\eb30' });
export const pulse = new Codicon('pulse', { character: '\\eb31' });
export const question = new Codicon('question', { character: '\\eb32' });
export const quote = new Codicon('quote', { character: '\\eb33' });
export const radioTower = new Codicon('radio-tower', { character: '\\eb34' });
export const reactions = new Codicon('reactions', { character: '\\eb35' });
export const references = new Codicon('references', { character: '\\eb36' });
export const refresh = new Codicon('refresh', { character: '\\eb37' });
export const regex = new Codicon('regex', { character: '\\eb38' });
export const remoteExplorer = new Codicon('remote-explorer', { character: '\\eb39' });
export const remote = new Codicon('remote', { character: '\\eb3a' });
export const remove = new Codicon('remove', { character: '\\eb3b' });
export const replaceAll = new Codicon('replace-all', { character: '\\eb3c' });
export const replace = new Codicon('replace', { character: '\\eb3d' });
export const repoClone = new Codicon('repo-clone', { character: '\\eb3e' });
export const repoForcePush = new Codicon('repo-force-push', { character: '\\eb3f' });
export const repoPull = new Codicon('repo-pull', { character: '\\eb40' });
export const repoPush = new Codicon('repo-push', { character: '\\eb41' });
export const report = new Codicon('report', { character: '\\eb42' });
export const requestChanges = new Codicon('request-changes', { character: '\\eb43' });
export const rocket = new Codicon('rocket', { character: '\\eb44' });
export const rootFolderOpened = new Codicon('root-folder-opened', { character: '\\eb45' });
export const rootFolder = new Codicon('root-folder', { character: '\\eb46' });
export const rss = new Codicon('rss', { character: '\\eb47' });
export const ruby = new Codicon('ruby', { character: '\\eb48' });
export const saveAll = new Codicon('save-all', { character: '\\eb49' });
export const saveAs = new Codicon('save-as', { character: '\\eb4a' });
export const save = new Codicon('save', { character: '\\eb4b' });
export const screenFull = new Codicon('screen-full', { character: '\\eb4c' });
export const screenNormal = new Codicon('screen-normal', { character: '\\eb4d' });
export const searchStop = new Codicon('search-stop', { character: '\\eb4e' });
export const server = new Codicon('server', { character: '\\eb50' });
export const settingsGear = new Codicon('settings-gear', { character: '\\eb51' });
export const settings = new Codicon('settings', { character: '\\eb52' });
export const shield = new Codicon('shield', { character: '\\eb53' });
export const smiley = new Codicon('smiley', { character: '\\eb54' });
export const sortPrecedence = new Codicon('sort-precedence', { character: '\\eb55' });
export const splitHorizontal = new Codicon('split-horizontal', { character: '\\eb56' });
export const splitVertical = new Codicon('split-vertical', { character: '\\eb57' });
export const squirrel = new Codicon('squirrel', { character: '\\eb58' });
export const starFull = new Codicon('star-full', { character: '\\eb59' });
export const starHalf = new Codicon('star-half', { character: '\\eb5a' });
export const symbolClass = new Codicon('symbol-class', { character: '\\eb5b' });
export const symbolColor = new Codicon('symbol-color', { character: '\\eb5c' });
export const symbolConstant = new Codicon('symbol-constant', { character: '\\eb5d' });
export const symbolEnumMember = new Codicon('symbol-enum-member', { character: '\\eb5e' });
export const symbolField = new Codicon('symbol-field', { character: '\\eb5f' });
export const symbolFile = new Codicon('symbol-file', { character: '\\eb60' });
export const symbolInterface = new Codicon('symbol-interface', { character: '\\eb61' });
export const symbolKeyword = new Codicon('symbol-keyword', { character: '\\eb62' });
export const symbolMisc = new Codicon('symbol-misc', { character: '\\eb63' });
export const symbolOperator = new Codicon('symbol-operator', { character: '\\eb64' });
export const symbolProperty = new Codicon('symbol-property', { character: '\\eb65' });
export const wrench = new Codicon('wrench', { character: '\\eb65' });
export const wrenchSubaction = new Codicon('wrench-subaction', { character: '\\eb65' });
export const symbolSnippet = new Codicon('symbol-snippet', { character: '\\eb66' });
export const tasklist = new Codicon('tasklist', { character: '\\eb67' });
export const telescope = new Codicon('telescope', { character: '\\eb68' });
export const textSize = new Codicon('text-size', { character: '\\eb69' });
export const threeBars = new Codicon('three-bars', { character: '\\eb6a' });
export const thumbsdown = new Codicon('thumbsdown', { character: '\\eb6b' });
export const thumbsup = new Codicon('thumbsup', { character: '\\eb6c' });
export const tools = new Codicon('tools', { character: '\\eb6d' });
export const triangleDown = new Codicon('triangle-down', { character: '\\eb6e' });
export const triangleLeft = new Codicon('triangle-left', { character: '\\eb6f' });
export const triangleRight = new Codicon('triangle-right', { character: '\\eb70' });
export const triangleUp = new Codicon('triangle-up', { character: '\\eb71' });
export const twitter = new Codicon('twitter', { character: '\\eb72' });
export const unfold = new Codicon('unfold', { character: '\\eb73' });
export const unlock = new Codicon('unlock', { character: '\\eb74' });
export const unmute = new Codicon('unmute', { character: '\\eb75' });
export const unverified = new Codicon('unverified', { character: '\\eb76' });
export const verified = new Codicon('verified', { character: '\\eb77' });
export const versions = new Codicon('versions', { character: '\\eb78' });
export const vmActive = new Codicon('vm-active', { character: '\\eb79' });
export const vmOutline = new Codicon('vm-outline', { character: '\\eb7a' });
export const vmRunning = new Codicon('vm-running', { character: '\\eb7b' });
export const watch = new Codicon('watch', { character: '\\eb7c' });
export const whitespace = new Codicon('whitespace', { character: '\\eb7d' });
export const wholeWord = new Codicon('whole-word', { character: '\\eb7e' });
export const window = new Codicon('window', { character: '\\eb7f' });
export const wordWrap = new Codicon('word-wrap', { character: '\\eb80' });
export const zoomIn = new Codicon('zoom-in', { character: '\\eb81' });
export const zoomOut = new Codicon('zoom-out', { character: '\\eb82' });
export const listFilter = new Codicon('list-filter', { character: '\\eb83' });
export const listFlat = new Codicon('list-flat', { character: '\\eb84' });
export const listSelection = new Codicon('list-selection', { character: '\\eb85' });
export const selection = new Codicon('selection', { character: '\\eb85' });
export const listTree = new Codicon('list-tree', { character: '\\eb86' });
export const debugBreakpointFunctionUnverified = new Codicon('debug-breakpoint-function-unverified', { character: '\\eb87' });
export const debugBreakpointFunction = new Codicon('debug-breakpoint-function', { character: '\\eb88' });
export const debugBreakpointFunctionDisabled = new Codicon('debug-breakpoint-function-disabled', { character: '\\eb88' });
export const debugStackframeActive = new Codicon('debug-stackframe-active', { character: '\\eb89' });
export const debugStackframeDot = new Codicon('debug-stackframe-dot', { character: '\\eb8a' });
export const debugStackframe = new Codicon('debug-stackframe', { character: '\\eb8b' });
export const debugStackframeFocused = new Codicon('debug-stackframe-focused', { character: '\\eb8b' });
export const debugBreakpointUnsupported = new Codicon('debug-breakpoint-unsupported', { character: '\\eb8c' });
export const symbolString = new Codicon('symbol-string', { character: '\\eb8d' });
export const debugReverseContinue = new Codicon('debug-reverse-continue', { character: '\\eb8e' });
export const debugStepBack = new Codicon('debug-step-back', { character: '\\eb8f' });
export const debugRestartFrame = new Codicon('debug-restart-frame', { character: '\\eb90' });
export const debugAlternate = new Codicon('debug-alternate', { character: '\\eb91' });
export const callIncoming = new Codicon('call-incoming', { character: '\\eb92' });
export const callOutgoing = new Codicon('call-outgoing', { character: '\\eb93' });
export const menu = new Codicon('menu', { character: '\\eb94' });
export const expandAll = new Codicon('expand-all', { character: '\\eb95' });
export const feedback = new Codicon('feedback', { character: '\\eb96' });
export const groupByRefType = new Codicon('group-by-ref-type', { character: '\\eb97' });
export const ungroupByRefType = new Codicon('ungroup-by-ref-type', { character: '\\eb98' });
export const account = new Codicon('account', { character: '\\eb99' });
export const bellDot = new Codicon('bell-dot', { character: '\\eb9a' });
export const debugConsole = new Codicon('debug-console', { character: '\\eb9b' });
export const library = new Codicon('library', { character: '\\eb9c' });
export const output = new Codicon('output', { character: '\\eb9d' });
export const runAll = new Codicon('run-all', { character: '\\eb9e' });
export const syncIgnored = new Codicon('sync-ignored', { character: '\\eb9f' });
export const pinned = new Codicon('pinned', { character: '\\eba0' });
export const githubInverted = new Codicon('github-inverted', { character: '\\eba1' });
export const debugAlt2 = new Codicon('debug-alt-2', { character: '\\f101' });
export const debugAlt = new Codicon('debug-alt', { character: '\\f102' });
}
const escapeCodiconsRegex = /(\\)?\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)/gi;
export function escapeCodicons(text: string): string {

View File

@@ -404,10 +404,10 @@ export function createMatches(score: undefined | FuzzyScore, offset = 0): IMatch
for (let pos = wordStart; pos < _maxLen; pos++) {
if (matches[matches.length - (pos + 1)] === '1') {
const last = res[res.length - 1];
if (last && last.end === pos) {
last.end = pos + 1;
if (last && last.end === pos + offset) {
last.end = pos + offset + 1;
} else {
res.push({ start: pos + offset, end: pos + 1 + offset });
res.push({ start: pos + offset, end: pos + offset + 1 });
}
}
}

View File

@@ -161,7 +161,7 @@ function doScoreFuzzy(query: string, queryLower: string, queryLength: number, ta
function computeCharScore(queryCharAtIndex: string, queryLowerCharAtIndex: string, target: string, targetLower: string, targetIndex: number, matchesSequenceLength: number): number {
let score = 0;
if (queryLowerCharAtIndex !== targetLower[targetIndex]) {
if (!considerAsEqual(queryLowerCharAtIndex, targetLower[targetIndex])) {
return score; // no match of characters
}
@@ -228,6 +228,19 @@ function computeCharScore(queryCharAtIndex: string, queryLowerCharAtIndex: strin
return score;
}
function considerAsEqual(a: string, b: string): boolean {
if (a === b) {
return true;
}
// Special case path spearators: ignore platform differences
if (a === '/' || a === '\\') {
return b === '/' || b === '\\';
}
return false;
}
function scoreSeparatorAtPos(charCode: number): number {
switch (charCode) {
case CharCode.Slash:
@@ -264,15 +277,16 @@ function scoreSeparatorAtPos(charCode: number): number {
//#region Alternate fuzzy scorer implementation that is e.g. used for symbols
export type FuzzyScore2 = [number /* score*/, IMatch[]];
export type FuzzyScore2 = [number | undefined /* score */, IMatch[]];
const NO_SCORE2: FuzzyScore2 = [NO_MATCH, []];
const NO_SCORE2: FuzzyScore2 = [undefined, []];
export function scoreFuzzy2(target: string, query: IPreparedQuery, patternStart = 0, matchOffset = 0): FuzzyScore2 {
export function scoreFuzzy2(target: string, query: IPreparedQuery | IPreparedQueryPiece, patternStart = 0, matchOffset = 0): FuzzyScore2 {
// Score: multiple inputs
if (query.values && query.values.length > 1) {
return doScoreFuzzy2Multiple(target, query.values, patternStart, matchOffset);
const preparedQuery = query as IPreparedQuery;
if (preparedQuery.values && preparedQuery.values.length > 1) {
return doScoreFuzzy2Multiple(target, preparedQuery.values, patternStart, matchOffset);
}
// Score: single input
@@ -285,7 +299,7 @@ function doScoreFuzzy2Multiple(target: string, query: IPreparedQueryPiece[], pat
for (const queryPiece of query) {
const [score, matches] = doScoreFuzzy2Single(target, queryPiece, patternStart, matchOffset);
if (!score) {
if (typeof score !== 'number') {
// if a single query value does not match, return with
// no score entirely, we require all queries to match
return NO_SCORE2;
@@ -796,9 +810,14 @@ export interface IPreparedQueryPiece {
export interface IPreparedQuery extends IPreparedQueryPiece {
// Split by spaces
/**
* Query split by spaces into pieces.
*/
values: IPreparedQueryPiece[] | undefined;
/**
* Wether the query contains path separator(s) or not.
*/
containsPathSeparator: boolean;
}

View File

@@ -6,7 +6,7 @@
export namespace Iterable {
const _empty: Iterable<any> = Object.freeze([]);
export function empty<T>(): Iterable<T> {
export function empty<T = any>(): Iterable<T> {
return _empty;
}

View File

@@ -5,7 +5,9 @@
import { URI } from 'vs/base/common/uri';
import { CharCode } from 'vs/base/common/charCode';
import { compareIgnoreCase, compare } from 'vs/base/common/strings';
import { compareSubstringIgnoreCase, compare, compareSubstring } from 'vs/base/common/strings';
import { Schemas } from 'vs/base/common/network';
import { isLinux } from 'vs/base/common/platform';
/**
* @deprecated ES6: use `[...SetOrMap.values()]`
@@ -102,7 +104,10 @@ export class PathIterator implements IKeyIterator<string> {
private _from!: number;
private _to!: number;
constructor(private _splitOnBackslash: boolean = true) { }
constructor(
private readonly _splitOnBackslash: boolean = true,
private readonly _caseSensitive: boolean = true
) { }
reset(key: string): this {
this._value = key.replace(/\\$|\/$/, '');
@@ -135,27 +140,9 @@ export class PathIterator implements IKeyIterator<string> {
}
cmp(a: string): number {
let aPos = 0;
const aLen = a.length;
let thisPos = this._from;
while (aPos < aLen && thisPos < this._to) {
const cmp = a.charCodeAt(aPos) - this._value.charCodeAt(thisPos);
if (cmp !== 0) {
return cmp;
}
aPos += 1;
thisPos += 1;
}
if (aLen === this._to - this._from) {
return 0;
} else if (aPos < aLen) {
return -1;
} else {
return 1;
}
return this._caseSensitive
? compareSubstring(a, this._value, 0, a.length, this._from, this._to)
: compareSubstringIgnoreCase(a, this._value, 0, a.length, this._from, this._to);
}
value(): string {
@@ -169,7 +156,7 @@ const enum UriIteratorState {
export class UriIterator implements IKeyIterator<URI> {
private _pathIterator = new PathIterator(false);
private _pathIterator!: PathIterator;
private _value!: URI;
private _states: UriIteratorState[] = [];
private _stateIdx: number = 0;
@@ -184,6 +171,10 @@ export class UriIterator implements IKeyIterator<URI> {
this._states.push(UriIteratorState.Authority);
}
if (this._value.path) {
//todo@jrieken the case-sensitive logic is copied form `resources.ts#hasToIgnoreCase`
// which cannot be used because it depends on this
const caseSensitive = key.scheme === Schemas.file && isLinux;
this._pathIterator = new PathIterator(false, caseSensitive);
this._pathIterator.reset(key.path);
if (this._pathIterator.value()) {
this._states.push(UriIteratorState.Path);
@@ -215,9 +206,9 @@ export class UriIterator implements IKeyIterator<URI> {
cmp(a: string): number {
if (this._states[this._stateIdx] === UriIteratorState.Scheme) {
return compareIgnoreCase(a, this._value.scheme);
return compareSubstringIgnoreCase(a, this._value.scheme);
} else if (this._states[this._stateIdx] === UriIteratorState.Authority) {
return compareIgnoreCase(a, this._value.authority);
return compareSubstringIgnoreCase(a, this._value.authority);
} else if (this._states[this._stateIdx] === UriIteratorState.Path) {
return this._pathIterator.cmp(a);
} else if (this._states[this._stateIdx] === UriIteratorState.Query) {

View File

@@ -18,3 +18,19 @@ export class Counter {
return this._next++;
}
}
export class MovingAverage {
private _n = 1;
private _val = 0;
update(value: number): this {
this._val = this._val + (value - this._val) / this._n;
this._n += 1;
return this;
}
get value(): number {
return this._val;
}
}

View File

@@ -317,7 +317,7 @@ export namespace DataUri {
export class ResourceGlobMatcher {
private readonly globalExpression: ParsedExpression;
private readonly expressionsByRoot: TernarySearchTree<string, { root: URI, expression: ParsedExpression }> = TernarySearchTree.forPaths<{ root: URI, expression: ParsedExpression }>();
private readonly expressionsByRoot: TernarySearchTree<URI, { root: URI, expression: ParsedExpression }> = TernarySearchTree.forUris<{ root: URI, expression: ParsedExpression }>();
constructor(
globalExpression: IExpression,
@@ -325,12 +325,12 @@ export class ResourceGlobMatcher {
) {
this.globalExpression = parse(globalExpression);
for (const expression of rootExpressions) {
this.expressionsByRoot.set(expression.root.toString(), { root: expression.root, expression: parse(expression.expression) });
this.expressionsByRoot.set(expression.root, { root: expression.root, expression: parse(expression.expression) });
}
}
matches(resource: URI): boolean {
const rootExpression = this.expressionsByRoot.findSubstr(resource.toString());
const rootExpression = this.expressionsByRoot.findSubstr(resource);
if (rootExpression) {
const path = relativePath(rootExpression.root, resource);
if (path && !!rootExpression.expression(path)) {

View File

@@ -102,14 +102,14 @@ export class ScrollState implements IScrollDimensions, IScrollPosition {
);
}
public withScrollDimensions(update: INewScrollDimensions): ScrollState {
public withScrollDimensions(update: INewScrollDimensions, useRawScrollPositions: boolean): ScrollState {
return new ScrollState(
(typeof update.width !== 'undefined' ? update.width : this.width),
(typeof update.scrollWidth !== 'undefined' ? update.scrollWidth : this.scrollWidth),
this.rawScrollLeft,
useRawScrollPositions ? this.rawScrollLeft : this.scrollLeft,
(typeof update.height !== 'undefined' ? update.height : this.height),
(typeof update.scrollHeight !== 'undefined' ? update.scrollHeight : this.scrollHeight),
this.rawScrollTop
useRawScrollPositions ? this.rawScrollTop : this.scrollTop
);
}
@@ -224,8 +224,8 @@ export class Scrollable extends Disposable {
return this._state;
}
public setScrollDimensions(dimensions: INewScrollDimensions): void {
const newState = this._state.withScrollDimensions(dimensions);
public setScrollDimensions(dimensions: INewScrollDimensions, useRawScrollPositions: boolean): void {
const newState = this._state.withScrollDimensions(dimensions, useRawScrollPositions);
this._setState(newState);
// Validate outstanding animated scroll position target

View File

@@ -295,7 +295,31 @@ export function compare(a: string, b: string): number {
}
}
export function compareIgnoreCase(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {
export function compareSubstring(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {
for (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {
let codeA = a.charCodeAt(aStart);
let codeB = b.charCodeAt(bStart);
if (codeA < codeB) {
return -1;
} else if (codeA > codeB) {
return 1;
}
}
const aLen = aEnd - aStart;
const bLen = bEnd - bStart;
if (aLen < bLen) {
return -1;
} else if (aLen > bLen) {
return 1;
}
return 0;
}
export function compareIgnoreCase(a: string, b: string): number {
return compareSubstringIgnoreCase(a, b, 0, a.length, 0, b.length);
}
export function compareSubstringIgnoreCase(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {
for (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {
@@ -307,26 +331,20 @@ export function compareIgnoreCase(a: string, b: string, aStart: number = 0, aEnd
continue;
}
if (isUpperAsciiLetter(codeA)) {
codeA += 32;
}
if (isUpperAsciiLetter(codeB)) {
codeB += 32;
}
const diff = codeA - codeB;
if (diff === 0) {
// equal -> ignoreCase
if (diff === 32 && isUpperAsciiLetter(codeB)) { //codeB =[65-90] && codeA =[97-122]
continue;
} else if (isLowerAsciiLetter(codeA) && isLowerAsciiLetter(codeB)) {
} else if (diff === -32 && isUpperAsciiLetter(codeA)) { //codeB =[97-122] && codeA =[65-90]
continue;
}
if (isLowerAsciiLetter(codeA) && isLowerAsciiLetter(codeB)) {
//
return diff;
} else {
return compare(a.toLowerCase(), b.toLowerCase());
return compareSubstring(a.toLowerCase(), b.toLowerCase(), aStart, aEnd, bStart, bEnd);
}
}
@@ -833,6 +851,9 @@ export function safeBtoa(str: string): string {
return btoa(encodeURIComponent(str)); // we use encodeURIComponent because btoa fails for non Latin 1 values
}
/**
* @deprecated ES6
*/
export function repeat(s: string, count: number): string {
let result = '';
for (let i = 0; i < count; i++) {

View File

@@ -258,3 +258,19 @@ export type Dto<T> = { [K in keyof T]: T[K] extends URI
: T[K] extends Function
? never
: UriDto<T[K]> };
export function NotImplementedProxy<T>(name: string): { new(): T } {
return <any>class {
constructor() {
return new Proxy({}, {
get(target: any, prop: PropertyKey) {
if (target[prop]) {
return target[prop];
}
throw new Error(`Not Implemented: ${name}->${String(prop)}`);
}
});
}
};
}

View File

@@ -138,10 +138,6 @@ export function toDecodeStream(readable: Readable, options: IDecodeStreamOptions
});
}
export function decode(buffer: Buffer, encoding: string): string {
return iconv.decode(buffer, toNodeEncoding(encoding));
}
export function encodingExists(encoding: string): boolean {
return iconv.encodingExists(toNodeEncoding(encoding));
}
@@ -154,7 +150,7 @@ export function encodeStream(encoding: string, options?: { addBOM?: boolean }):
return iconv.encodeStream(toNodeEncoding(encoding), options);
}
function toNodeEncoding(enc: string | null): string {
export function toNodeEncoding(enc: string | null): string {
if (enc === UTF8_with_bom || enc === null) {
return UTF8; // iconv does not distinguish UTF 8 with or without BOM, so we need to help it
}

View File

@@ -109,8 +109,11 @@
.quick-input-action .monaco-text-button {
font-size: 85%;
padding: 7px 6px 5.5px 6px;
padding: 0 6px;
line-height: initial;
display: flex;
height: 100%;
align-items: center;
}
.quick-input-message {
@@ -202,7 +205,6 @@
}
.quick-input-list .quick-input-list-rows > .quick-input-list-row .codicon[class*='codicon-'] {
color: currentColor !important;
vertical-align: sub;
}

View File

@@ -27,6 +27,7 @@ import { IListVirtualDelegate, IListRenderer } from 'vs/base/browser/ui/list/lis
import { List, IListOptions, IListStyles } from 'vs/base/browser/ui/list/listWidget';
import { IInputBoxStyles } from 'vs/base/browser/ui/inputbox/inputBox';
import { Color } from 'vs/base/common/color';
import { registerIcon, Codicon } from 'vs/base/common/codicons';
export interface IQuickInputOptions {
idPrefix: string;
@@ -67,8 +68,11 @@ const $ = dom.$;
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
const backButtonIcon = registerIcon('quick-input-back', Codicon.arrowLeft);
const backButton = {
iconClass: 'codicon-arrow-left',
iconClass: backButtonIcon.classNames,
tooltip: localize('quickInput.back', "Back"),
handle: -1 // TODO
};
@@ -662,14 +666,14 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
this.ui.list.clearFocus();
}
}));
this.visibleDisposables.add(this.ui.inputBox.onKeyDown(event => {
this.visibleDisposables.add((this._hideInput ? this.ui.list : this.ui.inputBox).onKeyDown((event: KeyboardEvent | StandardKeyboardEvent) => {
switch (event.keyCode) {
case KeyCode.DownArrow:
this.ui.list.focus(QuickInputListFocus.Next);
if (this.canSelectMany) {
this.ui.list.domFocus();
}
event.preventDefault();
dom.EventHelper.stop(event, true);
break;
case KeyCode.UpArrow:
if (this.ui.list.getFocusedElements().length) {
@@ -680,21 +684,21 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
if (this.canSelectMany) {
this.ui.list.domFocus();
}
event.preventDefault();
dom.EventHelper.stop(event, true);
break;
case KeyCode.PageDown:
this.ui.list.focus(QuickInputListFocus.NextPage);
if (this.canSelectMany) {
this.ui.list.domFocus();
}
event.preventDefault();
dom.EventHelper.stop(event, true);
break;
case KeyCode.PageUp:
this.ui.list.focus(QuickInputListFocus.PreviousPage);
if (this.canSelectMany) {
this.ui.list.domFocus();
}
event.preventDefault();
dom.EventHelper.stop(event, true);
break;
case KeyCode.RightArrow:
if (!this._canAcceptInBackground) {
@@ -711,6 +715,18 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
this.onDidAcceptEmitter.fire({ inBackground: true });
}
break;
case KeyCode.Home:
if (event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
this.ui.list.focus(QuickInputListFocus.First);
dom.EventHelper.stop(event, true);
}
break;
case KeyCode.End:
if (event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
this.ui.list.focus(QuickInputListFocus.Last);
dom.EventHelper.stop(event, true);
}
break;
}
}));
@@ -1077,10 +1093,10 @@ export class QuickInputController extends Disposable {
private parentElement: HTMLElement;
private styles: IQuickInputStyles;
private onShowEmitter = new Emitter<void>();
private onShowEmitter = this._register(new Emitter<void>());
readonly onShow = this.onShowEmitter.event;
private onHideEmitter = new Emitter<void>();
private onHideEmitter = this._register(new Emitter<void>());
readonly onHide = this.onHideEmitter.event;
private previousFocusElement?: HTMLElement;
@@ -1287,9 +1303,10 @@ export class QuickInputController extends Disposable {
return this.ui;
}
pick<T extends IQuickPickItem, O extends IPickOptions<T>>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options: O = <O>{}, token: CancellationToken = CancellationToken.None): Promise<O extends { canPickMany: true } ? T[] : T> {
return new Promise<O extends { canPickMany: true } ? T[] : T>((doResolve, reject) => {
let resolve = (result: any) => {
pick<T extends IQuickPickItem, O extends IPickOptions<T>>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options: O = <O>{}, token: CancellationToken = CancellationToken.None): Promise<(O extends { canPickMany: true } ? T[] : T) | undefined> {
type R = (O extends { canPickMany: true } ? T[] : T) | undefined;
return new Promise<R>((doResolve, reject) => {
let resolve = (result: R) => {
resolve = doResolve;
if (options.onKeyMods) {
options.onKeyMods(input.keyMods);
@@ -1306,12 +1323,12 @@ export class QuickInputController extends Disposable {
input,
input.onDidAccept(() => {
if (input.canSelectMany) {
resolve(<any>input.selectedItems.slice());
resolve(<R>input.selectedItems.slice());
input.hide();
} else {
const result = input.activeItems[0];
if (result) {
resolve(<any>result);
resolve(<R>result);
input.hide();
}
}
@@ -1326,7 +1343,7 @@ export class QuickInputController extends Disposable {
if (!input.canSelectMany) {
const result = items[0];
if (result) {
resolve(<any>result);
resolve(<R>result);
input.hide();
}
}
@@ -1388,7 +1405,7 @@ export class QuickInputController extends Disposable {
});
}
input(options: IInputOptions = {}, token: CancellationToken = CancellationToken.None): Promise<string> {
input(options: IInputOptions = {}, token: CancellationToken = CancellationToken.None): Promise<string | undefined> {
return new Promise<string>((resolve, reject) => {
if (token.isCancellationRequested) {
resolve(undefined);

View File

@@ -25,8 +25,9 @@ import { Action } from 'vs/base/common/actions';
import { getIconClass } from 'vs/base/parts/quickinput/browser/quickInputUtils';
import { withNullAsUndefined } from 'vs/base/common/types';
import { IQuickInputOptions } from 'vs/base/parts/quickinput/browser/quickInput';
import { IListOptions, List, IListStyles, IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { IListOptions, List, IListStyles, IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';
import { localize } from 'vs/nls';
const $ = dom.$;
@@ -45,7 +46,7 @@ interface IListElement {
readonly fireButtonTriggered: (event: IQuickPickItemButtonEvent<IQuickPickItem>) => void;
}
class ListElement implements IListElement {
class ListElement implements IListElement, IDisposable {
index!: number;
item!: IQuickPickItem;
saneLabel!: string;
@@ -74,6 +75,10 @@ class ListElement implements IListElement {
constructor(init: IListElement) {
assign(this, init);
}
dispose() {
this._onChecked.dispose();
}
}
interface IListElementTemplateData {
@@ -259,6 +264,8 @@ export class QuickInputList {
onChangedCheckedElements: Event<IQuickPickItem[]> = this._onChangedCheckedElements.event;
private readonly _onButtonTriggered = new Emitter<IQuickPickItemButtonEvent<IQuickPickItem>>();
onButtonTriggered = this._onButtonTriggered.event;
private readonly _onKeyDown = new Emitter<StandardKeyboardEvent>();
onKeyDown: Event<StandardKeyboardEvent> = this._onKeyDown.event;
private readonly _onLeave = new Emitter<void>();
onLeave: Event<void> = this._onLeave.event;
private _fireCheckedEvents = true;
@@ -280,13 +287,7 @@ export class QuickInputList {
setRowLineHeight: false,
multipleSelectionSupport: false,
horizontalScrolling: false,
accessibilityProvider,
ariaProvider: {
getRole: () => 'option',
getSetSize: (_: ListElement, _index: number, listLength: number) => listLength,
getPosInSet: (_: ListElement, index: number) => index
},
ariaRole: 'listbox'
accessibilityProvider
} as IListOptions<ListElement>);
this.list.getHTMLElement().id = id;
this.disposables.push(this.list);
@@ -314,6 +315,8 @@ export class QuickInputList {
}
break;
}
this._onKeyDown.fire(event);
}));
this.disposables.push(this.list.onMouseDown(e => {
if (e.browserEvent.button !== 2) {
@@ -341,6 +344,15 @@ export class QuickInputList {
this.list.setSelection([e.index]);
}
}));
this.disposables.push(
this._onChangedAllVisibleChecked,
this._onChangedCheckedCount,
this._onChangedVisibleCount,
this._onChangedCheckedElements,
this._onButtonTriggered,
this._onLeave,
this._onKeyDown
);
}
@memoize
@@ -439,6 +451,7 @@ export class QuickInputList {
}
return result;
}, [] as ListElement[]);
this.elementDisposables.push(...this.elements);
this.elementDisposables.push(...this.elements.map(element => element.onChecked(() => this.fireCheckedEvents())));
this.elementsToIndexes = this.elements.reduce((map, element, index) => {
@@ -699,8 +712,21 @@ function compareEntries(elementA: ListElement, elementB: ListElement, lookFor: s
return compareAnything(elementA.saneLabel, elementB.saneLabel, lookFor);
}
class QuickInputAccessibilityProvider implements IAccessibilityProvider<ListElement> {
class QuickInputAccessibilityProvider implements IListAccessibilityProvider<ListElement> {
getWidgetAriaLabel(): string {
return localize('quickInput', "Quick Input");
}
getAriaLabel(element: ListElement): string | null {
return element.saneAriaLabel;
}
getWidgetRole() {
return 'listbox';
}
getRole() {
return 'option';
}
}

View File

@@ -6,7 +6,7 @@
import * as assert from 'assert';
import * as scorer from 'vs/base/common/fuzzyScorer';
import { URI } from 'vs/base/common/uri';
import { basename, dirname, sep } from 'vs/base/common/path';
import { basename, dirname, sep, posix, win32 } from 'vs/base/common/path';
import { isWindows } from 'vs/base/common/platform';
import { Schemas } from 'vs/base/common/network';
@@ -27,6 +27,40 @@ class ResourceAccessorClass implements scorer.IItemAccessor<URI> {
const ResourceAccessor = new ResourceAccessorClass();
class ResourceWithSlashAccessorClass implements scorer.IItemAccessor<URI> {
getItemLabel(resource: URI): string {
return basename(resource.fsPath);
}
getItemDescription(resource: URI): string {
return posix.normalize(dirname(resource.path));
}
getItemPath(resource: URI): string {
return posix.normalize(resource.path);
}
}
const ResourceWithSlashAccessor = new ResourceWithSlashAccessorClass();
class ResourceWithBackslashAccessorClass implements scorer.IItemAccessor<URI> {
getItemLabel(resource: URI): string {
return basename(resource.fsPath);
}
getItemDescription(resource: URI): string {
return win32.normalize(dirname(resource.path));
}
getItemPath(resource: URI): string {
return win32.normalize(resource.path);
}
}
const ResourceWithBackslashAccessor = new ResourceWithBackslashAccessorClass();
class NullAccessorClass implements scorer.IItemAccessor<URI> {
getItemLabel(resource: URI): string {
@@ -48,29 +82,24 @@ function _doScore(target: string, query: string, fuzzy: boolean): scorer.FuzzySc
return scorer.scoreFuzzy(target, preparedQuery.normalized, preparedQuery.normalizedLowercase, fuzzy);
}
function _doScore2(target: string, query: string): scorer.FuzzyScore2 {
function _doScore2(target: string, query: string, matchOffset: number = 0): scorer.FuzzyScore2 {
const preparedQuery = scorer.prepareQuery(query);
return scorer.scoreFuzzy2(target, preparedQuery);
return scorer.scoreFuzzy2(target, preparedQuery, 0, matchOffset);
}
function scoreItem<T>(item: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor<T>, cache: scorer.FuzzyScorerCache): scorer.IItemScore {
return scorer.scoreItemFuzzy(item, scorer.prepareQuery(query), fuzzy, accessor, cache);
function scoreItem<T>(item: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor<T>): scorer.IItemScore {
return scorer.scoreItemFuzzy(item, scorer.prepareQuery(query), fuzzy, accessor, Object.create(null));
}
function compareItemsByScore<T>(itemA: T, itemB: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor<T>, cache: scorer.FuzzyScorerCache): number {
return scorer.compareItemsByFuzzyScore(itemA, itemB, scorer.prepareQuery(query), fuzzy, accessor, cache);
function compareItemsByScore<T>(itemA: T, itemB: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor<T>): number {
return scorer.compareItemsByFuzzyScore(itemA, itemB, scorer.prepareQuery(query), fuzzy, accessor, Object.create(null));
}
const NullAccessor = new NullAccessorClass();
let cache: scorer.FuzzyScorerCache = Object.create(null);
suite('Fuzzy Scorer', () => {
setup(() => {
cache = Object.create(null);
});
test('score (fuzzy)', function () {
const target = 'HeLlo-World';
@@ -118,16 +147,16 @@ suite('Fuzzy Scorer', () => {
});
test('scoreItem - matches are proper', function () {
let res = scoreItem(null, 'something', true, ResourceAccessor, cache);
let res = scoreItem(null, 'something', true, ResourceAccessor);
assert.ok(!res.score);
const resource = URI.file('/xyz/some/path/someFile123.txt');
res = scoreItem(resource, 'something', true, NullAccessor, cache);
res = scoreItem(resource, 'something', true, NullAccessor);
assert.ok(!res.score);
// Path Identity
const identityRes = scoreItem(resource, ResourceAccessor.getItemPath(resource), true, ResourceAccessor, cache);
const identityRes = scoreItem(resource, ResourceAccessor.getItemPath(resource), true, ResourceAccessor);
assert.ok(identityRes.score);
assert.equal(identityRes.descriptionMatch!.length, 1);
assert.equal(identityRes.labelMatch!.length, 1);
@@ -137,7 +166,7 @@ suite('Fuzzy Scorer', () => {
assert.equal(identityRes.labelMatch![0].end, ResourceAccessor.getItemLabel(resource).length);
// Basename Prefix
const basenamePrefixRes = scoreItem(resource, 'som', true, ResourceAccessor, cache);
const basenamePrefixRes = scoreItem(resource, 'som', true, ResourceAccessor);
assert.ok(basenamePrefixRes.score);
assert.ok(!basenamePrefixRes.descriptionMatch);
assert.equal(basenamePrefixRes.labelMatch!.length, 1);
@@ -145,7 +174,7 @@ suite('Fuzzy Scorer', () => {
assert.equal(basenamePrefixRes.labelMatch![0].end, 'som'.length);
// Basename Camelcase
const basenameCamelcaseRes = scoreItem(resource, 'sF', true, ResourceAccessor, cache);
const basenameCamelcaseRes = scoreItem(resource, 'sF', true, ResourceAccessor);
assert.ok(basenameCamelcaseRes.score);
assert.ok(!basenameCamelcaseRes.descriptionMatch);
assert.equal(basenameCamelcaseRes.labelMatch!.length, 2);
@@ -155,7 +184,7 @@ suite('Fuzzy Scorer', () => {
assert.equal(basenameCamelcaseRes.labelMatch![1].end, 5);
// Basename Match
const basenameRes = scoreItem(resource, 'of', true, ResourceAccessor, cache);
const basenameRes = scoreItem(resource, 'of', true, ResourceAccessor);
assert.ok(basenameRes.score);
assert.ok(!basenameRes.descriptionMatch);
assert.equal(basenameRes.labelMatch!.length, 2);
@@ -165,7 +194,7 @@ suite('Fuzzy Scorer', () => {
assert.equal(basenameRes.labelMatch![1].end, 5);
// Path Match
const pathRes = scoreItem(resource, 'xyz123', true, ResourceAccessor, cache);
const pathRes = scoreItem(resource, 'xyz123', true, ResourceAccessor);
assert.ok(pathRes.score);
assert.ok(pathRes.descriptionMatch);
assert.ok(pathRes.labelMatch);
@@ -177,7 +206,7 @@ suite('Fuzzy Scorer', () => {
assert.equal(pathRes.descriptionMatch![0].end, 4);
// No Match
const noRes = scoreItem(resource, '987', true, ResourceAccessor, cache);
const noRes = scoreItem(resource, '987', true, ResourceAccessor);
assert.ok(!noRes.score);
assert.ok(!noRes.labelMatch);
assert.ok(!noRes.descriptionMatch);
@@ -192,7 +221,7 @@ suite('Fuzzy Scorer', () => {
test('scoreItem - multiple', function () {
const resource = URI.file('/xyz/some/path/someFile123.txt');
let res1 = scoreItem(resource, 'xyz some', true, ResourceAccessor, cache);
let res1 = scoreItem(resource, 'xyz some', true, ResourceAccessor);
assert.ok(res1.score);
assert.equal(res1.labelMatch?.length, 1);
assert.equal(res1.labelMatch![0].start, 0);
@@ -201,7 +230,7 @@ suite('Fuzzy Scorer', () => {
assert.equal(res1.descriptionMatch![0].start, 1);
assert.equal(res1.descriptionMatch![0].end, 4);
let res2 = scoreItem(resource, 'some xyz', true, ResourceAccessor, cache);
let res2 = scoreItem(resource, 'some xyz', true, ResourceAccessor);
assert.ok(res2.score);
assert.equal(res1.score, res2.score);
assert.equal(res2.labelMatch?.length, 1);
@@ -211,7 +240,7 @@ suite('Fuzzy Scorer', () => {
assert.equal(res2.descriptionMatch![0].start, 1);
assert.equal(res2.descriptionMatch![0].end, 4);
let res3 = scoreItem(resource, 'some xyz file file123', true, ResourceAccessor, cache);
let res3 = scoreItem(resource, 'some xyz file file123', true, ResourceAccessor);
assert.ok(res3.score);
assert.ok(res3.score > res2.score);
assert.equal(res3.labelMatch?.length, 1);
@@ -221,7 +250,7 @@ suite('Fuzzy Scorer', () => {
assert.equal(res3.descriptionMatch![0].start, 1);
assert.equal(res3.descriptionMatch![0].end, 4);
let res4 = scoreItem(resource, 'path z y', true, ResourceAccessor, cache);
let res4 = scoreItem(resource, 'path z y', true, ResourceAccessor);
assert.ok(res4.score);
assert.ok(res4.score < res2.score);
assert.equal(res4.labelMatch?.length, 0);
@@ -234,10 +263,10 @@ suite('Fuzzy Scorer', () => {
test('scoreItem - invalid input', function () {
let res = scoreItem(null, null!, true, ResourceAccessor, cache);
let res = scoreItem(null, null!, true, ResourceAccessor);
assert.equal(res.score, 0);
res = scoreItem(null, 'null', true, ResourceAccessor, cache);
res = scoreItem(null, 'null', true, ResourceAccessor);
assert.equal(res.score, 0);
});
@@ -247,7 +276,7 @@ suite('Fuzzy Scorer', () => {
// xsp is more relevant to the end of the file path even though it matches
// fuzzy also in the beginning. we verify the more relevant match at the
// end gets returned.
const pathRes = scoreItem(resource, 'xspfile123', true, ResourceAccessor, cache);
const pathRes = scoreItem(resource, 'xspfile123', true, ResourceAccessor);
assert.ok(pathRes.score);
assert.ok(pathRes.descriptionMatch);
assert.ok(pathRes.labelMatch);
@@ -262,7 +291,7 @@ suite('Fuzzy Scorer', () => {
test('scoreItem - avoid match scattering (bug #36119)', function () {
const resource = URI.file('projects/ui/cula/ats/target.mk');
const pathRes = scoreItem(resource, 'tcltarget.mk', true, ResourceAccessor, cache);
const pathRes = scoreItem(resource, 'tcltarget.mk', true, ResourceAccessor);
assert.ok(pathRes.score);
assert.ok(pathRes.descriptionMatch);
assert.ok(pathRes.labelMatch);
@@ -276,7 +305,7 @@ suite('Fuzzy Scorer', () => {
// expect "ad" to be matched towards the end of the file because the
// match is more compact
const res = scoreItem(resource, 'ad', true, ResourceAccessor, cache);
const res = scoreItem(resource, 'ad', true, ResourceAccessor);
assert.ok(res.score);
assert.ok(res.descriptionMatch);
assert.ok(!res.labelMatch!.length);
@@ -290,14 +319,14 @@ suite('Fuzzy Scorer', () => {
test('scoreItem - proper target offset', function () {
const resource = URI.file('etem');
const res = scoreItem(resource, 'teem', true, ResourceAccessor, cache);
const res = scoreItem(resource, 'teem', true, ResourceAccessor);
assert.ok(!res.score);
});
test('scoreItem - proper target offset #2', function () {
const resource = URI.file('ede');
const res = scoreItem(resource, 'de', true, ResourceAccessor, cache);
const res = scoreItem(resource, 'de', true, ResourceAccessor);
assert.equal(res.labelMatch!.length, 1);
assert.equal(res.labelMatch![0].start, 1);
@@ -307,7 +336,7 @@ suite('Fuzzy Scorer', () => {
test('scoreItem - proper target offset #3', function () {
const resource = URI.file('/src/vs/editor/browser/viewParts/lineNumbers/flipped-cursor-2x.svg');
const res = scoreItem(resource, 'debug', true, ResourceAccessor, cache);
const res = scoreItem(resource, 'debug', true, ResourceAccessor);
assert.equal(res.descriptionMatch!.length, 3);
assert.equal(res.descriptionMatch![0].start, 9);
@@ -327,7 +356,7 @@ suite('Fuzzy Scorer', () => {
test('scoreItem - no match unless query contained in sequence', function () {
const resource = URI.file('abcde');
const res = scoreItem(resource, 'edcda', true, ResourceAccessor, cache);
const res = scoreItem(resource, 'edcda', true, ResourceAccessor);
assert.ok(!res.score);
});
@@ -336,10 +365,22 @@ suite('Fuzzy Scorer', () => {
const remoteResource = URI.from({ scheme: Schemas.vscodeRemote, path: 'abcde/super/duper' });
for (const resource of [localResource, remoteResource]) {
let res = scoreItem(resource, 'abcde\\super\\duper', true, ResourceAccessor, cache);
let res = scoreItem(resource, 'abcde\\super\\duper', true, ResourceAccessor);
assert.ok(res.score);
res = scoreItem(resource, 'abcde/super/duper', true, ResourceAccessor, cache);
res = scoreItem(resource, 'abcde\\super\\duper', true, ResourceWithSlashAccessor);
assert.ok(res.score);
res = scoreItem(resource, 'abcde\\super\\duper', true, ResourceWithBackslashAccessor);
assert.ok(res.score);
res = scoreItem(resource, 'abcde/super/duper', true, ResourceAccessor);
assert.ok(res.score);
res = scoreItem(resource, 'abcde/super/duper', true, ResourceWithSlashAccessor);
assert.ok(res.score);
res = scoreItem(resource, 'abcde/super/duper', true, ResourceWithBackslashAccessor);
assert.ok(res.score);
}
});
@@ -352,12 +393,12 @@ suite('Fuzzy Scorer', () => {
// Full resource A path
let query = ResourceAccessor.getItemPath(resourceA);
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
@@ -365,12 +406,12 @@ suite('Fuzzy Scorer', () => {
// Full resource B path
query = ResourceAccessor.getItemPath(resourceB);
res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
@@ -384,12 +425,12 @@ suite('Fuzzy Scorer', () => {
// Full resource A basename
let query = ResourceAccessor.getItemLabel(resourceA);
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
@@ -397,12 +438,12 @@ suite('Fuzzy Scorer', () => {
// Full resource B basename
query = ResourceAccessor.getItemLabel(resourceB);
res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
@@ -416,12 +457,12 @@ suite('Fuzzy Scorer', () => {
// resource A camelcase
let query = 'fA';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
@@ -429,12 +470,12 @@ suite('Fuzzy Scorer', () => {
// resource B camelcase
query = 'fB';
res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
@@ -448,12 +489,12 @@ suite('Fuzzy Scorer', () => {
// Resource A part of basename
let query = 'fileA';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
@@ -461,12 +502,12 @@ suite('Fuzzy Scorer', () => {
// Resource B part of basename
query = 'fileB';
res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
@@ -480,12 +521,12 @@ suite('Fuzzy Scorer', () => {
// Resource A part of path
let query = 'pathfileA';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
@@ -493,12 +534,12 @@ suite('Fuzzy Scorer', () => {
// Resource B part of path
query = 'pathfileB';
res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
@@ -512,12 +553,12 @@ suite('Fuzzy Scorer', () => {
// Resource A part of path
let query = 'somepath';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
@@ -531,12 +572,12 @@ suite('Fuzzy Scorer', () => {
// Resource A part of path
let query = 'file';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceC);
assert.equal(res[2], resourceB);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceC);
assert.equal(res[2], resourceB);
@@ -550,12 +591,12 @@ suite('Fuzzy Scorer', () => {
// Resource A part of path
let query = 'somepath';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceB);
assert.equal(res[2], resourceC);
@@ -568,7 +609,7 @@ suite('Fuzzy Scorer', () => {
let query = 'co/te';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
assert.equal(res[2], resourceC);
@@ -580,7 +621,7 @@ suite('Fuzzy Scorer', () => {
let query = 'partsquick';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
});
@@ -591,11 +632,11 @@ suite('Fuzzy Scorer', () => {
let query = 'AH';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
});
@@ -606,11 +647,11 @@ suite('Fuzzy Scorer', () => {
let query = 'xp';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
});
@@ -621,11 +662,11 @@ suite('Fuzzy Scorer', () => {
let query = 'xp';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
});
@@ -636,11 +677,11 @@ suite('Fuzzy Scorer', () => {
let query = 'exfile';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
});
@@ -653,18 +694,18 @@ suite('Fuzzy Scorer', () => {
let query = isWindows ? 'modu1\\index.js' : 'modu1/index.js';
let res = [resourceA, resourceB, resourceC, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceC);
res = [resourceC, resourceB, resourceA, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceC);
query = isWindows ? 'un1\\index.js' : 'un1/index.js';
res = [resourceA, resourceB, resourceC, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceA, resourceB, resourceC, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceC, resourceB, resourceA, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA, resourceD].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -675,10 +716,10 @@ suite('Fuzzy Scorer', () => {
let query = 'StatVideoindex';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceC);
});
@@ -688,10 +729,10 @@ suite('Fuzzy Scorer', () => {
let query = 'reproreduxts';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -702,10 +743,10 @@ suite('Fuzzy Scorer', () => {
let query = 'bookpageIndex';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceC);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceC);
});
@@ -715,10 +756,10 @@ suite('Fuzzy Scorer', () => {
let query = isWindows ? 'ui\\icons' : 'ui/icons';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -728,10 +769,10 @@ suite('Fuzzy Scorer', () => {
let query = isWindows ? 'ui\\input\\index' : 'ui/input/index';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -741,10 +782,10 @@ suite('Fuzzy Scorer', () => {
let query = 'djancosig';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -755,12 +796,12 @@ suite('Fuzzy Scorer', () => {
let query = 'protectedconfig.php';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceC);
assert.equal(res[2], resourceB);
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceC, resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceA);
assert.equal(res[1], resourceC);
assert.equal(res[2], resourceB);
@@ -772,10 +813,10 @@ suite('Fuzzy Scorer', () => {
let query = 'gradientmain';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -785,10 +826,10 @@ suite('Fuzzy Scorer', () => {
let query = 'abc';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -798,10 +839,10 @@ suite('Fuzzy Scorer', () => {
let query = 'xyz';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -811,10 +852,10 @@ suite('Fuzzy Scorer', () => {
let query = 'async';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -824,10 +865,10 @@ suite('Fuzzy Scorer', () => {
let query = 'partisettings';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -837,10 +878,10 @@ suite('Fuzzy Scorer', () => {
let query = 'tipsindex.cshtml';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -850,10 +891,10 @@ suite('Fuzzy Scorer', () => {
let query = 'listview';
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -864,10 +905,10 @@ suite('Fuzzy Scorer', () => {
let query = 'filesexplorerview.ts';
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
let res = [resourceA, resourceB, resourceC].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
res = [resourceA, resourceC, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache));
res = [resourceA, resourceC, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
});
@@ -932,6 +973,28 @@ suite('Fuzzy Scorer', () => {
}
});
test('fuzzyScore2 (matching)', function () {
const target = 'HeLlo-World';
for (const offset of [0, 3]) {
let [score, matches] = _doScore2(target, 'HeLlo-World', offset);
assert.ok(score);
assert.equal(matches.length, 1);
assert.equal(matches[0].start, 0 + offset);
assert.equal(matches[0].end, target.length + offset);
[score, matches] = _doScore2(target, 'HW', offset);
assert.ok(score);
assert.equal(matches.length, 2);
assert.equal(matches[0].start, 0 + offset);
assert.equal(matches[0].end, 1 + offset);
assert.equal(matches[1].start, 6 + offset);
assert.equal(matches[1].end, 7 + offset);
}
});
test('fuzzyScore2 (multiple queries)', function () {
const target = 'HeLlo-World';
@@ -957,7 +1020,7 @@ suite('Fuzzy Scorer', () => {
}
function assertNoScore() {
assert.equal(multiScore, 0);
assert.equal(multiScore, undefined);
assert.equal(multiMatches.length, 0);
}
@@ -975,4 +1038,13 @@ suite('Fuzzy Scorer', () => {
[multiScore, multiMatches] = _doScore2(target, 'More Nothing');
assertNoScore();
});
test('fuzzyScore2 (#95716)', function () {
const target = '# ❌ Wow';
const score = _doScore2(target, '❌');
assert.ok(score);
assert.ok(typeof score[0] === 'number');
assert.ok(score[1].length > 0);
});
});

View File

@@ -84,7 +84,7 @@ suite('Strings', () => {
test('compareIgnoreCase (substring)', () => {
function assertCompareIgnoreCase(a: string, b: string, aStart: number, aEnd: number, bStart: number, bEnd: number, recurse = true): void {
let actual = strings.compareIgnoreCase(a, b, aStart, aEnd, bStart, bEnd);
let actual = strings.compareSubstringIgnoreCase(a, b, aStart, aEnd, bStart, bEnd);
actual = actual > 0 ? 1 : actual < 0 ? -1 : actual;
let expected = strings.compare(a.toLowerCase().substring(aStart, aEnd), b.toLowerCase().substring(bStart, bEnd));

View File

@@ -8,6 +8,7 @@ import * as fs from 'fs';
import * as encoding from 'vs/base/node/encoding';
import * as terminalEncoding from 'vs/base/node/terminalEncoding';
import { Readable } from 'stream';
import * as iconv from 'iconv-lite';
import { getPathFromAmdModule } from 'vs/base/common/amd';
export async function detectEncodingByBOM(file: string): Promise<typeof encoding.UTF16be | typeof encoding.UTF16le | typeof encoding.UTF8_with_bom | null> {
@@ -224,7 +225,7 @@ suite('Encoding', () => {
if (err) {
reject(err);
} else {
resolve(encoding.decode(data, fileEncoding!));
resolve(iconv.decode(data, encoding.toNodeEncoding(fileEncoding!)));
}
});
});