branch: elpa/haskell-tng-mode commit 393930336b189df631ac22f095d1bb4382131bfc Author: Tseen She <ts33n....@gmail.com> Commit: Tseen She <ts33n....@gmail.com>
importing from the hsinspect index will update the buffer cache --- haskell-tng-hsinspect.el | 52 +++++++++++++++++++++++++++++++++----- haskell-tng-util.el | 2 +- test/haskell-tng-hsinspect-test.el | 35 +++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 7 deletions(-) diff --git a/haskell-tng-hsinspect.el b/haskell-tng-hsinspect.el index 2d45224..10a95bb 100644 --- a/haskell-tng-hsinspect.el +++ b/haskell-tng-hsinspect.el @@ -96,29 +96,57 @@ Respects the `C-u' cache invalidation convention." (type (alist-get 'type hit)) (name (alist-get 'name hit))) (cond - (qual (haskell-tng--import-symbol module qual)) + (qual (haskell-tng--hsinspect-import-symbol index module qual)) ((xor haskell-tng-hsinspect-qualify (eq '- alt)) (when-let (as (haskell-tng--hsinspect-as module)) - (haskell-tng--import-symbol module as) + (haskell-tng--hsinspect-import-symbol index module as) (save-excursion (haskell-tng--hsinspect-beginning-of-symbol) (insert as ".")))) ((eq class 'tycon) - (haskell-tng--import-symbol + (haskell-tng--hsinspect-import-symbol + index module nil (haskell-tng--hsinspect-return-type type))) ((eq class 'con) - (haskell-tng--import-symbol + (haskell-tng--hsinspect-import-symbol + index module nil (concat (haskell-tng--hsinspect-return-type type) "(..)"))) - (t (haskell-tng--import-symbol module nil name))))) - ;; FIXME update the hsinspect-imports cache + (t (haskell-tng--hsinspect-import-symbol index module nil name))))) ))) +(defun haskell-tng--hsinspect-extract-imports (index module &optional as sym) + "Calculates the imports from INDEX that are implied by MODULE AS and SYM." + ;; TODO a nested seq-mapcat threaded syntax + (if sym + `(((local . ,sym) (full . ,(concat module "." sym)))) + (seq-mapcat + (lambda (pkg-entry) + (seq-mapcat + (lambda (module-entry) + (when (equal module (alist-get 'module module-entry)) + (seq-mapcat + (lambda (entry) + (let* ((name (alist-get 'name entry)) + (type (alist-get 'type entry)) + (id (pcase (alist-get 'class entry) + ((or 'id 'con) name) + ('tycon type))) + (full (concat module "." id))) + (if as + `(((qual . ,(concat as "." id)) + (full . ,full))) + `(((local . ,id) + (full . ,full)))))) + (alist-get 'ids module-entry)))) + (alist-get 'modules pkg-entry))) + index))) + (defun haskell-tng--hsinspect-return-type (type) (car (split-string @@ -148,6 +176,9 @@ Respects the `C-u' cache invalidation convention." (selected (popup-menu* entries))) (seq-find (lambda (el) (equal (alist-get 'module el) selected)) hits)))) +;; TODO when the same name is reused as a type and data constructor we show dupe +;; entries to the user. We should dedupe that to just the cons unless we have a +;; way to make the choice clearer. (defun haskell-tng--hsinspect-import-candidates (index sym) "Return an list of alists with keys: unitid, module, name, type. When using hsinspect-0.0.8, also: class, export, flavour." @@ -222,6 +253,15 @@ When using hsinspect-0.0.8, also: class, export, flavour." no-work flush-cache)) +(defun haskell-tng--hsinspect-import-symbol (index module as &optional sym) + "Add the import to the current buffer and update `haskell-tng--hsinspect-imports'. + +Does not persist the cache changes to disk." + (haskell-tng--import-symbol module as sym) + (let ((updates (haskell-tng--hsinspect-extract-imports index module as sym))) + (setq haskell-tng--hsinspect-imports + (append haskell-tng--hsinspect-imports updates)))) + ;; TODO add a package-wide variable cache (defun haskell-tng--hsinspect-index (&optional flush-cache) (when-let (ghcflags-dir diff --git a/haskell-tng-util.el b/haskell-tng-util.el index 3d296e4..c43f0c8 100644 --- a/haskell-tng-util.el +++ b/haskell-tng-util.el @@ -71,7 +71,7 @@ and taking a regexp." (while (not (setq ,res ,test)) ,@body) ,res))) -(defun haskell-tng--import-symbol (module as &optional sym) +(defun haskell-tng--import-symbol (module &optional as sym) "Adds an import for MODULE." ;; TODO outsource to `hsimport' when it does de-duping and formatting. (save-excursion diff --git a/test/haskell-tng-hsinspect-test.el b/test/haskell-tng-hsinspect-test.el index 8184c74..803f77e 100644 --- a/test/haskell-tng-hsinspect-test.el +++ b/test/haskell-tng-hsinspect-test.el @@ -95,6 +95,41 @@ ;;(message "%S" (haskell-tng--hsinspect-import-candidates index "Contravariant")) )) +(ert-deftest haskell-tng-hsinspect-test-extract-imports () + (let ((index + (haskell-tng--util-read + (testdata "data/hsinspect-0.0.8-index.sexp.gz")))) + + ;; explicit import + (should + (equal + (haskell-tng--hsinspect-extract-imports index "Data.List" nil "head") + '(((local . "head") + (full . "Data.List.head"))))) + + ;; qualified import + (should + (equal + (seq-take + (haskell-tng--hsinspect-extract-imports index "Data.List" "L") + 2) + '(((qual . "L.all") + (full . "Data.List.all")) + ((qual . "L.and") + (full . "Data.List.and"))))) + + ;; unqualified import + (should + (equal + (seq-take + (haskell-tng--hsinspect-extract-imports index "Data.List" nil) + 2) + '(((local . "all") + (full . "Data.List.all")) + ((local . "and") + (full . "Data.List.and"))))) + )) + ;; TODO tests for 0.0.7 data ;;; haskell-tng-hsinspect-test.el ends here