-
Notifications
You must be signed in to change notification settings - Fork 11
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 support for the Debug Adapter Protocol #92
Conversation
In order for the DebugAdapter to be able to use the appropriate debugger for the given module, we need to move the responsibility of creating the right debugger to the *Engine class of the language in question.
There are cases where the URLs reported by the module are different than those sent in DAP requests. This happens, for instance, if we're running an Epsilon script from the classpath of a Java program, instead of running it directly from a file in the filesystem. This commit introduces an approach which will match based on the longest matching sequence of trailing URI components. Suppose we had set a breakpoint on this file in our IDE: file:/your/path/to/sources/a.b.c/epsilon/main/a.eol If we had modules for these: platform:/plugin/a.b.c/epsilon/main/a.eol platform:/plugin/a.b.c/epsilon/util/a.eol Then it would prefer the main/a.eol option, as it would match a longer sequence of trailing URI components.
On second thought, the approximate matching was not a good idea. It would help with the initial setting of breakpoints, but when we actually hit one, we had no reliable way to tell the DAP client the file that should be shown to the user. I have replaced the approximate matching with an explicit URI-to-path mapping. Before starting the debugging session, we tell the adapter which URI prefixes match to which filesystem paths (e.g.
|
The PR branch passes the tests on Jenkins: https://ci.eclipse.org/epsilon/job/interim-kubernetes/job/debug-adapter/21/ |
This makes the logic easier to understand: if we set a mapping, we will always try that first. We will only fall back to using the module's file if we don't have an appropriate URI-to-path mapping.
In an initial walkthrough over the approach, @kolovos commented that it made more sense to always try to use the URI-to-Path mappings first, and only fall back to the module file if that didn't produce a path. I agree that it makes the user experience more consistent (instead of depending on whether we run a program which uses an Epsilon script from the classpath via Eclipse or via a JAR file), so I have made that change. |
I have also looked a bit more into the VS Code configuration, and it turns out you can use A future version of the Epsilon VS Code extension could perhaps simplify this a bit, by just retrying the connection a few times before handing over control to VS Code. |
VS Code can do the waiting for the server for us, so long as we run the Gradle task as a background task, and provide a problemMatcher with the "background" key set up to detect when we are ready to debug. This requires the latest version of the remote-debug branch of the Epsilon extension for VS Code, which provides a problemMatcher with the necessary "background" patterns.
VS Code already has the necessary functionality to wait until the session is ready to be debugged. You only need to provide a I guess it would be nice if the user didn't have to set up |
https://code.visualstudio.com/api/extension-guides/task-provider |
I had a look yesterday, and found that Gradle contributes its own kind of task and its own task provider, which does most of what we need and more (except for the background patterns for problem matching). This is what the {
"version": "2.0.0",
"tasks": [
{
"type": "gradle",
"script": "debugHello",
"group": "other",
"buildFile": "${workspaceFolder}/build.gradle",
"workspaceFolder": "${workspaceFolder}",
"projectFolder": "${workspaceFolder}",
"args": "--info",
"problemMatcher": "$epsilon-debug",
"label": "epsilonDebug: hello",
"isBackground": true
}
]
} Writing the task provider would not be trivial, as we'd have to find out which Gradle tasks are available. It looks like the We could also provide the above snippet, and tell users how to tweak the |
The existing code would only work for simple variables, but it would have required having a getReference(...) method for every type of reference that we would have. This commit introduces a generic interface (IVariableReference) for anything that we can reference through a DAP integer, which we could then use to inspect model element properties, the elements of a collection, and so on.
This commit allows for inspecting Java collections. For small collections (below the threshold in SuspendedState, currently 200 elements) we will list each element on its own. For larger collections, we will initially only show slices (according to the constant in SuspendedState, currently 100-element long), and then let the user specify the slice they are interested in. For slices, there is a minor optimisation where we will use List.subList instead of creating our own list by iterating to the starting index.
I've added the ability to inspect collections (per-element for small ones, and per-slice for large ones) and the properties of model elements. I have also tweaked I think this is ready for general use. In terms of future improvements, we could do things like showing the type of the variables in addition to their name and value, or perhaps supporting launch requests, but those bits feel outside the scope of this first PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It all looks good to me!
This PR adds support for debugging Epsilon scripts over the network, through the Debug Adapter Protocol. It has been tested with LSP4E and the
debug-adapter
branch of my fork of the Epsilon VS Code extension:The PR includes a new example project with documentation, as well as automated tests for the server and the debug adapter itself. It has required some refactoring of the debugging infrastructure in Epsilon, separating the Eclipse-specific parts out to the
EolDebugTarget
, and moving all*Debugger
classes (which are now Eclipse-agnostic) to their.engine
plugins.The PR allows for using the DAP server from the Ant tasks, and from plain Java. There is an implementation of approximate matching to allow for debugging scripts running from the classpath without requiring configuration, while looking out for ambiguous matches.