I noticed a few behavioral differences between the CLR and JVM implementations of tools.namespace
.
As an example, the following tests will pass in the JVM implementation and fail in the CLR implementation. In CLR, files-2
is empty and ::dir/time
is an instant.
(ns clojure.tools.namespace.repl-test
(:require [clojure.test :refer [deftest is]]
[clojure.tools.namespace.dir :as dir]
[clojure.tools.namespace.find :as find]
[clojure.tools.namespace.repl :as repl]
[clojure.tools.namespace.test-helpers :as help]))
(deftest t-repl-scan
(let [dir (help/create-temp-dir "t-repl-scan")
_main-clj (help/create-source dir 'example.main :clj '[example.one])
_one-cljc (help/create-source dir 'example.one :clj)
_other-dir (help/create-temp-dir "t-repl-scan-other")
files-1 (::dir/files (repl/scan {:platform find/clj}))
files-2 (::dir/files (repl/scan {:platform find/clj}))]
(is (not-empty files-1))
(is (not-empty files-2))
(is (= files-1 files-2))))
(deftest t-repl-scan-time
(let [scan (repl/scan {:platform find/clj})]
(is (integer? (::dir/time scan)))))
After discussing with other contributors, the question of intent came up and this test was proposed as something that correctly captures the intent of repl/scan
. However, if this is the intended behavior, then a new problem arises as this test fails in the JVM implementation.
(deftest t-repl-scan
(try
(let [dir (help/create-temp-dir "t-repl-scan")
_main-clj (help/create-source dir 'example.main :clj '[example.one])
_one-cljc (help/create-source dir 'example.one :clj)
other-dir (help/create-temp-dir "t-repl-scan-other")
_ (repl/set-refresh-dirs dir other-dir)
scan1 (repl/scan {:platform find/clj})
scan2 (repl/scan {:platform find/clj})
files-1 (::dir/files scan1)
files-2 (::dir/files scan2)]
(is (= (count files-1) 2))
(is (= (count files-2) 0)))
(finally (repl/clear))))
A couple things I think would help here:
1. Flesh out the tools.namespace
(JVM) test suite to capture all the intended behavior.
2. Realign clr.tools.namespace
with tools.namespace
.
Point 1 will provide a good baseline for point 2, as well as any other existing/future ports of tools.namespace
and help prevent things from diverging in the future as changes are made.
Note
As of writing, repl/scan
will throw an InvalidCastException
on CLR. To fix this, replace clojure.tools.namespace.dir/modified-files
with this:
(defn- modified-files [tracker files]
(filter #(DateTime/op_LessThan ^DateTime (::time tracker System.DateTime/UnixEpoch) (.get_LastWriteTimeUtc ^FileSystemInfo %)) files))