[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/dart-mode 8f972c0 097/192: Add support for finding referen
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/dart-mode 8f972c0 097/192: Add support for finding references |
Date: |
Sun, 29 Aug 2021 11:01:58 -0400 (EDT) |
branch: elpa/dart-mode
commit 8f972c0ebdd036909cfe4504fede01b8f9be4681
Author: Natalie Weizenbaum <nex342@gmail.com>
Commit: Natalie Weizenbaum <nex342@gmail.com>
Add support for finding references
---
CHANGELOG.md | 3 ++
README.md | 8 ++++
dart-mode.el | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 147 insertions(+), 14 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 277544e..8691acf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,5 +6,8 @@
* Added a `dart-goto` command bound to `C-c C-g` which takes the user to the
definition of the Dart API under the cursor.
+* Added a `dart-find-refs` command bound to `C-c C-f` which shows a list of
+ references to the Dart API under the cursor.
+
* `dart-executable-path`'s default value is now set correctly even if the
executable named `dart` on the user's path is a symlink or a wrapper script.
diff --git a/README.md b/README.md
index 5c79c34..46f3681 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,7 @@
* [Error Checking](#error-checking)
* [Seeing Information](#seeing-information)
* [Navigation](#navigation)
+ * [Search](#search)
## Installation
@@ -53,3 +54,10 @@ When your cursor is on an identifier, you can press `C-c
C-g` to go to the exact
location that identifier was originally defined. This can even take you to the
Dart SDK's sources, or to packages that your library imports. Be careful when
you're there, though: any edits may corrupt your package cache!
+
+### Search
+
+You can search for all references to the identifier under your cursor by
+pressing `C-c C-f`. This will show you everywhere a method, getter, or setter
is
+called; everywhere a class is used as a type, constructed, or has static
methods
+called on it; everywhere a named argument is passed; and so on.
diff --git a/dart-mode.el b/dart-mode.el
index d6aa345..7fb0a13 100644
--- a/dart-mode.el
+++ b/dart-mode.el
@@ -180,13 +180,17 @@ FIELDS may be either identifiers or (ELISP-IDENTIFIER
JSON-IDENTIFIER) pairs."
,@body))))
(defun dart--property-string (text prop value)
- "Returns a copy of TEXT with PROP set to VALUE."
- (let ((copy (substring text 0)))
+ "Returns a copy of TEXT with PROP set to VALUE.
+
+Converts TEXT to a string if it's not already."
+ (let ((copy (substring (format "%s" text) 0)))
(put-text-property 0 (length copy) prop value copy)
copy))
(defun dart--face-string (text face)
- "Returns a copy of TEXT with its font face set to FACE."
+ "Returns a copy of TEXT with its font face set to FACE.
+
+Converts TEXT to a string if it's not already."
(dart--property-string text 'face face))
(defmacro dart--fontify-excursion (face &rest body)
@@ -414,6 +418,7 @@ Any stderr is logged using dart-log. Returns nil if the
exit code is non-0."
"Keymap used in dart-mode buffers.")
(define-key dart-mode-map (kbd "C-c ?") 'dart-show-hover)
(define-key dart-mode-map (kbd "C-c C-g") 'dart-goto)
+(define-key dart-mode-map (kbd "C-c C-f") 'dart-find-refs)
;;; CC indentation support
@@ -734,6 +739,12 @@ server sends a response to a request, it tags the response
with the ID of the
request. We look up the callback for the request in this alist and run it with
the JSON decoded server response.")
+(defvar dart--analysis-server-subscriptions nil
+ "An alist of event names to lists of callbacks to be called for those events.
+
+These callbacks take the event object and an opaque subcription
+object which can be passed to `dart--analysis-server-unsubscribe'.")
+
(defun dart-info (msg)
"Logs MSG to the dart log if `dart-debug' is non-nil."
(when dart-debug (dart-log msg)))
@@ -927,17 +938,48 @@ the callback for that request is given the json decoded
response."
(defun dart--analysis-server-handle-msg (msg)
"Handle the parsed MSG from the analysis server."
- (-when-let* ((id-assoc (assoc 'id msg))
- (raw-id (cdr id-assoc))
- (id (string-to-number raw-id)))
- (-if-let (resp-closure (assoc id dart--analysis-server-callbacks))
- (progn
- (setq dart--analysis-server-callbacks
- (assq-delete-all id dart--analysis-server-callbacks))
- (funcall (cdr resp-closure) msg))
- (-if-let (err (assoc 'error msg))
- (dart--analysis-server-on-error-callback msg)
- (dart-info (format "No callback was associated with id %s" raw-id))))))
+ (-if-let* ((raw-id (cdr (assoc 'id msg)))
+ (id (string-to-number raw-id)))
+ ;; This is a response to a request, so we should invoke a callback in
+ ;; dart--analysis-server-callbacks.
+ (-if-let (resp-closure (assoc id dart--analysis-server-callbacks))
+ (progn
+ (setq dart--analysis-server-callbacks
+ (assq-delete-all id dart--analysis-server-callbacks))
+ (funcall (cdr resp-closure) msg))mode
+ (-if-let (err (assoc 'error msg))
+ (dart--analysis-server-on-error-callback msg)
+ (dart-info (format "No callback was associated with id %s" raw-id))))
+
+ ;; This is a notification, so we should invoke callbacks in
+ ;; dart--analysis-server-subscriptions.
+ (-when-let* ((event (cdr (assoc 'event msg)))
+ (params (cdr (assoc 'params msg)))
+ (callbacks (cdr (assoc event
dart--analysis-server-subscriptions))))
+ (dolist (callback callbacks)
+ (let ((subscription (cons event callback)))
+ (apply callback params subscription nil))))))
+
+(defun dart--analysis-server-subscribe (event callback)
+ "Registers CALLBACK to be called for each EVENT of the given type.
+
+CALLBACK should take two parameters: the event object and an
+opaque subscription object that can be passed to
+`dart--analysis-server-unsubscribe'. Returns the same opaque
+subscription object."
+ (-if-let (cell (assoc event dart--analysis-server-subscriptions))
+ (nconc cell (list callback))
+ (push (cons event (list callback)) dart--analysis-server-subscriptions))
+ (cons event callback))
+
+(defun dart--analysis-server-unsubscribe (subscription)
+ "Unregisters the analysis server SUBSCRIPTION.
+
+SUBSCRIPTION is an opaque object provided by
+`dart--analysis-server-subscribe'."
+ (let ((event (car subscription))
+ (callback (cdr subscription)))
+ (delq callback (assoc event dart--analysis-server-subscriptions))))
;;;; Flycheck Error Reporting
@@ -1155,6 +1197,86 @@ minibuffer."
(goto-char (+ 1 offset))
(dart--flash-highlight offset length)))))))))
+;;;; Search
+
+(defun dart-find-refs (pos &optional include-potential)
+ (interactive "dP")
+ (-when-let (filename (buffer-file-name))
+ (dart--analysis-server-send
+ "search.findElementReferences"
+ `(("file" . ,filename)
+ ("offset" . ,pos)
+ ("includePotential" . ,(or include-potential json-false)))
+ (lambda (response)
+ (-when-let (result (cdr (assoc 'result response)))
+ (lexical-let* (buffer
+ (search-id (cdr (assoc 'id result))))
+ (with-current-buffer-window
+ "*Dart Search*" nil nil
+ (setq buffer (current-buffer))
+
+ (lexical-let* ((element (cdr (assoc 'element result)))
+ (name (cdr (assoc 'name element)))
+ (location (cdr (assoc 'location element))))
+ (insert "References to ")
+ (insert-button
+ name
+ 'action (lambda (_) (dart--goto-location location)))
+ (insert ":\n\n"))
+
+ (dart--analysis-server-subscribe
+ "search.results"
+ (lambda (event subscription)
+ (with-current-buffer buffer
+ (dart--json-let event (id results (is-last isLast))
+ (when (equal id search-id)
+ (when (eq is-last t)
+ (dart--analysis-server-unsubscribe subscription))
+
+ (save-excursion
+ (goto-char (point-max))
+ (loop
+ for result across results
+ do (lexical-let* ((location (cdr (assoc 'location
result)))
+ (path (cdr (assoc 'path result))))
+ (let ((start (point))
+ (buffer-read-only nil))
+ (dart--fontify-excursion '(compilation-info
underline)
+ (when (cl-some
+ (lambda (element)
+ (equal (cdr (assoc 'kind element))
"CONSTRUCTOR"))
+ path)
+ (insert "new "))
+
+ (insert
+ (loop for element across path
+ unless (member (cdr (assoc 'kind
element))
+ '("COMPILATION_UNIT"
"FILE" "LIBRARY" "PARAMETER"))
+ unless (string-empty-p (cdr (assoc
'name element)))
+ collect (cdr (assoc 'name element))
into names
+ finally return (mapconcat 'identity
(reverse names) ".")))
+
+ (make-text-button
+ start (point)
+ 'action (lambda (_) (dart--goto-location
location))))
+
+ (let ((file (cdr (assoc 'file location)))
+ (line (cdr (assoc 'startLine location)))
+ (column (cdr (assoc 'startColumn
location))))
+ (insert " " file ":"
+ (dart--face-string line
'compilation-line-number) ":"
+ (dart--face-string column
'compilation-column-number) ?\n))))))))))))
+
+ (select-window (get-buffer-window buffer))
+ (forward-line 2)))))))
+
+(defun dart--goto-location (location)
+ "Sends the user to the analysis server LOCATION."
+ (dart--json-let location (file offset length)
+ (find-file file)
+ (goto-char (+ 1 offset))
+ (dart--flash-highlight offset length)))
+
;;; Formatting
(defcustom dartfmt-command "dartfmt"
- [nongnu] elpa/dart-mode ecf3191 091/192: Add a command to show hover information, (continued)
- [nongnu] elpa/dart-mode ecf3191 091/192: Add a command to show hover information, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode 0cf32d5 092/192: Highlight hover descriptions, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode c4a5045 096/192: Add support for navigation, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode a1f36f4 094/192: Allow dart-show-hover to display in a new buffer, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode 89a2d4e 100/192: Add a special mode for popups, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode eca3f15 105/192: Add the ability to autocomplete parameters, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode d333a73 102/192: Add an analyzer-based auto-complete, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode d507fa1 101/192: Add a binding to re-run searches, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode a2ab55b 114/192: Make more thorough use of dash, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode c11d02a 137/192: Remedy invalid file path format, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode 8f972c0 097/192: Add support for finding references,
ELPA Syncer <=
- [nongnu] elpa/dart-mode 848f983 104/192: Show docs for expansions, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode 6bc08f7 136/192: Adds failing test against dart dev, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode 9c9a63e 130/192: Fix dart-format, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode 1f27d03 119/192: Properly set up font-lock variables, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode 6397b3d 115/192: Clean up the way the SDK is configured, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode e9cd33d 109/192: Use proper private name convention, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode a087c75 099/192: Add a result counter in search results, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode 847707d 129/192: Require final newline, like dartfmt, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode 570e58c 116/192: Refactor formatter support, ELPA Syncer, 2021/08/29
- [nongnu] elpa/dart-mode d4da484 126/192: Removes nil c-syntactic-context (#56), ELPA Syncer, 2021/08/29