Created
September 21, 2018 15:16
-
-
Save kjeremy/d8a551ec1eb156ae8407577a38378e0c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// LSP entry point | |
pub fn handle_folding_range( | |
world: ServerWorld, | |
params: FoldingRangeParams, | |
_token: JobToken, | |
) -> Result<Option<Vec<FoldingRange>>> { | |
let file_id = params.text_document.try_conv_with(&world)?; | |
let file = world.analysis().file_syntax(file_id); | |
let line_index = world.analysis().file_line_index(file_id); | |
let ranges = folds(&file); | |
if ranges.is_empty() { | |
info!("Oh no! No ranges!"); | |
return Ok(None); | |
} | |
// Now that we have our ranges we need to put them into the response | |
let mut res = vec![]; | |
info!("Ranges: "); | |
for range in ranges { | |
let range = range.conv_with(&line_index); | |
let folding_range = FoldingRange { | |
start_line : range.start.line, | |
start_character : None, | |
end_line : range.end.line, | |
end_character : None, | |
kind : Some(FoldingRangeKind::Comment) | |
}; | |
info!(" {:?}", folding_range); | |
res.push(folding_range); | |
} | |
Ok(Some(res)) | |
} | |
// Folds comments only | |
fn folds(file: &File) -> Vec<TextRange> { | |
use ra_syntax::SyntaxNodeRef; | |
use ra_syntax::SyntaxKind; | |
use ra_syntax::TextRange; | |
use ra_syntax::algo::{siblings, Direction}; | |
use ra_syntax::algo::walk; | |
fn comment_range(node: SyntaxNodeRef) -> Option<TextRange> { | |
let left = node; | |
let mut right = node; | |
for node in siblings(node, Direction::Forward) { | |
match node.kind() { | |
SyntaxKind::COMMENT => right = node, | |
SyntaxKind::WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), | |
_ => break | |
} | |
} | |
if left != right { | |
Some(TextRange::from_to(left.range().start(), right.range().end())) | |
} else { | |
None | |
} | |
} | |
let syntax = file.syntax(); | |
let mut ranges = vec![]; | |
for node in walk::preorder(syntax) { | |
if node.kind() == SyntaxKind::COMMENT { | |
// Check for overlapping ranges | |
// This is terribly innefficient | |
if ranges.iter().any(|range : &TextRange| { | |
node.range().start() >= range.start() | |
&& node.range().end() <= range.end() | |
}) { | |
continue; | |
} | |
if let Some(range) = comment_range(node) { | |
ranges.push(range); | |
} | |
} | |
} | |
ranges | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment