Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

Commit 903bd86

Browse files
authored
Merge pull request #1549 from fendor/cradle-fix-haddock
Fix haddock documentation for Cradle.hs
2 parents 1542fa2 + 8ff0499 commit 903bd86

File tree

1 file changed

+96
-78
lines changed

1 file changed

+96
-78
lines changed

hie-plugin-api/Haskell/Ide/Engine/Cradle.hs

+96-78
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,24 @@ findLocalCradle fp = do
5252
Nothing -> cabalHelperCradle fp
5353
logm $ "Module \"" ++ fp ++ "\" is loaded by Cradle: " ++ show crdl
5454
return crdl
55+
5556
-- | Check if the given cradle is a stack cradle.
5657
-- This might be used to determine the GHC version to use on the project.
57-
-- If it is a stack-cradle, we have to use `stack path --compiler-exe`
58+
-- If it is a stack-cradle, we have to use @"stack path --compiler-exe"@
5859
-- otherwise we may ask `ghc` directly what version it is.
5960
isStackCradle :: Cradle -> Bool
6061
isStackCradle = (`elem` ["stack", "Cabal-Helper-Stack", "Cabal-Helper-Stack-None"])
6162
. BIOS.actionName
6263
. BIOS.cradleOptsProg
6364

64-
-- | Check if the given cradle is a cabal cradle.
65+
-- | Check if the given cradle is a cabal cradle.
6566
-- This might be used to determine the GHC version to use on the project.
66-
-- If it is a stack-cradle, we have to use `stack path --compiler-exe`
67-
-- otherwise we may ask `ghc` directly what version it is.
67+
-- If it is a stack-cradle, we have to use @"stack path --compiler-exe"@
68+
-- otherwise we may ask @ghc@ directly what version it is.
6869
isCabalCradle :: Cradle -> Bool
6970
isCabalCradle =
7071
(`elem`
71-
["cabal"
72+
[ "cabal"
7273
, "Cabal-Helper-Cabal-V1"
7374
, "Cabal-Helper-Cabal-V2"
7475
, "Cabal-Helper-Cabal-V1-Dir"
@@ -81,10 +82,10 @@ isCabalCradle =
8182

8283
-- | Execute @ghc@ that is based on the given cradle.
8384
-- Output must be a single line. If an error is raised, e.g. the command
84-
-- failed, a @Nothing@ is returned.
85+
-- failed, a 'Nothing' is returned.
8586
-- The exact error is written to logs.
8687
--
87-
-- E.g. for a stack cradle, we use `stack ghc` and for a cabal cradle
88+
-- E.g. for a stack cradle, we use @stack ghc@ and for a cabal cradle
8889
-- we are taking the @ghc@ that is on the path.
8990
execProjectGhc :: Cradle -> [String] -> IO (Maybe String)
9091
execProjectGhc crdl args = do
@@ -167,6 +168,8 @@ This guessing has no guarantees and may change at any time.
167168
=== Example:
168169
169170
Assume the following project structure:
171+
172+
@
170173
/
171174
└── Foo/
172175
├── Foo.cabal
@@ -178,28 +181,31 @@ Assume the following project structure:
178181
├── B.cabal
179182
└── src/
180183
└── Lib2.hs
184+
@
181185
182-
Assume the call @findCabalHelperEntryPoint "/Foo/B/src/Lib2.hs"@.
183-
We now want to know to which project "/Foo/B/src/Lib2.hs" belongs to
186+
Assume the call @findCabalHelperEntryPoint "\/Foo\/B\/src\/Lib2.hs"@.
187+
We now want to know to which project "\/Foo\/B\/src\/Lib2.hs" belongs to
184188
and what the projects root is. If we only do a naive search to find the
185189
first occurrence of either "B.cabal", "stack.yaml", "cabal.project"
186190
or "Foo.cabal", we might assume that the location of "B.cabal" marks
187-
the project's root directory of which "/Foo/B/src/Lib2.hs" is part of.
191+
the project's root directory of which "\/Foo\/B\/src\/Lib2.hs" is part of.
188192
However, there is also a "cabal.project" and "stack.yaml" in the parent
189-
directory, which add the package "B" as a package.
190-
So, the compilation of the package "B", and the file "src/Lib2.hs" in it,
193+
directory, which add the package @B@ as a package.
194+
So, the compilation of the package @B@, and the file "src\/Lib2.hs" in it,
191195
does not only depend on the definitions in "B.cabal", but also
192196
on "stack.yaml" and "cabal.project".
193-
The project root is therefore "/Foo/".
197+
The project root is therefore "\/Foo\/".
194198
Only if there is no "stack.yaml" or "cabal.project" in any of the ancestor
195199
directories, it is safe to assume that "B.cabal" marks the root of the project.
196200
197201
Thus:
202+
198203
>>> findCabalHelperEntryPoint "/Foo/B/src/Lib2.hs
199204
Just (Ex (ProjLocStackYaml { plStackYaml = "/Foo/"}))
200205
201206
or
202-
>>> findCabalHelperEntryPoint "/Foo/B/src/Lib2.hs
207+
208+
>>> findCabalHelperEntryPoint "/Foo/B/src/Lib2.hs"
203209
Just (Ex (ProjLocV2File { plProjectDirV2 = "/Foo/"}))
204210
205211
In the given example, it is not guaranteed which project type is found,
@@ -340,6 +346,8 @@ required to load and compile the given file.
340346
=== Mono-Repo
341347
342348
Assume the project structure:
349+
350+
@
343351
/
344352
└── Mono/
345353
├── cabal.project
@@ -350,21 +358,24 @@ Assume the project structure:
350358
└── B/
351359
├── B.cabal
352360
└── Exe.hs
361+
@
353362
354363
Currently, Haskell IDE Engine needs to know on startup which GHC version is
355364
needed to compile the project. This information is needed to show warnings to
356365
the user if the GHC version on the project does not agree with the GHC version
357366
that was used to compile Haskell IDE Engine.
358367
359368
Therefore, the function 'findLocalCradle' is invoked with a dummy FilePath,
360-
such as "/Mono/Lib.hs". Since there will be no package that contains this
369+
such as "\/Mono\/Lib.hs". Since there will be no package that contains this
361370
dummy FilePath, the result will be a None-cradle.
362371
363372
Either
373+
364374
>>> findLocalCradle "/Mono/Lib.hs"
365375
Cradle { cradleRootDir = "/Mono/", CradleAction { actionName = "Cabal-Helper-Stack-None", ..} }
366376
367-
or:
377+
or
378+
368379
>>> findLocalCradle "/Mono/Lib.hs"
369380
Cradle { cradleRootDir = "/Mono/", CradleAction { actionName = "Cabal-Helper-Cabal-V2-None", ..} }
370381
@@ -374,8 +385,9 @@ a 'cabal' project.
374385
375386
376387
If we are trying to load the executable:
388+
377389
>>> findLocalCradle "/Mono/B/Exe.hs"
378-
Cradle { cradleRootDir = "/Mono/B/", CradleAction { actionName = "Cabal-Helper-Cabal-V2", ..} }
390+
Cradle { cradleRootDir = "/Mono/", CradleAction { actionName = "Cabal-Helper-Cabal-V2", ..} }
379391
380392
we will detect correctly the compiler options, by first finding the appropriate
381393
package, followed by traversing the units in the package and finding the
@@ -384,6 +396,8 @@ component that exposes the executable by FilePath.
384396
=== No explicit executable folder
385397
386398
Assume the project structure:
399+
400+
@
387401
/
388402
└── Library/
389403
├── cabal.project
@@ -392,18 +406,21 @@ Assume the project structure:
392406
└── src
393407
├── Lib.hs
394408
└── Exe.hs
409+
@
395410
396411
There are different dependencies for the library "Lib.hs" and the
397-
executable "Exe.hs". If we are trying to load the executable "src/Exe.hs"
412+
executable "Exe.hs". If we are trying to load the executable "src\/Exe.hs"
398413
we will correctly identify the executable unit, and correctly initialise
399414
dependencies of "exe:Library".
400415
It will be correct even if we load the unit "lib:Library" before
401416
the "exe:Library" because the unit "lib:Library" does not expose
402-
a module "Exe".
417+
a module @"Exe"@.
403418
404419
=== Sub package
405420
406421
Assume the project structure:
422+
423+
@
407424
/
408425
└── Repo/
409426
├── cabal.project
@@ -414,12 +431,13 @@ Assume the project structure:
414431
└── SubRepo
415432
├── SubRepo.cabal
416433
└── Lib2.hs
434+
@
417435
418-
When we try to load "/Repo/SubRepo/Lib2.hs", we need to identify root
419-
of the project, which is "/Repo/" but set the root directory of the cradle
420-
responsible to load "/Repo/SubRepo/Lib2.hs" to "/Repo/SubRepo", since
436+
When we try to load "\/Repo\/SubRepo\/Lib2.hs", we need to identify root
437+
of the project, which is "\/Repo\/" but set the root directory of the cradle
438+
responsible to load "\/Repo\/SubRepo\/Lib2.hs" to "\/Repo\/SubRepo", since
421439
the compiler options obtained from Cabal-Helper are relative to the package
422-
source directory, which is "/Repo/SubRepo".
440+
source directory, which is "\/Repo\/SubRepo".
423441
424442
-}
425443
cabalHelperCradle :: FilePath -> IO Cradle
@@ -492,60 +510,60 @@ cabalHelperCradle file = do
492510
fp
493511
}
494512
}
495-
where
496513

