(try-best-match tags methods)
Given a vector of arg tags and a collection of methods, tries to return the
subset of methods that match best the given tags
Source
(defn try-best-match
"Given a vector of arg tags and a collection of methods, tries to return the
subset of methods that match best the given tags"
[tags methods]
(let [o-tags (mapv #(or (maybe-class %) Object) tags)]
(if-let [methods (or (seq (filter
#(= o-tags (mapv maybe-class (:parameter-types %))) methods))
(seq (filter #(tag-match? tags %) methods)))]
(reduce (fn [[prev & _ :as p] next]
(let [prev-params (mapv maybe-class (:parameter-types prev))
next-params (mapv maybe-class (:parameter-types next))
prev-ret (maybe-class (:return-type prev))
next-ret (maybe-class (:return-type next))
prev-decl (maybe-class (:declaring-class prev))
next-decl (maybe-class (:declaring-class next))]
(cond
(not prev)
[next]
(= prev-params next-params)
(cond
(= prev-ret next-ret)
(cond
(.isAssignableFrom prev-decl next-decl)
[next]
(.isAssignableFrom next-decl prev-decl)
p
:else
(conj p next))
(.isAssignableFrom prev-ret next-ret)
[next]
(.isAssignableFrom next-ret prev-ret)
p
:else
(conj p next))
(and (some true? (map subsumes? next-params prev-params))
(not-any? true? (map subsumes? prev-params next-params)))
[next]
:else
(conj p next)))) [] methods)
methods)))