2024 Clojure 调查!(调查)中分享您的想法!

欢迎!请参阅关于页面了解有关这是如何工作的更多信息。

0
tools.namespace
重新标记

如果我用任何 jar 调用 find-ns-decls-in-jarfile jarfile(以下示例),我都会获得异常。

在 clojure.tools.namespace.find/read-ns-decl-from-jarfile-entry (find.clj:158) 中打印返回值时出错(ClassCastException)。
class java.util.jar.JarFile 不能转换到 class java.io.File(java.util.jar.JarFile 和 java.io.File 在模块 java.base 的加载器 'bootstrap' 中)

我可以用此示例重现此问题


    (let [filename (format "%s/.m2/repository/org/clojure/tools.namespace/1.4.2/tools.namespace-1.4.2.jar" (System/getenv "HOME"))
      jarfile (JarFile. (io/file filename))]
  (clojure.tools.namespace.find/find-ns-decls-in-jarfile jarfile))

我认为问题在于第 159 行的类型提示。我认为它应该改为 ^java.util.jar.JarFile

我还创建了以下补丁(包括 lint 修复),如果这样有帮助。如果需要,我可以签署贡献者协议。

<pre>
<code>
diff --git a/src/main/clojure/clojure/tools/namespace/find.clj b/src/main/clojure/clojure/tools/namespace/find.clj
index 88f88ef..d67aaf1 100644
--- a/src/main/clojure/clojure/tools/namespace/find.clj
+++ b/src/main/clojure/clojure/tools/namespace/find.clj
@@ -12,12 +12,10 @@
   clojure.tools.namespace.find
   (:require [clojure.java.classpath :as classpath]
             [clojure.java.io :as io]
-            [clojure.set :as set]
             [clojure.tools.namespace.file :as file]
-           [clojure.tools.namespace.parse :as parse])
-  (:import (java.io File FileReader BufferedReader PushbackReader
-                    InputStreamReader)
-           (java.util.jar JarFile JarEntry)))
+  (:import (java.io File PushbackReader)
+           (java.util.jar JarFile)))
 
 (set! *warn-on-reflection* true)
 
@@ -92,7 +90,7 @@
            (let [[_ nom & more :as decl] (file/read-file-ns-decl % (:read-opts platform))]
              (when (and decl nom (symbol? nom))
                (list* 'ns (with-meta nom
-                       {:dir (.getName ^java.io.File dir) :file (.getName ^java.io.File %)})
+                       {:dir (.getName ^File dir) :file (.getName ^File %)})
                      more))))
          (find-sources-in-dir dir platform))))
 
@@ -156,7 +154,7 @@
        ;(try
          (let [[_ nom & more] (parse/read-ns-decl rdr read-opts)]
            (list* 'ns (with-meta nom
-                       {:jar (.getName ^java.io.File jarfile) :file entry-name})
+                       {:jar (.getName ^JarFile jarfile) :file entry-name})
                  more)))))))
 
 (defn find-ns- declarations-in-jarfile
</code>
</pre>

1 答案

0
感谢修复这个问题。顺便说一下,我认为我发现了另一个问题。当我运行我的类路径中的JAR时,通过 `find-namespaces` 我得到类似以下错误的错误:

<pre>
<code>
打印返回值时出错(NullPointerException)在clojure.core/with-meta (core.clj:220)。
无法调用 "clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)" 因为 "x" 为空
</code>
</pre>

我认为发生的事情是 `read-ns-decl` 函数有时无法返回 ns 声明(例如,所读取的文件是 project.clj,因此不在 ns 中),然后 `nom` 在 return let 绑定中为 `nil`。这将在调用 `with-meta nom` 时引发异常。

因此,我认为第157行的 `(let [[_ nom & more] (parse/read-ns-decl rdr read-opts)]` 形式只需要更改为一个 `when-let`。我在本地分支中进行了更改,并且它工作正常。

感谢!

通知:以下是一个使用从本地 m2 目录的 clojure JAR 的样例 REPL 会话

<pre>
<code>
;; 使用现有的 1.4.3 实现
正在加载 src/main/clojure/clojure/tools/namespace/find.clj... 完成
(find-namespaces [(io/file "/Users/mbastian/.m2/repository/amalloy/ring-buffer/1.3.1/ring-buffer-1.3.1.jar")])
打印返回值时出错(NullPointerException)在clojure.core/with-meta (core.clj:220)。
无法调用 "clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)" 因为 "x" 为空
;; 使用 when-let
正在加载 src/main/clojure/clojure/tools/namespace/find.clj... 完成
(find-namespaces [(io/file "/Users/mbastian/.m2/repository/amalloy/ring-buffer/1.3.1/ring-buffer-1.3.1.jar")])
=> (amalloy.ring-buffer)
</code>
</pre>
谢谢!我也在修复`JarFile`类型提示的补丁中解决了这个问题,两者都将在下一个版本中发布。
太好了,谢谢!
...