|
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)
|
|
1359 | 1380 | [env sym]
|
1360 | 1381 | ;; we need to dissoc locals for the `(let [x 1] (def x x))` case, because we
|
1361 | 1382 | ;; want the var's AST and `resolve-var` will check locals first. - António Monteiro
|
1362 |
| - (let [env (dissoc env :locals) |
1363 |
| - var (resolve-var env sym (confirm-var-exists-throw)) |
1364 |
| - expr-env (assoc env :context :expr)] |
1365 |
| - (when-some [var-ns (:ns var)] |
1366 |
| - {:var (analyze expr-env sym) |
1367 |
| - :sym (analyze expr-env `(quote ~(symbol (name var-ns) (name (:name var))))) |
1368 |
| - :meta (var-meta var expr-env)}))) |
| 1383 | + (binding [*private-var-access-nowarn* true] |
| 1384 | + (let [env (dissoc env :locals) |
| 1385 | + var (resolve-var env sym (confirm-var-exists-throw)) |
| 1386 | + expr-env (assoc env :context :expr)] |
| 1387 | + (when-some [var-ns (:ns var)] |
| 1388 | + {:var (analyze expr-env sym) |
| 1389 | + :sym (analyze expr-env `(quote ~(symbol (name var-ns) (name (:name var))))) |
| 1390 | + :meta (var-meta var expr-env)})))) |
1369 | 1391 |
|
1370 | 1392 | (defmethod parse 'var
|
1371 | 1393 | [op env [_ sym :as form] _ _]
|
|
1619 | 1641 | (analyze (assoc env :context :expr) (:init args) sym))))
|
1620 | 1642 | fn-var? (and (some? init-expr) (= (:op init-expr) :fn))
|
1621 | 1643 | tag (if fn-var?
|
1622 |
| - (or (:ret-tag init-expr) tag) |
| 1644 | + (or (:ret-tag init-expr) tag (:inferred-ret-tag init-expr)) |
1623 | 1645 | (or tag (:tag init-expr)))
|
1624 | 1646 | export-as (when-let [export-val (-> sym meta :export)]
|
1625 | 1647 | (if (= true export-val) var-name export-val))
|
|
1860 | 1882 | children (if (some? name-var)
|
1861 | 1883 | [:local :methods]
|
1862 | 1884 | [:methods])
|
| 1885 | + inferred-ret-tag (let [inferred-tags (map (partial infer-tag env) (map :body methods))] |
| 1886 | + (when (apply = inferred-tags) |
| 1887 | + (first inferred-tags))) |
1863 | 1888 | ast (merge {:op :fn
|
1864 | 1889 | :env env
|
1865 | 1890 | :form form
|
1866 | 1891 | :name name-var
|
1867 | 1892 | :methods methods
|
1868 | 1893 | :variadic? variadic
|
1869 | 1894 | :tag 'function
|
| 1895 | + :inferred-ret-tag inferred-ret-tag |
1870 | 1896 | :recur-frames *recur-frames*
|
1871 | 1897 | :loop-lets *loop-lets*
|
1872 | 1898 | :jsdoc [js-doc]
|
|
2135 | 2161 | [`(. ~target ~val) alt]
|
2136 | 2162 | [target val])]
|
2137 | 2163 | (disallowing-recur
|
2138 |
| - (let [enve (assoc env :context :expr) |
2139 |
| - texpr (cond |
2140 |
| - (symbol? target) |
2141 |
| - (do |
2142 |
| - (cond |
2143 |
| - (and (= target '*unchecked-if*) ;; TODO: proper resolve |
2144 |
| - (or (true? val) (false? val))) |
2145 |
| - (set! *unchecked-if* val) |
2146 |
| - |
2147 |
| - (and (= target '*unchecked-arrays*) ;; TODO: proper resolve |
2148 |
| - (or (true? val) (false? val))) |
2149 |
| - (set! *unchecked-arrays* val) |
2150 |
| - |
2151 |
| - (and (= target '*warn-on-infer*) |
2152 |
| - (or (true? val) (false? val))) |
2153 |
| - (set! *cljs-warnings* (assoc *cljs-warnings* :infer-warning val))) |
2154 |
| - (when (some? (:const (resolve-var (dissoc env :locals) target))) |
2155 |
| - (throw (error env "Can't set! a constant"))) |
2156 |
| - (let [local (-> env :locals target)] |
2157 |
| - (when-not (or (nil? local) |
2158 |
| - (and (:field local) |
2159 |
| - (or (:mutable local) |
2160 |
| - (:unsynchronized-mutable local) |
2161 |
| - (:volatile-mutable local)))) |
2162 |
| - (throw (error env "Can't set! local var or non-mutable field")))) |
2163 |
| - (analyze-symbol enve target)) |
2164 |
| - |
2165 |
| - :else |
2166 |
| - (when (seq? target) |
2167 |
| - (let [texpr (analyze-seq enve target nil)] |
2168 |
| - (when (:field texpr) |
2169 |
| - texpr)))) |
2170 |
| - vexpr (analyze enve val)] |
2171 |
| - (when-not texpr |
2172 |
| - (throw (error env "set! target must be a field or a symbol naming a var"))) |
2173 |
| - (cond |
2174 |
| - (and (not (:def-emits-var env)) ;; non-REPL context |
2175 |
| - (some? ('#{*unchecked-if* *unchecked-array* *warn-on-infer*} target))) |
2176 |
| - {:env env :op :no-op} |
2177 |
| - |
2178 |
| - :else |
2179 |
| - {:env env :op :set! :form form :target texpr :val vexpr |
2180 |
| - :children [:target :val]}))))) |
| 2164 | + (binding [*private-var-access-nowarn* true] |
| 2165 | + (let [enve (assoc env :context :expr) |
| 2166 | + texpr (cond |
| 2167 | + (symbol? target) |
| 2168 | + (do |
| 2169 | + (cond |
| 2170 | + (and (= target '*unchecked-if*) ;; TODO: proper resolve |
| 2171 | + (or (true? val) (false? val))) |
| 2172 | + (set! *unchecked-if* val) |
| 2173 | + |
| 2174 | + (and (= target '*unchecked-arrays*) ;; TODO: proper resolve |
| 2175 | + (or (true? val) (false? val))) |
| 2176 | + (set! *unchecked-arrays* val) |
| 2177 | + |
| 2178 | + (and (= target '*warn-on-infer*) |
| 2179 | + (or (true? val) (false? val))) |
| 2180 | + (set! *cljs-warnings* (assoc *cljs-warnings* :infer-warning val))) |
| 2181 | + (when (some? (:const (resolve-var (dissoc env :locals) target))) |
| 2182 | + (throw (error env "Can't set! a constant"))) |
| 2183 | + (let [local (-> env :locals target)] |
| 2184 | + (when-not (or (nil? local) |
| 2185 | + (and (:field local) |
| 2186 | + (or (:mutable local) |
| 2187 | + (:unsynchronized-mutable local) |
| 2188 | + (:volatile-mutable local)))) |
| 2189 | + (throw (error env "Can't set! local var or non-mutable field")))) |
| 2190 | + (analyze-symbol enve target)) |
| 2191 | + |
| 2192 | + :else |
| 2193 | + (when (seq? target) |
| 2194 | + (let [texpr (analyze-seq enve target nil)] |
| 2195 | + (when (:field texpr) |
| 2196 | + texpr)))) |
| 2197 | + vexpr (analyze enve val)] |
| 2198 | + (when-not texpr |
| 2199 | + (throw (error env "set! target must be a field or a symbol naming a var"))) |
| 2200 | + (cond |
| 2201 | + (and (not (:def-emits-var env)) ;; non-REPL context |
| 2202 | + (some? ('#{*unchecked-if* *unchecked-array* *warn-on-infer*} target))) |
| 2203 | + {:env env :op :no-op} |
| 2204 | + |
| 2205 | + :else |
| 2206 | + {:env env :op :set! :form form :target texpr :val vexpr |
| 2207 | + :children [:target :val]})))))) |
2181 | 2208 |
|
2182 | 2209 | #?(:clj (declare analyze-file))
|
2183 | 2210 |
|
|
3770 | 3797 | (if (and (not (namespace sym))
|
3771 | 3798 | (dotted-symbol? sym))
|
3772 | 3799 | sym
|
3773 |
| - (:name (resolve-var (assoc @env/*compiler* :ns (get-namespace *cljs-ns*)) sym)))) |
| 3800 | + (:name (binding [*private-var-access-nowarn* true] |
| 3801 | + (resolve-var (assoc @env/*compiler* :ns (get-namespace *cljs-ns*)) |
| 3802 | + sym))))) |
3774 | 3803 |
|
3775 | 3804 | #?(:clj
|
3776 | 3805 | (defn forms-seq*
|
|
0 commit comments