@@ -670,29 +670,30 @@ This associates text properties to enable filtering and source navigation."
670
670
'follow-link t
671
671
'action (lambda (x ) (browse-url (button-get x 'url )))))
672
672
(nrepl-dbind-response frame (file line flags class method name var ns fn)
673
- (let ((flags (mapcar #'intern flags))) ; strings -> symbols
674
- (insert-text-button (format " %2 6s:%5 d %s /%s "
675
- (if (member 'repl flags) " REPL" file) line
676
- (if (member 'clj flags) ns class)
677
- (if (member 'clj flags) fn method))
678
- 'var var 'class class 'method method
679
- 'name name 'file file 'line line
680
- 'flags flags 'follow-link t
681
- 'action #'cider-stacktrace-navigate
682
- 'help-echo (cider-stacktrace-tooltip
683
- " View source at this location" )
684
- 'font-lock-face 'cider-stacktrace-face
685
- 'type 'cider-plain-button )
686
- (save-excursion
687
- (let ((p4 (point ))
688
- (p1 (search-backward " " ))
689
- (p2 (search-forward " /" ))
690
- (p3 (search-forward-regexp " [^/$]+" )))
691
- (put-text-property p1 p4 'font-lock-face 'cider-stacktrace-ns-face )
692
- (put-text-property p2 p3 'font-lock-face 'cider-stacktrace-fn-face )
693
- (put-text-property (line-beginning-position ) (line-end-position )
694
- 'cider-stacktrace-frame t )))
695
- (insert " \n " ))))))
673
+ (when (or class file fn method ns name)
674
+ (let ((flags (mapcar #'intern flags))) ; strings -> symbols
675
+ (insert-text-button (format " %2 6s:%5 d %s /%s "
676
+ (if (member 'repl flags) " REPL" file) (or line -1 )
677
+ (if (member 'clj flags) ns class)
678
+ (if (member 'clj flags) fn method))
679
+ 'var var 'class class 'method method
680
+ 'name name 'file file 'line line
681
+ 'flags flags 'follow-link t
682
+ 'action #'cider-stacktrace-navigate
683
+ 'help-echo (cider-stacktrace-tooltip
684
+ " View source at this location" )
685
+ 'font-lock-face 'cider-stacktrace-face
686
+ 'type 'cider-plain-button )
687
+ (save-excursion
688
+ (let ((p4 (point ))
689
+ (p1 (search-backward " " ))
690
+ (p2 (search-forward " /" ))
691
+ (p3 (search-forward-regexp " [^/$]+" )))
692
+ (put-text-property p1 p4 'font-lock-face 'cider-stacktrace-ns-face )
693
+ (put-text-property p2 p3 'font-lock-face 'cider-stacktrace-fn-face )
694
+ (put-text-property (line-beginning-position ) (line-end-position )
695
+ 'cider-stacktrace-frame t )))
696
+ (insert " \n " )))))))
696
697
697
698
(defun cider-stacktrace-render-compile-error (buffer cause )
698
699
" Emit into BUFFER the compile error CAUSE, and enable jumping to it."
@@ -844,7 +845,8 @@ the NAME. The whole group is prefixed by string INDENT."
844
845
(goto-char (next-single-property-change (point ) 'compile-error ))
845
846
(progn
846
847
(while (cider-stacktrace-next-cause))
847
- (goto-char (next-single-property-change (point ) 'flags )))))))))
848
+ (when-let (position (next-single-property-change (point ) 'flags ))
849
+ (goto-char position)))))))))
848
850
849
851
(defun cider-stacktrace-render (buffer causes &optional error-types )
850
852
" Emit into BUFFER useful stacktrace information for the CAUSES.
@@ -876,6 +878,54 @@ through the `cider-stacktrace-suppressed-errors' variable."
876
878
(cider-stacktrace-initialize causes)
877
879
(font-lock-refresh-defaults )))
878
880
881
+ (defun cider-stacktrace--analyze-stacktrace-op (stacktrace )
882
+ " Return the Cider NREPL op to analyze STACKTRACE."
883
+ (list " op" " analyze-stacktrace" " stacktrace" stacktrace))
884
+
885
+ (defun cider-stacktrace--stacktrace-request (stacktrace )
886
+ " Return the Cider NREPL request to analyze STACKTRACE."
887
+ (thread-last
888
+ (map-merge 'list
889
+ (list (cider-stacktrace--analyze-stacktrace-op stacktrace))
890
+ (cider--nrepl-print-request-map fill-column))
891
+ (seq-mapcat #'identity )))
892
+
893
+ (defun cider-stacktrace--analyze-render (causes )
894
+ " Render the CAUSES of the stacktrace analysis result."
895
+ (let ((buffer (get-buffer-create cider-error-buffer)))
896
+ (with-current-buffer buffer
897
+ (cider-stacktrace-mode)
898
+ (cider-stacktrace-render buffer (reverse causes))
899
+ (display-buffer buffer cider-jump-to-pop-to-buffer-actions))))
900
+
901
+ (defun cider-stacktrace-analyze-string (stacktrace )
902
+ " Analyze the STACKTRACE string and show the result."
903
+ (when (stringp stacktrace)
904
+ (set-text-properties 0 (length stacktrace) nil stacktrace))
905
+ (let (causes)
906
+ (cider-nrepl-send-request
907
+ (cider-stacktrace--stacktrace-request stacktrace)
908
+ (lambda (response )
909
+ (setq causes (nrepl-dbind-response response (class status)
910
+ (cond (class (cons response causes))
911
+ ((and (member " done" status) causes)
912
+ (cider-stacktrace--analyze-render causes)))))))))
913
+
914
+ (defun cider-stacktrace-analyze-at-point ()
915
+ " Analyze the stacktrace at point."
916
+ (interactive )
917
+ (cond ((thing-at-point 'sentence )
918
+ (cider-stacktrace-analyze-string (thing-at-point 'sentence )))
919
+ ((thing-at-point 'paragraph )
920
+ (cider-stacktrace-analyze-string (thing-at-point 'paragraph )))
921
+ (t (cider-stacktrace-analyze-in-region (region-beginning ) (region-end )))))
922
+
923
+ (defun cider-stacktrace-analyze-in-region (beg end )
924
+ " Analyze the stacktrace in the region between BEG and END."
925
+ (interactive (list (region-beginning ) (region-end )))
926
+ (let ((stacktrace (buffer-substring beg end)))
927
+ (cider-stacktrace-analyze-string stacktrace)))
928
+
879
929
(provide 'cider-stacktrace )
880
930
881
931
; ;; cider-stacktrace.el ends here
0 commit comments