[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/haskell-tng-mode 3ea52c1 341/385: special case jumping to
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/haskell-tng-mode 3ea52c1 341/385: special case jumping to inplace packages |
Date: |
Wed, 6 Oct 2021 00:00:00 -0400 (EDT) |
branch: elpa/haskell-tng-mode
commit 3ea52c1a8433318abb0d267883a66393c29fe7cd
Author: Tseen She <ts33n.sh3@gmail.com>
Commit: Tseen She <ts33n.sh3@gmail.com>
special case jumping to inplace packages
---
haskell-tng-hsinspect.el | 130 ++++++++++++++++++++++++++---------------------
1 file changed, 73 insertions(+), 57 deletions(-)
diff --git a/haskell-tng-hsinspect.el b/haskell-tng-hsinspect.el
index cc01612..f56944f 100644
--- a/haskell-tng-hsinspect.el
+++ b/haskell-tng-hsinspect.el
@@ -18,6 +18,7 @@
(require 'subr-x)
(require 'tar-mode)
(require 'url)
+(require 'xref)
;; Popups are not supported in stock Emacs so an extension is necessary:
;; https://emacs.stackexchange.com/questions/53373
@@ -50,9 +51,7 @@ A prefix argument ensures that caches are flushes."
(defun haskell-tng-jump-to-definition (&optional alt)
"Consult the `imports' in scope to calculate the symbol at point,
then find the package using the `index', then visit the
-definition of the symbol in the build tool's source archive.
-
-TODO: support local / git packages by consulting `plan.json'"
+definition of the symbol in the build tool's source archive."
(interactive "P")
;; TODO better error reporting when any of these things fail
(when-let* ((imports (haskell-tng--hsinspect-imports nil alt))
@@ -62,42 +61,46 @@ TODO: support local / git packages by consulting
`plan.json'"
(found (haskell-tng--hsinspect-qualify imports sym)))
(pcase-let* ((`(,imported . ,name) (haskell-tng--string-split-last found
"."))
(`(,srcid . ,module) (haskell-tng--hsinspect-follow index nil
imported name))
- ;; FIXME filter out inplace things
+ (`(,pkg . _) (haskell-tng--hsinspect-index-get-module index
srcid module) )
+ (inplace (alist-get 'inplace pkg))
(tarball (haskell-tng--hsinspect-srcid-source srcid))
(file (concat
;; TODO string-replace would be nice...
(mapconcat 'identity (split-string module (rx "."))
"/" )
".hs")))
- (when (not (file-exists-p tarball))
- ;; We can't expect stack to reveal source locations because it
- ;; obfuscates all downloads. Cabal has "cabal get" but it is broken.
- ;; WORKAROUND https://github.com/haskell/cabal/issues/6443
- (let ((remote (haskell-tng--hsinspect-hackage-source srcid))
- (dir (file-name-directory tarball)))
- (unless (file-directory-p dir)
- (make-directory dir t))
- (message "%s was not found, attempting to download %s" tarball
remote)
- (url-copy-file remote tarball)))
-
- (message "Loading %s from %s" sym tarball)
- (find-file tarball)
- ;; TODO it would be a faster UX if we used ZIP instead of TAR.GZ because
- ;; this requires us to decompress the entire file to find the index,
- ;; and then again until we reach the entry we want to load. But that
- ;; would come with the cost of recompressing, plus the storage cost
- ;; of caching it all.
- (let ((archive (current-buffer)))
- (goto-char (point-min))
- (re-search-forward (rx-to-string `(: (* any) ,file)))
- (tar-extract)
- (kill-buffer archive)
- (read-only-mode 1)
- (goto-char (point-min))
- ;; TODO re-use the imenu top-level parser, this is a massive hack
- (re-search-forward (rx line-start "import" word-end) nil t)
- (or
- (re-search-forward (rx-to-string `(: (| bol "| " "data " "type "
"class ") ,name symbol-end)) nil t)
- (re-search-forward (rx-to-string `(: symbol-start ,name
symbol-end))))))))
+ (if inplace
+ ;; TODO support local / git packages by consulting `plan.json'
+ ;; TODO or should we error until it is supported properly?
+ (xref-find-definitions name)
+ (when (not (file-exists-p tarball))
+ ;; We can't expect stack to reveal source locations because it
+ ;; obfuscates all downloads. Cabal has "cabal get" but it is broken.
+ ;; WORKAROUND https://github.com/haskell/cabal/issues/6443
+ (let ((remote (haskell-tng--hsinspect-hackage-source srcid))
+ (dir (file-name-directory tarball)))
+ (unless (file-directory-p dir)
+ (make-directory dir t))
+ (message "%s was not found, attempting to download %s" tarball
remote)
+ (url-copy-file remote tarball)))
+ (message "Loading %s from %s" sym tarball)
+ (find-file tarball)
+ ;; TODO it would be a faster UX if we used ZIP instead of TAR.GZ
because
+ ;; this requires us to decompress the entire file to find the
index,
+ ;; and then again until we reach the entry we want to load. But
that
+ ;; would come with the cost of recompressing, plus the storage
cost
+ ;; of caching it all.
+ (let ((archive (current-buffer)))
+ (goto-char (point-min))
+ (re-search-forward (rx-to-string `(: (* any) ,file)))
+ (tar-extract)
+ (kill-buffer archive)
+ (read-only-mode 1)
+ (goto-char (point-min))
+ ;; TODO re-use the imenu top-level parser, this is a massive hack
+ (re-search-forward (rx line-start "import" word-end) nil t)
+ (or
+ (re-search-forward (rx-to-string `(: (| bol "| " "data " "type "
"class ") ,name symbol-end)) nil t)
+ (re-search-forward (rx-to-string `(: symbol-start ,name
symbol-end)))))))))
(defun haskell-tng--string-split-last (str sep)
"Return `(front . back)' of a STR split on the last SEP."
@@ -246,6 +249,21 @@ Respects the `C-u' cache invalidation convention."
(lambda (names) (member sym (seq-map #'cdr names)))
imports))))
+(defun haskell-tng--hsinspect-index-get-module (index srcid module)
+ "Return the (pkg-entry . module-entry) for SRCID and MODULE."
+ ;; TODO a more general solution that also searches for NAME would help
simplify this file
+ (car
+ (seq-mapcat
+ (lambda (pkg-entry)
+ (let ((srcid_ (alist-get 'srcid pkg-entry)))
+ (when (or (null srcid) (equal srcid srcid_))
+ (when-let (found (seq-find
+ (lambda (module-entry)
+ (equal module (alist-get 'module module-entry)))
+ (alist-get 'modules pkg-entry)))
+ (list (cons pkg-entry found))))))
+ index)))
+
(defun haskell-tng--hsinspect-follow (index srcid module name)
"Follow re-exports of MODULE to find which (srcid . module)
originally defined NAME.
@@ -254,33 +272,31 @@ The original module may not be exported and is therefore
not
present in the index. If an unexported module exports another
unexported module's definition, we are unable to locate it."
;; TODO probably doesn't work for 'tycon
- ;; TODO use seq-find instead of seq-mapcat
+ ;; TODO use seq-find instead of seq-mapcat. Most uses of car . seq-mapcat in
this
+ ;; file would be more efficient with something that flatmaps and takes
+ ;; the first element, without evaluating the rest.
;; TODO `hsinspect index' could evaluate all re-exports to their final
destination
(when srcid
(message "[haskell-tng] [DEBUG] follow %s %s %s" srcid module name))
(or
- (car
- (seq-mapcat
- (lambda (pkg-entry)
- (let ((srcid_ (alist-get 'srcid pkg-entry)))
- (when (or (null srcid) (equal srcid srcid_))
- (seq-mapcat
- (lambda (module-entry)
- (when (equal module (alist-get 'module module-entry))
- (seq-mapcat
- (lambda (entry)
- (let ((id (pcase (alist-get 'class entry)
- ((or 'id 'con 'pat) (alist-get 'name entry))
- ('tycon (alist-get 'type entry)))))
- (when (equal id name)
- (if-let* ((export (alist-get 'export entry))
- (from (alist-get 'module export))
- (pkg (or (alist-get 'srcid export) srcid_)))
- (list (haskell-tng--hsinspect-follow index pkg from
name))
- (list (cons srcid_ module))))))
- (alist-get 'ids module-entry))))
- (alist-get 'modules pkg-entry)))))
- index))
+ (when-let*
+ ((found (haskell-tng--hsinspect-index-get-module index srcid module))
+ (pkg-entry (car found))
+ (srcid_ (alist-get 'srcid pkg-entry))
+ (module-entry (cdr found)))
+ (car
+ (seq-mapcat
+ (lambda (entry)
+ (let ((id (pcase (alist-get 'class entry)
+ ((or 'id 'con 'pat) (alist-get 'name entry))
+ ('tycon (alist-get 'type entry)))))
+ (when (equal id name)
+ (if-let* ((export (alist-get 'export entry))
+ (from (alist-get 'module export))
+ (pkg (or (alist-get 'srcid export) srcid_)))
+ (list (haskell-tng--hsinspect-follow index pkg from name))
+ (list (cons srcid_ module))))))
+ (alist-get 'ids module-entry))))
(cons srcid module)))
(defun haskell-tng--hsinspect-import-popup (index sym)
- [nongnu] elpa/haskell-tng-mode ae8ebbc 320/385: thots, (continued)
- [nongnu] elpa/haskell-tng-mode ae8ebbc 320/385: thots, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode aca98c2 333/385: simplify import-symbol-at-point logic, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 1e3c465 329/385: import types and data constructors, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 3ab7495 342/385: thots, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode ef3cea6 340/385: thots, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode a14a2c2 332/385: allow dir locals for the -as lookups, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 2050c16 323/385: bad parameter order, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 2d50a06 358/385: enable CI, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 923fa9e 344/385: bugfixes in jump-to-definition, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 3939303 334/385: importing from the hsinspect index will update the buffer cache, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 3ea52c1 341/385: special case jumping to inplace packages,
ELPA Syncer <=
- [nongnu] elpa/haskell-tng-mode 4217d98 378/385: fixup! third party tools use project specific PATH, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode f7f0e0f 383/385: moar extras, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 2017d07 384/385: widen hsinspect range, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 083e80a 110/385: assert on alternative indentation order, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode ec1ac46 361/385: document a bug, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 4b598b2 377/385: third party tools use project specific PATH, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode aaf7c55 370/385: support for hsinspect-lsp, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode b3e6c9a 113/385: compilation mode regression tests vs haskell-mode, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 99a7f10 337/385: cleanup, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode e6d8761 343/385: local jump-to-definition should error, ELPA Syncer, 2021/10/06