From fcebe03576e213d2c0d1cc84da18df5512230710 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Fri, 11 Sep 2026 20:15:31 +0700 Subject: [PATCH] A file that is a package is still a package to the editor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit package_of matched the file being edited against a package's directory, which is right for every package that is one — and answers "not a package" for one that is a single file, because the file's directory is not the file. A form typed into sand.flan with the headless driver running would have spliced as a bare step, the evaluation would have said ok, and the program would have gone on calling the step it already had. That is the exact silent failure the function exists to prevent, so it now matches the file too. --- lib/session.ml | 14 ++++++++++---- test/test_session.ml | 13 +++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/session.ml b/lib/session.ml index ddfb794..540bd39 100644 --- a/lib/session.ml +++ b/lib/session.ml @@ -80,15 +80,21 @@ let package_of t origin = match origin with | "" -> None | origin -> - let dir = - try Filename.dirname (Unix.realpath origin) - with Unix.Unix_error _ -> Filename.dirname origin + let here = + try Unix.realpath origin with Unix.Unix_error _ -> origin in + let dir = Filename.dirname here in + (* A package is a directory, or a single .flan file named outright — so the + file being edited belongs to it if the package *is* that file, or if it + sits in the package's directory. Comparing only the directory would miss + the file case entirely and answer [None], which is the silent failure + above rather than a loud one: the form splices unqualified and the + running program keeps calling the name it already had. *) let same p = let d = try Unix.realpath p.Load.dir with Unix.Unix_error _ -> p.Load.dir in - String.equal d dir + String.equal d here || String.equal d dir in (match List.filter same t.pkgs with | [] -> None diff --git a/test/test_session.ml b/test/test_session.ml index 70469a8..5a6ba7f 100644 --- a/test/test_session.ml +++ b/test/test_session.ml @@ -167,6 +167,19 @@ let () = fail "a form from a package file reported %s, wanted agent/poll" (String.concat " " c.Session.fns) | exception Loc.Error (_, m) -> fail "redefining agent/poll: %s" m); + (* A package that is a single file, which is what sand.flan is to the + headless driver. The file being edited *is* the package rather than a + member of a directory, so matching on the directory alone would answer + "not a package" — and the failure is the silent one above: the form + splices as a bare [step] and the running program keeps the one it had. *) + let t2, _ = Session.create ~file:"programs/sand-headless.flan" in + (match Session.eval ~origin:"../sand.flan" t2 "(defn step [] Unit (do))" with + | c -> + if c.Session.fns <> [ "sand/step" ] then + fail "a form from a single-file package reported %s, wanted sand/step" + (String.concat " " c.Session.fns) + | exception Loc.Error (_, m) -> fail "redefining sand/step: %s" m); + (* And a file that is not a package keeps its names as written. *) (match Session.eval ~origin:"../sand.flan" t "(defn game-draw [] Unit (do))" with | c ->