diff --git a/src/main/om/next.cljc b/src/main/om/next.cljc index 749a2fbd..38396636 100644 --- a/src/main/om/next.cljc +++ b/src/main/om/next.cljc @@ -312,6 +312,29 @@ #?(:clj (intern 'cljs.core 'proto-assign-impls proto-assign-impls)) +#?(:clj (defn- extract-static-methods [protocols] + (letfn [(add-protocol-method [existing-methods method] + (let [nm (first method) + new-arity (rest method) + k (keyword nm) + existing-method (get existing-methods k)] + (if existing-method + (let [single-arity? (vector? (second existing-method)) + existing-arities (if single-arity? + (list (rest existing-method)) + (rest existing-method))] + (assoc existing-methods k (conj existing-arities new-arity 'fn))) + (assoc existing-methods k (list 'fn new-arity)))))] + (when-not (empty? protocols) + (let [result (->> protocols + (filter #(not (symbol? %))) + (reduce + (fn [r impl] (add-protocol-method r impl)) + {}))] + (if (contains? result :params) + result + (assoc result :params '(fn [this])))))))) + #?(:clj (defn defui*-clj [name forms] (let [docstring (when (string? (first forms)) @@ -327,12 +350,7 @@ (and (sequential? x) (not (lifecycle-method-names (first x))))) obj-dt) - class-methods (when-not (empty? (:protocols statics)) - (->> (partition 2 (:protocols statics)) - (reduce - (fn [r [_ impl]] - (assoc r (keyword (first impl)) - (cons 'fn (rest impl)))) {:params '(fn [this])})))] + class-methods (extract-static-methods (:protocols statics))] `(do ~(when-not (empty? non-lifecycle-dt) `(defprotocol ~(symbol (str name "_proto")) diff --git a/src/test/om/next/next_test.clj b/src/test/om/next/next_test.clj index 3475a400..cb4f8413 100644 --- a/src/test/om/next/next_test.clj +++ b/src/test/om/next/next_test.clj @@ -889,3 +889,23 @@ (let [c ((om/factory NonLifecycleMethodsComponent))] (is (= (.someMethod c) "Hello World")) (is (= (.render c) "Hello World")))) + +(deftest extracting-protocol-static-methods + (testing "extracts protocols with single methods" + (is (= '{:params (fn [this]), :query (fn ([this] [:a])), :ident (fn ([this props] [:a 1]))} + (#'om/extract-static-methods '[IQuery (query [this] [:a]) + Ident (ident [this props] [:a 1])])))) + (testing "extracts protocols with multiple methods" + (is (= '{:params (fn [this]), :query (fn ([this] [:a])), :ident (fn ([this props] [:a 1])) + :method-a (fn ([this] :a)) :method-b (fn ([this] :b)) :method-c (fn ([this] :c))} + (#'om/extract-static-methods '[IQuery (query [this] [:a]) Multi + (method-a [this] :a) + (method-b [this] :b) + (method-c [this] :c) + Ident + (ident [this props] [:a 1])])))) + (testing "extracts protocols with multiple arity methods" + (is (= '{:params (fn [this]) :method-a (fn ([this] :b) ([this arg] :a))} + (#'om/extract-static-methods '[Multi + (method-a [this arg] :a) + (method-a [this] :b)])))))