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 @@ impl AnalysisImpl {
|
|||||||
|
|
||||||
Ok(symbol.docs(&file))
|
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>> {
|
pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
|
||||||
let syntax = self.db.source_file(file_id);
|
let syntax = self.db.source_file(file_id);
|
||||||
|
@ -236,7 +236,7 @@ impl Analysis {
|
|||||||
pub fn approximately_resolve_symbol(
|
pub fn approximately_resolve_symbol(
|
||||||
&self,
|
&self,
|
||||||
position: FilePosition,
|
position: FilePosition,
|
||||||
) -> Cancelable<Vec<(FileId, FileSymbol)>> {
|
) -> Cancelable<Option<(TextRange, Vec<(FileId, FileSymbol)>)>> {
|
||||||
self.imp.approximately_resolve_symbol(position)
|
self.imp.approximately_resolve_symbol(position)
|
||||||
}
|
}
|
||||||
pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
|
pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
|
||||||
@ -249,6 +249,9 @@ impl Analysis {
|
|||||||
) -> Cancelable<Option<String>> {
|
) -> Cancelable<Option<String>> {
|
||||||
self.imp.doc_comment_for(file_id, symbol)
|
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)>> {
|
pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
|
||||||
self.imp.parent_module(position)
|
self.imp.parent_module(position)
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,9 @@ fn approximate_resolve_works_in_items() {
|
|||||||
",
|
",
|
||||||
);
|
);
|
||||||
|
|
||||||
let symbols = analysis.approximately_resolve_symbol(pos).unwrap();
|
let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap();
|
||||||
assert_eq_dbg(
|
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,
|
&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(
|
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,
|
&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(
|
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,
|
&symbols,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,61 @@ impl FileSymbol {
|
|||||||
})
|
})
|
||||||
.nth(0)
|
.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> {
|
pub fn file_symbols(file: &SourceFileNode) -> Vec<FileSymbol> {
|
||||||
|
@ -204,7 +204,10 @@ pub fn handle_goto_definition(
|
|||||||
) -> Result<Option<req::GotoDefinitionResponse>> {
|
) -> Result<Option<req::GotoDefinitionResponse>> {
|
||||||
let position = params.try_conv_with(&world)?;
|
let position = params.try_conv_with(&world)?;
|
||||||
let mut res = Vec::new();
|
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 line_index = world.analysis().file_line_index(file_id);
|
||||||
let location = to_location(file_id, symbol.node_range, &world, &line_index)?;
|
let location = to_location(file_id, symbol.node_range, &world, &line_index)?;
|
||||||
res.push(location)
|
res.push(location)
|
||||||
@ -504,33 +507,31 @@ pub fn handle_hover(
|
|||||||
world: ServerWorld,
|
world: ServerWorld,
|
||||||
params: req::TextDocumentPositionParams,
|
params: req::TextDocumentPositionParams,
|
||||||
) -> Result<Option<Hover>> {
|
) -> Result<Option<Hover>> {
|
||||||
|
// TODO: Cut down on number of allocations
|
||||||
let position = params.try_conv_with(&world)?;
|
let position = params.try_conv_with(&world)?;
|
||||||
let line_index = world.analysis().file_line_index(position.file_id);
|
let line_index = world.analysis().file_line_index(position.file_id);
|
||||||
let file = world.analysis().file_syntax(position.file_id);
|
let (range, resolved) = match world.analysis().approximately_resolve_symbol(position)? {
|
||||||
|
None => return Ok(None),
|
||||||
for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? {
|
Some(it) => it,
|
||||||
let comment = world.analysis.doc_comment_for(file_id, symbol)?;
|
};
|
||||||
|
let mut result = Vec::new();
|
||||||
if comment.is_some() {
|
for (file_id, symbol) in resolved {
|
||||||
let range = match ra_syntax::algo::find_leaf_at_offset(file.syntax(), position.offset)
|
if let Some(docs) = world.analysis().doc_text_for(file_id, symbol)? {
|
||||||
.left_biased()
|
result.push(docs);
|
||||||
{
|
|
||||||
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 = 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)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Test doc comment
|
||||||
pub fn handle_prepare_rename(
|
pub fn handle_prepare_rename(
|
||||||
world: ServerWorld,
|
world: ServerWorld,
|
||||||
params: req::TextDocumentPositionParams,
|
params: req::TextDocumentPositionParams,
|
||||||
|
@ -560,4 +560,3 @@ impl SyntaxKind {
|
|||||||
Some(tok)
|
Some(tok)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,4 +75,3 @@ impl SyntaxKind {
|
|||||||
Some(tok)
|
Some(tok)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user