Add a better text for hover and stop duplicating work done in approximatelly_resolve_symbol
This commit is contained in:
parent
6d548d944f
commit
f88e0700e6
@ -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);
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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,
|
||||
|
@ -560,4 +560,3 @@ pub(crate) fn from_char(c: char) -> Option<SyntaxKind> {
|
||||
Some(tok)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,4 +75,3 @@ impl SyntaxKind {
|
||||
Some(tok)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user