branch: elpa/flamegraph
commit 19bc1877310f28df32c77d460a4eb6ceb4977acf
Author: Dmitry Gutov <[email protected]>
Commit: Dmitry Gutov <[email protected]>

    flamegraph-describe: Use the "regular" path for Elisp functions too
    
    That required some adaptations.
---
 flamegraph.el | 57 ++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 42 insertions(+), 15 deletions(-)

diff --git a/flamegraph.el b/flamegraph.el
index a6246d88f2..a6f4a6fec2 100644
--- a/flamegraph.el
+++ b/flamegraph.el
@@ -441,9 +441,9 @@ If POINT is non-nil, restore point there after drawing."
 
 (defun flamegraph-describe (&optional event)
   "Describe the frame at point or EVENT.
-For Emacs functions this shows the usual function documentation.  For
-other frames it shows a report: the sampled source line in context, the
-frame's sample counts, and buttons to its caller and callees."
+Shows a report: the frame's name (clickable for Emacs functions, to
+their usual documentation), the sampled source line in context, the
+sample counts, and buttons to the caller and callees."
   (interactive (list last-nonmenu-event))
   (when event
     (let ((posn (event-end event)))
@@ -451,12 +451,9 @@ frame's sample counts, and buttons to its caller and 
callees."
   (let ((frame (flamegraph--frame-at-point)))
     (if (null frame)
         (message "No frame at point")
-      (let* ((node (flamegraph-frame-node frame))
-             (entry (profiler-calltree-entry node)))
-        (if (or (and (symbolp entry) (fboundp entry)) (functionp entry))
-            (progn (require 'help-fns) (describe-function entry))
-          (flamegraph--describe-frame
-           node flamegraph--grand-total flamegraph--directory))))))
+      (flamegraph--describe-frame
+       (flamegraph-frame-node frame)
+       flamegraph--grand-total flamegraph--directory))))
 
 (defun flamegraph--entry-location (entry)
   "Extract a (FILE . LINE) source location embedded in ENTRY, or nil.
@@ -468,6 +465,22 @@ that \"perf script -F +srcline\" folded stacks use (e.g.
     (cons (match-string 1 entry)
           (string-to-number (match-string 2 entry)))))
 
+(defun flamegraph--symbol-location (symbol)
+  "Return (FILE . LINE) of SYMBOL's defining source, or nil.
+Uses `find-function-noselect', so handles autoloads and — when the user
+has set `find-function-C-source-directory' — subrs."
+  (when (and (symbolp symbol) (fboundp symbol))
+    (require 'find-func)
+    (condition-case nil
+        (let ((res (find-function-noselect symbol t)))
+          (when (consp res)
+            (let ((buf (car res)) (pos (cdr res)))
+              (when (and (bufferp buf) (buffer-file-name buf))
+                (with-current-buffer buf
+                  (cons (buffer-file-name buf)
+                        (line-number-at-pos pos)))))))
+      (error nil))))
+
 (defun flamegraph--resolve-source (file directory)
   "Expand FILE against the configured source directory and return it.
 A relative FILE is resolved against `flamegraph-source-directory', then
@@ -551,6 +564,7 @@ with `⋯'.  CONTEXT defaults to 4."
                  (def-pos (save-excursion
                             (goto-char (point-min))
                             (forward-line (1- line))
+                            (end-of-line)
                             (let ((p (point)))
                               (ignore-errors (beginning-of-defun))
                               (if (< (point) p) (point) (point-min)))))
@@ -559,11 +573,16 @@ with `⋯'.  CONTEXT defaults to 4."
                             (goto-char def-pos)
                             (ignore-errors (end-of-defun))
                             (if (> (point) def-pos) (point) (point-max))))
+                 ;; Anything that's plausibly a symbol — no whitespace,
+                 ;; brackets, parens, comma, semicolon.  Permissive on
+                 ;; purpose: Lisp names use `-' (and friends), C names use
+                 ;; `_'; `\_<...\_>' below enforces real symbol boundaries
+                 ;; in the target buffer's syntax.
                  (names (cl-remove-if-not
                          (lambda (n)
-                           (and (stringp n)
-                                (string-match-p
-                                 "\\`[A-Za-z_][A-Za-z0-9_]*\\'" n)))
+                           (and (stringp n) (not (string-empty-p n))
+                                (not (string-match-p
+                                      "[][[:space:]();,]" n))))
                          names))
                  (keep nil))
             ;; The sampled line and its immediate context.
@@ -632,8 +651,12 @@ frames, with Help-style back/forward navigation."
   (help-setup-xref (list #'flamegraph--describe-frame node total directory)
                    (called-interactively-p 'interactive))
   (let* ((entry (profiler-calltree-entry node))
-         (loc (and (stringp entry) (flamegraph--entry-location entry)))
-         (path (and loc (flamegraph--resolve-source (car loc) directory)))
+         (loc (cond ((stringp entry) (flamegraph--entry-location entry))
+                    ((symbolp entry) (flamegraph--symbol-location entry))))
+         (path (when loc
+                 (if (stringp entry)
+                     (flamegraph--resolve-source (car loc) directory)
+                   (car loc))))
          (count (profiler-calltree-count node))
          (kids (sort (copy-sequence (profiler-calltree-children node))
                      (lambda (a b) (> (profiler-calltree-count a)
@@ -642,7 +665,11 @@ frames, with Help-style back/forward navigation."
          (parent (profiler-calltree-parent node)))
     (with-help-window (help-buffer)
       (with-current-buffer standard-output
-        (insert (flamegraph--frame-display-name entry))
+        (if (and (symbolp entry) (fboundp entry))
+            (insert-text-button (flamegraph--frame-display-name entry)
+                                'type 'help-function
+                                'help-args (list entry))
+          (insert (flamegraph--frame-display-name entry)))
         (when loc
           (insert "  ")
           (insert-text-button

Reply via email to