未验证 提交 f7316889 编写于 作者: J Johannes Rieken 提交者: GitHub

Merge pull request #49917 from Microsoft/joh/outline

Implements an outline view
......@@ -146,6 +146,10 @@
"name": "vs/workbench/parts/welcome",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/outline",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/actions",
"project": "vscode-workbench"
......
......@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { DocumentSymbolProvider, SymbolInformation, SymbolKind, TextDocument, CancellationToken, Uri } from 'vscode';
import { DocumentSymbolProvider, SymbolInformation, SymbolKind, TextDocument, CancellationToken, Uri, HierarchicalSymbolInformation } from 'vscode';
import * as Proto from '../protocol';
import * as PConst from '../protocol.const';
......@@ -31,7 +31,7 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP
public constructor(
private readonly client: ITypeScriptServiceClient) { }
public async provideDocumentSymbols(resource: TextDocument, token: CancellationToken): Promise<SymbolInformation[]> {
public async provideDocumentSymbols(resource: TextDocument, token: CancellationToken): Promise<any[]> { // todo@joh `any[]` temporary hack to make typescript happy...
const filepath = this.client.normalizePath(resource.uri);
if (!filepath) {
return [];
......@@ -41,21 +41,21 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP
};
try {
const result: SymbolInformation[] = [];
const result: SymbolInformation[] | HierarchicalSymbolInformation[] = [];
if (this.client.apiVersion.has206Features()) {
const response = await this.client.execute('navtree', args, token);
if (response.body) {
// The root represents the file. Ignore this when showing in the UI
let tree = response.body;
if (tree.childItems) {
tree.childItems.forEach(item => TypeScriptDocumentSymbolProvider.convertNavTree(resource.uri, result, item));
tree.childItems.forEach(item => TypeScriptDocumentSymbolProvider.convertNavTree(resource.uri, result as HierarchicalSymbolInformation[], item));
}
}
} else {
const response = await this.client.execute('navbar', args, token);
if (response.body) {
let foldingMap: ObjectMap<SymbolInformation> = Object.create(null);
response.body.forEach(item => TypeScriptDocumentSymbolProvider.convertNavBar(resource.uri, 0, foldingMap, result, item));
response.body.forEach(item => TypeScriptDocumentSymbolProvider.convertNavBar(resource.uri, 0, foldingMap, result as SymbolInformation[], item));
}
}
return result;
......@@ -82,15 +82,18 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP
}
}
private static convertNavTree(resource: Uri, bucket: SymbolInformation[], item: Proto.NavigationTree, containerLabel?: string): void {
const result = new SymbolInformation(item.text,
private static convertNavTree(resource: Uri, bucket: HierarchicalSymbolInformation[], item: Proto.NavigationTree): void {
const result = new HierarchicalSymbolInformation(
item.text,
'', // detail, e.g. signature etc
outlineTypeTable[item.kind as string] || SymbolKind.Variable,
containerLabel ? containerLabel : '',
typeConverters.Location.fromTextSpan(resource, item.spans[0])
typeConverters.Location.fromTextSpan(resource, item.spans[0]),
typeConverters.Range.fromTextSpan(item.spans[0])
);
if (item.childItems && item.childItems.length > 0) {
result.children = [];
for (const child of item.childItems) {
TypeScriptDocumentSymbolProvider.convertNavTree(resource, bucket, child, result.name);
TypeScriptDocumentSymbolProvider.convertNavTree(resource, result.children, child);
}
}
......@@ -102,4 +105,4 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP
private static shouldInclueEntry(name: string): boolean {
return !!(name && name !== '<function>' && name !== '<class>');
}
}
\ No newline at end of file
}
......@@ -18,6 +18,7 @@ export class HighlightedLabel implements IDisposable {
private domNode: HTMLElement;
private text: string;
private title: string;
private highlights: IHighlight[];
private didEverRender: boolean;
......@@ -32,11 +33,14 @@ export class HighlightedLabel implements IDisposable {
return this.domNode;
}
set(text: string, highlights: IHighlight[] = []) {
set(text: string, highlights: IHighlight[] = [], title?: string) {
if (!text) {
text = '';
}
if (this.didEverRender && this.text === text && objects.equals(this.highlights, highlights)) {
if (!title) {
title = text;
}
if (this.didEverRender && this.text === text && this.title === title && objects.equals(this.highlights, highlights)) {
return;
}
......@@ -45,6 +49,7 @@ export class HighlightedLabel implements IDisposable {
}
this.text = text;
this.title = title || text;
this.highlights = highlights;
this.render();
}
......@@ -80,6 +85,7 @@ export class HighlightedLabel implements IDisposable {
}
this.domNode.innerHTML = htmlContent.join('');
this.domNode.title = this.title;
this.didEverRender = true;
}
......
......@@ -5,7 +5,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
export interface ITelemetryData {
......@@ -237,3 +237,26 @@ export class ActionRunner implements IActionRunner {
this._onDidRun.dispose();
}
}
export class RadioGroup {
private _disposable: IDisposable;
constructor(readonly actions: Action[]) {
this._disposable = combinedDisposable(actions.map(action => {
return action.onDidChange(e => {
if (e.checked && action.checked) {
for (const candidate of actions) {
if (candidate !== action) {
candidate.checked = false;
}
}
}
});
}));
}
dispose(): void {
this._disposable.dispose();
}
}
......@@ -47,6 +47,15 @@ export function size<T>(from: IStringDictionary<T> | INumberDictionary<T>): numb
return count;
}
export function first<T>(from: IStringDictionary<T> | INumberDictionary<T>): T {
for (let key in from) {
if (hasOwnProperty.call(from, key)) {
return from[key];
}
}
return undefined;
}
/**
* Iterates over each entry in the provided set. The iterator allows
* to remove elements and will stop when the callback returns {{false}}.
......
......@@ -14,7 +14,7 @@ import * as dom from 'vs/base/browser/dom';
import * as mouse from 'vs/base/browser/mouseEvent';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import * as _ from 'vs/base/parts/tree/browser/tree';
import { KeyCode, KeyMod, Keybinding, createKeybinding, SimpleKeybinding } from 'vs/base/common/keyCodes';
import { KeyCode, KeyMod, Keybinding, createKeybinding, SimpleKeybinding, createSimpleKeybinding } from 'vs/base/common/keyCodes';
export interface IKeyBindingCallback {
(tree: _.ITree, event: IKeyboardEvent): void;
......@@ -62,7 +62,17 @@ export class KeybindingDispatcher {
this._arr = [];
}
public set(keybinding: number, callback: IKeyBindingCallback) {
public has(keybinding: KeyCode): boolean {
let target = createSimpleKeybinding(keybinding, platform.OS);
for (const a of this._arr) {
if (target.equals(a.keybinding)) {
return true;
}
}
return false;
}
public set(keybinding: KeyCode, callback: IKeyBindingCallback) {
this._arr.push({
keybinding: createKeybinding(keybinding, platform.OS),
callback: callback
......@@ -203,7 +213,7 @@ export class DefaultController implements _.IController {
// the twistie is drawn, but the <div class="content"> element in the
// tree item is the only thing we get back as target when the user clicks
// on the twistie.
return target && target.className === 'content' && dom.hasClass(target.parentElement, 'monaco-tree-row');
return target && dom.hasClass(target, 'content') && dom.hasClass(target.parentElement, 'monaco-tree-row');
}
public onContextMenu(tree: _.ITree, element: any, event: _.ContextMenuEvent): boolean {
......
......@@ -676,6 +676,9 @@ export interface SymbolInformation {
* the [go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_goto-symbol)-feature.
*/
export interface DocumentSymbolProvider {
extensionId?: string;
/**
* Provide symbol information for the given document.
*/
......
......@@ -4893,6 +4893,7 @@ declare namespace monaco.languages {
* the [go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_goto-symbol)-feature.
*/
export interface DocumentSymbolProvider {
extensionId?: string;
/**
* Provide symbol information for the given document.
*/
......
......@@ -82,6 +82,9 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
return <modes.SymbolInformation[]>data;
} else {
data.location = MainThreadLanguageFeatures._reviveLocationDto(data.location);
if (data.children) {
data.children.forEach(MainThreadLanguageFeatures._reviveSymbolInformationDto);
}
return <modes.SymbolInformation>data;
}
}
......@@ -97,8 +100,9 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- outline
$registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
$registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[], extensionId: string): void {
this._registrations[handle] = modes.DocumentSymbolProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.DocumentSymbolProvider>{
extensionId,
provideDocumentSymbols: (model: ITextModel, token: CancellationToken): Thenable<modes.SymbolInformation[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentSymbols(handle, model.uri)).then(MainThreadLanguageFeatures._reviveSymbolInformationDto);
}
......
......@@ -287,7 +287,7 @@ export function createApiFactory(
return extHostLanguageFeatures.registerRenameProvider(checkSelector(selector), provider);
},
registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentSymbolProvider(checkSelector(selector), provider);
return extHostLanguageFeatures.registerDocumentSymbolProvider(checkSelector(selector), provider, extension.id);
},
registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
return extHostLanguageFeatures.registerWorkspaceSymbolProvider(provider);
......@@ -674,9 +674,9 @@ export function createApiFactory(
StatusBarAlignment: extHostTypes.StatusBarAlignment,
SymbolInformation: extHostTypes.SymbolInformation,
HierarchicalSymbolInformation: class extends extHostTypes.HierarchicalSymbolInformation {
constructor(name, kind, detail, keyof, range) {
constructor(name, detail, kind, keyof, range) {
checkProposedApiEnabled(extension);
super(name, kind, detail, keyof, range);
super(name, detail, kind, keyof, range);
}
},
SymbolKind: extHostTypes.SymbolKind,
......
......@@ -263,7 +263,7 @@ export interface ISerializedDocumentFilter {
export interface MainThreadLanguageFeaturesShape extends IDisposable {
$unregister(handle: number): void;
$registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[], extensionId: string): void;
$registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number): void;
$emitCodeLensEvent(eventHandle: number, event?: any): void;
$registerDeclaractionSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
......@@ -666,6 +666,8 @@ export interface SymbolInformationDto extends IdObject {
containerName?: string;
kind: modes.SymbolKind;
location: LocationDto;
definingRange: IRange;
children?: SymbolInformationDto[];
}
export interface WorkspaceSymbolsDto extends IdObject {
......
......@@ -44,12 +44,43 @@ class OutlineAdapter {
return undefined;
}
let [probe] = value;
if (probe instanceof HierarchicalSymbolInformation) {
return (<HierarchicalSymbolInformation[]>value).map(typeConvert.HierarchicalSymbolInformation.from);
} else {
return (<SymbolInformation[]>value).map(typeConvert.SymbolInformation.from);
if (!(probe instanceof HierarchicalSymbolInformation)) {
value = OutlineAdapter._asSymbolTree(<SymbolInformation[]>value);
}
return (<HierarchicalSymbolInformation[]>value).map(typeConvert.HierarchicalSymbolInformation.from);
});
}
private static _asSymbolTree(info: SymbolInformation[]): vscode.HierarchicalSymbolInformation[] {
// first sort by start (and end) and then loop over all elements
// and build a tree based on containment.
info = info.slice(0).sort((a, b) => {
let res = a.location.range.start.compareTo(b.location.range.start);
if (res === 0) {
res = b.location.range.end.compareTo(a.location.range.end);
}
return res;
});
let res: HierarchicalSymbolInformation[] = [];
let parentStack: HierarchicalSymbolInformation[] = [];
for (let i = 0; i < info.length; i++) {
let element = new HierarchicalSymbolInformation(info[i].name, '', info[i].kind, info[i].location, info[i].location.range);
while (true) {
if (parentStack.length === 0) {
parentStack.push(element);
res.push(element);
break;
}
let parent = parentStack[parentStack.length - 1];
if (parent.range.contains(element.range)) {
parent.children.push(element);
parentStack.push(element);
break;
}
parentStack.pop();
}
}
return res;
}
}
......@@ -928,9 +959,9 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
// --- outline
registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider, extensionId?: string): vscode.Disposable {
const handle = this._addNewAdapter(new OutlineAdapter(this._documents, provider));
this._proxy.$registerOutlineSupport(handle, this._transformDocumentSelector(selector));
this._proxy.$registerOutlineSupport(handle, this._transformDocumentSelector(selector), extensionId);
return this._createDisposable(handle);
}
......
......@@ -380,8 +380,8 @@ export namespace HierarchicalSymbolInformation {
export function to(info: modes.SymbolInformation): types.HierarchicalSymbolInformation {
let result = new types.HierarchicalSymbolInformation(
info.name,
SymbolKind.to(info.kind),
info.detail,
SymbolKind.to(info.kind),
location.to(info.location),
Range.to(info.definingRange)
);
......
......@@ -884,29 +884,13 @@ export class HierarchicalSymbolInformation {
range: Range;
children: HierarchicalSymbolInformation[];
constructor(name: string, kind: SymbolKind, detail: string, location: Location, range: Range) {
constructor(name: string, detail: string, kind: SymbolKind, location: Location, range: Range) {
this.name = name;
this.kind = kind;
this.location = location;
this.range = range;
this.children = [];
}
static toFlatSymbolInformation(info: HierarchicalSymbolInformation): SymbolInformation[] {
let result: SymbolInformation[] = [];
HierarchicalSymbolInformation._toFlatSymbolInformation(info, undefined, result);
return result;
}
private static _toFlatSymbolInformation(info: HierarchicalSymbolInformation, containerName: string, bucket: SymbolInformation[]): void {
bucket.push(new SymbolInformation(info.name, info.kind, containerName, new Location(info.location.uri, info.range)));
if (Array.isArray(info.children)) {
for (const child of info.children) {
HierarchicalSymbolInformation._toFlatSymbolInformation(child, info.name, bucket);
}
}
}
}
export class CodeAction {
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M2.879 14L1 12.121V3.879L2.879 2h10.242L15 3.879v8.242L13.121 14H2.879z" id="outline"/><path class="icon-vs-fg" d="M12.293 4H3.707L3 4.707v6.586l.707.707h8.586l.707-.707V4.707L12.293 4zM11 10H5V9h6v1zm0-3H5V6h6v1z" id="iconFg"/><g id="iconBg"><path class="icon-vs-bg" d="M12.707 13H3.293L2 11.707V4.293L3.293 3h9.414L14 4.293v7.414L12.707 13zm-9-1h8.586l.707-.707V4.707L12.293 4H3.707L3 4.707v6.586l.707.707z"/><path class="icon-vs-action-blue" d="M11 7H5V6h6v1zm0 2H5v1h6V9z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#252526}.icon-vs-out{fill:#252526}.icon-vs-bg{fill:#c5c5c5}.icon-vs-fg{fill:#2b282e}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M2.879 14L1 12.121V3.879L2.879 2h10.242L15 3.879v8.242L13.121 14H2.879z" id="outline"/><path class="icon-vs-fg" d="M12.293 4H3.707L3 4.707v6.586l.707.707h8.586l.707-.707V4.707L12.293 4zM11 10H5V9h6v1zm0-3H5V6h6v1z" id="iconFg"/><g id="iconBg"><path class="icon-vs-bg" d="M12.707 13H3.293L2 11.707V4.293L3.293 3h9.414L14 4.293v7.414L12.707 13zm-9-1h8.586l.707-.707V4.707L12.293 4H3.707L3 4.707v6.586l.707.707z"/><path class="icon-vs-action-blue" d="M11 7H5V6h6v1zm0 2H5v1h6V9z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 15V6h6V2.586L7.585 1h6.829L16 2.586v5.829L14.414 10H10v5H0zm3-6z" id="outline"/><path class="icon-vs-fg" d="M8 3v3h5v1h-3v1h4V3H8zm5 2H9V4h4v1zM2 8v5h6V8H2zm5 3H3v-1h4v1z" id="iconFg"/><path class="icon-vs-action-blue" d="M10 6h3v1h-3V6zM9 4v1h4V4H9zm5-2H8L7 3v3h1V3h6v5h-4v1h4l1-1V3l-1-1zm-7 8H3v1h4v-1zm2-3v7H1V7h8zM8 8H2v5h6V8z" id="iconBg"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-fg{fill:#2b282e}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 15V6h6V2.586L7.585 1h6.829L16 2.586v5.829L14.414 10H10v5H0zm3-6z" id="outline"/><path class="icon-vs-fg" d="M8 3v3h5v1h-3v1h4V3H8zm5 2H9V4h4v1zM2 8v5h6V8H2zm5 3H3v-1h4v1z" id="iconFg"/><path class="icon-vs-action-blue" d="M10 6h3v1h-3V6zM9 4v1h4V4H9zm5-2H8L7 3v3h1V3h6v5h-4v1h4l1-1V3l-1-1zm-7 8H3v1h4v-1zm2-3v7H1V7h8zM8 8H2v5h6V8z" id="iconBg"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-action-orange{fill:#c27d1a}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M14 1.414L9.414 6H14v1.414L5.414 16H3v-1.234L5.371 10H2V8.764L6.382 0H14v1.414z" id="outline" style="display: none;"/><path class="icon-vs-action-orange" d="M7 7h6l-8 8H4l2.985-6H3l4-8h6L7 7z" id="iconBg"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-action-orange{fill:#e8ab53}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M14 1.414L9.414 6H14v1.414L5.414 16H3v-1.234L5.371 10H2V8.764L6.382 0H14v1.414z" id="outline" style="display: none;"/><path class="icon-vs-action-orange" d="M7 7h6l-8 8H4l2.985-6H3l4-8h6L7 7z" id="iconBg"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 16H0V0h16v16z" id="outline" style="display: none;"/><path class="icon-vs-action-blue" d="M1 1v14h14V1H1zm6 12H3v-1h4v1zm0-3H3V9h4v1zm0-5H5v2H4V5H2V4h2V2h1v2h2v1zm3.281 8H8.719l3-4h1.563l-3.001 4zM14 5H9V4h5v1z" id="iconBg"/><path class="icon-vs-fg" d="M7 5H5v2H4V5H2V4h2V2h1v2h2v1zm7-1H9v1h5V4zM7 9H3v1h4V9zm0 3H3v1h4v-1zm3.281 1l3-4h-1.563l-3 4h1.563z" id="iconFg" style="display: none;"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-fg{fill:#2b282e}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 16H0V0h16v16z" id="outline" style="display: none;"/><path class="icon-vs-action-blue" d="M1 1v14h14V1H1zm6 12H3v-1h4v1zm0-3H3V9h4v1zm0-5H5v2H4V5H2V4h2V2h1v2h2v1zm3.281 8H8.719l3-4h1.563l-3.001 4zM14 5H9V4h5v1z" id="iconBg"/><path class="icon-vs-fg" d="M7 5H5v2H4V5H2V4h2V2h1v2h2v1zm7-1H9v1h5V4zM7 9H3v1h4V9zm0 3H3v1h4v-1zm3.281 1l3-4h-1.563l-3 4h1.563z" id="iconFg" style="display: none;"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M9 14V8H7v6H1V2h14v12H9z" id="outline" style="display: none;"/><path class="icon-vs-action-blue" d="M10 9h4v4h-4V9zm-8 4h4V9H2v4zM2 3v4h12V3H2z" id="iconBg"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M9 14V8H7v6H1V2h14v12H9z" id="outline" style="display: none;"/><path class="icon-vs-action-blue" d="M10 9h4v4h-4V9zm-8 4h4V9H2v4zM2 3v4h12V3H2z" id="iconBg"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M10.702 10.5l2-2-2-2 .5-.5H10v5h1v3H5v-3h1V6H4.798l.5.5-2 2 2 2L3 12.797l-3-3V7.201l3-3V2h10v2.201l3 3v2.596l-3 3-2.298-2.297z" id="outline" style="display: none;"/><path class="icon-vs-bg" d="M4 3h8v2h-1v-.5c0-.277-.224-.5-.5-.5H9v7.5c0 .275.224.5.5.5h.5v1H6v-1h.5a.5.5 0 0 0 .5-.5V4H5.5a.5.5 0 0 0-.5.5V5H4V3zM3 5.615L.116 8.5 3 11.383l.884-.883-2-2 2-2L3 5.615zm10 0l-.884.885 2 2-2 2 .884.883L15.884 8.5 13 5.615z" id="iconBg"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M10.702 10.5l2-2-2-2 .5-.5H10v5h1v3H5v-3h1V6H4.798l.5.5-2 2 2 2L3 12.797l-3-3V7.201l3-3V2h10v2.201l3 3v2.596l-3 3-2.298-2.297z" id="outline" style="display: none;"/><path class="icon-vs-bg" d="M4 3h8v2h-1v-.5c0-.277-.224-.5-.5-.5H9v7.5c0 .275.224.5.5.5h.5v1H6v-1h.5a.5.5 0 0 0 .5-.5V4H5.5a.5.5 0 0 0-.5.5V5H4V3zM3 5.615L.116 8.5 3 11.383l.884-.883-2-2 2-2L3 5.615zm10 0l-.884.885 2 2-2 2 .884.883L15.884 8.5 13 5.615z" id="iconBg"/></svg>
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench .symbol-icon {
display: inline-block;
height: 14px;
width: 16px;
min-height: 14px;
min-width: 16px;
}
.monaco-workbench .symbol-icon.constant {
background-image: url('Constant_16x.svg');
background-repeat: no-repeat;
background-position: 0 -2px;
}
.vs-dark .monaco-workbench .symbol-icon.constant, .hc-black .monaco-workbench .symbol-icon.constant {
background-image: url('Constant_16x_inverse.svg');
}
.monaco-workbench .symbol-icon.enum-member {
background-image: url('EnumItem_16x.svg');
background-repeat: no-repeat;
background-position: 0 -2px;
}
.vs-dark .monaco-workbench .symbol-icon.enum-member, .hc-black .monaco-workbench .symbol-icon.enum-member {
background-image: url('EnumItem_inverse_16x.svg');
}
.monaco-workbench .symbol-icon.struct {
background-image: url('Structure_16x_vscode.svg');
background-repeat: no-repeat;
background-position: 0 -2px;
}
.vs-dark .monaco-workbench .symbol-icon.struct, .hc-black .monaco-workbench .symbol-icon.struct {
background-image: url('Structure_16x_vscode_inverse.svg');
}
.monaco-workbench .symbol-icon.event {
background-image: url('Event_16x_vscode.svg');
background-repeat: no-repeat;
background-position: 0 -2px;
}
.vs-dark .monaco-workbench .symbol-icon.event, .hc-black .monaco-workbench .symbol-icon.event {
background-image: url('Event_16x_vscode_inverse.svg');
}
.monaco-workbench .symbol-icon.operator {
background-image: url('Operator_16x_vscode.svg');
background-repeat: no-repeat;
background-position: 0 -2px;
}
.vs-dark .monaco-workbench .symbol-icon.operator, .hc-black .monaco-workbench .symbol-icon.operator {
background-image: url('Operator_16x_vscode_inverse.svg');
}
.monaco-workbench .symbol-icon.type-parameter {
background-image: url('Template_16x_vscode.svg');
background-repeat: no-repeat;
background-position: 0 -2px;
}
.vs-dark .monaco-workbench .symbol-icon.type-parameter, .hc-black .monaco-workbench .symbol-icon.type-parameter {
background-image: url('Template_16x_vscode_inverse.svg');
}
.monaco-workbench .symbol-icon.method, .monaco-workbench .symbol-icon.function, .monaco-workbench .symbol-icon.constructor, .monaco-workbench .symbol-icon.field, .monaco-workbench .symbol-icon.variable, .monaco-workbench .symbol-icon.class, .monaco-workbench .symbol-icon.interface, .monaco-workbench .symbol-icon.object, .monaco-workbench .symbol-icon.namespace, .monaco-workbench .symbol-icon.package, .monaco-workbench .symbol-icon.module, .monaco-workbench .symbol-icon.property, .monaco-workbench .symbol-icon.enum, .monaco-workbench .symbol-icon.key, .monaco-workbench .symbol-icon.string, .monaco-workbench .symbol-icon.rule, .monaco-workbench .symbol-icon.file, .monaco-workbench .symbol-icon.array, .monaco-workbench .symbol-icon.number, .monaco-workbench .symbol-icon.null, .monaco-workbench .symbol-icon.boolean {
background-image: url('symbol-sprite.svg');
background-repeat: no-repeat;
}
.vs .monaco-workbench .symbol-icon.method, .vs .monaco-workbench .symbol-icon.function, .vs .monaco-workbench .symbol-icon.constructor {
background-position: 0 -4px;
}
.vs .monaco-workbench .symbol-icon.field, .vs .monaco-workbench .symbol-icon.variable {
background-position: -22px -4px;
}
.vs .monaco-workbench .symbol-icon.class {
background-position: -43px -3px;
}
.vs .monaco-workbench .symbol-icon.interface {
background-position: -63px -4px;
}
.vs .monaco-workbench .symbol-icon.object, .vs .monaco-workbench .symbol-icon.namespace, .vs .monaco-workbench .symbol-icon.package, .vs .monaco-workbench .symbol-icon.module {
background-position: -82px -4px;
}
.vs .monaco-workbench .symbol-icon.property {
background-position: -102px -3px;
}
.vs .monaco-workbench .symbol-icon.enum {
background-position: -122px -3px;
}
.vs .monaco-workbench .symbol-icon.key, .vs .monaco-workbench .symbol-icon.string {
background-position: -202px -3px;
}
.vs .monaco-workbench .symbol-icon.rule {
background-position: -242px -4px;
}
.vs .monaco-workbench .symbol-icon.file {
background-position: -262px -4px;
}
.vs .monaco-workbench .symbol-icon.array {
background-position: -302px -4px;
}
.vs .monaco-workbench .symbol-icon.number {
background-position: -322px -4px;
}
.vs .monaco-workbench .symbol-icon.null, .vs .monaco-workbench .symbol-icon.boolean {
background-position: -343px -4px;
}
.vs-dark .monaco-workbench .symbol-icon.method, .vs-dark .monaco-workbench .symbol-icon.function, .vs-dark .monaco-workbench .symbol-icon.constructor, .hc-black .monaco-workbench .symbol-icon.method, .hc-black .monaco-workbench .symbol-icon.function, .hc-black .monaco-workbench .symbol-icon.constructor {
background-position: 0 -24px;
}
.vs-dark .monaco-workbench .symbol-icon.field, .hc-black .monaco-workbench .symbol-icon.field, .vs-dark .monaco-workbench .symbol-icon.variable, .hc-black .monaco-workbench .symbol-icon.variable {
background-position: -22px -24px;
}
.vs-dark .monaco-workbench .symbol-icon.class, .hc-black .monaco-workbench .symbol-icon.class {
background-position: -43px -23px;
}
.vs-dark .monaco-workbench .symbol-icon.interface, .hc-black .monaco-workbench .symbol-icon.interface {
background-position: -63px -24px;
}
.vs-dark .monaco-workbench .symbol-icon.object, .vs-dark .monaco-workbench .symbol-icon.namespace, .vs-dark .monaco-workbench .symbol-icon.package, .vs-dark .monaco-workbench .symbol-icon.module, .hc-black .monaco-workbench .symbol-icon.object, .hc-black .monaco-workbench .symbol-icon.namespace, .hc-black .monaco-workbench .symbol-icon.package, .hc-black .monaco-workbench .symbol-icon.module {
background-position: -82px -24px;
}
.vs-dark .monaco-workbench .symbol-icon.property, .hc-black .monaco-workbench .symbol-icon.property {
background-position: -102px -23px;
}
.vs-dark .monaco-workbench .symbol-icon.key, .vs-dark .monaco-workbench .symbol-icon.string, .hc-black .monaco-workbench .symbol-icon.key, .hc-black .monaco-workbench .symbol-icon.string {
background-position: -202px -23px;
}
.vs-dark .monaco-workbench .symbol-icon.enum, .hc-black .monaco-workbench .symbol-icon.enum {
background-position: -122px -23px;
}
.vs-dark .monaco-workbench .symbol-icon.rule, .hc-black .monaco-workbench .symbol-icon.rule {
background-position: -242px -24px;
}
.vs-dark .monaco-workbench .symbol-icon.file, .hc-black .monaco-workbench .symbol-icon.file {
background-position: -262px -24px;
}
.vs-dark .monaco-workbench .symbol-icon.array, .hc-black .monaco-workbench .symbol-icon.array {
background-position: -302px -24px;
}
.vs-dark .monaco-workbench .symbol-icon.number, .hc-black .monaco-workbench .symbol-icon.number {
background-position: -322px -24px;
}
.vs-dark .monaco-workbench .symbol-icon.null, .vs-dark .monaco-workbench .symbol-icon.boolean, .hc-black .monaco-workbench .symbol-icon.null, .hc-black .monaco-workbench .symbol-icon.boolean {
background-position: -342px -24px;
}
<svg xmlns="http://www.w3.org/2000/svg" width="360" height="40"><rect x="342" y="24" fill="#2D2D30" width="16" height="12"/><polygon fill="#C5C5C5" points="353,27 356,30 353,33 351,33 353,31 350,31 350,29 353,29 351,27"/><rect x="343" y="25" fill="#C5C5C5" width="14" height="10"/><polygon fill="#C5C5C5" points="356,26 350,26 350,29 349.999,29 347,29 349,27 347,27 344,30 347,33 349,33 347,31 349.999,31 350,31 350,34 356,34 356,30"/><polygon fill="#2B282E" points="350,31 347,31 349,33 347,33 344,30 347,27 349,27 347,29 350,29"/><polygon fill="#2B282E" points="351,33 353,31 350,31 350,34 356,34 356,30 353,33"/><polygon fill="#2B282E" points="356,26 356,30 353,27 351,27 353,29 350,29 350,26"/><rect x="349.999" y="29" fill="#2B282E" width=".001" height="2"/><path fill="#F6F6F6" d="M358 16h-16v-12h16v12z"/><path fill="#424242" d="M353 7l3 3-3 3h-2l2-2h-3v-2h3l-2-2h2zm4-2v10h-14v-10h14zm-1 1h-6v3h-3l2-2h-2l-3 3 3 3h2l-2-2h3v3h6v-8z"/><path fill="#F0EFF1" d="M350 11h-3l2 2h-2l-3-3 3-3h2l-2 2h3v2zm1 2l2-2h-3v3h6v-4l-3 3h-2zm5-7v4l-3-3h-2l2 2h-3v-3h6zm-6 3v2h-.001l.001-2z"/><polygon fill="#2D2D30" points="333,27 333,25 330,25 327,25 327,27 325,27 325,33 327,33 327,35 333,35 333,33 335,33 335,30 335,27"/><polygon fill="#F6F6F6" points="333,7 333,5 330,5 327,5 327,7 325,7 325,13 327,13 327,15 333,15 333,13 335,13 335,10 335,7"/><path fill="#424242" d="M334 9v-1h-2v-2h-1v2h-2v-2h-1v2h-2v1h2v2h-2v1h2v2h1v-2h2v2h1v-2h2v-1h-2v-2h2zm-3 2h-2v-2h2v2z"/><g fill="#C5C5C5"><polygon points="304,26 304,34.016 306,34.016 306,35.006 303,35.006 303,35 303,34.016 303,26 303,25 304,25 304,25 306,25 306,26"/><polygon points="312,26 312,34.016 310,34.016 310,35.006 313,35.006 313,35 313,34.016 313,26 313,25 312,25 312,25 310,25 310,26"/></g><path fill="#424242" d="M304 6v8.016h2v.99h-3v-10.006h3v1h-2zm8 0v8.016h-2v.99h3v-10.006h-3v1h2z"/><polygon fill="#2D2D30" points="292.414,24 287.586,24 286,25.586 286,28 283.586,28 282,29.586 282,33.414 283.586,35 288.414,35 290,33.414 290,31 292.414,31 294,29.414 294,25.586"/><polygon fill="#E8AB53" points="288,29 284,29 283,30 283,33 284,34 288,34 289,33 289,30"/><rect x="284" y="32" fill="#E8AB53" width="4" height="1"/><rect x="284" y="30" fill="#E8AB53" width="4" height="1"/><polygon fill="#E8AB53" points="292,25 288,25 287,26 287,28 292,28 292,29 289.414,29 290,29.586 290,30 292,30 293,29 293,26"/><rect x="288" y="26" fill="#E8AB53" width="4" height="1"/><polygon fill="#2B282E" points="292,28 292,29 289.414,29 288.414,28"/><rect x="288" y="26" fill="#2B282E" width="4" height="1"/><rect x="284" y="32" fill="#2B282E" width="4" height="1"/><rect x="284" y="30" fill="#2B282E" width="4" height="1"/><polygon fill="#F6F6F6" points="292.414,4 287.586,4 286,5.586 286,8 283.586,8 282,9.586 282,13.414 283.586,15 288.414,15 290,13.414 290,11 292.414,11 294,9.414 294,5.586"/><path fill="#C27D1A" d="M288 9h-4l-1 1v3l1 1h4l1-1v-3l-1-1zm0 4h-4v-1h4v1zm0-2h-4v-1h4v1z"/><path fill="#C27D1A" d="M292 5h-4l-1 1v2h5v1h-2.586l.586.586v.414h2l1-1v-3l-1-1zm0 2h-4v-1h4v1z"/><path fill="#F0EFF1" d="M292 8v1h-2.586l-1-1h3.586zm0-2h-4v1h4v-1zm-4 6h-4v1h4v-1zm0-2h-4v1h4v-1z"/><polygon fill="#2D2D30" points="265,35 265,24 271.414,24 275,27.586 275,35"/><polygon fill="#C5C5C5" points="271,25 266,25 266,34 274,34 274,28"/><polygon fill="#C5C5C5" points="273,29 273,33 267,33 267,26 270,26 271,26 271,28 273,28"/><polygon fill="#2B282E" points="273,29 273,33 267,33 267,26 270,26 271,26 271,28 273,28"/><path fill="#F6F6F6" d="M265 15v-11h6.414l3.586 3.586v7.414h-10z"/><path fill="#424242" d="M271 5h-5v9h8v-6l-3-3zm2 4v4h-6v-7h4v2h2v1z"/><polygon fill="#F0EFF1" points="273,9 273,13 267,13 267,6 270,6 271,6 271,8 273,8"/><polygon fill="#2D2D30" points="247,34 247,30 245,30 245,26 255,26 255,34"/><rect x="246" y="27" fill="#C5C5C5" width="8" height="2"/><rect x="248" y="30" fill="#C5C5C5" width="6" height="1"/><rect x="248" y="32" fill="#C5C5C5" width="6" height="1"/><polygon fill="#F6F6F6" points="247,14 247,10 245,10 245,6 255,6 255,14"/><path fill="#424242" d="M254 9h-8v-2h8v2zm0 1h-6v1h6v-1zm0 2h-6v1h6v-1z"/><path fill="#2D2D30" d="M230.701 35.992c-3.336 0-6.701-1.703-6.701-5.51 0-4.174 4.968-6.482 8.402-6.482 1.07 0 1.867.244 2.369.725.658.631.791 1.299.785 1.746-.013 1.176-.904 2.146-1.822 3.008 1.408.194 2.088 1.144 2.254 2.037.297 1.604-.805 3.371-2.508 4.021-.761.293-1.75.455-2.779.455z"/><path fill="#C5C5C5" d="M232.646 30.482s-1.91.459-.478-.916c1.217-1.166 3.345-2.746 1.91-4.119-1.435-1.375-9.079.455-9.079 5.035s5.734 5.037 8.124 4.121c2.391-.914 2.867-4.578-.477-4.121z"/><circle fill="#C5C5C5" cx="227.375" cy="31.343" r="1.042"/><circle fill="#C5C5C5" cx="228.416" cy="28.343" r="1.041"/><circle fill="#C5C5C5" cx="231.402" cy="27.135" r="1.041"/><circle fill="#2B282E" cx="231.402" cy="27.135" r="1.041"/><circle fill="#2B282E" cx="228.416" cy="28.343" r="1.041"/><circle fill="#2B282E" cx="227.375" cy="31.344" r="1.041"/><path fill="#F6F6F6" d="M230.701 15.992c-3.336 0-6.701-1.703-6.701-5.509 0-4.174 4.968-6.483 8.402-6.483 1.07 0 1.867.244 2.369.725.658.631.791 1.298.785 1.746-.013 1.174-.904 2.146-1.822 3.008 1.408.194 2.088 1.142 2.254 2.036.297 1.604-.805 3.371-2.508 4.022-.761.294-1.75.455-2.779.455z"/><path fill="#424242" d="M232.646 10.482s-1.91.458-.478-.916c1.217-1.167 3.345-2.747 1.91-4.12-1.433-1.375-9.078.456-9.078 5.036 0 4.581 5.734 5.038 8.124 4.122 2.39-.915 2.866-4.578-.478-4.122zm-5.271 1.902c-.574 0-1.041-.467-1.041-1.041 0-.575.467-1.042 1.041-1.042s1.041.466 1.041 1.042c0 .574-.467 1.041-1.041 1.041zm1.041-3c-.574 0-1.041-.466-1.041-1.041s.467-1.041 1.041-1.041 1.041.466 1.041 1.041-.467 1.041-1.041 1.041zm1.945-2.25c0-.575.467-1.041 1.041-1.041s1.041.466 1.041 1.041-.467 1.041-1.041 1.041-1.041-.466-1.041-1.041z"/><g fill="#F0EFF1"><circle cx="231.402" cy="7.134" r="1.041"/><circle cx="228.416" cy="8.343" r="1.041"/><circle cx="227.375" cy="11.343" r="1.041"/></g><rect x="202" y="23" fill="#2D2D30" width="16" height="14"/><rect x="203" y="24" fill="#C5C5C5" width="14" height="12"/><rect x="210" y="29" fill="#C5C5C5" width="1" height="2"/><rect x="204" y="25" fill="#2B282E" width="12" height="10"/><polygon fill="#C5C5C5" points="210,28 210,27 209,27 209,32 212,32 212,28"/><rect x="210" y="29" fill="#2B282E" width="1" height="2"/><polygon fill="#C5C5C5" points="214,29 214,31 215,31 215,32 213,32 213,28 215,28 215,29"/><polygon fill="#C5C5C5" points="208,28 208,32 205,32 205,30 206,30 206,31 207,31 207,30 206,30 206,29 205,29 205,28"/><rect x="202" y="3" fill="#F6F6F6" width="16" height="14"/><path fill="#424242" d="M203 4v12h14v-12h-14zm13 11h-12v-10h12v10zm-6-7v-1h-1v5h3v-4h-2zm1 3h-1v-2h1v2zm3-2v2h1v1h-2v-4h2v1h-1zm-6-1v4h-3v-2h1v1h1v-1h-1v-1h-1v-1h3z"/><path fill="#F0EFF1" d="M210 9h1v2h-1v-2zm-3 2v-1h-1v1h1zm9-6v10h-12v-10h12zm-8 3h-3v1h1v1h-1v2h3v-4zm4 0h-2v-1h-1v5h3v-4zm3 0h-2v4h2v-1h-1v-2h1v-1z"/><rect x="185" y="24" fill="#2D2D30" width="11" height="12"/><polygon fill="#C5C5C5" points="194,33 194,26 187,26 187,33 186,33 186,25 195,25 195,33"/><rect x="186" y="34" fill="#C5C5C5" width="1" height="1"/><rect x="188" y="34" fill="#C5C5C5" width="1" height="1"/><rect x="190" y="34" fill="#C5C5C5" width="1" height="1"/><rect x="192" y="34" fill="#C5C5C5" width="1" height="1"/><rect x="194" y="34" fill="#C5C5C5" width="1" height="1"/><rect x="187" y="26" fill="#2B282E" width="7" height="7"/><rect x="185" y="4" fill="#F6F6F6" width="11" height="12"/><path fill="#424242" d="M194 13v-7h-7v7h-1v-8h9v8h-1zm-7 2h-1v-1h1v1zm2-1h-1v1h1v-1zm2 0h-1v1h1v-1zm2 1h-1v-1h1v1zm2-1h-1v1h1v-1z"/><path fill="#F0EFF1" d="M187 13v-7h7v7h-7z"/><polygon fill="#2D2D30" points="164,35 164,24 171,24 171,25 176,25 176,28 171,28 171,29 176,29 176,35"/><rect x="171" y="26" fill="#C5C5C5" width="4" height="1"/><rect x="173" y="30" fill="#C5C5C5" width="2" height="1"/><rect x="165" y="30" fill="#C5C5C5" width="6" height="1"/><rect x="165" y="33" fill="#C5C5C5" width="4" height="1"/><rect x="171" y="33" fill="#C5C5C5" width="4" height="1"/><rect x="165" y="25" fill="#C5C5C5" width="5" height="3"/><rect x="166" y="26" fill="#C5C5C5" width="3" height="1"/><rect x="166" y="26" fill="#2B282E" width="3" height="1"/><polygon fill="#F6F6F6" points="164,15 164,4 171,4 171,5 176,5 176,8 171,8 171,9 176,9 176,15"/><path fill="#424242" d="M175 7h-4v-1h4v1zm0 3h-2v1h2v-1zm-4 0h-6v1h6v-1zm-2 3h-4v1h4v-1zm6 0h-4v1h4v-1zm-5-8v3h-5v-3h5zm-1 1h-3v1h3v-1z"/><rect x="166" y="6" fill="#F0EFF1" width="3" height="1"/><polygon fill="#2D2D30" points="154.414,24 149.586,24 148,25.586 148,28 144,28 144,35 152,35 152,31 154.414,31 156,29.414 156,25.586"/><polygon fill="#75BEFF" points="154,25 150,25 149,26 149,28 154,28 154,29 152,29 152,30 154,30 155,29 155,26"/><rect x="150" y="26" fill="#00539C" width="4" height="1"/><rect x="145" y="29" fill="#75BEFF" width="6" height="5"/><rect x="146" y="31" fill="#00539C" width="4" height="1"/><rect x="146" y="31" fill="#2B282E" width="4" height="1"/><rect x="150" y="26" fill="#2B282E" width="4" height="1"/><rect x="152" y="28" fill="#2B282E" width="2" height="1"/><polygon fill="#F6F6F6" points="154.414,4 149.586,4 148,5.586 148,8 144,8 144,15 152,15 152,11 154.414,11 156,9.414 156,5.586"/><path fill="#00539C" d="M154 5h-4l-1 1v2h5v1h-2v1h2l1-1v-3l-1-1zm0 2h-4v-1h4v1zm-9 7h6v-5h-6v5zm1-3h4v1h-4v-1z"/><g fill="#F0EFF1"><rect x="146" y="11" width="4" height="1"/><rect x="150" y="6" width="4" height="1"/><rect x="152" y="8" width="2" height="1"/></g><rect x="125" y="27" fill="#2D2D30" width="11" height="6"/><rect x="126" y="28" fill="#C5C5C5" width="9" height="4"/><rect x="127" y="30" fill="#2B282E" width="1" height="1"/><rect x="129" y="30" fill="#2B282E" width="1" height="1"/><rect x="131" y="30" fill="#2B282E" width="1" height="1"/><rect x="133" y="30" fill="#2B282E" width="1" height="1"/><rect x="127" y="29" fill="#2B282E" width="3" height="1"/><rect x="131" y="29" fill="#2B282E" width="3" height="1"/><rect x="125" y="7" fill="#F6F6F6" width="11" height="6"/><rect x="126" y="8" fill="#424242" width="9" height="4"/><rect x="127" y="10" fill="#F0EFF1" width="1" height="1"/><rect x="129" y="10" fill="#F0EFF1" width="1" height="1"/><rect x="131" y="10" fill="#F0EFF1" width="1" height="1"/><rect x="133" y="10" fill="#F0EFF1" width="1" height="1"/><rect x="127" y="9" fill="#F0EFF1" width="3" height="1"/><rect x="131" y="9" fill="#F0EFF1" width="3" height="1"/><path fill="#2D2D30" d="M110.449 23c-1.637 0-3.075.797-3.987 2.012l.001.002c-.628.836-1.014 1.863-1.014 2.986 0 .469.067.934.2 1.385l-2.907 2.908c-.687.686-1.253 2.161 0 3.414.609.609 1.244.736 1.67.736.958 0 1.621-.613 1.744-.736l2.907-2.908c.453.133.917.201 1.386.201 1.123 0 2.149-.387 2.985-1.014h.002c1.216-.911 2.013-2.352 2.013-3.986 0-2.762-2.238-5-5-5z"/><path fill="#C5C5C5" d="M114.09 26.359l-2.641 2.641-2-2 2.641-2.641c-.502-.228-1.055-.359-1.641-.359-2.209 0-4 1.791-4 4 0 .586.133 1.139.359 1.641l-3.359 3.359s-1 1 0 2h2l3.359-3.359c.502.227 1.055.359 1.641.359 2.209 0 4-1.791 4-4 0-.586-.133-1.139-.359-1.641z"/><path fill="#F6F6F6" d="M110.449 3c-1.637 0-3.075.797-3.987 2.012l.001.002c-.628.836-1.014 1.863-1.014 2.986 0 .469.067.933.2 1.385l-2.907 2.908c-.687.686-1.253 2.161 0 3.414.609.609 1.244.736 1.67.736.958 0 1.621-.613 1.744-.736l2.907-2.908c.453.133.917.201 1.386.201 1.123 0 2.149-.387 2.985-1.014l.002.001c1.216-.912 2.013-2.352 2.013-3.987 0-2.762-2.238-5-5-5z"/><path fill="#424242" d="M114.09 6.359l-2.641 2.641-2-2 2.641-2.641c-.502-.226-1.055-.359-1.641-.359-2.209 0-4 1.791-4 4 0 .586.133 1.139.359 1.64l-3.359 3.36s-1 1 0 2h2l3.359-3.36c.502.227 1.055.36 1.641.36 2.209 0 4-1.791 4-4 0-.586-.133-1.139-.359-1.641z"/><path fill="#2D2D30" d="M89 33h1v-1c0-.537.741-1.613 1-2-.259-.389-1-1.467-1-2v-1h-1v-3h1c1.969.021 3 1.277 3 3v1l1 1v2l-1 1v1c0 1.709-1.031 2.979-3 3h-1v-3z"/><path fill="#2D2D30" d="M87 33h-1v-1c0-.537-.741-1.613-1-2 .259-.389 1-1.467 1-2v-1h1v-3h-1c-1.969.021-3 1.277-3 3v1l-1 1v2l1 1v1c0 1.709 1.317 2.979 3.286 3h.714v-3z"/><path fill="#C5C5C5" d="M91 33v-1c0-.834.496-1.738 1-2-.504-.27-1-1.168-1-2v-1c0-.84-.584-1-1-1v-1c2.083 0 2 1.166 2 2v1c0 .969.703.98 1 1v2c-.322.02-1 .053-1 1v1c0 .834.083 2-2 2v-1c.833 0 1-1 1-1z"/><path fill="#C5C5C5" d="M85 33v-1c0-.834-.496-1.738-1-2 .504-.27 1-1.168 1-2v-1c0-.84.584-1 1-1v-1c-2.083 0-2 1.166-2 2v1c0 .969-.703.98-1 1v2c.322.02 1 .053 1 1v1c0 .834-.083 2 2 2v-1c-.833 0-1-1-1-1z"/><path fill="#F6F6F6" d="M89 13h1v-1c0-.537.741-1.613 1-2-.259-.389-1-1.467-1-2v-1h-1v-3h1c1.969.021 3 1.277 3 3v1l1 1v2l-1 1v1c0 1.709-1.031 2.979-3 3h-1v-3zm-2 0h-1v-1c0-.537-.741-1.613-1-2 .259-.389 1-1.467 1-2v-1h1v-3h-1c-1.969.021-3 1.277-3 3v1l-1 1v2l1 1v1c0 1.709 1.317 2.979 3.286 3h.714v-3z"/><path fill="#424242" d="M91 13v-1c0-.834.496-1.738 1-2-.504-.27-1-1.168-1-2v-1c0-.84-.584-1-1-1v-1c2.083 0 2 1.166 2 2v1c0 .969.703.98 1 1v2c-.322.02-1 .053-1 1v1c0 .834.083 2-2 2v-1c.833 0 1-1 1-1zm-6 0v-1c0-.834-.496-1.738-1-2 .504-.27 1-1.168 1-2v-1c0-.84.584-1 1-1v-1c-2.083 0-2 1.166-2 2v1c0 .969-.703.98-1 1v2c.322.02 1 .053 1 1v1c0 .834-.083 2 2 2v-1c-.833 0-1-1-1-1z"/><path fill="#2D2D30" d="M73.5 34c-1.914 0-3.601-1.242-4.227-3h-1.683c-.524.91-1.503 1.5-2.591 1.5-1.654 0-3-1.346-3-3s1.346-3 3-3c1.088 0 2.066.588 2.591 1.5h1.683c.626-1.76 2.313-3 4.227-3 2.481 0 4.5 2.018 4.5 4.5 0 2.48-2.019 4.5-4.5 4.5z"/><path fill="#75BEFF" d="M73.5 26c-1.759 0-3.204 1.309-3.449 3h-3.122c-.223-.861-.998-1.5-1.929-1.5-1.104 0-2 .895-2 2 0 1.104.896 2 2 2 .931 0 1.706-.639 1.929-1.5h3.122c.245 1.691 1.69 3 3.449 3 1.93 0 3.5-1.57 3.5-3.5 0-1.932-1.57-3.5-3.5-3.5z"/><circle fill="#75BEFF" cx="73.5" cy="29.5" r="1.5"/><circle fill="#2B282E" cx="73.5" cy="29.5" r="1.5"/><path fill="#F6F6F6" d="M73.5 14c-1.914 0-3.601-1.242-4.227-3h-1.683c-.524.91-1.503 1.5-2.591 1.5-1.654 0-3-1.346-3-3s1.346-3 3-3c1.088 0 2.066.588 2.591 1.5h1.683c.626-1.76 2.313-3 4.227-3 2.481 0 4.5 2.018 4.5 4.5 0 2.48-2.019 4.5-4.5 4.5z"/><path fill="#00539C" d="M73.5 6c-1.759 0-3.204 1.308-3.449 3h-3.122c-.223-.861-.998-1.5-1.929-1.5-1.104 0-2 .895-2 2 0 1.104.896 2 2 2 .931 0 1.706-.639 1.929-1.5h3.122c.245 1.691 1.69 3 3.449 3 1.93 0 3.5-1.57 3.5-3.5 0-1.931-1.57-3.5-3.5-3.5zm0 5c-.827 0-1.5-.674-1.5-1.5 0-.828.673-1.5 1.5-1.5s1.5.672 1.5 1.5c0 .826-.673 1.5-1.5 1.5z"/><circle fill="#F0EFF1" cx="73.5" cy="9.5" r="1.5"/><polygon fill="#2D2D30" points="58,28.586 55,25.586 53.586,27 51.414,27 52.414,26 48.414,22 47.586,22 42,27.586 42,28.414 46,32.414 48.414,30 49,30 49,35 50.586,35 53.586,38 54.414,38 58,34.414 58,33.586 55.914,31.5 58,29.414"/><polygon fill="#E8AB53" points="53.998,33.002 51,33 51,29 53,29 52,30 54,32 57,29 55,27 54,28 49,28 51,26 48,23 43,28 46,31 48,29 50,29 50,34 53,34 52,35 54,37 57,34 55,32"/><path fill="#F6F6F6" d="M58 8.586l-3-3-1.414 1.414h-2.172l1-1-4-4h-.828l-5.586 5.586v.828l4 4 2.414-2.414h.586v5h1.586l3 3h.828l3.586-3.586v-.828l-2.086-2.086 2.086-2.086v-.828z"/><polygon fill="#C27D1A" points="53.998,13.002 51,13 51,9 53,9 52,10 54,12 57,9 55,7 54,8 49,8 51,6 48,3 43,8 46,11 48,9 50,9 50,14 53,14 52,15 54,17 57,14 55,12"/><polygon fill="#2D2D30" points="29.263,24 34,26.369 34,31.605 27.209,35 26.789,35 22,32.605 22,27.369 28.739,24"/><polygon fill="#75BEFF" points="23,28 23,32 27,34 33,31 33,27 29,25"/><polygon fill="#75BEFF" points="27,29 25,28 29,26 31,27"/><polygon fill="#2B282E" points="29,26 31,27 27,29 25,28"/><path fill="#F6F6F6" d="M29.263 4l4.737 2.369v5.236l-6.791 3.395h-.42l-4.789-2.395v-5.236l6.739-3.369h.524z"/><path fill="#00539C" d="M23 8v4l4 2 6-3v-4l-4-2-6 3zm4 1l-2-1 4-2 2 1-4 2z"/><path fill="#F0EFF1" d="M29 6l2 1-4 2-2-1 4-2z"/><polygon fill="#2D2D30" points="2,27.309 2,32.691 7.209,36 7.791,36 13,32.691 13,27.309 7.791,24 7.209,24"/><polygon fill="#B180D7" points="7.5,25 3,27.857 3,32.143 7.5,35 12,32.143 12,27.857"/><polygon fill="#B180D7" points="7,33.498 4,31.593 4,28.777 7,30.684"/><polygon fill="#B180D7" points="4.642,28 7.5,26.186 10.358,28 7.5,29.814"/><polygon fill="#B180D7" points="11,31.593 8,33.498 8,30.684 11,28.777"/><polygon fill="#2B282E" points="10.358,28 7.5,29.814 4.642,28 7.5,26.186"/><polygon fill="#2B282E" points="4,28.777 7,30.684 7,33.498 4,31.593"/><polygon fill="#2B282E" points="8,33.498 8,30.684 11,28.777 11,31.593"/><polygon fill="#F6F6F6" points="2,7.308 2,12.692 7.209,16 7.791,16 13,12.692 13,7.308 7.791,4 7.209,4"/><path fill="#652D90" d="M7.5 5l-4.5 2.857v4.285l4.5 2.858 4.5-2.857v-4.286l-4.5-2.857zm-.5 8.498l-3-1.905v-2.816l3 1.905v2.816zm-2.358-5.498l2.858-1.815 2.858 1.815-2.858 1.815-2.858-1.815zm6.358 3.593l-3 1.905v-2.815l3-1.905v2.815z"/><polygon fill="#F0EFF1" points="10.358,8 7.5,9.815 4.642,8 7.5,6.185"/><polygon fill="#F0EFF1" points="4,8.777 7,10.683 7,13.498 4,11.593"/><polygon fill="#F0EFF1" points="8,13.498 8,10.683 11,8.777 11,11.593"/><path fill="#C5C5C5" d="M334 29v-1h-2v-2h-1v2h-2v-2h-1v2h-2v1h2v2h-2v1h2v2h1v-2h2v2h1v-2h2v-1h-2v-2h2zm-3 2h-2v-2h2v2z"/></svg>
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { localize } from 'vs/nls';
import { IViewsService, ViewLocation, ViewsRegistry, IViewDescriptor } from 'vs/workbench/common/views';
import { OutlinePanel } from './outlinePanel';
const _outlineDesc = <IViewDescriptor>{
id: 'code.outline',
name: localize('name', "Outline"),
ctor: OutlinePanel,
location: ViewLocation.Explorer,
canToggleVisibility: true,
hideByDefault: true
};
ViewsRegistry.registerViews([_outlineDesc]);
CommandsRegistry.registerCommand('outline.focus', accessor => {
let viewsService = accessor.get(IViewsService);
return viewsService.openView(_outlineDesc.id, true);
});
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { DocumentSymbolProviderRegistry, SymbolInformation, DocumentSymbolProvider } from 'vs/editor/common/modes';
import { ITextModel } from 'vs/editor/common/model';
import { asWinJsPromise } from 'vs/base/common/async';
import { TPromise } from 'vs/base/common/winjs.base';
import { fuzzyScore } from 'vs/base/common/filters';
import { IPosition } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { size, first } from 'vs/base/common/collections';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
export type FuzzyScore = [number, number[]];
export abstract class TreeElement {
abstract id: string;
abstract children: { [id: string]: TreeElement };
abstract parent: TreeElement | any;
static findId(candidate: string, container: TreeElement): string {
// complex id-computation which contains the origin/extension,
// the parent path, and some dedupe logic when names collide
let id = container.id + candidate;
for (let i = 1; container.children[id] !== void 0; i++) {
id = container.id + candidate + i;
}
return id;
}
static getElementById(id: string, element: TreeElement): TreeElement {
if (element.id === id) {
return element;
}
for (const key in element.children) {
let candidate = TreeElement.getElementById(id, element.children[key]);
if (candidate) {
return candidate;
}
}
return undefined;
}
}
export class OutlineElement extends TreeElement {
children: { [id: string]: OutlineElement; } = Object.create(null);
score: FuzzyScore = [0, []];
constructor(
readonly id: string,
public parent: OutlineModel | OutlineGroup | OutlineElement,
readonly symbol: SymbolInformation
) {
super();
}
}
export class OutlineGroup extends TreeElement {
children: { [id: string]: OutlineElement; } = Object.create(null);
constructor(
readonly id: string,
public parent: OutlineModel,
readonly provider: DocumentSymbolProvider,
readonly providerIndex: number,
) {
super();
}
updateMatches(pattern: string, topMatch: OutlineElement): OutlineElement {
for (const key in this.children) {
topMatch = this._updateMatches(pattern, this.children[key], topMatch);
}
return topMatch;
}
private _updateMatches(pattern: string, item: OutlineElement, topMatch: OutlineElement): OutlineElement {
item.score = fuzzyScore(pattern, item.symbol.name);
if (item.score && (!topMatch || item.score[0] > topMatch.score[0])) {
topMatch = item;
}
for (const key in item.children) {
let child = item.children[key];
topMatch = this._updateMatches(pattern, child, topMatch);
if (!item.score && child.score) {
// don't filter parents with unfiltered children
item.score = [0, []];
}
}
return topMatch;
}
getItemEnclosingPosition(position: IPosition): OutlineElement {
return this._getItemEnclosingPosition(position, this.children);
}
private _getItemEnclosingPosition(position: IPosition, children: { [id: string]: OutlineElement }): OutlineElement {
for (let key in children) {
let item = children[key];
if (!Range.containsPosition(item.symbol.definingRange || item.symbol.location.range, position)) {
continue;
}
return this._getItemEnclosingPosition(position, item.children) || item;
}
return undefined;
}
}
export class OutlineModel extends TreeElement {
readonly id = 'root';
readonly parent = undefined;
private _groups: { [id: string]: OutlineGroup; } = Object.create(null);
children: { [id: string]: OutlineGroup | OutlineElement; } = Object.create(null);
request: TPromise<any>;
constructor(readonly textModel: ITextModel) {
super();
this._makeRequest();
}
dispose(): void {
this.request.cancel();
}
refresh(): void {
this.request.cancel();
this._groups = Object.create(null);
this.children = Object.create(null);
this._makeRequest();
}
private _makeRequest(): void {
let promises = DocumentSymbolProviderRegistry.ordered(this.textModel).map((provider, index) => {
let id = TreeElement.findId(`provider_${index}`, this);
let group = new OutlineGroup(id, this, provider, index);
return asWinJsPromise(token => provider.provideDocumentSymbols(this.textModel, token)).then(result => {
if (!isFalsyOrEmpty(result)) {
for (const info of result) {
OutlineModel._makeOutlineElement(info, group);
}
}
return group;
}, err => {
//todo@joh capture error in group
return group;
}).then(group => {
this._groups[id] = group;
});
});
this.request = TPromise.join(promises).then(() => {
if (size(this._groups) !== 1) {
this.children = this._groups;
return;
}
// adopt all elements of the first group
let group = first(this._groups);
for (let key in group.children) {
let child = group.children[key];
child.parent = this;
this.children[child.id] = child;
}
});
}
private static _makeOutlineElement(info: SymbolInformation, container: OutlineGroup | OutlineElement): void {
let id = TreeElement.findId(info.name, container);
let res = new OutlineElement(id, container, info);
if (info.children) {
for (const childInfo of info.children) {
OutlineModel._makeOutlineElement(childInfo, res);
}
}
container.children[res.id] = res;
}
updateMatches(pattern: string): OutlineElement {
let topMatch: OutlineElement;
for (const key in this._groups) {
topMatch = this._groups[key].updateMatches(pattern, topMatch);
}
return topMatch;
}
getItemEnclosingPosition(position: IPosition): OutlineElement {
for (const key in this._groups) {
let result = this._groups[key].getItemEnclosingPosition(position);
if (result) {
return result;
}
}
return undefined;
}
getItemById(id: string): TreeElement {
return TreeElement.getElementById(id, this);
}
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench .outline-panel {
display: flex;
flex-direction: column;
}
.monaco-workbench .outline-panel .outline-input {
box-sizing: border-box;
padding: 5px 9px 9px 9px;
}
.monaco-workbench .outline-panel .outline-input .monaco-inputbox {
width: 100%;
}
.monaco-workbench .outline-panel .outline-tree {
width: 100%;
height: 100%;
}
.monaco-workbench .outline-panel .outline-message {
display: none;
padding: 10px 22px 0 22px;
opacity: 0.5;
}
.monaco-workbench .outline-panel.message .outline-message {
display: inherit;
}
.monaco-workbench .outline-panel.message .outline-input {
display: none;
}
.monaco-workbench .outline-panel.message .outline-tree {
display: none;
}
.monaco-workbench .outline-panel .outline-element {
display: flex;
flex-flow: row nowrap;
align-items: center;
}
.monaco-workbench .outline-panel .outline-element .outline-element-icon {
padding-right: 3px;
}
.monaco-workbench .outline-panel .outline-element .outline-element-label {
text-overflow: ellipsis;
overflow: hidden;
}
.monaco-workbench .outline-panel .outline-element .outline-element-label .monaco-highlighted-label .highlight {
font-weight: bold;
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as dom from 'vs/base/browser/dom';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { Action, IAction, RadioGroup } from 'vs/base/common/actions';
import { Emitter } from 'vs/base/common/event';
import { defaultGenerator } from 'vs/base/common/idGenerator';
import { KeyCode } from 'vs/base/common/keyCodes';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { LRUCache } from 'vs/base/common/map';
import { escape } from 'vs/base/common/strings';
import { TPromise } from 'vs/base/common/winjs.base';
import { ITree } from 'vs/base/parts/tree/browser/tree';
import 'vs/css!./outlinePanel';
import { ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser';
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { DocumentSymbolProviderRegistry } from 'vs/editor/common/modes';
import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry';
import { localize } from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { WorkbenchTree } from 'vs/platform/list/browser/listService';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IViewOptions, ViewsViewletPanel } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { CollapseAction } from 'vs/workbench/browser/viewlet';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { OutlineElement, OutlineModel } from './outlineModel';
import { OutlineController, OutlineDataSource, OutlineItemComparator, OutlineItemCompareType, OutlineItemFilter, OutlineRenderer, OutlineTreeState } from './outlineTree';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
class RequestState {
constructor(
private _editorId: string,
private _modelId: string,
private _modelVersion: number,
private _providerCount: number
) {
//
}
equals(other: RequestState): boolean {
return other
&& this._editorId === other._editorId
&& this._modelId === other._modelId
&& this._modelVersion === other._modelVersion
&& this._providerCount === other._providerCount;
}
}
class RequestOracle {
private _disposables = new Array<IDisposable>();
private _sessionDisposable: IDisposable;
private _lastState: RequestState;
constructor(
private readonly _callback: (editor: ICodeEditor) => any,
private readonly _featureRegistry: LanguageFeatureRegistry<any>,
@IEditorGroupService editorGroupService: IEditorGroupService,
@IWorkbenchEditorService private readonly _workbenchEditorService: IWorkbenchEditorService,
) {
editorGroupService.onEditorsChanged(this._update, this, this._disposables);
_featureRegistry.onDidChange(this._update, this, this._disposables);
this._update();
}
dispose(): void {
dispose(this._disposables);
dispose(this._sessionDisposable);
}
private _update(): void {
dispose(this._sessionDisposable);
let editor = this._workbenchEditorService.getActiveEditor();
let control = editor && editor.getControl();
let codeEditor: ICodeEditor = undefined;
if (isCodeEditor(control)) {
codeEditor = control;
} else if (isDiffEditor(control)) {
codeEditor = control.getModifiedEditor();
}
if (!codeEditor || !codeEditor.getModel()) {
this._callback(undefined);
return;
}
let thisState = new RequestState(
codeEditor.getId(),
codeEditor.getModel().id,
codeEditor.getModel().getVersionId(),
this._featureRegistry.all(codeEditor.getModel()).length
);
if (thisState.equals(this._lastState)) {
// prevent unneccesary changes...
return;
}
this._lastState = thisState;
this._callback(codeEditor);
let handle: number;
let listener = codeEditor.onDidChangeModelContent(_ => {
handle = setTimeout(() => this._callback(codeEditor), 50);
});
this._sessionDisposable = {
dispose() {
listener.dispose();
clearTimeout(handle);
}
};
}
}
class SimpleToggleAction extends Action {
constructor(label: string, checked: boolean, callback: (action: SimpleToggleAction) => any) {
super(`simple` + defaultGenerator.nextId(), label, undefined, true, _ => {
this.checked = !this.checked;
callback(this);
return undefined;
});
this.checked = checked;
}
}
class OutlineState {
private _followCursor = false;
private _sortBy = OutlineItemCompareType.ByKind;
private _onDidChange = new Emitter<{ followCursor?: boolean, sortBy?: boolean }>();
readonly onDidChange = this._onDidChange.event;
set followCursor(value: boolean) {
if (value !== this._followCursor) {
this._followCursor = value;
this._onDidChange.fire({ followCursor: true });
}
}
get followCursor(): boolean {
return this._followCursor;
}
set sortBy(value: OutlineItemCompareType) {
if (value !== this._sortBy) {
this._sortBy = value;
this._onDidChange.fire({ sortBy: true });
}
}
get sortBy(): OutlineItemCompareType {
return this._sortBy;
}
persist(storageService: IStorageService): void {
storageService.store('outline/state', JSON.stringify({ followCursor: this.followCursor, sortBy: this.sortBy }), StorageScope.WORKSPACE);
}
restore(storageService: IStorageService): void {
let raw = storageService.get('outline/state', StorageScope.WORKSPACE);
if (!raw) {
return;
}
let data: any;
try {
data = JSON.parse(raw);
} catch (e) {
return;
}
this.followCursor = data.followCursor;
this.sortBy = data.sortBy;
}
}
export class OutlinePanel extends ViewsViewletPanel {
private _disposables = new Array<IDisposable>();
private _editorDisposables = new Array<IDisposable>();
private _outlineViewState = new OutlineState();
private _requestOracle: RequestOracle;
private _domNode: HTMLElement;
private _message: HTMLDivElement;
private _inputContainer: HTMLDivElement;
private _input: InputBox;
private _tree: WorkbenchTree;
private _treeFilter: OutlineItemFilter;
private _treeComparator: OutlineItemComparator;
private _treeStates = new LRUCache<string, OutlineTreeState>(10);
constructor(
options: IViewOptions,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IThemeService private readonly _themeService: IThemeService,
@IStorageService private readonly _storageService: IStorageService,
@IWorkbenchEditorService private readonly _editorService: IWorkbenchEditorService,
@IConfigurationService configurationService: IConfigurationService,
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
) {
super(options, keybindingService, contextMenuService, configurationService);
this._outlineViewState.restore(this._storageService);
}
dispose(): void {
dispose(this._disposables);
dispose(this._requestOracle);
super.dispose();
}
focus(): void {
if (this._tree) {
this._tree.domFocus();
}
}
protected renderBody(container: HTMLElement): void {
this._domNode = container;
dom.addClass(container, 'outline-panel');
this._message = dom.$('.outline-message');
this._inputContainer = dom.$('.outline-input');
let treeContainer = dom.$('.outline-tree');
dom.append(container, this._message, this._inputContainer, treeContainer);
this._input = new InputBox(this._inputContainer, null, { placeholder: localize('filter', "Filter") });
this._input.disable();
this.disposables.push(attachInputBoxStyler(this._input, this._themeService));
this.disposables.push(dom.addStandardDisposableListener(this._input.inputElement, 'keyup', event => {
// todo@joh make those keybindings configurable?
if (event.keyCode === KeyCode.DownArrow) {
this._tree.focusNext();
this._tree.domFocus();
} else if (event.keyCode === KeyCode.UpArrow) {
this._tree.focusPrevious();
this._tree.domFocus();
} else if (event.keyCode === KeyCode.Enter) {
let element = this._tree.getFocus();
this._revealTreeSelection(element, true, false);
} else if (event.keyCode === KeyCode.Escape) {
this._input.value = '';
this._tree.domFocus();
}
}));
const $this = this;
const controller = new class extends OutlineController {
private readonly _mapper = KeyboardMapperFactory.INSTANCE;
constructor() {
super({}, $this.configurationService);
}
onKeyDown(tree: ITree, event: IKeyboardEvent) {
let handled = super.onKeyDown(tree, event);
if (handled) {
return true;
}
if (this.upKeyBindingDispatcher.has(event.keyCode)) {
return false;
}
// crazy -> during keydown focus moves to the input box
// and because of that the keyup event is handled by the
// input field
const mapping = this._mapper.getRawKeyboardMapping();
if (!mapping) {
return false;
}
const keyInfo = mapping[event.code];
if (keyInfo.value) {
$this._input.focus();
return true;
}
return false;
}
};
const dataSource = new OutlineDataSource();
const renderer = this._instantiationService.createInstance(OutlineRenderer);
this._treeComparator = new OutlineItemComparator(this._outlineViewState.sortBy);
this._treeFilter = new OutlineItemFilter();
this._tree = this._instantiationService.createInstance(WorkbenchTree, treeContainer, { controller, dataSource, renderer, sorter: this._treeComparator, filter: this._treeFilter }, {});
this._disposables.push(this._tree, this._input);
this._disposables.push(this._outlineViewState.onDidChange(this._onDidChangeUserState, this));
}
protected layoutBody(height: number): void {
this._tree.layout(height - dom.getTotalHeight(this._inputContainer));
}
setVisible(visible: boolean): TPromise<void> {
if (visible) {
this._requestOracle = this._requestOracle || this._instantiationService.createInstance(RequestOracle, editor => this._onEditor(editor), DocumentSymbolProviderRegistry);
} else {
dispose(this._requestOracle);
this._requestOracle = undefined;
this._onEditor(undefined);
}
return super.setVisible(visible);
}
getActions(): IAction[] {
return [
new Action('collapse', localize('collapse', "Collapse All"), 'explorer-action collapse-explorer', true, () => {
return new CollapseAction(this._tree, true, undefined).run();
})
];
}
getSecondaryActions(): IAction[] {
let group = new RadioGroup([
new SimpleToggleAction(localize('sortByPosition', "Sort By: Position"), this._outlineViewState.sortBy === OutlineItemCompareType.ByPosition, _ => this._outlineViewState.sortBy = OutlineItemCompareType.ByPosition),
new SimpleToggleAction(localize('sortByName', "Sort By: Name"), this._outlineViewState.sortBy === OutlineItemCompareType.ByName, _ => this._outlineViewState.sortBy = OutlineItemCompareType.ByName),
new SimpleToggleAction(localize('sortByKind', "Sort By: Type"), this._outlineViewState.sortBy === OutlineItemCompareType.ByKind, _ => this._outlineViewState.sortBy = OutlineItemCompareType.ByKind),
]);
let result = [
new SimpleToggleAction(localize('live', "Follow Cursor"), this._outlineViewState.followCursor, action => this._outlineViewState.followCursor = action.checked),
new Separator(),
...group.actions,
];
this.disposables.push(...result);
this.disposables.push(group);
return result;
}
private _onDidChangeUserState(e: { followCursor?: boolean, sortBy?: boolean }) {
this._outlineViewState.persist(this._storageService);
if (e.followCursor) {
// todo@joh update immediately
}
if (e.sortBy) {
this._treeComparator.type = this._outlineViewState.sortBy;
this._tree.refresh(undefined, true);
}
}
private _showMessage(message: string) {
dom.addClass(this._domNode, 'message');
this._message.innerText = escape(message);
}
private async _onEditor(editor: ICodeEditor): TPromise<void> {
dispose(this._editorDisposables);
this._editorDisposables = new Array();
this._input.disable();
this._input.value = '';
if (!editor || !DocumentSymbolProviderRegistry.has(editor.getModel())) {
return this._showMessage(localize('no-editor', "There are no editors open that can provide outline information."));
}
dom.removeClass(this._domNode, 'message');
let model: OutlineModel;
let textModel = editor.getModel();
let oldModel = <OutlineModel>this._tree.getInput();
if (oldModel && oldModel.textModel.uri.toString() === textModel.uri.toString()) {
oldModel.refresh();
this._tree.refresh(undefined, true);
model = oldModel;
} else {
// persist state
if (oldModel) {
let state = OutlineTreeState.capture(this._tree);
this._treeStates.set(oldModel.textModel.uri.toString(), state);
}
model = new OutlineModel(textModel);
await this._tree.setInput(model);
let state = this._treeStates.get(model.textModel.uri.toString());
OutlineTreeState.restore(this._tree, state);
}
// wait for the actual model to work with...
await model.request;
this._input.enable();
// feature: filter on type
// on type -> update filters
// on first type -> capture tree state
// on erase -> restore captured tree state
let beforePatternState: OutlineTreeState;
this._editorDisposables.push(this._input.onDidChange(async pattern => {
if (!beforePatternState) {
beforePatternState = OutlineTreeState.capture(this._tree);
}
let item = model.updateMatches(pattern);
await this._tree.refresh(undefined, true);
if (item) {
await this._tree.expandAll(undefined /*all*/);
await this._tree.reveal(item);
this._tree.setFocus(item, this);
this._tree.setSelection([item], this);
}
if (!pattern && beforePatternState) {
await OutlineTreeState.restore(this._tree, beforePatternState);
beforePatternState = undefined;
}
}));
// feature: reveal outline selection in editor
// on change -> reveal/select defining range
this._editorDisposables.push(this._tree.onDidChangeSelection(e => {
if (e.payload === this) {
return;
}
let [first] = e.selection;
if (!(first instanceof OutlineElement)) {
return;
}
let focus = false;
let aside = false;
if (e.payload) {
if (e.payload.origin === 'keyboard') {
focus = true;
} else if (e.payload.origin === 'mouse' && e.payload.originalEvent instanceof StandardMouseEvent) {
let event = <StandardMouseEvent>e.payload.originalEvent;
focus = event.detail === 2;
aside = !this._tree.useAltAsMultipleSelectionModifier && event.altKey || this._tree.useAltAsMultipleSelectionModifier && (event.ctrlKey || event.metaKey);
}
}
this._revealTreeSelection(first, focus, aside);
}));
// feature: reveal editor selection in outline
this._editorDisposables.push(editor.onDidChangeCursorSelection(e => e.reason === CursorChangeReason.Explicit && this._revealEditorSelection(model, e.selection)));
this._revealEditorSelection(model, editor.getSelection());
}
private async _revealTreeSelection(element: OutlineElement, focus: boolean, aside: boolean): TPromise<void> {
let { range, uri } = element.symbol.location;
let input = this._editorService.createInput({ resource: uri });
await this._editorService.openEditor(input, { preserveFocus: !focus, selection: Range.collapseToStart(range), revealInCenterIfOutsideViewport: true, forceOpen: true }, aside);
}
private async _revealEditorSelection(model: OutlineModel, selection: Selection): TPromise<void> {
if (!this._outlineViewState.followCursor) {
return;
}
let item = model.getItemEnclosingPosition({
lineNumber: selection.selectionStartLineNumber,
column: selection.selectionStartColumn
});
if (item) {
await this._tree.reveal(item, .5);
this._tree.setFocus(item, this);
this._tree.setSelection([item], this);
} else {
this._tree.setSelection([], this);
}
}
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as dom from 'vs/base/browser/dom';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
import { values } from 'vs/base/common/collections';
import { onUnexpectedError } from 'vs/base/common/errors';
import { createMatches } from 'vs/base/common/filters';
import { TPromise } from 'vs/base/common/winjs.base';
import { IDataSource, IFilter, IRenderer, ISorter, ITree } from 'vs/base/parts/tree/browser/tree';
import 'vs/css!./media/symbol-icons';
import { Range } from 'vs/editor/common/core/range';
import { symbolKindToCssClass } from 'vs/editor/common/modes';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { OutlineElement, OutlineGroup, OutlineModel, TreeElement } from './outlineModel';
import { getPathLabel } from 'vs/base/common/labels';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { localize } from 'vs/nls';
import { WorkbenchTreeController } from 'vs/platform/list/browser/listService';
export enum OutlineItemCompareType {
ByPosition,
ByName,
ByKind
}
export class OutlineItemComparator implements ISorter {
constructor(
public type: OutlineItemCompareType = OutlineItemCompareType.ByPosition
) { }
compare(tree: ITree, a: OutlineGroup | OutlineElement, b: OutlineGroup | OutlineElement): number {
if (a instanceof OutlineGroup && b instanceof OutlineGroup) {
return a.providerIndex - b.providerIndex;
}
if (a instanceof OutlineElement && b instanceof OutlineElement) {
switch (this.type) {
case OutlineItemCompareType.ByKind:
return a.symbol.kind - b.symbol.kind;
case OutlineItemCompareType.ByName:
return a.symbol.name.localeCompare(b.symbol.name);
case OutlineItemCompareType.ByPosition:
default:
return Range.compareRangesUsingStarts(a.symbol.location.range, b.symbol.location.range);
}
}
return 0;
}
}
export class OutlineItemFilter implements IFilter {
isVisible(tree: ITree, element: OutlineElement | any): boolean {
return !(element instanceof OutlineElement) || Boolean(element.score);
}
}
export class OutlineDataSource implements IDataSource {
getId(tree: ITree, element: TreeElement): string {
return element.id;
}
hasChildren(tree: ITree, element: TreeElement): boolean {
if (element instanceof OutlineModel) {
return true;
}
if (element instanceof OutlineElement && !element.score) {
return false;
}
for (const _ in element.children) {
return true;
}
return false;
}
async getChildren(tree: ITree, element: TreeElement): TPromise<TreeElement[]> {
if (element instanceof OutlineModel) {
await element.request;
}
let res = values(element.children);
// console.log(element.id + ' with children ' + res.length);
return res;
}
async getParent(tree: ITree, element: TreeElement | any): TPromise<TreeElement> {
return element.parent;
}
shouldAutoexpand(tree: ITree, element: TreeElement): boolean {
return element instanceof OutlineModel || element.parent instanceof OutlineModel || element instanceof OutlineGroup || element.parent instanceof OutlineGroup;
}
}
export interface OutlineGroupTemplate {
label: HTMLDivElement;
}
export interface OutlineElementTemplate {
icon: HTMLSpanElement;
label: HighlightedLabel;
}
export class OutlineRenderer implements IRenderer {
constructor(
@IExtensionService readonly _extensionService: IExtensionService,
@IEnvironmentService readonly _environmentService: IEnvironmentService,
@IWorkspaceContextService readonly _contextService: IWorkspaceContextService
) {
//
}
getHeight(tree: ITree, element: any): number {
return 22;
}
getTemplateId(tree: ITree, element: OutlineGroup | OutlineElement): string {
return element instanceof OutlineGroup ? 'outline-group' : 'outline-element';
}
renderTemplate(tree: ITree, templateId: string, container: HTMLElement): any {
if (templateId === 'outline-element') {
const icon = dom.$('.outline-element-icon symbol-icon');
const labelContainer = dom.$('.outline-element-label');
dom.addClass(container, 'outline-element');
dom.append(container, icon, labelContainer);
return { icon, label: new HighlightedLabel(labelContainer) };
}
if (templateId === 'outline-group') {
const labelContainer = dom.$('.outline-element-label');
dom.addClass(container, 'outline-element');
dom.append(container, labelContainer);
return { label: new HighlightedLabel(labelContainer) };
}
}
renderElement(tree: ITree, element: OutlineGroup | OutlineElement, templateId: string, template: any): void {
if (element instanceof OutlineElement) {
template.icon.className = `outline-element-icon symbol-icon ${symbolKindToCssClass(element.symbol.kind)}`;
template.label.set(element.symbol.name, element.score ? createMatches(element.score[1]) : undefined, localize('outline.title', "line {0} in {1}", element.symbol.location.range.startLineNumber, getPathLabel(element.symbol.location.uri, this._contextService, this._environmentService)));
}
if (element instanceof OutlineGroup) {
this._extensionService.getExtensions().then(all => {
let found = false;
for (let i = 0; !found && i < all.length; i++) {
const extension = all[i];
if (extension.id === element.provider.extensionId) {
template.label.set(extension.displayName);
break;
}
}
}, _err => {
template.label.set(element.provider.extensionId);
});
}
}
disposeTemplate(tree: ITree, templateId: string, template: OutlineElementTemplate | OutlineGroupTemplate): void {
if (template.label instanceof HighlightedLabel) {
template.label.dispose();
}
}
}
export class OutlineTreeState {
readonly selected: string;
readonly focused: string;
readonly expanded: string[];
static capture(tree: ITree): OutlineTreeState {
// selection
let selected: string;
let element = tree.getSelection()[0];
if (element instanceof TreeElement) {
selected = element.id;
}
// focus
let focused: string;
element = tree.getFocus(true);
if (element instanceof TreeElement) {
focused = element.id;
}
// expansion
let expanded = new Array<string>();
let nav = tree.getNavigator();
while (nav.next()) {
let element = nav.current();
if (element instanceof TreeElement) {
if (tree.isExpanded(element)) {
expanded.push(element.id);
}
}
}
return { selected, focused, expanded };
}
static async restore(tree: ITree, state: OutlineTreeState): TPromise<void> {
let model = <OutlineModel>tree.getInput();
if (!state || !(model instanceof OutlineModel)) {
return TPromise.as(undefined);
}
await model.request;
// expansion
let items: TreeElement[] = [];
for (const id of state.expanded) {
let item = model.getItemById(id);
if (item) {
items.push(item);
}
}
await tree.collapseAll(undefined);
await tree.expandAll(items);
// selection & focus
let selected = model.getItemById(state.selected);
let focused = model.getItemById(state.focused);
tree.setSelection([selected]);
tree.setFocus(focused);
}
}
export class OutlineController extends WorkbenchTreeController {
protected onLeftClick(tree: ITree, element: any, event: IMouseEvent, origin: string = 'mouse'): boolean {
const payload = { origin: origin, originalEvent: event };
if (tree.getInput() === element) {
tree.clearFocus(payload);
tree.clearSelection(payload);
} else {
const isMouseDown = event && event.browserEvent && event.browserEvent.type === 'mousedown';
if (!isMouseDown) {
event.preventDefault(); // we cannot preventDefault onMouseDown because this would break DND otherwise
}
event.stopPropagation();
tree.domFocus();
tree.setSelection([element], payload);
tree.setFocus(element, payload);
const didClickElement = element instanceof OutlineElement && !this.isClickOnTwistie(event);
if (!didClickElement) {
if (tree.isExpanded(element)) {
tree.collapse(element).then(null, onUnexpectedError);
} else {
tree.expand(element).then(null, onUnexpectedError);
}
}
}
return true;
}
}
......@@ -133,5 +133,7 @@ import 'vs/workbench/parts/watermark/electron-browser/watermark';
import 'vs/workbench/parts/welcome/overlay/browser/welcomeOverlay';
import 'vs/workbench/parts/outline/electron-browser/outline.contribution';
// services
import 'vs/workbench/services/bulkEdit/electron-browser/bulkEditService';
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册