diff --git a/src/zen/store.clj b/src/zen/store.clj index 111eaaf..3a2d021 100644 --- a/src/zen/store.clj +++ b/src/zen/store.clj @@ -47,7 +47,7 @@ (fnil conj #{}) (mk-symbol zen-ns ns-key))))) - (when (nil? res) + (when (and (nil? res) (not (contains? (:declares @ctx) resolved-sym))) (swap! ctx update :errors (fnil conj []) (if (namespace sym) @@ -128,12 +128,21 @@ (defn load-alias [ctx alias-dest alias] (swap! ctx update :aliases zen.utils/disj-set-union-push alias-dest alias)) +(defn load-declare [ctx declare-sym] + (swap! ctx update :declares (fnil conj #{}) declare-sym)) + (defn symbol-definition? [[k v]] (and (symbol? k) (map? v))) (defn symbol-alias? [[k v]] (and (symbol? k) (qualified-symbol? v))) +(defn backward-alias? [[k v]] + (and (qualified-symbol? k) (simple-symbol? v))) + +(defn backward-alias-declare? [[k v]] + (and (simple-symbol? k) (= :zen/declare v))) + (defn pre-load-ns! "loads symbols from namespace to ztx before processing" [ctx zen-ns ns-map] @@ -179,11 +188,13 @@ ;; eval symbols and aliases (let [load-result (->> (apply dissoc ns-map ['ns 'import 'alias :ns :import :alias]) - (sort-by (juxt symbol-definition? symbol-alias?)) #_"NOTE: load aliases first, symbols after" + (sort-by (juxt symbol-definition? symbol-alias? backward-alias? backward-alias-declare?)) #_"NOTE: load aliases first, symbols after" (mapv (fn [[k v :as kv]] (cond (symbol-definition? kv) (load-symbol ctx zen-ns k (merge v opts)) (symbol-alias? kv) (load-alias ctx v (mk-symbol zen-ns k)) - :else nil))) + (backward-alias? kv) (load-alias ctx (mk-symbol zen-ns v) k) + (backward-alias-declare? kv) (load-declare ctx (mk-symbol zen-ns k)) + :else nil))) (mapv (fn [res] (validate-resource ctx res))))] [:resources-loaded (count load-result)]))) diff --git a/test/zen/alias_test.clj b/test/zen/alias_test.clj index 02e1a99..61d5041 100644 --- a/test/zen/alias_test.clj +++ b/test/zen/alias_test.clj @@ -164,3 +164,31 @@ :type "string.type" :path [:a] :schema [myns/sch2 :a :type]}]}))) + + +(deftest backward-alias-test + (def test-namespaces + '{lib {:ns lib + foo :zen/declare + bar {:cfg foo}} + + user {:ns user + :import #{lib} + lib/foo myfoo + myfoo {:baz :quux}}}) + + (def ztx (zen/new-context {:unsafe true :memory-store test-namespaces})) + + (zen/load-ns ztx (get test-namespaces 'user)) + + (matcho/match (zen/errors ztx) + empty?) + + (matcho/match (zen/get-symbol ztx 'lib/foo) + {:baz :quux}) + + (matcho/match (zen/get-symbol ztx 'user/myfoo) + {:baz :quux}) + + (is (= (zen/get-symbol ztx 'lib/foo) + (zen/get-symbol ztx 'user/myfoo))))