dante
dante copied to clipboard
Jump to definition and Info unreliable. Configuration of test targets hard to get right
This is my 2nd time trying this out, emmigrating from Intero. It seems to install nicely, no errors, but key features aren't working, and no debug information seems to be logged anywhere.
Weirdly, flycheck
, C-c ,
and C-c "
work just fine. (EDIT: sometimes)
This looks related to: https://github.com/jyp/dante/issues/137 and https://github.com/jyp/dante/issues/78#issuecomment-413336831, but neither solves it.
Features broken:
M-. :: No definitions found for: "/tmp/danteTqJJvj.hs" ...
M-? :: 1.) in helm: "Find references of (default "/tmp/dante..." 12 12 12 12 functionName)
2. ) No references found for: "/tmp/dante..." ...
C-c . :: Couldn't guess that module name. Does it exist?
Details:
# Dante Version
dante 20200131.1211 installed Development mode for Haskell
# OS
Debian Buster
# Emacs version
26.1
# Stack version
2.1.3, rev 636e3a75...
# dante-diagnose
default-directory "<correct project root>"
dante-command-line ("stack" "repl")
dante-state (loaded "Prelude Domain.Analysis")
dante-queue nil
dante-loaded-file "<project root>/Domain/Analysis.hs"
dante-load-message nil
lcr-process-callback nil
; init.el
(use-package dante
:ensure t
:after haskell-mode
:commands 'dante-mode
:init
;; Dante can only check *saved* buffers, make sure flycheck gets
;; along. Disable checks on idle after change.
(add-hook 'haskell-mode-hook 'flycheck-mode)
(setq flymake-no-changes-timeout nil)
(setq flymake-start-syntax-check-on-newline nil)
(setq flycheck-check-syntax-automatically '(save mode-enabled))
;; HLint
(add-hook 'dante-mode-hook
'(lambda () (flycheck-add-next-checker 'haskell-dante
'(warning . haskell-hlint))))
;; Dante
(add-hook 'haskell-mode-hook 'dante-mode)
)
; .dir-locals.el
((nil . ((dante-methods . (stack)))))
EDIT0: These features do work in a stack script, but not in a full fledged stack project.
EDIT1: I was wondering if stack
was running in the wrong place, so I tried C-c "
on the following:
-- >>> :! ls
-- <LISTS MY ROOT>
Not sure how else to debug this, it looks like it has the right root.
EDIT2: Just to be sure I've got the latest, I git clone
d the latest to use it locally instead of from MELPA. Same bugs apply on the latest master (4955bc7363e250d22579bc34b0b4ab6611c0766c).
EDIT3: If I turn off Dante all together, xref-find-references
works on its own, maybe it's just haskell-mode
that's doing that? It's not intero or anything else.
In my understanding, this is related to the fact that we save the current buffer as a temporary file. GHCi ends up with two "versions" of the module and it gets confused. Usually it works again after a reload.
@jyp after a dante-restart
? hmm... that tends to not work. The features to print type at point, and jump to def never work, and eventually dante remains stopped
eternally until I kill emacs...
Are there any debug logs that'd help me investigate?
Since evaluation works, it could be good to check if +c
is activated by running :set
. For example:
-- >>> :set
-- options currently set: +c
-- base language is: Haskell2010
-- with the following modifiers:
-- -XNoDatatypeContexts
-- -XNondecreasingIndentation
-- GHCi-specific dynamic flag settings:
-- other dynamic, non-language, flag settings:
-- -fdefer-type-errors
-- -fdefer-typed-holes
-- -fdefer-out-of-scope-variables
-- -fno-diagnostics-show-caret
-- -ferror-spans
-- -fexternal-dynamic-refs
-- -fignore-optim-changes
-- -fignore-hpc-changes
-- -fimplicit-import-qualified
-- warning settings:
-- -Wunbanged-strict-patterns
-- -Wdodgy-exports
-- -Wdodgy-imports
-- -Whi-shadowing
-- -Wincomplete-patterns
-- -Wmissing-signatures
-- -Wname-shadowing
-- -Worphans
-- -Wtrustworthy-safe
-- -Wtype-defaults
-- -Wunticked-promoted-constructors
-- -Wunused-do-bind
-- -Wunused-foralls
-- -Wunused-imports
-- -Wunused-local-binds
-- -Wunused-matches
-- -Wunused-pattern-binds
-- -Wunused-top-binds
-- -Wmissing-pattern-synonym-signatures
You can also configure dante-debug (see below) and read the contents of the dante buffer.
dante-debug is a variable defined in ‘dante.el’.
Its value is (inputs outputs responses command-line)
Original value was nil
This variable is safe as a file local variable if its value
satisfies the predicate ‘t’.
Documentation:
Show debug output.
You can customize this variable.
Also: if the module cannot be loaded then GHCi won't give any type. Deferring type errors will help there.
@jyp Thanks, those were good leads! Still not quite solved though, and totally not your duty to make it work, but I'll document what I'm going through for you and future ppl with the same problems.
For future guests, here are the docs for : :set +c
-- :set -- and C-c "
-- options currently set: none.
So I add a .ghci
to my root dir with simply :set +c
.
Now I see though, after (setq dante-debug t)
, the dante
error buffer shows that ghci is frozen waiting for my input:
The main module to load is ambiguous. Candidates are:
...
You can specify which one to pick by:
* Specifying targets to stack ghci e.g. stack ghci theproject:exe:devel
* Specifying what the main is e.g. stack ghci --main-is theproject:exe:devel
* Choosing from the candidate above [1..3]
* * * * * * * *
Specify main module to use (press enter to load none):
I would think that having the following would have helped it figure out my desired target (PS this was also confusing to figure out how to get my test targets working, just a barb in adoption of Dante):
;; src/.dir-locals.el
((haskell-mode . ((dante-target . "theproject"))))
I'll report back if I figure this out!
Progress (though incomplete)! I can thread a variable in via a .dir-locals.el
living at project root:
(("src" .
((nil . ((dante-target . "theproject:exe:theproject")))))
("test" .
((nil . ((dante-target . ":test"))))))
(If you've never had to play with this file: directory variables, associated lists. Lifelong emacser, non-elisper, ya it's the basics... :man_shrugging:. Oh, and you can revert-buffer
if you want to check out what effect your changes to .dir-locals.el
had)
But now I get weird errors that generally hint at - Wrong type argument: listp, t
- but still tracking em down.
EDIT: the errors are somehow related to flycheck
. When starting flycheck-mode
:
Debugger entered--Lisp error: (wrong-type-argument listp t)
signal(wrong-type-argument (listp t))
flycheck-buffer()
flycheck-buffer-automatically()
flycheck-perform-deferred-syntax-check()
relatedly:
Error while checking syntax automatically: (wrong-type-argument listp t)
It's working, sorta. I don't know how I fixed it but after wrestling all day I:
-
cloned dante locally (instead of using MELPA)
-
then from MELPA again
-
then from local again
-
git clone'd flycheck
-
added the
.dir-locals.el
I commented above, ang the.ghci
with:set +c
in it. -
reinstalled
hlint
-
sprouted a few gray hairs
-
then it just started working
A residual bug is M-i
for find-definitiions
doesn't work... except I found it can work if you visit the file that dante should be jumping to and re-save it.
I like that Dante is fast-light-simple, thanks and I hope it becomes my daily driver since other projects are either dead or still a little buggy. Thanks, and Stay healthy!
gahh, ok, the thing I spent a couple hours debugging, that whole listp t
thing? That's because I set this in my init.el
:
(setq dante-debug t)
Apologies for closing and reopening, testing targets still don't work, if they depend on the main project library, which can't be found.
I can't find a way to enable multiple targets, and having a testing target is buggy.
If I use a (dante-target . "theproject:test:theproject-test")
it can find the test target but not the library target, and so dante fails to boot up.
Digging through the commit history of dante
, it looks like multiple targets were considered at some point, so I tried these, but they threw errors:
(dante-target . "theproject:exe:theproject theproject:test:theproject-test")
(dante-target . '("theproject:exe:theproject" "theproject:test:theproject-test"))
(dante-target . (quote ("theproject:exe:theproject" "theproject:test:theproject-test")))
If I use (dante-target . "--test")
it... sorta works sometimes, but is still buggy, and it seems like the 2 instances of dante that load up for library+test suffer a ~20 second switching time if I'm going back and forth between them, which I don't quite understand.
This is sorta just an involved bug report, hopefully it helps someone in the future, and if anyone's "in the know" about what's going on, a little documentation would help a tooon.
You have really two issues here.
- The unreliability of jump to definition and info is something I could never fix, and seem related to a GHCi bug and/or the way we load temporary files into GHCi
- The test targets is something that should be fixable using the dante-target variable. If you still have this issue I think it could be fixable with a precise report. (ie. if I could try your project on my machine).
For me, jump to definition / info started working once I added my targets into .dir-locals.el. Perhaps readme should say
==Troubleshooting==
If `dante-type-at` gives `Couldn't guess that module name. Does it
exist?` or `xref-find-definitions` gives `No definitions found for:
"/tmp/danteTqJJvj.hs" `, you may need to add your targets to
`.dir-locals.el`; see the Configuration section above.
@unhammer Good suggestion.
Doc updated