|
11 | 11 | [cljs.analyzer :as ana] |
12 | 12 | [cljs.analyzer.api :as ana-api] |
13 | 13 | [cljs.compiler :as comp] |
14 | | - [cljs.closure :as closure] |
15 | 14 | [cljs.env :as env] |
16 | | - [cljs.externs :as externs] |
17 | 15 | [cljs.test-util :refer [unsplit-lines]] |
18 | 16 | [cljs.util :as util] |
19 | 17 | [clojure.java.io :as io] |
|
1493 | 1491 | (.getMessage (.getCause e)))) |
1494 | 1492 | "Argument to var must be symbol"))) |
1495 | 1493 |
|
1496 | | -(deftest test-has-extern?-basic |
1497 | | - (let [externs (externs/externs-map |
1498 | | - (closure/load-externs |
1499 | | - {:externs ["src/test/externs/test.js"] |
1500 | | - :use-only-custom-externs true}))] |
1501 | | - (is (true? (ana/has-extern? '[Foo] externs))) |
1502 | | - (is (true? (ana/has-extern? '[Foo wozMethod] externs))) |
1503 | | - (is (false? (ana/has-extern? '[foo] externs))) |
1504 | | - (is (false? (ana/has-extern? '[Foo gozMethod] externs))) |
1505 | | - (is (true? (ana/has-extern? '[baz] externs))) |
1506 | | - (is (false? (ana/has-extern? '[Baz] externs))))) |
1507 | | - |
1508 | | -(deftest test-has-extern?-defaults |
1509 | | - (let [externs (externs/externs-map)] |
1510 | | - (is (true? (ana/has-extern? '[console] externs))) |
1511 | | - (is (true? (ana/has-extern? '[console log] externs))) |
1512 | | - (is (true? (ana/has-extern? '[Number isNaN] externs))))) |
1513 | | - |
1514 | | -(def externs-cenv |
1515 | | - (atom |
1516 | | - {::ana/externs |
1517 | | - (externs/externs-map |
1518 | | - (closure/load-externs |
1519 | | - {:externs ["src/test/externs/test.js"]}))})) |
1520 | | - |
1521 | | -(deftest test-js-tag |
1522 | | - (let [externs (externs/externs-map |
1523 | | - (closure/load-externs |
1524 | | - {:externs ["src/test/externs/test.js"]}))] |
1525 | | - (is (= 'js/Console (ana/js-tag '[console] :tag externs))) |
1526 | | - (is (= 'js/Function (ana/js-tag '[console log] :tag externs))) |
1527 | | - (is (= 'js/Boolean (ana/js-tag '[Number isNaN] :ret-tag externs))) |
1528 | | - (is (= 'js/Foo (ana/js-tag '[baz] :ret-tag externs))))) |
1529 | | - |
1530 | | -(deftest test-externs-infer |
1531 | | - (is (= 'js/Foo |
1532 | | - (-> (binding [ana/*cljs-ns* ana/*cljs-ns*] |
1533 | | - (env/with-compiler-env externs-cenv |
1534 | | - (analyze (ana/empty-env) 'js/baz))) |
1535 | | - :info :ret-tag))) |
1536 | | - (is (= 'js/Foo |
1537 | | - (-> (binding [ana/*cljs-ns* ana/*cljs-ns*] |
1538 | | - (env/with-compiler-env externs-cenv |
1539 | | - (analyze (ana/empty-env) '(js/baz)))) |
1540 | | - :tag))) |
1541 | | - (is (= 'js |
1542 | | - (-> (binding [ana/*cljs-ns* ana/*cljs-ns*] |
1543 | | - (env/with-compiler-env externs-cenv |
1544 | | - (analyze (ana/empty-env) '(js/woz)))) |
1545 | | - :tag))) |
1546 | | - (is (= 'js |
1547 | | - (-> (binding [ana/*cljs-ns* ana/*cljs-ns*] |
1548 | | - (env/with-compiler-env externs-cenv |
1549 | | - (analyze (ana/empty-env) '(def foo (js/woz))))) |
1550 | | - :tag))) |
1551 | | - (is (= 'js |
1552 | | - (-> (binding [ana/*cljs-ns* ana/*cljs-ns*] |
1553 | | - (env/with-compiler-env externs-cenv |
1554 | | - (analyze (ana/empty-env) '(def foo js/boz)))) |
1555 | | - :tag))) |
1556 | | - (is (nil? (-> (binding [ana/*cljs-ns* ana/*cljs-ns*] |
1557 | | - (ana/no-warn |
1558 | | - (env/with-compiler-env externs-cenv |
1559 | | - (analyze (ana/empty-env) |
1560 | | - '(let [z (.baz ^js/Foo.Bar x)] |
1561 | | - z))))) |
1562 | | - :tag meta :prefix)))) |
1563 | | - |
1564 | 1494 | (deftest test-cljs-1871 |
1565 | 1495 | (let [ws (atom [])] |
1566 | 1496 | (try |
|
1695 | 1625 | #"Can't recur here" |
1696 | 1626 | (analyze test-env invalid-try-recur-form))))) |
1697 | 1627 |
|
1698 | | -(comment |
1699 | | - (binding [ana/*cljs-ns* ana/*cljs-ns*] |
1700 | | - (ana/no-warn |
1701 | | - (env/with-compiler-env externs-cenv |
1702 | | - (analyze (ana/empty-env) |
1703 | | - '(let [React (js/require "react")] |
1704 | | - React))))) |
1705 | | - |
1706 | | - ;; FIXME: we don't preserve tag information |
1707 | | - (binding [ana/*cljs-ns* ana/*cljs-ns*] |
1708 | | - (ana/no-warn |
1709 | | - (env/with-compiler-env externs-cenv |
1710 | | - (let [aenv (ana/empty-env) |
1711 | | - _ (analyze aenv '(ns foo.core)) |
1712 | | - aenv' (assoc-in aenv [:ns :name] 'foo.core) |
1713 | | - _ (ana/analyze aenv' '(def x 1))] |
1714 | | - (dissoc (ana/analyze-symbol (assoc-in aenv [:ns :name] 'foo.core) 'x) :env) |
1715 | | - ;(get-in @externs-cenv [::ana/namespaces 'foo.core]) |
1716 | | - )))) |
1717 | | - ) |
1718 | | - |
1719 | | -(def core-inferred |
1720 | | - ["var setTimeout;" "var process;" "process.hrtime;" |
1721 | | - "goog.isArrayLike;" "Java.type;" "Object.out;" "Object.out.println;" |
1722 | | - "Object.error;" "Object.error.println;"]) |
1723 | | - |
1724 | | -(defn infer-test-helper |
1725 | | - [{:keys [forms externs warnings warn js-dependency-index with-core? opts]}] |
1726 | | - (let [test-cenv (atom |
1727 | | - (cond-> |
1728 | | - (if with-core? |
1729 | | - (env/default-compiler-env* |
1730 | | - (closure/add-externs-sources (merge {:infer-externs true} opts))) |
1731 | | - {::ana/externs |
1732 | | - (externs/externs-map |
1733 | | - (closure/load-externs {:externs (or externs [])}))}) |
1734 | | - js-dependency-index (assoc :js-dependency-index js-dependency-index))) |
1735 | | - wrap (if with-core? |
1736 | | - #(comp/with-core-cljs nil %) |
1737 | | - #(do (%)))] |
1738 | | - (ana/with-warning-handlers [(collecting-warning-handler (or warnings (atom [])))] |
1739 | | - (binding [ana/*analyze-deps* false |
1740 | | - ana/*cljs-ns* ana/*cljs-ns*] |
1741 | | - (env/with-compiler-env test-cenv |
1742 | | - (wrap |
1743 | | - (fn [] |
1744 | | - (binding [ana/*analyze-deps* true |
1745 | | - ana/*cljs-warnings* |
1746 | | - (assoc ana/*cljs-warnings* |
1747 | | - :infer-warning (if (nil? warn) true warn))] |
1748 | | - (ana/analyze-form-seq forms)) |
1749 | | - (with-out-str |
1750 | | - (comp/emit-externs |
1751 | | - (reduce util/map-merge {} |
1752 | | - (map (comp :externs second) |
1753 | | - (get @test-cenv ::ana/namespaces)))))))))))) |
1754 | | - |
1755 | | -(deftest test-basic-infer |
1756 | | - (let [res (infer-test-helper |
1757 | | - {:forms '[(ns foo.core) |
1758 | | - (defn bar [a] (js/parseInt a)) |
1759 | | - (def c js/React.Component) |
1760 | | - (js/console.log "Hello world!") |
1761 | | - (fn [& args] |
1762 | | - (.apply (.-log js/console) js/console (into-array args))) |
1763 | | - (js/console.log js/Number.MAX_VALUE) |
1764 | | - (js/console.log js/Symbol.iterator)]})] |
1765 | | - (is (= (unsplit-lines ["var React;" "React.Component;"]) res)))) |
1766 | | - |
1767 | | -(deftest test-method-infer |
1768 | | - (let [res (infer-test-helper |
1769 | | - {:forms '[(defn foo [^js/React.Component c] |
1770 | | - (.render c))]})] |
1771 | | - (is (= (unsplit-lines ["var React;" "React.Component;" "React.Component.prototype.render;"]) |
1772 | | - res)))) |
1773 | | - |
1774 | | -(deftest test-minimal-infer |
1775 | | - (let [res (infer-test-helper |
1776 | | - {:forms '[(js/console.log (.wozMethod (js/baz)))] |
1777 | | - :externs ["src/test/externs/test.js"]})] |
1778 | | - (is (string/blank? res)))) |
1779 | | - |
1780 | | -(deftest test-type-hint-minimal-infer |
1781 | | - (let [res (infer-test-helper |
1782 | | - {:forms ''[(defn afun [^js/Foo x] |
1783 | | - (.wozMethod x))] |
1784 | | - :externs ["src/test/externs/test.js"]})] |
1785 | | - (is (string/blank? res)))) |
1786 | | - |
1787 | | -(deftest test-type-hint-infer-unknown-method-in-chain |
1788 | | - (let [ws (atom []) |
1789 | | - res (infer-test-helper |
1790 | | - {:forms '[(defn afun [^js/Foo.Bar x] |
1791 | | - (let [z (.baz x)] |
1792 | | - (.wozz z)))] |
1793 | | - :externs ["src/test/externs/test.js"] |
1794 | | - :warnings ws})] |
1795 | | - (is (= (unsplit-lines ["Foo.Boo.prototype.wozz;"]) res)) |
1796 | | - (is (= 1 (count @ws))) |
1797 | | - (is (string/starts-with? |
1798 | | - (first @ws) |
1799 | | - "Cannot resolve property wozz for inferred type js/Foo.Boo")))) |
1800 | | - |
1801 | | -(deftest test-type-hint-infer-unknown-property-in-chain |
1802 | | - (let [ws (atom []) |
1803 | | - res (infer-test-helper |
1804 | | - {:forms '[(defn afun [^js/Foo.Bar x] |
1805 | | - (let [z (.baz x)] |
1806 | | - (.-wozz z)))] |
1807 | | - :externs ["src/test/externs/test.js"] |
1808 | | - :warnings ws})] |
1809 | | - (is (= (unsplit-lines ["Foo.Boo.prototype.wozz;"]) res)) |
1810 | | - (is (= 1 (count @ws))) |
1811 | | - (is (string/starts-with? |
1812 | | - (first @ws) |
1813 | | - "Cannot resolve property wozz for inferred type js/Foo.Boo")))) |
1814 | | - |
1815 | | -(deftest test-type-hint-infer-unknown-method |
1816 | | - (let [ws (atom []) |
1817 | | - res (infer-test-helper |
1818 | | - {:forms '[(defn baz [^js/Foo a] |
1819 | | - (.gozMethod a))] |
1820 | | - :externs ["src/test/externs/test.js"] |
1821 | | - :warnings ws})] |
1822 | | - (is (= (unsplit-lines ["Foo.prototype.gozMethod;"]) res)) |
1823 | | - (is (= 1 (count @ws))) |
1824 | | - (is (string/starts-with? |
1825 | | - (first @ws) |
1826 | | - "Cannot resolve property gozMethod for inferred type js/Foo")))) |
1827 | | - |
1828 | | -(deftest test-infer-unknown-method-from-externs |
1829 | | - (let [ws (atom []) |
1830 | | - res (infer-test-helper |
1831 | | - {:forms '[(.gozMethod (js/baz))] |
1832 | | - :externs ["src/test/externs/test.js"] |
1833 | | - :warnings ws})] |
1834 | | - (is (= (unsplit-lines ["Foo.prototype.gozMethod;"]) res)) |
1835 | | - (is (= 1 (count @ws))) |
1836 | | - (is (string/starts-with? |
1837 | | - (first @ws) |
1838 | | - "Cannot resolve property gozMethod for inferred type js/Foo")))) |
1839 | | - |
1840 | | -(deftest test-infer-js-require |
1841 | | - (let [ws (atom []) |
1842 | | - res (infer-test-helper |
1843 | | - {:forms '[(ns foo.core) |
1844 | | - (def React (js/require "react")) |
1845 | | - (.log js/console (.-Component React))] |
1846 | | - :externs ["src/test/externs/test.js"] |
1847 | | - :warnings ws})] |
1848 | | - (is (= (unsplit-lines ["var require;" "Object.Component;"]) res)) |
1849 | | - (is (= 1 (count @ws))) |
1850 | | - (is (string/starts-with? |
1851 | | - (first @ws) |
1852 | | - "Adding extern to Object for property Component")))) |
1853 | | - |
1854 | | -(deftest test-set-warn-on-infer |
1855 | | - (let [ws (atom []) |
1856 | | - res (infer-test-helper |
1857 | | - {:forms '[(ns warn-on-infer-test.app) |
1858 | | - (set! *warn-on-infer* true) |
1859 | | - (defn wrap-baz [x] |
1860 | | - (.baz x))] |
1861 | | - :externs ["src/test/externs/test.js"] |
1862 | | - :warnings ws |
1863 | | - :warn false |
1864 | | - :with-core? true})] |
1865 | | - (is (= 1 (count @ws))) |
1866 | | - (is (string/starts-with? (first @ws) "Cannot infer target type")))) |
1867 | | - |
1868 | | -(deftest test-cljs-1970-infer-with-cljs-literals |
1869 | | - (let [ws (atom []) |
1870 | | - res (infer-test-helper |
1871 | | - {:forms '[(ns cjls-1970.core) |
1872 | | - (set! *warn-on-infer* true) |
1873 | | - (defn foo [] (list)) |
1874 | | - (defn bar [] (vector))] |
1875 | | - :externs ["src/test/externs/test.js"] |
1876 | | - :warnings ws |
1877 | | - :with-core? true})] |
1878 | | - (is (zero? (count @ws))))) |
1879 | | - |
1880 | | -(deftest test-cljs-1918-infer-with-case-keywords |
1881 | | - (let [ws (atom []) |
1882 | | - res (infer-test-helper |
1883 | | - {:forms '[(ns cjls-1918.core) |
1884 | | - (defn foo [x] |
1885 | | - (cljs.core/case x |
1886 | | - :foo 1 |
1887 | | - nil))] |
1888 | | - :externs ["src/test/externs/test.js"] |
1889 | | - :warnings ws |
1890 | | - :with-core? true})] |
1891 | | - (is (zero? (count @ws))))) |
1892 | | - |
1893 | | -(deftest test-cljs-2247 |
1894 | | - (let [ws (atom [])] |
1895 | | - (try |
1896 | | - (ana/with-warning-handlers [(collecting-warning-handler ws)] |
1897 | | - (env/with-compiler-env (assoc @test-cenv :repl-env {}) |
1898 | | - (ana/analyze (ana/empty-env) |
1899 | | - '(defn -foo [])) |
1900 | | - (ana/analyze (ana/empty-env) |
1901 | | - '(defprotocol IAlpha (-foo [this]))))) |
1902 | | - (catch Exception _)) |
1903 | | - (is (= ["Protocol IAlpha is overwriting function -foo"] @ws)))) |
1904 | | - |
1905 | | -(deftest test-cljs-2385-infer-priority |
1906 | | - (let [ws (atom []) |
1907 | | - res (infer-test-helper |
1908 | | - {:forms '[(ns cjls-1918.core) |
1909 | | - (defn thing [{:as this}] |
1910 | | - (.componentDidUpdate ^js/Thing this))] |
1911 | | - :externs ["src/test/externs/test.js"] |
1912 | | - :warnings ws |
1913 | | - :with-core? true})] |
1914 | | - (is (string/includes? res "Thing.prototype.componentDidUpdate;")) |
1915 | | - (is (zero? (count @ws))))) |
1916 | | - |
1917 | | -(deftest test-cljs-2392-broken-inferred-externs |
1918 | | - (let [ws (atom []) |
1919 | | - res (infer-test-helper |
1920 | | - {:forms '[(ns cjls-1918.core |
1921 | | - (:require [cljs.nodejs] |
1922 | | - [cljs.nodejscli]))] |
1923 | | - :warnings ws |
1924 | | - :with-core? true |
1925 | | - :opts {:target :nodejs}})] |
1926 | | - (not (string/includes? res "COMPILED")) |
1927 | | - (not (string/includes? res "goog")) |
1928 | | - (is (zero? (count @ws))))) |
1929 | | - |
1930 | | -(deftest test-cljs-2678-global-exports-infer |
1931 | | - (let [ws (atom []) |
1932 | | - res (infer-test-helper |
1933 | | - {:js-dependency-index {"react" {:global-exports '{react React}}} |
1934 | | - :forms '[(ns foo.core |
1935 | | - (:require [react :as react])) |
1936 | | - (.log js/console react/Component)] |
1937 | | - :warnings ws |
1938 | | - :warn false})] |
1939 | | - (is (= (unsplit-lines ["Object.Component;"]) res)))) |
1940 | | - |
1941 | | -(deftest test-cljs-2767-deftype-defrecord |
1942 | | - (let [ws (atom []) |
1943 | | - res (infer-test-helper |
1944 | | - {:forms '[(ns cjls-2767.core) |
1945 | | - (defrecord Foo [])] |
1946 | | - :externs ["src/test/externs/test.js"] |
1947 | | - :warnings ws |
1948 | | - :with-core? true})] |
1949 | | - (is (empty? @ws)) |
1950 | | - (is (not (string/includes? res "cljs.core")))) |
1951 | | - (let [ws (atom []) |
1952 | | - res (infer-test-helper |
1953 | | - {:forms '[(ns cjls-2767.core) |
1954 | | - (deftype Foo [])] |
1955 | | - :externs ["src/test/externs/test.js"] |
1956 | | - :warnings ws |
1957 | | - :with-core? true})] |
1958 | | - (is (empty? @ws)) |
1959 | | - (is (not (string/includes? res "cljs.core"))))) |
1960 | | - |
1961 | | -(deftest test-cljs-2790-defrecord-fields |
1962 | | - (let [ws (atom []) |
1963 | | - res (infer-test-helper |
1964 | | - {:forms '[(ns cjls-2790.core) |
1965 | | - (defrecord Foo [a b])] |
1966 | | - :externs ["src/test/externs/test.js"] |
1967 | | - :warnings ws |
1968 | | - :with-core? true})] |
1969 | | - (is (empty? @ws)) |
1970 | | - (is (not (string/includes? res "cljs.core"))))) |
1971 | | - |
1972 | 1628 | (deftest test-locals-mapped-to-sym |
1973 | 1629 | (testing "analyze should be robust to :locals mapping to symbols" |
1974 | 1630 | (is (= [:local 'a] (-> (analyze (assoc-in test-env [:locals 'a] 'foo) 'a) |
|
2137 | 1793 | (is (= w2 "cljs.core/-, all arguments must be numbers, got [string] instead")) |
2138 | 1794 | (is (= w3 "cljs.core//, all arguments must be numbers, got [number string] instead")) |
2139 | 1795 | (is (= w4 "cljs.core/*, all arguments must be numbers, got [string] instead"))))) |
2140 | | - |
2141 | | -(deftest test-cljs-3181 |
2142 | | - (let [ws (atom []) |
2143 | | - res (binding [ana/*cljs-static-fns* true] |
2144 | | - (infer-test-helper |
2145 | | - {:forms '[(ns warn-on-infer-test.app) |
2146 | | - (set! *warn-on-infer* true) |
2147 | | - (defn f [gfn] |
2148 | | - (.then ^js/Promise (gfn (inc 1)) identity))] |
2149 | | - :externs ["src/test/externs/test.js"] |
2150 | | - :warnings ws |
2151 | | - :warn false |
2152 | | - :with-core? true}))] |
2153 | | - (is (empty? @ws)))) |
0 commit comments