提交 07e5e714 编写于 作者: S Sandeep Somavarapu

#10271 Show diagnostics with children in problems panel

上级 2cd29c42
......@@ -7,26 +7,32 @@
import * as paths from 'vs/base/common/paths';
import URI from 'vs/base/common/uri';
import { Range, IRange } from 'vs/editor/common/core/range';
import { IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers';
import { IMarker, MarkerSeverity, IRelatedInformation } from 'vs/platform/markers/common/markers';
import { IFilter, IMatch, or, matchesContiguousSubString, matchesPrefix, matchesFuzzy } from 'vs/base/common/filters';
import Messages from 'vs/workbench/parts/markers/electron-browser/messages';
import { Schemas } from 'vs/base/common/network';
import { groupBy, isFalsyOrEmpty } from 'vs/base/common/arrays';
import { values } from 'vs/base/common/map';
export class Resource {
export abstract class NodeWithId {
constructor(readonly id: string) { }
}
export class ResourceData<T> extends NodeWithId {
private _name: string = null;
private _path: string = null;
filteredMarkersCount: number = 0;
count: number = 0;
uriMatches: IMatch[] = [];
constructor(
id: string,
readonly uri: URI,
readonly markers: Marker[],
readonly data: T[]
) {
markers.sort(Marker.compare);
super(id);
this.count = this.data.length;
}
public get path(): string {
......@@ -42,10 +48,21 @@ export class Resource {
}
return this._name;
}
}
static compare(a: Resource, b: Resource): number {
let [firstMarkerOfA] = a.markers;
let [firstMarkerOfB] = b.markers;
export class ResourceMarkers extends ResourceData<Marker> {
constructor(
uri: URI,
markers: Marker[]
) {
const sorted = markers.sort(Marker.compare);
super(uri.toString(), uri, sorted);
}
static compare(a: ResourceMarkers, b: ResourceMarkers): number {
let [firstMarkerOfA] = a.data;
let [firstMarkerOfB] = b.data;
let res = 0;
if (firstMarkerOfA && firstMarkerOfB) {
res = MarkerSeverity.compare(firstMarkerOfA.raw.severity, firstMarkerOfB.raw.severity);
......@@ -57,16 +74,19 @@ export class Resource {
}
}
export class Marker {
export class Marker extends NodeWithId {
isSelected: boolean = false;
messageMatches: IMatch[] = [];
sourceMatches: IMatch[] = [];
resourceRelatedInformation: ResourceData<RelatedInformation>[] = [];
constructor(
readonly id: string,
id: string,
readonly raw: IMarker,
) { }
) {
super(id);
}
public get resource(): URI {
return this.raw.resource;
......@@ -93,6 +113,15 @@ export class Marker {
}
}
export class RelatedInformation extends NodeWithId {
constructor(
id: string,
readonly relatedInformation: IRelatedInformation,
public matches: IMatch[]) {
super(id);
}
}
export class FilterOptions {
static readonly _filter: IFilter = or(matchesPrefix, matchesContiguousSubString);
......@@ -126,12 +155,12 @@ export class FilterOptions {
export class MarkersModel {
private _cachedSortedResources: Resource[];
private _markersByResource: Map<string, Resource>;
private _cachedSortedResources: ResourceMarkers[];
private _markersByResource: Map<string, ResourceMarkers>;
private _filterOptions: FilterOptions;
constructor(markers: IMarker[] = []) {
this._markersByResource = new Map<string, Resource>();
this._markersByResource = new Map<string, ResourceMarkers>();
this._filterOptions = new FilterOptions();
for (const group of groupBy(markers, MarkersModel._compareMarkersByUri)) {
......@@ -154,16 +183,16 @@ export class MarkersModel {
return this._filterOptions;
}
public get resources(): Resource[] {
public get resources(): ResourceMarkers[] {
if (!this._cachedSortedResources) {
this._cachedSortedResources = values(this._markersByResource).sort(Resource.compare);
this._cachedSortedResources = values(this._markersByResource).sort(ResourceMarkers.compare);
}
return this._cachedSortedResources;
}
public forEachFilteredResource(callback: (resource: Resource) => any) {
public forEachFilteredResource(callback: (resource: ResourceMarkers) => any) {
this._markersByResource.forEach(resource => {
if (resource.filteredMarkersCount > 0) {
if (resource.count > 0) {
callback(resource);
}
});
......@@ -172,7 +201,7 @@ export class MarkersModel {
public hasFilteredResources(): boolean {
let res = false;
this._markersByResource.forEach(resource => {
res = res || resource.filteredMarkersCount > 0;
res = res || resource.count > 0;
});
return res;
}
......@@ -189,8 +218,8 @@ export class MarkersModel {
let total = 0;
let filtered = 0;
this._markersByResource.forEach(resource => {
total += resource.markers.length;
filtered += resource.filteredMarkersCount;
total += resource.data.length;
filtered += resource.count;
});
return { total, filtered };
......@@ -212,13 +241,17 @@ export class MarkersModel {
if (!this._filterOptions.hasFilters()) {
// reset all filters/matches
this._markersByResource.forEach(resource => {
resource.filteredMarkersCount = resource.markers.length;
resource.count = resource.data.length;
resource.uriMatches = [];
for (const marker of resource.markers) {
for (const marker of resource.data) {
marker.isSelected = true;
marker.messageMatches = [];
marker.sourceMatches = [];
marker.resourceRelatedInformation.forEach(r => {
r.uriMatches = [];
r.data.forEach(d => d.matches = []);
});
}
});
} else {
......@@ -226,21 +259,25 @@ export class MarkersModel {
this._markersByResource.forEach(resource => {
resource.uriMatches = this._filterOptions.hasFilters() ? FilterOptions._filter(this._filterOptions.filter, paths.basename(resource.uri.fsPath)) : [];
resource.filteredMarkersCount = 0;
resource.count = 0;
for (const marker of resource.markers) {
for (const marker of resource.data) {
marker.messageMatches = this._filterOptions.hasFilters() ? FilterOptions._fuzzyFilter(this._filterOptions.filter, marker.raw.message) : [];
marker.sourceMatches = marker.raw.source && this._filterOptions.hasFilters() ? FilterOptions._filter(this._filterOptions.filter, marker.raw.source) : [];
marker.isSelected = this.filterMarker(marker.raw);
if (marker.isSelected) {
resource.filteredMarkersCount += 1;
resource.count += 1;
}
marker.resourceRelatedInformation.forEach(r => {
r.uriMatches = this._filterOptions.hasFilters() ? FilterOptions._filter(this._filterOptions.filter, paths.basename(r.uri.fsPath)) : [];
r.data.forEach(d => d.matches = this._filterOptions.hasFilters() ? FilterOptions._fuzzyFilter(this._filterOptions.filter, d.relatedInformation.message) : []);
});
}
});
}
}
private createResource(uri: URI, rawMarkers: IMarker[]): Resource {
private createResource(uri: URI, rawMarkers: IMarker[]): ResourceMarkers {
let markers: Marker[] = [];
let filteredCount = 0;
......@@ -252,19 +289,36 @@ export class MarkersModel {
}
}
const resource = new Resource(uri, markers);
resource.filteredMarkersCount = filteredCount;
const resource = new ResourceMarkers(uri, markers);
resource.count = filteredCount;
resource.uriMatches = this._filterOptions.hasFilters() ? FilterOptions._filter(this._filterOptions.filter, paths.basename(uri.fsPath)) : [];
return resource;
}
private createMarker(marker: IMarker, index: number, uri: string): Marker {
const res = new Marker(uri + index, marker);
res.messageMatches = this._filterOptions.hasFilters() ? FilterOptions._fuzzyFilter(this._filterOptions.filter, marker.message) : [];
res.sourceMatches = marker.source && this._filterOptions.hasFilters() ? FilterOptions._filter(this._filterOptions.filter, marker.source) : [];
res.isSelected = this.filterMarker(marker);
return res;
private createMarker(rawMarker: IMarker, index: number, uri: string): Marker {
const marker = new Marker(uri + index, rawMarker);
marker.messageMatches = this._filterOptions.hasFilters() ? FilterOptions._fuzzyFilter(this._filterOptions.filter, rawMarker.message) : [];
marker.sourceMatches = rawMarker.source && this._filterOptions.hasFilters() ? FilterOptions._filter(this._filterOptions.filter, rawMarker.source) : [];
marker.isSelected = this.filterMarker(rawMarker);
if (rawMarker.relatedInformation) {
marker.resourceRelatedInformation = groupBy(rawMarker.relatedInformation, MarkersModel._compareMarkersByUri)
.map(group => {
const id = uri + index + uri + index.toString();
const r = new ResourceData<RelatedInformation>(
id,
group[0].resource,
group.map((relatedInformation, index) =>
new RelatedInformation(
id + index,
relatedInformation,
this._filterOptions.hasFilters() ? FilterOptions._fuzzyFilter(this._filterOptions.filter, relatedInformation.message) : []
)));
r.uriMatches = this._filterOptions.hasFilters() ? FilterOptions._filter(this._filterOptions.filter, paths.basename(r.uri.fsPath)) : [];
return r;
});
}
return marker;
}
private filterMarker(marker: IMarker): boolean {
......@@ -292,6 +346,11 @@ export class MarkersModel {
if (!!marker.source && !!FilterOptions._filter(this._filterOptions.filter, marker.source)) {
return true;
}
if (!!marker.relatedInformation && marker.relatedInformation.some(r =>
!!FilterOptions._filter(this._filterOptions.filter, paths.basename(r.resource.fsPath)) || !
!FilterOptions._filter(this._filterOptions.filter, r.message))) {
return true;
}
return false;
}
......
......@@ -18,7 +18,7 @@ import { IEditorGroupService } from 'vs/workbench/services/group/common/groupSer
import { Panel } from 'vs/workbench/browser/panel';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import Constants from 'vs/workbench/parts/markers/electron-browser/constants';
import { Marker, Resource } from 'vs/workbench/parts/markers/electron-browser/markersModel';
import { Marker, ResourceMarkers, RelatedInformation } from 'vs/workbench/parts/markers/electron-browser/markersModel';
import { Controller } from 'vs/workbench/parts/markers/electron-browser/markersTreeController';
import * as Viewer from 'vs/workbench/parts/markers/electron-browser/markersTreeViewer';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
......@@ -134,25 +134,20 @@ export class MarkersPanel extends Panel {
}
public openFileAtElement(element: any, preserveFocus: boolean, sideByside: boolean, pinned: boolean): boolean {
if (element instanceof Marker) {
const marker: Marker = element;
/* __GDPR__
"problems.marker.opened" : {
"source" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('problems.marker.opened', { source: marker.raw.source });
const { resource, selection } = element instanceof Marker ? { resource: element.resource, selection: element.range } :
element instanceof RelatedInformation ? { resource: element.relatedInformation.resource, selection: element.relatedInformation } : { resource: null, selection: null };
if (resource && selection) {
this.editorService.openEditor({
resource: marker.resource,
resource,
options: {
selection: marker.range,
selection,
preserveFocus,
pinned,
revealIfVisible: true
},
}, sideByside).done(editor => {
if (editor && preserveFocus) {
this.rangeHighlightDecorations.highlightRange(marker, <ICodeEditor>editor.getControl());
this.rangeHighlightDecorations.highlightRange({ resource, range: selection }, <ICodeEditor>editor.getControl());
} else {
this.rangeHighlightDecorations.removeHighlightRange();
}
......@@ -195,7 +190,7 @@ export class MarkersPanel extends Panel {
this.treeContainer = dom.append(parent, dom.$('.tree-container'));
dom.addClass(this.treeContainer, 'show-file-icons');
const renderer = this.instantiationService.createInstance(Viewer.Renderer);
const dnd = this.instantiationService.createInstance(SimpleFileResourceDragAndDrop, obj => obj instanceof Resource ? obj.uri : void 0);
const dnd = this.instantiationService.createInstance(SimpleFileResourceDragAndDrop, obj => obj instanceof ResourceMarkers ? obj.uri : void 0);
const controller = this.instantiationService.createInstance(Controller);
this.tree = this.instantiationService.createInstance(WorkbenchTree, this.treeContainer, {
dataSource: new Viewer.DataSource(),
......@@ -205,7 +200,6 @@ export class MarkersPanel extends Panel {
accessibilityProvider: new Viewer.MarkersTreeAccessibilityProvider(),
dnd
}, {
indentPixels: 0,
twistiePixels: 20,
ariaLabel: Messages.MARKERS_PANEL_ARIA_LABEL_PROBLEMS_TREE
});
......@@ -333,8 +327,8 @@ export class MarkersPanel extends Panel {
}
}
private getResourceForCurrentActiveResource(): Resource {
let res: Resource = null;
private getResourceForCurrentActiveResource(): ResourceMarkers {
let res: ResourceMarkers = null;
if (this.currentActiveResource) {
this.markersWorkbenchService.markersModel.forEachFilteredResource(resource => {
if (!res && resource.uri.toString() === this.currentActiveResource.toString()) {
......@@ -345,7 +339,7 @@ export class MarkersPanel extends Panel {
return res;
}
private hasSelectedMarkerFor(resource: Resource): boolean {
private hasSelectedMarkerFor(resource: ResourceMarkers): boolean {
let selectedElement = this.tree.getSelection();
if (selectedElement && selectedElement.length > 0) {
if (selectedElement[0] instanceof Marker) {
......@@ -379,7 +373,7 @@ export class MarkersPanel extends Panel {
return super.getActionItem(action);
}
public getFocusElement(): Resource | Marker {
public getFocusElement(): ResourceMarkers | Marker {
return this.tree.getFocus();
}
......
......@@ -12,24 +12,20 @@ import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
import { FileLabel, ResourceLabel } from 'vs/workbench/browser/labels';
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
import { IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers';
import { MarkersModel, Resource, Marker } from 'vs/workbench/parts/markers/electron-browser/markersModel';
import { MarkersModel, ResourceMarkers, Marker, ResourceData, RelatedInformation, NodeWithId } from 'vs/workbench/parts/markers/electron-browser/markersModel';
import Messages from 'vs/workbench/parts/markers/electron-browser/messages';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { attachBadgeStyler } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IDisposable } from 'vs/base/common/lifecycle';
interface IAnyResourceTemplateData {
count: CountBadge;
styler: IDisposable;
}
interface IResourceTemplateData extends IAnyResourceTemplateData {
interface IResourceTemplateData {
resourceLabel: ResourceLabel;
}
interface IFileResourceTemplateData extends IAnyResourceTemplateData {
fileLabel: FileLabel;
interface IProblemResourceTemplateData extends IResourceTemplateData {
count: CountBadge;
styler: IDisposable;
}
interface IMarkerTemplateData {
......@@ -39,30 +35,35 @@ interface IMarkerTemplateData {
lnCol: HTMLElement;
}
interface IRelatedInformationTemplateData {
description: HighlightedLabel;
lnCol: HTMLElement;
}
export class DataSource implements IDataSource {
public getId(tree: ITree, element: MarkersModel | Resource | Marker): string {
public getId(tree: ITree, element: any): string {
if (element instanceof MarkersModel) {
return 'root';
}
if (element instanceof Resource) {
return element.uri.toString();
}
if (element instanceof Marker) {
if (element instanceof NodeWithId) {
return element.id;
}
return '';
}
public hasChildren(tree: ITree, element: any): boolean {
return element instanceof MarkersModel || element instanceof Resource;
return element instanceof MarkersModel || element instanceof ResourceData || (element instanceof Marker && element.resourceRelatedInformation.length > 0);
}
public getChildren(tree: ITree, element: MarkersModel | Resource): Promise {
public getChildren(tree: ITree, element: any): Promise {
if (element instanceof MarkersModel) {
return Promise.as(element.resources);
}
if (element instanceof Resource) {
return Promise.as(element.markers);
if (element instanceof ResourceData) {
return Promise.as(element.data);
}
if (element instanceof Marker && element.resourceRelatedInformation.length > 0) {
return Promise.as(element.resourceRelatedInformation);
}
return null;
}
......@@ -73,9 +74,9 @@ export class DataSource implements IDataSource {
}
export class DataFilter implements IFilter {
public isVisible(tree: ITree, element: Resource | Marker | any): boolean {
if (element instanceof Resource) {
return element.filteredMarkersCount > 0;
public isVisible(tree: ITree, element: any): boolean {
if (element instanceof ResourceMarkers) {
return element.count > 0;
}
if (element instanceof Marker) {
return element.isSelected;
......@@ -86,9 +87,12 @@ export class DataFilter implements IFilter {
export class Renderer implements IRenderer {
private static readonly RESOURCE_TEMPLATE_ID = 'resource-template';
private static readonly FILE_RESOURCE_TEMPLATE_ID = 'file-resource-template';
private static readonly PROBLEM_RESOURCE_TEMPLATE_ID = 'problem-resource-template';
private static readonly PROBLEM_FILE_RESOURCE_TEMPLATE_ID = 'problem-file-resource-template';
private static readonly RELATED_RESOURCE_TEMPLATE_ID = 'related-resource-template';
private static readonly RELATED_FILE_RESOURCE_TEMPLATE_ID = 'related-file-resource-template';
private static readonly MARKER_TEMPLATE_ID = 'marker-template';
private static readonly RELATED_INFORMATION_TEMPLATE_ID = 'related-info-template';
constructor(
@IInstantiationService private instantiationService: IInstantiationService,
......@@ -101,35 +105,63 @@ export class Renderer implements IRenderer {
}
public getTemplateId(tree: ITree, element: any): string {
if (element instanceof Resource) {
if ((<Resource>element).uri.scheme === network.Schemas.file || (<Resource>element).uri.scheme === network.Schemas.untitled) {
return Renderer.FILE_RESOURCE_TEMPLATE_ID;
if (element instanceof ResourceMarkers) {
if ((element).uri.scheme === network.Schemas.file || (<ResourceMarkers>element).uri.scheme === network.Schemas.untitled) {
return Renderer.PROBLEM_FILE_RESOURCE_TEMPLATE_ID;
} else {
return Renderer.PROBLEM_RESOURCE_TEMPLATE_ID;
}
}
if (element instanceof ResourceData) {
if ((element).uri.scheme === network.Schemas.file || (<ResourceMarkers>element).uri.scheme === network.Schemas.untitled) {
return Renderer.RELATED_FILE_RESOURCE_TEMPLATE_ID;
} else {
return Renderer.RESOURCE_TEMPLATE_ID;
return Renderer.RELATED_RESOURCE_TEMPLATE_ID;
}
}
if (element instanceof Marker) {
return Renderer.MARKER_TEMPLATE_ID;
}
if (element instanceof RelatedInformation) {
return Renderer.RELATED_INFORMATION_TEMPLATE_ID;
}
return '';
}
public renderTemplate(tree: ITree, templateId: string, container: HTMLElement): any {
dom.addClass(container, 'markers-panel-tree-entry');
switch (templateId) {
case Renderer.FILE_RESOURCE_TEMPLATE_ID:
case Renderer.PROBLEM_FILE_RESOURCE_TEMPLATE_ID:
return this.renderProblemFileResourceTemplate(container);
case Renderer.PROBLEM_RESOURCE_TEMPLATE_ID:
return this.renderProblemResourceTemplate(container);
case Renderer.RELATED_FILE_RESOURCE_TEMPLATE_ID:
return this.renderFileResourceTemplate(container);
case Renderer.RESOURCE_TEMPLATE_ID:
case Renderer.RELATED_RESOURCE_TEMPLATE_ID:
return this.renderResourceTemplate(container);
case Renderer.MARKER_TEMPLATE_ID:
return this.renderMarkerTemplate(container);
case Renderer.RELATED_INFORMATION_TEMPLATE_ID:
return this.renderRelatedInformationTemplate(container);
}
}
private renderFileResourceTemplate(container: HTMLElement): IFileResourceTemplateData {
const data: IFileResourceTemplateData = Object.create(null);
private renderFileResourceTemplate(container: HTMLElement): IResourceTemplateData {
const data: IProblemResourceTemplateData = Object.create(null);
const resourceLabelContainer = dom.append(container, dom.$('.resource-label-container'));
data.fileLabel = this.instantiationService.createInstance(FileLabel, resourceLabelContainer, { supportHighlights: true });
data.resourceLabel = this.instantiationService.createInstance(FileLabel, resourceLabelContainer, { supportHighlights: true });
return data;
}
private renderResourceTemplate(container: HTMLElement): IResourceTemplateData {
const data: IProblemResourceTemplateData = Object.create(null);
const resourceLabelContainer = dom.append(container, dom.$('.resource-label-container'));
data.resourceLabel = this.instantiationService.createInstance(ResourceLabel, resourceLabelContainer, { supportHighlights: true });
return data;
}
private renderProblemFileResourceTemplate(container: HTMLElement): IProblemResourceTemplateData {
const data = <IProblemResourceTemplateData>this.renderFileResourceTemplate(container);
const badgeWrapper = dom.append(container, dom.$('.count-badge-wrapper'));
data.count = new CountBadge(badgeWrapper);
......@@ -138,10 +170,8 @@ export class Renderer implements IRenderer {
return data;
}
private renderResourceTemplate(container: HTMLElement): IResourceTemplateData {
const data: IResourceTemplateData = Object.create(null);
const resourceLabelContainer = dom.append(container, dom.$('.resource-label-container'));
data.resourceLabel = this.instantiationService.createInstance(ResourceLabel, resourceLabelContainer, { supportHighlights: true });
private renderProblemResourceTemplate(container: HTMLElement): IProblemResourceTemplateData {
const data = <IProblemResourceTemplateData>this.renderResourceTemplate(container);
const badgeWrapper = dom.append(container, dom.$('.count-badge-wrapper'));
data.count = new CountBadge(badgeWrapper);
......@@ -159,23 +189,36 @@ export class Renderer implements IRenderer {
return data;
}
private renderRelatedInformationTemplate(container: HTMLElement): IRelatedInformationTemplateData {
const data: IRelatedInformationTemplateData = Object.create(null);
data.description = new HighlightedLabel(dom.append(container, dom.$('.marker-description')));
data.lnCol = dom.append(container, dom.$('span.marker-line'));
return data;
}
public renderElement(tree: ITree, element: any, templateId: string, templateData: any): void {
switch (templateId) {
case Renderer.FILE_RESOURCE_TEMPLATE_ID:
case Renderer.RESOURCE_TEMPLATE_ID:
return this.renderResourceElement(tree, <Resource>element, templateData);
case Renderer.PROBLEM_FILE_RESOURCE_TEMPLATE_ID:
case Renderer.PROBLEM_RESOURCE_TEMPLATE_ID:
case Renderer.RELATED_FILE_RESOURCE_TEMPLATE_ID:
case Renderer.RELATED_RESOURCE_TEMPLATE_ID:
return this.renderResourceElement(tree, <ResourceData<any>>element, templateData);
case Renderer.MARKER_TEMPLATE_ID:
return this.renderMarkerElement(tree, (<Marker>element), templateData);
case Renderer.RELATED_INFORMATION_TEMPLATE_ID:
return this.renderRelatedInformationElement(tree, (<RelatedInformation>element), templateData);
}
}
private renderResourceElement(tree: ITree, element: Resource, templateData: IAnyResourceTemplateData) {
if ((<IFileResourceTemplateData>templateData).fileLabel) {
(<IFileResourceTemplateData>templateData).fileLabel.setFile(element.uri, { matches: element.uriMatches });
} else if ((<IResourceTemplateData>templateData).resourceLabel) {
(<IResourceTemplateData>templateData).resourceLabel.setLabel({ name: element.name, description: element.uri.toString(), resource: element.uri }, { matches: element.uriMatches });
private renderResourceElement(tree: ITree, element: ResourceData<any>, templateData: IResourceTemplateData | IProblemResourceTemplateData) {
if (templateData.resourceLabel instanceof FileLabel) {
templateData.resourceLabel.setFile(element.uri, { matches: element.uriMatches });
} else {
templateData.resourceLabel.setLabel({ name: element.name, description: element.uri.toString(), resource: element.uri }, { matches: element.uriMatches });
}
if ((<IProblemResourceTemplateData>templateData).count) {
(<IProblemResourceTemplateData>templateData).count.setCount(element.count);
}
templateData.count.setCount(element.filteredMarkersCount);
}
private renderMarkerElement(tree: ITree, element: Marker, templateData: IMarkerTemplateData) {
......@@ -190,6 +233,12 @@ export class Renderer implements IRenderer {
templateData.lnCol.textContent = Messages.MARKERS_PANEL_AT_LINE_COL_NUMBER(marker.startLineNumber, marker.startColumn);
}
private renderRelatedInformationElement(tree: ITree, element: RelatedInformation, templateData: IRelatedInformationTemplateData) {
templateData.description.set(element.relatedInformation.message, element.matches);
templateData.description.element.title = element.relatedInformation.message;
templateData.lnCol.textContent = Messages.MARKERS_PANEL_AT_LINE_COL_NUMBER(element.relatedInformation.startLineNumber, element.relatedInformation.startColumn);
}
private static iconClassNameFor(element: IMarker): string {
switch (element.severity) {
case MarkerSeverity.Hint:
......@@ -205,15 +254,16 @@ export class Renderer implements IRenderer {
}
public disposeTemplate(tree: ITree, templateId: string, templateData: any): void {
if (templateId === Renderer.FILE_RESOURCE_TEMPLATE_ID) {
(<IFileResourceTemplateData>templateData).fileLabel.dispose();
(<IFileResourceTemplateData>templateData).styler.dispose();
} else if (templateId === Renderer.RESOURCE_TEMPLATE_ID) {
(<IResourceTemplateData>templateData).resourceLabel.dispose();
(<IResourceTemplateData>templateData).styler.dispose();
if (templateId === Renderer.PROBLEM_RESOURCE_TEMPLATE_ID || templateId === Renderer.PROBLEM_FILE_RESOURCE_TEMPLATE_ID) {
(<IProblemResourceTemplateData>templateData).resourceLabel.dispose();
(<IProblemResourceTemplateData>templateData).styler.dispose();
} else if (templateId === Renderer.RELATED_RESOURCE_TEMPLATE_ID || templateId === Renderer.RELATED_FILE_RESOURCE_TEMPLATE_ID) {
(<IProblemResourceTemplateData>templateData).resourceLabel.dispose();
} else if (templateId === Renderer.MARKER_TEMPLATE_ID) {
(<IMarkerTemplateData>templateData).description.dispose();
(<IMarkerTemplateData>templateData).source.dispose();
} else if (templateId === Renderer.RELATED_INFORMATION_TEMPLATE_ID) {
(<IRelatedInformationTemplateData>templateData).description.dispose();
}
}
}
......@@ -221,11 +271,17 @@ export class Renderer implements IRenderer {
export class MarkersTreeAccessibilityProvider implements IAccessibilityProvider {
public getAriaLabel(tree: ITree, element: any): string {
if (element instanceof Resource) {
return Messages.MARKERS_TREE_ARIA_LABEL_RESOURCE(element.name, element.filteredMarkersCount);
if (element instanceof ResourceMarkers) {
return Messages.MARKERS_TREE_ARIA_LABEL_RESOURCE(element.name, element.count);
}
if (element instanceof Marker) {
return Messages.MARKERS_TREE_ARIA_LABEL_MARKER(element.raw);
return Messages.MARKERS_TREE_ARIA_LABEL_MARKER(element);
}
if (element instanceof ResourceData) {
return element.name;
}
if (element instanceof RelatedInformation) {
return Messages.MARKERS_TREE_ARIA_LABEL_RELATED_INFORMATION(element.relatedInformation);
}
return null;
}
......
......@@ -5,7 +5,8 @@
'use strict';
import * as nls from 'vs/nls';
import { IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers';
import { MarkerSeverity, IRelatedInformation } from 'vs/platform/markers/common/markers';
import { Marker } from './markersModel';
export default class Messages {
......@@ -40,23 +41,24 @@ export default class Messages {
public static readonly MARKERS_PANEL_AT_LINE_COL_NUMBER = (ln: number, col: number): string => { return nls.localize('markers.panel.at.ln.col.number', "({0}, {1})", '' + ln, '' + col); };
public static readonly MARKERS_TREE_ARIA_LABEL_RESOURCE = (fileName: string, noOfProblems: number): string => { return nls.localize('problems.tree.aria.label.resource', "{0} with {1} problems", fileName, noOfProblems); };
public static readonly MARKERS_TREE_ARIA_LABEL_MARKER = (marker: IMarker): string => {
switch (marker.severity) {
public static readonly MARKERS_TREE_ARIA_LABEL_MARKER = (marker: Marker): string => {
const relatedInformationMessage = marker.resourceRelatedInformation.length ? nls.localize('problems.tree.aria.label.marker.relatedInformation', " This problem has references to {0} locations.", marker.resourceRelatedInformation.reduce((count, r) => count + r.count, 0)) : '';
switch (marker.raw.severity) {
case MarkerSeverity.Error:
return marker.source ? nls.localize('problems.tree.aria.label.error.marker', "Error generated by {0}: {1} at line {2} and character {3}", marker.source, marker.message, marker.startLineNumber, marker.startColumn)
: nls.localize('problems.tree.aria.label.error.marker.nosource', "Error: {0} at line {1} and character {2}", marker.message, marker.startLineNumber, marker.startColumn);
return marker.raw.source ? nls.localize('problems.tree.aria.label.error.marker', "Error generated by {0}: {1} at line {2} and character {3}.{4}", marker.raw.source, marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage)
: nls.localize('problems.tree.aria.label.error.marker.nosource', "Error: {0} at line {1} and character {2}.{3}", marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage);
case MarkerSeverity.Warning:
return marker.source ? nls.localize('problems.tree.aria.label.warning.marker', "Warning generated by {0}: {1} at line {2} and character {3}", marker.source, marker.message, marker.startLineNumber, marker.startColumn)
: nls.localize('problems.tree.aria.label.warning.marker.nosource', "Warning: {0} at line {1} and character {2}", marker.message, marker.startLineNumber, marker.startColumn);
return marker.raw.source ? nls.localize('problems.tree.aria.label.warning.marker', "Warning generated by {0}: {1} at line {2} and character {3}.{4}", marker.raw.source, marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage)
: nls.localize('problems.tree.aria.label.warning.marker.nosource', "Warning: {0} at line {1} and character {2}.{3}", marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage, relatedInformationMessage);
case MarkerSeverity.Info:
return marker.source ? nls.localize('problems.tree.aria.label.info.marker', "Info generated by {0}: {1} at line {2} and character {3}", marker.source, marker.message, marker.startLineNumber, marker.startColumn)
: nls.localize('problems.tree.aria.label.info.marker.nosource', "Info: {0} at line {1} and character {2}", marker.message, marker.startLineNumber, marker.startColumn);
return marker.raw.source ? nls.localize('problems.tree.aria.label.info.marker', "Info generated by {0}: {1} at line {2} and character {3}.{4}", marker.raw.source, marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage)
: nls.localize('problems.tree.aria.label.info.marker.nosource', "Info: {0} at line {1} and character {2}.{3}", marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage);
default:
return marker.source ? nls.localize('problems.tree.aria.label.marker', "Problem generated by {0}: {1} at line {2} and character {3}", marker.source, marker.message, marker.startLineNumber, marker.startColumn)
: nls.localize('problems.tree.aria.label.marker.nosource', "Problem: {0} at line {1} and character {2}", marker.message, marker.startLineNumber, marker.startColumn);
return marker.raw.source ? nls.localize('problems.tree.aria.label.marker', "Problem generated by {0}: {1} at line {2} and character {3}.{4}", marker.raw.source, marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage)
: nls.localize('problems.tree.aria.label.marker.nosource', "Problem: {0} at line {1} and character {2}.{3}", marker.raw.message, marker.raw.startLineNumber, marker.raw.startColumn, relatedInformationMessage);
}
}
public static readonly MARKERS_TREE_ARIA_LABEL_RELATED_INFORMATION = (relatedInformation: IRelatedInformation): string => nls.localize('problems.tree.aria.label.relatedinfo.message', "{0} at line {1} and character {2}", relatedInformation.message, relatedInformation.startLineNumber, relatedInformation.startColumn);
public static SHOW_ERRORS_WARNINGS_ACTION_LABEL: string = nls.localize('errors.warnings.show.label', "Show Errors and Warnings");
}
......@@ -8,19 +8,19 @@
import * as assert from 'assert';
import URI from 'vs/base/common/uri';
import { IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers';
import { MarkersModel, Marker, Resource } from 'vs/workbench/parts/markers/electron-browser/markersModel';
import { MarkersModel, Marker, ResourceMarkers } from 'vs/workbench/parts/markers/electron-browser/markersModel';
class TestMarkersModel extends MarkersModel {
get filteredResources(): Resource[] {
let res: Resource[] = [];
get filteredResources(): ResourceMarkers[] {
let res: ResourceMarkers[] = [];
this.forEachFilteredResource(resource => res.push(resource));
return res;
}
static compare(a: any, b: any): number {
if (a instanceof Resource && b instanceof Resource) {
return Resource.compare(a, b);
if (a instanceof ResourceMarkers && b instanceof ResourceMarkers) {
return ResourceMarkers.compare(a, b);
}
if (a instanceof Marker && b instanceof Marker) {
return Marker.compare(a, b);
......@@ -45,22 +45,22 @@ suite('MarkersModel Test', () => {
assert.equal(4, actuals.length);
assert.ok(compareResource(actuals[0], 'res1'));
assert.equal(2, actuals[0].markers.length);
assert.ok(hasMarker(actuals[0].markers, marker1));
assert.ok(hasMarker(actuals[0].markers, marker3));
assert.equal(2, actuals[0].data.length);
assert.ok(hasMarker(actuals[0].data, marker1));
assert.ok(hasMarker(actuals[0].data, marker3));
assert.ok(compareResource(actuals[1], 'res2'));
assert.equal(2, actuals[1].markers.length);
assert.ok(hasMarker(actuals[1].markers, marker2));
assert.ok(hasMarker(actuals[1].markers, marker6));
assert.equal(2, actuals[1].data.length);
assert.ok(hasMarker(actuals[1].data, marker2));
assert.ok(hasMarker(actuals[1].data, marker6));
assert.ok(compareResource(actuals[2], 'res3'));
assert.equal(1, actuals[2].markers.length);
assert.ok(hasMarker(actuals[2].markers, marker4));
assert.equal(1, actuals[2].data.length);
assert.ok(hasMarker(actuals[2].data, marker4));
assert.ok(compareResource(actuals[3], 'res4'));
assert.equal(1, actuals[3].markers.length);
assert.ok(hasMarker(actuals[3].markers, marker5));
assert.equal(1, actuals[3].data.length);
assert.ok(hasMarker(actuals[3].data, marker5));
});
test('sort palces resources with no errors at the end', function () {
......@@ -119,7 +119,7 @@ suite('MarkersModel Test', () => {
let marker15 = anErrorWithRange(8, 2, 8, 4);
let testObject = new TestMarkersModel([marker1, marker2, marker3, marker4, marker5, marker6, marker7, marker8, marker9, marker10, marker11, marker12, marker13, marker14, marker15]);
let actuals = testObject.filteredResources[0].markers.sort(TestMarkersModel.compare);
let actuals = testObject.filteredResources[0].data.sort(TestMarkersModel.compare);
assert.equal(actuals[0].raw, marker6);
assert.equal(actuals[1].raw, marker14);
......@@ -153,7 +153,7 @@ suite('MarkersModel Test', () => {
}).length === 1;
}
function compareResource(a: Resource, b: string): boolean {
function compareResource(a: ResourceMarkers, b: string): boolean {
return a.uri.toString() === URI.file(b).toString();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册