Skip to content

Commit 0b415ae

Browse files
Add parallel parsing
The GHC API is no longer used to discover modules. Because of that, modules can be parsed in parallel.
1 parent d3df7aa commit 0b415ae

File tree

15 files changed

+352
-313
lines changed

15 files changed

+352
-313
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,7 @@ jobs:
7171
- "9.2.8"
7272
- "9.0.2"
7373
- "8.10.7"
74-
- "8.8.4"
75-
- "8.6.5"
76-
- "8.4.4"
7774
exclude:
78-
# Windows gets stuck while running the testsuite, but this is not a
79-
# doctest-parallel failure
80-
- os: windows-latest
81-
ghc: 8.8.4
82-
83-
# GHCUp fails to install newer GHCs on macOS
84-
- os: macOS-latest
85-
ghc: "8.8.4"
86-
- os: macOS-latest
87-
ghc: "8.6.5"
88-
- os: macOS-latest
89-
ghc: "8.4.4"
90-
9175
# Newer macOSs don't have the right LLVM to compile our dependencies
9276
- os: macOS-latest
9377
ghc: "9.0.2"

CHANGES.markdown

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# 0.4
22
* Account for `default-language` sections in Cabal files ([#85](https://github.com/martijnbastiaan/doctest-parallel/issues/85))
33
* Add support for Cabal 3.14 ([#88](https://github.com/martijnbastiaan/doctest-parallel/pull/88))
4+
* Add parallel parsing on Linux/macOS. The GHC API is now used to call the parser directly, which allows parallel parsing. On Windows, files will be parsed sequentially still due to the GHC API locking files. ([#85](https://github.com/martijnbastiaan/doctest-parallel/issues/89))
5+
* Drop support for GHC 8.4, 8.6, and 8.8
46

57
# 0.3.1.1
68
* Add support for GHC 9.12 (loosened bounds in Hackage revision)

doctest-parallel.cabal

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ author: Martijn Bastiaan <martijn@hmbastiaan.nl>
1717
maintainer: Martijn Bastiaan <martijn@hmbastiaan.nl>
1818
build-type: Simple
1919
tested-with:
20-
GHC == 8.4.4
21-
, GHC == 8.6.5
22-
, GHC == 8.8.4
23-
, GHC == 8.10.7
20+
GHC == 8.10.7
2421
, GHC == 9.0.2
2522
, GHC == 9.2.8
2623
, GHC == 9.4.7
@@ -105,6 +102,7 @@ library
105102
, exceptions
106103
, filepath
107104
, ghc >=8.2 && <9.13
105+
, ghc-exactprint
108106
, ghc-paths >=0.1.0.9
109107
, process
110108
, random >= 1.2

scripts/build_all.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
set -e
3+
4+
GHCS=( "8.10.7" "9.0.2" "9.2.8" "9.4.8" "9.6.6" "9.8.1" "9.10.1" )
5+
6+
cabal update
7+
8+
for GHC in "${GHCS[@]}"
9+
do
10+
echo "> cabal build all --with-compiler=ghc-$GHC --only-dependencies"
11+
cabal build all --with-compiler=ghc-$GHC --only-dependencies
12+
done
13+
14+
for GHC in "${GHCS[@]}"
15+
do
16+
echo "> cabal build all --with-compiler=ghc-$GHC"
17+
cabal build all --with-compiler=ghc-$GHC
18+
done

src/Data/List/Extra.hs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module Data.List.Extra (trim) where
1+
module Data.List.Extra (trim, splitOn) where
22

33
import Data.Char (isSpace)
44
import Data.List (dropWhileEnd)
@@ -19,3 +19,21 @@ trimStart = dropWhile isSpace
1919
-- | Remove spaces from the end of a string, see 'trim'.
2020
trimEnd :: String -> String
2121
trimEnd = dropWhileEnd isSpace
22+
23+
-- TODO: Use doctests after fixing: https://github.com/martijnbastiaan/doctest-parallel/issues/87
24+
25+
-- | Break a list into pieces separated by the first argument, consuming the delimiter.
26+
--
27+
-- > splitOn '.' "A.B"
28+
-- ["A","B"]
29+
-- > splitOn '.' "A.B.C"
30+
-- ["A","B","C"]
31+
-- > splitOn '.' "."
32+
-- ["",""]
33+
-- > splitOn '.' ""
34+
-- [""]
35+
splitOn :: Eq a => a -> [a] -> [[a]]
36+
splitOn needle haystack =
37+
case break (== needle) haystack of
38+
(chunk, []) -> [chunk]
39+
(chunk, _ : rest) -> chunk : splitOn needle rest

src/Test/DocTest.hs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import Panic
3737
import GHC.Utils.Panic
3838
#endif
3939

40-
import Test.DocTest.Internal.Parse
4140
import Test.DocTest.Internal.Options
4241
import Test.DocTest.Internal.Runner
4342
import Test.DocTest.Internal.Nix (getNixGhciArgs)
@@ -110,17 +109,17 @@ isSuccess s = sErrors s == 0 && sFailures s == 0
110109
-- | Filter modules to be tested against a list of modules to be tested (specified
111110
-- by the user on the command line). If list is empty, test all modules. Throws
112111
-- and error if a non-existing module was specified.
113-
filterModules :: [ModuleName] -> [Module a] -> [Module a]
112+
filterModules :: [ModuleName] -> [ModuleName] -> [ModuleName]
114113
filterModules [] mods = mods
115114
filterModules wantedMods0 allMods0
116115
| (_:_) <- nonExistingMods = error ("Unknown modules specified: " <> show nonExistingMods)
117116
| otherwise = filter isSpecifiedMod allMods0
118117
where
119118
wantedMods1 = Set.fromList wantedMods0
120-
allMods1 = Set.fromList (map moduleName allMods0)
119+
allMods1 = Set.fromList allMods0
121120

122121
nonExistingMods = Set.toList (wantedMods1 `Set.difference` allMods1)
123-
isSpecifiedMod Module{moduleName} = moduleName `Set.member` wantedMods1
122+
isSpecifiedMod nm = nm `Set.member` wantedMods1
124123

125124
setSeed :: (?verbosity :: LogLevel) => ModuleConfig -> IO ModuleConfig
126125
setSeed cfg@ModuleConfig{cfgRandomizeOrder=True, cfgSeed=Nothing} = do
@@ -137,24 +136,19 @@ run lib Config{..} = do
137136

138137
let
139138
implicitPrelude = DisableExtension ImplicitPrelude `notElem` libDefaultExtensions lib
140-
(includeArgs, moduleArgs, otherGhciArgs) = libraryToGhciArgs lib
139+
(includeArgs, allModules, otherGhciArgs) = libraryToGhciArgs lib
141140
evalGhciArgs = otherGhciArgs ++ ["-XNoImplicitPrelude"] ++ nixGhciArgs
142-
parseGhcArgs = includeArgs ++ moduleArgs ++ otherGhciArgs ++ nixGhciArgs ++ cfgGhcArgs
141+
parseGhcArgs = includeArgs ++ otherGhciArgs ++ nixGhciArgs ++ cfgGhcArgs
143142

144143
let
145144
?verbosity = cfgLogLevel
146145

147146
modConfig <- setSeed cfgModuleConfig
148147

149-
-- Get examples from Haddock comments
150-
Logging.log Verbose "Parsing comments.."
151-
Logging.log Debug ("Calling GHC API with: " <> unwords parseGhcArgs)
152-
allModules <- getDocTests parseGhcArgs
153-
154148
-- Run tests
155149
Logging.log Verbose "Running examples.."
156150
let
157151
filteredModules = filterModules cfgModules allModules
158-
filteredModulesMsg = intercalate ", " (map moduleName filteredModules)
152+
filteredModulesMsg = intercalate ", " filteredModules
159153
Logging.log Debug ("Running examples in modules: " <> filteredModulesMsg)
160-
runModules modConfig cfgThreads implicitPrelude evalGhciArgs filteredModules
154+
runModules modConfig cfgThreads implicitPrelude parseGhcArgs evalGhciArgs filteredModules

src/Test/DocTest/Helpers.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import Distribution.PackageDescription
3131
( GenericPackageDescription (condLibrary)
3232
, exposedModules, libBuildInfo, hsSourceDirs, defaultExtensions, package
3333
, packageDescription, condSubLibraries, includeDirs, autogenModules, ConfVar(..)
34-
, defaultLanguage )
34+
, defaultLanguage, BuildInfo (otherModules) )
3535

3636
import Distribution.Compiler (CompilerFlavor(GHC))
3737
import Distribution.Pretty (prettyShow)
@@ -256,11 +256,12 @@ extractSpecificCabalLibrary maybeLibName pkgPath = do
256256
$ map compatPrettyShow
257257
#endif
258258
cSourceDirs
259-
, libModules = exposedModules lib `rmList` autogenModules buildInfo
259+
, libModules = modules `rmList` autogenModules buildInfo
260260
, libDefaultExtensions = defaultExtensions buildInfo
261261
, libDefaultLanguages = maybeToList (defaultLanguage buildInfo)
262262
}
263263
where
264+
modules = otherModules buildInfo <> exposedModules lib
264265
buildInfo = libBuildInfo lib
265266
sourceDirs = hsSourceDirs buildInfo
266267
cSourceDirs = includeDirs buildInfo

0 commit comments

Comments
 (0)