aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilfred Hughes <me@wilfred.me.uk>2018-01-15 23:11:21 +0000
committerWilfred Hughes <me@wilfred.me.uk>2018-01-15 23:12:09 +0000
commit5eb8368c429833309abaa5c42e170e6fad84a19f (patch)
treece0ed4d4e273d4e50a88e02fdd796338185f81c1
parent5746e9dbe486c75fe4904575f9663c2da455013e (diff)
Don't error if a symbol is only defined in a .elc file
Fixes #88
-rw-r--r--CHANGELOG.md3
-rw-r--r--helpful.el88
-rw-r--r--test/unit-test.el11
3 files changed, 63 insertions, 39 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0803ef2..b778662 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
# v0.7
-Nothing yet.
+Fixed a crash on functions defined in a .elc when the .el file is not
+available.
# v0.6
diff --git a/helpful.el b/helpful.el
index 70b7e1a..272b4cc 100644
--- a/helpful.el
+++ b/helpful.el
@@ -754,6 +754,16 @@ If the source code cannot be found, return the sexp used."
(or (assoc sym completions)
(assoc-string sym completions))))
+(defun helpful--find-library-name (path)
+ "A wrapper around `find-library-name' that returns nil if PATH
+has no library with that name.
+
+This can happen when users have installed Emacs without its
+source code: they have e.g. org.elc but no org.el."
+ (condition-case _err
+ (find-library-name path)
+ (error nil)))
+
(defun helpful--definition (sym callable-p)
"Return a list (BUF POS OPENED) where SYM is defined.
@@ -781,45 +791,47 @@ buffer."
(cond
((and callable-p path)
- ;; Open `path' ourselves, so we can widen before searching.
-
- ;; Opening large.c files can be slow (e.g. when looking at
- ;; `defalias'), especially if the user has configured mode hooks.
- ;;
- ;; Bind `auto-mode-alist' to nil, so we open the buffer in
- ;; `fundamental-mode' if it isn't already open.
- (let (auto-mode-alist
- ;; Don't both setting buffer-local variables, it's
- ;; annoying to prompt the user since we immediately
- ;; discard the buffer.
- enable-local-variables)
- (setq buf (find-file-noselect (find-library-name path))))
-
- (unless (-contains-p initial-buffers buf)
- (setq opened t))
-
- ;; If it's a freshly opened buffer, we need to switch to the
- ;; correct mode so we can search correctly. Enable the mode, but
- ;; don't bother with mode hooks, because we just need the syntax
- ;; table for searching.
- (when opened
- (with-current-buffer buf
- (let (enable-local-variables)
- (delay-mode-hooks (normal-mode t)))))
+ ;; Convert foo.elc to foo.el.
+ (-when-let (src-path (helpful--find-library-name path))
+ ;; Open `path' ourselves, so we can widen before searching.
+ ;;
+ ;; Opening large.c files can be slow (e.g. when looking at
+ ;; `defalias'), especially if the user has configured mode hooks.
+ ;;
+ ;; Bind `auto-mode-alist' to nil, so we open the buffer in
+ ;; `fundamental-mode' if it isn't already open.
+ (let (auto-mode-alist
+ ;; Don't both setting buffer-local variables, it's
+ ;; annoying to prompt the user since we immediately
+ ;; discard the buffer.
+ enable-local-variables)
+ (setq buf (find-file-noselect src-path)))
+
+ (unless (-contains-p initial-buffers buf)
+ (setq opened t))
+
+ ;; If it's a freshly opened buffer, we need to switch to the
+ ;; correct mode so we can search correctly. Enable the mode, but
+ ;; don't bother with mode hooks, because we just need the syntax
+ ;; table for searching.
+ (when opened
+ (with-current-buffer buf
+ (let (enable-local-variables)
+ (delay-mode-hooks (normal-mode t)))))
- ;; Based on `find-function-noselect'.
- (with-current-buffer buf
- ;; `find-function-search-for-symbol' moves point. Prevent
- ;; that.
- (save-excursion
- ;; Narrowing has been fixed upstream:
- ;; http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=abd18254aec76b26e86ae27e91d2c916ec20cc46
- (save-restriction
- (widen)
- (setq pos
- (if primitive-p
- (cdr (find-function-C-source sym path nil))
- (cdr (find-function-search-for-symbol sym nil path))))))))
+ ;; Based on `find-function-noselect'.
+ (with-current-buffer buf
+ ;; `find-function-search-for-symbol' moves point. Prevent
+ ;; that.
+ (save-excursion
+ ;; Narrowing has been fixed upstream:
+ ;; http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=abd18254aec76b26e86ae27e91d2c916ec20cc46
+ (save-restriction
+ (widen)
+ (setq pos
+ (if primitive-p
+ (cdr (find-function-C-source sym path nil))
+ (cdr (find-function-search-for-symbol sym nil path)))))))))
(callable-p
;; Functions defined interactively may have an edebug property
;; that contains the location of the definition.
diff --git a/test/unit-test.el b/test/unit-test.el
index 2579316..6572a95 100644
--- a/test/unit-test.el
+++ b/test/unit-test.el
@@ -262,3 +262,14 @@ and that buffer has been killed, handle it gracefully."
(should
(equal (helpful--aliases 'emacs-repository-version nil)
(list 'emacs-bzr-version 'emacs-repository-version))))
+
+(defun helpful-fn-in-elc ())
+
+(ert-deftest helpful--elc-only ()
+ "Ensure we handle functions where we have the .elc but no .el
+file."
+ ;; Pretend that we've loaded `helpful-fn-in-elc' from /tmp/foo.elc.
+ (let ((load-history (cons '("/tmp/foo.elc" (defun . helpful-fn-in-elc))
+ load-history)))
+ ;; This should not error.
+ (helpful-function 'helpful-fn-in-elc)))