Skip to content
This repository has been archived by the owner on Apr 25, 2020. It is now read-only.

Explicit project (Was: #585) #806

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Language/Haskell/GhcMod/Cradle.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ findCradle' Programs { stackProgram, cabalProgram } dir = run $
msum [ stackCradle stackProgram dir
, cabalCradle cabalProgram dir
, sandboxCradle dir
, explicitCradle dir
, plainCradle dir
]
where run a = fillTempDir =<< (fromJustNote "findCradle'" <$> runMaybeT a)
Expand All @@ -57,6 +58,7 @@ findSpecCradle Programs { stackProgram, cabalProgram } dir = do
let cfs = [ stackCradleSpec stackProgram
, cabalCradle cabalProgram
, sandboxCradle
, explicitCradle
]
cs <- catMaybes <$> mapM (runMaybeT . ($ dir)) cfs
gcs <- filterM isNotGmCradle cs
Expand Down Expand Up @@ -184,3 +186,15 @@ plainCradle wdir = do
, cradleCabalFile = Nothing
, cradleDistDir = "dist"
}

explicitCradle :: IOish m => FilePath -> MaybeT m Cradle
explicitCradle wdir = do
optionsFile <- MaybeT $ liftIO $ findExplicitOptionsFile wdir
return $ Cradle {
cradleProject = ExplicitProject
, cradleCurrentDir = wdir
, cradleRootDir = takeDirectory optionsFile
, cradleTempDir = error "tmpDir"
, cradleCabalFile = Just optionsFile
, cradleDistDir = ""
}
20 changes: 8 additions & 12 deletions Language/Haskell/GhcMod/Find.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import Exception
import Language.Haskell.GhcMod.Convert
import Language.Haskell.GhcMod.Gap
import Language.Haskell.GhcMod.Monad
import Language.Haskell.GhcMod.Output
import Language.Haskell.GhcMod.Types
import Language.Haskell.GhcMod.Utils
import Language.Haskell.GhcMod.World
Expand Down Expand Up @@ -120,26 +119,23 @@ loadSymbolDb' = do
return db
doLoad =<< liftIO (doesFileExist cache)

-- | Loading a file and creates 'SymbolDb'.
loadSymbolDb :: IOish m => GhcModT m SymbolDb
loadSymbolDb = do
ghcMod <- liftIO ghcModExecutable
readProc <- gmReadProcess'
out <- liftIO $ readProc ghcMod ["--verbose", "error", "dumpsym"] ""
return $!! decode out
ts <- liftIO getCurrentModTime
st <- runGmPkgGhc getGlobalSymbolTable
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no good, there is a reason we do this in another process (memory usage). Please revert.

return SymbolDb {
sdTable = st
, sdTimestamp = ts
}

----------------------------------------------------------------
-- used 'ghc-mod dumpsym'

-- | Dumps a 'Binary' representation of 'SymbolDb' to stdout
dumpSymbol :: IOish m => GhcModT m ()
dumpSymbol = do
ts <- liftIO getCurrentModTime
st <- runGmPkgGhc $ getGlobalSymbolTable
liftIO . LBS.putStr $ encode SymbolDb {
sdTable = st
, sdTimestamp = ts
}
symbolDb <- loadSymbolDb
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here obviously.

liftIO . LBS.putStr $ encode symbolDb

-- | Check whether given file is older than any file from the given set.
-- Returns True if given file does not exist.
Expand Down
1 change: 0 additions & 1 deletion Language/Haskell/GhcMod/Gap.hs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ import StringBuffer
import TcType
import Var (varType)
import System.Directory
import SysTools
#if __GLASGOW_HASKELL__ >= 800
import GHCi (stopIServ)
#endif
Expand Down
1 change: 1 addition & 0 deletions Language/Haskell/GhcMod/GhcPkg.hs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ getPackageDbStack = do
getCabalPackageDbStack
(StackProject StackEnv {..}) ->
return $ map PackageDb [seSnapshotPkgDb, seLocalPkgDb]
ExplicitProject -> return []
return $ fromMaybe stack mCusPkgStack

