Add a better text for hover and stop duplicating work done in approximatelly_resolve_symbol

This commit is contained in:
DJMcNab 2018-12-08 16:02:23 +00:00 committed by Aleksey Kladov
parent 6d548d944f
commit f88e0700e6
7 changed files with 98 additions and 30 deletions

View File

@ -323,6 +323,17 @@ pub fn doc_comment_for(
Ok(symbol.docs(&file))
}
pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable<Option<String>> {
let file = self.db.source_file(file_id);
let result = match (symbol.description(&file), symbol.docs(&file)) {
(Some(desc), Some(docs)) => Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs),
(Some(desc), None) => Some("```rust\n".to_string() + &*desc + "\n```"),
(None, Some(docs)) => Some(docs),
_ => None,
};
Ok(result)
}
pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
let syntax = self.db.source_file(file_id);

View File

@ -236,7 +236,7 @@ pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)
pub fn approximately_resolve_symbol(
&self,
position: FilePosition,
) -> Cancelable<Vec<(FileId, FileSymbol)>> {
) -> Cancelable<Option<(TextRange, Vec<(FileId, FileSymbol)>)>> {
self.imp.approximately_resolve_symbol(position)
}
pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
@ -249,6 +249,9 @@ pub fn doc_comment_for(
) -> Cancelable<Option<String>> {
self.imp.doc_comment_for(file_id, symbol)
}
pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable<Option<String>> {
self.imp.doc_text_for(file_id, symbol)
}
pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
self.imp.parent_module(position)
}

View File

@ -21,9 +21,9 @@ enum E { X(Foo<|>) }
",
);
let symbols = analysis.approximately_resolve_symbol(pos).unwrap();
let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap();
assert_eq_dbg(
r#"[(FileId(1), FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF })]"#,
r#"([23; 26), [(FileId(1), FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF })])"#,
&symbols,
);
}
@ -39,9 +39,9 @@ fn test_resolve_module() {
",
);
let symbols = analysis.approximately_resolve_symbol(pos).unwrap();
let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap();
assert_eq_dbg(
r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#,
r#"([4; 7), [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })])"#,
&symbols,
);
@ -54,9 +54,9 @@ fn test_resolve_module() {
",
);
let symbols = analysis.approximately_resolve_symbol(pos).unwrap();
let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap();
assert_eq_dbg(
r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#,
r#"([4; 7), [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })])"#,
&symbols,
);
}

View File

@ -50,6 +50,61 @@ fn doc_comments<'a, N: DocCommentsOwner<'a>>(node: N) -> Option<String> {
})
.nth(0)
}
/// Get a description of this node.
///
/// e.g. `struct Name`, `enum Name`, `fn Name`
pub fn description(&self, file: &SourceFileNode) -> Option<String> {
// TODO: After type inference is done, add type information to improve the output
file.syntax()
.descendants()
.filter(|node| node.kind() == self.kind && node.range() == self.node_range)
.filter_map(|node: SyntaxNodeRef| {
// TODO: Refactor to be have less repetition
visitor()
.visit(|node: ast::FnDef| {
let mut string = "fn ".to_string();
node.name()?.syntax().text().push_to(&mut string);
Some(string)
})
.visit(|node: ast::StructDef| {
let mut string = "struct ".to_string();
node.name()?.syntax().text().push_to(&mut string);
Some(string)
})
.visit(|node: ast::EnumDef| {
let mut string = "enum ".to_string();
node.name()?.syntax().text().push_to(&mut string);
Some(string)
})
.visit(|node: ast::TraitDef| {
let mut string = "trait ".to_string();
node.name()?.syntax().text().push_to(&mut string);
Some(string)
})
.visit(|node: ast::Module| {
let mut string = "mod ".to_string();
node.name()?.syntax().text().push_to(&mut string);
Some(string)
})
.visit(|node: ast::TypeDef| {
let mut string = "type ".to_string();
node.name()?.syntax().text().push_to(&mut string);
Some(string)
})
.visit(|node: ast::ConstDef| {
let mut string = "const ".to_string();
node.name()?.syntax().text().push_to(&mut string);
Some(string)
})
.visit(|node: ast::StaticDef| {
let mut string = "static ".to_string();
node.name()?.syntax().text().push_to(&mut string);
Some(string)
})
.accept(node)?
})
.nth(0)
}
}
pub fn file_symbols(file: &SourceFileNode) -> Vec<FileSymbol> {

View File

@ -204,7 +204,10 @@ pub fn handle_goto_definition(
) -> Result<Option<req::GotoDefinitionResponse>> {
let position = params.try_conv_with(&world)?;
let mut res = Vec::new();
for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? {
for (file_id, symbol) in match world.analysis().approximately_resolve_symbol(position)? {
None => return Ok(None),
Some(it) => it.1,
} {
let line_index = world.analysis().file_line_index(file_id);
let location = to_location(file_id, symbol.node_range, &world, &line_index)?;
res.push(location)
@ -504,33 +507,31 @@ pub fn handle_hover(
world: ServerWorld,
params: req::TextDocumentPositionParams,
) -> Result<Option<Hover>> {
// TODO: Cut down on number of allocations
let position = params.try_conv_with(&world)?;
let line_index = world.analysis().file_line_index(position.file_id);
let file = world.analysis().file_syntax(position.file_id);
for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? {
let comment = world.analysis.doc_comment_for(file_id, symbol)?;
if comment.is_some() {
let range = match ra_syntax::algo::find_leaf_at_offset(file.syntax(), position.offset)
.left_biased()
{
None => return Ok(None),
Some(it) => it.range(),
};
let range = range.conv_with(&line_index);
let contents = HoverContents::Scalar(MarkedString::String(comment.unwrap()));
return Ok(Some(Hover {
contents,
range: Some(range),
}));
let (range, resolved) = match world.analysis().approximately_resolve_symbol(position)? {
None => return Ok(None),
Some(it) => it,
};
let mut result = Vec::new();
for (file_id, symbol) in resolved {
if let Some(docs) = world.analysis().doc_text_for(file_id, symbol)? {
result.push(docs);
}
}
let range = range.conv_with(&line_index);
if result.len() > 0 {
return Ok(Some(Hover {
contents: HoverContents::Scalar(MarkedString::String(result.join("\n\n---\n"))),
range: Some(range),
}));
}
Ok(None)
}
/// Test doc comment
pub fn handle_prepare_rename(
world: ServerWorld,
params: req::TextDocumentPositionParams,

View File

@ -560,4 +560,3 @@ pub(crate) fn from_char(c: char) -> Option<SyntaxKind> {
Some(tok)
}
}

View File

@ -75,4 +75,3 @@ impl SyntaxKind {
Some(tok)
}
}