Skip to content

Commit b5364a4

Browse files
committed
chore(mk_all): infer module style from existing aggregator file (#38395)
This PR makes `lake exe mk_all` infer whether each aggregator file should use module syntax (`module` header and `public import` lines) by parsing the existing file's header with `Lean.parseImports'`. Previously the choice came from a hardcoded `d.startsWith "Mathlib"` rule plus a `--module` flag, which meant downstream projects (e.g. FLT) that had modulized their aggregator file would have it silently reverted by `mk_all` (see [Zulip discussion](https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/module.20system.20questions/near/588595297)). The `--module` flag is still honored: when passed, it forces module style. Otherwise the style is inferred from the existing file, or defaults to plain for new files. One behavior change worth noting: creating a *new* `Mathlib/Foo` aggregator (e.g. via `lake exe mk_all --lib Mathlib/Foo` for a fresh subfolder) no longer auto-modulizes — pass `--module` once on first creation. 🤖 Prepared with Claude Code
1 parent 37b1af3 commit b5364a4

1 file changed

Lines changed: 26 additions & 7 deletions

File tree

scripts/mk_all.lean

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ def mkAllCLI (args : Parsed) : IO UInt32 := do
4444
let git := (args.flag? "git").isSome
4545
-- Check whether we only verify the files, or update them in-place.
4646
let check := (args.flag? "check").isSome
47-
let useModule := (args.flag? "module").isSome
47+
-- If `--module` is passed, force module style; otherwise infer from the existing
48+
-- aggregator file (when present), or default to plain.
49+
let moduleFlag := (args.flag? "module").isSome
4850
-- Check whether the `--lib` flag was set. If so, build the file corresponding to the library
4951
-- passed to `--lib`. Else build all the libraries of the package.
5052
-- If the package is `mathlib`, then it removes the libraries `Cache` and `MathlibTest` and it
@@ -54,8 +56,23 @@ def mkAllCLI (args : Parsed) : IO UInt32 := do
5456
| none => getLeanLibs
5557
let mut updates := 0
5658
for d in libs.reverse do -- reverse to create `Mathlib/Tactic.lean` before `Mathlib.lean`
57-
let useModule := useModule || d.startsWith "Mathlib"
5859
let fileName := addExtension d "lean"
60+
let fileExists ← pathExists fileName
61+
let existingContent ← if fileExists then IO.FS.readFile fileName else pure ""
62+
-- If `--module` was passed explicitly, honor it. Otherwise, if the aggregator file already
63+
-- exists, infer whether it uses the module system; if not, default to plain.
64+
let useModule ← if moduleFlag then pure true
65+
else if fileExists then
66+
try
67+
let header ← Lean.parseImports' existingContent fileName.toString
68+
pure header.isModule
69+
catch e =>
70+
throw <| IO.userError s!"\
71+
Could not parse the header of '{fileName}' to determine whether it should be a \
72+
module file: {e.toString}\n\
73+
Fix or delete the file, then re-run `mk_all` (with `--module` if you want a \
74+
module-style aggregator)."
75+
else pure false
5976
let mut allFiles ← getAllModulesSorted git d
6077
-- mathlib exception: manually import Std and Batteries in `Mathlib.lean`
6178
if d == "Mathlib" then
@@ -64,18 +81,17 @@ def mkAllCLI (args : Parsed) : IO UInt32 := do
6481
("\n".intercalate (allFiles.map ((if useModule then "public " else "") ++ "import " ++ ·)).toList) ++
6582
(if d == "Mathlib" then "\n\nset_option linter.style.longLine false" else "") ++
6683
"\n"
67-
if !(← pathExists fileName) then
84+
if !fileExists then
6885
if check then
6986
IO.println s!"File '{fileName}' does not exist"
7087
else
7188
IO.println s!"Creating '{fileName}'"
7289
IO.FS.writeFile fileName fileContent
7390
updates := updates + 1
74-
else if (← IO.FS.readFile fileName) != fileContent then
91+
else if existingContent != fileContent then
7592
if check then
7693
IO.println s!"The file '{fileName}' is out of date: \
77-
run `lake exe mk_all{if git then " --git" else ""}{if useModule then " --module" else ""}` \
78-
to update it"
94+
run `lake exe mk_all{if git then " --git" else ""}` to update it"
7995
else
8096
IO.println s!"Updating '{fileName}'"
8197
IO.FS.writeFile fileName fileContent
@@ -100,7 +116,10 @@ def mkAll : Cmd := `[Cli|
100116
lib : String; "Create a folder importing all Lean files from the specified library/subfolder."
101117
git; "Use the folder content information from git."
102118
check; "Only check if the files are up-to-date; print an error if not"
103-
module; "Generate `module` files with `public` imports."
119+
module; "Force the aggregator file to be generated as a `module` with `public` imports. \
120+
When this flag is omitted, the style is inferred from the existing file by \
121+
parsing its header with `Lean.parseImports'`, or defaults to plain for new \
122+
files."
104123
]
105124

106125
/-- The entrypoint to the `lake exe mk_all` command. -/

0 commit comments

Comments
 (0)