aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/display/structure.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/display/structure.rs')
-rw-r--r--crates/ra_ide_api/src/display/structure.rs50
1 files changed, 28 insertions, 22 deletions
diff --git a/crates/ra_ide_api/src/display/structure.rs b/crates/ra_ide_api/src/display/structure.rs
index 638484a9b..2e183d2f6 100644
--- a/crates/ra_ide_api/src/display/structure.rs
+++ b/crates/ra_ide_api/src/display/structure.rs
@@ -24,14 +24,14 @@ pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
24 for event in file.syntax().preorder() { 24 for event in file.syntax().preorder() {
25 match event { 25 match event {
26 WalkEvent::Enter(node) => { 26 WalkEvent::Enter(node) => {
27 if let Some(mut symbol) = structure_node(node) { 27 if let Some(mut symbol) = structure_node(&node) {
28 symbol.parent = stack.last().copied(); 28 symbol.parent = stack.last().copied();
29 stack.push(res.len()); 29 stack.push(res.len());
30 res.push(symbol); 30 res.push(symbol);
31 } 31 }
32 } 32 }
33 WalkEvent::Leave(node) => { 33 WalkEvent::Leave(node) => {
34 if structure_node(node).is_some() { 34 if structure_node(&node).is_some() {
35 stack.pop().unwrap(); 35 stack.pop().unwrap();
36 } 36 }
37 } 37 }
@@ -41,19 +41,20 @@ pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
41} 41}
42 42
43fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { 43fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
44 fn decl<N: NameOwner + AttrsOwner>(node: &N) -> Option<StructureNode> { 44 fn decl<N: NameOwner + AttrsOwner>(node: N) -> Option<StructureNode> {
45 decl_with_detail(node, None) 45 decl_with_detail(node, None)
46 } 46 }
47 47
48 fn decl_with_ascription<N: NameOwner + AttrsOwner + TypeAscriptionOwner>( 48 fn decl_with_ascription<N: NameOwner + AttrsOwner + TypeAscriptionOwner>(
49 node: &N, 49 node: N,
50 ) -> Option<StructureNode> { 50 ) -> Option<StructureNode> {
51 decl_with_type_ref(node, node.ascribed_type()) 51 let ty = node.ascribed_type();
52 decl_with_type_ref(node, ty)
52 } 53 }
53 54
54 fn decl_with_type_ref<N: NameOwner + AttrsOwner>( 55 fn decl_with_type_ref<N: NameOwner + AttrsOwner>(
55 node: &N, 56 node: N,
56 type_ref: Option<&ast::TypeRef>, 57 type_ref: Option<ast::TypeRef>,
57 ) -> Option<StructureNode> { 58 ) -> Option<StructureNode> {
58 let detail = type_ref.map(|type_ref| { 59 let detail = type_ref.map(|type_ref| {
59 let mut detail = String::new(); 60 let mut detail = String::new();
@@ -64,7 +65,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
64 } 65 }
65 66
66 fn decl_with_detail<N: NameOwner + AttrsOwner>( 67 fn decl_with_detail<N: NameOwner + AttrsOwner>(
67 node: &N, 68 node: N,
68 detail: Option<String>, 69 detail: Option<String>,
69 ) -> Option<StructureNode> { 70 ) -> Option<StructureNode> {
70 let name = node.name()?; 71 let name = node.name()?;
@@ -82,22 +83,24 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
82 83
83 fn collapse_ws(node: &SyntaxNode, output: &mut String) { 84 fn collapse_ws(node: &SyntaxNode, output: &mut String) {
84 let mut can_insert_ws = false; 85 let mut can_insert_ws = false;
85 for line in node.text().chunks().flat_map(|chunk| chunk.lines()) { 86 for chunk in node.text().chunks() {
86 let line = line.trim(); 87 for line in chunk.lines() {
87 if line.is_empty() { 88 let line = line.trim();
88 if can_insert_ws { 89 if line.is_empty() {
89 output.push_str(" "); 90 if can_insert_ws {
90 can_insert_ws = false; 91 output.push_str(" ");
92 can_insert_ws = false;
93 }
94 } else {
95 output.push_str(line);
96 can_insert_ws = true;
91 } 97 }
92 } else {
93 output.push_str(line);
94 can_insert_ws = true;
95 } 98 }
96 } 99 }
97 } 100 }
98 101
99 visitor() 102 visitor()
100 .visit(|fn_def: &ast::FnDef| { 103 .visit(|fn_def: ast::FnDef| {
101 let mut detail = String::from("fn"); 104 let mut detail = String::from("fn");
102 if let Some(type_param_list) = fn_def.type_param_list() { 105 if let Some(type_param_list) = fn_def.type_param_list() {
103 collapse_ws(type_param_list.syntax(), &mut detail); 106 collapse_ws(type_param_list.syntax(), &mut detail);
@@ -117,11 +120,14 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
117 .visit(decl::<ast::EnumVariant>) 120 .visit(decl::<ast::EnumVariant>)
118 .visit(decl::<ast::TraitDef>) 121 .visit(decl::<ast::TraitDef>)
119 .visit(decl::<ast::Module>) 122 .visit(decl::<ast::Module>)
120 .visit(|td: &ast::TypeAliasDef| decl_with_type_ref(td, td.type_ref())) 123 .visit(|td: ast::TypeAliasDef| {
124 let ty = td.type_ref();
125 decl_with_type_ref(td, ty)
126 })
121 .visit(decl_with_ascription::<ast::NamedFieldDef>) 127 .visit(decl_with_ascription::<ast::NamedFieldDef>)
122 .visit(decl_with_ascription::<ast::ConstDef>) 128 .visit(decl_with_ascription::<ast::ConstDef>)
123 .visit(decl_with_ascription::<ast::StaticDef>) 129 .visit(decl_with_ascription::<ast::StaticDef>)
124 .visit(|im: &ast::ImplBlock| { 130 .visit(|im: ast::ImplBlock| {
125 let target_type = im.target_type()?; 131 let target_type = im.target_type()?;
126 let target_trait = im.target_trait(); 132 let target_trait = im.target_trait();
127 let label = match target_trait { 133 let label = match target_trait {
@@ -142,14 +148,14 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
142 }; 148 };
143 Some(node) 149 Some(node)
144 }) 150 })
145 .visit(|mc: &ast::MacroCall| { 151 .visit(|mc: ast::MacroCall| {
146 let first_token = mc.syntax().first_token().unwrap(); 152 let first_token = mc.syntax().first_token().unwrap();
147 if first_token.text().as_str() != "macro_rules" { 153 if first_token.text().as_str() != "macro_rules" {
148 return None; 154 return None;
149 } 155 }
150 decl(mc) 156 decl(mc)
151 }) 157 })
152 .accept(node)? 158 .accept(&node)?
153} 159}
154 160
155#[cfg(test)] 161#[cfg(test)]