Skip to content

Commit

Permalink
Add linter support for widget's options (#292)
Browse files Browse the repository at this point in the history
  • Loading branch information
valerauko authored Dec 4, 2023
1 parent fed8bed commit fca6e1d
Showing 1 changed file with 190 additions and 11 deletions.
201 changes: 190 additions & 11 deletions resources/clj-kondo.exports/tensegritics/clojuredart/hooks/flutter2.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(ns hooks.flutter2
"Hook to support cljd.flutter.alpha2 macro"
(:require [clj-kondo.hooks-api :as api
:refer [sexpr token-node list-node map-node vector-node]]
:refer [sexpr token-node list-node vector-node]]
[clojure.string :as str]))

(defn- ^:macro-support camel-kebab [s]
Expand Down Expand Up @@ -38,8 +38,127 @@
(apply concat (get-node->let-binding-nodes (api/parse-string "{{{style displayLarge} textTheme} m/Theme :value-of [:counters]}")))))))
,)

(defn watch-vector-node->let-binding-nodes
"Example:
Args: `<vector: [animator (m/AnimationController ...)]`
Return: `[ [<token: animator> <List: (m/AnimationController .vsync vsync)>] ]`"
([node]
(watch-vector-node->let-binding-nodes node :watch))
([node opt-name]
(loop [pairs (partition 2 (:children node))
last-binding-pair nil
;; {:name hoge
;; :value (rd/subscribe ,,,)
;; :as true
;; :dispose true
;; :dedup true
;; :> true}
aggr []]
(let [[k v :as pair] (first pairs)]
(if pair
(if (api/keyword-node? k)
(let [kw (sexpr k)]
(when (kw last-binding-pair)
(api/reg-finding!
(assoc (meta k)
:message (str "duplicate " kw " option in " opt-name " for `"
(:name last-binding-pair) "`")
:type :flutter/widget)))
(case kw
:as
(recur
(rest pairs)
(assoc last-binding-pair :as true)
(conj aggr [v (:value last-binding-pair)]))

(:dispose :>)
(recur
(rest pairs)
(assoc last-binding-pair kw true)
(conj aggr
[(api/token-node '_)
(api/list-node
(list (api/token-node '->) v))]))

(:dedup :refresh-on)
(recur
(rest pairs)
(assoc last-binding-pair kw true)
(conj aggr [(api/token-node '_) v]))

;; else unknown kw
(do
(api/reg-finding!
(assoc (meta k)
:message (str "unknown keyword option to " opt-name " `" kw "`")
:type :flutter/widget))
(recur
(rest pairs)
last-binding-pair
aggr)))) ;; to ignore unknown keywords
(recur
(rest pairs)
{:name k
:value v}
(conj aggr
[k (let [node (api/list-node
(list (api/token-node 'deref) v))]
(with-meta node (meta v)))])))
aggr)))))

(defn managed-vector-node->let-binding-nodes
[node]
(loop [pairs (partition 2 (:children node))
last-binding-pair nil
;; {:name hoge
;; :value (rd/subscribe ,,,)
;; :refresh-on true
;; :dispose true}
aggr []]
(let [[k v :as pair] (first pairs)]
(if pair
(if (api/keyword-node? k)
(let [kw (sexpr k)]
(when (kw last-binding-pair)
(api/reg-finding!
(assoc (meta k)
:message (str "duplicate " kw " option in :managed for `"
(:name last-binding-pair) "`")
:type :flutter/widget)))
(case kw
:dispose
(recur
(rest pairs)
(assoc last-binding-pair kw true)
(conj aggr
[(api/token-node '_)
(api/list-node
(list (api/token-node '->) v))]))

:refresh-on
(recur
(rest pairs)
(assoc last-binding-pair kw true)
(conj aggr [(api/token-node '_) v]))

(defn vector-node->let-binding-nodesr
;; else unknown kw
(do
(api/reg-finding!
(assoc (meta k)
:message (str "unknown keyword option to :managed `" kw "`")
:type :flutter/widget))
(recur
(rest pairs)
last-binding-pair
aggr))))
(recur
(rest pairs)
{:name k
:value v}
(conj aggr pair)))
aggr))))

(defn vector-node->let-binding-nodes
"Example:
Args: `<vector: [animator (m/AnimationController ...)]`
Return: `[ [<token: animator> <List: (m/AnimationController .vsync vsync)>] ]`"
Expand All @@ -50,20 +169,79 @@
node-pair))
(partition 2 (:children node))))

(defn vector-node->bg-watcher-node
[node]
(update node :children
(fn [[watcher & body]]
(let [watch-args (watch-vector-node->let-binding-nodes watcher :bg-watcher)]
(list*
(api/token-node 'let)
(vector-node (apply concat watch-args))
body)))))

(defn bind-node->let-binding-nodes
[node]
(if (api/map-node? node)
(mapv (fn [[_ v]]
[(api/token-node '_) v])
(partition 2 (:children node)))
(do
(api/reg-finding!
(assoc (meta node)
:message (str ":bind needs a map parameter")
:type :flutter/widget))
[])))

(defn top-key-value->let-binding-nodes
"Examples:
Args: `<token: :get>`, `<vector: [m/MediaQuery]>`
Return: `[ [<token: media-query> <token: identity>], ... ]`"
[node-key node-val]
(case (sexpr node-key)
:get (get-node->let-binding-nodes node-val)
:bind (bind-node->let-binding-nodes node-val)
(:key :keep-alive :spy :padding :color :width :height) [[(token-node '_) node-val]]
(:vsync :context) (vector [(with-meta (token-node (sexpr node-val)) (meta node-val))
(token-node 'identity)])
(:let :managed :watch) (vector-node->let-binding-nodesr node-val)
:bg-watcher []
:let (vector-node->let-binding-nodes node-val)
:managed (managed-vector-node->let-binding-nodes node-val)
:watch (watch-vector-node->let-binding-nodes node-val)
:bg-watcher [[(token-node '_) (vector-node->bg-watcher-node node-val)]]
;; unsupported keys ignored
[]))

(defn nest-body
[[head & tail]]
(if (seq? tail)
(cond
(api/token-node? head)
(nest-body
(list* (api/list-node
(list head))
tail))

(api/list-node? head)
(let [[maybe-prop & followup] tail
nested-body
(if (and (api/token-node? maybe-prop)
(simple-symbol? (sexpr maybe-prop))
(.startsWith (name (sexpr maybe-prop)) "."))
(list maybe-prop (nest-body followup))
(list (api/token-node '.child)
(nest-body (list* maybe-prop followup))))]
(update
head :children
(fn [children]
(concat children nested-body))))

:else
(api/list-node
(list head (nest-body tail))))
(if (api/token-node? head)
(api/list-node
(list head))
head)))

(defn widget
"The idea is to have all of the bindings in let form and everything else in the body.
Expand Down Expand Up @@ -98,16 +276,17 @@
(remove (fn [[_ i]]
(when (> i 0)
(api/keyword-node? (nth children (dec i))))))
(map first))
(map first)
nest-body)

let-node
(list-node
(list*
(token-node 'let)
(vector-node
(apply concat let-bindings))
body))]
; (clojure.pprint/pprint (sexpr let-node))
(list
(token-node 'let)
(vector-node
(apply concat let-bindings))
body))]
;; (clojure.pprint/pprint (sexpr let-node))
{:node let-node}))

(comment
Expand Down

0 comments on commit fca6e1d

Please sign in to comment.