-
Notifications
You must be signed in to change notification settings - Fork 26
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
Smart Step Into #122
Labels
Comments
This was referenced Oct 6, 2021
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Introduction
The scala-debug-adapter is the debugger of Scala programs in Metals.
Problem
Some Scala constructs generate methods in the bytecode that do not contain any part of the source code. For example we have the getter methods, the mixin forwarders, the bridges.
When the compiler generates those methods, it fills their source lines tables with the line of the class or field definition. That's because there is nothing else to go since there is no corresponding source code of the method.
As a consequence the JVM debugger steps into those generated methods showing the class or field definition.
This is:
Live example (mixin forwarder):
Instead, the user expects those intermediate steps to be skipped.
Identified patterns
In these examples, when the user steps into
1=>
the debugger goes to2=>
.Getter
The getter method in the class file of
Foo
is:It is not flagged as
ACC_SYNTHETIC
. Its line number table contains line 4 where the fieldfoo
is defined.How to detect that a method is a getter?
Setter
The setter method in the class file of
Foo
is:It is not flagged as
ACC_SYNTHETIC
. Its line number table contains line 4 where the fieldfoo
is defined.How to detect that a method is a setter?
<field>_$eq
where<field>
is a field of the classMixin forwarder
The mixin forwarder in the class file of
B
is:Again it is not flagged as
ACC_SYNTHETIC
. Its line table contains line7
which is the definition of classB
.How to detect that a method is a mixin forwarder?
<methodname>$
in a interface x that have the same signature but takes an instance of x as first parameter.Bridge method
The bridge in the class file of
D
is:It is flagged
ACC_BRIDGE
. Its line number table contains line 7 which is the definition ofclass D
.In this case we can skip the bridge method on the fact that is flagged
ACC_BRIDGE
. That should be fine because allACC_BRIGE
methods should be skipped, even the java ones.Implementation
Solution 1: Create custom
StepFilters
Currently the
StepFilters
in https://github.com/scalacenter/java-debug contains:and it inherits from
ClassFilters
This is not what we need because we do not want:
But we can adapt this class with something more customizable:
Then create one custom filter for each identified patterns (in https://github.com/scalacenter/scala-debug-adapter).
The heuristic to identify such patterns can be taken from or inspired by the intellij-scala smartStepInto classes.
Solution 2: The compiler does not set line numbers in those methods
We change the compiler so that it does not set line numbers in those methods.
We should check, in the JVM specification, that it is valid to have a method with an empty source line table.
Also we should test that the JVM can skip those methods and step into the next method call.
And we should sync with JetBrains team to not break their debugger.
Solution 3: The compiler set some attribute in the class file.
It is easier for the compiler to know which method should be skipped and which one should not be skipped.
So if the Solution 2 is not viable, the compiler can still add some attribute in the class file that stores a list of methods that should be skipped.
Expectations
Going further
loadClass
when stepping into constructor #126The text was updated successfully, but these errors were encountered: