Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add command to create an issue from within the extension #2503

Merged
merged 38 commits into from
Sep 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7b1c30d
Add command to create an issue
akshita31 Sep 7, 2018
599794b
use child process promise
akshita31 Sep 8, 2018
afd08ba
Add
akshita31 Sep 8, 2018
6f563df
add mono information
akshita31 Sep 8, 2018
42fa329
Use existing child-process
akshita31 Sep 10, 2018
7876468
refactoring for testing
akshita31 Sep 10, 2018
c2c2e7e
rename
akshita31 Sep 10, 2018
63e1746
Add the unit test
akshita31 Sep 10, 2018
44d4085
Remove package-lock
akshita31 Sep 11, 2018
e548da2
add tests for the observer
akshita31 Sep 11, 2018
7b2ee67
Merge remote-tracking branch 'upstream/master' into bug_generator
akshita31 Sep 11, 2018
440b0e3
add encoding and some structure change
akshita31 Sep 11, 2018
543ad48
make bold
akshita31 Sep 11, 2018
3a7ac64
add encoding and some structure change
akshita31 Sep 11, 2018
aed6f9a
Add the changes
akshita31 Sep 11, 2018
8980a2c
using the openurl observer
akshita31 Sep 12, 2018
d47164a
Modify the tests for the observer
akshita31 Sep 12, 2018
c15eb7d
Rename to report issue
akshita31 Sep 12, 2018
379654c
PR feedback
akshita31 Sep 12, 2018
6537a8d
Add refactoring for the mono options
akshita31 Sep 13, 2018
293c97b
Some more refactoring
akshita31 Sep 13, 2018
3835cfb
Add the global mono information
akshita31 Sep 13, 2018
1a2dcdc
add the mono resolver to the issue creator
akshita31 Sep 14, 2018
834f8d1
small changes
akshita31 Sep 14, 2018
5c5304e
should throw error when not valid
akshita31 Sep 14, 2018
cb72d3f
Do not use mono information interface
akshita31 Sep 14, 2018
5cd3196
using the mono resolver interface
akshita31 Sep 14, 2018
cdb2345
rename
akshita31 Sep 14, 2018
2eee6b7
pass the GetMonoVersion
akshita31 Sep 15, 2018
baed655
Add the environment to the information
akshita31 Sep 15, 2018
053f326
add tests for the mono resolver
akshita31 Sep 15, 2018
f29f892
remove file
akshita31 Sep 15, 2018
2d963c2
Merge branch 'master' into bug_generator
akshita31 Sep 15, 2018
8e55eb4
Rename and add interfaces
akshita31 Sep 17, 2018
0c543b8
using more interfaces
akshita31 Sep 17, 2018
dfc383f
refactor the test
akshita31 Sep 17, 2018
30b3995
soe more changes
akshita31 Sep 17, 2018
61a2efb
Merge branch 'bug_generator' of https://github.com/akshita31/omnishar…
akshita31 Sep 17, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,11 @@
"command": "csharp.listRemoteProcess",
"title": "List processes on remote connection for attach",
"category": "CSharp"
},
{
"command": "csharp.reportIssue",
"title": "Start authoring a new issue on GitHub",
"category": "CSharp"
}
],
"keybindings": [
Expand Down
6 changes: 6 additions & 0 deletions src/constants/CSharpExtensionId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

export const CSharpExtensionId = 'ms-vscode.csharp';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this appears in package.json, can we read it from there instead of redefining it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package json has a publisher name and the name of the extension combining which gives the extension id, but to get access to the package.json we need the extension first and to get the extension we need the extension id. Hence from what I understand there is no way to get the extension id directly from the package.json.

8 changes: 8 additions & 0 deletions src/constants/IGetDotnetInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

export interface IGetDotnetInfo {
(): Promise<string>;
}
8 changes: 8 additions & 0 deletions src/constants/IGetMonoVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

export interface IGetMonoVersion {
(environment: NodeJS.ProcessEnv): Promise<string>;
}
11 changes: 11 additions & 0 deletions src/constants/IMonoResolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { Options } from "../omnisharp/options";
import { MonoInformation } from "./MonoInformation";

export interface IMonoResolver {
getGlobalMonoInfo(options: Options): Promise<MonoInformation>;
}
10 changes: 10 additions & 0 deletions src/constants/MonoInformation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

export interface MonoInformation {
version: string;
path: string;
env: NodeJS.ProcessEnv;
}
6 changes: 5 additions & 1 deletion src/features/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ import { EventStream } from '../EventStream';
import { PlatformInformation } from '../platform';
import CompositeDisposable from '../CompositeDisposable';
import OptionProvider from '../observers/OptionProvider';
import reportIssue from './reportIssue';
import { IMonoResolver } from '../constants/IMonoResolver';
import { getDotnetInfo } from '../utils/getDotnetInfo';

export default function registerCommands(server: OmniSharpServer, platformInfo: PlatformInformation, eventStream: EventStream, optionProvider: OptionProvider): CompositeDisposable {
export default function registerCommands(server: OmniSharpServer, platformInfo: PlatformInformation, eventStream: EventStream, optionProvider: OptionProvider, monoResolver: IMonoResolver): CompositeDisposable {
let disposable = new CompositeDisposable();
disposable.add(vscode.commands.registerCommand('o.restart', () => restartOmniSharp(server)));
disposable.add(vscode.commands.registerCommand('o.pickProjectAndStart', async () => pickProjectAndStart(server, optionProvider)));
Expand All @@ -46,6 +49,7 @@ export default function registerCommands(server: OmniSharpServer, platformInfo:
// Register command for adapter executable command.
disposable.add(vscode.commands.registerCommand('csharp.coreclrAdapterExecutableCommand', async (args) => getAdapterExecutionCommand(platformInfo, eventStream)));
disposable.add(vscode.commands.registerCommand('csharp.clrAdapterExecutableCommand', async (args) => getAdapterExecutionCommand(platformInfo, eventStream)));
disposable.add(vscode.commands.registerCommand('csharp.reportIssue', async () => reportIssue(vscode, eventStream, getDotnetInfo, platformInfo.isValidPlatformForMono(), optionProvider.GetLatestOptions(), monoResolver)));

return new CompositeDisposable(disposable);
}
Expand Down
118 changes: 118 additions & 0 deletions src/features/reportIssue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { vscode } from "../vscodeAdapter";
import { Extension } from "../vscodeAdapter";
import { CSharpExtensionId } from "../constants/CSharpExtensionId";
import { EventStream } from "../EventStream";
import { OpenURL } from "../omnisharp/loggingEvents";
import { Options } from "../omnisharp/options";
import { IMonoResolver } from "../constants/IMonoResolver";
import { IGetDotnetInfo } from "../constants/IGetDotnetInfo";

const issuesUrl = "https://github.com/OmniSharp/omnisharp-vscode/issues/new";

export default async function reportIssue(vscode: vscode, eventStream: EventStream, getDotnetInfo: IGetDotnetInfo, isValidPlatformForMono: boolean, options: Options, monoResolver: IMonoResolver) {
const dotnetInfo = await getDotnetInfo();
const monoInfo = await getMonoIfPlatformValid(isValidPlatformForMono, options, monoResolver);
let extensions = getInstalledExtensions(vscode);
let csharpExtVersion = getCsharpExtensionVersion(vscode);

const body = encodeURIComponent(`## Issue Description ##
## Steps to Reproduce ##

## Expected Behavior ##

## Actual Behavior ##

## Logs ##

### OmniSharp log ###
<details>Post the output from Output-->OmniSharp log here</details>

### C# log ###
<details>Post the output from Output-->C# here</details>

## Environment information ##

**VSCode version**: ${vscode.version}
**C# Extension**: ${csharpExtVersion}

${monoInfo}
<details><summary>Dotnet Information</summary>
${dotnetInfo}</details>
<details><summary>Visual Studio Code Extensions</summary>
${generateExtensionTable(extensions)}
</details>
`);

const encodedBody = encodeURIComponent(body);
const queryStringPrefix: string = "?";
const fullUrl = `${issuesUrl}${queryStringPrefix}body=${encodedBody}`;
eventStream.post(new OpenURL(fullUrl));
}

function sortExtensions(a: Extension<any>, b: Extension<any>): number {

if (a.packageJSON.name.toLowerCase() < b.packageJSON.name.toLowerCase()) {
return -1;
}
if (a.packageJSON.name.toLowerCase() > b.packageJSON.name.toLowerCase()) {
return 1;
}
return 0;
}

function generateExtensionTable(extensions: Extension<any>[]) {
if (extensions.length <= 0) {
return "none";
}

const tableHeader = `|Extension|Author|Version|\n|---|---|---|`;
const table = extensions.map((e) => `|${e.packageJSON.name}|${e.packageJSON.publisher}|${e.packageJSON.version}|`).join("\n");

const extensionTable = `
${tableHeader}\n${table};
`;

return extensionTable;
}

async function getMonoIfPlatformValid(isValidPlatformForMono: boolean, options: Options, monoResolver: IMonoResolver): Promise<string> {
if (isValidPlatformForMono) {
let monoVersion: string;
try {
let globalMonoInfo = await monoResolver.getGlobalMonoInfo(options);
if (globalMonoInfo) {
monoVersion = `OmniSharp using global mono :${globalMonoInfo.version}`;
}
else {
monoVersion = `OmniSharp using built-in mono`;
}
}
catch (error) {
monoVersion = `There is a problem with running OmniSharp on mono: ${error}`;
}

return `<details><summary>Mono Information</summary>
${monoVersion}</details>`;
}

return "";
}



function getInstalledExtensions(vscode: vscode) {
let extensions = vscode.extensions.all
.filter(extension => extension.packageJSON.isBuiltin === false);

return extensions.sort(sortExtensions);
}

function getCsharpExtensionVersion(vscode: vscode): string {
const extension = vscode.extensions.getExtension(CSharpExtensionId);
return extension.packageJSON.version;
}
7 changes: 6 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ import DotNetTestChannelObserver from './observers/DotnetTestChannelObserver';
import DotNetTestLoggerObserver from './observers/DotnetTestLoggerObserver';
import { ShowOmniSharpConfigChangePrompt } from './observers/OptionChangeObserver';
import createOptionStream from './observables/CreateOptionStream';
import { CSharpExtensionId } from './constants/CSharpExtensionId';
import { OpenURLObserver } from './observers/OpenURLObserver';

export async function activate(context: vscode.ExtensionContext): Promise<CSharpExtensionExports> {

const extensionId = 'ms-vscode.csharp';
const extensionId = CSharpExtensionId;
const extension = vscode.extensions.getExtension<CSharpExtensionExports>(extensionId);
const extensionVersion = extension.packageJSON.version;
const aiKey = extension.packageJSON.contributes.debuggers[0].aiKey;
Expand Down Expand Up @@ -91,6 +93,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<CSharp
let projectStatusBarObserver = new ProjectStatusBarObserver(projectStatusBar);
eventStream.subscribe(projectStatusBarObserver.post);

let openURLObserver = new OpenURLObserver(vscode);
eventStream.subscribe(openURLObserver.post);

const debugMode = false;
if (debugMode) {
let omnisharpDebugModeLoggerObserver = new OmnisharpDebugModeLoggerObserver(omnisharpChannel);
Expand Down
22 changes: 22 additions & 0 deletions src/observers/OpenURLObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { vscode } from "../vscodeAdapter";
import { BaseEvent, OpenURL } from "../omnisharp/loggingEvents";

export class OpenURLObserver {

constructor(private vscode: vscode) {
}

public post = (event: BaseEvent) => {
switch (event.constructor.name) {
case OpenURL.name:
let url = (<OpenURL>event).url;
this.vscode.commands.executeCommand("vscode.open", this.vscode.Uri.parse(url));
break;
}
}
}
54 changes: 54 additions & 0 deletions src/omnisharp/OmniSharpMonoResolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { satisfies } from 'semver';
import * as path from 'path';
import { Options } from './options';
import { IMonoResolver } from '../constants/IMonoResolver';
import { MonoInformation } from '../constants/MonoInformation';
import { IGetMonoVersion } from '../constants/IGetMonoVersion';

export class OmniSharpMonoResolver implements IMonoResolver {
private minimumMonoVersion = "5.8.1";
constructor(private getMonoVersion: IGetMonoVersion) {
}

private async configureEnvironmentAndGetInfo(options: Options): Promise<MonoInformation> {
let env = { ...process.env };
let monoPath: string;
if (options.useGlobalMono !== "never" && options.monoPath !== undefined) {
env['PATH'] = path.join(options.monoPath, 'bin') + path.delimiter + env['PATH'];
env['MONO_GAC_PREFIX'] = options.monoPath;
monoPath = options.monoPath;
}

let version = await this.getMonoVersion(env);

return {
version,
path: monoPath,
env
};
}

public async getGlobalMonoInfo(options: Options): Promise<MonoInformation> {
let monoInfo = await this.configureEnvironmentAndGetInfo(options);
let isValid = monoInfo.version && satisfies(monoInfo.version, `>=${this.minimumMonoVersion}`);

if (options.useGlobalMono === "always") {
if (!isValid) {
throw new Error(`Cannot start OmniSharp because Mono version >=${this.minimumMonoVersion} is required.`);
}

return monoInfo;
}
else if (options.useGlobalMono === "auto" && isValid) {
return monoInfo;
}

return undefined;
}
}

7 changes: 5 additions & 2 deletions src/omnisharp/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import Disposable from '../Disposable';
import OptionProvider from '../observers/OptionProvider';
import trackVirtualDocuments from '../features/virtualDocumentTracker';
import { StructureProvider } from '../features/structureProvider';
import { OmniSharpMonoResolver } from './OmniSharpMonoResolver';
import { getMonoVersion } from '../utils/getMonoVersion';

export let omnisharp: OmniSharpServer;

Expand All @@ -45,7 +47,8 @@ export async function activate(context: vscode.ExtensionContext, packageJSON: an
};

const options = optionProvider.GetLatestOptions();
const server = new OmniSharpServer(vscode, provider, packageJSON, platformInfo, eventStream, optionProvider, extensionPath);
let omnisharpMonoResolver = new OmniSharpMonoResolver(getMonoVersion);
const server = new OmniSharpServer(vscode, provider, packageJSON, platformInfo, eventStream, optionProvider, extensionPath, omnisharpMonoResolver);
omnisharp = server;
const advisor = new Advisor(server); // create before server is started
const disposables = new CompositeDisposable();
Expand Down Expand Up @@ -93,7 +96,7 @@ export async function activate(context: vscode.ExtensionContext, packageJSON: an
localDisposables = null;
}));

disposables.add(registerCommands(server, platformInfo, eventStream, optionProvider));
disposables.add(registerCommands(server, platformInfo, eventStream, optionProvider, omnisharpMonoResolver));

if (!context.workspaceState.get<boolean>('assetPromptDisabled')) {
disposables.add(server.onServerStart(() => {
Expand Down
Loading