getPackageCachePaths :: IOish m => FilePath -> GhcModT m [FilePath]
Expand Down
9 changes: 9 additions & 0 deletions Language/Haskell/GhcMod/PathsAndFiles.hs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ findStackConfigFile dir = do
Just (d, Just a) -> return $ Just $ d </> a
Just (_, Nothing) -> error "findStackConfigFile"

findExplicitOptionsFile :: FilePath -> IO (Maybe FilePath)
findExplicitOptionsFile dir = do
dss <- findFileInParentsP (==explicitOptionsFile) dir
return $ case find (not . null . snd) $ dss of
Just (expDir, _:_) -> Just (expDir </> explicitOptionsFile)
_ -> Nothing
where
explicitOptionsFile = "ghc-mod.options"

-- | Get path to sandbox config file
getSandboxDb :: Cradle -> IO (Maybe GhcPkgDb)
getSandboxDb crdl = do
Expand Down
19 changes: 14 additions & 5 deletions Language/Haskell/GhcMod/Target.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import GHC
#if __GLASGOW_HASKELL__ >= 800
import GHC.LanguageExtensions
#endif
import GHC.Paths (libdir)
import SysTools
import DynFlags
import HscTypes
Expand Down Expand Up @@ -106,7 +105,7 @@ initSession opts mdf = do
putNewSession s = do
crdl <- cradle
nhsc_env_ref <- liftIO . newIORef =<< newLightEnv (initDF crdl)
runLightGhc' nhsc_env_ref $ setSessionDynFlags =<< getSessionDynFlags
void $ runLightGhc' nhsc_env_ref $ setSessionDynFlags =<< getSessionDynFlags
gmsPut s { gmGhcSession = Just $ GmGhcSession nhsc_env_ref }


Expand Down Expand Up @@ -188,12 +187,22 @@ targetGhcOptions crdl sefnmn = do
when (Set.null sefnmn) $ error "targetGhcOptions: no targets given"

case cradleProject crdl of
proj
| isCabalHelperProject proj -> cabalOpts crdl
| otherwise -> sandboxOpts crdl
proj | isCabalHelperProject proj -> cabalOpts crdl
ExplicitProject -> do
opts <- explicitOpts crdl
dbStack <- maybe [] id <$> getCustomPkgDbStack
return $ opts ++ ghcDbStackOpts dbStack
_ -> sandboxOpts crdl
where
zipMap f l = l `zip` (f `map` l)

explicitOpts :: Cradle -> GhcModT m [String]
explicitOpts Cradle {..} = case cradleCabalFile of
Nothing -> return []
Copy link
Owner

@DanielG DanielG Aug 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain what you're doing here? Looking at what explicitCradle above it seems that when the project type is ExplicitCradle """cradleCabalFile""" would always be: cradleCabalFile = Just optionsFile which seems like a horrible misnomer in its own right ;)

Also maybe you could put the optionsFile in the ExplicitProject constructor like we do with the StackEnv stuff?

Just optionsFile -> do
contents <- liftIO $ readFile optionsFile
return $ lines contents

cabalOpts :: Cradle -> GhcModT m [String]
cabalOpts Cradle{..} = do
mcs <- cabalResolvedComponents
Expand Down
1 change: 1 addition & 0 deletions Language/Haskell/GhcMod/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ data Project = CabalProject
| SandboxProject
| PlainProject
| StackProject StackEnv
| ExplicitProject
deriving (Eq, Show, Ord)

isCabalHelperProject :: Project -> Bool
Expand Down
2 changes: 0 additions & 2 deletions Language/Haskell/GhcMod/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ import System.Environment
import System.FilePath
import System.IO.Temp (createTempDirectory)
import System.Process (readProcess)
import Text.Printf

import Paths_ghc_mod (getLibexecDir)
import Utils
import Prelude

