aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api_light/src/structure.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api_light/src/structure.rs')
-rw-r--r--crates/ra_ide_api_light/src/structure.rs69
1 files changed, 62 insertions, 7 deletions
diff --git a/crates/ra_ide_api_light/src/structure.rs b/crates/ra_ide_api_light/src/structure.rs
index 3c6f39e16..e3713c217 100644
--- a/crates/ra_ide_api_light/src/structure.rs
+++ b/crates/ra_ide_api_light/src/structure.rs
@@ -2,7 +2,7 @@ use crate::TextRange;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 algo::visit::{visitor, Visitor}, 4 algo::visit::{visitor, Visitor},
5 ast::{self, NameOwner}, 5 ast::{self, NameOwner, TypeParamsOwner},
6 AstNode, SourceFile, SyntaxKind, SyntaxNode, WalkEvent, 6 AstNode, SourceFile, SyntaxKind, SyntaxNode, WalkEvent,
7}; 7};
8 8
@@ -13,6 +13,7 @@ pub struct StructureNode {
13 pub navigation_range: TextRange, 13 pub navigation_range: TextRange,
14 pub node_range: TextRange, 14 pub node_range: TextRange,
15 pub kind: SyntaxKind, 15 pub kind: SyntaxKind,
16 pub detail: Option<String>,
16} 17}
17 18
18pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> { 19pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
@@ -40,6 +41,22 @@ pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
40 41
41fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { 42fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
42 fn decl<N: NameOwner>(node: &N) -> Option<StructureNode> { 43 fn decl<N: NameOwner>(node: &N) -> Option<StructureNode> {
44 decl_with_detail(node, None)
45 }
46
47 fn decl_with_type_ref<N: NameOwner>(
48 node: &N,
49 type_ref: Option<&ast::TypeRef>,
50 ) -> Option<StructureNode> {
51 let detail = type_ref.map(|type_ref| {
52 let mut detail = String::new();
53 collapse_ws(type_ref.syntax(), &mut detail);
54 detail
55 });
56 decl_with_detail(node, detail)
57 }
58
59 fn decl_with_detail<N: NameOwner>(node: &N, detail: Option<String>) -> Option<StructureNode> {
43 let name = node.name()?; 60 let name = node.name()?;
44 Some(StructureNode { 61 Some(StructureNode {
45 parent: None, 62 parent: None,
@@ -47,19 +64,50 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
47 navigation_range: name.syntax().range(), 64 navigation_range: name.syntax().range(),
48 node_range: node.syntax().range(), 65 node_range: node.syntax().range(),
49 kind: node.syntax().kind(), 66 kind: node.syntax().kind(),
67 detail,
50 }) 68 })
51 } 69 }
52 70
71 fn collapse_ws(node: &SyntaxNode, output: &mut String) {
72 let mut can_insert_ws = false;
73 for line in node.text().chunks().flat_map(|chunk| chunk.lines()) {
74 let line = line.trim();
75 if line.is_empty() {
76 if can_insert_ws {
77 output.push_str(" ");
78 can_insert_ws = false;
79 }
80 } else {
81 output.push_str(line);
82 can_insert_ws = true;
83 }
84 }
85 }
86
53 visitor() 87 visitor()
54 .visit(decl::<ast::FnDef>) 88 .visit(|fn_def: &ast::FnDef| {
89 let mut detail = String::from("fn");
90 if let Some(type_param_list) = fn_def.type_param_list() {
91 collapse_ws(type_param_list.syntax(), &mut detail);
92 }
93 if let Some(param_list) = fn_def.param_list() {
94 collapse_ws(param_list.syntax(), &mut detail);
95 }
96 if let Some(ret_type) = fn_def.ret_type() {
97 detail.push_str(" ");
98 collapse_ws(ret_type.syntax(), &mut detail);
99 }
100
101 decl_with_detail(fn_def, Some(detail))
102 })
55 .visit(decl::<ast::StructDef>) 103 .visit(decl::<ast::StructDef>)
56 .visit(decl::<ast::NamedFieldDef>) 104 .visit(|nfd: &ast::NamedFieldDef| decl_with_type_ref(nfd, nfd.type_ref()))
57 .visit(decl::<ast::EnumDef>) 105 .visit(decl::<ast::EnumDef>)
58 .visit(decl::<ast::TraitDef>) 106 .visit(decl::<ast::TraitDef>)
59 .visit(decl::<ast::Module>) 107 .visit(decl::<ast::Module>)
60 .visit(decl::<ast::TypeDef>) 108 .visit(|td: &ast::TypeDef| decl_with_type_ref(td, td.type_ref()))
61 .visit(decl::<ast::ConstDef>) 109 .visit(|cd: &ast::ConstDef| decl_with_type_ref(cd, cd.type_ref()))
62 .visit(decl::<ast::StaticDef>) 110 .visit(|sd: &ast::StaticDef| decl_with_type_ref(sd, sd.type_ref()))
63 .visit(|im: &ast::ImplBlock| { 111 .visit(|im: &ast::ImplBlock| {
64 let target_type = im.target_type()?; 112 let target_type = im.target_type()?;
65 let target_trait = im.target_trait(); 113 let target_trait = im.target_trait();
@@ -78,6 +126,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
78 navigation_range: target_type.syntax().range(), 126 navigation_range: target_type.syntax().range(),
79 node_range: im.syntax().range(), 127 node_range: im.syntax().range(),
80 kind: im.syntax().kind(), 128 kind: im.syntax().kind(),
129 detail: None,
81 }; 130 };
82 Some(node) 131 Some(node)
83 }) 132 })
@@ -98,7 +147,13 @@ struct Foo {
98} 147}
99 148
100mod m { 149mod m {
101 fn bar() {} 150 fn bar1() {}
151 fn bar2<T>(t: T) -> T {}
152 fn bar3<A,
153 B>(a: A,
154 b: B) -> Vec<
155 u32
156 > {}
102} 157}
103 158
104enum E { X, Y(i32) } 159enum E { X, Y(i32) }