diff options
Diffstat (limited to 'crates/ra_ide_api_light/src/structure.rs')
-rw-r--r-- | crates/ra_ide_api_light/src/structure.rs | 69 |
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 | ||
3 | use ra_syntax::{ | 3 | use 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 | ||
18 | pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> { | 19 | pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> { |
@@ -40,6 +41,22 @@ pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> { | |||
40 | 41 | ||
41 | fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { | 42 | fn 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 | ||
100 | mod m { | 149 | mod 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 | ||
104 | enum E { X, Y(i32) } | 159 | enum E { X, Y(i32) } |