-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
engine.clj
55 lines (47 loc) · 1.93 KB
/
engine.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
(ns clj-holmes.rules.engine
(:require [clojure.walk :as walk]))
(defn ^:private extract-findings-from-rule [rule]
(->> rule
(tree-seq coll? identity)
(filter :findings)
(pmap :findings)
(reduce concat)
(into [])))
(defn ^:private execute-rule* [forms ns-declaration entry]
(let [check-fn (:check-fn entry)
condition-fn (:condition-fn entry)]
(if (not (nil? check-fn))
(let [results (filterv #(check-fn % ns-declaration) forms)
results-with-metadata (mapv (fn [result]
(assoc (meta result) :code result)) results)]
(-> entry
(assoc :result (condition-fn (-> results-with-metadata seq boolean)))
(assoc :findings results-with-metadata)))
entry)))
(defn ^:private entry->pattern-type [entry]
(cond
(contains? entry :patterns) :patterns
(contains? entry :patterns-either) :patterns-either))
(defn ^:private pattern-type->condition-fn [pattern-type]
(case pattern-type
:patterns every?
:patterns-either (comp boolean some)))
(defn ^:private check* [entry]
(if (and (map? entry) (entry->pattern-type entry))
(let [pattern-type (entry->pattern-type entry)
condition-fn (pattern-type->condition-fn pattern-type)
pattern (pattern-type entry)
result (condition-fn :result pattern)]
(assoc entry :result result))
entry))
(defn ^:private check [rule]
(walk/postwalk check* rule))
(defn ^:private execute-rule [rule forms ns-declaration]
(walk/postwalk (partial execute-rule* forms ns-declaration) rule))
(defn run [{:keys [forms ns-declaration filename]} rule]
(let [executed-rule (execute-rule rule forms ns-declaration)
executed-rule-checked (check executed-rule)
findings (extract-findings-from-rule executed-rule-checked)]
(-> executed-rule-checked
(assoc :filename filename)
(assoc :findings findings))))