497-
-- | Fix occurrences of "-i." to "-i<cradle-root-dir>"
498-
-- Flags obtained from cabal-helper are relative to the package
499-
-- source directory. This is less resilient to using absolute paths,
500-
-- thus, we fix it here.
501-
fixImportDirs :: FilePath -> String -> String
502-
fixImportDirs base_dir arg =
503-
if "-i" `isPrefixOf` arg
504-
then let dir = drop 2 arg
505-
-- the flag "-i" has special meaning.
506-
in if not (null dir) && isRelative dir then ("-i" ++ base_dir </> dir)
507-
else arg
508-
else arg
509-
510-
-- | Cradle Action to query for the ComponentOptions that are needed
511-
-- to load the given FilePath.
512-
-- This Function is not supposed to throw any exceptions and use
513-
-- 'CradleLoadResult' to indicate errors.
514-
cabalHelperAction :: Ex ProjLoc -- ^ Project location, can be used
515-
-- to present error build-tool
516-
-- agnostic error messages.
517-
-> QueryEnv v -- ^ Query Env created by 'mkQueryEnv'
518-
-- with the appropriate 'distdir'
519-
-> Package v -- ^ Package this cradle is part for.
520-
-> FilePath -- ^ Root directory of the cradle
521-
-- this action belongs to.
522-
-> FilePath -- ^ FilePath to load, expected to be an absolute path.
523-
-> IO (CradleLoadResult ComponentOptions)
524-
cabalHelperAction proj env package root fp = do
525-
-- Get all unit infos the given FilePath may belong to
526-
let units = pUnits package
527-
-- make the FilePath to load relative to the root of the cradle.
528-
let relativeFp = makeRelative root fp
529-
debugm $ "Relative Module FilePath: " ++ relativeFp
530-
getComponent proj env (toList units) relativeFp
531-
>>= \case
532-
Right comp -> do
533-
let fs' = getFlags comp
534-
let fs = map (fixImportDirs root) fs'
535-
let targets = getTargets comp relativeFp
536-
let ghcOptions = fs ++ targets
537-
debugm $ "Flags for \"" ++ fp ++ "\": " ++ show ghcOptions
538-
debugm $ "Component Infos: " ++ show comp
539-
return
540-
$ CradleSuccess
541-
ComponentOptions { componentOptions = ghcOptions
542-
, componentDependencies = []
543-
}
544-
Left err -> return
545-
$ CradleFail
546-
$ CradleError
547-
(ExitFailure 2)
548-
err
514+
-- | Cradle Action to query for the ComponentOptions that are needed
515+
-- to load the given FilePath.
516+
-- This Function is not supposed to throw any exceptions and use
517+
-- 'CradleLoadResult' to indicate errors.
518+
cabalHelperAction :: Ex ProjLoc -- ^ Project location, can be used
519+
-- to present build-tool
520+
-- agnostic error messages.
521+
-> QueryEnv v -- ^ Query Env created by 'mkQueryEnv'
522+
-- with the appropriate 'distdir'
523+
-> Package v -- ^ Package this cradle is part for.
524+
-> FilePath -- ^ Root directory of the cradle
525+
-- this action belongs to.
526+
-> FilePath -- ^ FilePath to load, expected to be an absolute path.
527+
-> IO (CradleLoadResult ComponentOptions)
528+
cabalHelperAction proj env package root fp = do
529+
-- Get all unit infos the given FilePath may belong to
530+
let units = pUnits package
531+
-- make the FilePath to load relative to the root of the cradle.
532+
let relativeFp = makeRelative root fp
533+
debugm $ "Relative Module FilePath: " ++ relativeFp
534+
getComponent proj env (toList units) relativeFp
535+
>>= \case
536+
Right comp -> do
537+
let fs' = getFlags comp
538+
let fs = map (fixImportDirs root) fs'
539+
let targets = getTargets comp relativeFp
540+
let ghcOptions = fs ++ targets
541+
debugm $ "Flags for \"" ++ fp ++ "\": " ++ show ghcOptions
542+
debugm $ "Component Infos: " ++ show comp
543+
return
544+
$ CradleSuccess
545+
ComponentOptions { componentOptions = ghcOptions
546+
, componentDependencies = []
547+
}
548+
Left err -> return
549+
$ CradleFail
550+
$ CradleError
551+
(ExitFailure 2)
552+
err
553+
554+
-- | Fix occurrences of "-i." to "-i<cradle-root-dir>"
555+
-- Flags obtained from cabal-helper are relative to the package
556+
-- source directory. This is less resilient to using absolute paths,
557+
-- thus, we fix it here.
558+
fixImportDirs :: FilePath -> String -> String
559+
fixImportDirs base_dir arg =
560+
if "-i" `isPrefixOf` arg
561+
then let dir = drop 2 arg
562+
-- the flag "-i" has special meaning.
563+
in if not (null dir) && isRelative dir then ("-i" ++ base_dir </> dir)
564+
else arg
565+
else arg
566+
549567

550568
-- | Get the component the given FilePath most likely belongs to.
551569
-- Lazily ask units whether the given FilePath is part of one of their
@@ -826,8 +844,8 @@ ancestors dir
826844
where
827845
subdir = takeDirectory dir
828846

829-
-- | Assuming a FilePath "src/Lib/Lib.hs" and a list of directories
830-
-- such as ["src", "app"], returns either the given FilePath
847+
-- | Assuming a FilePath @"src\/Lib\/Lib.hs"@ and a list of directories
848+
-- such as @["src", "app"]@, returns either the given FilePath
831849
-- with a matching directory stripped away.
832850
-- If there are multiple matches, e.g. multiple directories are a prefix
833851
-- of the given FilePath, return the first match in the list.

0 commit comments

Comments
 (0)