Skip to content

Commit 80f8eca

Browse files
authored
Merge pull request #15 from emacs-lsp/add-flutter-dap
Add Flutter DAP support
2 parents 7d224ba + aceb3ad commit 80f8eca

File tree

6 files changed

+539
-144
lines changed

6 files changed

+539
-144
lines changed

README.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ An example with a minimal configuration to start using `lsp-dart`:
2424
;; Optional packages
2525
(use-package lsp-ui :ensure t)
2626
(use-package company-capf :ensure t)
27-
2827
```
2928

3029
## Features
@@ -75,16 +74,22 @@ You can disable the feature setting `lsp-dart-flutter-widget-guides` to `nil`.
7574

7675
### Debug
7776

78-
For emacs debugging, `lsp-dart` uses [`dap-mode`](https://github.com/emacs-lsp/dap-mode#dart) to debug.
79-
You only need to run `dap-dart-setup` one time to setup the debugger.
77+
For debugging, `lsp-dart` uses [`dap-mode`](https://github.com/emacs-lsp/dap-mode#dart).
78+
You only need to run `dap-dart-setup` one time to setup the debugger to your Emacs and `dap-debug` to start the debug.
8079

8180
![debug](https://raw.githubusercontent.com/emacs-lsp/lsp-dart/screenshots/debug.gif)
8281

82+
#### Flutter
83+
84+
`lsp-dart` support Flutter debugging too via `dap-debug` with an option to select the device to debug.
85+
86+
![flutter-debug](https://raw.githubusercontent.com/emacs-lsp/lsp-dart/screenshots/flutter-debug.gif)
87+
8388
#### DevTools
8489

85-
You can also open the [Dart DevTools](https://dart.dev/tools/dart-devtools) on the current debug session with `lsp-dart-dap-open-devtools`.
90+
You can also open the [Dart DevTools](https://dart.dev/tools/dart-devtools) on the current debug session with `lsp-dart-dap-devtools-open`.
8691

87-
##### :warning:* Features only available for Dart SDK version 2.8.0 (currently the dev branch) or above.
92+
###### :warning:* Features only available for Dart SDK version 2.8.0 (currently the dev branch) or above.
8893

8994
## Supported settings
9095

@@ -105,7 +110,13 @@ You can also open the [Dart DevTools](https://dart.dev/tools/dart-devtools) on t
105110
* `lsp-dart-test-code-lens` - Enable the `Run` code lens on tests. Defaults to t.
106111
* `lsp-dart-dap-extension-version` - The debugger extension version. Defaults to [3.9.1](https://github.com/Dart-Code/Dart-Code/releases/tag/v3.9.1)
107112
* `lsp-dart-dap-debugger-path` - The debugger extension path.
108-
* `lsp-dart-dap-debugger-program` - The command to execute the debugger extension.
113+
* `lsp-dart-dap-dart-debugger-program` - The command to execute the debugger extension on dart projects.
114+
* `lsp-dart-dap-flutter-debugger-program` - The command to execute the debugger extension on flutter projects.
115+
* `lsp-dart-dap-debug-external-libraries` - Whether to enable the debug on external libraries. Defaults to nil.
116+
* `lsp-dart-dap-debug-sdk-libraries` - Whether to enable the debug on Dart SDK libraries. Defaults to nil.
117+
* `lsp-dart-dap-flutter-track-widget-creation` - Whether to pass –track-widget-creation to Flutter apps. Required to support 'Inspect Widget'.
118+
* `lsp-dart-dap-flutter-structured-errors` - Whether to pass `–track-widget-creation` to Flutter apps. Required to support 'Inspect Widget'.
119+
* `lsp-dart-dap-flutter-verbose-log` - Whether to enable verbose logs from Flutter DAP.
109120
* `lsp-dart-dap-devtools-theme` - The devtools theme when openning via `lsp-dart-dap-open-devtools`.
110121
* `lsp-dart-dap-devtools-hide-options` - What to hide when openning DevTools via `lsp-dart-dap-open-devtools`. Defaults to `debugger`.
111122

lsp-dart-dap-devtools.el

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
;;; lsp-dart-dap-devtools.el --- Support for Dart DevTools on debugger -*- lexical-binding: t; -*-
2+
;;
3+
;; Version: 1.8
4+
;; Keywords: languages, extensions
5+
;; Package-Requires: ((emacs "25.2") (lsp-mode "6.0") (dap-mode "0.3") (dash "2.14.1"))
6+
;; URL: https://github.com/emacs-lsp/lsp-dart.el
7+
;;
8+
;; This program is free software; you can redistribute it and/or modify
9+
;; it under the terms of the GNU General Public License as published by
10+
;; the Free Software Foundation, either version 3 of the License, or
11+
;; (at your option) any later version.
12+
13+
;; This program is distributed in the hope that it will be useful,
14+
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
;; GNU General Public License for more details.
17+
18+
;; You should have received a copy of the GNU General Public License
19+
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
;;
21+
;;; Commentary:
22+
;;
23+
;; Support for Dart DevTools on debugger
24+
;;
25+
;;; Code:
26+
27+
(require 'dash)
28+
(require 'lsp-mode)
29+
(require 'dap-mode)
30+
31+
(require 'lsp-dart-project)
32+
33+
(defcustom lsp-dart-dap-devtools-theme "dark"
34+
"The theme to Dart DevTools."
35+
:group 'lsp-dart
36+
:type 'string)
37+
38+
(defcustom lsp-dart-dap-devtools-hide-options "debugger"
39+
"What to hide when openning Dart DevTools."
40+
:group 'lsp-dart
41+
:type 'string)
42+
43+
(defconst lsp-dart-dap-devtools--buffer-name "*LSP Dart - DevTools*")
44+
(defconst lsp-dart-dap-devtools--pub-list-packages-buffer-name "*LSP Dart - Pub list packages*")
45+
46+
(defun lsp-dart-dap-devtools-log (msg &rest args)
47+
"Custom logger for MSG and ARGS."
48+
(apply #'lsp-dart-project-custom-log "[DEVTOOLS]" msg args))
49+
50+
(cl-defmethod dap-handle-event ((_event (eql dart.debuggerUris)) _session params)
51+
"Handle debugger uris EVENT for SESSION with PARAMS."
52+
(-let* (((&hash "vmServiceUri" vm-service-uri) params))
53+
(lsp-workspace-set-metadata "devtools-vm-service-uri" vm-service-uri)))
54+
55+
(defun lsp-dart-dap-devtools--clean-buffer (buffer)
56+
"Clean BUFFER content."
57+
(when (get-buffer buffer)
58+
(with-current-buffer buffer
59+
(erase-buffer))))
60+
61+
(defun lsp-dart-dap-devtools--buffer-whole-string (buffer)
62+
"Return all content of BUFFER."
63+
(with-current-buffer buffer
64+
(save-restriction
65+
(widen)
66+
(buffer-substring-no-properties (point-min) (point-max)))))
67+
68+
(defun lsp-dart-dap-devtools--check-devtools-uri (callback)
69+
"Check for uri on devtools buffer and call CALLBACK with it.
70+
If URI is not found on buffer, schedule re-check."
71+
(let ((content (lsp-dart-dap-devtools--buffer-whole-string lsp-dart-dap-devtools--buffer-name)))
72+
(if (string= content "")
73+
(run-with-idle-timer 0.3 nil #'lsp-dart-dap-devtools--check-devtools-uri callback)
74+
(-let* (((&hash "params" (&hash "host" "port")) (lsp--read-json content))
75+
(uri (concat host ":" (number-to-string port))))
76+
(lsp-workspace-set-metadata "dart-debug-devtools-uri" uri)
77+
(funcall callback uri)))))
78+
79+
(defun lsp-dart-dap-devtools--activated-p ()
80+
"Return non-nil if devtools is activated otherwise nil."
81+
(lsp-dart-dap-devtools--clean-buffer lsp-dart-dap-devtools--pub-list-packages-buffer-name)
82+
(let* ((pub (lsp-dart-project-get-pub-command))
83+
(_proc (call-process pub
84+
nil
85+
lsp-dart-dap-devtools--pub-list-packages-buffer-name
86+
nil
87+
"global" "list"))
88+
(content (lsp-dart-dap-devtools--buffer-whole-string lsp-dart-dap-devtools--pub-list-packages-buffer-name)))
89+
(string-match-p "devtools \\([0-9]\\.[0-9]\\.[0-9]\\)" content)))
90+
91+
(defun lsp-dart-dap-devtools--activate (callback)
92+
"Activate Dart Devtools via pub then call CALLBACK."
93+
(lsp-dart-dap-devtools-log "Activating...")
94+
(let ((pub (lsp-dart-project-get-pub-command)))
95+
(lsp-async-start-process
96+
(lambda ()
97+
(lsp-dart-dap-devtools-log "Activated successfully!")
98+
(funcall callback))
99+
(lambda (_) (lsp-dart-dap-devtools-log "Could not activate DevTools. \
100+
Try to activate manually running 'pub global activate devtools'"))
101+
pub "global" "activate" "devtools")))
102+
103+
(defun lsp-dart-dap-devtools--check-activated (callback)
104+
"Check if devtools is activated otherwise prompt for activate it.
105+
If it is already activated or after activated successfully, call CALLBACK."
106+
(if (lsp-dart-dap-devtools--activated-p)
107+
(funcall callback)
108+
(when (y-or-n-p "Dart DevTools needs to be activated with \
109+
'pub global activate devtools' to use this feature.\nActivate DevTools? ")
110+
(lsp-dart-dap-devtools--activate callback))))
111+
112+
(defun lsp-dart-dap-devtools--kill-proc (proc _session)
113+
"Kill the devtools PROC process of SESSION."
114+
(lsp-workspace-set-metadata "dart-debug-devtools-uri" nil)
115+
(delete-process proc)
116+
(lsp-dart-dap-devtools--clean-buffer lsp-dart-dap-devtools--buffer-name))
117+
118+
(defvar-local lsp-dart-dap-devtools--check-uri-timer nil)
119+
120+
(defun lsp-dart-dap-devtools--start (callback)
121+
"Start Dart DevTools process and call CALLBACK after started successfully."
122+
(lsp-dart-dap-devtools--check-activated
123+
(lambda ()
124+
(if-let ((uri (lsp-workspace-get-metadata "dart-debug-devtools-uri")))
125+
(funcall callback uri)
126+
(let* ((pub (lsp-dart-project-get-pub-command))
127+
(proc (start-process "Start DevTools"
128+
lsp-dart-dap-devtools--buffer-name
129+
pub "global" "run" "devtools"
130+
"--machine"
131+
"--enable-notifications"
132+
"--try-ports" "10")))
133+
(add-hook 'dap-terminated-hook (-partial #'lsp-dart-dap-devtools--kill-proc proc))
134+
(when lsp-dart-dap-devtools--check-uri-timer
135+
(cancel-timer lsp-dart-dap-devtools--check-uri-timer))
136+
(setq lsp-dart-dap-devtools--check-uri-timer
137+
(run-with-idle-timer 0.3 nil #'lsp-dart-dap-devtools--check-devtools-uri callback)))))))
138+
139+
(defun lsp-dart-dap-devtools--open (uri vm-service-uri)
140+
"Open DevTools URI with VM-SERVICE-URI param at browser."
141+
(let* ((params (url-build-query-string `((ide Emacs)
142+
(uri ,vm-service-uri)
143+
(hide ,lsp-dart-dap-devtools-hide-options)
144+
(theme ,lsp-dart-dap-devtools-theme))))
145+
(url (concat "http://" uri "?" params)))
146+
(browse-url url)))
147+
148+
149+
;;; Public interface
150+
151+
;;;###autoload
152+
(defun lsp-dart-dap-devtools-open ()
153+
"Open Dart DevTools for the current debug session."
154+
(interactive)
155+
(let ((session (dap--cur-session))
156+
(vm-service-uri (lsp-workspace-get-metadata "devtools-vm-service-uri")))
157+
(when (and session vm-service-uri)
158+
(lsp-dart-dap-devtools--start
159+
(lambda (uri)
160+
(lsp-dart-dap-devtools-log "Openning at browser...")
161+
(lsp-dart-dap-devtools--open uri vm-service-uri))))))
162+
163+
(provide 'lsp-dart-dap-devtools)
164+
;;; lsp-dart-dap-devtools.el ends here

0 commit comments

Comments
 (0)