Skip to content

Commit

Permalink
Support for cabal multi-component
Browse files Browse the repository at this point in the history
new versions of cabal-install (>= 3.11) have support for starting
multi-component repls which allow us to correctly load multiple components,
cruicially including the correct transitive closure of all the components we
need for correct HLS support.

This works by passing multiple targets to `cabal repl`, i.e.
`cabal repl target1 target2 ...`

In order to do this, we must know all the previous targets we have loaded,
so `runCradle` gets an extra `[FilePath]` argument so that this can be supplied.

This is the only externally visible API change in this patch.

`hie-bios` sometimes passes raw `FilePath`s as targets, and sometimes
actual component names (lib:foo, test:foo, exe:bar ...)

The latter happes when we have user configuration in the hie.yaml explicitly
specifying component names.

As downstream users of hie-bios have no concept of "component names", they
only know about files which caused a particular component to be loaded, we
must handle mapping back from `FilePath`s when starting a multi-component session.

It was not easy to do this with the way the code previously work with multi-cradles
and `getCradle` and `multiAction` being mutually recursive.

So now we uniformly treat everything as a multi-cradle of sorts, resolving the
configuration tree from hie.yaml (which I took care not to change) into a
list of `ResolvedCradle`s ordered by prefixes, which can easily be consulted
by the cabal multi-component cradle to map `FilePath`s back to component
names when needed.
  • Loading branch information
wz1000 committed Jun 28, 2023
1 parent 78d0cd2 commit 47da04a
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 220 deletions.
2 changes: 1 addition & 1 deletion exe/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ main = do
[] -> error "too few arguments"
_ -> do
res <- forM files $ \fp -> do
res <- getCompilerOptions logger fp cradle
res <- getCompilerOptions logger fp [] cradle
case res of
CradleFail (CradleError _deps _ex err) ->
return $ "Failed to show flags for \""
Expand Down
26 changes: 13 additions & 13 deletions src/HIE/Bios/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module HIE.Bios.Config(
pattern StackType,
stackComponent,
stackYaml,
CradleType(..),
CradleTree(..),
Callable(..)
) where

Expand Down Expand Up @@ -47,7 +47,7 @@ data CradleConfig a =
-- ^ Dependencies of a cradle.
-- Dependencies are expected to be relative to the root directory.
-- The given files are not required to exist.
, cradleType :: CradleType a
, cradleTree :: CradleTree a
-- ^ Type of the cradle to use. Actions to obtain
-- compiler flags from are dependant on this field.
}
Expand Down Expand Up @@ -100,7 +100,7 @@ pattern StackType { stackComponent, stackYaml } = StackType_ (Last stackComponen
instance Show StackType where
show = show . Stack

data CradleType a
data CradleTree a
= Cabal { cabalType :: !CabalType }
| CabalMulti { defaultCabal :: !CabalType, subCabalComponents :: [ (FilePath, CabalType) ] }
| Stack { stackType :: !StackType }
Expand All @@ -125,7 +125,7 @@ data CradleType a
| Other { otherConfig :: a, originalYamlValue :: Value }
deriving (Eq, Functor)

instance Show (CradleType a) where
instance Show (CradleTree a) where
show (Cabal comp) = "Cabal {component = " ++ show (cabalComponent comp) ++ "}"
show (CabalMulti d a) = "CabalMulti {defaultCabal = " ++ show d ++ ", subCabalComponents = " ++ show a ++ "}"
show (Stack comp) = "Stack {component = " ++ show (stackComponent comp) ++ ", stackYaml = " ++ show (stackYaml comp) ++ "}"
Expand Down Expand Up @@ -154,31 +154,31 @@ readConfig fp = do

fromYAMLConfig :: CradleConfigYAML a -> Config a
fromYAMLConfig cradleYAML = Config $ CradleConfig (fromMaybe [] $ YAML.dependencies cradleYAML)
(toCradleType $ YAML.cradle cradleYAML)
(toCradleTree $ YAML.cradle cradleYAML)

toCradleType :: YAML.CradleComponent a -> CradleType a
toCradleType (YAML.Multi cpts) =
toCradleTree :: YAML.CradleComponent a -> CradleTree a
toCradleTree (YAML.Multi cpts) =
Multi $ (\(YAML.MultiSubComponent fp' cfg) -> (fp', cradle $ fromYAMLConfig cfg)) <$> cpts
toCradleType (YAML.Stack (YAML.StackConfig yaml cpts)) =
toCradleTree (YAML.Stack (YAML.StackConfig yaml cpts)) =
case cpts of
YAML.NoComponent -> Stack $ StackType Nothing yaml
(YAML.SingleComponent c) -> Stack $ StackType (Just c) yaml
(YAML.ManyComponents cs) -> StackMulti (StackType Nothing yaml)
((\(YAML.StackComponent fp' c cYAML) ->
(fp', StackType (Just c) cYAML)) <$> cs)
toCradleType (YAML.Cabal (YAML.CabalConfig prjFile cpts)) =
toCradleTree (YAML.Cabal (YAML.CabalConfig prjFile cpts)) =
case cpts of
YAML.NoComponent -> Cabal $ CabalType Nothing prjFile
(YAML.SingleComponent c) -> Cabal $ CabalType (Just c) prjFile
(YAML.ManyComponents cs) -> CabalMulti (CabalType Nothing prjFile)
((\(YAML.CabalComponent fp' c cPrjFile) ->
(fp', CabalType (Just c) cPrjFile)) <$> cs)
toCradleType (YAML.Direct cfg) = Direct (YAML.arguments cfg)
toCradleType (YAML.Bios cfg) = Bios (toCallable $ YAML.callable cfg)
toCradleTree (YAML.Direct cfg) = Direct (YAML.arguments cfg)
toCradleTree (YAML.Bios cfg) = Bios (toCallable $ YAML.callable cfg)
(toCallable <$> YAML.depsCallable cfg)
(YAML.ghcPath cfg)
toCradleType (YAML.None _) = None
toCradleType (YAML.Other cfg) = Other (YAML.otherConfig cfg)
toCradleTree (YAML.None _) = None
toCradleTree (YAML.Other cfg) = Other (YAML.otherConfig cfg)
(YAML.originalYamlValue cfg)

toCallable :: YAML.Callable -> Callable
Expand Down
Loading

0 comments on commit 47da04a

Please sign in to comment.