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

Added processCommand to attach config #2969

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,11 @@
"type": "object",
"required": [],
"properties": {
"processCommand": {
gregg-miskelly marked this conversation as resolved.
Show resolved Hide resolved
"type": "string",
"description": "Attaches to a process with this command",
"default": "If this is use 'processId' and 'processName' should not be used."
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a typo here. You want 'used' instead of 'use'.

But thinking about it more, you might want to instead use something like dotnet exec /example/path/to/program.dll to provide an example of the kind of thing we might want.

},
"processName": {
"type": "string",
"description": "",
Expand Down Expand Up @@ -2456,6 +2461,11 @@
"type": "object",
"required": [],
"properties": {
"processCommand": {
"type": "string",
"description": "Attaches to a process with this command",
"default": "If this is use 'processId' and 'processName' should not be used."
},
"processName": {
"type": "string",
"description": "",
Expand Down
66 changes: 38 additions & 28 deletions src/configurationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@ import { WorkspaceInformationResponse } from './omnisharp/protocol';
import { isSubfolderOf } from './common';
import { parse } from 'jsonc-parser';
import { MessageItem } from './vscodeAdapter';
import { AttachItemsProvider, DotNetAttachItemsProviderFactory } from './features/processPicker';

export class CSharpConfigurationProvider implements vscode.DebugConfigurationProvider {
private server: OmniSharpServer;

public constructor(server: OmniSharpServer) {
this.server = server;
private attachItemsProvider: AttachItemsProvider;

public constructor(private server: OmniSharpServer) {
this.attachItemsProvider = DotNetAttachItemsProviderFactory.Get();
}

/**
* TODO: Remove function when https://github.com/OmniSharp/omnisharp-roslyn/issues/909 is resolved.
*
*
* Note: serverUtils.requestWorkspaceInformation only retrieves one folder for multi-root workspaces. Therefore, generator will be incorrect for all folders
* except the first in a workspace. Currently, this only works if the requested folder is the same as the server's solution path or folder.
*/
Expand All @@ -35,8 +37,7 @@ export class CSharpConfigurationProvider implements vscode.DebugConfigurationPro
const solutionPathOrFolder: string = this.server.getSolutionPathOrFolder();

// Make sure folder, folder.uri, and solutionPathOrFolder are defined.
if (!solutionPathOrFolder)
{
if (!solutionPathOrFolder) {
return Promise.resolve(false);
}

Expand All @@ -45,8 +46,7 @@ export class CSharpConfigurationProvider implements vscode.DebugConfigurationPro
return fs.lstat(solutionPathOrFolder).then(stat => {
return stat.isFile();
}).then(isFile => {
if (isFile)
{
if (isFile) {
serverFolder = path.dirname(solutionPathOrFolder);
}

Expand All @@ -73,48 +73,46 @@ export class CSharpConfigurationProvider implements vscode.DebugConfigurationPro
return [];
}

try
{
let hasWorkspaceMatches : boolean = await this.checkWorkspaceInformationMatchesWorkspaceFolder(folder);
try {
let hasWorkspaceMatches: boolean = await this.checkWorkspaceInformationMatchesWorkspaceFolder(folder);
if (!hasWorkspaceMatches) {
vscode.window.showErrorMessage(`Cannot create .NET debug configurations. The active C# project is not within folder '${folder.uri.fsPath}'.`);
return [];
}

let info: WorkspaceInformationResponse = await serverUtils.requestWorkspaceInformation(this.server);
let info: WorkspaceInformationResponse = await serverUtils.requestWorkspaceInformation(this.server);

const generator = new AssetGenerator(info, folder);
if (generator.hasExecutableProjects()) {

if (!await generator.selectStartupProject())
{

if (!await generator.selectStartupProject()) {
return [];
}
// Make sure .vscode folder exists, addTasksJsonIfNecessary will fail to create tasks.json if the folder does not exist.

// Make sure .vscode folder exists, addTasksJsonIfNecessary will fail to create tasks.json if the folder does not exist.
await fs.ensureDir(generator.vscodeFolder);

// Add a tasks.json
const buildOperations : AssetOperations = await getBuildOperations(generator);
const buildOperations: AssetOperations = await getBuildOperations(generator);
await addTasksJsonIfNecessary(generator, buildOperations);

const isWebProject = generator.hasWebServerDependency();
const launchJson: string = generator.createLaunchJson(isWebProject);

// jsonc-parser's parse function parses a JSON string with comments into a JSON object. However, this removes the comments.
// jsonc-parser's parse function parses a JSON string with comments into a JSON object. However, this removes the comments.
return parse(launchJson);

} else {
} else {
// Error to be caught in the .catch() below to write default C# configurations
throw new Error("Does not contain .NET Core projects.");
}
}
catch
{
// Provider will always create an launch.json file. Providing default C# configurations.
// jsonc-parser's parse to convert to JSON object without comments.
// jsonc-parser's parse to convert to JSON object without comments.
return [
createFallbackLaunchConfiguration(),
createFallbackLaunchConfiguration(),
parse(createAttachConfiguration())
];
}
Expand All @@ -127,7 +125,7 @@ export class CSharpConfigurationProvider implements vscode.DebugConfigurationPro
if (envFile) {
try {
const parsedFile: ParsedEnvironmentFile = ParsedEnvironmentFile.CreateFromFile(envFile, config["env"]);

// show error message if single lines cannot get parsed
if (parsedFile.Warning) {
CSharpConfigurationProvider.showFileWarningAsync(parsedFile.Warning, envFile);
Expand All @@ -153,14 +151,26 @@ export class CSharpConfigurationProvider implements vscode.DebugConfigurationPro
*/
resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration> {

if (!config.type)
{
if (!config.type) {
// If the config doesn't look functional force VSCode to open a configuration file https://github.com/Microsoft/vscode/issues/54213
return null;
}

if (config.request === "launch")
{
if (config.request === "attach" && config.processCommand) {
const processCommand = config.processCommand.replace(/\${workspaceFolder}/g, folder.uri.fsPath);
delete config.processCommand;
return this.attachItemsProvider.getAttachItems()
Copy link
Contributor

Choose a reason for hiding this comment

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

return [](start = 12, length = 6)

nit: make this an async method and use await.

Copy link
Author

Choose a reason for hiding this comment

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

Done

.then(attachItems => {
const attachItem = attachItems.find(ai => ai.detail === processCommand);
if (attachItem == null) {
throw new Error("Can't find process");
Copy link
Contributor

Choose a reason for hiding this comment

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

"Can't find process" [](start = 40, length = 20)

We might want to mention what we are looking for.

Copy link
Author

Choose a reason for hiding this comment

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

Now throws Couldn't find process with command ${processCommand}

}
config.processId = attachItem.id;
Copy link
Contributor

Choose a reason for hiding this comment

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

config.processId = attachItem.id; [](start = 20, length = 33)

We should probably fail if there are multiple processes with the command rather than picking the first.

Copy link
Author

Choose a reason for hiding this comment

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

Done

return config;
});
}

if (config.request === "launch") {
if (!config.cwd && !config.pipeTransport) {
config.cwd = "${workspaceFolder}";
}
Expand Down
2 changes: 1 addition & 1 deletion src/omnisharp/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,4 @@ export async function activate(context: vscode.ExtensionContext, packageJSON: an
return new Promise<ActivationResult>(resolve =>
server.onServerStart(e =>
resolve({ server, advisor })));
}
}
31 changes: 25 additions & 6 deletions src/tools/OptionsSchema.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
},
"PipeTransport": {
"type": "object",
"required": [ "debuggerPath" ],
"required": [
"debuggerPath"
],
"description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the .NET Core debugger backend executable (vsdbg).",
"default": {
"pipeCwd": "${workspaceFolder}",
Expand Down Expand Up @@ -176,7 +178,9 @@
},
"LaunchBrowserPlatformOptions": {
"type": "object",
"required": [ "command" ],
"required": [
"command"
],
"properties": {
"command": {
"type": "string",
Expand All @@ -192,7 +196,9 @@
},
"LaunchBrowser": {
"type": "object",
"required": [ "enabled" ],
"required": [
"enabled"
],
"description": "Configures starting a web browser as part of the launch -- should a web browser be started, and if so, what command should be run to start it. This option can be modified to launch a specific browser.",
"default": {
"enabled": true
Expand Down Expand Up @@ -294,7 +300,11 @@
},
"console": {
"type": "string",
"enum": [ "internalConsole", "integratedTerminal", "externalTerminal" ],
"enum": [
"internalConsole",
"integratedTerminal",
"externalTerminal"
],
"enumDescriptions": [
"Output to the VS Code Debug Console. This doesn't support reading console input (ex:Console.ReadLine)",
"VS Code's integrated terminal",
Expand Down Expand Up @@ -358,7 +368,9 @@
"$ref": "#/definitions/SourceLinkOptions",
"description": "Options to control how Source Link connects to web servers. For more information: https://aka.ms/VSCode-CS-LaunchJson#source-link-options",
"default": {
"*": { "enabled": true }
"*": {
"enabled": true
}
}
}
}
Expand All @@ -367,6 +379,11 @@
"type": "object",
"required": [],
"properties": {
"processCommand": {
"type": "string",
"description": "Attaches to a process with this command",
"default": "If this is use 'processId' and 'processName' should not be used."
},
"processName": {
"type": "string",
"description": "",
Expand Down Expand Up @@ -436,7 +453,9 @@
"$ref": "#/definitions/SourceLinkOptions",
"description": "Options to control how Source Link connects to web servers. For more information: https://aka.ms/VSCode-CS-LaunchJson#source-link-options",
"default": {
"*": { "enabled": true }
"*": {
"enabled": true
}
}
}
}
Expand Down