Issue
Tools.namespace find 1.4.1 does not handle sources that don't include a ns
declaration.
Reproduction
Given file ./src/foo.clj
:
;; no ns declaration here
And test script ./test.clj
:
(require '[clojure.tools.namespace.find :as f]
'[clojure.java.io :as io])
(println "found nses:" (f/find-ns-decls-in-dir (io/file "src")))
We can see that tools.namespace 1.4.0
returns an empty sequence for this scenario:
$ clj -Sdeps '{:deps {org.clojure/tools.namespace {:mvn/version "1.4.0"}}}' -M --report stderr test.clj
found nses: ()
But version 1.4.1 throws an exception for this same test:
$ clj -Sdeps '{:deps {org.clojure/tools.namespace {:mvn/version "1.4.1"}}}' -M --report stderr test.clj
{:clojure.main/message
"Execution error (NullPointerException) at clojure.tools.namespace.find/find-ns-decls-in-dir$fn (find.clj:93).\nCannot invoke \"clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)\" because \"x\" is null\n",
:clojure.main/triage
{:clojure.error/class java.lang.NullPointerException,
:clojure.error/line 93,
:clojure.error/cause
"Cannot invoke \"clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)\" because \"x\" is null",
:clojure.error/symbol
clojure.tools.namespace.find/find-ns-decls-in-dir$fn,
:clojure.error/source "find.clj",
:clojure.error/phase :execution},
:clojure.main/trace
{:via
[{:type clojure.lang.Compiler$CompilerException,
:message
"Syntax error macroexpanding at (/home/lee/proj/oss/-verify/tns-test/test.clj:4:1).",
:data
{:clojure.error/phase :execution,
:clojure.error/line 4,
:clojure.error/column 1,
:clojure.error/source
"/home/lee/proj/oss/-verify/tns-test/test.clj"},
:at [clojure.lang.Compiler load "Compiler.java" 7665]}
{:type java.lang.NullPointerException,
:message
"Cannot invoke \"clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)\" because \"x\" is null",
:at [clojure.core$with_meta__5485 invokeStatic "core.clj" 220]}],
:trace
[[clojure.core$with_meta__5485 invokeStatic "core.clj" 220]
[clojure.core$with_meta__5485 invoke "core.clj" 219]
[clojure.tools.namespace.find$find_ns_decls_in_dir$fn__1437
invoke
"find.clj"
93]
[clojure.core$keep$fn__8649 invoke "core.clj" 7409]
[clojure.lang.LazySeq sval "LazySeq.java" 42]
[clojure.lang.LazySeq seq "LazySeq.java" 51]
[clojure.lang.RT seq "RT.java" 535]
[clojure.core$seq__5467 invokeStatic "core.clj" 139]
[clojure.core$print_sequential invokeStatic "core_print.clj" 53]
[clojure.core$fn__7391 invokeStatic "core_print.clj" 174]
[clojure.core$fn__7391 invoke "core_print.clj" 174]
[clojure.lang.MultiFn invoke "MultiFn.java" 234]
[clojure.core$pr_on invokeStatic "core.clj" 3675]
[clojure.core$pr invokeStatic "core.clj" 3678]
[clojure.core$pr invoke "core.clj" 3678]
[clojure.lang.AFn applyToHelper "AFn.java" 154]
[clojure.lang.RestFn applyTo "RestFn.java" 132]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$pr invokeStatic "core.clj" 3691]
[clojure.core$pr doInvoke "core.clj" 3678]
[clojure.lang.RestFn applyTo "RestFn.java" 139]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$prn invokeStatic "core.clj" 3715]
[clojure.core$prn doInvoke "core.clj" 3715]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$println invokeStatic "core.clj" 3734]
[clojure.core$println doInvoke "core.clj" 3734]
[clojure.lang.RestFn invoke "RestFn.java" 421]
[user$eval1480 invokeStatic "test.clj" 4]
[user$eval1480 invoke "test.clj" 4]
[clojure.lang.Compiler eval "Compiler.java" 7194]
[clojure.lang.Compiler load "Compiler.java" 7653]
[clojure.lang.Compiler loadFile "Compiler.java" 7591]
[clojure.main$load_script invokeStatic "main.clj" 475]
[clojure.main$script_opt invokeStatic "main.clj" 535]
[clojure.main$script_opt invoke "main.clj" 530]
[clojure.main$main invokeStatic "main.clj" 664]
[clojure.main$main doInvoke "main.clj" 616]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 40]],
:cause
"Cannot invoke \"clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)\" because \"x\" is null",
:phase :execution}}
Execution error (NullPointerException) at clojure.tools.namespace.find/find-ns-decls-in-dir$fn (find.clj:93).
Cannot invoke "clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)" because "x" is null
Usage Scenario
Cljdoc uses tools.namespace to find namespaces during API analysis.
Various libs include all sorts of weirdnesses including namespace-less sources.
Previous versions of tools.namespace handled this weirdness for us.
We can certainly work around this if it is decided that tools.namespace should not handle namespace-less sources.