diff options
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 98 |
1 files changed, 21 insertions, 77 deletions
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 36cdeda38..51061543c 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use std::collections::{HashMap, HashSet}; | 1 | use std::collections::{HashMap}; |
2 | 2 | ||
3 | use languageserver_types::{ | 3 | use languageserver_types::{ |
4 | Diagnostic, DiagnosticSeverity, DocumentSymbol, | 4 | Diagnostic, DiagnosticSeverity, DocumentSymbol, |
@@ -8,11 +8,9 @@ use languageserver_types::{ | |||
8 | FoldingRange, FoldingRangeParams, FoldingRangeKind | 8 | FoldingRange, FoldingRangeParams, FoldingRangeKind |
9 | }; | 9 | }; |
10 | use serde_json::to_value; | 10 | use serde_json::to_value; |
11 | use ra_analysis::{Query, FileId, RunnableKind, JobToken}; | 11 | use ra_analysis::{Query, FileId, RunnableKind, JobToken, FoldKind}; |
12 | use ra_syntax::{ | 12 | use ra_syntax::{ |
13 | algo::{siblings, walk, Direction}, | 13 | text_utils::contains_offset_nonstrict |
14 | text_utils::contains_offset_nonstrict, | ||
15 | SyntaxKind, SyntaxNodeRef, TextRange | ||
16 | }; | 14 | }; |
17 | 15 | ||
18 | use ::{ | 16 | use ::{ |
@@ -375,82 +373,28 @@ pub fn handle_folding_range( | |||
375 | _token: JobToken, | 373 | _token: JobToken, |
376 | ) -> Result<Option<Vec<FoldingRange>>> { | 374 | ) -> Result<Option<Vec<FoldingRange>>> { |
377 | let file_id = params.text_document.try_conv_with(&world)?; | 375 | let file_id = params.text_document.try_conv_with(&world)?; |
378 | let file = world.analysis().file_syntax(file_id); | ||
379 | let line_index = world.analysis().file_line_index(file_id); | 376 | let line_index = world.analysis().file_line_index(file_id); |
380 | let syntax = file.syntax(); | ||
381 | |||
382 | let mut res = vec![]; | ||
383 | let mut visited = HashSet::new(); | ||
384 | |||
385 | for node in walk::preorder(syntax) { | ||
386 | if visited.contains(&node) { | ||
387 | continue; | ||
388 | } | ||
389 | |||
390 | let range_and_kind = match node.kind() { | ||
391 | SyntaxKind::COMMENT => ( | ||
392 | contiguous_range_for(SyntaxKind::COMMENT, node, &mut visited), | ||
393 | Some(FoldingRangeKind::Comment), | ||
394 | ), | ||
395 | SyntaxKind::USE_ITEM => ( | ||
396 | contiguous_range_for(SyntaxKind::USE_ITEM, node, &mut visited), | ||
397 | Some(FoldingRangeKind::Imports), | ||
398 | ), | ||
399 | _ => (None, None), | ||
400 | }; | ||
401 | 377 | ||
402 | match range_and_kind { | 378 | let res = Some(world.analysis() |
403 | (Some(range), Some(kind)) => { | 379 | .folding_ranges(file_id) |
404 | let range = range.conv_with(&line_index); | 380 | .into_iter() |
405 | res.push(FoldingRange { | 381 | .map(|fold| { |
406 | start_line: range.start.line, | 382 | let kind = match fold.kind { |
407 | start_character: Some(range.start.character), | 383 | FoldKind::Comment => FoldingRangeKind::Comment, |
408 | end_line: range.end.line, | 384 | FoldKind::Imports => FoldingRangeKind::Imports |
409 | end_character: Some(range.start.character), | 385 | }; |
410 | kind: Some(kind), | 386 | let range = fold.range.conv_with(&line_index); |
411 | }); | 387 | FoldingRange { |
388 | start_line: range.start.line, | ||
389 | start_character: Some(range.start.character), | ||
390 | end_line: range.end.line, | ||
391 | end_character: Some(range.start.character), | ||
392 | kind: Some(kind) | ||
412 | } | 393 | } |
413 | _ => {} | 394 | }) |
414 | } | 395 | .collect()); |
415 | } | ||
416 | |||
417 | if res.is_empty() { | ||
418 | Ok(None) | ||
419 | } else { | ||
420 | Ok(Some(res)) | ||
421 | } | ||
422 | } | ||
423 | 396 | ||
424 | fn contiguous_range_for<'a>( | 397 | Ok(res) |
425 | kind: SyntaxKind, | ||
426 | node: SyntaxNodeRef<'a>, | ||
427 | visited: &mut HashSet<SyntaxNodeRef<'a>>, | ||
428 | ) -> Option<TextRange> { | ||
429 | visited.insert(node); | ||
430 | |||
431 | let left = node; | ||
432 | let mut right = node; | ||
433 | for node in siblings(node, Direction::Forward) { | ||
434 | visited.insert(node); | ||
435 | match node.kind() { | ||
436 | SyntaxKind::WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), | ||
437 | k => { | ||
438 | if k == kind { | ||
439 | right = node | ||
440 | } else { | ||
441 | break; | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | if left != right { | ||
447 | Some(TextRange::from_to( | ||
448 | left.range().start(), | ||
449 | right.range().end(), | ||
450 | )) | ||
451 | } else { | ||
452 | None | ||
453 | } | ||
454 | } | 398 | } |
455 | 399 | ||
456 | pub fn handle_code_action( | 400 | pub fn handle_code_action( |