请在2024 Clojure 状态调查中分享您的看法!

欢迎!请查看关于页面以获得更多关于如何使用本站的详细信息。

0
tools.namespace
重标记

问题
1.4.1 版本的 tools.namespace 无法处理没有包含 ns 声明的源文件。

重现过程
给定文件 ./src/foo.clj

;; no ns declaration here

以及测试脚本 ./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")))

我们可以看到,在此场景中,tools.namespace 1.4.0 返回一个空序列

$ clj -Sdeps '{:deps {org.clojure/tools.namespace {:mvn/version "1.4.0"}}}' -M --report stderr test.clj
found nses: ()

但是 1.4.1 版本在相同的测试中抛出异常

$ 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

使用场景

Cljdoc 使用 tools.namespace 在 API 分析期间查找命名空间。

各种库包含各种奇怪的内容,包括无命名空间源。

之前的 tools.namespace 版本已经为我们处理了这种奇怪的情况。

如果我们决定 tools.namespace 不应处理无命名空间源,我们可以解决这个问题。

以以下备注关闭: 在 tools.namespace 1.4.2 中修复

1回答

0

感谢这份报告。已创建 https://clojure.atlassian.net/browse/TNS-59

感谢Fogus!我已经将您的回答标记为“最佳答案”,但后来意识到这可能会对公开的问题产生误导。
...