Merge #630
630: Fill in DocumentSymbol::detail r=matklad a=hban Closes: #516 I just pulled type text from the syntax node and "formatted" is bit. VS Code can't really handle multi-line symbol detail (it's will crop it when rendering), so that formatting will just collapse all white-space to singe space. It isn't pretty, but maybe there's a better way. Issue also mentions "need to be done for `NavigationTarget` to `SymbolInformation`", but `SymbolInformation` doesn't have detail field on it? Co-authored-by: Hrvoje Ban <hban@users.noreply.github.com>
This commit is contained in:
commit
675943712c
5 changed files with 179 additions and 59 deletions
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
created: "2019-01-22T14:45:01.959724300+00:00"
|
||||
created: "2019-01-24T18:04:00.090162+00:00"
|
||||
creator: insta@0.4.0
|
||||
expression: structure
|
||||
source: "crates\\ra_ide_api_light\\src\\structure.rs"
|
||||
|
@ -10,7 +10,8 @@ source: "crates\\ra_ide_api_light\\src\\structure.rs"
|
|||
label: "Foo",
|
||||
navigation_range: [8; 11),
|
||||
node_range: [1; 26),
|
||||
kind: STRUCT_DEF
|
||||
kind: STRUCT_DEF,
|
||||
detail: None
|
||||
},
|
||||
StructureNode {
|
||||
parent: Some(
|
||||
|
@ -19,64 +20,107 @@ source: "crates\\ra_ide_api_light\\src\\structure.rs"
|
|||
label: "x",
|
||||
navigation_range: [18; 19),
|
||||
node_range: [18; 24),
|
||||
kind: NAMED_FIELD_DEF
|
||||
kind: NAMED_FIELD_DEF,
|
||||
detail: Some(
|
||||
"i32"
|
||||
)
|
||||
},
|
||||
StructureNode {
|
||||
parent: None,
|
||||
label: "m",
|
||||
navigation_range: [32; 33),
|
||||
node_range: [28; 53),
|
||||
kind: MODULE
|
||||
node_range: [28; 158),
|
||||
kind: MODULE,
|
||||
detail: None
|
||||
},
|
||||
StructureNode {
|
||||
parent: Some(
|
||||
2
|
||||
),
|
||||
label: "bar",
|
||||
navigation_range: [43; 46),
|
||||
node_range: [40; 51),
|
||||
kind: FN_DEF
|
||||
label: "bar1",
|
||||
navigation_range: [43; 47),
|
||||
node_range: [40; 52),
|
||||
kind: FN_DEF,
|
||||
detail: Some(
|
||||
"fn()"
|
||||
)
|
||||
},
|
||||
StructureNode {
|
||||
parent: Some(
|
||||
2
|
||||
),
|
||||
label: "bar2",
|
||||
navigation_range: [60; 64),
|
||||
node_range: [57; 81),
|
||||
kind: FN_DEF,
|
||||
detail: Some(
|
||||
"fn<T>(t: T) -> T"
|
||||
)
|
||||
},
|
||||
StructureNode {
|
||||
parent: Some(
|
||||
2
|
||||
),
|
||||
label: "bar3",
|
||||
navigation_range: [89; 93),
|
||||
node_range: [86; 156),
|
||||
kind: FN_DEF,
|
||||
detail: Some(
|
||||
"fn<A, B>(a: A, b: B) -> Vec< u32 >"
|
||||
)
|
||||
},
|
||||
StructureNode {
|
||||
parent: None,
|
||||
label: "E",
|
||||
navigation_range: [60; 61),
|
||||
node_range: [55; 75),
|
||||
kind: ENUM_DEF
|
||||
navigation_range: [165; 166),
|
||||
node_range: [160; 180),
|
||||
kind: ENUM_DEF,
|
||||
detail: None
|
||||
},
|
||||
StructureNode {
|
||||
parent: None,
|
||||
label: "T",
|
||||
navigation_range: [81; 82),
|
||||
node_range: [76; 88),
|
||||
kind: TYPE_DEF
|
||||
navigation_range: [186; 187),
|
||||
node_range: [181; 193),
|
||||
kind: TYPE_DEF,
|
||||
detail: Some(
|
||||
"()"
|
||||
)
|
||||
},
|
||||
StructureNode {
|
||||
parent: None,
|
||||
label: "S",
|
||||
navigation_range: [96; 97),
|
||||
node_range: [89; 108),
|
||||
kind: STATIC_DEF
|
||||
navigation_range: [201; 202),
|
||||
node_range: [194; 213),
|
||||
kind: STATIC_DEF,
|
||||
detail: Some(
|
||||
"i32"
|
||||
)
|
||||
},
|
||||
StructureNode {
|
||||
parent: None,
|
||||
label: "C",
|
||||
navigation_range: [115; 116),
|
||||
node_range: [109; 127),
|
||||
kind: CONST_DEF
|
||||
navigation_range: [220; 221),
|
||||
node_range: [214; 232),
|
||||
kind: CONST_DEF,
|
||||
detail: Some(
|
||||
"i32"
|
||||
)
|
||||
},
|
||||
StructureNode {
|
||||
parent: None,
|
||||
label: "impl E",
|
||||
navigation_range: [134; 135),
|
||||
node_range: [129; 138),
|
||||
kind: IMPL_BLOCK
|
||||
navigation_range: [239; 240),
|
||||
node_range: [234; 243),
|
||||
kind: IMPL_BLOCK,
|
||||
detail: None
|
||||
},
|
||||
StructureNode {
|
||||
parent: None,
|
||||
label: "impl fmt::Debug for E",
|
||||
navigation_range: [160; 161),
|
||||
node_range: [140; 164),
|
||||
kind: IMPL_BLOCK
|
||||
navigation_range: [265; 266),
|
||||
node_range: [245; 269),
|
||||
kind: IMPL_BLOCK,
|
||||
detail: None
|
||||
}
|
||||
]
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::TextRange;
|
|||
|
||||
use ra_syntax::{
|
||||
algo::visit::{visitor, Visitor},
|
||||
ast::{self, NameOwner},
|
||||
ast::{self, NameOwner, TypeParamsOwner},
|
||||
AstNode, SourceFile, SyntaxKind, SyntaxNode, WalkEvent,
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,7 @@ pub struct StructureNode {
|
|||
pub navigation_range: TextRange,
|
||||
pub node_range: TextRange,
|
||||
pub kind: SyntaxKind,
|
||||
pub detail: Option<String>,
|
||||
}
|
||||
|
||||
pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
|
||||
|
@ -40,6 +41,22 @@ pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
|
|||
|
||||
fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
|
||||
fn decl<N: NameOwner>(node: &N) -> Option<StructureNode> {
|
||||
decl_with_detail(node, None)
|
||||
}
|
||||
|
||||
fn decl_with_type_ref<N: NameOwner>(
|
||||
node: &N,
|
||||
type_ref: Option<&ast::TypeRef>,
|
||||
) -> Option<StructureNode> {
|
||||
let detail = type_ref.map(|type_ref| {
|
||||
let mut detail = String::new();
|
||||
collapse_ws(type_ref.syntax(), &mut detail);
|
||||
detail
|
||||
});
|
||||
decl_with_detail(node, detail)
|
||||
}
|
||||
|
||||
fn decl_with_detail<N: NameOwner>(node: &N, detail: Option<String>) -> Option<StructureNode> {
|
||||
let name = node.name()?;
|
||||
Some(StructureNode {
|
||||
parent: None,
|
||||
|
@ -47,19 +64,50 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
|
|||
navigation_range: name.syntax().range(),
|
||||
node_range: node.syntax().range(),
|
||||
kind: node.syntax().kind(),
|
||||
detail,
|
||||
})
|
||||
}
|
||||
|
||||
fn collapse_ws(node: &SyntaxNode, output: &mut String) {
|
||||
let mut can_insert_ws = false;
|
||||
for line in node.text().chunks().flat_map(|chunk| chunk.lines()) {
|
||||
let line = line.trim();
|
||||
if line.is_empty() {
|
||||
if can_insert_ws {
|
||||
output.push_str(" ");
|
||||
can_insert_ws = false;
|
||||
}
|
||||
} else {
|
||||
output.push_str(line);
|
||||
can_insert_ws = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitor()
|
||||
.visit(decl::<ast::FnDef>)
|
||||
.visit(|fn_def: &ast::FnDef| {
|
||||
let mut detail = String::from("fn");
|
||||
if let Some(type_param_list) = fn_def.type_param_list() {
|
||||
collapse_ws(type_param_list.syntax(), &mut detail);
|
||||
}
|
||||
if let Some(param_list) = fn_def.param_list() {
|
||||
collapse_ws(param_list.syntax(), &mut detail);
|
||||
}
|
||||
if let Some(ret_type) = fn_def.ret_type() {
|
||||
detail.push_str(" ");
|
||||
collapse_ws(ret_type.syntax(), &mut detail);
|
||||
}
|
||||
|
||||
decl_with_detail(fn_def, Some(detail))
|
||||
})
|
||||
.visit(decl::<ast::StructDef>)
|
||||
.visit(decl::<ast::NamedFieldDef>)
|
||||
.visit(|nfd: &ast::NamedFieldDef| decl_with_type_ref(nfd, nfd.type_ref()))
|
||||
.visit(decl::<ast::EnumDef>)
|
||||
.visit(decl::<ast::TraitDef>)
|
||||
.visit(decl::<ast::Module>)
|
||||
.visit(decl::<ast::TypeDef>)
|
||||
.visit(decl::<ast::ConstDef>)
|
||||
.visit(decl::<ast::StaticDef>)
|
||||
.visit(|td: &ast::TypeDef| decl_with_type_ref(td, td.type_ref()))
|
||||
.visit(|cd: &ast::ConstDef| decl_with_type_ref(cd, cd.type_ref()))
|
||||
.visit(|sd: &ast::StaticDef| decl_with_type_ref(sd, sd.type_ref()))
|
||||
.visit(|im: &ast::ImplBlock| {
|
||||
let target_type = im.target_type()?;
|
||||
let target_trait = im.target_trait();
|
||||
|
@ -78,6 +126,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
|
|||
navigation_range: target_type.syntax().range(),
|
||||
node_range: im.syntax().range(),
|
||||
kind: im.syntax().kind(),
|
||||
detail: None,
|
||||
};
|
||||
Some(node)
|
||||
})
|
||||
|
@ -98,7 +147,13 @@ struct Foo {
|
|||
}
|
||||
|
||||
mod m {
|
||||
fn bar() {}
|
||||
fn bar1() {}
|
||||
fn bar2<T>(t: T) -> T {}
|
||||
fn bar3<A,
|
||||
B>(a: A,
|
||||
b: B) -> Vec<
|
||||
u32
|
||||
> {}
|
||||
}
|
||||
|
||||
enum E { X, Y(i32) }
|
||||
|
|
|
@ -136,7 +136,7 @@ pub fn handle_document_symbol(
|
|||
for symbol in world.analysis().file_structure(file_id) {
|
||||
let doc_symbol = DocumentSymbol {
|
||||
name: symbol.label,
|
||||
detail: Some("".to_string()),
|
||||
detail: symbol.detail,
|
||||
kind: symbol.kind.conv(),
|
||||
deprecated: None,
|
||||
range: symbol.node_range.conv_with(&line_index),
|
||||
|
|
|
@ -598,7 +598,11 @@ impl ast::NameOwner for ConstDef {}
|
|||
impl ast::TypeParamsOwner for ConstDef {}
|
||||
impl ast::AttrsOwner for ConstDef {}
|
||||
impl ast::DocCommentsOwner for ConstDef {}
|
||||
impl ConstDef {}
|
||||
impl ConstDef {
|
||||
pub fn type_ref(&self) -> Option<&TypeRef> {
|
||||
super::child_opt(self)
|
||||
}
|
||||
}
|
||||
|
||||
// ContinueExpr
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -3407,7 +3411,11 @@ impl ast::NameOwner for StaticDef {}
|
|||
impl ast::TypeParamsOwner for StaticDef {}
|
||||
impl ast::AttrsOwner for StaticDef {}
|
||||
impl ast::DocCommentsOwner for StaticDef {}
|
||||
impl StaticDef {}
|
||||
impl StaticDef {
|
||||
pub fn type_ref(&self) -> Option<&TypeRef> {
|
||||
super::child_opt(self)
|
||||
}
|
||||
}
|
||||
|
||||
// Stmt
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -3948,7 +3956,11 @@ impl ast::NameOwner for TypeDef {}
|
|||
impl ast::TypeParamsOwner for TypeDef {}
|
||||
impl ast::AttrsOwner for TypeDef {}
|
||||
impl ast::DocCommentsOwner for TypeDef {}
|
||||
impl TypeDef {}
|
||||
impl TypeDef {
|
||||
pub fn type_ref(&self) -> Option<&TypeRef> {
|
||||
super::child_opt(self)
|
||||
}
|
||||
}
|
||||
|
||||
// TypeParam
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
|
|
|
@ -289,27 +289,36 @@ Grammar(
|
|||
collections: [["impl_items", "ImplItem"]],
|
||||
traits: [ "FnDefOwner", "ModuleItemOwner" ],
|
||||
),
|
||||
"ConstDef": ( traits: [
|
||||
"VisibilityOwner",
|
||||
"NameOwner",
|
||||
"TypeParamsOwner",
|
||||
"AttrsOwner",
|
||||
"DocCommentsOwner"
|
||||
] ),
|
||||
"StaticDef": ( traits: [
|
||||
"VisibilityOwner",
|
||||
"NameOwner",
|
||||
"TypeParamsOwner",
|
||||
"AttrsOwner",
|
||||
"DocCommentsOwner"
|
||||
] ),
|
||||
"TypeDef": ( traits: [
|
||||
"VisibilityOwner",
|
||||
"NameOwner",
|
||||
"TypeParamsOwner",
|
||||
"AttrsOwner",
|
||||
"DocCommentsOwner"
|
||||
] ),
|
||||
"ConstDef": (
|
||||
traits: [
|
||||
"VisibilityOwner",
|
||||
"NameOwner",
|
||||
"TypeParamsOwner",
|
||||
"AttrsOwner",
|
||||
"DocCommentsOwner"
|
||||
],
|
||||
options: ["TypeRef"]
|
||||
),
|
||||
"StaticDef": (
|
||||
traits: [
|
||||
"VisibilityOwner",
|
||||
"NameOwner",
|
||||
"TypeParamsOwner",
|
||||
"AttrsOwner",
|
||||
"DocCommentsOwner"
|
||||
],
|
||||
options: ["TypeRef"]
|
||||
),
|
||||
"TypeDef": (
|
||||
traits: [
|
||||
"VisibilityOwner",
|
||||
"NameOwner",
|
||||
"TypeParamsOwner",
|
||||
"AttrsOwner",
|
||||
"DocCommentsOwner"
|
||||
],
|
||||
options: ["TypeRef"]
|
||||
),
|
||||
"ImplBlock": (options: ["ItemList"]),
|
||||
|
||||
"ParenType": (options: ["TypeRef"]),
|
||||
|
|
Loading…
Add table
Reference in a new issue