@@ -42,6 +42,7 @@ import qualified Data.HashMap.Strict as HM
4242import Data.IORef
4343import qualified Data.Set as OS
4444import Data.List
45+ import Data.List.Extra as L
4546import qualified Data.List.NonEmpty as NE
4647import qualified Data.Map.Strict as Map
4748import Data.Maybe
@@ -501,7 +502,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
501502 packageSetup (hieYaml, cfp, opts, libDir) = do
502503 -- Parse DynFlags for the newly discovered component
503504 hscEnv <- emptyHscEnv ideNc libDir
504- newTargetDfs <- evalGhcEnv hscEnv $ setOptions opts (hsc_dflags hscEnv)
505+ newTargetDfs <- evalGhcEnv hscEnv $ setOptions cfp opts (hsc_dflags hscEnv)
505506 let deps = componentDependencies opts ++ maybeToList hieYaml
506507 dep_info <- getDependencyInfo deps
507508 -- Now lookup to see whether we are combining with an existing HscEnv
@@ -575,7 +576,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
575576 let this_flags_map = HM. fromList (concatMap toFlagsMap all_targets)
576577
577578 void $ modifyVar' fileToFlags $
578- Map. insertWith HM. union hieYaml this_flags_map
579+ Map. insert hieYaml this_flags_map
579580 void $ modifyVar' filesMap $
580581 flip HM. union (HM. fromList (zip (map fst $ concatMap toFlagsMap all_targets) (repeat hieYaml)))
581582
@@ -756,7 +757,10 @@ fromTargetId is exts (GHC.TargetModule modName) env dep = do
756757-- For a 'TargetFile' we consider all the possible module names
757758fromTargetId _ _ (GHC. TargetFile f _) env deps = do
758759 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]]
760764
761765toFlagsMap :: TargetDetails -> [(NormalizedFilePath , (IdeResult HscEnvEq , DependencyInfo ))]
762766toFlagsMap TargetDetails {.. } =
@@ -781,8 +785,13 @@ newComponentCache
781785 -> [ComponentInfo ]
782786 -> IO [ ([TargetDetails ], (IdeResult HscEnvEq , DependencyInfo ))]
783787newComponentCache 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))
786795 let dfs = map componentDynFlags $ Map. elems cis
787796 uids = Map. keys cis
788797 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
825834 Nothing -> pure ()
826835 Just err -> logWith recorder Error $ LogDLLLoadError err
827836
828- fmap (addSpecial cfp) $ forM (Map. elems cis) $ \ ci -> do
837+ forM (Map. elems cis) $ \ ci -> do
829838 let df = componentDynFlags ci
830839 let newFunc = maybe newHscEnvEqPreserveImportPaths newHscEnvEq cradlePath
831840 thisEnv <- do
@@ -859,34 +868,7 @@ newComponentCache recorder exts cradlePath cfp hsc_env old_cis new_cis = do
859868 let mk t = fromTargetId (importPaths df) exts (targetId t) targetEnv targetDepends
860869 ctargets <- concatMapM mk (componentTargets ci)
861870
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)
890872
891873{- Note [Avoiding bad interface files]
892874~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1068,12 +1050,28 @@ addUnit unit_str = liftEwM $ do
10681050 putCmdLineState (unit_str : units)
10691051
10701052-- | 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
10731055 ((theOpts',errs,warns),units) <- processCmdLineP unit_flags [] (map noLoc theOpts)
10741056 case NE. nonEmpty units of
10751057 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. :| []
10771075 where
10781076 initMulti unitArgFiles =
10791077 forM unitArgFiles $ \ f -> do
0 commit comments