Skip to content

Commit 8957a42

Browse files
authored
Merge branch 'master' into batch-load-multi-read
2 parents aff67c0 + 2c200b4 commit 8957a42

File tree

14 files changed

+189
-14
lines changed

14 files changed

+189
-14
lines changed

cabal.project

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ packages:
88
./hls-test-utils
99

1010

11-
index-state: 2025-06-16T09:44:13Z
11+
index-state: 2025-07-09T16:51:20Z
1212

1313
tests: True
1414
test-show-details: direct

ghcide-test/data/multi-unit/a-1.0.0-inplace

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ base
1616
text
1717
-XHaskell98
1818
A
19+
+RTS
20+
-A32M
21+
-RTS

ghcide-test/data/multi-unit/c-1.0.0-inplace

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ a-1.0.0-inplace
1717
base
1818
-XHaskell98
1919
C
20+
+RTS
21+
-A32M

ghcide-test/exe/CradleTests.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@ simpleSubDirectoryTest =
117117

118118
multiTests :: FilePath -> [TestTree]
119119
multiTests dir =
120-
[simpleMultiTest dir, simpleMultiTest2 dir, simpleMultiTest3 dir, simpleMultiDefTest dir]
120+
[ simpleMultiTest dir
121+
, simpleMultiTest2 dir
122+
, simpleMultiTest3 dir
123+
, simpleMultiDefTest dir
124+
]
121125

122126
multiTestName :: FilePath -> String -> String
123127
multiTestName dir name = "simple-" ++ dir ++ "-" ++ name

ghcide/ghcide.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ library
7373
, Glob
7474
, haddock-library >=1.8 && <1.12
7575
, hashable
76-
, hie-bios ^>=0.15.0
76+
, hie-bios ^>=0.16.0
7777
, hie-compat ^>=0.3.0.0
7878
, hiedb ^>= 0.7.0.0
7979
, hls-graph == 2.11.0.0

ghcide/session-loader/Development/IDE/Session.hs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import Development.IDE.Types.HscEnvEq (HscEnvEq)
5656
import Development.IDE.Types.Location
5757
import Development.IDE.Types.Options
5858
import qualified HIE.Bios as HieBios
59+
import qualified HIE.Bios.Cradle.Utils as HieBios
5960
import HIE.Bios.Environment hiding (getCacheDir)
6061
import HIE.Bios.Types hiding (Log)
6162
import qualified HIE.Bios.Types as HieBios
@@ -1023,6 +1024,121 @@ memoIO op = do
10231024
return (Map.insert k res mp, res)
10241025
Just res -> return (mp, res)
10251026

