Skip to content

Commit

Permalink
Fix #1845: add :derived-location to analysis (#1851)
Browse files Browse the repository at this point in the history
  • Loading branch information
borkdude committed Oct 21, 2022
1 parent 5859a8e commit 4536247
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 24 deletions.
4 changes: 2 additions & 2 deletions src/clj_kondo/hooks_api.clj
Expand Up @@ -122,14 +122,14 @@
(defn annotate
{:no-doc true}
[node original-meta]
(let [!!last-meta (volatile! original-meta)]
(let [!!last-meta (volatile! (assoc original-meta :derived-location true))]
(prewalk (fn [node]
(cond
(and (instance? clj_kondo.impl.rewrite_clj.node.seq.SeqNode node)
(identical? :list (utils/tag node)))
(if-let [m (meta node)]
(if-let [m (not-empty (select-keys m [:row :end-row :col :end-col]))]
(do (vreset! !!last-meta m)
(do (vreset! !!last-meta (assoc m :derived-location true))
(mark-generate node))
(-> (with-meta node
(merge @!!last-meta (meta node)))
Expand Down
22 changes: 14 additions & 8 deletions src/clj_kondo/impl/analysis.clj
Expand Up @@ -39,7 +39,9 @@
:name-end-row
:name-end-col
:end-row
:end-col]))
:end-col
:derived-location
:derived-name-location]))
:arity arity
:lang lang
:from-var in-def
Expand All @@ -49,7 +51,7 @@
filename row col ns nom attrs]
(when analysis
(let [raw-attrs attrs
attrs (select-keys attrs [:private :macro :fixed-arities :varargs-min-arity
attrs (select-some attrs [:private :macro :fixed-arities :varargs-min-arity
:doc :added :deprecated :test :export :defined-by
:protocol-ns :protocol-name
:imported-ns
Expand Down Expand Up @@ -113,15 +115,15 @@
(when (and analysis
(not (:clj-kondo.impl/generated binding)))
(swap! analysis update :locals conj
(assoc-some (select-keys binding [:name :str :id :row :col :end-row :end-col :scope-end-col :scope-end-row])
(assoc-some (select-keys binding [:name :str :id :row :col :end-row :end-col :scope-end-col :scope-end-row :derived-location])
:filename filename
:lang (when (= :cljc (:base-lang ctx)) (:lang ctx))))))

(defn reg-local-usage! [{:keys [:analysis] :as ctx} filename binding usage]
(when (and analysis
(not (:clj-kondo.impl/generated binding)))
(swap! analysis update :local-usages conj
(assoc-some (select-keys usage [:id :row :col :end-row :end-col :name-row :name-col :name-end-row :name-end-col])
(assoc-some (select-keys usage [:id :row :col :end-row :end-col :name-row :name-col :name-end-row :name-end-col :derived-location])
:name (:name binding)
:filename filename
:lang (when (= :cljc (:base-lang ctx)) (:lang ctx))
Expand All @@ -134,7 +136,8 @@
(assoc-some (select-keys usage [:row :col :end-row :end-col :alias :ns
:keys-destructuring
:keys-destructuring-ns-modifier
:reg :auto-resolved :namespace-from-prefix])
:reg :auto-resolved :namespace-from-prefix
:derived-location])
:name (name (:name usage))
:filename filename
:lang (when (= :cljc (:base-lang ctx)) (:lang ctx))
Expand Down Expand Up @@ -162,14 +165,16 @@
:row (:row method-meta)
:col (:col method-meta)
:end-row (:end-row method-meta)
:end-col (:end-col method-meta)})))))
:end-col (:end-col method-meta)
:derived-location (:derived-location method-meta)})))))

(defn reg-instance-invocation!
[ctx method-name-node]
(when (:analyze-instance-invocations? ctx)
(when-let [analysis (:analysis ctx)]
(let [method-meta (meta method-name-node)
k :instance-invocations]
k :instance-invocations
derived-location (:derived-location method-meta)]
(when k
(swap! analysis update k conj
(cond->
Expand All @@ -180,4 +185,5 @@
:name-end-row (:end-row method-meta)
:name-end-col (:end-col method-meta)}
(= :cljc (:base-lang ctx))
(assoc :lang (:lang ctx)))))))))
(assoc :lang (:lang ctx))
derived-location (assoc :derived-location true))))))))
9 changes: 6 additions & 3 deletions src/clj_kondo/impl/analyzer.clj
Expand Up @@ -1751,7 +1751,8 @@
;; :arg-types (:arg-types ctx)
:interop? interop?
:resolved-core? resolved-core?
:in-def (:in-def ctx)})))
:in-def (:in-def ctx)
:derived-location (:derived-location (meta expr))})))
(and arity arg-count)
(let [{:keys [:fixed-arities :varargs-min-arity]} arity
config (:config ctx)
Expand Down Expand Up @@ -2022,7 +2023,8 @@
:interop? interop?
:resolved-core? resolved-core?
:idx (:idx ctx)
:len (:len ctx)}))
:len (:len ctx)
:derived-location (:derived-location expr-meta)}))
;;;; This registers the namespace as used, to prevent unused warnings
(namespace/reg-used-namespace! ctx
ns-name
Expand Down Expand Up @@ -2325,7 +2327,8 @@
:resolved-core? resolved-core?
:redundant-fn-wrapper-parent-loc fn-parent-loc
:idx (:idx ctx)
:len (:len ctx)}
:len (:len ctx)
:derived-location (:derived-location expr-meta)}
ret-tag (or (:ret m)
(types/ret-tag-from-call ctx proto-call expr))
call (cond-> proto-call
Expand Down
4 changes: 3 additions & 1 deletion src/clj_kondo/impl/linters.clj
Expand Up @@ -319,7 +319,9 @@
:name-end-row name-end-row
:name-end-col name-end-col
:end-row end-row
:end-col end-col))))
:end-col end-col
:derived-location (:derived-location call)
:derived-name-location (:derived-location name-meta)))))
call-config (:config call)
fn-sym (symbol (str resolved-ns)
(str fn-name))
Expand Down
3 changes: 2 additions & 1 deletion src/clj_kondo/impl/namespace.clj
Expand Up @@ -112,7 +112,8 @@
:row expr-row
:col expr-col
:end-row expr-end-row
:end-col expr-end-col)
:end-col expr-end-col
:derived-location (:derived-location m))
path [base-lang lang ns-sym]
temp? (:temp metadata)
config (:config ctx)]
Expand Down
92 changes: 91 additions & 1 deletion test/clj_kondo/analysis_test.clj
Expand Up @@ -991,6 +991,96 @@
" {:node (with-meta new-node (meta node))"
" :defined-by 'user/defflow}))")}}}}))))

