|
62 | 62 | (def ^:dynamic *macro-infer* true)
|
63 | 63 | (def ^:dynamic *passes* nil)
|
64 | 64 | (def ^:dynamic *file-defs* nil)
|
| 65 | +(def ^:dynamic *private-var-access-nowarn* false) |
65 | 66 |
|
66 | 67 | (def constants-ns-sym
|
67 | 68 | "The namespace of the constants table as a symbol."
|
|
123 | 124 | {:preamble-missing true
|
124 | 125 | :unprovided true
|
125 | 126 | :undeclared-var true
|
| 127 | + :private-var-access true |
126 | 128 | :undeclared-ns true
|
127 | 129 | :undeclared-ns-form true
|
128 | 130 | :redef true
|
|
305 | 307 | "Use of undeclared Var ")
|
306 | 308 | (:prefix info) "/" (:suffix info)))
|
307 | 309 |
|
| 310 | +(defmethod error-message :private-var-access |
| 311 | + [warning-type info] |
| 312 | + (str "var: " (:sym info) " is not public")) |
| 313 | + |
308 | 314 | (defmethod error-message :undeclared-ns
|
309 | 315 | [warning-type {:keys [ns-sym js-provide] :as info}]
|
310 | 316 | (str "No such namespace: " ns-sym
|
|
969 | 975 | (node-module-dep? ns) :node
|
970 | 976 | (dep-has-global-exports? ns) :global))
|
971 | 977 |
|
972 |
| -(defmulti resolve* (fn [sym full-ns current-ns] (ns->module-type full-ns))) |
| 978 | +(defmulti resolve* (fn [env sym full-ns current-ns] (ns->module-type full-ns))) |
973 | 979 |
|
974 | 980 | (defmethod resolve* :js
|
975 |
| - [sym full-ns current-ns] |
| 981 | + [env sym full-ns current-ns] |
976 | 982 | {:name (symbol (str full-ns) (str (name sym)))
|
977 | 983 | :ns full-ns})
|
978 | 984 |
|
979 | 985 | (defmethod resolve* :node
|
980 |
| - [sym full-ns current-ns] |
| 986 | + [env sym full-ns current-ns] |
981 | 987 | {:name (symbol (str current-ns) (str (munge-node-lib full-ns) "." (name sym)))
|
982 | 988 | :ns current-ns})
|
983 | 989 |
|
984 | 990 | (defmethod resolve* :global
|
985 |
| - [sym full-ns current-ns] |
| 991 | + [env sym full-ns current-ns] |
986 | 992 | (let [pre (into '[Object] (->> (string/split (name sym) #"\.") (map symbol) vec))]
|
987 | 993 | (when-not (has-extern? pre)
|
988 | 994 | (swap! env/*compiler* update-in
|
|
991 | 997 | :ns current-ns
|
992 | 998 | :tag (with-meta 'js {:prefix pre})}))
|
993 | 999 |
|
| 1000 | +(def ^:private private-var-access-exceptions |
| 1001 | + "Specially-treated symbols for which we don't trigger :private-var-access warnings." |
| 1002 | + '#{cljs.core/checked-aget |
| 1003 | + cljs.core/checked-aset |
| 1004 | + cljs.core/checked-aget' |
| 1005 | + cljs.core/checked-aset'}) |
| 1006 | + |
994 | 1007 | (defmethod resolve* :default
|
995 |
| - [sym full-ns current-ns] |
996 |
| - (merge (gets @env/*compiler* ::namespaces full-ns :defs (symbol (name sym))) |
997 |
| - {:name (symbol (str full-ns) (str (name sym))) |
998 |
| - :ns full-ns})) |
| 1008 | + [env sym full-ns current-ns] |
| 1009 | + (let [sym-ast (gets @env/*compiler* ::namespaces full-ns :defs (symbol (name sym))) |
| 1010 | + sym-name (symbol (str full-ns) (str (name sym)))] |
| 1011 | + (when (and (not= current-ns full-ns) |
| 1012 | + (:private sym-ast) |
| 1013 | + (not *private-var-access-nowarn*) |
| 1014 | + (not (contains? private-var-access-exceptions sym-name))) |
| 1015 | + (warning :private-var-access env |
| 1016 | + {:sym sym-name})) |
| 1017 | + (merge sym-ast |
| 1018 | + {:name sym-name |
| 1019 | + :ns full-ns}))) |
999 | 1020 |
|
1000 | 1021 | (defn required? [ns env]
|
1001 | 1022 | (or (contains? (set (vals (gets env :ns :requires))) ns)
|
|
1070 | 1091 | (when (not= current-ns full-ns)
|
1071 | 1092 | (confirm-ns env full-ns))
|
1072 | 1093 | (confirm env full-ns (symbol (name sym))))
|
1073 |
| - (resolve* sym full-ns current-ns)) |
| 1094 | + (resolve* env sym full-ns current-ns)) |
1074 | 1095 |
|
1075 | 1096 | (dotted-symbol? sym)
|
1076 | 1097 | (let [idx (.indexOf s ".")
|
|
1090 | 1111 |
|
1091 | 1112 | (some? (gets @env/*compiler* ::namespaces current-ns :uses sym))
|
1092 | 1113 | (let [full-ns (gets @env/*compiler* ::namespaces current-ns :uses sym)]
|
1093 |
| - (resolve* sym full-ns current-ns)) |
| 1114 | + (resolve* env sym full-ns current-ns)) |
1094 | 1115 |
|
1095 | 1116 | (some? (gets @env/*compiler* ::namespaces current-ns :renames sym))
|
1096 | 1117 | (let [qualified-symbol (gets @env/*compiler* ::namespaces current-ns :renames sym)
|
1097 | 1118 | full-ns (symbol (namespace qualified-symbol))
|
1098 | 1119 | sym (symbol (name qualified-symbol))]
|
1099 |
| - (resolve* sym full-ns current-ns)) |
| 1120 | + (resolve* env sym full-ns current-ns)) |
1100 | 1121 |
|
1101 | 1122 | (some? (gets @env/*compiler* ::namespaces current-ns :imports sym))
|
1102 | 1123 | (recur env (gets @env/*compiler* ::namespaces current-ns :imports sym) confirm)
|
|
1352 | 1373 | [env sym]
|
1353 | 1374 | ;; we need to dissoc locals for the `(let [x 1] (def x x))` case, because we
|
1354 | 1375 | ;; want the var's AST and `resolve-var` will check locals first. - António Monteiro
|
1355 |
| - (let [env (dissoc env :locals) |
1356 |
| - var (resolve-var env sym (confirm-var-exists-throw)) |
1357 |
| - expr-env (assoc env :context :expr)] |
1358 |
| - (when-some [var-ns (:ns var)] |
1359 |
| - {:var (analyze expr-env sym) |
1360 |
| - :sym (analyze expr-env `(quote ~(symbol (name var-ns) (name (:name var))))) |
1361 |
| - :meta (var-meta var expr-env)}))) |
| 1376 | + (binding [*private-var-access-nowarn* true] |
| 1377 | + (let [env (dissoc env :locals) |
| 1378 | + var (resolve-var env sym (confirm-var-exists-throw)) |
| 1379 | + expr-env (assoc env :context :expr)] |
| 1380 | + (when-some [var-ns (:ns var)] |
| 1381 | + {:var (analyze expr-env sym) |
| 1382 | + :sym (analyze expr-env `(quote ~(symbol (name var-ns) (name (:name var))))) |
| 1383 | + :meta (var-meta var expr-env)})))) |
1362 | 1384 |
|
1363 | 1385 | (defmethod parse 'var
|
1364 | 1386 | [op env [_ sym :as form] _ _]
|
|
2104 | 2126 | [`(. ~target ~val) alt]
|
2105 | 2127 | [target val])]
|
2106 | 2128 | (disallowing-recur
|
2107 |
| - (let [enve (assoc env :context :expr) |
2108 |
| - texpr (cond |
2109 |
| - (symbol? target) |
2110 |
| - (do |
2111 |
| - (cond |
2112 |
| - (and (= target '*unchecked-if*) ;; TODO: proper resolve |
2113 |
| - (or (true? val) (false? val))) |
2114 |
| - (set! *unchecked-if* val) |
2115 |
| - |
2116 |
| - (and (= target '*unchecked-arrays*) ;; TODO: proper resolve |
2117 |
| - (or (true? val) (false? val))) |
2118 |
| - (set! *unchecked-arrays* val) |
2119 |
| - |
2120 |
| - (and (= target '*warn-on-infer*) |
2121 |
| - (or (true? val) (false? val))) |
2122 |
| - (set! *cljs-warnings* (assoc *cljs-warnings* :infer-warning val))) |
2123 |
| - (when (some? (:const (resolve-var (dissoc env :locals) target))) |
2124 |
| - (throw (error env "Can't set! a constant"))) |
2125 |
| - (let [local (-> env :locals target)] |
2126 |
| - (when-not (or (nil? local) |
2127 |
| - (and (:field local) |
2128 |
| - (or (:mutable local) |
2129 |
| - (:unsynchronized-mutable local) |
2130 |
| - (:volatile-mutable local)))) |
2131 |
| - (throw (error env "Can't set! local var or non-mutable field")))) |
2132 |
| - (analyze-symbol enve target)) |
2133 |
| - |
2134 |
| - :else |
2135 |
| - (when (seq? target) |
2136 |
| - (let [texpr (analyze-seq enve target nil)] |
2137 |
| - (when (:field texpr) |
2138 |
| - texpr)))) |
2139 |
| - vexpr (analyze enve val)] |
2140 |
| - (when-not texpr |
2141 |
| - (throw (error env "set! target must be a field or a symbol naming a var"))) |
2142 |
| - (cond |
2143 |
| - (and (not (:def-emits-var env)) ;; non-REPL context |
2144 |
| - (some? ('#{*unchecked-if* *unchecked-array* *warn-on-infer*} target))) |
2145 |
| - {:env env :op :no-op} |
2146 |
| - |
2147 |
| - :else |
2148 |
| - {:env env :op :set! :form form :target texpr :val vexpr |
2149 |
| - :children [:target :val]}))))) |
| 2129 | + (binding [*private-var-access-nowarn* true] |
| 2130 | + (let [enve (assoc env :context :expr) |
| 2131 | + texpr (cond |
| 2132 | + (symbol? target) |
| 2133 | + (do |
| 2134 | + (cond |
| 2135 | + (and (= target '*unchecked-if*) ;; TODO: proper resolve |
| 2136 | + (or (true? val) (false? val))) |
| 2137 | + (set! *unchecked-if* val) |
| 2138 | + |
| 2139 | + (and (= target '*unchecked-arrays*) ;; TODO: proper resolve |
| 2140 | + (or (true? val) (false? val))) |
| 2141 | + (set! *unchecked-arrays* val) |
| 2142 | + |
| 2143 | + (and (= target '*warn-on-infer*) |
| 2144 | + (or (true? val) (false? val))) |
| 2145 | + (set! *cljs-warnings* (assoc *cljs-warnings* :infer-warning val))) |
| 2146 | + (when (some? (:const (resolve-var (dissoc env :locals) target))) |
| 2147 | + (throw (error env "Can't set! a constant"))) |
| 2148 | + (let [local (-> env :locals target)] |
| 2149 | + (when-not (or (nil? local) |
| 2150 | + (and (:field local) |
| 2151 | + (or (:mutable local) |
| 2152 | + (:unsynchronized-mutable local) |
| 2153 | + (:volatile-mutable local)))) |
| 2154 | + (throw (error env "Can't set! local var or non-mutable field")))) |
| 2155 | + (analyze-symbol enve target)) |
| 2156 | + |
| 2157 | + :else |
| 2158 | + (when (seq? target) |
| 2159 | + (let [texpr (analyze-seq enve target nil)] |
| 2160 | + (when (:field texpr) |
| 2161 | + texpr)))) |
| 2162 | + vexpr (analyze enve val)] |
| 2163 | + (when-not texpr |
| 2164 | + (throw (error env "set! target must be a field or a symbol naming a var"))) |
| 2165 | + (cond |
| 2166 | + (and (not (:def-emits-var env)) ;; non-REPL context |
| 2167 | + (some? ('#{*unchecked-if* *unchecked-array* *warn-on-infer*} target))) |
| 2168 | + {:env env :op :no-op} |
| 2169 | + |
| 2170 | + :else |
| 2171 | + {:env env :op :set! :form form :target texpr :val vexpr |
| 2172 | + :children [:target :val]})))))) |
2150 | 2173 |
|
2151 | 2174 | #?(:clj (declare analyze-file))
|
2152 | 2175 |
|
|
3734 | 3757 | (if (and (not (namespace sym))
|
3735 | 3758 | (dotted-symbol? sym))
|
3736 | 3759 | sym
|
3737 |
| - (:name (resolve-var (assoc @env/*compiler* :ns (get-namespace *cljs-ns*)) sym)))) |
| 3760 | + (:name (binding [*private-var-access-nowarn* true] |
| 3761 | + (resolve-var (assoc @env/*compiler* :ns (get-namespace *cljs-ns*)) |
| 3762 | + sym))))) |
3738 | 3763 |
|
3739 | 3764 | #?(:clj
|
3740 | 3765 | (defn forms-seq*
|
|
0 commit comments