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

overriding "Run and Debug" button #142019

Closed
elahehrashedi opened this issue Feb 2, 2022 · 12 comments
Closed

overriding "Run and Debug" button #142019

elahehrashedi opened this issue Feb 2, 2022 · 12 comments
Assignees
Labels
debug Debug viewlet, configurations, breakpoints, adapter issues

Comments

@elahehrashedi
Copy link

The C/C++ extension has two entry point for "run and debug":
one is the "Run and Debug" button from the debug panel (F5)
and the other one is the debug shortcut button on text editor (fully designed by extension).

image

image

Is there a way for extension to override the functionality of F5 to make the two functinality to be the same?

  1. for example F5 will run the last recent launched task, but the debug button (designed by our extension) runs the default task (which is our desired behaviour). Can the extension do that or is this something VsCode has yet to provide?
  2. The F5 writes in the launch.json, but we designed our shortcut button to not to do that. Can we change that behaviour in F5?

Thank you :)

@miguelsolorio
Copy link
Contributor

miguelsolorio commented Feb 2, 2022

@roblourens @weinand I wonder if we can detect if there are run actions (like the separate run & debug actions in the toolbar) if we can render the button differently and use a split button that had the same commands from the run action in the toolbar?

CleanShot 2022-02-02 at 09 10 32@2x

I guess this is dependent on having an actual file open to debug, maybe prompting the user to select a file in that case?

@weinand
Copy link
Contributor

weinand commented Feb 2, 2022

@misolori yes, your suggestion should be possible.

One issue I see with this approach is that the contributed Run/Debug actions have sophisticated "when" clauses that control their visibility based on the editor contents. That means if the wrong file is active in an editor, no actions would show up in the Debug viewlet. And it is not really obvious, that the contents of the Debug viewlet depends on the contents of an editor...

To fix this we would have to make the contributed actions smarter and richer so that they can always be visible in the Debug Viewlet and explain in the surrounding text how to use them.

I'm not sure whether we want to build logic into VS Code so that it works generically with the existing action contributions or if we want to rely on extension contribution for the debug Viewlet instead.

@weinand weinand added the debug Debug viewlet, configurations, breakpoints, adapter issues label Feb 2, 2022
@roblourens
Copy link
Member

@elahehrashedi The extension can't own the behavior of F5, because you may be in a workspace where multiple debug extensions are in play.

The F5 writes in the launch.json

I'm not sure what you mean by this, can you explain?

@jureid
Copy link

jureid commented Feb 3, 2022

In 8224, @isidorn mentioned that we don't need to generate tasks.json and launch.json, and can instead provide a dynamic resolveDebugConfiguration that will provide a launch configuration on the fly, linking to this example. Can we do this for F5 if the user doesn't already have tasks.json and launch.json?

@jureid
Copy link

jureid commented Feb 3, 2022

Created an issue to use dynamic debug configuration for F5 rather than generate tasks.json/launch.json if they don't already exist: microsoft/vscode-cpptools#8773

@elahehrashedi
Copy link
Author

I'm not sure what you mean by this, can you explain?

@roblourens @weinand When debugging with F5, the debug configs will be written in F5. using vscode.DebugConfigurationProviderTriggerKind.Dynamic in vscode.debug.registerDebugConfigurationProvider doesn't help with skipping writing in the launch.json.

@weinand
Copy link
Contributor

weinand commented Feb 8, 2022

@elahehrashedi VS Code has two mechanisms that automatically write debug configs into the launch.json (if it doesn't exist):

  • a static mechanism: in the package.json a debugger can contribute a list of debug configurations via the "debuggers" / "initialConfigurations" contribution point.

  • a dynamic mechanism: an extension can register a "DebugConfigurationProvider" with "vscode.debug.registerDebugConfigurationProvider": please see

    vscode/src/vscode-dts/vscode.d.ts

    Lines 13750 to 13764 in 5e11759

    /**
    * Register a {@link DebugConfigurationProvider debug configuration provider} for a specific debug type.
    * The optional {@link DebugConfigurationProviderTriggerKind triggerKind} can be used to specify when the `provideDebugConfigurations` method of the provider is triggered.
    * Currently two trigger kinds are possible: with the value `Initial` (or if no trigger kind argument is given) the `provideDebugConfigurations` method is used to provide the initial debug configurations to be copied into a newly created launch.json.
    * With the trigger kind `Dynamic` the `provideDebugConfigurations` method is used to dynamically determine debug configurations to be presented to the user (in addition to the static configurations from the launch.json).
    * Please note that the `triggerKind` argument only applies to the `provideDebugConfigurations` method: so the `resolveDebugConfiguration` methods are not affected at all.
    * Registering a single provider with resolve methods for different trigger kinds, results in the same resolve methods called multiple times.
    * More than one provider can be registered for the same type.
    *
    * @param type The debug type for which the provider is registered.
    * @param provider The {@link DebugConfigurationProvider debug configuration provider} to register.
    * @param triggerKind The {@link DebugConfigurationProviderTrigger trigger} for which the 'provideDebugConfiguration' method of the provider is registered. If `triggerKind` is missing, the value `DebugConfigurationProviderTriggerKind.Initial` is assumed.
    * @return A {@link Disposable} that unregisters this provider when being disposed.
    */
    export function registerDebugConfigurationProvider(debugType: string, provider: DebugConfigurationProvider, triggerKind?: DebugConfigurationProviderTriggerKind): Disposable;

If you don't want to have your debugger extension write into the launch.json make sure that you don't have "initialConfigurations" in your package.json and that your extension doesn't register a "DebugConfigurationProvider" for the Initial trigger type).

@elahehrashedi
Copy link
Author

elahehrashedi commented Feb 10, 2022

@weinand
We don't have initial configurations in package.json. and Here are two outcomes of the code:
By using vscode.DebugConfigurationProviderTriggerKind.Initial in the code, after pressing F5, we have a correct launch.json as below and the "Run and Debug" works fine.

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "C/C++: cl.exe Build and debug active file",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "console": "externalTerminal",
            "preLaunchTask": "C/C++: cl.exe build active file"
        }
}

