<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Clojure Q&amp;A - Recent questions tagged clj-kondo</title>
<link>https://ask.clojure.org/index.php/tag/clj-kondo</link>
<description></description>
<item>
<title>Could tools.namespace refresh get more sophisticated directory/file filtering?</title>
<link>https://ask.clojure.org/index.php/11434/could-namespace-refresh-sophisticated-directory-filtering</link>
<description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt;&lt;br&gt;
currently the only way of affecting which source files are loaded by &lt;code&gt;clojure.tools.namespace.repl/refresh&lt;/code&gt; is setting refresh dirs, which is an allowlist-based system. There is no way currently to &lt;em&gt;block&lt;/em&gt; specific directories/files/patterns from being loaded but allowing everything else. This presents an issue when there are clojure source files in source directories on the classpath, which are not meant to be loaded at all.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Long story:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We bumped into an interesting issue with &lt;code&gt;clojure.tools.namespace/refresh&lt;/code&gt; vs &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md&quot;&gt;clj-kondo hooks&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;A one-liner repro case is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;clj -Srepro -Sdeps '{:deps {org.clojure/tools.namespace {:mvn/version &quot;1.2.0&quot;} seancorfield/next.jdbc {:git/url &quot;https://github.com/seancorfield/next-jdbc/&quot; :git/sha &quot;24bf1dbaa441d62461f980e9f880df5013f295dd&quot;}}}' -M -e &quot;((requiring-resolve 'clojure.tools.namespace.repl/refresh-all))&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will fail with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:error-while-loading hooks.com.github.seancorfield.next-jdbc
Could not locate hooks/com/github/seancorfield/next_jdbc__init.class, hooks/com/github/seancorfield/next_jdbc.clj or hooks/com/github/seancorfield/next_jdbc.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For context, clj-kondo is a static analyzer/linter. In order to be able to analyze custom macros properly, it lets libraries distribute clj files (describing how these macros should be analyzed) as resources under a specific directory.&lt;/p&gt;
&lt;p&gt;The above example fails due to the combination of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;referring a lib by git coordinates, which means that it will appear as a directory on the classpath&lt;/li&gt;
&lt;li&gt;said lib exporting clj-kondo hooks&lt;/li&gt;
&lt;li&gt;clj-kondo hooks themselves being .clj files&lt;/li&gt;
&lt;li&gt;as these are for clj-kondo to use, they are not meant to be loaded in the app using the lib&lt;/li&gt;
&lt;li&gt;as a result these files normally having a namespace inside them that does not appear in code proper, for example: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/seancorfield/next-jdbc/blob/24bf1dbaa441d62461f980e9f880df5013f295dd/resources/clj-kondo.exports/com.github.seancorfield/next.jdbc/hooks/com/github/seancorfield/next_jdbc.clj#L1&quot;&gt;https://github.com/seancorfield/next-jdbc/blob/24bf1dbaa441d62461f980e9f880df5013f295dd/resources/clj-kondo.exports/com.github.seancorfield/next.jdbc/hooks/com/github/seancorfield/next_jdbc.clj#L1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;tools.namespace by default reloads all clj source files found in &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.github.io/java.classpath/#clojure.java.classpath/classpath-directories&quot;&gt;classpath-directories&lt;/a&gt; (referring back to the first point)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As there is currently no way to tell tools.namespace to &lt;em&gt;not&lt;/em&gt; load certain files I had to come up with a somewhat hacky workaround, which tries to set the refresh dirs to classpath-directories minus problematic ones, but it would be much much nicer if there was a way to be able to set this with a blocklist or predicate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Workaround&lt;/strong&gt; in case anyone else bumps into it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn remove-clj-kondo-exports-from-tools-ns-refresh-dirs
  &quot;A potential issue from using this is that if the directory containing the clj-kondo.exports folder
  also directly contains to-be-reloaded clojure source files, those will no longer be reloaded.&quot;
  []
  (-&amp;gt;&amp;gt; (clojure.java.classpath/classpath-directories)
       (mapcat
        (fn [^File classpath-directory]
          (let [children   (.listFiles classpath-directory)
                directory? #(.isDirectory ^File %)
                clj-kondo-exports?
                           #(= &quot;clj-kondo.exports&quot; (.getName ^File %))
                has-clj-kondo-exports
                           (some (every-pred clj-kondo-exports? directory?) children)]
            (if has-clj-kondo-exports
              (-&amp;gt;&amp;gt; children
                   (filter directory?)
                   (remove clj-kondo-exports?))
              [classpath-directory]))))
       (apply clojure.tools.namespace.repl/set-refresh-dirs)))

;; call in user.clj
(remove-clj-kondo-exports-from-tools-ns-refresh-dirs)
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>tools.namespace</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/11434/could-namespace-refresh-sophisticated-directory-filtering</guid>
<pubDate>Wed, 05 Jan 2022 18:03:20 +0000</pubDate>
</item>
</channel>
</rss>