2024 年 Clojure 状态调查 中分享您的想法!

欢迎!请查阅 关于 页面以获取关于此如何工作的更多信息。

0 投票
tools.namespace
重新标记

如果您使用以下示例调用 find-ns-decls-in-jarfile jarfile,使用任何 jar 文件都会抛出异常

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

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


    (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 @@
        (ignore-reader-exception
         (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-decls-in-jarfile
</code>
</pre>

1 个答案

0 投票
by
by
谢谢解决这个问题。顺便说一下,我认为我发现了另一个问题。如果您将类路径中的jar文件通过`find-namespaces`运行,我会收到类似以下错误的错误

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

我认为发生的问题可能是`read-ns-decl`函数有时未能返回ns声明(例如读取的文件是project.clj,所以不在ns中),然后`nom`在返回的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" 为 null
;; 使用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>
by
谢谢!我也在修复`JarFile`类型提示的修复中都包含了这些,它们将随着下一个版本一起发布。
by
太好了,谢谢!
...