Skip to content

Commit a90729a

Browse files
committed
fix(Shake): update for changes to header grammar (#25054)
fixes #24743 ... again Co-authored-by: Mario Carneiro <di.gama@gmail.com>
1 parent 2193fd8 commit a90729a

File tree

1 file changed

+39
-23
lines changed

1 file changed

+39
-23
lines changed

Shake/Main.lean

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ Copyright (c) 2023 Mario Carneiro. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Mario Carneiro
55
-/
6-
import Lake.Util.Error
7-
import Lean.Environment
8-
import Lean.Parser.Module
9-
import Lean.Util.FoldConsts
10-
import Lean.Util.Paths
116
import Lake.CLI.Main
127

138
/-! # `lake exe shake` command
@@ -221,24 +216,38 @@ def Edits.add (ed : Edits) (src : Name) (tgt : Nat) : Edits :=
221216

222217
/-- Parse a source file to extract the location of the import lines, for edits and error messages.
223218
224-
Returns `(path, inputCtx, headerStx, endPos)` where `headerStx` is the `Lean.Parser.Module.header`
219+
Returns `(path, inputCtx, imports, endPos)` where `imports` is the `Lean.Parser.Module.import` list
225220
and `endPos` is the position of the end of the header.
226221
-/
227-
def parseHeader (srcSearchPath : SearchPath) (mod : Name) :
228-
IO (System.FilePath × Parser.InputContext × TSyntax ``Parser.Module.header × String.Pos) := do
229-
-- Parse the input file
230-
let some path ← srcSearchPath.findModuleWithExt "lean" mod
231-
| throw <| .userError "error: failed to find source file for {mod}"
232-
let text ← IO.FS.readFile path
233-
let inputCtx := Parser.mkInputContext text path.toString
222+
def parseHeaderFromString (text path : String) :
223+
IO (System.FilePath × Parser.InputContext ×
224+
TSyntaxArray ``Parser.Module.import × String.Pos) := do
225+
let inputCtx := Parser.mkInputContext text path
234226
let (header, parserState, msgs) ← Parser.parseHeader inputCtx
235227
if !msgs.toList.isEmpty then -- skip this file if there are parse errors
236228
msgs.forM fun msg => msg.toString >>= IO.println
237229
throw <| .userError "parse errors in file"
238230
-- the insertion point for `add` is the first newline after the imports
239231
let insertion := header.raw.getTailPos?.getD parserState.pos
240232
let insertion := text.findAux (· == '\n') text.endPos insertion + ⟨1
241-
pure (path, inputCtx, header, insertion)
233+
pure (path, inputCtx, .mk header.raw[2].getArgs, insertion)
234+
235+
/-- Parse a source file to extract the location of the import lines, for edits and error messages.
236+
237+
Returns `(path, inputCtx, imports, endPos)` where `imports` is the `Lean.Parser.Module.import` list
238+
and `endPos` is the position of the end of the header.
239+
-/
240+
def parseHeader (srcSearchPath : SearchPath) (mod : Name) :
241+
IO (System.FilePath × Parser.InputContext ×
242+
TSyntaxArray ``Parser.Module.import × String.Pos) := do
243+
-- Parse the input file
244+
let some path ← srcSearchPath.findModuleWithExt "lean" mod
245+
| throw <| .userError "error: failed to find source file for {mod}"
246+
let text ← IO.FS.readFile path
247+
parseHeaderFromString text path.toString
248+
249+
/-- Gets the name `Foo` in `import Foo`. -/
250+
def importId (stx : TSyntax ``Parser.Module.import) : Name := stx.raw[3].getId
242251

243252
/-- Analyze and report issues from module `i`. Arguments:
244253
@@ -291,10 +300,10 @@ def visitModule (s : State) (srcSearchPath : SearchPath) (ignoreImps : Bitset)
291300
edits.remove s.modNames[i]! s.modNames[n]!
292301
if githubStyle then
293302
try
294-
let (path, inputCtx, header, endHeader) ← parseHeader srcSearchPath s.modNames[i]!
295-
for stx in header.raw[2].getArgs do
296-
if toRemove.any fun i => s.modNames[i]! == stx[2].getId then
297-
let pos := inputCtx.fileMap.toPosition stx.getPos?.get!
303+
let (path, inputCtx, imports, endHeader) ← parseHeader srcSearchPath s.modNames[i]!
304+
for stx in imports do
305+
if toRemove.any fun i => s.modNames[i]! == importId stx then
306+
let pos := inputCtx.fileMap.toPosition stx.raw.getPos?.get!
298307
println! "{path}:{pos.line}:{pos.column+1}: warning: unused import \
299308
(use `lake exe shake --fix` to fix this, or `lake exe shake --update` to ignore)"
300309
if !toAdd.isEmpty then
@@ -595,7 +604,7 @@ def main (args : List String) : IO UInt32 := do
595604
out.qsort Name.lt
596605

597606
-- Parse the input file
598-
let (path, inputCtx, header, insertion) ←
607+
let (path, inputCtx, imports, insertion) ←
599608
try parseHeader srcSearchPath mod
600609
catch e => println! e.toString; return count
601610
let text := inputCtx.input
@@ -604,12 +613,12 @@ def main (args : List String) : IO UInt32 := do
604613
let mut pos : String.Pos := 0
605614
let mut out : String := ""
606615
let mut seen : NameSet := {}
607-
for stx in header.raw[2].getArgs do
608-
let mod := stx[2].getId
616+
for stx in imports do
617+
let mod := importId stx
609618
if remove.contains mod || seen.contains mod then
610-
out := out ++ text.extract pos stx.getPos?.get!
619+
out := out ++ text.extract pos stx.raw.getPos?.get!
611620
-- We use the end position of the syntax, but include whitespace up to the first newline
612-
pos := text.findAux (· == '\n') text.endPos stx.getTailPos?.get! + ⟨1
621+
pos := text.findAux (· == '\n') text.endPos stx.raw.getTailPos?.get! + ⟨1
613622
seen := seen.insert mod
614623
out := out ++ text.extract pos insertion
615624
for mod in add do
@@ -628,3 +637,10 @@ def main (args : List String) : IO UInt32 := do
628637
else
629638
println! "No edits required."
630639
return 0
640+
641+
-- self-test so that future grammar changes cause a build failure
642+
/-- info: #[`Lake.CLI.Main] -/
643+
#guard_msgs (whitespace := lax) in
644+
#eval show MetaM _ from do
645+
let (_, _, imports, _) ← parseHeaderFromString (← getFileMap).source (← getFileName)
646+
return imports.map importId

0 commit comments

Comments
 (0)