thheller / shadow-cljs

ClojureScript compilation made easy
https://github.com/thheller/shadow-cljs
Eclipse Public License 1.0
2.25k stars 178 forks source link

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

Closed lilactown closed 4 months ago

lilactown commented 9 months ago

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

I noticed https://github.com/thheller/shadow-cljs/issues/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.

thheller commented 9 months ago

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.

lilactown commented 9 months ago

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

thheller commented 4 months ago

See https://clojure.atlassian.net/browse/CLJS-3413