@@ -18,7 +18,7 @@ pub struct ParsedTree {
18
18
impl ProtoParser {
19
19
pub fn new ( ) -> Self {
20
20
let mut parser = tree_sitter:: Parser :: new ( ) ;
21
- if let Err ( e) = parser. set_language ( & tree_sitter_proto :: language ( ) ) {
21
+ if let Err ( e) = parser. set_language ( & protols_tree_sitter_proto :: language ( ) ) {
22
22
panic ! ( "failed to set ts language parser {:?}" , e) ;
23
23
}
24
24
Self { parser }
@@ -33,7 +33,6 @@ impl ProtoParser {
33
33
34
34
impl ParsedTree {
35
35
fn walk_and_collect_kinds < ' a > (
36
- & self ,
37
36
cursor : & mut TreeCursor < ' a > ,
38
37
kinds : & [ & str ] ,
39
38
) -> Vec < Node < ' a > > {
@@ -47,7 +46,7 @@ impl ParsedTree {
47
46
}
48
47
49
48
if cursor. goto_first_child ( ) {
50
- v. extend ( self . walk_and_collect_kinds ( cursor, kinds) ) ;
49
+ v. extend ( Self :: walk_and_collect_kinds ( cursor, kinds) ) ;
51
50
cursor. goto_parent ( ) ;
52
51
}
53
52
@@ -59,14 +58,14 @@ impl ParsedTree {
59
58
v
60
59
}
61
60
62
- fn advance_cursor_to < ' a > ( & self , cursor : & mut TreeCursor < ' a > , nid : usize ) -> bool {
61
+ fn advance_cursor_to ( cursor : & mut TreeCursor < ' _ > , nid : usize ) -> bool {
63
62
loop {
64
63
let node = cursor. node ( ) ;
65
64
if node. id ( ) == nid {
66
65
return true ;
67
66
}
68
67
if cursor. goto_first_child ( ) {
69
- if self . advance_cursor_to ( cursor, nid) {
68
+ if Self :: advance_cursor_to ( cursor, nid) {
70
69
return true ;
71
70
}
72
71
cursor. goto_parent ( ) ;
@@ -83,7 +82,7 @@ impl ParsedTree {
83
82
84
83
info ! ( "Looking for node with id: {nid}" ) ;
85
84
86
- self . advance_cursor_to ( & mut cursor, nid) ;
85
+ Self :: advance_cursor_to ( & mut cursor, nid) ;
87
86
if !cursor. goto_parent ( ) {
88
87
return None ;
89
88
}
@@ -108,12 +107,12 @@ impl ParsedTree {
108
107
break ;
109
108
}
110
109
}
111
- return if comments. len ( ) != 0 {
110
+ if ! comments. is_empty ( ) {
112
111
comments. reverse ( ) ;
113
112
Some ( comments. join ( "\n " ) )
114
113
} else {
115
114
None
116
- } ;
115
+ }
117
116
}
118
117
}
119
118
@@ -132,7 +131,7 @@ impl ParsedTree {
132
131
133
132
pub fn find_childrens_by_kinds ( & self , kinds : & [ & str ] ) -> Vec < Node > {
134
133
let mut cursor = self . tree . root_node ( ) . walk ( ) ;
135
- self . walk_and_collect_kinds ( & mut cursor, kinds)
134
+ Self :: walk_and_collect_kinds ( & mut cursor, kinds)
136
135
}
137
136
138
137
pub fn definition (
@@ -170,7 +169,7 @@ impl ParsedTree {
170
169
. into_iter ( )
171
170
. filter ( |n| n. utf8_text ( content. as_ref ( ) ) . expect ( "utf-8 parse error" ) == text)
172
171
. filter_map ( |n| self . find_preceeding_comments ( n. id ( ) , content. as_ref ( ) ) )
173
- . map ( |s| MarkedString :: String ( s ) )
172
+ . map ( MarkedString :: String )
174
173
. collect ( ) ,
175
174
None => vec ! [ ] ,
176
175
}
@@ -198,3 +197,191 @@ impl ParsedTree {
198
197
}
199
198
}
200
199
}
200
+
201
+ #[ cfg( test) ]
202
+ mod test {
203
+ use async_lsp:: lsp_types:: { DiagnosticSeverity , MarkedString , Position , Range , Url } ;
204
+
205
+ use super :: ProtoParser ;
206
+
207
+ #[ test]
208
+ fn test_find_children_by_kind ( ) {
209
+ let contents = r#"syntax = "proto3";
210
+
211
+ package com.book;
212
+
213
+ message Book {
214
+
215
+ message Author {
216
+ string name = 1;
217
+ string country = 2;
218
+ };
219
+ // This is a multi line comment on the field name
220
+ // Of a message called Book
221
+ int64 isbn = 1;
222
+ string title = 2;
223
+ Author author = 3;
224
+ }
225
+ "# ;
226
+ let parsed = ProtoParser :: new ( ) . parse ( contents) ;
227
+ assert ! ( parsed. is_some( ) ) ;
228
+ let tree = parsed. unwrap ( ) ;
229
+ let nodes = tree. find_childrens_by_kinds ( & [ "message_name" ] ) ;
230
+
231
+ assert_eq ! ( nodes. len( ) , 2 ) ;
232
+
233
+ let names: Vec < _ > = nodes
234
+ . into_iter ( )
235
+ . map ( |n| n. utf8_text ( contents. as_ref ( ) ) . unwrap ( ) )
236
+ . collect ( ) ;
237
+ assert_eq ! ( names[ 0 ] , "Book" ) ;
238
+ assert_eq ! ( names[ 1 ] , "Author" ) ;
239
+ }
240
+
241
+ #[ test]
242
+ fn test_collect_parse_error ( ) {
243
+ let url = "file://foo/bar.proto" ;
244
+ let contents = r#"syntax = "proto3";
245
+
246
+ package com.book;
247
+
248
+ message Book {
249
+ message Author {
250
+ string name;
251
+ string country = 2;
252
+ };
253
+ }
254
+ "# ;
255
+ let parsed = ProtoParser :: new ( ) . parse ( contents) ;
256
+ assert ! ( parsed. is_some( ) ) ;
257
+ let tree = parsed. unwrap ( ) ;
258
+ let diagnostics = tree. collect_parse_errors ( & url. parse ( ) . unwrap ( ) ) ;
259
+
260
+ assert_eq ! ( diagnostics. uri, Url :: parse( url) . unwrap( ) ) ;
261
+ assert_eq ! ( diagnostics. diagnostics. len( ) , 1 ) ;
262
+
263
+ let error = & diagnostics. diagnostics [ 0 ] ;
264
+ assert_eq ! ( error. severity, Some ( DiagnosticSeverity :: ERROR ) ) ;
265
+ assert_eq ! ( error. source, Some ( "protols" . to_owned( ) ) ) ;
266
+ assert_eq ! ( error. message, "Syntax error" ) ;
267
+ assert_eq ! (
268
+ error. range,
269
+ Range {
270
+ start: Position {
271
+ line: 6 ,
272
+ character: 8
273
+ } ,
274
+ end: Position {
275
+ line: 6 ,
276
+ character: 19
277
+ }
278
+ }
279
+ ) ;
280
+ }
281
+
282
+ #[ test]
283
+ fn test_hover ( ) {
284
+ let posbook = Position {
285
+ line : 5 ,
286
+ character : 9 ,
287
+ } ;
288
+ let posinvalid = Position {
289
+ line : 0 ,
290
+ character : 1 ,
291
+ } ;
292
+ let posauthor = Position {
293
+ line : 11 ,
294
+ character : 14 ,
295
+ } ;
296
+ let contents = r#"syntax = "proto3";
297
+
298
+ package com.book;
299
+
300
+ // A Book is book
301
+ message Book {
302
+
303
+ // This is represents author
304
+ // A author is a someone who writes books
305
+ //
306
+ // Author has a name and a country where they were born
307
+ message Author {
308
+ string name = 1;
309
+ string country = 2;
310
+ };
311
+ }
312
+ "# ;
313
+ let parsed = ProtoParser :: new ( ) . parse ( contents) ;
314
+ assert ! ( parsed. is_some( ) ) ;
315
+ let tree = parsed. unwrap ( ) ;
316
+ let res = tree. hover ( & posbook, contents) ;
317
+
318
+ assert_eq ! ( res. len( ) , 1 ) ;
319
+ assert_eq ! ( res[ 0 ] , MarkedString :: String ( "A Book is book" . to_owned( ) ) ) ;
320
+
321
+ let res = tree. hover ( & posinvalid, contents) ;
322
+ assert_eq ! ( res. len( ) , 0 ) ;
323
+
324
+ let res = tree. hover ( & posauthor, contents) ;
325
+ assert_eq ! ( res. len( ) , 1 ) ;
326
+ assert_eq ! (
327
+ res[ 0 ] ,
328
+ MarkedString :: String (
329
+ r#"This is represents author
330
+ A author is a someone who writes books
331
+
332
+ Author has a name and a country where they were born"#
333
+ . to_owned( )
334
+ )
335
+ ) ;
336
+ }
337
+
338
+ #[ test]
339
+ fn test_goto_definition ( ) {
340
+ let url = "file://foo/bar.proto" ;
341
+ let posinvalid = Position {
342
+ line : 0 ,
343
+ character : 1 ,
344
+ } ;
345
+ let posauthor = Position {
346
+ line : 10 ,
347
+ character : 5 ,
348
+ } ;
349
+ let contents = r#"syntax = "proto3";
350
+
351
+ package com.book;
352
+
353
+ message Book {
354
+ message Author {
355
+ string name = 1;
356
+ string country = 2;
357
+ };
358
+
359
+ Author author = 1;
360
+ string isbn = 2;
361
+ }
362
+ "# ;
363
+ let parsed = ProtoParser :: new ( ) . parse ( contents) ;
364
+ assert ! ( parsed. is_some( ) ) ;
365
+ let tree = parsed. unwrap ( ) ;
366
+ let res = tree. definition ( & posauthor, & url. parse ( ) . unwrap ( ) , contents) ;
367
+
368
+ assert_eq ! ( res. len( ) , 1 ) ;
369
+ assert_eq ! ( res[ 0 ] . uri, Url :: parse( url) . unwrap( ) ) ;
370
+ assert_eq ! (
371
+ res[ 0 ] . range,
372
+ Range {
373
+ start: Position {
374
+ line: 5 ,
375
+ character: 12
376
+ } ,
377
+ end: Position {
378
+ line: 5 ,
379
+ character: 18
380
+ } ,
381
+ }
382
+ ) ;
383
+
384
+ let res = tree. definition ( & posinvalid, & url. parse ( ) . unwrap ( ) , contents) ;
385
+ assert_eq ! ( res. len( ) , 0 ) ;
386
+ }
387
+ }
0 commit comments