babashka/test-resources/lib_tests/rewrite_clj/node/coercer_test.cljc
2021-04-04 16:22:45 +02:00

192 lines
6.9 KiB
Clojure

(ns rewrite-clj.node.coercer-test
(:require [clojure.test :refer [deftest testing is are]]
[rewrite-clj.node :as node]
[rewrite-clj.parser :as p]))
(deftest t-sexpr->node->sexpr-roundtrip
(testing "simple cases roundtrip"
(are [?sexpr expected-tag ]
(let [n (node/coerce ?sexpr)]
(is (node/node? n))
(is (= ?sexpr (node/sexpr n)))
(is (string? (node/string n)))
(is (= expected-tag (node/tag n)) "tag")
(is (not (meta n)))
(is (= (type ?sexpr) (type (node/sexpr n)))))
;; numbers
;; note that we do have an integer-node, but rewrite-clj never parses to it
;; so we never coerce to it either
3 :token ;;:token
3N :token ;;:token
3.14 :token ;;:token
3.14M :token ;;:token
3e14 :token ;;:token
;; ratios are not valid in cljs
#?@(:clj [3/4 :token ;;:token
]
)
;; symbol/keyword/string/...
'symbol :token ;;:symbol
'namespace/symbol :token ;;:symbol
:keyword :token ;;:keyword
:1.5.1 :token ;;:keyword
::keyword :token ;;:keyword
::1.5.1 :token ;;:keyword
:namespace/keyword :token ;;:keyword
"" :token ;;:string
"hello, over there!" :token ;;:string
"multi\nline" :multi-line ;;:string
" " :token ;;:string
"\n" :multi-line ;;:string
"\n\n" :multi-line ;;:string
"," :token ;;:string
;; seqs
[] :vector ;;:seq
[1 2 3] :vector ;;:seq
() :list ;;:seq
'() :list ;;:seq
(list 1 2 3) :list ;;:seq
#{} :set ;;:seq
#{1 2 3} :set ;;:seq
;; date
#inst "2014-11-26T00:05:23" :token ;; :token
))
(testing "multi-line string newline variants are normalized"
(let [s "hey\nyou\rover\r\nthere"
n (node/coerce s)]
(is (= "hey\nyou\nover\nthere" (node/sexpr n))))))
(deftest
t-quoted-list-reader-location-metadata-elided
(are [?sexpr expected-meta-keys]
(let [n (node/coerce ?sexpr)]
(is (node/node? n))
(is (= expected-meta-keys (node/string n)))
(is (string? (node/string n)))
(is (= ?sexpr (node/sexpr n)))
(is (not (meta n)))
(is (= (type ?sexpr) (type (node/sexpr n)))))
'(1 2 3) "(1 2 3)"
'^:other-meta (4 5 6) "^{:other-meta true} (4 5 6)"))
(deftest t-maps
(are [?sexpr]
(let [n (node/coerce ?sexpr)]
(is (node/node? n))
(is (= :map (node/tag n)))
;; (is (= :seq protocols/node-type n))
(is (string? (node/string n)))
(is (= ?sexpr (node/sexpr n)))
;; we do not restore to original map (hash-map or array-map),
;; checking if we convert to any map is sufficient
(is (map? (node/sexpr n))))
{}
{:a 1 :b 2}
(hash-map)
(hash-map :a 0 :b 1)
(array-map)
(array-map :d 4 :e 5)))
(deftest t-namespaced-maps-coerce-to-maps
(are [?sexpr]
(let [n (node/coerce ?sexpr)]
(is (node/node? n))
(is (= :map (node/tag n)))
;; (is (= :seq (protocols/node-type n)))
(is (string? (node/string n)))
(is (= ?sexpr (node/sexpr n)))
(is (map? (node/sexpr n))))
#:prefix {:a 1 :b 2}
#::{:c 3 :d 4}
#::p{:e 5 :f 6}))
(deftest t-sexpr->node->sexpr-roundtrip-for-regex
(are [?in]
(let [n (node/coerce ?in)]
(is (node/node? n))
(is (= :regex (node/tag n)))
;; (is (= :regex (protocols/node-type n)))
(is (string? (node/string n)))
#_(is (= (list 're-pattern (regex/pattern-string-for-regex ?in))
(node/sexpr n))))
#"abc"
#"a\nb\nc"
#"a\.\s*"
#"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"))
#_(deftest
^:skip-for-sci ;; sci, by design has its own var type, so skip this one for sci
t-vars
(let [n (node/coerce #'identity)]
(is (node/node? n))
(is (= :var (node/tag n)))
#_(is (= :reader (protocols/node-type n)))
(is (= '(var #?(:clj clojure.core/identity :cljs cljs.core/identity)) (node/sexpr n)))))
(deftest t-nil
(let [n (node/coerce nil)]
(is (node/node? n))
(is (= :token (node/tag n)))
#_(is (= :token (protocols/node-type n)))
(is (= nil (node/sexpr n)))
(is (= n (p/parse-string "nil")))))
(defrecord Foo-Bar [a])
#_(deftest
^:skip-for-sci ;; records have special metadata in sci, so skip this one for sci
t-records
(let [v (Foo-Bar. 0)
n (node/coerce v)]
(is (node/node? n))
;; records are represented by rewrite-clj reader macro nodes
(is (= :reader-macro (node/tag n)))
(is (= (pr-str v) (node/string n)))))
(deftest t-nodes-coerce-to-themselves
(testing "parsed nodes"
;; lean on the parser to create node structures
(are [?s ?tag #_?type]
(let [n (p/parse-string ?s)]
(is (= n (node/coerce n)))
(is (= ?tag (node/tag n)))
#_(is (= ?type (protocols/node-type n))))
";; comment" :comment ;;:comment
"#! comment" :comment ;;:comment
"#(+ 1 %)" :fn ;;:fn
":my-kw" :token ;;:keyword
"^:m1 [1 2 3]" :meta ;;:meta
"#:p1{:a 1 :b 2}" :namespaced-map ;;:namespaced-map
"'a" :quote ;;:quote
"#'var" :var ;;:reader
"#=eval" :eval ;;:reader
"@deref" :deref ;;:deref
"#mymacro 44" :reader-macro ;;:reader-macro
"#\"regex\"" :regex ;;:regex
"[1 2 3]" :vector ;;:seq
"42" :token ;;:token
"sym" :token ;;:symbol
"#_ 99" :uneval ;;:uneval
" " :whitespace ;;:whitespace
"," :comma ;;:comma
"\n" :newline ;;:newline
))
(testing "parsed forms nodes"
(let [n (p/parse-string-all "(def a 1)")]
(is (= n (node/coerce n)))
(is (= :forms (node/tag n)))))
(testing "map qualifier node"
(let [n (node/map-qualifier-node false "prefix")]
(is (= n (node/coerce n)))))
(testing "nodes that are not parsed, but can be created manually"
(let [n (node/integer-node 10)]
(is (= n (node/coerce n))))
(let [n (node/string-node "my-string")]
(is (= n (node/coerce n))))))