(deftest hooks-derived-location-test
(testing "without custom with-meta"
(testing "generated def var-usage"
(let [{:keys [var-definitions var-usages]}
(analyze "(user/defflow foobar)"
{:config {:analysis {:keywords true}
:hooks {:__dangerously-allow-string-hooks__ true
:analyze-call
{'user/defflow
(str '(require '[clj-kondo.hooks-api :as api])
'(fn [{:keys [:node]}]
(let [[test-name] (rest (:children node))
new-node (api/list-node
[(api/token-node 'def)
test-name])]
{:node new-node})))}}}})]
(assert-submaps
'[{:ns user,
:name foobar
:derived-location :submap/missing}]
var-definitions)
(assert-submaps
'[{:name defflow}
{:name def
:derived-location true
:derived-name-location true
:row 1 :col 1 :end-row 1 :end-col 22
:name-row 1 :name-col 1 :name-end-row 1 :name-end-col 22}]
var-usages)))
(testing "generated keyword and let var-usage"
(let [{:keys [var-definitions var-usages keywords]}
(analyze "(user/deflet my-k)"
{:config {:analysis {:keywords true}
:hooks {:__dangerously-allow-string-hooks__ true
:analyze-call
{'user/deflet
(str
'(require '[clj-kondo.hooks-api :as api])
'(fn [{:keys [node]}]
(let [[my-k] (rest (:children node))
new-node (api/list-node
[(api/token-node 'let)
(api/vector-node [(api/token-node '_)
(api/keyword-node (keyword (api/sexpr my-k)))])])]
{:node new-node})))}}}})]
(assert-submaps
'[{:name "my-k"
:row 1 :col 1 :end-row 1 :end-col 19
:derived-location true
:derived-name-location :submap/missing}]
keywords)
(is (empty? var-definitions))
(assert-submaps
'[{:name deflet}
{:name let
:derived-location true
:derived-name-location true
:row 1 :col 1 :end-row 1 :end-col 19
:name-row 1 :name-col 1 :name-end-row 1 :name-end-col 19}]
var-usages))))
(testing "with custom with-meta"
(let [{:keys [var-definitions var-usages]}
(analyze "(user/defflow foobar)"
{:config {:analysis {:keywords true}
:hooks {:__dangerously-allow-string-hooks__ true
:analyze-call
{'user/defflow
(str '(require '[clj-kondo.hooks-api :as api])
'(fn [{:keys [:node]}]
(let [[test-name] (rest (:children node))
new-node (api/list-node
[(api/token-node 'def)
test-name])]
{:node (with-meta new-node {:row 10 :col 11 :end-row 12 :end-col 13})
})))}}}})]
(assert-submaps
'[{:ns user,
:name foobar,
:derived-location :submap/missing
:derived-name-location :submap/missing}]
var-definitions)
(assert-submaps
'[{:name defflow}
{:name def
:derived-name-location true
:row 10 :col 11 :end-row 12 :end-col 13
:name-row 10 :name-col 11 :name-end-row 12 :name-end-col 13
:derived-location :submap/missing}]
var-usages))))

(deftest hooks-custom-missing-meta-test
(assert-submaps
'[{:row 1
Expand Down Expand Up @@ -1063,7 +1153,7 @@
{:name f6,
:defined-by clojure.core/def
:arglist-strs ["[n]"]}]
var-definitions))))
var-definitions))))

(deftest analysis-is-valid-edn-test
(testing "solution for GH-476, CLJS with string require"
Expand Down
19 changes: 11 additions & 8 deletions test/clj_kondo/test_utils.clj
Expand Up @@ -34,14 +34,17 @@
[m1 m2]
(cond
(and (map? m1) (map? m2))
(every? (fn [[k v]] (and (contains? m2 k)
(if (or (identical? k :filename)
(identical? k :file))
(if (regex? v)
(re-find v (normalize-filename (get m2 k)))
(= (normalize-filename v)
(normalize-filename (get m2 k))))
(submap? v (get m2 k)))))
(every? (fn [[k v]]
(if (identical? v :submap/missing)
(not (contains? m2 k))
(and (contains? m2 k)
(if (or (identical? k :filename)
(identical? k :file))
(if (regex? v)
(re-find v (normalize-filename (get m2 k)))
(= (normalize-filename v)
(normalize-filename (get m2 k))))
(submap? v (get m2 k))))))
m1)
(regex? m1)
(re-find m1 m2)
Expand Down

0 comments on commit 4536247

Please sign in to comment.