Skip to content

Commit 00e46fe

Browse files
author
dnolen
committed
CLJS-1785: Warn on reference to js/foo shadowed by local binding
1 parent 7ef1ed8 commit 00e46fe

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

src/main/clojure/cljs/analyzer.cljc

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@
138138
:ns-var-clash true
139139
:extend-type-invalid-method-shape true
140140
:unsupported-js-module-type true
141-
:unsupported-preprocess-value true})
141+
:unsupported-preprocess-value true
142+
:js-shadowed-by-local true})
142143

143144
(def js-reserved
144145
#{"arguments" "abstract" "boolean" "break" "byte" "case"
@@ -409,6 +410,10 @@
409410
(str "Unsupported preprocess value " preprocess " for foreign library "
410411
file "."))
411412

413+
(defmethod error-message :js-shadowed-by-local
414+
[warning-type {:keys [name]}]
415+
(str name " is shadowed by a local"))
416+
412417
(defn default-warning-handler [warning-type env extra]
413418
(when (warning-type *cljs-warnings*)
414419
(when-let [s (error-message warning-type extra)]
@@ -740,12 +745,15 @@
740745
warnings about unresolved vars."
741746
([env sym] (resolve-var env sym nil))
742747
([env sym confirm]
748+
(let [locals (:locals env)]
743749
(if #?(:clj (= "js" (namespace sym))
744750
:cljs (identical? "js" (namespace sym)))
745-
{:name sym :ns 'js}
746-
(let [s (str sym)
747-
lcls (:locals env)
748-
lb (get lcls sym)]
751+
(do
752+
(when (contains? locals (-> sym name symbol))
753+
(warning :js-shadowed-by-local env {:name sym}))
754+
{:name sym :ns 'js})
755+
(let [s (str sym)
756+
lb (get locals sym)]
749757
(cond
750758
(not (nil? lb)) lb
751759

@@ -771,7 +779,7 @@
771779
(let [idx (.indexOf s ".")
772780
prefix (symbol (subs s 0 idx))
773781
suffix (subs s (inc idx))
774-
lb (get lcls prefix)]
782+
lb (get locals prefix)]
775783
(if-not (nil? lb)
776784
{:name (symbol (str (:name lb)) suffix)}
777785
(let [cur-ns (-> env :ns :name)
@@ -816,7 +824,7 @@
816824
(confirm env full-ns sym))
817825
(merge (gets @env/*compiler* ::namespaces full-ns :defs sym)
818826
{:name (symbol (str full-ns) (str sym))
819-
:ns full-ns})))))))
827+
:ns full-ns}))))))))
820828

821829
(defn resolve-existing-var
822830
"Given env, an analysis environment, and sym, a symbol, resolve an existing var.

src/test/clojure/cljs/analyzer_tests.clj

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
[cljs.analyzer.api :as ana-api])
77
(:use clojure.test))
88

9+
(defn collecting-warning-handler [state]
10+
(fn [warning-type env extra]
11+
(when (warning-type a/*cljs-warnings*)
12+
(when-let [s (a/error-message warning-type extra)]
13+
(swap! state conj s)))))
14+
915
;;******************************************************************************
1016
;; cljs-warnings tests
1117
;;******************************************************************************
@@ -456,3 +462,12 @@
456462
{:excludes #{}
457463
:renames {}}))
458464
(is (set? (:excludes parsed)))))
465+
466+
(deftest test-cljs-1785-js-shadowed-by-local
467+
(let [ws (atom [])]
468+
(a/with-warning-handlers [(collecting-warning-handler ws)]
469+
(a/analyze ns-env
470+
'(fn [foo]
471+
(let [x js/foo]
472+
(println x)))))
473+
(is (.startsWith (first @ws) "js/foo is shadowed by a local"))))

0 commit comments

Comments
 (0)