Skip to content

Commit a70c453

Browse files
authored
Merge pull request #139 from leeebai/2.0.0
release visualis 2.0.0
2 parents 772028c + acbd0f3 commit a70c453

File tree

7,901 files changed

+1354316
-219731
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

7,901 files changed

+1354316
-219731
lines changed

.babel_cache/.gitkeep

Whitespace-only changes.

.babelrc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"plugins": ["@emotion"],
3+
"presets": [
4+
"@babel/preset-env",
5+
"@babel/preset-react",
6+
"@babel/preset-typescript"
7+
],
8+
"env": {
9+
"development": {
10+
"presets": []
11+
},
12+
"extract": {
13+
"plugins": [
14+
[
15+
"ttag",
16+
{
17+
"extract": {
18+
"output": "locales/metabase-frontend.pot"
19+
},
20+
"discover": ["t", "jt"],
21+
"numberedExpressions": true
22+
}
23+
]
24+
]
25+
}
26+
}
27+
}

.circleci/config.yml

Lines changed: 903 additions & 0 deletions
Large diffs are not rendered by default.

.clj-kondo/config.edn

Lines changed: 459 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
(ns hooks.metabase.api.common
2+
(:require
3+
[clj-kondo.hooks-api :as api]
4+
[clojure.string :as str]))
5+
6+
(defn route-fn-name
7+
[method route]
8+
(let [route (if (vector? route) (first route) route)]
9+
(-> (str (name method) route)
10+
(str/replace #"/" "_")
11+
symbol)))
12+
13+
(defn defendpoint [{:keys [node]}]
14+
(let [[method route & body] (rest (:children node))]
15+
{:node
16+
(api/list-node [(api/token-node 'do)
17+
;; register usage of compojure core var
18+
(api/token-node (symbol (str "compojure.core")
19+
(str method)))
20+
;; define function with route-fn-name
21+
(api/list-node (list* (api/token-node 'clojure.core/defn)
22+
(route-fn-name (api/sexpr method) (api/sexpr route))
23+
body))])}))
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
(ns hooks.metabase.models.setting
2+
(:require [clj-kondo.hooks-api :as hooks]))
3+
4+
(defn defsetting
5+
"Rewrite a [[metabase.models.defsetting]] form like
6+
7+
(defsetting my-setting \"Description\" :type :boolean)
8+
9+
as
10+
11+
(let [_ \"Description\"
12+
_ :type
13+
_ :boolean]
14+
(defn my-setting \"Docstring.\" [])
15+
(defn my-setting! \"Docstring.\" [_value-or-nil]))
16+
17+
for linting purposes."
18+
[{:keys [node]}]
19+
(let [[setting-name & args] (rest (:children node))
20+
;; (defn my-setting [] ...)
21+
getter-node (-> (list
22+
(hooks/token-node 'defn)
23+
setting-name
24+
(hooks/string-node "Docstring.")
25+
(hooks/vector-node []))
26+
hooks/list-node
27+
(with-meta (meta setting-name)))
28+
;; (defn my-setting! [_x] ...)
29+
setter-node (-> (list
30+
(hooks/token-node 'defn)
31+
(with-meta
32+
(hooks/token-node (symbol (str (:string-value setting-name) \!)))
33+
(meta setting-name))
34+
(hooks/string-node "Docstring.")
35+
(hooks/vector-node [(hooks/token-node '_value-or-nil)]))
36+
hooks/list-node
37+
(with-meta (meta setting-name)))]
38+
{:node (-> (list
39+
(hooks/token-node 'let)
40+
;; include description and the options map so they can get validated as well.
41+
(hooks/vector-node (vec (interleave (repeat (hooks/token-node '_))
42+
args)))
43+
getter-node
44+
setter-node)
45+
hooks/list-node
46+
(with-meta (meta node)))}))
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
(ns hooks.metabase.test.data
2+
(:require
3+
[clj-kondo.hooks-api :as hooks]
4+
[clojure.string :as str]
5+
[clojure.walk :as walk]))
6+
7+
(defn- global-dataset-symbols
8+
"Dataset definitions defined in [[metabase.test.data.dataset-definitions]]. This is only populated if clj-kondo has
9+
cached analysis for that namespace -- so it may or may not be populated. If it is populated we can do a bit of extra
10+
linting with that information."
11+
[]
12+
(not-empty (set (keys (:clj (hooks/ns-analysis 'metabase.test.data.dataset-definitions))))))
13+
14+
(defn- dataset-type
15+
"`dataset` can be one of:
16+
17+
- a qualified symbol
18+
- an unqualified symbol referring to a a var in [[metabase.test.data.dataset-definitions]]
19+
- an unqualified symbol (referring to a let-bound value or a var in the current namespace
20+
- some sort of non-symbol form like a function call
21+
22+
We can only determine if an unqualified symbol refers to something in the dataset definitions namespace if there are
23+
cached results available from [[global-dataset-symbols]]."
24+
[dataset]
25+
(let [sexpr (hooks/sexpr dataset)
26+
global-defs (global-dataset-symbols)]
27+
(cond
28+
(not (symbol? sexpr))
29+
:non-symbol
30+
31+
(namespace sexpr)
32+
:qualified
33+
34+
(empty? global-defs)
35+
:unqualified/unknown
36+
37+
(contains? global-defs sexpr)
38+
:unqualified/from-dataset-defs-namespace
39+
40+
;; either something defined in the current namespace or let-bound in the current scope.
41+
:else
42+
:unqualified/local-def)))
43+
44+
(defn dataset
45+
[{{[_ dataset & body] :children} :node}]
46+
(let [body (case (dataset-type dataset)
47+
;; non-symbol, qualified symbols, and unqualified symbols from the current namespace/let-bound can all
48+
;; get converted from something like
49+
;;
50+
;; (dataset whatever
51+
;; ...)
52+
;;
53+
;; to
54+
;;
55+
;; (let [_ whatever]
56+
;; ...)
57+
(:non-symbol :qualified :unqualified/local-def)
58+
(list* (hooks/token-node 'let)
59+
(hooks/vector-node [(hooks/token-node '_) dataset])
60+
body)
61+
62+
;; for ones that came from the dataset defs namespace or ones whose origin is unknown, just ignore them
63+
;; and generate a `do` form:
64+
;;
65+
;; (do ...)
66+
(:unqualified/from-dataset-defs-namespace :unqualified/unknown)
67+
(list* (hooks/token-node 'do)
68+
body))]
69+
{:node (with-meta (hooks/list-node (with-meta body
70+
(meta dataset)))
71+
(meta dataset))}))
72+
73+
(defn- special-token-node?
74+
"Whether this node is one of the special symbols like `$field`."
75+
[node]
76+
(when (hooks/token-node? node)
77+
(let [symb (hooks/sexpr node)]
78+
(and (symbol? symb)
79+
(some (partial str/starts-with? symb)
80+
#{"$" "!" "&" "*" "%"})
81+
;; ignore args like `%` or `%1` inside function literals. $id forms have to be more than one character long,
82+
;; and the first character won't be a number (hopefully -- maybe some DBs allow this -- but we don't use it)
83+
(> (count (str symb)) 1)
84+
(not (re-find #"^%\d+" (str symb)))))))
85+
86+
(defn- replace-$id-special-tokens
87+
"Impl for [[$ids]] and [[mbql-query]]. Walk `form` and look for special tokens like `$field` and replace them with
88+
strings so we don't get unresolved symbol errors. Preserves metadata."
89+
[form]
90+
;; [[walk/postwalk]] seems to preserve its meta so we don't need to do anything special
91+
(walk/postwalk
92+
(fn [node]
93+
(if (special-token-node? node)
94+
(-> (hooks/string-node (str (hooks/sexpr node)))
95+
(with-meta (meta node)))
96+
node))
97+
form))
98+
99+
(defn $ids
100+
[{{[_ & args] :children} :node}]
101+
;; `$ids` accepts either
102+
;;
103+
;; ($ids form)
104+
;;
105+
;; or
106+
;;
107+
;; ($ids table & body)
108+
;;
109+
;; table is only relevant for expanding the special tokens so we can ignore it.
110+
(let [body (if (= (count args) 1)
111+
(first args)
112+
(hooks/list-node
113+
(list*
114+
(hooks/token-node `do)
115+
(rest args))))]
116+
{:node (replace-$id-special-tokens body)}))
117+
118+
(defn mbql-query
119+
[{{[_ & args] :children} :node}]
120+
;; `mbql-query` accepts either
121+
;;
122+
;; (mbql-query table)
123+
;;
124+
;; or
125+
;;
126+
;; (mbql-query table query)
127+
;;
128+
;; and table may be `nil`.
129+
;;
130+
;; table is only relevant for expanding the special tokens so we can ignore it either way.
131+
(let [[table query] (if (= (count args) 1)
132+
[(first args)
133+
(hooks/map-node [])]
134+
args)]
135+
(when-not ((some-fn symbol? nil?) (hooks/sexpr table))
136+
(hooks/reg-finding! (assoc (meta table)
137+
:message "First arg to mbql-query should be either a table name symbol or nil."
138+
:type ::mbql-query-first-arg)))
139+
(let [result (replace-$id-special-tokens query)
140+
;; HACK I'm not sure WHY it works but I ran into https://github.com/clj-kondo/clj-kondo/issues/1773 when
141+
;; trying to get this working -- for some magical reason wrapping the whole thing in a `do` form seems to fix
142+
;; it. Once that bug is resolved we can go ahead and remove this line
143+
result (with-meta (hooks/list-node (with-meta (list
144+
(hooks/token-node 'do)
145+
result)
146+
(meta query)))
147+
(meta query))]
148+
{:node result})))
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
(ns hooks.metabase.test.util
2+
(:require [clj-kondo.hooks-api :as hooks]))
3+
4+
(defn- namespaced-symbol-node? [node]
5+
(when (hooks/token-node? node)
6+
(let [symb (hooks/sexpr node)]
7+
(and (symbol? symb)
8+
(namespace symb)))))
9+
10+
(defn with-temporary-setting-values
11+
"Rewrite a form like
12+
13+
(with-temporary-setting-values [x 1, some.ns/y 2]
14+
...)
15+
16+
as one like
17+
18+
(let [_ 1, _ some.ns/y, _ 2]
19+
...)
20+
21+
for analysis purposes. We only need to 'capture' namespaced Setting bindings with a `_` so Kondo considers their
22+
namespace to be 'used' and to catch undefined var usage."
23+
[{{[_ bindings & body] :children} :node}]
24+
(let [bindings (if (hooks/vector-node? bindings)
25+
(hooks/vector-node (into []
26+
(mapcat (fn [[setting-name v]]
27+
(concat
28+
[(hooks/token-node '_) v]
29+
;; if the setting name is namespace-qualified add a `_`
30+
;; entry for it too.
31+
(when (namespaced-symbol-node? setting-name)
32+
[(hooks/token-node '_) setting-name]))))
33+
(partition 2 (:children bindings))))
34+
bindings)]
35+
{:node (-> (list*
36+
(hooks/token-node 'let)
37+
bindings
38+
body)
39+
(with-meta (meta body))
40+
hooks/list-node
41+
(with-meta (meta body)))}))

.clj-kondo/hooks/toucan/util/test.clj

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
(ns hooks.toucan.util.test
2+
(:require [clj-kondo.hooks-api :as api]))
3+
4+
(defn- with-temp-inner [body bindings]
5+
(let [binding-infos (for [[model {[binding value] :children}] (partition 2 bindings)]
6+
{:model model
7+
:binding binding
8+
:value (or value
9+
(api/token-node 'nil))})]
10+
(-> (api/vector-node
11+
[(api/vector-node (map :model binding-infos))
12+
(-> (api/list-node (list* (api/token-node `let)
13+
(api/vector-node (mapcat (juxt :binding :value) binding-infos))
14+
body))
15+
(with-meta (meta body)))])
16+
(with-meta (meta body)))))
17+
18+
(defn with-temp [{:keys [node]}]
19+
(let [[_ db-ref binding+opts & body] (:children node)]
20+
{:node (with-temp-inner body [db-ref binding+opts])}))
21+
22+
(defn with-temp* [{:keys [node]}]
23+
(let [[_ bindings & body] (:children node)]
24+
{:node (with-temp-inner body (:children bindings))}))
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(ns macros.metabase.api.common)
2+
3+
(defmacro define-routes [& args]
4+
`(do (def ~'routes "docstring" nil)
5+
~@args))

0 commit comments

Comments
 (0)