commit 217b38398bfa523c48f630b06b21427974d93e1d
parent 8df39c15d290cd499ef261de868191d3fc84f75a
Author: Wilfred Hughes <me@wilfred.me.uk>
Date: Fri, 10 Dec 2021 21:38:58 -0800
Rewrite helpful--tree-any-p as a loop
Fixes #279
Diffstat:
3 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
@@ -8,6 +8,8 @@ Fixed issue with displaying circular data structures.
Fixed a crash in `helpful-variable` in files that weren't
syntactically valid lisp.
+Fixed stack overflow in macroexpanding large s-expressions (#279).
+
# v0.18
Show the original value for custom variables whose value has changed.
diff --git a/helpful.el b/helpful.el
@@ -1317,13 +1317,17 @@ If it fails, attempt to partially macroexpand FORM."
(defun helpful--tree-any-p (pred tree)
"Walk TREE, applying PRED to every subtree.
Return t if PRED ever returns t."
- (cond
- ((null tree) nil)
- ((funcall pred tree) t)
- ((not (consp tree)) nil)
- (t (or
- (helpful--tree-any-p pred (car tree))
- (helpful--tree-any-p pred (cdr tree))))))
+ (catch 'found
+ (let ((stack (list tree)))
+ (while stack
+ (let ((next (pop stack)))
+ (cond
+ ((funcall pred next)
+ (throw 'found t))
+ ((consp next)
+ (push (car next) stack)
+ (push (cdr next) stack))))))
+ nil))
(defun helpful--find-by-macroexpanding (buf sym callable-p)
"Search BUF for the definition of SYM by macroexpanding
diff --git a/test/helpful-unit-test.el b/test/helpful-unit-test.el
@@ -1072,3 +1072,7 @@ find the source code."
"Ensure that we can describe an autoloaded function
that has advice attached before it is loadedl."
(helpful-function 'ruby-mode))
+
+(ert-deftest helpful--tree-any-p ()
+ (should (helpful--tree-any-p (lambda (x) (eq x 1)) '((((1))))))
+ (should (helpful--tree-any-p (lambda (x) (eq x 1)) (cons 2 1))))