@@ -18,7 +18,7 @@ pub struct ParsedTree {
1818impl ProtoParser {
1919 pub fn new ( ) -> Self {
2020 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 ( ) ) {
2222 panic ! ( "failed to set ts language parser {:?}" , e) ;
2323 }
2424 Self { parser }
@@ -33,7 +33,6 @@ impl ProtoParser {
3333
3434impl ParsedTree {
3535 fn walk_and_collect_kinds < ' a > (
36- & self ,
3736 cursor : & mut TreeCursor < ' a > ,
3837 kinds : & [ & str ] ,
3938 ) -> Vec < Node < ' a > > {
@@ -47,7 +46,7 @@ impl ParsedTree {
4746 }
4847
4948 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) ) ;
5150 cursor. goto_parent ( ) ;
5251 }
5352
@@ -59,14 +58,14 @@ impl ParsedTree {
5958 v
6059 }
6160
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 {
6362 loop {
6463 let node = cursor. node ( ) ;
6564 if node. id ( ) == nid {
6665 return true ;
6766 }
6867 if cursor. goto_first_child ( ) {
69- if self . advance_cursor_to ( cursor, nid) {
68+ if Self :: advance_cursor_to ( cursor, nid) {
7069 return true ;
7170 }
7271 cursor. goto_parent ( ) ;
@@ -83,7 +82,7 @@ impl ParsedTree {
8382
8483 info ! ( "Looking for node with id: {nid}" ) ;
8584
86- self . advance_cursor_to ( & mut cursor, nid) ;
85+ Self :: advance_cursor_to ( & mut cursor, nid) ;
8786 if !cursor. goto_parent ( ) {
8887 return None ;
8988 }
@@ -108,12 +107,12 @@ impl ParsedTree {
108107 break ;
109108 }
110109 }
111- return if comments. len ( ) != 0 {
110+ if ! comments. is_empty ( ) {
112111 comments. reverse ( ) ;
113112 Some ( comments. join ( "\n " ) )
114113 } else {
115114 None
116- } ;
115+ }
117116 }
118117}
119118
@@ -132,7 +131,7 @@ impl ParsedTree {
132131
133132 pub fn find_childrens_by_kinds ( & self , kinds : & [ & str ] ) -> Vec < Node > {
134133 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)
136135 }
137136
138137 pub fn definition (
@@ -170,7 +169,7 @@ impl ParsedTree {
170169 . into_iter ( )
171170 . filter ( |n| n. utf8_text ( content. as_ref ( ) ) . expect ( "utf-8 parse error" ) == text)
172171 . filter_map ( |n| self . find_preceeding_comments ( n. id ( ) , content. as_ref ( ) ) )
173- . map ( |s| MarkedString :: String ( s ) )
172+ . map ( MarkedString :: String )
174173 . collect ( ) ,
175174 None => vec ! [ ] ,
176175 }
@@ -198,3 +197,191 @@ impl ParsedTree {
198197 }
199198 }
200199}
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