-
Notifications
You must be signed in to change notification settings - Fork 12
/
evil-textobj-tree-sitter-test.el
254 lines (214 loc) · 11.2 KB
/
evil-textobj-tree-sitter-test.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
;;; evil-textobj-tree-sitter-test.el --- Tests for evil-textobj-tree-sitter -*- lexical-binding: t -*-
;;; Commentary:
;; We can only use statically linked files here or libstdc++ screams at you.
;; C is an ideal candidate for this as it is builtin and is statically linked.
;;; Code:
(require 'tree-sitter-langs)
(require 'evil-textobj-tree-sitter)
(require 'go-mode)
(setq treesit-language-source-alist
'((c . ("https://github.com/tree-sitter/tree-sitter-c"))
(cpp . ("https://github.com/tree-sitter/tree-sitter-cpp"))
(python . ("https://github.com/tree-sitter/tree-sitter-python"))
(go . ("https://github.com/tree-sitter/tree-sitter-go"))
(gomod . ("https://github.com/camdencheek/tree-sitter-go-mod.git"))))
(treesit-install-language-grammar 'c)
(treesit-install-language-grammar 'cpp)
(treesit-install-language-grammar 'python)
(treesit-install-language-grammar 'go)
(treesit-install-language-grammar 'gomod)
(defvar evil-textobj-tree-sitter--test-file-content
'((c-simple . "// Lukasz
int main() {
printf(\"hello\")
}")
(c-multiple-funcs . "// mango
int main() {
printf(\"hello\")
}
int main2() {
printf(\"hello2\")
}
")
(c-unicode . "// Łukasz
int main() {
printf(\"hello\")
}")
(c-multibyte . "// Комментарий
int main(int temp, int temp2) {
printf(\"hello\");
}")
(go-multibyte-code . "// Комментарий
func main(int Комментарий, int temp2) {
printf(\"hello\");
}")
(go-nested . "// comment
func main() {
fmt.Println(\"howdy bruh!\")
func() {
fmt.Println(\"yo!\")
}
}")
(py-complex . "def func ():
var1
def func2(): pass
def nested():
var2
def inner():
var3
var4
var5
")))
(defun evil-textobj-tree-sitter--range-test (mode treesit start textobj range content)
"Check ranges of tree-sitter targets.
`MODE' is the `major-mode' to be used.
`TREESIT' non nil will use `treesit'.
`CONTENT' is the content to be used.
`START' is the starting position.
`TEXTOBJ' is the textobject to check.
`RANGE' is the range that should be returned."
(let* ((bufname (make-temp-name "evil-textobj-tree-sitter-test--"))
(buffer (get-buffer-create bufname)))
(with-current-buffer buffer
(insert (alist-get content evil-textobj-tree-sitter--test-file-content))
(funcall mode)
(if (not treesit) (tree-sitter-mode))
(message "%s" major-mode)
(goto-char start)
(should (equal
(evil-textobj-tree-sitter--range 1 (list (intern textobj)))
range)))
(kill-buffer buffer)))
(ert-deftest evil-textobj-tree-sitter-within-unicode-test ()
"Check inner range queries within unicode buffers."
;; function.inner selects brackets in treesit queries but not in tree-sitter ones
(evil-textobj-tree-sitter--range-test 'c-mode nil 31 "function.inner" (cons 28 43) 'c-unicode)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 31 "function.inner" (cons 22 45) 'c-unicode))
(ert-deftest evil-textobj-tree-sitter-within-unicode-test-outer ()
"Check outer range queries within unicode buffers."
(evil-textobj-tree-sitter--range-test 'c-mode nil 31 "function.outer" (cons 11 45) 'c-unicode)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 31 "function.outer" (cons 11 45) 'c-unicode))
(ert-deftest evil-textobj-tree-sitter-within-multibyte-buffers ()
"Check range in multibyte comment before."
(evil-textobj-tree-sitter--range-test 'c-mode nil 35 "parameter.inner" (cons 35 44) 'c-multibyte)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 35 "parameter.inner" (cons 35 44) 'c-multibyte))
(ert-deftest evil-textobj-tree-sitter-within-unicode-test3 ()
"Check range with multibyte code."
(evil-textobj-tree-sitter--range-test 'go-mode nil 31 "parameter.inner" (cons 26 41) 'go-multibyte-code)
(evil-textobj-tree-sitter--range-test 'go-ts-mode t 31 "parameter.inner" (cons 26 41) 'go-multibyte-code))
(ert-deftest evil-textobj-tree-sitter-within-test ()
"Check range when we are within the textobj with buffer having only ASCII chars."
(evil-textobj-tree-sitter--range-test 'c-mode nil 31 "function.outer" (cons 11 45) 'c-simple)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 31 "function.outer" (cons 11 45) 'c-simple))
(ert-deftest evil-textobj-tree-sitter-lookahed-test ()
"Check range when we are before the textobj with buffer having only ASCII chars."
(evil-textobj-tree-sitter--range-test 'c-mode nil 1 "function.outer" (cons 11 45) 'c-simple)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 1 "function.outer" (cons 11 45) 'c-simple))
(ert-deftest evil-textobj-tree-sitter-right-at-start-test ()
"Checking for off by one errors at start."
(evil-textobj-tree-sitter--range-test 'c-mode nil 11 "function.outer" (cons 11 45) 'c-simple)
(evil-textobj-tree-sitter--range-test 'c-ts-mode t 11 "function.outer" (cons 11 45) 'c-simple))
;;; Reading query files
(ert-deftest evil-textoj-tree-sitter-check-query-read-simple ()
"Simple query read check."
(let ((evil-textobj-tree-sitter--get-queries-dir-func (lambda () "fixtures/")))
(should (string-prefix-p ";; \"Classes\"" (evil-textobj-tree-sitter--get-query "zig")))))
(ert-deftest evil-textoj-tree-sitter-check-query-read-nocomment ()
"Check a query file with no comment."
(let ((evil-textobj-tree-sitter--get-queries-dir-func (lambda () "fixtures/")))
(should (string-prefix-p "(function_definition" (evil-textobj-tree-sitter--get-query "bash")))))
(ert-deftest evil-textoj-tree-sitter-check-query-read-nested ()
"Check a query with nested files to be loaded."
(let ((evil-textobj-tree-sitter--get-queries-dir-func (lambda () "fixtures/")))
(should (string-prefix-p "; inherits: (jsx)" (evil-textobj-tree-sitter--get-query "typescript")))))
(ert-deftest evil-textoj-tree-sitter-check-query-read-nested-nofile ()
"Check a file pointing to a non existent file."
(let ((evil-textobj-tree-sitter--get-queries-dir-func (lambda () "fixtures/")))
(should (string-prefix-p "; inherits: (jsx)" (evil-textobj-tree-sitter--get-query "javascript")))))
(ert-deftest evil-textoj-tree-sitter-check-query-read-nested-multi ()
"Check a query with multiple nesting items."
(let ((evil-textobj-tree-sitter--get-queries-dir-func (lambda () "fixtures/")))
(should (string-prefix-p "; inherits: (javascript)" (evil-textobj-tree-sitter--get-query "tsx")))))
(ert-deftest evil-textoj-tree-sitter-check-query-read-non-top-level ()
"Check a non top level direct query."
(should (string-prefix-p "; inherits: (javascript)" (evil-textobj-tree-sitter--get-query-from-dir "typescript" "fixtures/" nil))))
(defun evil-textobj-tree-sitter--goto-test (mode treesit start textobj pos prev end content)
"Check for location of goto actions.
`MODE' is the `major-mode' to be used.
`TREESIT' non nil will use `treesit'.
`CONTENT' is the content to be used.
`START' is the starting position.
`TEXTOBJ' is the textobject to check.
`PREV' goes to previous textobj.
`END' goes to end of textobj.
`POS' is the position that should be returned."
(let* ((bufname (make-temp-name "evil-textobj-tree-sitter-test--"))
(buffer (get-buffer-create bufname)))
(with-current-buffer buffer
(insert (alist-get content evil-textobj-tree-sitter--test-file-content))
(funcall mode)
(if (not treesit) (tree-sitter-mode))
(goto-char start)
(should (equal (evil-textobj-tree-sitter--get-goto-location
(list (intern textobj)) prev end nil)
pos)))
(kill-buffer bufname)))
(ert-deftest evil-textobj-tree-sitter-goto-next-start-simple ()
"Go to next start in ASCII buffers."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 1 "function.outer" 11 nil nil 'c-simple)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 1 "function.outer" 11 nil nil 'c-simple))
(ert-deftest evil-textobj-tree-sitter-goto-next-start-multiple-textobjects ()
"Check to see if we are able to find first one when we have multiple textobjects."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 1 "parameter.outer" 25 nil nil 'c-multibyte)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 1 "parameter.outer" 25 nil nil 'c-multibyte))
(ert-deftest evil-textobj-tree-sitter-goto-next-end-simple ()
"Check if we can navigate to end of a textobj."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 1 "function.outer" 69 nil t 'c-multibyte)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 1 "function.outer" 69 nil t 'c-multibyte))
(ert-deftest evil-textobj-tree-sitter-goto-next-end-multi ()
"Goto end when we have multiple functions."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 1 "function.outer" 43 nil t 'c-multiple-funcs)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 1 "function.outer" 43 nil t 'c-multiple-funcs))
(ert-deftest evil-textobj-tree-sitter-goto-previous-end-multi ()
"Goto end of previous textobj."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 69 "function.outer" 43 t t 'c-multiple-funcs)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 69 "function.outer" 43 t t 'c-multiple-funcs))
(ert-deftest evil-textobj-tree-sitter-goto-previous-end-multi-on-end ()
"Testing going to end of previous one while on end of current one."
(evil-textobj-tree-sitter--goto-test 'c-mode nil 82 "function.outer" 43 t t 'c-multiple-funcs)
(evil-textobj-tree-sitter--goto-test 'c-ts-mode t 82 "function.outer" 43 t t 'c-multiple-funcs))
(ert-deftest evil-textobj-tree-sitter-goto-previous-start-nested ()
"Goto the start of the previous textobj in a nested scenario."
(evil-textobj-tree-sitter--goto-test 'go-mode nil 66 "function.outer" 55 t nil 'go-nested)
(evil-textobj-tree-sitter--goto-test 'go-ts-mode t 66 "function.outer" 55 t nil 'go-nested))
(ert-deftest evil-textobj-tree-sitter-goto-previous-start-nested-3 ()
"Go to previous nested complex test."
(evil-textobj-tree-sitter--goto-test 'python-mode nil 71 "function.outer" 49 t nil 'py-complex)
(evil-textobj-tree-sitter--goto-test 'python-ts-mode t 71 "function.outer" 49 t nil 'py-complex))
;;; `thing-at-point' tests
(defun evil-textobj-tree-sitter--thing-at-point-test (mode treesit start thing content selection range)
"Check ranges of tree-sitter targets.
`MODE' is the `major-mode' to be used.
`TREESIT' non nil will use `treesit'.
`CONTENT' is the content to be used.
`START' is the starting position.
`THING' is the thing to select.
`SELECTION' is the selection that `thing-at-point' will return."
(let* ((bufname (make-temp-name "evil-textobj-tree-sitter-test--"))
(buffer (get-buffer-create bufname)))
(with-current-buffer buffer
(insert (alist-get content evil-textobj-tree-sitter--test-file-content))
(funcall mode)
(if (not treesit) (tree-sitter-mode))
(goto-char start)
(should (equal (thing-at-point thing t) selection))
(should (equal (bounds-of-thing-at-point thing) range)))
(kill-buffer bufname)))
(ert-deftest evil-textobj-tree-sitter-thing-at-point ()
"Check if `thing-at-point' returns correct result."
(let ((selection "int main() {
printf(\"hello\")
}"))
(evil-textobj-tree-sitter--thing-at-point-test 'c-mode nil 31 'function 'c-unicode selection (cons 11 45))
(evil-textobj-tree-sitter--thing-at-point-test 'c-ts-mode t 31 'function 'c-unicode selection (cons 11 45))))
;;; evil-textobj-tree-sitter-test.el ends here