In the same code, by using vscode.DebugConfigurationProviderTriggerKind.Dynamic the debug doesn’t start with F5 and this launch.json gets created:

{
    "version": "0.2.0",
    "configurations": []
}

@weinand
Copy link
Contributor

weinand commented Feb 11, 2022

@elahehrashedi I do not really understand your "scenarios" because you don't provide any details about what the user does and what should happen...

I can only explain what the APIs do:

  • a DebugConfigurationProvider registered for a trigger kind "Initial" (the default) is called if there is no launch.json and the user presses F5 and there is no "resolveDebugConfiguration" registered (which could create and execute a single launch config on the fly). The returned launch configs are added to the launch.json (together with the launch configs returned by other debugger extension). This F5 does not start debugging, it just creates a launch.json.
  • a DebugConfigurationProvider registered for a trigger kind "Dynamic" is called to add dynamically created launch configs to the menus that list debug configuration: e.g. the drop down menu in the debug viewlet and the launch config QuickPick. Dynamic launch configs generated by the DebugConfigurationProvider are not automatically executed, they are just added to the UI. And dynamic launch configs are not automatically added to the launch.json (but a user can do this manually from the gear icon in the Quickpick menu). The "dynamic" DebugConfigurationProvider is never involved when pressing F5.

If you just want to start debugging when the user presses F5 (and there is no launch config), your best bet is to register a "resolveDebugConfiguration" and create an in-memory launch config that does the right thing.
If a launch.json already exists, F5 will launch the selected launch config from that launch.json.

@elahehrashedi
Copy link
Author

elahehrashedi commented Feb 11, 2022

Hi @weinand,

Let me see if I can help clarify the "scenarios". Our users have a source file open in the editor that is runnable/debuggable.

Scenario 1:

  • User clicks the new "play" button in the editor that will run or debug the code file.
  • We compile the code and run or debug the binary produced.
  • We do not write to launch.json.
  • This works regardless of whether a folder is open or not.

Scenario 2:

  • User presses F5 or clicks the "Run and Debug" button in the Debug panel to run or debug the active file.
  • (the reset should be the same as Scenario 1)

What we would like to do is not write to launch.json in Scenario 2, primarily because we are unable to make the single-file (no workspace folder open) case work since writing to launch.json seems to be a prerequisite. We are also seeing a "Variable ${workspaceFolder} can not be resolved" error.

We think we are already doing what you said was necessary to make this work. We call vscode.debug.registerDebugConfigurationProvider and pass it a vscode.DebugConfigurationProvider that has an implementation for resolveDebugConfiguration. We've tried passing both values of vscode.DebugConfigurationProviderTriggerKind to the API, but we get the behavior described in #142019 (comment) when testing.

@weinand
Copy link
Contributor

weinand commented Feb 14, 2022

@elahehrashedi thanks for the additional information.

I understand Scenario 1 and that seems to work fine.

So let's focus on Scenario 2:
What do you mean by "the reset should be the same as Scenario 1"? Do you mean "result"?

I'm assuming the following detailed scenario:

  • user has a file "helloworld.cpp" in a folder "test",
  • opens the folder with VS Code but does not open the file "helloworld.cpp",
  • switches to "Run and Debug" panel,
  • presses the "Run and Debug" button,
  • helloworld.cpp is compiled and executed and produces a "Hello world" on the console.
  • no launch.json is created.

I've tried this with the Java extension and they fully support the scenario:

CleanShot 2022-02-14 at 12 32 14

This proves that it is already possible to achieve the desired behavior for scenario 2.
(BTW the code for Java lives here).

Since my own Mock Debugger shows the same behavior as Java, I've added breakpoints to the MockConfigurationProvider's methods provideDebugConfigurations and resolveDebugConfiguration (see here). For Scenario 2 only the resolveDebugConfiguration method is hit and no launch.json is created.

The cpp extension registers a QuickPickConfigurationProvider.
I suggest that you set breakpoints in its provideDebugConfigurations and resolveDebugConfiguration methods and investigate when and why they are hit.

@elahehrashedi
Copy link
Author

elahehrashedi commented Feb 15, 2022

@weinand thank you, I could modify the DebugConfigurationProvider to skip writing in the launch.json.

@weinand weinand closed this as completed Oct 19, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Dec 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
debug Debug viewlet, configurations, breakpoints, adapter issues
Projects
None yet
Development

No branches or pull requests

5 participants