feat: server: support Lake

This commit is contained in:
Sebastian Ullrich 2021-10-06 19:34:32 +02:00 committed by Leonardo de Moura
parent 89f9045646
commit 765ed37409
3 changed files with 26 additions and 22 deletions

View file

@ -185,15 +185,15 @@ in rec {
srcRoot = fullSrc; # use root flake.nix in case of Lean repo
inherit bash nix srcTarget srcArgs;
};
leanpkg-dev = substituteAll {
name = "leanpkg";
lake-dev = substituteAll {
name = "lake";
dir = "bin";
src = ./leanpkg-dev.in;
src = ./lake-dev.in;
isExecutable = true;
srcRoot = fullSrc; # use root flake.nix in case of Lean repo
inherit bash nix srcTarget srcArgs;
};
lean-dev = symlinkJoin { name = "lean-dev"; paths = [ lean-bin-dev leanpkg-dev ]; };
lean-dev = symlinkJoin { name = "lean-dev"; paths = [ lean-bin-dev lake-dev ]; };
emacs-dev = makeEmacsWrapper "emacs-dev" lean-dev;
vscode-dev = makeVSCodeWrapper "vscode-dev" lean-dev;
})

View file

@ -2,7 +2,7 @@
set -euo pipefail
[[ $# -gt 0 && "$1" == print-paths ]] || { echo 'This is just a simple Nix adapter for `leanpkg print-paths`. Please use the `lean-all` attribute for the real thing.'; exit 1; }
[[ $# -gt 0 && "$1" == print-paths ]] || { echo 'This is just a simple Nix adapter for `lake print-paths`. Please use the `lean-all` attribute for the real thing.'; exit 1; }
shift
deps="$@"
root=.

View file

@ -117,31 +117,31 @@ abbrev WorkerM := ReaderT WorkerContext <| StateRefT WorkerState IO
/- Worker initialization sequence. -/
section Initialization
/-- Use `leanpkg print-paths` to compile dependencies on the fly and add them to `LEAN_PATH`.
/-- Use `lake print-paths` to compile dependencies on the fly and add them to `LEAN_PATH`.
Compilation progress is reported to `hOut` via LSP notifications. Return the search path for
source files. -/
partial def leanpkgSetupSearchPath (leanpkgPath : System.FilePath) (m : DocumentMeta) (imports : Array Import) (hOut : FS.Stream) : IO SearchPath := do
let leanpkgProc ← Process.spawn {
partial def lakeSetupSearchPath (lakePath : System.FilePath) (m : DocumentMeta) (imports : Array Import) (hOut : FS.Stream) : IO SearchPath := do
let lakeProc ← Process.spawn {
stdin := Process.Stdio.null
stdout := Process.Stdio.piped
stderr := Process.Stdio.piped
cmd := leanpkgPath.toString
cmd := lakePath.toString
args := #["print-paths"] ++ imports.map (toString ·.module)
}
-- progress notification: report latest stderr line
let rec processStderr (acc : String) : IO String := do
let line ← leanpkgProc.stderr.getLine
let line ← lakeProc.stderr.getLine
if line == "" then
return acc
else
publishDiagnostics m #[{ range := ⟨⟨0, 0⟩, ⟨0, 0⟩⟩, severity? := DiagnosticSeverity.information, message := line }] hOut
processStderr (acc ++ line)
let stderr ← IO.asTask (processStderr "") Task.Priority.dedicated
let stdout := String.trim (← leanpkgProc.stdout.readToEnd)
let stdout := String.trim (← lakeProc.stdout.readToEnd)
let stderr ← IO.ofExcept stderr.get
if (← leanpkgProc.wait) == 0 then
if (← lakeProc.wait) == 0 then
if stdout.isEmpty then
pure [] -- e.g. no leanpkg.toml
pure [] -- e.g. no lakefile.lean
else
-- ignore any output up to the last line
-- TODO: leanpkg should instead redirect nested stdout output to stderr
@ -155,25 +155,29 @@ section Initialization
searchPathRef.set sp
paths.srcPath.mapM realPathNormalized
else
throwServerError s!"`leanpkg print-paths` failed:\n{stdout}\nstderr:\n{stderr}"
throwServerError s!"`{lakePath} print-paths` failed:\n{stdout}\nstderr:\n{stderr}"
def compileHeader (m : DocumentMeta) (hOut : FS.Stream) (opts : Options) : IO (Snapshot × SearchPath) := do
let inputCtx := Parser.mkInputContext m.text.source "<input>"
let (headerStx, headerParserState, msgLog) ← Parser.parseHeader inputCtx
let leanpkgPath ← match (← IO.getEnv "LEAN_SYSROOT") with
| some path => pure <| System.FilePath.mk path / "bin" / "leanpkg"
| _ => pure <| (← appDir) / "leanpkg"
let leanpkgPath := leanpkgPath.withExtension System.FilePath.exeExtension
let lakePath :=
-- backward compatibility, kill when `leanpkg` is removed
if (← System.FilePath.pathExists "leanpkg.toml") && !(← System.FilePath.pathExists "lakefile.lean") then "leanpkg"
else "lake"
let lakePath ← match (← IO.getEnv "LEAN_SYSROOT") with
| some path => pure <| System.FilePath.mk path / "bin" / lakePath
| _ => pure <| (← appDir) / lakePath
let lakePath := lakePath.withExtension System.FilePath.exeExtension
let mut srcSearchPath := [(← appDir) / ".." / "lib" / "lean" / "src"]
if let some p := (← IO.getEnv "LEAN_SRC_PATH") then
srcSearchPath := srcSearchPath ++ System.SearchPath.parse p
let (headerEnv, msgLog) ← try
-- NOTE: leanpkg does not exist in stage 0 (yet?)
if (← System.FilePath.pathExists leanpkgPath) then
let pkgSearchPath ← leanpkgSetupSearchPath leanpkgPath m (Lean.Elab.headerToImports headerStx).toArray hOut
-- NOTE: lake does not exist in stage 0 (yet?)
if (← System.FilePath.pathExists lakePath) then
let pkgSearchPath ← lakeSetupSearchPath lakePath m (Lean.Elab.headerToImports headerStx).toArray hOut
srcSearchPath := srcSearchPath ++ pkgSearchPath
Elab.processHeader headerStx opts msgLog inputCtx
catch e => -- should be from `leanpkg print-paths`
catch e => -- should be from `lake print-paths`
let msgs := MessageLog.empty.add { fileName := "<ignored>", pos := ⟨0, 0⟩, data := e.toString }
pure (← mkEmptyEnvironment, msgs)
let cmdState := Elab.Command.mkState headerEnv msgLog opts