flycheck / flycheck-haskell

Improved Haskell support for Flycheck
GNU General Public License v3.0
67 stars 25 forks source link

flycheck-disable-checked not disabling haskell-stack-ghci #101

Open chrissound opened 4 years ago

chrissound commented 4 years ago

The error is probably due to this project using Nix for it's dependencies. And emacs is not running within the nix-context.

I've tried to disable this with either of these two options but I still run into the error (which locks up the editor for a second or two after each file save):

(setq-default flycheck-disabled-checkers '(haskell-stack-ghc))
(add-to-list 'flycheck-disabled-checkers 'haskell-stack-ghc)
Suspicious state from syntax checker haskell-stack-ghc: Flycheck checker haskell-stack-ghc returned non-zero exit code 1, but its output contained no errors: <command line>: cannot satisfy -package X11

Flycheck version: 32snapshot (package: 20191126.2142)

emacs --version
GNU Emacs 26.3
paulyoung commented 4 years ago

I've done the same with haskell-ghc but it has no effect.

Every time I try to open a Haskell file, nothing happens and I see File mode specification error: (file-missing Searching for program No such file or directory runghc)

sergv commented 4 years ago

Thanks for reporting. Just to clarify, this project doesn't directly manage haskell-ghc and haskell-stack-ghc checkers. They're part of the main flycheck project as well as flycheck-disabled-checkers variable. The flycheck-haskell project only concerns itself with configuring proper environment for those checkers.

@chrissound perhaps it would make sense to disable flycheck-mode completely for Haskell files if you don't want any checking? Or maybe select the proper checker you want inside haskell-mode-hook? Judging from the output you posted, line Suspicious state from syntax checker haskell-stack-ghc seems to indicate that haskell-stack-ghc checker is being used despite being disabled. Can you check that it's not being enabled somewhere in your config?

@paulyoung The error you observer seems to come from the flycheck-haskell.el. It requires runghc executable to be present in order to parse cabal file and retrieve packages that your project uses. If you know you have run-ghc somewhere, you can point flycheck-haskell to it via flycheck-haskell-runghc-command.

codygman commented 4 years ago

This is likely what I've run into.

direnv-mode (commonly used on nix) adds (direnv--maybe-update-environment) to before-hack-local-variables-hook. That means the project specific ghc environment and package path should be loaded first.

Then flycheck-haskell adds (flycheck-haskell-configure) to hack-local-variables-hook.

Theoretically that means the per project nix-shell based ghc should be picked up at the time of (flycheck-haskell-configure). I wonder if it is though, because when I somehow reproduce the error like others got above the fix is to call (flycheck-haskell-configure) and it always works.

That leads me to believe that (flycheck-haskell-configure) is somehow running before direnv is done updating the environment. Then the next call you do manually of (flycheck-haskell-configure) works because everything is loaded appropriately.

codygman commented 4 years ago

I paid more attention to my logs and found I was getting the error from this function in my messages buffer when failing:

(defun flycheck-haskell--read-configuration-with-helper (command)
  (with-temp-buffer
    ;; Hack around call-process' limitation handling standard error
    (let ((error-file (make-temp-file "flycheck-haskell-errors")))
      (pcase (apply 'call-process (car command) nil (list t error-file) nil (cdr command))
        (0 (delete-file error-file)
           (goto-char (point-min))
           (read (current-buffer)))
        (retcode (insert-file-contents error-file)
                 (delete-file error-file)
                 (message "Reading Haskell configuration failed with exit code %s and output:\n%s"
                          retcode (buffer-string))
                 nil)))))
codygman commented 4 years ago

Aha! I overrode the function above like so:

(use-package flycheck-haskell
    :config
    (defun flycheck-haskell--read-configuration-with-helper (command)
      (with-temp-buffer
        ;; Hack around call-process' limitation handling standard error
        (let ((error-file (make-temp-file "flycheck-haskell-errors")))
          (pcase (apply 'call-process (car command) nil (list t error-file) nil (cdr command))
        (0 (delete-file error-file)
           (goto-char (point-min))
           (read (current-buffer)))
        (retcode (insert-file-contents error-file)
             (delete-file error-file)
             (message "command is: \n%s" command)
             (message "Reading Haskell configuration failed with exit code %s and (haxx) output:\n%s"
                  retcode (buffer-string))
             nil)))))
    :hook (haskell-mode . flycheck-haskell-setup))

And I saw it was running this:

/home/cody/.nix-profile/bin/stack --verbosity silent runghc --no-ghc-package-path -- -i -packageCab\
al -packagebase -packagebytestring -packagecontainers -packageprocess -packagedirectory -packagefile\
path /nix/store/aipjxsx1rawcascch2lbd1sjwjp1ral4-emacs-packages-deps/share/emacs/site-lisp/elpa/flyc\
heck-haskell-20200218.753/get-cabal-configuration.hs --cabal-file /home/cody/hci/testdata/haskell-ni\
x-stack-workflow/myproj.cabal

Notice its using/home/cody/.nix-profile/bin/stack. This is a bug in a setup that uses direnv and nix-shell. After I runflycheck-haskell-configure` the stack it uses (which contains my packages and a modified ghc package directory) is:

/nix/store/dzivj11vsiy2n28ix8mbs1frrpmlw603-stack-2.3.1/bin/stack

That means either something is wrong with the direnv code applying or somehow flycheck-haskell read configuration happens before direnv.

codygman commented 4 years ago

For some reason the cabal file is always being preferred, even when I explicitly evaluate this in the errored state:

(let ((flycheck-haskell-hpack-preference 'prefer-hpack)) (flycheck-haskell--find-config-file))