thheller / shadow-cljs

ClojureScript compilation made easy

Home Page:https://github.com/thheller/shadow-cljs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Preloads with a top-level namespace don't load macros

lilactown opened this issue · comments

See https://github.com/lilactown/macro-repl-bug for a reproduction.

I noticed #1059 which seems to be directly related. I changed the code to use more than a single part (e.g. bug-shadow.macro-repl) and it resolved the bug.

In a project I work on, we have a top-level namespace that we use frequently from the REPL. It would be helpful to have a macro available from within it, but currently this blocks us from easily doing so.

I did a quick debug and found the cause in CLJS directly, at least I think so.

Basically the fix is to (require 'bug-shadow-macro-repl) first, since that creates the necessary analyzer info CLJS seems to base this off.

The CLJS code has a path that checks (.contains nstr ".") and only then tries to look at namespaces directly then. Without a dot it only checks namespaces the current namespace has required, not the global ones. Since with preloads that require is missing, it ends up as unresolved.

(defn get-expander-ns [env ^String nstr]
  ;; first check for clojure.* -> cljs.* cases
  (let [res  (or (resolve-macro-ns-alias env nstr nil)
                 (resolve-ns-alias env nstr nil))
        nstr (if (some? res) (str res) nstr)]
    (cond
     #?@(:clj  [(= "clojure.core" nstr) (find-ns 'cljs.core)]
         :cljs [(identical? "clojure.core" nstr) (find-macros-ns impl/CLJS_CORE_MACROS_SYM)])
     #?@(:clj  [(= "clojure.repl" nstr) (find-ns 'cljs.repl)]
         :cljs [(identical? "clojure.repl" nstr) (find-macros-ns 'cljs.repl)])
     #?@(:clj  [(.contains nstr ".") (find-ns (symbol nstr))]
         :cljs [(goog.string/contains nstr ".") (find-macros-ns (symbol nstr))])
     :else (some-> env :ns :require-macros (get (symbol nstr)) #?(:clj  find-ns
                                                                  :cljs find-macros-ns)))))

Do you want to try to recreate this issue CLJS only? I can see if I can work around this, but it seems to be entirely in code shadow-cljs doesn't control.

I'll open a bug with CLJS. Thanks for investigating!