1027+
unit_flags :: [Flag (CmdLineP [String])]
1028+
unit_flags = [defFlag "unit" (SepArg addUnit)]
1029+
1030+
addUnit :: String -> EwM (CmdLineP [String]) ()
1031+
addUnit unit_str = liftEwM $ do
1032+
units <- getCmdLineState
1033+
putCmdLineState (unit_str : units)
1034+
1035+
-- | Throws if package flags are unsatisfiable
1036+
setOptions :: GhcMonad m
1037+
=> NormalizedFilePath
1038+
-> ComponentOptions
1039+
-> DynFlags
1040+
-> FilePath -- ^ root dir, see Note [Root Directory]
1041+
-> m (NonEmpty (DynFlags, [GHC.Target]))
1042+
setOptions cfp (ComponentOptions theOpts compRoot _) dflags rootDir = do
1043+
((theOpts',_errs,_warns),units) <- processCmdLineP unit_flags [] (map noLoc theOpts)
1044+
case NE.nonEmpty units of
1045+
Just us -> initMulti us
1046+
Nothing -> do
1047+
(df, targets) <- initOne (map unLoc theOpts')
1048+
-- A special target for the file which caused this wonderful
1049+
-- component to be created. In case the cradle doesn't list all the targets for
1050+
-- the component, in which case things will be horribly broken anyway.
1051+
--
1052+
-- When we have a singleComponent that is caused to be loaded due to a
1053+
-- file, we assume the file is part of that component. This is useful
1054+
-- for bare GHC sessions, such as many of the ones used in the testsuite
1055+
--
1056+
-- We don't do this when we have multiple components, because each
1057+
-- component better list all targets or there will be anarchy.
1058+
-- It is difficult to know which component to add our file to in
1059+
-- that case.
1060+
-- Multi unit arguments are likely to come from cabal, which
1061+
-- does list all targets.
1062+
--
1063+
-- If we don't end up with a target for the current file in the end, then
1064+
-- we will report it as an error for that file
1065+
let abs_fp = toAbsolute rootDir (fromNormalizedFilePath cfp)
1066+
let special_target = Compat.mkSimpleTarget df abs_fp
1067+
pure $ (df, special_target : targets) :| []
1068+
where
1069+
initMulti unitArgFiles =
1070+
forM unitArgFiles $ \f -> do
1071+
args <- liftIO $ expandResponse [f]
1072+
-- The reponse files may contain arguments like "+RTS",
1073+
-- and hie-bios doesn't expand the response files of @-unit@ arguments.
1074+
-- Thus, we need to do the stripping here.
1075+
initOne $ HieBios.removeRTS $ HieBios.removeVerbosityOpts args
1076+
initOne this_opts = do
1077+
(dflags', targets') <- addCmdOpts this_opts dflags
1078+
let dflags'' =
1079+
case unitIdString (homeUnitId_ dflags') of
1080+
-- cabal uses main for the unit id of all executable packages
1081+
-- This makes multi-component sessions confused about what
1082+
-- options to use for that component.
1083+
-- Solution: hash the options and use that as part of the unit id
1084+
-- This works because there won't be any dependencies on the
1085+
-- executable unit.
1086+
"main" ->
1087+
let hash = B.unpack $ B16.encode $ H.finalize $ H.updates H.init (map B.pack this_opts)
1088+
hashed_uid = Compat.toUnitId (Compat.stringToUnit ("main-"++hash))
1089+
in setHomeUnitId_ hashed_uid dflags'
1090+
_ -> dflags'
1091+
1092+
let targets = makeTargetsAbsolute root targets'
1093+
root = case workingDirectory dflags'' of
1094+
Nothing -> compRoot
1095+
Just wdir -> compRoot </> wdir
1096+
let dflags''' =
1097+
setWorkingDirectory root $
1098+
disableWarningsAsErrors $
1099+
-- disabled, generated directly by ghcide instead
1100+
flip gopt_unset Opt_WriteInterface $
1101+
-- disabled, generated directly by ghcide instead
1102+
-- also, it can confuse the interface stale check
1103+
dontWriteHieFiles $
1104+
setIgnoreInterfacePragmas $
1105+
setBytecodeLinkerOptions $
1106+
disableOptimisation $
1107+
Compat.setUpTypedHoles $
1108+
makeDynFlagsAbsolute compRoot -- makeDynFlagsAbsolute already accounts for workingDirectory
1109+
dflags''
1110+
return (dflags''', targets)
1111+
1112+
setIgnoreInterfacePragmas :: DynFlags -> DynFlags
1113+
setIgnoreInterfacePragmas df =
1114+
gopt_set (gopt_set df Opt_IgnoreInterfacePragmas) Opt_IgnoreOptimChanges
1115+
1116+
disableOptimisation :: DynFlags -> DynFlags
1117+
disableOptimisation df = updOptLevel 0 df
1118+
1119+
setHiDir :: FilePath -> DynFlags -> DynFlags
1120+
setHiDir f d =
1121+
-- override user settings to avoid conflicts leading to recompilation
1122+
d { hiDir = Just f}
1123+
1124+
setODir :: FilePath -> DynFlags -> DynFlags
1125+
setODir f d =
1126+
-- override user settings to avoid conflicts leading to recompilation
1127+
d { objectDir = Just f}
1128+
1129+
getCacheDirsDefault :: String -> [String] -> IO CacheDirs
1130+
getCacheDirsDefault prefix opts = do
1131+
dir <- Just <$> getXdgDirectory XdgCache (cacheDir </> prefix ++ "-" ++ opts_hash)
1132+
return $ CacheDirs dir dir dir
1133+
where
1134+
-- Create a unique folder per set of different GHC options, assuming that each different set of
1135+
-- GHC options will create incompatible interface files.
1136+
opts_hash = B.unpack $ B16.encode $ H.finalize $ H.updates H.init (map B.pack opts)
1137+
1138+
-- | Sub directory for the cache path
1139+
cacheDir :: String
1140+
cacheDir = "ghcide"
1141+
10261142
----------------------------------------------------------------------------------------------------
10271143

10281144
data PackageSetupException

ghcide/src/Development/IDE/Spans/Common.hs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,10 @@ haddockToMarkdown (H.DocOrderedList things) =
190190
haddockToMarkdown (H.DocDefList things)
191191
= '\n' : (unlines $ map (\(term, defn) -> "+ **" ++ haddockToMarkdown term ++ "**: " ++ haddockToMarkdown defn) things)
192192

193-
-- we cannot render math by default
194-
haddockToMarkdown (H.DocMathInline _)
195-
= "*cannot render inline math formula*"
196-
haddockToMarkdown (H.DocMathDisplay _)
197-
= "\n\n*cannot render display math formula*\n\n"
193+
haddockToMarkdown (H.DocMathInline s)
194+
= "`" ++ s ++ "`"
195+
haddockToMarkdown (H.DocMathDisplay s)
196+
= "\n```latex\n" ++ s ++ "\n```\n"
198197

199198
-- TODO: render tables
200199
haddockToMarkdown (H.DocTable _t)

haskell-language-server.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ library hls-cabal-plugin
282282
, transformers
283283
, unordered-containers >=0.2.10.0
284284
, containers
285-
, cabal-add
285+
, cabal-add ^>=0.1
286286
, process
287287
, aeson
288288
, Cabal

hls-graph/src/Development/IDE/Graph/Internal/Key.hs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ module Development.IDE.Graph.Internal.Key
3434
) where
3535

3636
--import Control.Monad.IO.Class ()
37+
import Control.Exception (evaluate)
3738
import Data.Coerce
3839
import Data.Dynamic
3940
import qualified Data.HashMap.Strict as Map
@@ -85,8 +86,15 @@ newKey k = unsafePerformIO $ do
8586

8687
lookupKeyValue :: Key -> KeyValue
8788
lookupKeyValue (UnsafeMkKey x) = unsafePerformIO $ do
89+
-- NOTE:
90+
-- The reason for this evaluate is that the x, if not forced yet, is a thunk
91+
-- that forces the atomicModifyIORef' in the creation of the new key. If it
92+
-- isn't forced *before* reading the keyMap, the keyMap will only obtain the new
93+
-- key (x) *after* the IntMap is already copied out of the keyMap reference,
94+
-- i.e. when it is forced for the lookup in the IntMap.
95+
k <- evaluate x
8896
GlobalKeyValueMap _ im _ <- readIORef keyMap
89-
pure $! im IM.! x
97+
pure $! im IM.! k
9098

9199
{-# NOINLINE lookupKeyValue #-}
92100

plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import GHC (addAnns, ann)
6363

6464
#if MIN_VERSION_ghc(9,9,0)
6565
import GHC (NoAnn (..))
66+
import GHC (EpAnnComments (..))
6667
#endif
6768

6869
------------------------------------------------------------------------------
@@ -170,7 +171,7 @@ appendConstraint constraintT = go . traceAst "appendConstraint"
170171
constraint <- liftParseAST df constraintT
171172
constraint <- pure $ setEntryDP constraint (SameLine 1)
172173
#if MIN_VERSION_ghc(9,9,0)
173-
let l'' = fmap (addParensToCtxt close_dp) l'
174+
let l'' = moveCommentsToTheEnd $ fmap (addParensToCtxt close_dp) l'
174175
#else
175176
let l'' = (fmap.fmap) (addParensToCtxt close_dp) l'
176177
#endif
@@ -205,6 +206,26 @@ appendConstraint constraintT = go . traceAst "appendConstraint"
205206

206207
return $ reLocA $ L lTop $ HsQualTy noExtField context ast
207208

209+
#if MIN_VERSION_ghc(9,9,0)
210+
-- | This moves comment annotation toward the end of the block
211+
-- This is useful when extending a block, so the comment correctly appears
212+
-- after.
213+
--
214+
-- See https://github.com/haskell/haskell-language-server/issues/4648 for
215+
-- discussion.
216+
--
217+
-- For example, the following element, @(Foo) => -- hello@, when introducing an
218+
-- additionnal constraint, `Bar`, instead of getting `@(Foo, Bar) => -- hello@,
219+
-- we get @(Foo, -- hello Bar) =>@
220+
--
221+
-- This is a bit painful that the pretty printer is not able to realize that it
222+
-- introduces the token `=>` inside the comment and instead does something with
223+
-- meaning, but that's another story.
224+
moveCommentsToTheEnd :: EpAnn ann -> EpAnn ann
225+
moveCommentsToTheEnd (EpAnn entry anns (EpaComments priors)) = EpAnn entry anns (EpaCommentsBalanced { priorComments = [], followingComments = priors})
226+
moveCommentsToTheEnd (EpAnn entry anns (EpaCommentsBalanced priors following)) = EpAnn entry anns (EpaCommentsBalanced { priorComments = [], followingComments = priors <> following})
227+
#endif
228+
208229
liftParseAST
209230
:: forall ast l. (ASTElement l ast, ExactPrint (LocatedAn l ast))
210231
=> DynFlags -> String -> TransformT (Either String) (LocatedAn l ast)
@@ -500,7 +521,7 @@ extendHiding symbol (L l idecls) mlies df = do
500521
Nothing -> do
501522
#if MIN_VERSION_ghc(9,11,0)
502523
let ann :: EpAnn (AnnList (EpToken "hiding", [EpToken ","]))
503-
ann = noAnnSrcSpanDP0
524+
ann = noAnnSrcSpanDP0
504525
#elif MIN_VERSION_ghc(9,9,0)
505526
let ann = noAnnSrcSpanDP0
506527
#else

0 commit comments

Comments
 (0)