Skip to content

Commit a89ae43

Browse files
committed
Add main code lens support
1 parent 14d11f9 commit a89ae43

File tree

6 files changed

+277
-110
lines changed

6 files changed

+277
-110
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ You can also open the [Dart DevTools](https://dart.dev/tools/dart-devtools) on t
167167
| `lsp-dart-flutter-outline-position-params` | The Flutter outline tree position params | Left side |
168168
| `lsp-dart-flutter-fringe-colors` | Enable the Flutter colors on fringe. | `t` |
169169
| `lsp-dart-flutter-widget-guides` | Enable the Flutter widget guide lines from parent to child widgets | `t` |
170-
| `lsp-dart-test-code-lens` | Enable the `Run` code lens on tests. | `t` |
170+
| `lsp-dart-main-code-lens` | Enable the `Run|Debug` code lens on main methods. | `t` |
171+
| `lsp-dart-test-code-lens` | Enable the `Run|Debug` code lens on tests. | `t` |
171172
| `lsp-dart-dap-extension-version` | The debugger extension version. | 3.10.1 |
172173
| `lsp-dart-dap-debugger-path` | The debugger extension path | Check source file |
173174
| `lsp-dart-dap-dart-debugger-program` | The command to execute the debugger extension on dart projects. | Check source file |

lsp-dart-code-lens.el

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
;;; lsp-dart-code-lens.el --- Code lens support for LSP Dart -*- lexical-binding: t; -*-
2+
;;
3+
;; This program is free software; you can redistribute it and/or modify
4+
;; it under the terms of the GNU General Public License as published by
5+
;; the Free Software Foundation, either version 3 of the License, or
6+
;; (at your option) any later version.
7+
8+
;; This program is distributed in the hope that it will be useful,
9+
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
;; GNU General Public License for more details.
12+
13+
;; You should have received a copy of the GNU General Public License
14+
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
;;
16+
;; This file is not part of GNU Emacs.
17+
;;
18+
;;; Commentary:
19+
;;
20+
;; Code lens support for LSP Dart
21+
;;
22+
;;; Code:
23+
24+
(require 'dash)
25+
(require 'ht)
26+
27+
(require 'lsp-dart-dap)
28+
(require 'lsp-dart-test-support)
29+
30+
(defcustom lsp-dart-main-code-lens t
31+
"Enable the main code lens overlays."
32+
:type 'boolean
33+
:group 'lsp-dart)
34+
35+
(defcustom lsp-dart-test-code-lens t
36+
"Enable the test code lens overlays."
37+
:type 'boolean
38+
:group 'lsp-dart)
39+
40+
(defface lsp-dart-code-lens-separator
41+
'((t :height 0.3))
42+
"The face used for separate test code lens overlays."
43+
:group 'lsp-dart-test-support)
44+
45+
46+
;; Internal
47+
48+
(defun lsp-dart-code-lens--find-main-outline (children)
49+
"Return the main outline if exists in CHILDREN."
50+
(if-let (main (seq-find (-lambda ((&hash "element" (&hash "name")))
51+
(string= name "main"))
52+
children))
53+
main
54+
(->> children
55+
(seq-map (-lambda ((&hash "children"))
56+
(when children
57+
(lsp-dart-code-lens--find-main-outline children))))
58+
-first-item)))
59+
60+
(defun lsp-dart-code-lens--build-action (label help-echo action-fn &rest action-args)
61+
"Build a String action to overlay.
62+
LABEL is teh text to display.
63+
HELP-ECHO is the mouse hover text.
64+
ACTION-FN is the function to be called with ACTION-ARGS when clicked."
65+
(propertize label
66+
'pointer 'hand
67+
'help-echo help-echo
68+
'mouse-face 'lsp-lens-mouse-face
69+
'local-map (-doto (make-sparse-keymap)
70+
(define-key [mouse-1] (lambda ()
71+
(interactive)
72+
(apply action-fn action-args))))
73+
'font-lock-face 'lsp-lens-face))
74+
75+
(defun lsp-dart-code-lens--run-application (path test-file?)
76+
"Run Dart/Flutter application from PATH.
77+
If TEST-FILE? debug tests otherwise debug application."
78+
(if test-file?
79+
(if (lsp-dart--flutter-project-p)
80+
(lsp-dart-dap-debug-flutter-test path)
81+
(lsp-dart-dap-debug-dart-test path))
82+
(if (lsp-dart--flutter-project-p)
83+
(lsp-dart-dap-run-flutter path)
84+
(lsp-dart-dap-run-dart path))))
85+
86+
(defun lsp-dart-code-lens--debug-application (path test-file?)
87+
"Debug Dart/Flutter application from PATH.
88+
If TEST-FILE? debug tests otherwise debug application."
89+
(if test-file?
90+
(if (lsp-dart--flutter-project-p)
91+
(lsp-dart-dap-debug-flutter-test path)
92+
(lsp-dart-dap-debug-dart-test path))
93+
(if (lsp-dart--flutter-project-p)
94+
(lsp-dart-dap-debug-flutter path)
95+
(lsp-dart-dap-debug-dart path))))
96+
97+
(defun lsp-dart-code-lens--build-main-overlay (buffer main-outline)
98+
"Build main overlay code lens from MAIN-OUTLINE into BUFFER."
99+
(-let* (((&hash "range") main-outline)
100+
(beg-position (gethash "character" (gethash "start" range)))
101+
((beg . end) (lsp--range-to-region range))
102+
(beg-line (progn (goto-char beg)
103+
(line-beginning-position)))
104+
(overlay (make-overlay beg-line end buffer))
105+
(spaces (make-string beg-position ?\s))
106+
(test-file? (lsp-dart-test-file-p (buffer-file-name buffer)))
107+
(separator (propertize " " 'font-lock-face 'lsp-dart-code-lens-separator)))
108+
(overlay-put overlay 'lsp-dart-main-code-lens t)
109+
(overlay-put overlay 'before-string
110+
(concat spaces
111+
(lsp-dart-code-lens--build-action "Run"
112+
(if test-file?
113+
"mouse-1: Run tests"
114+
"mouse-1: Run application")
115+
#'lsp-dart-code-lens--run-application
116+
(buffer-file-name buffer)
117+
test-file?)
118+
separator
119+
(propertize "|" 'font-lock-face 'lsp-lens-face)
120+
separator
121+
(lsp-dart-code-lens--build-action "Debug"
122+
(if test-file?
123+
"mouse-1: Debug tests"
124+
"mouse-1: Debug application")
125+
#'lsp-dart-code-lens--debug-application
126+
(buffer-file-name buffer)
127+
test-file?)
128+
"\n"))))
129+
130+
(defun lsp-dart-code-lens--build-test-overlay (buffer names kind range test-range)
131+
"Build an overlay in BUFFER for a test NAMES of KIND.
132+
RANGE is the overlay range to build.
133+
TEST-RANGE is the test method range."
134+
(-let* ((beg-position (gethash "character" (gethash "start" range)))
135+
((beg . end) (lsp--range-to-region range))
136+
(beg-line (progn (goto-char beg)
137+
(line-beginning-position)))
138+
(spaces (make-string beg-position ?\s))
139+
(overlay (make-overlay beg-line end buffer))
140+
(test (make-lsp-dart-test :file-name (buffer-file-name buffer)
141+
:names names
142+
:position beg
143+
:kind kind))
144+
(separator (propertize " " 'font-lock-face 'lsp-dart-code-lens-separator)))
145+
(overlay-put overlay 'lsp-dart-test-code-lens t)
146+
(overlay-put overlay 'lsp-dart-test test)
147+
(overlay-put overlay 'lsp-dart-code-lens-overlay-test-range (lsp--range-to-region test-range))
148+
(overlay-put overlay 'before-string
149+
(concat spaces
150+
(lsp-dart-code-lens--build-action "Run"
151+
"mouse-1: Run this test"
152+
#'lsp-dart-test--run
153+
test)
154+
separator
155+
(propertize "|" 'font-lock-face 'lsp-lens-face)
156+
separator
157+
(lsp-dart-code-lens--build-action "Debug"
158+
"mouse-1: Debug this test"
159+
#'lsp-dart-test--debug
160+
test)
161+
"\n"))))
162+
163+
(defun lsp-dart-code-lens--add-test (buffer items &optional names)
164+
"Add test code lens to BUFFER for ITEMS.
165+
NAMES arg is optional and are the group of tests representing a test name."
166+
(seq-doseq (item items)
167+
(-let* (((&hash "children" "codeRange" test-range "element"
168+
(&hash "kind" "name" "range")) item)
169+
(test-kind? (lsp-dart-test--test-kind-p kind))
170+
(concatened-names (if test-kind?
171+
(append names (list name))
172+
names)))
173+
(when test-kind?
174+
(lsp-dart-code-lens--build-test-overlay buffer (append names (list name)) kind range test-range))
175+
(unless (seq-empty-p children)
176+
(lsp-dart-code-lens--add-test buffer children concatened-names)))))
177+
178+
179+
;; Public
180+
181+
(defun lsp-dart-code-lens-check-main (uri outline)
182+
"Check URI and OUTLINE for main method adding lens to it."
183+
(-let* (((&hash "children") outline)
184+
(buffer (lsp--buffer-for-file (lsp--uri-to-path uri)))
185+
(main-outline (lsp-dart-code-lens--find-main-outline children)))
186+
(when buffer
187+
(with-current-buffer buffer
188+
(remove-overlays (point-min) (point-max) 'lsp-dart-main-code-lens t)
189+
(save-excursion
190+
(lsp-dart-code-lens--build-main-overlay buffer main-outline))))))
191+
192+
(defun lsp-dart-code-lens-check-test (uri outline)
193+
"Check URI and OUTLINE for test adding lens to it."
194+
(when (lsp-dart-test-file-p uri)
195+
(-let* (((&hash "children") outline)
196+
(buffer (lsp--buffer-for-file (lsp--uri-to-path uri))))
197+
(when buffer
198+
(with-current-buffer buffer
199+
(remove-overlays (point-min) (point-max) 'lsp-dart-test-code-lens t)
200+
(save-excursion
201+
(lsp-dart-code-lens--add-test buffer children)))))))
202+
203+
(provide 'lsp-dart-code-lens)
204+
;;; lsp-dart-code-lens.el ends here

lsp-dart-dap.el

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -160,18 +160,6 @@ Required to support 'Inspect Widget'."
160160
(dap-register-debug-template "Dart :: Debug"
161161
(list :type "dart"))
162162

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

177165
(declare-function all-the-icons-faicon "ext:all-the-icons")
@@ -193,13 +181,15 @@ Check for icons if supports it."
193181
Call CALLBACK when the device is chosen and started successfully."
194182
(lsp-dart-flutter-daemon-get-emulators
195183
(lambda (devices)
196-
(-let* ((chosen-device (dap--completing-read "Select a device to use: "
197-
devices
198-
(-lambda ((&hash "id" "name" "platformType" platform))
199-
(lsp-dart-dap--device-label id name platform))
200-
nil
201-
t)))
202-
(lsp-dart-flutter-daemon-launch chosen-device callback)))))
184+
(if (seq-empty-p devices)
185+
(lsp-dart-log "No devices found. Try to create a device first via `flutter emulators` command")
186+
(-let* ((chosen-device (dap--completing-read "Select a device to use: "
187+
devices
188+
(-lambda ((&hash "id" "name" "platformType" platform))
189+
(lsp-dart-dap--device-label id name platform))
190+
nil
191+
t)))
192+
(lsp-dart-flutter-daemon-launch chosen-device callback))))))
203193

204194
(defun lsp-dart-dap--populate-flutter-start-file-args (conf)
205195
"Populate CONF with the required arguments for Flutter debug."
@@ -297,7 +287,54 @@ Call CALLBACK when the device is chosen and started successfully."
297287
(cl-defmethod dap-handle-event ((_event (eql dart.testRunNotification)) _session _params)
298288
"Ignore this event.")
299289

300-
(defun lsp-dart-dap-debug-flutter-test (path args)
290+
291+
;; Public
292+
293+
(defun lsp-dart-dap-run-dart (path)
294+
"Start Dart application without debugging from PATH."
295+
(-> (list :type "dart"
296+
:name "Dart Run"
297+
:program path
298+
:noDebug t
299+
:shouldConnectDebugger nil)
300+
lsp-dart-dap--populate-dart-start-file-args
301+
dap-start-debugging))
302+
303+
(defun lsp-dart-dap-run-flutter (path)
304+
"Start Flutter app without debugging from PATH."
305+
(-> (list :type "flutter"
306+
:name "Flutter Run"
307+
:program path
308+
:noDebug t
309+
:shouldConnectDebugger nil)
310+
lsp-dart-dap--populate-flutter-start-file-args
311+
(funcall #'dap-start-debugging)))
312+
313+
(defun lsp-dart-dap-debug-dart (path)
314+
"Debug dart application from PATH."
315+
(-> (list :program path)
316+
lsp-dart-dap--populate-dart-start-file-args
317+
dap-start-debugging))
318+
319+
(defun lsp-dart-dap-debug-flutter (path)
320+
"Debug Flutter application from PATH."
321+
(-> (list :program path)
322+
lsp-dart-dap--populate-flutter-start-file-args
323+
(funcall #'dap-start-debugging)))
324+
325+
(defun lsp-dart-dap-debug-dart-test (path &optional args)
326+
"Start dart test debugging from PATH with ARGS."
327+
(-> (list :type "dart"
328+
:name "Dart Tests"
329+
:dap-server-path lsp-dart-dap-dart-test-debugger-program
330+
:program path
331+
:noDebug nil
332+
:shouldConnectDebugger t
333+
:args args)
334+
lsp-dart-dap--base-debugger-args
335+
dap-start-debugging))
336+
337+
(defun lsp-dart-dap-debug-flutter-test (path &optional args)
301338
"Start dart test debugging from PATH with ARGS."
302339
(-> (list :name "Flutter Tests"
303340
:type "flutter"
@@ -310,6 +347,9 @@ Call CALLBACK when the device is chosen and started successfully."
310347
lsp-dart-dap--base-debugger-args
311348
dap-start-debugging))
312349

350+
351+
;; Public Interface
352+
313353
;;;###autoload
314354
(defun lsp-dart-dap-flutter-hot-restart ()
315355
"Hot restart current Flutter debug session."

lsp-dart-outline.el

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
(require 'lsp-treemacs)
2323

2424
(require 'lsp-dart-utils)
25-
(require 'lsp-dart-test-support)
25+
(require 'lsp-dart-code-lens)
2626
(require 'lsp-dart-flutter-widget-guide)
2727

2828
(defcustom lsp-dart-outline t
@@ -216,11 +216,13 @@ Focus on it if IGNORE-FOCUS? is nil."
216216
PARAMS outline notification data sent.
217217
It updates the outline view if it already exists."
218218
(lsp-dart-outline--set-metadata workspace params "current-outline")
219-
(when (and lsp-dart-test-code-lens
220-
(lsp-dart-test-file-p (gethash "uri" params)))
221-
(lsp-dart-test-check-code-lens params))
222-
(when (get-buffer-window "*Dart Outline*")
223-
(lsp-dart-outline--show-outline (lsp--buffer-for-file (lsp--uri-to-path (gethash "uri" params))) t)))
219+
(-let (((&hash "uri" "outline") params))
220+
(when lsp-dart-main-code-lens
221+
(lsp-dart-code-lens-check-main uri outline))
222+
(when lsp-dart-test-code-lens
223+
(lsp-dart-code-lens-check-test uri outline))
224+
(when (get-buffer-window "*Dart Outline*")
225+
(lsp-dart-outline--show-outline (lsp--buffer-for-file (lsp--uri-to-path uri)) t))))
224226

225227
(defun lsp-dart-outline-handle-flutter-outline (workspace params)
226228
"Flutter outline notification handling from WORKSPACE.

0 commit comments

Comments
 (0)