Repository: vscode
Issue: Debugger: Smart Step Into
Labels: feature-request,debug

# Problem

Given that we are debugging the following code:

```ts
console.log(add(f1(), f2())); // This is the currently active line that is about to be run.

function f1() {
    // ...
    return 1;
}

function f2() {
    // ...
    return 2;
}

function add(a, b) {
    return a + b + 1;
}
```

Next, we want to step into `add` to fix our bug. However, if we use the "Step Into" command, we step into `f1` and `f2` first.
This is especially annoying when there are a lot of uninteresting `getXYZ` functions/getters.

# Suggested Solution

It would be nice if VS Code had a way so that the user can specify in which method/function they want to step into.
[IntelliJ](https://www.jetbrains.com/help/idea/stepping-through-the-program.html#smart-step-into) and [PhpStorm](https://blog.jetbrains.com/phpstorm/2013/07/debugging-with-smart-step-into/) have a "smart step into" feature that does this.

If there is only one target to step into, nothing can be done.
However, if there are multiple targets that the debugger can step into, it would be nice if the user could select one.

There a many ways how the selection story can be implemented.

* **By using a quick pick dialog.** ([like PhpStorm in 2013](https://blog.jetbrains.com/phpstorm/2013/07/debugging-with-smart-step-into/)) If "Step Into" is called and the debug adapter reports multiple targets, show them all in a quick pick dialog (it would list "add", "f1" and "f2"). If the user selects one, the debugger will step into the selected target. This might be confusing if a method appears twice.

* **Source Code Range Highlight + Selection.** (similar to [IntelliJ](https://www.jetbrains.com/help/idea/stepping-through-the-program.html#smart-step-into)) If "Step Into" is called and the debug adapter reports multiple target ranges, highlight all those ranges like this (imagine the line being yellow):
![image](https://user-images.githubusercontent.com/2931520/118259971-125a0580-b4b2-11eb-906a-16de1a2c78b3.png)
If the user clicks on a range, the debugger will step into the selected target. With the arrow keys to select a target range and enter to accept it, a keyboard only story can be provided.

* **Modifier Key + Inline Decorators.**
While the user holds `Ctrl`, inline target decorators are shown before each step-into target in the line that is about to be executed like this (imagine the line being yellow):
![image](https://user-images.githubusercontent.com/2931520/118261965-8695a880-b4b4-11eb-9f26-afc576ea2c3b.png)
If the user clicks on one of those decorators while `Ctrl` is pressed, the debugger steps into the selected target. "Step Into" does not need to be invoked before for this scenario and does not need to be changed. This still allows for the "Go To Declaration/Definition" scenario, as separate click targets are shown.
This could be extended for "Go To Cursor" too ([similar to how Chrome does it](https://developer.chrome.com/blog/new-in-devtools-60/#continue), except that they don't render additional inline decorators as they don't have the "Go To Definition" feature).
This approach is very efficient for users who debug with the mouse. Keyboard users could enter this "Show All Step-Into Target Decorators" mode with a specific command and then use the arrow keys to select a target.

## JS Debug Adapter Implementation Details

Afaik, the V8 debugger does not directly provide the information/commands required for this.
Some heuristic involving the AST might be needed. I think it is ok if this feature is not enabled in situations where the list of available targets cannot be statically computed. If it is enabled though, it should always work.

The JS debug adapter could always "step in" and use "step out" if the method that V8 stepped into does not match the selected target.

## Examples

Here I would like to step into `_applySessionResult`, skipping `_addSelectionToNextFindMatch`. I think pressing "ctrl" + clicking on an appearing "jump to/in" decorator would be a really fun experience:

![image](https://user-images.githubusercontent.com/2931520/118275315-90c0a280-b4c6-11eb-8238-8ec4e5e1cb7f.png)