Skip to content

Commit 0de0244

Browse files
authored
Merge pull request #26 from emacs-lsp/add-test-debug
Add Dart/Flutter test debug
2 parents 5c4f0f5 + 843e448 commit 0de0244

File tree

8 files changed

+169
-49
lines changed

8 files changed

+169
-49
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ LINT="(progn \
1818
build:
1919
cask install
2020

21-
test: build compile checkdoc lint
21+
test: clean build compile checkdoc lint
2222

2323
compile:
2424
@echo "Compiling..."
@@ -57,7 +57,7 @@ lint:
5757
*.el
5858

5959
clean:
60-
rm -rf .cask
60+
rm -rf .cask *.elc
6161

6262
tag:
6363
$(eval TAG := $(filter-out $@,$(MAKECMDGOALS)))

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,14 @@ Besides the `lsp-mode` features, `lsp-dart` implements the [custom methods featu
6565

6666
![flutter-outline](images/flutter-outline.gif)
6767

68-
### Run tests
68+
### Run/Debug tests
6969

7070
`lsp-dart-run-test-file` - Run all tests from current test buffer.
71-
72-
`lsp-dart-run-test-at-point` - Run single test at point. [:warning:*](#features-only-available-for-dart-sdk-version-280-currently-the-dev-branch-or-above)
73-
71+
`lsp-dart-run-test-at-point` - Run single test at point.
72+
`lsp-dart-debug-test-at-point` - Debug single test at point.
7473
`lsp-dart-visit-last-test` - Go to last ran test.
75-
7674
`lsp-dart-run-last-test` - Run last ran test.
75+
`lsp-dart-debug-last-test` - Debug last ran test.
7776

7877
Running a test interactively:
7978

@@ -162,12 +161,15 @@ You can also open the [Dart DevTools](https://dart.dev/tools/dart-devtools) on t
162161
| `lsp-dart-flutter-fringe-colors` | Enable the Flutter colors on fringe. | `t` |
163162
| `lsp-dart-flutter-widget-guides` | Enable the Flutter widget guide lines from parent to child widgets | `t` |
164163
| `lsp-dart-test-code-lens` | Enable the `Run` code lens on tests. | `t` |
165-
| `lsp-dart-dap-extension-version` | The debugger extension version. | 3.9.1 |
164+
| `lsp-dart-dap-extension-version` | The debugger extension version. | 3.10.1 |
166165
| `lsp-dart-dap-debugger-path` | The debugger extension path | Check source file |
167166
| `lsp-dart-dap-dart-debugger-program` | The command to execute the debugger extension on dart projects. | Check source file |
167+
| `lsp-dart-dap-dart-test-debugger-program` | The command to execute the test debugger extension on dart projects. | Check source file |
168168
| `lsp-dart-dap-flutter-debugger-program` | The command to execute the debugger extension on flutter projects. | Check source file |
169+
| `lsp-dart-dap-flutter-test-debugger-program` | The command to execute the test debugger extension on flutter projects. | Check source file |
169170
| `lsp-dart-dap-debug-external-libraries` | Whether to enable the debug on external libraries | `nil` |
170171
| `lsp-dart-dap-debug-sdk-libraries` | Whether to enable the debug on Dart SDK libraries | `nil` |
172+
| `lsp-dart-dap-vm-additional-args` | Additional args for dart debugging VM when the debugging. | `""` |
171173
| `lsp-dart-dap-flutter-track-widget-creation` | Whether to pass –track-widget-creation to Flutter apps. Required to support 'Inspect Widget'. | `t` |
172174
| `lsp-dart-dap-flutter-structured-errors` | Whether to use Flutter’s structured error support for improve error display. | `t` |
173175
| `lsp-dart-dap-flutter-verbose-log` | Whether to enable verbose logs from Flutter DAP | `nil` |

images/run-test.gif

-85.2 KB
Loading

lsp-dart-dap-devtools.el

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ If URI is not found on buffer, schedule re-check."
7979
(defun lsp-dart-dap-devtools--activated-p ()
8080
"Return non-nil if devtools is activated otherwise nil."
8181
(lsp-dart-dap-devtools--clean-buffer lsp-dart-dap-devtools--pub-list-packages-buffer-name)
82-
(let* ((pub (lsp-dart-project-get-pub-command))
82+
(let* ((pub (lsp-dart-project-pub-command))
8383
(_proc (call-process pub
8484
nil
8585
lsp-dart-dap-devtools--pub-list-packages-buffer-name
@@ -91,7 +91,7 @@ If URI is not found on buffer, schedule re-check."
9191
(defun lsp-dart-dap-devtools--activate (callback)
9292
"Activate Dart Devtools via pub then call CALLBACK."
9393
(lsp-dart-dap-devtools-log "Activating...")
94-
(let ((pub (lsp-dart-project-get-pub-command)))
94+
(let ((pub (lsp-dart-project-pub-command)))
9595
(lsp-async-start-process
9696
(lambda ()
9797
(lsp-dart-dap-devtools-log "Activated successfully!")
@@ -123,7 +123,7 @@ If it is already activated or after activated successfully, call CALLBACK."
123123
(lambda ()
124124
(if-let ((uri (lsp-workspace-get-metadata "dart-debug-devtools-uri")))
125125
(funcall callback uri)
126-
(let* ((pub (lsp-dart-project-get-pub-command))
126+
(let* ((pub (lsp-dart-project-pub-command))
127127
(proc (start-process "Start DevTools"
128128
lsp-dart-dap-devtools--buffer-name
129129
pub "global" "run" "devtools"

lsp-dart-dap.el

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,24 @@
5050
:group 'lsp-dart
5151
:type '(repeat string))
5252

53+
(defcustom lsp-dart-dap-dart-test-debugger-program
54+
`("node" ,(f-join lsp-dart-dap-debugger-path "extension/out/src/debug/dart_test_debug_entry.js"))
55+
"The path to the dart test debugger."
56+
:group 'lsp-dart
57+
:type '(repeat string))
58+
5359
(defcustom lsp-dart-dap-flutter-debugger-program
5460
`("node" ,(f-join lsp-dart-dap-debugger-path "extension/out/src/debug/flutter_debug_entry.js"))
5561
"The path to the Flutter debugger."
5662
:group 'lsp-dart
5763
:type '(repeat string))
5864

65+
(defcustom lsp-dart-dap-flutter-test-debugger-program
66+
`("node" ,(f-join lsp-dart-dap-debugger-path "extension/out/src/debug/flutter_test_debug_entry.js"))
67+
"The path to the dart test debugger."
68+
:group 'lsp-dart
69+
:type '(repeat string))
70+
5971
(defcustom lsp-dart-dap-debug-external-libraries nil
6072
"If non-nil, enable the debug on external libraries."
6173
:group 'lsp-dart
@@ -66,6 +78,11 @@
6678
:group 'lsp-dart
6779
:type 'boolean)
6880

81+
(defcustom lsp-dart-dap-vm-additional-args ""
82+
"Additional args for dart debugging VM."
83+
:group 'lsp-dart
84+
:type 'string)
85+
6986
(defcustom lsp-dart-dap-flutter-track-widget-creation t
7087
"Whether to pass –track-widget-creation to Flutter apps.
7188
Required to support 'Inspect Widget'."
@@ -103,6 +120,23 @@ Required to support 'Inspect Widget'."
103120
"npm" "install" "--prefix" (f-join lsp-dart-dap-debugger-path "extension")
104121
"--no-package-lock" "--silent" "--no-save"))
105122

123+
(defun lsp-dart-dap--base-debugger-args (conf)
124+
"Return the base args for debugging merged with CONF."
125+
(-> conf
126+
(dap--put-if-absent :request "launch")
127+
(dap--put-if-absent :dartPath (lsp-dart-project-dart-command))
128+
(dap--put-if-absent :cwd (lsp-dart-project-get-root))
129+
(dap--put-if-absent :pubPath (lsp-dart-project-pub-command))
130+
(dap--put-if-absent :pubSnapshotPath (lsp-dart-project-pub-snapshot-command))
131+
(dap--put-if-absent :vmAdditionalArgs lsp-dart-dap-vm-additional-args)
132+
(dap--put-if-absent :debugExternalLibraries lsp-dart-dap-debug-external-libraries)
133+
(dap--put-if-absent :debugSdkLibraries lsp-dart-dap-debug-sdk-libraries)
134+
(dap--put-if-absent :flutterPath (lsp-dart-project-get-flutter-path))
135+
(dap--put-if-absent :flutterTrackWidgetCreation lsp-dart-dap-flutter-track-widget-creation)
136+
(dap--put-if-absent :useFlutterStructuredErrors lsp-dart-dap-flutter-structured-errors)))
137+
138+
;; Dart
139+
106140
(dap-utils-github-extension-setup-function
107141
"dap-dart"
108142
"Dart-Code"
@@ -114,20 +148,28 @@ Required to support 'Inspect Widget'."
114148
(defun lsp-dart-dap--populate-dart-start-file-args (conf)
115149
"Populate CONF with the required arguments for dart debug."
116150
(-> conf
151+
lsp-dart-dap--base-debugger-args
117152
(dap--put-if-absent :type "dart")
118153
(dap--put-if-absent :name "Dart")
119-
(dap--put-if-absent :request "launch")
120154
(dap--put-if-absent :dap-server-path lsp-dart-dap-dart-debugger-program)
121-
(dap--put-if-absent :cwd (lsp-dart-project-get-root))
122-
(dap--put-if-absent :program (buffer-file-name))
123-
(dap--put-if-absent :dartPath (lsp-dart-project-dart-command))
124-
(dap--put-if-absent :debugExternalLibraries lsp-dart-dap-debug-external-libraries)
125-
(dap--put-if-absent :debugSdkLibraries lsp-dart-dap-debug-sdk-libraries)))
155+
(dap--put-if-absent :program (buffer-file-name))))
126156

127157
(dap-register-debug-provider "dart" 'lsp-dart-dap--populate-dart-start-file-args)
128158
(dap-register-debug-template "Dart :: Debug"
129159
(list :type "dart"))
130160

161+
(defun lsp-dart-dap-debug-dart-test (path args)
162+
"Start dart test debugging from PATH with ARGS."
163+
(-> (list :type "dart"
164+
:name "Dart Tests"
165+
:dap-server-path lsp-dart-dap-dart-test-debugger-program
166+
:program path
167+
:noDebug nil
168+
:shouldConnectDebugger t
169+
:args args)
170+
lsp-dart-dap--base-debugger-args
171+
dap-start-debugging))
172+
131173
;; Flutter
132174

133175
(declare-function all-the-icons-faicon "ext:all-the-icons")
@@ -160,18 +202,11 @@ Call CALLBACK when the device is chosen and started successfully."
160202
(defun lsp-dart-dap--populate-flutter-start-file-args (conf)
161203
"Populate CONF with the required arguments for Flutter debug."
162204
(let ((pre-conf (-> conf
205+
lsp-dart-dap--base-debugger-args
163206
(dap--put-if-absent :type "flutter")
164-
(dap--put-if-absent :request "launch")
165207
(dap--put-if-absent :flutterMode "debug")
166208
(dap--put-if-absent :dap-server-path lsp-dart-dap-flutter-debugger-program)
167-
(dap--put-if-absent :cwd (lsp-dart-project-get-root))
168-
(dap--put-if-absent :program (lsp-dart-project-get-entrypoint))
169-
(dap--put-if-absent :dartPath (lsp-dart-project-dart-command))
170-
(dap--put-if-absent :flutterPath (lsp-dart-project-get-flutter-path))
171-
(dap--put-if-absent :flutterTrackWidgetCreation lsp-dart-dap-flutter-track-widget-creation)
172-
(dap--put-if-absent :useFlutterStructuredErrors lsp-dart-dap-flutter-structured-errors)
173-
(dap--put-if-absent :debugExternalLibraries lsp-dart-dap-debug-external-libraries)
174-
(dap--put-if-absent :debugSdkLibraries lsp-dart-dap-debug-sdk-libraries))))
209+
(dap--put-if-absent :program (lsp-dart-project-get-entrypoint)))))
175210
(lambda (start-debugging-callback)
176211
(lsp-dart-dap--flutter-get-or-create-device
177212
(-lambda ((&hash "id" device-id "name" device-name))
@@ -257,6 +292,22 @@ Call CALLBACK when the device is chosen and started successfully."
257292
(cl-defmethod dap-handle-event ((_event (eql dart.navigate)) _session _params)
258293
"Ignore this event.")
259294

295+
(cl-defmethod dap-handle-event ((_event (eql dart.testRunNotification)) _session _params)
296+
"Ignore this event.")
297+
298+
(defun lsp-dart-dap-debug-flutter-test (path args)
299+
"Start dart test debugging from PATH with ARGS."
300+
(-> (list :name "Flutter Tests"
301+
:type "flutter"
302+
:dap-server-path lsp-dart-dap-flutter-test-debugger-program
303+
:program path
304+
:noDebug nil
305+
:shouldConnectDebugger t
306+
:flutterMode "debug"
307+
:args args)
308+
lsp-dart-dap--base-debugger-args
309+
dap-start-debugging))
310+
260311
;;;###autoload
261312
(defun lsp-dart-dap-flutter-hot-restart ()
262313
"Hot restart current Flutter debug session."

lsp-dart-project.el

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,18 @@ flutter cache dir."
6666
(locate-dominating-file "bin")
6767
file-truename))))
6868

69-
(defun lsp-dart-project-get-pub-command ()
69+
(defun lsp-dart-project-pub-command ()
7070
"Return the pub executable path from dart SDK path."
7171
(-> (lsp-dart-project-get-sdk-dir)
7272
file-name-as-directory
7373
(concat "bin/pub")))
7474

75+
(defun lsp-dart-project-pub-snapshot-command ()
76+
"Return the pub snapshot executable path from dart SDK path."
77+
(-> (lsp-dart-project-get-sdk-dir)
78+
file-name-as-directory
79+
(concat "bin/snapshots/pub.dart.snapshot")))
80+
7581
(defun lsp-dart-project-dart-command ()
7682
"Return the dart executable from dart SDK dir."
7783
(expand-file-name "bin/dart" (lsp-dart-project-get-sdk-dir)))

lsp-dart-test-support.el

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
(require 'lsp-mode)
2929

3030
(require 'lsp-dart-project)
31+
(require 'lsp-dart-dap)
3132

3233
(defconst lsp-dart-test-support-tests-buffer-name "*LSP Dart tests*")
3334

@@ -40,6 +41,11 @@
4041
(position nil)
4142
(kind nil))
4243

44+
(defface lsp-dart-code-lens-separator
45+
'((t :height 0.3))
46+
"The face used for separate code lens overlays."
47+
:group 'lsp-dart-test-support)
48+
4349
(defun lsp-dart-test-support--test-kind-p (kind)
4450
"Return non-nil if KIND is a test type."
4551
(or (string= kind "UNIT_TEST_TEST")
@@ -100,9 +106,8 @@ otherwise the dart command."
100106
escaped-str))
101107

102108
(defun lsp-dart-test-support-run (test)
103-
"Run Dart/Flutter test command in a compilation buffer for BUFFER file.
109+
"Run Dart/Flutter test command in a compilation buffer.
104110
If TEST is non nil, it will run only this test."
105-
(interactive)
106111
(lsp-dart-test-support--from-project-root
107112
(let* ((file-name (lsp-dart-test-file-name test))
108113
(buffer (get-file-buffer file-name))
@@ -125,6 +130,22 @@ If TEST is non nil, it will run only this test."
125130
t
126131
(lambda (_) lsp-dart-test-support-tests-buffer-name)))))
127132

133+
(defun lsp-dart-test-support-debug (test)
134+
"Debug Dart/Flutter TEST."
135+
(let* ((file-name (lsp-dart-test-file-name test))
136+
(names (lsp-dart-test-names test))
137+
(kind (lsp-dart-test-kind test))
138+
(test-name (lsp-dart-test-support--build-test-name names))
139+
(group-kind? (string= kind "UNIT_TEST_GROUP"))
140+
(regex (concat "^"
141+
(lsp-dart-test-support--escape-test-name test-name)
142+
(unless group-kind? "$")))
143+
(test-arg `("--name" ,regex)))
144+
(lsp-workspace-set-metadata "last-ran-test" test)
145+
(if (lsp-dart-test-support--flutter-test-file-p (get-file-buffer file-name))
146+
(lsp-dart-dap-debug-flutter-test file-name test-arg)
147+
(lsp-dart-dap-debug-dart-test file-name test-arg))))
148+
128149
(defun lsp-dart-test-support--build-overlay (buffer names kind range test-range)
129150
"Build an overlay in BUFFER for a test NAMES of KIND.
130151
RANGE is the overlay range to build.
@@ -138,20 +159,33 @@ TEST-RANGE is the test method range."
138159
(test (make-lsp-dart-test :file-name (buffer-file-name buffer)
139160
:names names
140161
:position beg
141-
:kind kind)))
162+
:kind kind))
163+
(separator (propertize " " 'font-lock-face 'lsp-dart-code-lens-separator)))
142164
(overlay-put overlay 'lsp-dart-test-code-lens t)
143165
(overlay-put overlay 'lsp-dart-test test)
144166
(overlay-put overlay 'lsp-dart-test-overlay-test-range (lsp--range-to-region test-range))
145167
(overlay-put overlay 'before-string
146168
(concat spaces
147-
(propertize "Run\n"
169+
(propertize "Run"
148170
'help-echo "mouse-1: Run this test"
149171
'mouse-face 'lsp-lens-mouse-face
150172
'local-map (-doto (make-sparse-keymap)
151-
(define-key [mouse-1] (lambda ()
173+
(define-key [mouse-1] (lambda ()
152174
(interactive)
153175
(lsp-dart-test-support-run test))))
154-
'font-lock-face 'lsp-lens-face)))))
176+
'font-lock-face 'lsp-lens-face)
177+
separator
178+
(propertize "|" 'font-lock-face 'lsp-lens-face)
179+
separator
180+
(propertize "Debug"
181+
'help-echo "mouse-1: Debug this test"
182+
'mouse-face 'lsp-lens-mouse-face
183+
'local-map (-doto (make-sparse-keymap)
184+
(define-key [mouse-1] (lambda ()
185+
(interactive)
186+
(lsp-dart-test-support-debug test))))
187+
'font-lock-face 'lsp-lens-face)
188+
"\n"))))
155189

156190
(defun lsp-dart-test-support--add-code-lens (buffer items &optional names)
157191
"Add test code lens to BUFFER for ITEMS.
@@ -183,12 +217,32 @@ PARAMS is the notification data from outline."
183217
"Return non-nil if FILE-NAME is a dart test files."
184218
(string-match "_test.dart" file-name))
185219

220+
(defun lsp-dart-test-support-test-overlay-at-point ()
221+
"Return test overlay at point.
222+
Return the overlay which has the smallest range of all test overlays in
223+
the current buffer."
224+
(-some--> (overlays-in (point-min) (point-max))
225+
(--filter (when (overlay-get it 'lsp-dart-test-code-lens)
226+
(-let* (((beg . end) (overlay-get it 'lsp-dart-test-overlay-test-range)))
227+
(and (>= (point) beg)
228+
(<= (point) end)))) it)
229+
(--min-by (-let* (((beg1 . end1) (overlay-get it 'lsp-dart-test-overlay-test-range))
230+
((beg2 . end2) (overlay-get other 'lsp-dart-test-overlay-test-range)))
231+
(and (< beg1 beg2)
232+
(> end1 end2))) it)))
233+
186234
(defun lsp-dart-test-support-run-last-test ()
187-
"Visit the last ran test going to the test definition."
235+
"Run last ran test."
188236
(if-let ((test (lsp-workspace-get-metadata "last-ran-test")))
189237
(lsp-dart-test-support-run test)
190238
(lsp-dart-project-log "No last test found.")))
191239

240+
(defun lsp-dart-test-support-debug-last-test ()
241+
"Debug last ran test."
242+
(if-let ((test (lsp-workspace-get-metadata "last-ran-test")))
243+
(lsp-dart-test-support-debug test)
244+
(lsp-dart-project-log "No last test found.")))
245+
192246
(defun lsp-dart-test-support-visit-last-test ()
193247
"Visit the last ran test going to the test definition."
194248
(-if-let* ((test (lsp-workspace-get-metadata "last-ran-test"))

0 commit comments

Comments
 (0)