@@ -42,6 +42,7 @@ import qualified Data.HashMap.Strict as HM
42
42
import Data.IORef
43
43
import qualified Data.Set as OS
44
44
import Data.List
45
+ import Data.List.Extra as L
45
46
import qualified Data.List.NonEmpty as NE
46
47
import qualified Data.Map.Strict as Map
47
48
import Data.Maybe
@@ -501,7 +502,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
501
502
packageSetup (hieYaml, cfp, opts, libDir) = do
502
503
-- Parse DynFlags for the newly discovered component
503
504
hscEnv <- emptyHscEnv ideNc libDir
504
- newTargetDfs <- evalGhcEnv hscEnv $ setOptions opts (hsc_dflags hscEnv)
505
+ newTargetDfs <- evalGhcEnv hscEnv $ setOptions cfp opts (hsc_dflags hscEnv)
505
506
let deps = componentDependencies opts ++ maybeToList hieYaml
506
507
dep_info <- getDependencyInfo deps
507
508
-- Now lookup to see whether we are combining with an existing HscEnv
@@ -575,7 +576,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
575
576
let this_flags_map = HM. fromList (concatMap toFlagsMap all_targets)
576
577
577
578
void $ modifyVar' fileToFlags $
578
- Map. insertWith HM. union hieYaml this_flags_map
579
+ Map. insert hieYaml this_flags_map
579
580
void $ modifyVar' filesMap $
580
581
flip HM. union (HM. fromList (zip (map fst $ concatMap toFlagsMap all_targets) (repeat hieYaml)))
581
582
@@ -756,7 +757,10 @@ fromTargetId is exts (GHC.TargetModule modName) env dep = do
756
757
-- For a 'TargetFile' we consider all the possible module names
757
758
fromTargetId _ _ (GHC. TargetFile f _) env deps = do
758
759
nf <- toNormalizedFilePath' <$> makeAbsolute f
759
- return [TargetDetails (TargetFile nf) env deps [nf]]
760
+ let other
761
+ | " -boot" `isSuffixOf` f = toNormalizedFilePath' (L. dropEnd 5 $ fromNormalizedFilePath nf)
762
+ | otherwise = toNormalizedFilePath' (fromNormalizedFilePath nf ++ " -boot" )
763
+ return [TargetDetails (TargetFile nf) env deps [nf, other]]
760
764
761
765
toFlagsMap :: TargetDetails -> [(NormalizedFilePath , (IdeResult HscEnvEq , DependencyInfo ))]
762
766
toFlagsMap TargetDetails {.. } =
@@ -781,8 +785,13 @@ newComponentCache
781
785
-> [ComponentInfo ]
782
786
-> IO [ ([TargetDetails ], (IdeResult HscEnvEq , DependencyInfo ))]
783
787
newComponentCache recorder exts cradlePath cfp hsc_env old_cis new_cis = do
784
- let cis = Map. union (mkMap new_cis) (mkMap old_cis) -- Left biased so prefer new components over old ones
785
- mkMap = Map. fromList . map (\ ci -> (componentUnitId ci, ci))
788
+ let cis = Map. unionWith unionCIs (mkMap new_cis) (mkMap old_cis)
789
+ -- When we have multiple components with the same uid,
790
+ -- prefer the new one over the old.
791
+ -- However, we might have added some targets to the old unit
792
+ -- (see special target), so preserve those
793
+ unionCIs new_ci old_ci = new_ci { componentTargets = componentTargets new_ci ++ componentTargets old_ci }
794
+ mkMap = Map. fromListWith unionCIs . map (\ ci -> (componentUnitId ci, ci))
786
795
let dfs = map componentDynFlags $ Map. elems cis
787
796
uids = Map. keys cis
788
797
hscEnv' <- -- Set up a multi component session with the other units on GHC 9.4
@@ -825,7 +834,7 @@ newComponentCache recorder exts cradlePath cfp hsc_env old_cis new_cis = do
825
834
Nothing -> pure ()
826
835
Just err -> logWith recorder Error $ LogDLLLoadError err
827
836
828
- fmap (addSpecial cfp) $ forM (Map. elems cis) $ \ ci -> do
837
+ forM (Map. elems cis) $ \ ci -> do
829
838
let df = componentDynFlags ci
830
839
let newFunc = maybe newHscEnvEqPreserveImportPaths newHscEnvEq cradlePath
831
840
thisEnv <- do
@@ -859,34 +868,7 @@ newComponentCache recorder exts cradlePath cfp hsc_env old_cis new_cis = do
859
868
let mk t = fromTargetId (importPaths df) exts (targetId t) targetEnv targetDepends
860
869
ctargets <- concatMapM mk (componentTargets ci)
861
870
862
- return (ctargets, res)
863
- where
864
- -- A special target for the file which caused this wonderful
865
- -- component to be created. In case the cradle doesn't list all the targets for
866
- -- the component, in which case things will be horribly broken anyway.
867
- -- Otherwise, we will immediately attempt to reload this module which
868
- -- causes an infinite loop and high CPU usage.
869
- addSpecial cfp xs
870
- | alreadyIncluded = xs
871
- | otherwise = let (as,bs) = break inIncludePath xs
872
- in case bs of
873
- [] ->
874
- -- There is no appropriate target to add the file to, so pick one randomly
875
- case as of
876
- [] -> []
877
- ((ctargets,res@ (targetEnv, targetDepends)): xs) ->
878
- let x = (TargetDetails (TargetFile cfp) targetEnv targetDepends [cfp] : ctargets, res)
879
- in x: xs
880
- -- There is a component which could have this file in its include path
881
- -- pick one of these components
882
- ((ctargets,res@ (targetEnv, targetDepends)): bs) ->
883
- let b = (TargetDetails (TargetFile cfp) targetEnv targetDepends [cfp] : ctargets, res)
884
- in as ++ (b: bs)
885
- where
886
- alreadyIncluded = any (any (cfp == ) . concatMap targetLocations . fst ) xs
887
- inIncludePath (_,((_, Just env),_)) = any (isParent $ fromNormalizedFilePath cfp) $ maybe [] OS. toList $ envImportPaths env
888
- where
889
- isParent fp parent = any (equalFilePath parent) (map (foldr (</>) " " ) $ inits $ splitPath fp)
871
+ return (L. nubOrdOn targetTarget ctargets, res)
890
872
891
873
{- Note [Avoiding bad interface files]
892
874
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1068,12 +1050,28 @@ addUnit unit_str = liftEwM $ do
1068
1050
putCmdLineState (unit_str : units)
1069
1051
1070
1052
-- | Throws if package flags are unsatisfiable
1071
- setOptions :: GhcMonad m => ComponentOptions -> DynFlags -> m (NE. NonEmpty (DynFlags , [GHC. Target ]))
1072
- setOptions (ComponentOptions theOpts compRoot _) dflags = do
1053
+ setOptions :: GhcMonad m => NormalizedFilePath -> ComponentOptions -> DynFlags -> m (NE. NonEmpty (DynFlags , [GHC. Target ]))
1054
+ setOptions cfp (ComponentOptions theOpts compRoot _) dflags = do
1073
1055
((theOpts',errs,warns),units) <- processCmdLineP unit_flags [] (map noLoc theOpts)
1074
1056
case NE. nonEmpty units of
1075
1057
Just us -> initMulti us
1076
- Nothing -> (NE. :| [] ) <$> initOne (map unLoc theOpts')
1058
+ Nothing -> do
1059
+ (df, targets) <- initOne (map unLoc theOpts')
1060
+ -- A special target for the file which caused this wonderful
1061
+ -- component to be created. In case the cradle doesn't list all the targets for
1062
+ -- the component, in which case things will be horribly broken anyway.
1063
+ -- Otherwise, we will immediately attempt to reload this module which
1064
+ -- causes an infinite loop and high CPU usage.
1065
+ --
1066
+ -- We don't do this when we have multiple components, because each
1067
+ -- component better list all targets or there will be anarchy.
1068
+ -- It is difficult to know which component to add our file to in
1069
+ -- that case.
1070
+ -- Multi unit arguments are likely to come from cabal, which
1071
+ -- does list all targets.
1072
+ abs_fp <- liftIO $ makeAbsolute (fromNormalizedFilePath cfp)
1073
+ let special_target = Compat. mkSimpleTarget df abs_fp
1074
+ pure $ (df, special_target : targets) NE. :| []
1077
1075
where
1078
1076
initMulti unitArgFiles =
1079
1077
forM unitArgFiles $ \ f -> do
0 commit comments