diff options
Diffstat (limited to 'crates/ra_ide_api/src/display/structure.rs')
-rw-r--r-- | crates/ra_ide_api/src/display/structure.rs | 50 |
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 | ||
43 | fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { | 43 | fn 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)] |