branch: elpa/haskell-tng-mode commit c39d0f430807370111fcea024d2d3984eb58964e Author: Tseen She <ts33n....@gmail.com> Commit: Tseen She <ts33n....@gmail.com>
some hsinspect tests --- haskell-tng-hsinspect.el | 23 +++++++----- haskell-tng-util.el | 33 +++++++++------- test/data/hsinspect-0.0.7-imports.sexp.gz | Bin 0 -> 364 bytes test/data/hsinspect-0.0.7-index.sexp.gz | Bin 0 -> 52239 bytes test/data/hsinspect-0.0.8-imports.sexp.gz | Bin 0 -> 361 bytes test/data/hsinspect-0.0.8-index.sexp.gz | Bin 0 -> 74636 bytes test/haskell-tng-hsinspect-test.el | 60 ++++++++++++++++++++++++++++++ 7 files changed, 94 insertions(+), 22 deletions(-) diff --git a/haskell-tng-hsinspect.el b/haskell-tng-hsinspect.el index b932922..1bca5aa 100644 --- a/haskell-tng-hsinspect.el +++ b/haskell-tng-hsinspect.el @@ -34,13 +34,12 @@ name of the symbol at point in the minibuffer. A prefix argument ensures that caches are flushes." (interactive "P") (if-let* ((sym (haskell-tng--hsinspect-symbol-at-point)) - (found (seq-find - ;; FIXME test for this - ;; TODO add type information too - (lambda (names) (member sym (seq-map #'cdr names))) - (haskell-tng--hsinspect-imports nil alt)))) + (found (haskell-tng--hsinspect-qualify + (haskell-tng--hsinspect-imports nil alt) + sym))) ;; TODO multiple hits - (popup-tip (format "%s" (cdar (last found))))) + ;; TODO add type information from the index when available + (popup-tip (format "%s" found))) (user-error "Not found")) ;; FIXME jump-to-definition using import + index + heuristics @@ -71,6 +70,13 @@ A prefix argument ensures that caches are flushes." ;; TODO expand out pattern matches (function defns and cases) based on the cons ;; for a type obtained from the Index. +(defun haskell-tng--hsinspect-qualify (imports sym) + (cdar + (last + (seq-find + (lambda (names) (member sym (seq-map #'cdr names))) + imports)))) + (defun haskell-tng--hsinspect-import-popup (index sym) (when-let ((hits (haskell-tng--hsinspect-import-candidates index sym))) ;; TODO special case one hit @@ -78,7 +84,6 @@ A prefix argument ensures that caches are flushes." (selected (popup-menu* entries))) (seq-find (lambda (el) (equal (car el) selected)) hits)))) -;; FIXME this could be tested (defun haskell-tng--hsinspect-import-candidates (index sym) "Return a list of (module . symbol)" ;; TODO threading/do syntax @@ -138,7 +143,7 @@ A prefix argument ensures that caches are flushes." (defun haskell-tng--hsinspect-index (&optional flush-cache) (when-let (ghcflags-dir (locate-dominating-file default-directory ".ghc.flags")) - (haskell-tng--hsinspect-cached-disk + (haskell-tng--util-cached-disk (lambda () (haskell-tng--hsinspect flush-cache "index")) (concat "hsinspect-0.0.7" (expand-file-name ghcflags-dir) "index") nil @@ -152,7 +157,7 @@ A prefix argument ensures that caches are flushes." haskell-tng--compile-dominating-project) (haskell-tng--util-locate-dominating-file haskell-tng--compile-dominating-package))) - (haskell-tng--hsinspect-cached-disk + (haskell-tng-util-cached-disk #'haskell-tng--hsinspect-which-hsinspect (concat "which" (expand-file-name package-dir) "hsinspect") nil diff --git a/haskell-tng-util.el b/haskell-tng-util.el index bcb1cae..b501639 100644 --- a/haskell-tng-util.el +++ b/haskell-tng-util.el @@ -103,9 +103,9 @@ and taking a regexp." The caller is responsible for flushing the cache. For consistency, it is recommended that commands using this cache flush the cache when the universal argument is provided." - (haskell-tng--hsinspect-cached-variable + (haskell-tng--util-cached-variable (lambda () - (haskell-tng--hsinspect-cached-disk + (haskell-tng-util-cached-disk work key no-work @@ -114,7 +114,7 @@ flush the cache when the universal argument is provided." nil reset)) -(defun haskell-tng--hsinspect-cached-variable (work sym &optional no-work reset) +(defun haskell-tng--util-cached-variable (work sym &optional no-work reset) "A variable cache over a function WORK. If the SYM reference contains a cache of a previous call, it is @@ -141,7 +141,7 @@ RESET sets the variable to nil before doing anything." (cached cached))) ;; TODO max-age (fallback to disk if WORK fails) -(defun haskell-tng--hsinspect-cached-disk (work key &optional no-work reset) +(defun haskell-tng-util-cached-disk (work key &optional no-work reset) "A disk-based cache over a function WORK. If the cache contains a file matching the KEY string (which must @@ -156,22 +156,29 @@ nil return values are NOT cached. NO-WORK skips WORK and only queries the cache. RESET deletes the cache if it exists." - (let (jka-compr-verbose ;; disables gzip noise - (cache-file + (let ((cache-file (concat (xdg-cache-home) "/haskell-tng/" key ".gz"))) (when (and reset (file-exists-p cache-file)) (delete-file cache-file)) (if (file-exists-p cache-file) - (with-temp-buffer - (insert-file-contents cache-file) - (goto-char (point-min)) - (ignore-errors (read (current-buffer)))) + (haskell-tng--util-read cache-file) (unless no-work (when-let (result (funcall work)) - (with-temp-file cache-file - (make-directory (file-name-directory cache-file) 'create-parents) - (prin1 result (current-buffer))) + (haskell-tng--util-write result cache-file) result))))) +(defun haskell-tng--util-read (file) + (let (jka-compr-verbose) + (with-temp-buffer + (insert-file-contents file) + (goto-char (point-min)) + (ignore-errors (read (current-buffer)))))) + +(defun haskell-tng--util-write (file var) + (let (jka-compr-verbose) + (with-temp-file file + (make-directory (file-name-directory file) 'create-parents) + (prin1 var (current-buffer))))) + (provide 'haskell-tng-util) ;;; haskell-tng-util.el ends here diff --git a/test/data/hsinspect-0.0.7-imports.sexp.gz b/test/data/hsinspect-0.0.7-imports.sexp.gz new file mode 100644 index 0000000..dc6b7ac Binary files /dev/null and b/test/data/hsinspect-0.0.7-imports.sexp.gz differ diff --git a/test/data/hsinspect-0.0.7-index.sexp.gz b/test/data/hsinspect-0.0.7-index.sexp.gz new file mode 100644 index 0000000..aad2677 Binary files /dev/null and b/test/data/hsinspect-0.0.7-index.sexp.gz differ diff --git a/test/data/hsinspect-0.0.8-imports.sexp.gz b/test/data/hsinspect-0.0.8-imports.sexp.gz new file mode 100644 index 0000000..8c61dc4 Binary files /dev/null and b/test/data/hsinspect-0.0.8-imports.sexp.gz differ diff --git a/test/data/hsinspect-0.0.8-index.sexp.gz b/test/data/hsinspect-0.0.8-index.sexp.gz new file mode 100644 index 0000000..6e95415 Binary files /dev/null and b/test/data/hsinspect-0.0.8-index.sexp.gz differ diff --git a/test/haskell-tng-hsinspect-test.el b/test/haskell-tng-hsinspect-test.el new file mode 100644 index 0000000..3bbccac --- /dev/null +++ b/test/haskell-tng-hsinspect-test.el @@ -0,0 +1,60 @@ +;;; haskell-tng-hsinspect-test.el --- Tests for hsinspect features -*- lexical-binding: t -*- + +;; Copyright (C) 2019 Tseen She +;; License: GPL 3 or any later version + +(require 'ert) + +(require 'haskell-tng-mode) +(require 'haskell-tng-hsinspect) + +(require 'haskell-tng-testutils + "test/haskell-tng-testutils.el") + +(ert-deftest haskell-tng-hsinspect-test-qualify-latest () + (let ((imports + (haskell-tng--util-read + (testdata "data/hsinspect-0.0.8-imports.sexp.gz")))) + + ;; function search + (should + (equal + (haskell-tng--hsinspect-qualify imports "contramap") + "Data.Functor.Contravariant.contramap")) + + ;; operator search + (should + (equal + (haskell-tng--hsinspect-qualify imports ">$<") + "Data.Functor.Contravariant.>$<")) + + ;; TODO type search + ;; TODO constructor search + )) + +(ert-deftest haskell-tng-hsinspect-test-import-candidates-latest () + (let ((index + (haskell-tng--util-read + (testdata "data/hsinspect-0.0.8-index.sexp.gz")))) + + ;; function search + (should + (equal + (haskell-tng--hsinspect-import-candidates index "throw") + '(("Control.Exception.Base" . "throw") + ("Control.Exception" . "throw") + ("GHC.Exception" . "throw")))) + + ;; operator search + (should + (equal + (haskell-tng--hsinspect-import-candidates index ">$<") + '(("Data.Functor.Contravariant" . ">$<")))) + + ;; TODO type search + ;; TODO constructor search + )) + +;; TODO tests for 0.0.7 data + +;;; haskell-tng-hsinspect-test.el ends here