Skip to content

Commit d5db431

Browse files
committed
Extract module names from sources
1 parent 7593b01 commit d5db431

File tree

10 files changed

+1797
-447
lines changed

10 files changed

+1797
-447
lines changed

package-lock.json

Lines changed: 1684 additions & 389 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,47 +7,49 @@
77
"test": "test"
88
},
99
"bin": {
10-
"purescript-docs-search": "dist/purescript-docs-search"
10+
"purescript-docs-search": "dist/purescript-docs-search.cjs"
1111
},
1212
"files": [
13-
"dist/purescript-docs-search",
13+
"dist/purescript-docs-search.cjs",
1414
"dist/docs-search-app.js",
1515
"README.md",
1616
"CHANGELOG.md"
1717
],
1818
"scripts": {
19-
"test": "spago docs --no-search && ./dist/purescript-docs-search build-index && spago test && npm run check-version",
19+
"test": "spago docs --no-search && ./dist/purescript-docs-search.cjs build-index && spago test && npm run check-version",
2020
"bundle-app": "spago bundle-app --no-build --no-install -m Docs.Search.App --to dist/docs-search-app.js",
2121
"esbuild-app": "esbuild dist/docs-search-app.js --target=es2016 --bundle --minify --outfile=dist/docs-search-app.min.js && mv dist/docs-search-app.min.js dist/docs-search-app.js",
2222
"build-app": "npm run bundle-app && npm run esbuild-app",
2323
"bundle-main": "spago bundle-app --no-build --no-install --platform node -m Docs.Search.Main --to dist/main.js",
2424
"esbuild-main": "esbuild dist/main.js --platform=node --bundle --minify --outfile=dist/main.min.js && mv dist/main.min.js dist/main.js",
25-
"add-shebang": "echo \"#!/usr/bin/env node\" > dist/purescript-docs-search && cat dist/main.js >> dist/purescript-docs-search",
26-
"chmod-main": "chmod +x dist/purescript-docs-search",
25+
"add-shebang": "echo \"#!/usr/bin/env node\" > dist/purescript-docs-search.cjs && cat dist/main.js >> dist/purescript-docs-search.cjs",
26+
"chmod-main": "chmod +x dist/purescript-docs-search.cjs",
2727
"build-main": "npm run bundle-main && npm run esbuild-main && npm run add-shebang && rm dist/main.js && npm run chmod-main",
2828
"build": "spago build && npm run build-app && npm run build-main",
2929
"clean": "rm -rf dist",
30-
"check-version": "[ \"$(./dist/purescript-docs-search version)\" = \"$npm_package_version\" ]"
30+
"check-version": "[ \"$(./dist/purescript-docs-search.cjs version)\" = \"$npm_package_version\" ]"
3131
},
3232
"repository": {
3333
"type": "git",
34-
"url": "git+https://github.com/spacchetti/purescript-docs-search.git"
34+
"url": "git+https://github.com/purescript/purescript-docs-search.git"
3535
},
3636
"keywords": [
3737
"purescript"
3838
],
3939
"author": "Kalnitsky Vladimir <klntsky@gmail.com>",
4040
"license": "BSD-3-Clause",
4141
"bugs": {
42-
"url": "https://github.com/spacchetti/purescript-docs-search/issues"
42+
"url": "https://github.com/purescript/purescript-docs-search/issues"
43+
},
44+
"homepage": "https://github.com/purescript/purescript-docs-search#readme",
45+
"dependencies": {
46+
"punycode": "^2.1.1"
4347
},
44-
"homepage": "https://github.com/spacchetti/purescript-docs-search#readme",
45-
"dependencies": {},
4648
"devDependencies": {
4749
"esbuild": "^0.11.10",
4850
"glob": "^7.1.6",
4951
"markdown-it": "^12.0.4",
5052
"puppeteer": "^8.0.0",
51-
"spago": "^0.20.0"
53+
"spago": "^0.20.9"
5254
}
5355
}

spago.dhall

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
, "node-readline"
3434
, "optparse"
3535
, "ordered-collections"
36+
, "parallel"
3637
, "partial"
3738
, "prelude"
3839
, "profunctor"

