mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-21 12:20:29 -04:00
Vscode merge (#4582)
* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd * fix issues with merges * bump node version in azpipe * replace license headers * remove duplicate launch task * fix build errors * fix build errors * fix tslint issues * working through package and linux build issues * more work * wip * fix packaged builds * working through linux build errors * wip * wip * wip * fix mac and linux file limits * iterate linux pipeline * disable editor typing * revert series to parallel * remove optimize vscode from linux * fix linting issues * revert testing change * add work round for new node * readd packaging for extensions * fix issue with angular not resolving decorator dependencies
This commit is contained in:
@@ -3,49 +3,28 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-tree.focused .selected .outline-element-label, .monaco-tree.focused .selected .outline-element-decoration {
|
||||
.monaco-list .monaco-list-row.focused.selected .outline-element .monaco-highlighted-label,
|
||||
.monaco-list .monaco-list-row.focused.selected .outline-element-decoration {
|
||||
/* make sure selection color wins when a label is being selected */
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.monaco-tree .outline-element {
|
||||
.monaco-list .outline-element {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.monaco-tree .outline-element .outline-element-icon {
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
.monaco-tree .outline-element .outline-element-label {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
.monaco-list .outline-element .monaco-highlighted-label {
|
||||
color: var(--outline-element-color);
|
||||
}
|
||||
|
||||
.monaco-tree .outline-element .outline-element-label .monaco-highlighted-label .highlight {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.monaco-tree .outline-element .outline-element-detail {
|
||||
visibility: hidden;
|
||||
flex: 1;
|
||||
flex-basis: 10%;
|
||||
opacity: 0.8;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 90%;
|
||||
padding-left: 4px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.monaco-tree .monaco-tree-row.focused .outline-element .outline-element-detail {
|
||||
visibility: inherit;
|
||||
}
|
||||
|
||||
.monaco-tree .outline-element .outline-element-decoration {
|
||||
.monaco-list .outline-element .outline-element-decoration {
|
||||
opacity: 0.75;
|
||||
font-size: 90%;
|
||||
font-weight: 600;
|
||||
@@ -55,7 +34,7 @@
|
||||
color: var(--outline-element-color);
|
||||
}
|
||||
|
||||
.monaco-tree .outline-element .outline-element-decoration.bubble {
|
||||
.monaco-list .outline-element .outline-element-decoration.bubble {
|
||||
font-family: octicons;
|
||||
font-size: 14px;
|
||||
opacity: 0.4;
|
||||
|
||||
@@ -3,7 +3,13 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench .symbol-icon {
|
||||
.monaco-workbench .symbol-icon.inline {
|
||||
background-position: left center;
|
||||
padding-left: 20px;
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
.monaco-workbench .symbol-icon.block {
|
||||
display: inline-block;
|
||||
height: 14px;
|
||||
width: 16px;
|
||||
|
||||
18
src/vs/editor/contrib/documentSymbols/outline.ts
Normal file
18
src/vs/editor/contrib/documentSymbols/outline.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
||||
export const OutlineViewId = 'outline';
|
||||
|
||||
export const OutlineViewFiltered = new RawContextKey('outlineFiltered', false);
|
||||
export const OutlineViewFocused = new RawContextKey('outlineFocused', false);
|
||||
|
||||
export const enum OutlineConfigKeys {
|
||||
'icons' = 'outline.icons',
|
||||
'problemsEnabled' = 'outline.problems.enabled',
|
||||
'problemsColors' = 'outline.problems.colors',
|
||||
'problemsBadges' = 'outline.problems.badges'
|
||||
}
|
||||
@@ -3,18 +3,17 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { binarySearch, coalesceInPlace } from 'vs/base/common/arrays';
|
||||
import { binarySearch, coalesceInPlace, equals } from 'vs/base/common/arrays';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { first, forEach, size } from 'vs/base/common/collections';
|
||||
import { onUnexpectedExternalError } from 'vs/base/common/errors';
|
||||
import { fuzzyScore, FuzzyScore } from 'vs/base/common/filters';
|
||||
import { LRUCache } from 'vs/base/common/map';
|
||||
import { commonPrefixLength } from 'vs/base/common/strings';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { DocumentSymbol, DocumentSymbolProvider, DocumentSymbolProviderRegistry } from 'vs/editor/common/modes';
|
||||
import { IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
import { MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
|
||||
export abstract class TreeElement {
|
||||
|
||||
@@ -87,10 +86,17 @@ export abstract class TreeElement {
|
||||
}
|
||||
}
|
||||
|
||||
export interface IOutlineMarker {
|
||||
startLineNumber: number;
|
||||
startColumn: number;
|
||||
endLineNumber: number;
|
||||
endColumn: number;
|
||||
severity: MarkerSeverity;
|
||||
}
|
||||
|
||||
export class OutlineElement extends TreeElement {
|
||||
|
||||
children: { [id: string]: OutlineElement; } = Object.create(null);
|
||||
score: FuzzyScore | undefined = FuzzyScore.Default;
|
||||
marker: { count: number, topSev: MarkerSeverity } | undefined;
|
||||
|
||||
constructor(
|
||||
@@ -127,33 +133,6 @@ export class OutlineGroup extends TreeElement {
|
||||
return res;
|
||||
}
|
||||
|
||||
updateMatches(pattern: string, topMatch: OutlineElement | undefined): OutlineElement | undefined {
|
||||
for (const key in this.children) {
|
||||
topMatch = this._updateMatches(pattern, this.children[key], topMatch);
|
||||
}
|
||||
return topMatch;
|
||||
}
|
||||
|
||||
private _updateMatches(pattern: string, item: OutlineElement, topMatch: OutlineElement | undefined): OutlineElement | undefined {
|
||||
|
||||
item.score = pattern
|
||||
? fuzzyScore(pattern, pattern.toLowerCase(), 0, item.symbol.name, item.symbol.name.toLowerCase(), 0, true)
|
||||
: FuzzyScore.Default;
|
||||
|
||||
if (item.score && (!topMatch || !topMatch.score || 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 = FuzzyScore.Default;
|
||||
}
|
||||
}
|
||||
return topMatch;
|
||||
}
|
||||
|
||||
getItemEnclosingPosition(position: IPosition): OutlineElement | undefined {
|
||||
return position ? this._getItemEnclosingPosition(position, this.children) : undefined;
|
||||
}
|
||||
@@ -169,13 +148,13 @@ export class OutlineGroup extends TreeElement {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
updateMarker(marker: IMarker[]): void {
|
||||
updateMarker(marker: IOutlineMarker[]): void {
|
||||
for (const key in this.children) {
|
||||
this._updateMarker(marker, this.children[key]);
|
||||
}
|
||||
}
|
||||
|
||||
private _updateMarker(markers: IMarker[], item: OutlineElement): void {
|
||||
private _updateMarker(markers: IOutlineMarker[], item: OutlineElement): void {
|
||||
item.marker = undefined;
|
||||
|
||||
// find the proper start index to check for item/marker overlap.
|
||||
@@ -190,7 +169,7 @@ export class OutlineGroup extends TreeElement {
|
||||
start = idx;
|
||||
}
|
||||
|
||||
let myMarkers: IMarker[] = [];
|
||||
let myMarkers: IOutlineMarker[] = [];
|
||||
let myTopSev: MarkerSeverity | undefined;
|
||||
|
||||
for (; start < markers.length && Range.areIntersecting(item.symbol.range, markers[start]); start++) {
|
||||
@@ -198,7 +177,7 @@ export class OutlineGroup extends TreeElement {
|
||||
// and store them in a 'private' array.
|
||||
let marker = markers[start];
|
||||
myMarkers.push(marker);
|
||||
(markers as Array<IMarker | undefined>)[start] = undefined;
|
||||
(markers as Array<IOutlineMarker | undefined>)[start] = undefined;
|
||||
if (!myTopSev || marker.severity > myTopSev) {
|
||||
myTopSev = marker.severity;
|
||||
}
|
||||
@@ -268,7 +247,7 @@ export class OutlineModel extends TreeElement {
|
||||
|
||||
if (data!.model) {
|
||||
// resolved -> return data
|
||||
return Promise.resolve(data.model);
|
||||
return Promise.resolve(data.model!);
|
||||
}
|
||||
|
||||
// increase usage counter
|
||||
@@ -295,13 +274,17 @@ export class OutlineModel extends TreeElement {
|
||||
|
||||
static _create(textModel: ITextModel, token: CancellationToken): Promise<OutlineModel> {
|
||||
|
||||
let result = new OutlineModel(textModel);
|
||||
let promises = DocumentSymbolProviderRegistry.ordered(textModel).map((provider, index) => {
|
||||
const chainedCancellation = new CancellationTokenSource();
|
||||
token.onCancellationRequested(() => chainedCancellation.cancel());
|
||||
|
||||
const result = new OutlineModel(textModel);
|
||||
const provider = DocumentSymbolProviderRegistry.ordered(textModel);
|
||||
const promises = provider.map((provider, index) => {
|
||||
|
||||
let id = TreeElement.findId(`provider_${index}`, result);
|
||||
let group = new OutlineGroup(id, result, provider, index);
|
||||
|
||||
return Promise.resolve(provider.provideDocumentSymbols(result.textModel, token)).then(result => {
|
||||
return Promise.resolve(provider.provideDocumentSymbols(result.textModel, chainedCancellation.token)).then(result => {
|
||||
for (const info of result || []) {
|
||||
OutlineModel._makeOutlineElement(info, group);
|
||||
}
|
||||
@@ -318,7 +301,22 @@ export class OutlineModel extends TreeElement {
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(() => result._compact());
|
||||
const listener = DocumentSymbolProviderRegistry.onDidChange(() => {
|
||||
const newProvider = DocumentSymbolProviderRegistry.ordered(textModel);
|
||||
if (!equals(newProvider, provider)) {
|
||||
chainedCancellation.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
if (chainedCancellation.token.isCancellationRequested && !token.isCancellationRequested) {
|
||||
return OutlineModel._create(textModel, token);
|
||||
} else {
|
||||
return result._compact();
|
||||
}
|
||||
}).finally(() => {
|
||||
listener.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
private static _makeOutlineElement(info: DocumentSymbol, container: OutlineGroup | OutlineElement): void {
|
||||
@@ -395,20 +393,6 @@ export class OutlineModel extends TreeElement {
|
||||
return true;
|
||||
}
|
||||
|
||||
private _matches: [string, OutlineElement | undefined];
|
||||
|
||||
updateMatches(pattern: string): OutlineElement | undefined {
|
||||
if (this._matches && this._matches[0] === pattern) {
|
||||
return this._matches[1];
|
||||
}
|
||||
let topMatch: OutlineElement | undefined;
|
||||
for (const key in this._groups) {
|
||||
topMatch = this._groups[key].updateMatches(pattern, topMatch);
|
||||
}
|
||||
this._matches = [pattern, topMatch];
|
||||
return topMatch;
|
||||
}
|
||||
|
||||
getItemEnclosingPosition(position: IPosition, context?: OutlineElement): OutlineElement | undefined {
|
||||
|
||||
let preferredGroup: OutlineGroup | undefined;
|
||||
@@ -437,7 +421,7 @@ export class OutlineModel extends TreeElement {
|
||||
return TreeElement.getElementById(id, this);
|
||||
}
|
||||
|
||||
updateMarker(marker: IMarker[]): void {
|
||||
updateMarker(marker: IOutlineMarker[]): void {
|
||||
// sort markers by start range so that we can use
|
||||
// outline element starts for quicker look up
|
||||
marker.sort(Range.compareRangesUsingStarts);
|
||||
|
||||
@@ -4,178 +4,141 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
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 { IIdentityProvider, IKeyboardNavigationLabelProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { IDataSource, ITreeNode, ITreeRenderer, ITreeSorter } from 'vs/base/browser/ui/tree/tree';
|
||||
import { values } from 'vs/base/common/collections';
|
||||
import { createMatches } from 'vs/base/common/filters';
|
||||
import { IDataSource, IFilter, IRenderer, ISorter, ITree } from 'vs/base/parts/tree/browser/tree';
|
||||
import { createMatches, FuzzyScore } from 'vs/base/common/filters';
|
||||
import 'vs/css!./media/outlineTree';
|
||||
import 'vs/css!./media/symbol-icons';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { SymbolKind, symbolKindToCssClass } from 'vs/editor/common/modes';
|
||||
import { OutlineElement, OutlineGroup, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IKeybindingService, IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { WorkbenchTreeController } from 'vs/platform/list/browser/listService';
|
||||
import { OutlineConfigKeys } from 'vs/editor/contrib/documentSymbols/outline';
|
||||
import { MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
import { listErrorForeground, listWarningForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { listErrorForeground, listWarningForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
|
||||
export const enum OutlineItemCompareType {
|
||||
ByPosition,
|
||||
ByName,
|
||||
ByKind
|
||||
}
|
||||
export type OutlineItem = OutlineGroup | OutlineElement;
|
||||
|
||||
export class OutlineItemComparator implements ISorter {
|
||||
export class OutlineNavigationLabelProvider implements IKeyboardNavigationLabelProvider<OutlineItem> {
|
||||
|
||||
constructor(
|
||||
public type: OutlineItemCompareType = OutlineItemCompareType.ByPosition
|
||||
) { }
|
||||
constructor(@IKeybindingService private readonly _keybindingService: IKeybindingService) { }
|
||||
|
||||
compare(tree: ITree, a: OutlineGroup | OutlineElement, b: OutlineGroup | OutlineElement): number {
|
||||
|
||||
if (a instanceof OutlineGroup && b instanceof OutlineGroup) {
|
||||
return a.providerIndex - b.providerIndex;
|
||||
getKeyboardNavigationLabel(element: OutlineItem): { toString(): string; } {
|
||||
if (element instanceof OutlineGroup) {
|
||||
return element.provider.displayName || element.id;
|
||||
} else {
|
||||
return element.symbol.name;
|
||||
}
|
||||
}
|
||||
|
||||
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.range, b.symbol.range);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
mightProducePrintableCharacter(event: IKeyboardEvent): boolean {
|
||||
return this._keybindingService.mightProducePrintableCharacter(event);
|
||||
}
|
||||
}
|
||||
|
||||
export class OutlineItemFilter implements IFilter {
|
||||
|
||||
enabled: boolean = true;
|
||||
|
||||
isVisible(tree: ITree, element: OutlineElement | any): boolean {
|
||||
if (!this.enabled) {
|
||||
return true;
|
||||
}
|
||||
return !(element instanceof OutlineElement) || Boolean(element.score);
|
||||
export class OutlineIdentityProvider implements IIdentityProvider<OutlineItem> {
|
||||
getId(element: TreeElement): { toString(): string; } {
|
||||
return element.id;
|
||||
}
|
||||
}
|
||||
|
||||
export class OutlineDataSource implements IDataSource {
|
||||
export class OutlineGroupTemplate {
|
||||
static id = 'OutlineGroupTemplate';
|
||||
|
||||
// this is a workaround for the tree showing twisties for items
|
||||
// with only filtered children
|
||||
filterOnScore: boolean = true;
|
||||
|
||||
getId(tree: ITree, element: TreeElement): string {
|
||||
return element ? element.id : 'empty';
|
||||
}
|
||||
|
||||
hasChildren(tree: ITree, element: OutlineModel | OutlineGroup | OutlineElement): boolean {
|
||||
if (!element) {
|
||||
return false;
|
||||
}
|
||||
if (element instanceof OutlineModel) {
|
||||
return true;
|
||||
}
|
||||
if (element instanceof OutlineElement && (this.filterOnScore && !element.score)) {
|
||||
return false;
|
||||
}
|
||||
for (const id in element.children) {
|
||||
if (!this.filterOnScore || element.children[id].score) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getChildren(tree: ITree, element: TreeElement): Promise<TreeElement[]> {
|
||||
let res = values(element.children);
|
||||
// console.log(element.id + ' with children ' + res.length);
|
||||
return Promise.resolve(res);
|
||||
}
|
||||
|
||||
getParent(tree: ITree, element: TreeElement | any): Promise<TreeElement> {
|
||||
return Promise.resolve(element && element.parent);
|
||||
}
|
||||
|
||||
shouldAutoexpand(tree: ITree, element: TreeElement): boolean {
|
||||
return element && (element instanceof OutlineModel || element.parent instanceof OutlineModel || element instanceof OutlineGroup || element.parent instanceof OutlineGroup);
|
||||
}
|
||||
}
|
||||
|
||||
export interface OutlineTemplate {
|
||||
labelContainer: HTMLElement;
|
||||
label: HighlightedLabel;
|
||||
icon?: HTMLElement;
|
||||
detail?: HTMLElement;
|
||||
decoration?: HTMLElement;
|
||||
}
|
||||
|
||||
export class OutlineRenderer implements IRenderer {
|
||||
export class OutlineElementTemplate {
|
||||
static id = 'OutlineElementTemplate';
|
||||
container: HTMLElement;
|
||||
iconLabel: IconLabel;
|
||||
decoration: HTMLElement;
|
||||
}
|
||||
|
||||
renderProblemColors = true;
|
||||
renderProblemBadges = true;
|
||||
export class OutlineVirtualDelegate implements IListVirtualDelegate<OutlineItem> {
|
||||
|
||||
constructor(
|
||||
@IThemeService readonly _themeService: IThemeService,
|
||||
@IConfigurationService readonly _configurationService: IConfigurationService
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
getHeight(tree: ITree, element: any): number {
|
||||
getHeight(_element: OutlineItem): 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): OutlineTemplate {
|
||||
if (templateId === 'outline-element') {
|
||||
const icon = dom.$('.outline-element-icon symbol-icon');
|
||||
const labelContainer = dom.$('.outline-element-label');
|
||||
const detail = dom.$('.outline-element-detail');
|
||||
const decoration = dom.$('.outline-element-decoration');
|
||||
dom.addClass(container, 'outline-element');
|
||||
dom.append(container, icon, labelContainer, detail, decoration);
|
||||
return { icon, labelContainer, label: new HighlightedLabel(labelContainer, true), detail, decoration };
|
||||
}
|
||||
if (templateId === 'outline-group') {
|
||||
const labelContainer = dom.$('.outline-element-label');
|
||||
dom.addClass(container, 'outline-element');
|
||||
dom.append(container, labelContainer);
|
||||
return { labelContainer, label: new HighlightedLabel(labelContainer, true) };
|
||||
}
|
||||
|
||||
throw new Error(templateId);
|
||||
}
|
||||
|
||||
renderElement(tree: ITree, element: OutlineGroup | OutlineElement, templateId: string, template: OutlineTemplate): void {
|
||||
if (element instanceof OutlineElement) {
|
||||
template.icon.className = `outline-element-icon ${symbolKindToCssClass(element.symbol.kind)}`;
|
||||
template.label.set(element.symbol.name, element.score ? createMatches(element.score) : undefined, localize('title.template', "{0} ({1})", element.symbol.name, OutlineRenderer._symbolKindNames[element.symbol.kind]));
|
||||
template.detail.innerText = element.symbol.detail || '';
|
||||
this._renderMarkerInfo(element, template);
|
||||
|
||||
}
|
||||
getTemplateId(element: OutlineItem): string {
|
||||
if (element instanceof OutlineGroup) {
|
||||
template.label.set(element.provider.displayName || localize('provider', "Outline Provider"));
|
||||
return OutlineGroupTemplate.id;
|
||||
} else {
|
||||
return OutlineElementTemplate.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _renderMarkerInfo(element: OutlineElement, template: OutlineTemplate): void {
|
||||
export class OutlineGroupRenderer implements ITreeRenderer<OutlineGroup, FuzzyScore, OutlineGroupTemplate> {
|
||||
|
||||
readonly templateId: string = OutlineGroupTemplate.id;
|
||||
|
||||
renderTemplate(container: HTMLElement): OutlineGroupTemplate {
|
||||
const labelContainer = dom.$('.outline-element-label');
|
||||
dom.addClass(container, 'outline-element');
|
||||
dom.append(container, labelContainer);
|
||||
return { labelContainer, label: new HighlightedLabel(labelContainer, true) };
|
||||
}
|
||||
|
||||
renderElement(node: ITreeNode<OutlineGroup, FuzzyScore>, index: number, template: OutlineGroupTemplate): void {
|
||||
template.label.set(
|
||||
node.element.provider.displayName || localize('provider', "Outline Provider"),
|
||||
createMatches(node.filterData)
|
||||
);
|
||||
}
|
||||
|
||||
disposeTemplate(_template: OutlineGroupTemplate): void {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
export class OutlineElementRenderer implements ITreeRenderer<OutlineElement, FuzzyScore, OutlineElementTemplate> {
|
||||
|
||||
readonly templateId: string = OutlineElementTemplate.id;
|
||||
|
||||
constructor(
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@IThemeService private readonly _themeService: IThemeService,
|
||||
) { }
|
||||
|
||||
renderTemplate(container: HTMLElement): OutlineElementTemplate {
|
||||
dom.addClass(container, 'outline-element');
|
||||
const iconLabel = new IconLabel(container, { supportHighlights: true });
|
||||
const decoration = dom.$('.outline-element-decoration');
|
||||
container.appendChild(decoration);
|
||||
return { container, iconLabel, decoration };
|
||||
}
|
||||
|
||||
renderElement(node: ITreeNode<OutlineElement, FuzzyScore>, index: number, template: OutlineElementTemplate): void {
|
||||
const { element } = node;
|
||||
const options = {
|
||||
matches: createMatches(node.filterData),
|
||||
labelEscapeNewLines: true,
|
||||
extraClasses: <string[]>[],
|
||||
title: localize('title.template', "{0} ({1})", element.symbol.name, OutlineElementRenderer._symbolKindNames[element.symbol.kind])
|
||||
};
|
||||
if (this._configurationService.getValue(OutlineConfigKeys.icons)) {
|
||||
// add styles for the icons
|
||||
options.extraClasses.push(`outline-element-icon ${symbolKindToCssClass(element.symbol.kind, true)}`);
|
||||
}
|
||||
template.iconLabel.setLabel(element.symbol.name, element.symbol.detail, options);
|
||||
this._renderMarkerInfo(element, template);
|
||||
}
|
||||
|
||||
private _renderMarkerInfo(element: OutlineElement, template: OutlineElementTemplate): void {
|
||||
|
||||
if (!element.marker) {
|
||||
dom.hide(template.decoration);
|
||||
template.labelContainer.style.removeProperty('--outline-element-color');
|
||||
template.container.style.removeProperty('--outline-element-color');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -184,14 +147,14 @@ export class OutlineRenderer implements IRenderer {
|
||||
const cssColor = color ? color.toString() : 'inherit';
|
||||
|
||||
// color of the label
|
||||
if (this.renderProblemColors) {
|
||||
template.labelContainer.style.setProperty('--outline-element-color', cssColor);
|
||||
if (this._configurationService.getValue(OutlineConfigKeys.problemsColors)) {
|
||||
template.container.style.setProperty('--outline-element-color', cssColor);
|
||||
} else {
|
||||
template.labelContainer.style.removeProperty('--outline-element-color');
|
||||
template.container.style.removeProperty('--outline-element-color');
|
||||
}
|
||||
|
||||
// badge with color/rollup
|
||||
if (!this.renderProblemBadges) {
|
||||
if (!this._configurationService.getValue(OutlineConfigKeys.problemsBadges)) {
|
||||
dom.hide(template.decoration);
|
||||
|
||||
} else if (count > 0) {
|
||||
@@ -239,77 +202,46 @@ export class OutlineRenderer implements IRenderer {
|
||||
[SymbolKind.Variable]: localize('Variable', "variable"),
|
||||
};
|
||||
|
||||
disposeTemplate(tree: ITree, templateId: string, template: OutlineTemplate): void {
|
||||
// noop
|
||||
disposeTemplate(_template: OutlineElementTemplate): void {
|
||||
_template.iconLabel.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class OutlineTreeState {
|
||||
export const enum OutlineSortOrder {
|
||||
ByPosition,
|
||||
ByName,
|
||||
ByKind
|
||||
}
|
||||
|
||||
readonly selected: string;
|
||||
readonly focused: string;
|
||||
readonly expanded: string[];
|
||||
export class OutlineItemComparator implements ITreeSorter<OutlineItem> {
|
||||
|
||||
static capture(tree: ITree): OutlineTreeState {
|
||||
// selection
|
||||
let selected: string;
|
||||
let element = tree.getSelection()[0];
|
||||
if (element instanceof TreeElement) {
|
||||
selected = element.id;
|
||||
}
|
||||
constructor(
|
||||
public type: OutlineSortOrder = OutlineSortOrder.ByPosition
|
||||
) { }
|
||||
|
||||
// focus
|
||||
let focused: string;
|
||||
element = tree.getFocus(true);
|
||||
if (element instanceof TreeElement) {
|
||||
focused = element.id;
|
||||
}
|
||||
compare(a: OutlineItem, b: OutlineItem): number {
|
||||
if (a instanceof OutlineGroup && b instanceof OutlineGroup) {
|
||||
return a.providerIndex - b.providerIndex;
|
||||
|
||||
// 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);
|
||||
}
|
||||
} else if (a instanceof OutlineElement && b instanceof OutlineElement) {
|
||||
if (this.type === OutlineSortOrder.ByKind) {
|
||||
return a.symbol.kind - b.symbol.kind || a.symbol.name.localeCompare(b.symbol.name);
|
||||
} else if (this.type === OutlineSortOrder.ByName) {
|
||||
return a.symbol.name.localeCompare(b.symbol.name) || Range.compareRangesUsingStarts(a.symbol.range, b.symbol.range);
|
||||
} else if (this.type === OutlineSortOrder.ByPosition) {
|
||||
return Range.compareRangesUsingStarts(a.symbol.range, b.symbol.range) || a.symbol.name.localeCompare(b.symbol.name);
|
||||
}
|
||||
}
|
||||
return { selected, focused, expanded };
|
||||
}
|
||||
|
||||
static async restore(tree: ITree, state: OutlineTreeState, eventPayload: any): Promise<void> {
|
||||
let model = <OutlineModel>tree.getInput();
|
||||
if (!state || !(model instanceof OutlineModel)) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
// 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], eventPayload);
|
||||
tree.setFocus(focused, eventPayload);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export class OutlineController extends WorkbenchTreeController {
|
||||
protected shouldToggleExpansion(element: any, event: IMouseEvent, origin: string): boolean {
|
||||
if (element instanceof OutlineElement) {
|
||||
return this.isClickOnTwistie(event);
|
||||
} else {
|
||||
return super.shouldToggleExpansion(element, event, origin);
|
||||
export class OutlineDataSource implements IDataSource<OutlineModel, OutlineItem> {
|
||||
|
||||
getChildren(element: undefined | OutlineModel | OutlineGroup | OutlineElement): OutlineItem[] {
|
||||
if (!element) {
|
||||
return [];
|
||||
}
|
||||
return values(element.children);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,9 +101,9 @@ suite('OutlineModel', function () {
|
||||
|
||||
group.updateMarker(data);
|
||||
assert.equal(data.length, 0); // all 'stolen'
|
||||
assert.equal(e0.marker.count, 1);
|
||||
assert.equal(e0.marker!.count, 1);
|
||||
assert.equal(e1.marker, undefined);
|
||||
assert.equal(e2.marker.count, 2);
|
||||
assert.equal(e2.marker!.count, 2);
|
||||
|
||||
group.updateMarker([]);
|
||||
assert.equal(e0.marker, undefined);
|
||||
@@ -127,8 +127,8 @@ suite('OutlineModel', function () {
|
||||
];
|
||||
|
||||
group.updateMarker(data);
|
||||
assert.equal(p.marker.count, 0);
|
||||
assert.equal(c1.marker.count, 1);
|
||||
assert.equal(p.marker!.count, 0);
|
||||
assert.equal(c1.marker!.count, 1);
|
||||
assert.equal(c2.marker, undefined);
|
||||
|
||||
data = [
|
||||
@@ -137,18 +137,18 @@ suite('OutlineModel', function () {
|
||||
fakeMarker(new Range(7, 6, 7, 8)),
|
||||
];
|
||||
group.updateMarker(data);
|
||||
assert.equal(p.marker.count, 0);
|
||||
assert.equal(c1.marker.count, 2);
|
||||
assert.equal(c2.marker.count, 1);
|
||||
assert.equal(p.marker!.count, 0);
|
||||
assert.equal(c1.marker!.count, 2);
|
||||
assert.equal(c2.marker!.count, 1);
|
||||
|
||||
data = [
|
||||
fakeMarker(new Range(1, 4, 1, 11)),
|
||||
fakeMarker(new Range(7, 6, 7, 8)),
|
||||
];
|
||||
group.updateMarker(data);
|
||||
assert.equal(p.marker.count, 1);
|
||||
assert.equal(p.marker!.count, 1);
|
||||
assert.equal(c1.marker, undefined);
|
||||
assert.equal(c2.marker.count, 1);
|
||||
assert.equal(c2.marker!.count, 1);
|
||||
});
|
||||
|
||||
test('OutlineElement - updateMarker/multiple groups', function () {
|
||||
@@ -178,9 +178,9 @@ suite('OutlineModel', function () {
|
||||
|
||||
model.updateMarker(data);
|
||||
|
||||
assert.equal(model.children['g1'].children['c1'].marker.count, 2);
|
||||
assert.equal(model.children['g2'].children['c2'].children['c2.1'].marker.count, 1);
|
||||
assert.equal(model.children['g2'].children['c2'].children['c2.2'].marker.count, 1);
|
||||
assert.equal(model.children['g1']!.children['c1'].marker!.count, 2);
|
||||
assert.equal(model.children['g2']!.children['c2'].children['c2.1'].marker!.count, 1);
|
||||
assert.equal(model.children['g2']!.children['c2'].children['c2.2'].marker!.count, 1);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user