Expand Down
8 changes: 6 additions & 2 deletions ghc-mod.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,12 @@ Extra-Source-Files: ChangeLog
test/data/stack-project/app/*.hs
test/data/stack-project/src/*.hs
test/data/stack-project/test/*.hs
bench/data/simple-cabal/simple-cabal.cabal
bench/data/simple-cabal/*.hs
test/data/options-cradle/ghc-mod.options
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you removing these? Are they no longer used?

test/data/options-cradle/ghc-mod.package-db-stack
test/data/options-cradle/package-db-a/package.cache
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so you don't want to check in package.cache into repo, since it's ghc-specific binary format which can (and will) change, and your tests will fail for no good reason with something like
GHC.PackageDb.readPackageDb: inappropriate type (not a ghc-pkg db file, wrong file magic number)

test/data/options-cradle/package-db-b/package.cache
test/data/options-cradle/package-db-c/package.cache
test/data/options-cradle/src/*.hs

Custom-Setup
Setup-Depends: base
Expand Down
12 changes: 12 additions & 0 deletions test/CheckSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,15 @@ spec = do
#else
res `shouldBe` "NiceQualification.hs:4:8:Couldn't match expected type `IO ()' with actual type `[Char]'\NULIn the expression: \"wrong type\"\NULIn an equation for `main': main = \"wrong type\"\n"
#endif

it "works with explicit options" $ bracketTagged $ do
res <- runD $ checkSyntax ["src/Main.hs"]
res `shouldBe` ""

it "emits error with explicit options" $ bracketTagged $ do
res <- runD $ checkSyntax ["src/Main2.hs"]
#if __GLASGOW_HASKELL__ >= 708
res `shouldBe` "src/Main2.hs:10:11:Couldn't match expected type \8216Int\8217 with actual type \8216a0 -> a0\8217\NULProbable cause: \8216id\8217 is applied to too few arguments\NULIn the second argument of \8216(+)\8217, namely \8216id\8217\NULIn the expression: 0 + id\n"
#else
res `shouldBe` "src/Main2.hs:10:11:Couldn't match expected type `Int' with actual type `a0 -> a0'\NULIn the second argument of `(+)', namely `id'\NULIn the expression: 0 + id\NULIn an equation for `foo': foo = 0 + id\n"
#endif
1 change: 0 additions & 1 deletion test/CustomPackageDbSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ spec = do
let tdir = "test/data/custom-cradle"
Just stack <- runD' tdir $ getCustomPkgDbStack
stack `shouldBe` [ GlobalDb
, UserDb
, PackageDb "package-db-a"
, PackageDb "package-db-b"
, PackageDb "package-db-c"
Expand Down
11 changes: 11 additions & 0 deletions test/FindSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,20 @@ import Language.Haskell.GhcMod.Find
import Test.Hspec
import TestUtils

import Dir

spec :: Spec
spec = do
describe "db <- loadSymbolDb" $ do
it "lookupSymbol' db \"head\" contains at least `Data.List'" $ do
db <- runD $ loadSymbolDb
lookupSym "head" db `shouldContain` [ModuleString "Data.List"]

it "lookupSymbol' db \"untag\" contains at least `Data.Tagged'" $ bracketTagged $ do
db <- runD $ loadSymbolDb
lookupSym "untag" db `shouldContain` [ModuleString "Data.Tagged"]

it "lookupSymbol' db \"untag\" does not contain `Data.Tagged' if not installed" $ do
withDirectory_ "test/data/options-cradle" $ do
db <- runD $ loadSymbolDb
lookupSym "untag" db `shouldNotContain` [ModuleString "Data.Tagged"]
16 changes: 7 additions & 9 deletions test/InfoSpec.hs
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
{-# LANGUAGE CPP #-}
module InfoSpec where

import Control.Applicative
import Data.List (isPrefixOf)
import Language.Haskell.GhcMod
#if __GLASGOW_HASKELL__ < 706
import System.Environment.Executable (getExecutablePath)
#else
import System.Environment (getExecutablePath)
#endif
import System.FilePath
import Test.Hspec
import TestUtils
import Prelude
Expand Down Expand Up @@ -46,6 +39,10 @@ spec = do
res <- runD' tdir $ types False "ImportsTH.hs" 3 8
res `shouldBe` unlines ["3 8 3 16 \"String -> IO ()\"", "3 8 3 20 \"IO ()\"", "3 1 3 20 \"IO ()\""]

it "works with a module in Explicit project type" $ bracketTagged $ do
res <- runD $ types True "src/Main.hs" 9 10
res `shouldBe` unlines ["9 8 9 14 \"() -> IO ()\"\n9 8 9 17 \"IO ()\"\n9 1 9 17 \"IO ()\""]

describe "info" $ do
it "works for non exported functions" $ do
let tdir = "test/data/non-exported"
Expand All @@ -62,5 +59,6 @@ spec = do
res <- runD' tdir $ info "ImportsTH.hs" $ Expression "bar"
res `shouldSatisfy` ("bar :: [Char]" `isPrefixOf`)

getDistDir :: IO FilePath
getDistDir = takeDirectory . takeDirectory . takeDirectory <$> getExecutablePath
it "works with a module in Explicit project type" $ bracketTagged $ do
res <- runD $ info "src/Main.hs" $ Expression "foo"
res `shouldSatisfy` ("foo :: Int" `isPrefixOf`)
10 changes: 10 additions & 0 deletions test/ListSpec.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module ListSpec where

import Control.Applicative
import Dir
import Language.Haskell.GhcMod
import Test.Hspec
import TestUtils
Expand All @@ -12,3 +13,12 @@ spec = do
it "contains at least `Data.Map'" $ do
mdls <- runD $ lines <$> modules False
mdls `shouldContain` ["Data.Map"]

it "contains at least `Data.Tagged'" $ bracketTagged $ do
mdls <- runD $ lines <$> modules False
mdls `shouldContain` ["Data.Tagged"]

it "does not contain `Data.Tagged'" $ do
withDirectory_ "test/data/options-cradle" $ do
mdls <- runD $ lines <$> modules False
mdls `shouldNotContain` ["Data.Tagged"]
17 changes: 17 additions & 0 deletions test/TestUtils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module TestUtils (
, shouldReturnError
, isPkgDbAt
, isPkgConfDAt
, bracketTagged
, module Language.Haskell.GhcMod.Monad
, module Language.Haskell.GhcMod.Types
) where
Expand All @@ -22,13 +23,16 @@ import Language.Haskell.GhcMod.Types
import Control.Arrow
import Control.Category
import Control.Applicative
import Control.Monad
import Control.Monad.Error (ErrorT, runErrorT)
import Control.Monad.Trans.Journal
import Data.List.Split
import Data.Label
import Data.String
import Dir
import System.FilePath
import System.Directory
import System.Process
import Test.Hspec
import Prelude hiding ((.))

Expand Down Expand Up @@ -122,3 +126,16 @@ isPkgDbAt _ _ = False

instance IsString ModuleName where
fromString = mkModuleName

-- | Bracketing function for test/data/options-cradle environment to install tagged in package-db-a
bracketTagged :: IO a -> IO a
bracketTagged m = do
withDirectory_ "test/data/options-cradle" $ do
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hiding the directory in here is confusing, just took me more than 30sec to find that :p

void $ system "cabal install --global --package-db=package-db-a --prefix=$(pwd) tagged"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly I'd rather the tests didn't start installing stuff with cabal, is there a particular reason you need to install a package rather than just, say using one of the boot packages like containers or bytestring or something?

putStrLn "start"
void $ system "ghc-pkg list --global --user --package-db=package-db-a tagged"
putStrLn "stop"
res <- m
void $ system "ghc-pkg --package-db=package-db-a unregister tagged"
-- void $ system "cabal sandbox delete"
return res
1 change: 0 additions & 1 deletion test/data/custom-cradle/ghc-mod.package-db-stack
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
global
user
package-db-a
package-db-b
package-db-c
2 changes: 2 additions & 0 deletions test/data/options-cradle/ghc-mod.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-isrc
-DINTERPRETED
5 changes: 5 additions & 0 deletions test/data/options-cradle/ghc-mod.package-db-stack
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
global
user
package-db-a
package-db-b
package-db-c
Binary file not shown.
Binary file not shown.
Binary file not shown.
12 changes: 12 additions & 0 deletions test/data/options-cradle/src/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Main
( main
, foo
) where

import Data.Tagged

main :: IO ()
main = return ()

foo :: Int
foo = 0
10 changes: 10 additions & 0 deletions test/data/options-cradle/src/Main2.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module Main2
( main
, foo
) where

main :: IO ()
main = return ()

foo :: Int
foo = 0 + id