ghc-mod icon indicating copy to clipboard operation
ghc-mod copied to clipboard

ghc-mod fails in a multi-package stack project

Open simonmichael opened this issue 8 years ago • 6 comments

ghc-mod check FILE in the root of a multi-package stack project doesn't detect the stack package db.

$ ghc-mod check hledger-lib/Hledger/Read/JournalReader.hs
hledger-lib/Hledger/Read/JournalReader.hs:101:8:Could not find module ‘Hledger.Data’

simonmichael avatar May 13 '16 17:05 simonmichael

This hack makes it work for me.

my-ghc-mod.hs:

#!/usr/bin/env stack
-- stack runghc --verbosity info --package directory --package filepath --package process

-- A temporary workaround for https://github.com/DanielG/ghc-mod/issues/787
-- (make ghc-mod work in multi-package stack projects).
-- Ensures check commands are run inside the first directory of the path argument.
-- Setup: compile (stack ghc my-ghc-mod.hs) and install this in your path,
-- configure it as haskell-ghc-mod's Ghc Mod Path, uncheck Enable Ghc Modi.

import Data.List
import Control.Monad
import System.Directory
import System.Environment
import System.FilePath
import System.Process

main :: IO ()
main = do
  args <- getArgs
  when ("check" `elem` takeWhile (/="--") args) $ do
    wd <- getCurrentDirectory
    let wdparts = splitDirectories wd
        _:patharg:_ = dropWhile (/="check") args
        pathparts = splitDirectories patharg
    when (wdparts `isPrefixOf` pathparts) $ do
      case take 1 $ init $ drop (length wdparts) pathparts of
        [subdir] -> setCurrentDirectory $ wd </> subdir
        _        -> return ()
  callProcess "ghc-mod" args

simonmichael avatar May 14 '16 14:05 simonmichael

+1

mizunashi-mana avatar May 14 '16 14:05 mizunashi-mana

thanks @simonmichael

@DanielG @lierdakil integrating that would be great !

rvion avatar May 14 '16 15:05 rvion

PS the workaround above is not robust, ie does not handle all cases.

simonmichael avatar Aug 02 '16 20:08 simonmichael

This is more or less intended behavior, the project detection is based on the CWD, not the path you pass in for the simple reason that not all commands have a FILE argument but all of them still need the project detection to work. I think with some refactoring it should be possible to support this but I'm not sure how best to do it.

Essentially there's two internal run* functions that most commands are implemented in terms of :

that correspond to commands that have file or module arguments and ones that only need access to GHC's package databases.

Unfortunately both of these rely on the "Cradle" (i.e. project environment) to already have been resolved and just get it from the monadic environment. The resolution happens in the withGhcModEnv' wrapper used by runGhcModT which these run functions have to be run in.

The problem is that we have to support ghc-modi as well which does the "Cradle" resolution at startup based solely on the CWD so we can't easily delay it until we actually get a command that has a FILE argument.

ghc-mod was just never designed to handle superprojects to begin with :( I'm very much open to redesiging this core functionality though, so if anyone wants to work on this I'd be happy to help.

DanielG avatar Aug 06 '16 05:08 DanielG

As for a workaround, how about:

#!/bin/sh
cd "$(cd $(dirname "$1"); ghc-mod root)"
ghc-mod check "$@"

but that of course only works for check.

DanielG avatar Aug 06 '16 05:08 DanielG