Welcome! Please see the About page for a little more info on how this works.

+1 vote
ago in Clojure by

Environment

  • Clojure 1.12.1 REPL with :local/root dependencies in deps.edn
  • Example: local.lib namespace at /Users/user/projects/repo/src/local/lib.clj

History

  1. Load namespace from :local/root dependency in REPL
  2. Verify function metadata:

    (meta #'local.lib/some-function)
    => {:arglists ([arg]),

     :line 42,
     :column 1,
     :file "/Users/user/projects/repo/src/local/lib.clj",
     :name some-function,
     :ns #object [clojure.lang.Namespace 0x123abc "local.lib"]}
    
  3. Call (clojure.repl/source-fn 'local.lib/some-function) returns nil

Expectation

source-fn should return the source code string for the symbol.

Actual

source-fn returns nil.

Evidence

(.getResourceAsStream (RT/baseLoader) "/Users/user/projects/repo/src/local/lib.clj") returns nil because RT/baseLoader cannot access local filesystem paths, only classpath JAR resources.

Impact

Breaks REPL-driven development workflow for :local/root dependencies. Creates an inconsistent experience between JAR and local dependencies.

ago by
How exactly did you "Load namespace from :local/root dependency in REPL"?

If I just eval the file via Calva into the REPL, I can't get source. If I explicitly require the ns, I can get source.

1 Answer

0 votes
ago by
edited ago by

This works for me locally but I'm assuming things you haven't provided. What's the deps.edn of repo? what's the deps.edn/command line of the REPL? Did you (require 'local.lib)? (It is necessary to load the namespace before you call source-fn.)

  • My repo deps.edn: {:paths ["src"]}
  • My command line: clj -Sdeps '{:deps {local/repo {:local/root "repo"}}}'

    Clojure 1.12.1
    user=> (require 'local.lib)
    nil
    user=> (meta #'local.lib/some-function)
    {:arglists ([]), :line 3, :column 1, :file "local/lib.clj", :name some-function, :ns #object[clojure.lang.Namespace 0x14f3c6fc "local.lib"]}
    user=> (clojure.repl/source-fn 'local.lib/some-function)
    "(defn some-function [] \"hi\")"

"RT/baseLoader cannot access local filesystem paths, only classpath JAR resources." is incorrect. The file system resource path you care about here is NOT an absolute path, it is: (.getResourceAsStream (clojure.lang.RT/baseLoader) "local/lib.clj") (which is subsequently a path found via the classpath roots, which may be either in directories or jars:

user=> (:file (meta #'local.lib/some-function))
"local/lib.clj"
...