Skip to content

Commit a0cadee

Browse files
committed
CLJS-2819: Warn on non-dynamic earmuffed vars
1 parent 9ffa2f7 commit a0cadee

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

src/main/clojure/cljs/analyzer.cljc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
:single-segment-namespace true
154154
:munged-namespace true
155155
:ns-var-clash true
156+
:non-dynamic-earmuffed-var true
156157
:extend-type-invalid-method-shape true
157158
:unsupported-js-module-type true
158159
:unsupported-preprocess-value true
@@ -467,6 +468,11 @@
467468
[warning-type {:keys [ns var] :as info}]
468469
(str "Namespace " ns " clashes with var " var))
469470

471+
(defmethod error-message :non-dynamic-earmuffed-var
472+
[warning-type {:keys [var] :as info}]
473+
(str var " not declared dynamic and thus is not dynamically rebindable, but its name "
474+
"suggests otherwise. Please either indicate ^:dynamic " var " or change the name"))
475+
470476
(defmethod error-message :extend-type-invalid-method-shape
471477
[warning-type {:keys [protocol method] :as info}]
472478
(str "Bad extend-type method shape for protocol " protocol " method " method
@@ -1602,6 +1608,18 @@
16021608
:set (into #{} (map const-expr->constant-value (:items e)))
16031609
:vector (into [] (map const-expr->constant-value (:items e)))))
16041610

1611+
(defn- earmuffed? [sym]
1612+
(let [s (name sym)]
1613+
(and (> (count s) 2)
1614+
(string/starts-with? s "*")
1615+
(string/ends-with? s "*"))))
1616+
1617+
(defn- core-ns? [ns-sym]
1618+
(let [s (name ns-sym)]
1619+
(and (not= 'cljs.user ns-sym)
1620+
(or (string/starts-with? s "cljs.")
1621+
(string/starts-with? s "clojure.")))))
1622+
16051623
(defmethod parse 'def
16061624
[op env form _ _]
16071625
(when (> (count form) 4)
@@ -1639,6 +1657,11 @@
16391657
(when-some [doc (:doc args)]
16401658
(when-not (string? doc)
16411659
(throw (error env "Too many arguments to def"))))
1660+
(when (and (not dynamic)
1661+
(earmuffed? sym)
1662+
(not (core-ns? ns-name)))
1663+
(warning :non-dynamic-earmuffed-var env
1664+
{:var (str sym)}))
16421665
(when-some [v (get-in @env/*compiler* [::namespaces ns-name :defs sym])]
16431666
(when (and (not *allow-redef*)
16441667
(not (:declared v))

src/test/clojure/cljs/analyzer_tests.clj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,3 +1737,10 @@
17371737
(is (= "global$module$react" (a/munge-global-export 'react)))
17381738
(is (= "global$module$_CIRCA_material_ui$core$styles" (a/munge-global-export "@material-ui/core/styles")))
17391739
(is (= "node$module$_CIRCA_material_ui$core$styles" (ana/munge-node-lib "@material-ui/core/styles"))))
1740+
1741+
(deftest test-cljs-2819
1742+
(let [ws (atom [])]
1743+
(a/with-warning-handlers [(collecting-warning-handler ws)]
1744+
(a/analyze ns-env
1745+
'(def *foo* 1)))
1746+
(is (string/starts-with? (first @ws) "*foo* not declared dynamic and thus"))))

0 commit comments

Comments
 (0)