/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { assign } from 'vs/base/common/objects';
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IssueType, ISettingSearchResult } from 'vs/platform/issue/common/issue';
export interface IssueReporterData {
issueType?: IssueType;
issueDescription?: string;
versionInfo?: any;
systemInfo?: any;
processInfo?: any;
workspaceInfo?: any;
includeSystemInfo?: boolean;
includeWorkspaceInfo?: boolean;
includeProcessInfo?: boolean;
includeExtensions?: boolean;
includeSearchedExtensions?: boolean;
includeSettingsSearchDetails?: boolean;
numberOfThemeExtesions?: number;
allExtensions?: ILocalExtension[];
enabledNonThemeExtesions?: ILocalExtension[];
extensionsDisabled?: boolean;
fileOnExtension?: boolean;
selectedExtension?: ILocalExtension;
actualSearchResults?: ISettingSearchResult[];
query?: string;
filterResultCount?: number;
}
export class IssueReporterModel {
private _data: IssueReporterData;
constructor(initialData?: IssueReporterData) {
const defaultData = {
includeSystemInfo: true,
includeWorkspaceInfo: true,
includeProcessInfo: true,
includeExtensions: true,
includeSearchedExtensions: true,
includeSettingsSearchDetails: true
};
this._data = initialData ? assign(defaultData, initialData) : defaultData;
}
getData(): IssueReporterData {
return this._data;
}
update(newData: IssueReporterData): void {
assign(this._data, newData);
}
serialize(): string {
return `
Issue Type: ${this.getIssueTypeTitle()}
${this._data.issueDescription}
${this.getExtensionVersion()}
VS Code version: ${this._data.versionInfo && this._data.versionInfo.vscodeVersion}
OS version: ${this._data.versionInfo && this._data.versionInfo.os}
${this.getInfos()}
`;
}
fileOnExtension(): boolean {
const fileOnExtensionSupported = this._data.issueType === IssueType.Bug
|| this._data.issueType === IssueType.PerformanceIssue
|| this._data.issueType === IssueType.FeatureRequest;
return !!(fileOnExtensionSupported && this._data.fileOnExtension);
}
private getExtensionVersion(): string {
if (this.fileOnExtension() && this._data.selectedExtension) {
return `\nExtension version: ${this._data.selectedExtension.manifest.version}`;
} else {
return '';
}
}
private getIssueTypeTitle(): string {
if (this._data.issueType === IssueType.Bug) {
return 'Bug';
} else if (this._data.issueType === IssueType.PerformanceIssue) {
return 'Performance Issue';
} else if (this._data.issueType === IssueType.SettingsSearchIssue) {
return 'Settings Search Issue';
} else {
return 'Feature Request';
}
}
private getInfos(): string {
let info = '';
if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) {
if (this._data.includeSystemInfo) {
info += this.generateSystemInfoMd();
}
}
if (this._data.issueType === IssueType.PerformanceIssue) {
if (this._data.includeProcessInfo) {
info += this.generateProcessInfoMd();
}
if (this._data.includeWorkspaceInfo) {
info += this.generateWorkspaceInfoMd();
}
}
if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) {
if (this._data.includeExtensions) {
info += this.generateExtensionsMd();
}
}
if (this._data.issueType === IssueType.SettingsSearchIssue) {
if (this._data.includeSearchedExtensions) {
info += this.generateExtensionsMd();
}
if (this._data.includeSettingsSearchDetails) {
info += this.generateSettingSearchResultsMd();
info += '\n' + this.generateSettingsSearchResultDetailsMd();
}
}
return info;
}
private generateSystemInfoMd(): string {
let md = `
System Info
|Item|Value|
|---|---|
`;
Object.keys(this._data.systemInfo).forEach(k => {
const data = typeof this._data.systemInfo[k] === 'object'
? Object.keys(this._data.systemInfo[k]).map(key => `${key}: ${this._data.systemInfo[k][key]}`).join('
')
: this._data.systemInfo[k];
md += `|${k}|${data}|\n`;
});
md += '\n ';
return md;
}
private generateProcessInfoMd(): string {
return `
Process Info
\`\`\`
${this._data.processInfo}
\`\`\`
`;
}
private generateWorkspaceInfoMd(): string {
return `
Workspace Info
\`\`\`
${this._data.workspaceInfo};
\`\`\`
`;
}
private generateExtensionsMd(): string {
if (this._data.extensionsDisabled) {
return 'Extensions disabled';
}
const themeExclusionStr = this._data.numberOfThemeExtesions ? `\n(${this._data.numberOfThemeExtesions} theme extensions excluded)` : '';
if (!this._data.enabledNonThemeExtesions) {
return 'Extensions: none' + themeExclusionStr;
}
let tableHeader = `Extension|Author (truncated)|Version
---|---|---`;
const table = this._data.enabledNonThemeExtesions.map(e => {
return `${e.manifest.name}|${e.manifest.publisher.substr(0, 3)}|${e.manifest.version}`;
}).join('\n');
return `Extensions (${this._data.enabledNonThemeExtesions.length})
${tableHeader}
${table}
${themeExclusionStr}
`;
}
private generateSettingsSearchResultDetailsMd(): string {
return `
Query: ${this._data.query}
Literal matches: ${this._data.filterResultCount}`;
}
private generateSettingSearchResultsMd(): string {
if (!this._data.actualSearchResults) {
return '';
}
if (!this._data.actualSearchResults.length) {
return `No fuzzy results`;
}
let tableHeader = `Setting|Extension|Score
---|---|---`;
const table = this._data.actualSearchResults.map(setting => {
return `${setting.key}|${setting.extensionId}|${String(setting.score).slice(0, 5)}`;
}).join('\n');
return `Results
${tableHeader}
${table}
`;
}
}