src/Docs/Search/IndexBuilder.purs

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ import Docs.Search.Config as Config
55
import Docs.Search.Declarations (Declarations(..), mkDeclarations)
66
import Docs.Search.DocsJson (DocsJson)
77
import Docs.Search.Extra ((>#>))
8+
import Docs.Search.Meta (Meta)
89
import Docs.Search.ModuleIndex (PackedModuleIndex, mkPackedModuleIndex)
10+
import Docs.Search.ModuleParser (parseModuleName)
911
import Docs.Search.PackageIndex (PackageInfo, mkPackageInfo)
1012
import Docs.Search.Score (mkScores)
1113
import Docs.Search.SearchResult (SearchResult)
1214
import Docs.Search.TypeIndex (TypeIndex, mkTypeIndex)
13-
import Docs.Search.Types (PackageName, PartId)
14-
import Docs.Search.Meta (Meta)
15+
import Docs.Search.Types (ModuleName, PackageName, PartId)
1516

1617
import Prelude
1718

@@ -20,6 +21,7 @@ import Data.Argonaut.Decode (decodeJson)
2021
import Data.Argonaut.Decode.Error (printJsonDecodeError)
2122
import Data.Argonaut.Encode (encodeJson)
2223
import Data.Argonaut.Parser (jsonParser)
24+
import Data.Array (concat)
2325
import Data.Array as Array
2426
import Data.Either (Either(..), either)
2527
import Data.Foldable (sum)
@@ -38,14 +40,15 @@ import Data.String.Common (replace) as String
3840
import Data.String.Pattern (Pattern(..), Replacement(..))
3941
import Data.Traversable (for, for_)
4042
import Data.Tuple (Tuple(..), fst)
43+
import Data.Tuple.Nested ((/\))
4144
import Effect (Effect)
4245
import Effect.Aff (Aff, launchAff_, parallel, sequential)
4346
import Effect.Class (liftEffect)
4447
import Effect.Console (log)
4548
import Node.Encoding (Encoding(UTF8))
4649
import Node.FS.Aff (mkdir, readFile, readTextFile, readdir, stat, writeFile, writeTextFile)
47-
import Node.FS.Sync (exists)
4850
import Node.FS.Stats (isDirectory, isFile)
51+
import Node.FS.Sync (exists)
4952
import Node.Process as Process
5053
import Web.Bower.PackageMeta (PackageMeta(..))
5154

@@ -56,6 +59,7 @@ type Config =
5659
, generatedDocs :: String
5760
, noPatch :: Boolean
5861
, packageName :: PackageName
62+
, sourceFiles :: Array String
5963
}
6064

6165

@@ -71,8 +75,11 @@ run' cfg = do
7175
liftEffect do
7276
log "Building the search index..."
7377

74-
docsJsons <- decodeDocsJsons cfg
75-
packageMetas <- decodeBowerJsons cfg
78+
docsJsons /\ moduleNames /\ packageMetas <- sequential $
79+
(\d h m -> d /\ h /\ m)
80+
<$> parallel (decodeDocsJsons cfg)
81+
<*> parallel (parseModuleHeaders cfg.sourceFiles)
82+
<*> parallel (decodeBowerJsons cfg)
7683

7784
let countOfPackages = Array.length packageMetas
7885
countOfModules = Array.length docsJsons
@@ -89,14 +96,14 @@ run' cfg = do
8996
index = mkDeclarations scores docsJsons
9097
typeIndex = mkTypeIndex scores docsJsons
9198
packageInfo = mkPackageInfo scores packageMetas
92-
moduleIndex = mkPackedModuleIndex index
99+
moduleIndex = mkPackedModuleIndex index moduleNames
93100
meta = { localPackageName: cfg.packageName }
94101

95102
createDirectories cfg
96103

97104
void $ sequential do
98105
ignore <$> parallel (writeIndex cfg index)
99-
<*> parallel (writeTypeIndex cfg typeIndex)
106+
<*> parallel (writeTypeIndex typeIndex)
100107
<*> parallel (writePackageInfo packageInfo)
101108
<*> parallel (writeModuleIndex moduleIndex)
102109
<*> parallel (writeMeta meta)
@@ -176,6 +183,24 @@ decodeDocsJsons cfg@{ docsFiles } = do
176183

177184
pure docsJsons
178185

186+
-- | This function accepts an array of globs pointing to project sources
187+
-- | and returns a list of module names extracted from these files.
188+
-- | Unfortunately, we can't get all module names from `docs.json`s, because
189+
-- | reexport-only modules do not have a single declaration in them, so we can't
190+
-- | count them normally in `mkPackedModuleIndex.extract`, where we only look at
191+
-- | exported declarations.
192+
parseModuleHeaders :: Array String -> Aff (Array ModuleName)
193+
parseModuleHeaders globs = do
194+
files <- getPathsByGlobs globs
195+
concat <$> for files \filePath -> do
196+
fileContents <- readTextFile UTF8 filePath
197+
case parseModuleName fileContents of
198+
Nothing -> do
199+
liftEffect $ log $
200+
"Module header decoding failed for " <> filePath <>
201+
", unable to extract module name"
202+
pure []
203+
Just res -> pure [res]
179204

180205
decodeBowerJsons
181206
:: forall rest
@@ -210,8 +235,8 @@ decodeBowerJsons { bowerFiles } = do
210235

211236

212237
-- | Write type index parts to files.
213-
writeTypeIndex :: Config -> TypeIndex -> Aff Unit
214-
writeTypeIndex { generatedDocs } typeIndex =
238+
writeTypeIndex :: TypeIndex -> Aff Unit
239+
writeTypeIndex typeIndex =
215240
for_ entries \(Tuple typeShape results) -> do
216241
writeTextFile UTF8 (unwrap Config.typeIndexDirectory <> "/" <> typeShape <> ".js")
217242
(mkHeader typeShape <> stringify (encodeJson results))
@@ -265,7 +290,7 @@ getIndex (Declarations trie) =
265290
Trie.query prefix trie
266291
else
267292
-- Entries with path lengths > 1 have been added already.
268-
List.filter (\(Tuple path value) -> List.length path == 1) (
293+
List.filter (\(Tuple path _value) -> List.length path == 1) (
269294
Trie.query prefix trie
270295
)
271296
in

src/Docs/Search/Interactive.purs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Docs.Search.DocsJson (DataDeclType(..))
66
import Docs.Search.Engine (mkEngineState, packageInfoToString, Result(..))
77
import Docs.Search.Engine as Engine
88
import Docs.Search.Extra (stringToList, (>#>))
9+
import Docs.Search.IndexBuilder (parseModuleHeaders)
910
import Docs.Search.IndexBuilder as IndexBuilder
1011
import Docs.Search.ModuleIndex (ModuleResult, mkPackedModuleIndex, unpackModuleIndex)
1112
import Docs.Search.NodeEngine (nodeEngine)
@@ -19,7 +20,8 @@ import Docs.Search.TypePrinter (keyword, showConstraint, showFunDeps, showType,
1920
import Docs.Search.Types (ModuleName, PackageName, PackageInfo, Identifier)
2021

2122
import Prelude
22-
import Prim hiding (Type, Constraint)
23+
24+
import Control.Parallel (parallel, sequential)
2325
import Data.Array as Array
2426
import Data.Identity (Identity(..))
2527
import Data.List as List
@@ -28,17 +30,20 @@ import Data.Newtype (un, unwrap, wrap)
2830
import Data.Search.Trie as Trie
2931
import Data.String (length) as String
3032
import Data.String.Common (split, toLower, trim) as String
33+
import Data.Tuple.Nested ((/\))
3134
import Effect (Effect)
3235
import Effect.Aff (launchAff_)
3336
import Effect.Class (liftEffect)
3437
import Effect.Console (log, clear) as Console
3538
import Node.ReadLine (createConsoleInterface, question)
39+
import Prim hiding (Type, Constraint)
3640

3741

3842
type Config =
3943
{ docsFiles :: Array String
4044
, bowerFiles :: Array String
4145
, packageName :: PackageName
46+
, sourceFiles :: Array String
4247
}
4348

4449

@@ -48,14 +53,17 @@ run cfg = launchAff_ $ do
4853
liftEffect do
4954
Console.log "Loading search index..."
5055

51-
docsJsons <- IndexBuilder.decodeDocsJsons cfg
52-
packageMetas <- IndexBuilder.decodeBowerJsons cfg
56+
docsJsons /\ moduleNames /\ packageMetas <- sequential $
57+
(\d h m -> d /\ h /\ m)
58+
<$> parallel (IndexBuilder.decodeDocsJsons cfg)
59+
<*> parallel (parseModuleHeaders cfg.sourceFiles)
60+
<*> parallel (IndexBuilder.decodeBowerJsons cfg)
5361

5462
let scores = mkScores packageMetas
5563
index = mkDeclarations scores docsJsons
5664
typeIndex = docsJsons >>= resultsWithTypes scores
5765
packageIndex = mkPackageIndex $ mkPackageInfo scores packageMetas
58-
moduleIndex = unpackModuleIndex $ mkPackedModuleIndex index
66+
moduleIndex = unpackModuleIndex $ mkPackedModuleIndex index moduleNames
5967
engineState = mkEngineState (unwrap index) typeIndex packageIndex moduleIndex scores
6068

6169
let countOfDefinitions = Trie.size $ unwrap index

src/Docs/Search/Main.purs

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ main = do
2828
let defaultCommands = Search { docsFiles: defaultDocsFiles
2929
, bowerFiles: defaultBowerFiles
3030
, packageName: Config.defaultPackageName
31+
, sourceFiles: defaultSourceFiles
3132
}
3233

3334
case fromMaybe defaultCommands args of
3435
BuildIndex cfg -> IndexBuilder.run cfg
3536
Search cfg -> Interactive.run cfg
3637
Version -> log Config.version
3738

38-
3939
getArgs :: Effect (Maybe Commands)
4040
getArgs = execParser opts
4141
where
@@ -45,19 +45,16 @@ getArgs = execParser opts
4545
<> progDesc "Search frontend for the documentation generated by the PureScript compiler."
4646
)
4747

48-
4948
data Commands
5049
= BuildIndex IndexBuilder.Config
5150
| Search Interactive.Config
5251
| Version
5352

54-
5553
derive instance genericCommands :: Generic Commands _
5654

5755
instance showCommands :: Show Commands where
5856
show = genericShow
5957

60-
6158
commands :: Parser (Maybe Commands)
6259
commands = optional $ subparser
6360
( command "build-index"
@@ -80,39 +77,29 @@ commands = optional $ subparser
8077

8178
buildIndex :: Parser Commands
8279
buildIndex = ado
83-
8480
docsFiles <- docsFilesOption
85-
8681
bowerFiles <- bowerFilesOption
87-
8882
packageName <- packageNameOption
89-
83+
sourceFiles <- sourceFilesOption
9084
generatedDocs <- strOption
9185
( long "generated-docs"
9286
<> metavar "DIR"
9387
<> value "./generated-docs/"
9488
)
95-
9689
noPatch <- flag false true
9790
( long "no-patch"
9891
<> help "Do not patch the HTML docs, only build indices"
9992
)
100-
101-
102-
in BuildIndex { docsFiles, bowerFiles, generatedDocs, noPatch, packageName }
93+
in BuildIndex { docsFiles, bowerFiles, generatedDocs, noPatch, packageName, sourceFiles }
10394

10495

10596
startInteractive :: Parser Commands
10697
startInteractive = ado
107-
10898
docsFiles <- docsFilesOption
109-
11099
bowerFiles <- bowerFilesOption
111-
112100
packageName <- packageNameOption
113-
114-
in Search { docsFiles, bowerFiles, packageName }
115-
101+
sourceFiles <- sourceFilesOption
102+
in Search { docsFiles, bowerFiles, packageName, sourceFiles }
116103

117104
docsFilesOption :: Parser (Array String)
118105
docsFilesOption = fromMaybe defaultDocsFiles <$>
@@ -125,7 +112,6 @@ docsFilesOption = fromMaybe defaultDocsFiles <$>
125112
)
126113
)
127114

128-
129115
bowerFilesOption :: Parser (Array String)
130116
bowerFilesOption = fromMaybe defaultBowerFiles <$>
131117
optional
@@ -137,7 +123,6 @@ bowerFilesOption = fromMaybe defaultBowerFiles <$>
137123
)
138124
)
139125

140-
141126
packageNameOption :: Parser PackageName
142127
packageNameOption =
143128
PackageName <$> strOption
@@ -146,18 +131,28 @@ packageNameOption =
146131
<> value (unwrap Config.defaultPackageName)
147132
)
148133

134+
sourceFilesOption :: Parser (Array String)
135+
sourceFilesOption = fromMaybe defaultSourceFiles <$>
136+
optional
137+
( some
138+
( strOption
139+
( long "source-files"
140+
<> metavar "GLOB"
141+
)
142+
)
143+
)
149144

150145
defaultDocsFiles :: Array String
151146
defaultDocsFiles = [ "output/**/docs.json" ]
152147

153-
154148
defaultBowerFiles :: Array String
155149
defaultBowerFiles = [ ".spago/*/*/bower.json", "bower_components/purescript-*/bower.json" ]
156150

151+
defaultSourceFiles :: Array String
152+
defaultSourceFiles = [ "src/**/*.purs" ]
157153

158154
many :: forall a f. Unfoldable f => Parser a -> Parser (f a)
159155
many x = CA.many x <#> List.toUnfoldable
160156

161-
162157
some :: forall a f. Unfoldable f => Parser a -> Parser (f a)
163158
some x = CA.some x <#> NonEmpty.toUnfoldable

0 commit comments

Comments
 (0)