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

欢迎!请参阅关于页面了解此处的更多信息。

0
tools.namespace
重标记

如果我以任何jar文件调用find-ns-decls-in-jarfile jarfile(以下为示例),我将得到以下异常

打印返回值时出错(ClassCastException)在clojure.tools.namespace.find/read-ns-decl-from-jarfile-entry (find.clj:158)。
无法实例化java.util.jar.JarFile到class java.io.File(java.util.jar.JarFile和java.io.File位于启动器模块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

我还创建了一个以下补丁(包括代码风格修正),如果有所帮助,我会乐意签署贡献者协议。

<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
谢谢修复。顺便说一下,我认为我发现了一个问题。如果我在classpath中运行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
太好了,谢谢!
...