diff --git a/README.md b/README.md index 9cbe243907..aa9bb5137e 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,8 @@ to file an issue on our GitHub repository: Make sure to fill in the information that is requested in the issue template as it will help us investigate the problem more quickly. +> Note To automatically create a bug report from within the extension run the *"Report a problem on GitHub"* command. Some basic information about your instance and powershell versions will be collected and inserted into a new GitHub issue. + ### 2. Capture verbose logs and send them to us If you're having an issue with crashing or other erratic behavior, add the following diff --git a/package.json b/package.json index 8e5be1d9e8..88389be05d 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,11 @@ "title": "Open PowerShell Extension Logs Folder", "category": "PowerShell" }, + { + "command": "PowerShell.GenerateBugReport", + "title": "Upload Bug Report to Github", + "category": "PowerShell" + }, { "command": "PowerShell.OpenInISE", "title": "Open Current File in PowerShell ISE", @@ -399,6 +404,11 @@ "default": true, "description": "Loads user and system-wide PowerShell profiles (profile.ps1 and Microsoft.VSCode_profile.ps1) into the PowerShell session. This affects IntelliSense and interactive script execution, but it does not affect the debugger." }, + "powershell.bugReporting.project": { + "type": "string", + "default": "https://github.com/PowerShell/vscode-powershell", + "description": "Specifies the url of the GitHub project in which to generate bug reports." + }, "powershell.scriptAnalysis.enable": { "type": "boolean", "default": true, diff --git a/src/features/GenerateBugReport.ts b/src/features/GenerateBugReport.ts new file mode 100644 index 0000000000..33aeb96f69 --- /dev/null +++ b/src/features/GenerateBugReport.ts @@ -0,0 +1,126 @@ +import vscode = require('vscode'); +import { SessionManager } from '../session'; +import cp = require('child_process'); +import Settings = require('../settings'); + +const os = require("os"); + +import { IFeature, LanguageClient } from '../feature'; +// import { IExtensionManagementService, LocalExtensionType, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; + +const extensionId: string = 'ms-vscode.PowerShell'; +const extensionVersion: string = vscode.extensions.getExtension(extensionId).packageJSON.version; + +const queryStringPrefix: string = '?' + +var settings = Settings.load(); +let project = settings.bugReporting.project; + +const issuesUrl: string = `${project}/issues/new` + +var extensions = vscode.extensions.all.filter(element => element.packageJSON.isBuiltin == false).sort((leftside, rightside): number => { + if (leftside.packageJSON.name.toLowerCase() < rightside.packageJSON.name.toLowerCase()) return -1; + if (leftside.packageJSON.name.toLowerCase() > rightside.packageJSON.name.toLowerCase()) return 1; + return 0; +}) + +export class GenerateBugReportFeature implements IFeature { + + private command: vscode.Disposable; + private powerShellProcess: cp.ChildProcess; + + constructor(private sessionManager: SessionManager) { + this.command = vscode.commands.registerCommand('PowerShell.GenerateBugReport', () => { + + var body = encodeURIComponent(`## Issue Description ## + +I am experiencing a problem with... + +## Attached Logs ## + +Follow the instructions in the [README](https://github.com/PowerShell/vscode-powershell#reporting-problems) about capturing and sending logs. + +## Environment Information ## + +### Visual Studio Code ### + +| Name | Version | +| --- | --- | +| Operating System | ${os.type() + ' ' + os.arch() + ' ' + os.release()} | +| VSCode | ${vscode.version}| +| PowerShell Extension Version | ${extensionVersion} | + +### PowerShell Information ### + +${this.getRuntimeInfo()} + +### Visual Studio Code Extensions ### + +
Visual Studio Code Extensions(Click to Expand) + +${this.generateExtensionTable(extensions)} +
+ +`); + + var encodedBody = encodeURIComponent(body); + var fullUrl = `${issuesUrl}${queryStringPrefix}body=${encodedBody}`; + vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(fullUrl)); + + }); + + } + + + public setLanguageClient(LanguageClient: LanguageClient) { + // Not needed for this feature. + } + + public dispose() { + this.command.dispose(); + } + + + private generateExtensionTable(extensions): string { + if (!extensions.length) { + return 'none'; + } + + let tableHeader = `|Extension|Author|Version|\n|---|---|---|`; + const table = extensions.map(e => { + + if (e.packageJSON.isBuiltin == false) { + return `|${e.packageJSON.name}|${e.packageJSON.publisher}|${e.packageJSON.version}|`; + } + }).join('\n'); + + const extensionTable = ` +${tableHeader}\n${table}; +`; + // 2000 chars is browsers de-facto limit for URLs, 400 chars are allowed for other string parts of the issue URL + // http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers + // if (encodeURIComponent(extensionTable).length > 1600) { + // return 'the listing length exceeds browsers\' URL characters limit'; + // } + + return extensionTable; + } + + private getRuntimeInfo() { + + var psOutput; + var powerShellExePath = this.sessionManager.getPowerShellExePath(); + var powerShellArgs = [ + "-NoProfile", + "-Command", + '$PSVersionString = "|Name|Value|\n"; $PSVersionString += "|---|---|\n"; $PSVersionTable.keys | ForEach-Object { $PSVersionString += "|$_|$($PSVersionTable.Item($_))|\n" }; $PSVersionString' + ] + + var spawn = require('child_process').spawnSync; + var child = spawn(powerShellExePath, powerShellArgs); + return child.stdout.toString().replace(';', ','); + + } + +} + diff --git a/src/main.ts b/src/main.ts index 8ccb72bcb4..3df9942bb0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -15,6 +15,7 @@ import { PowerShellLanguageId } from './utils'; import { ConsoleFeature } from './features/Console'; import { ExamplesFeature } from './features/Examples'; import { OpenInISEFeature } from './features/OpenInISE'; +import { GenerateBugReportFeature } from './features/GenerateBugReport'; import { CustomViewsFeature } from './features/CustomViews'; import { ExpandAliasFeature } from './features/ExpandAlias'; import { ShowHelpFeature } from './features/ShowOnlineHelp'; @@ -109,6 +110,7 @@ export function activate(context: vscode.ExtensionContext): void { new ConsoleFeature(), new ExamplesFeature(), new OpenInISEFeature(), + new GenerateBugReportFeature(sessionManager), new ExpandAliasFeature(), new ShowHelpFeature(), new FindModuleFeature(), diff --git a/src/session.ts b/src/session.ts index f6fde9de1f..2cb073d19c 100644 --- a/src/session.ts +++ b/src/session.ts @@ -500,7 +500,7 @@ export class SessionManager implements Middleware { SessionStatus.Failed); } - private getPowerShellExePath(): string { + public getPowerShellExePath(): string { if (!this.sessionSettings.powerShellExePath && this.sessionSettings.developer.powerShellExePath) diff --git a/src/settings.ts b/src/settings.ts index 7934789098..4f9e3a6ad9 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -14,6 +14,10 @@ enum CodeFormattingPreset { Stroustrup } +export interface IBugReportingSettings { + project: string; +} + export interface ICodeFormattingSettings { preset: CodeFormattingPreset; openBraceOnSameLine: boolean; @@ -55,6 +59,7 @@ export interface ISettings { developer?: IDeveloperSettings; codeFormatting?: ICodeFormattingSettings; integratedConsole?: IIntegratedConsoleSettings; + bugReporting?: IBugReportingSettings } export interface IIntegratedConsoleSettings { @@ -67,6 +72,10 @@ export function load(): ISettings { vscode.workspace.getConfiguration( utils.PowerShellLanguageId); + let defaultBugReportingSettings: IBugReportingSettings = { + project: "https://github.com/PowerShell/vscode-powershell" + }; + let defaultScriptAnalysisSettings: IScriptAnalysisSettings = { enable: true, settingsPath: "" @@ -112,7 +121,8 @@ export function load(): ISettings { debugging: configuration.get("debugging", defaultDebuggingSettings), developer: configuration.get("developer", defaultDeveloperSettings), codeFormatting: configuration.get("codeFormatting", defaultCodeFormattingSettings), - integratedConsole: configuration.get("integratedConsole", defaultIntegratedConsoleSettings) + integratedConsole: configuration.get("integratedConsole", defaultIntegratedConsoleSettings), + bugReporting: configuration.get("bugReporting", defaultBugReportingSettings) }; }