aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/display
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/display')
-rw-r--r--crates/ra_ide/src/display/function_signature.rs321
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs81
-rw-r--r--crates/ra_ide/src/display/short_label.rs2
-rw-r--r--crates/ra_ide/src/display/structure.rs441
4 files changed, 28 insertions, 817 deletions
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs
deleted file mode 100644
index 1d39544d3..000000000
--- a/crates/ra_ide/src/display/function_signature.rs
+++ /dev/null
@@ -1,321 +0,0 @@
1//! FIXME: write short doc here
2
3// FIXME: this modules relies on strings and AST way too much, and it should be
4// rewritten (matklad 2020-05-07)
5use std::{
6 convert::From,
7 fmt::{self, Display},
8};
9
10use hir::{Docs, Documentation, HasSource, HirDisplay};
11use ra_ide_db::RootDatabase;
12use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
13use stdx::{split_delim, SepBy};
14
15use crate::display::{generic_parameters, where_predicates};
16
17#[derive(Debug)]
18pub enum CallableKind {
19 Function,
20 StructConstructor,
21 VariantConstructor,
22 Macro,
23}
24
25/// Contains information about a function signature
26#[derive(Debug)]
27pub struct FunctionSignature {
28 pub kind: CallableKind,
29 /// Optional visibility
30 pub visibility: Option<String>,
31 /// Qualifiers like `async`, `unsafe`, ...
32 pub qualifier: FunctionQualifier,
33 /// Name of the function
34 pub name: Option<String>,
35 /// Documentation for the function
36 pub doc: Option<Documentation>,
37 /// Generic parameters
38 pub generic_parameters: Vec<String>,
39 /// Parameters of the function
40 pub parameters: Vec<String>,
41 /// Parameter names of the function
42 pub parameter_names: Vec<String>,
43 /// Parameter types of the function
44 pub parameter_types: Vec<String>,
45 /// Optional return type
46 pub ret_type: Option<String>,
47 /// Where predicates
48 pub where_predicates: Vec<String>,
49 /// Self param presence
50 pub has_self_param: bool,
51}
52
53#[derive(Debug, Default)]
54pub struct FunctionQualifier {
55 // `async` and `const` are mutually exclusive. Do we need to enforcing it here?
56 pub is_async: bool,
57 pub is_const: bool,
58 pub is_unsafe: bool,
59 /// The string `extern ".."`
60 pub extern_abi: Option<String>,
61}
62
63impl FunctionSignature {
64 pub(crate) fn from_hir(db: &RootDatabase, function: hir::Function) -> Self {
65 let ast_node = function.source(db).value;
66 let mut res = FunctionSignature::from(&ast_node);
67 res.doc = function.docs(db);
68 res
69 }
70
71 pub(crate) fn from_struct(db: &RootDatabase, st: hir::Struct) -> Option<Self> {
72 let node: ast::StructDef = st.source(db).value;
73 if let ast::StructKind::Record(_) = node.kind() {
74 return None;
75 };
76
77 let mut params = vec![];
78 let mut parameter_types = vec![];
79 for field in st.fields(db).into_iter() {
80 let ty = field.signature_ty(db);
81 let raw_param = format!("{}", ty.display(db));
82
83 if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) {
84 parameter_types.push(param_type.to_string());
85 } else {
86 // useful when you have tuple struct
87 parameter_types.push(raw_param.clone());
88 }
89 params.push(raw_param);
90 }
91
92 Some(FunctionSignature {
93 kind: CallableKind::StructConstructor,
94 visibility: node.visibility().map(|n| n.syntax().text().to_string()),
95 // Do we need `const`?
96 qualifier: Default::default(),
97 name: node.name().map(|n| n.text().to_string()),
98 ret_type: node.name().map(|n| n.text().to_string()),
99 parameters: params,
100 parameter_names: vec![],
101 parameter_types,
102 generic_parameters: generic_parameters(&node),
103 where_predicates: where_predicates(&node),
104 doc: st.docs(db),
105 has_self_param: false,
106 })
107 }
108
109 pub(crate) fn from_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option<Self> {
110 let node: ast::EnumVariant = variant.source(db).value;
111 match node.kind() {
112 ast::StructKind::Record(_) | ast::StructKind::Unit => return None,
113 _ => (),
114 };
115
116 let parent_name = variant.parent_enum(db).name(db).to_string();
117
118 let name = format!("{}::{}", parent_name, variant.name(db));
119
120 let mut params = vec![];
121 let mut parameter_types = vec![];
122 for field in variant.fields(db).into_iter() {
123 let ty = field.signature_ty(db);
124 let raw_param = format!("{}", ty.display(db));
125 if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) {
126 parameter_types.push(param_type.to_string());
127 } else {
128 // The unwrap_or_else is useful when you have tuple
129 parameter_types.push(raw_param);
130 }
131 let name = field.name(db);
132
133 params.push(format!("{}: {}", name, ty.display(db)));
134 }
135
136 Some(FunctionSignature {
137 kind: CallableKind::VariantConstructor,
138 visibility: None,
139 // Do we need `const`?
140 qualifier: Default::default(),
141 name: Some(name),
142 ret_type: None,
143 parameters: params,
144 parameter_names: vec![],
145 parameter_types,
146 generic_parameters: vec![],
147 where_predicates: vec![],
148 doc: variant.docs(db),
149 has_self_param: false,
150 })
151 }
152
153 pub(crate) fn from_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
154 let node: ast::MacroCall = macro_def.source(db).value;
155
156 let params = vec![];
157
158 Some(FunctionSignature {
159 kind: CallableKind::Macro,
160 visibility: None,
161 qualifier: Default::default(),
162 name: node.name().map(|n| n.text().to_string()),
163 ret_type: None,
164 parameters: params,
165 parameter_names: vec![],
166 parameter_types: vec![],
167 generic_parameters: vec![],
168 where_predicates: vec![],
169 doc: macro_def.docs(db),
170 has_self_param: false,
171 })
172 }
173}
174
175impl From<&'_ ast::FnDef> for FunctionSignature {
176 fn from(node: &ast::FnDef) -> FunctionSignature {
177 fn param_list(node: &ast::FnDef) -> (bool, Vec<String>, Vec<String>) {
178 let mut res = vec![];
179 let mut res_types = vec![];
180 let mut has_self_param = false;
181 if let Some(param_list) = node.param_list() {
182 if let Some(self_param) = param_list.self_param() {
183 has_self_param = true;
184 let raw_param = self_param.syntax().text().to_string();
185
186 res_types.push(
187 raw_param
188 .split(':')
189 .nth(1)
190 .and_then(|it| it.get(1..))
191 .unwrap_or_else(|| "Self")
192 .to_string(),
193 );
194 res.push(raw_param);
195 }
196
197 // macro-generated functions are missing whitespace
198 fn fmt_param(param: ast::Param) -> String {
199 let text = param.syntax().text().to_string();
200 match split_delim(&text, ':') {
201 Some((left, right)) => format!("{}: {}", left.trim(), right.trim()),
202 _ => text,
203 }
204 }
205
206 res.extend(param_list.params().map(fmt_param));
207 res_types.extend(param_list.params().map(|param| {
208 let param_text = param.syntax().text().to_string();
209 match param_text.split(':').nth(1).and_then(|it| it.get(1..)) {
210 Some(it) => it.to_string(),
211 None => param_text,
212 }
213 }));
214 }
215 (has_self_param, res, res_types)
216 }
217
218 fn param_name_list(node: &ast::FnDef) -> Vec<String> {
219 let mut res = vec![];
220 if let Some(param_list) = node.param_list() {
221 if let Some(self_param) = param_list.self_param() {
222 res.push(self_param.syntax().text().to_string())
223 }
224
225 res.extend(
226 param_list
227 .params()
228 .map(|param| {
229 Some(
230 param
231 .pat()?
232 .syntax()
233 .descendants()
234 .find_map(ast::Name::cast)?
235 .text()
236 .to_string(),
237 )
238 })
239 .map(|param| param.unwrap_or_default()),
240 );
241 }
242 res
243 }
244
245 let (has_self_param, parameters, parameter_types) = param_list(node);
246
247 FunctionSignature {
248 kind: CallableKind::Function,
249 visibility: node.visibility().map(|n| n.syntax().text().to_string()),
250 qualifier: FunctionQualifier {
251 is_async: node.async_token().is_some(),
252 is_const: node.const_token().is_some(),
253 is_unsafe: node.unsafe_token().is_some(),
254 extern_abi: node.abi().map(|n| n.to_string()),
255 },
256 name: node.name().map(|n| n.text().to_string()),
257 ret_type: node
258 .ret_type()
259 .and_then(|r| r.type_ref())
260 .map(|n| n.syntax().text().to_string()),
261 parameters,
262 parameter_names: param_name_list(node),
263 parameter_types,
264 generic_parameters: generic_parameters(node),
265 where_predicates: where_predicates(node),
266 // docs are processed separately
267 doc: None,
268 has_self_param,
269 }
270 }
271}
272
273impl Display for FunctionSignature {
274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275 if let Some(t) = &self.visibility {
276 write!(f, "{} ", t)?;
277 }
278
279 if self.qualifier.is_async {
280 write!(f, "async ")?;
281 }
282
283 if self.qualifier.is_const {
284 write!(f, "const ")?;
285 }
286
287 if self.qualifier.is_unsafe {
288 write!(f, "unsafe ")?;
289 }
290
291 if let Some(extern_abi) = &self.qualifier.extern_abi {
292 // Keyword `extern` is included in the string.
293 write!(f, "{} ", extern_abi)?;
294 }
295
296 if let Some(name) = &self.name {
297 match self.kind {
298 CallableKind::Function => write!(f, "fn {}", name)?,
299 CallableKind::StructConstructor => write!(f, "struct {}", name)?,
300 CallableKind::VariantConstructor => write!(f, "{}", name)?,
301 CallableKind::Macro => write!(f, "{}!", name)?,
302 }
303 }
304
305 if !self.generic_parameters.is_empty() {
306 write!(f, "{}", self.generic_parameters.iter().sep_by(", ").surround_with("<", ">"))?;
307 }
308
309 write!(f, "{}", self.parameters.iter().sep_by(", ").surround_with("(", ")"))?;
310
311 if let Some(t) = &self.ret_type {
312 write!(f, " -> {}", t)?;
313 }
314
315 if !self.where_predicates.is_empty() {
316 write!(f, "\nwhere {}", self.where_predicates.iter().sep_by(",\n "))?;
317 }
318
319 Ok(())
320 }
321}
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs
index 8bf2428ed..6dcb9415a 100644
--- a/crates/ra_ide/src/display/navigation_target.rs
+++ b/crates/ra_ide/src/display/navigation_target.rs
@@ -22,15 +22,28 @@ use super::short_label::ShortLabel;
22/// code, like a function or a struct, but this is not strictly required. 22/// code, like a function or a struct, but this is not strictly required.
23#[derive(Debug, Clone, PartialEq, Eq, Hash)] 23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub struct NavigationTarget { 24pub struct NavigationTarget {
25 // FIXME: use FileRange? 25 pub file_id: FileId,
26 file_id: FileId, 26 /// Range which encompasses the whole element.
27 full_range: TextRange, 27 ///
28 name: SmolStr, 28 /// Should include body, doc comments, attributes, etc.
29 kind: SyntaxKind, 29 ///
30 focus_range: Option<TextRange>, 30 /// Clients should use this range to answer "is the cursor inside the
31 container_name: Option<SmolStr>, 31 /// element?" question.
32 description: Option<String>, 32 pub full_range: TextRange,
33 docs: Option<String>, 33 /// A "most interesting" range withing the `full_range`.
34 ///
35 /// Typically, `full_range` is the whole syntax node, including doc
36 /// comments, and `focus_range` is the range of the identifier. "Most
37 /// interesting" range within the full range, typically the range of
38 /// identifier.
39 ///
40 /// Clients should place the cursor on this range when navigating to this target.
41 pub focus_range: Option<TextRange>,
42 pub name: SmolStr,
43 pub kind: SyntaxKind,
44 pub container_name: Option<SmolStr>,
45 pub description: Option<String>,
46 pub docs: Option<String>,
34} 47}
35 48
36pub(crate) trait ToNav { 49pub(crate) trait ToNav {
@@ -42,44 +55,9 @@ pub(crate) trait TryToNav {
42} 55}
43 56
44impl NavigationTarget { 57impl NavigationTarget {
45 /// When `focus_range` is specified, returns it. otherwise 58 pub fn focus_or_full_range(&self) -> TextRange {
46 /// returns `full_range`
47 pub fn range(&self) -> TextRange {
48 self.focus_range.unwrap_or(self.full_range) 59 self.focus_range.unwrap_or(self.full_range)
49 } 60 }
50 /// A "most interesting" range withing the `full_range`.
51 ///
52 /// Typically, `full_range` is the whole syntax node,
53 /// including doc comments, and `focus_range` is the range of the identifier.
54 pub fn focus_range(&self) -> Option<TextRange> {
55 self.focus_range
56 }
57 pub fn full_range(&self) -> TextRange {
58 self.full_range
59 }
60 pub fn file_id(&self) -> FileId {
61 self.file_id
62 }
63
64 pub fn name(&self) -> &SmolStr {
65 &self.name
66 }
67
68 pub fn container_name(&self) -> Option<&SmolStr> {
69 self.container_name.as_ref()
70 }
71
72 pub fn kind(&self) -> SyntaxKind {
73 self.kind
74 }
75
76 pub fn docs(&self) -> Option<&str> {
77 self.docs.as_deref()
78 }
79
80 pub fn description(&self) -> Option<&str> {
81 self.description.as_deref()
82 }
83 61
84 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { 62 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
85 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); 63 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
@@ -107,17 +85,12 @@ impl NavigationTarget {
107 85
108 #[cfg(test)] 86 #[cfg(test)]
109 pub(crate) fn debug_render(&self) -> String { 87 pub(crate) fn debug_render(&self) -> String {
110 let mut buf = format!( 88 let mut buf =
111 "{} {:?} {:?} {:?}", 89 format!("{} {:?} {:?} {:?}", self.name, self.kind, self.file_id, self.full_range);
112 self.name(), 90 if let Some(focus_range) = self.focus_range {
113 self.kind(),
114 self.file_id(),
115 self.full_range()
116 );
117 if let Some(focus_range) = self.focus_range() {
118 buf.push_str(&format!(" {:?}", focus_range)) 91 buf.push_str(&format!(" {:?}", focus_range))
119 } 92 }
120 if let Some(container_name) = self.container_name() { 93 if let Some(container_name) = &self.container_name {
121 buf.push_str(&format!(" {}", container_name)) 94 buf.push_str(&format!(" {}", container_name))
122 } 95 }
123 buf 96 buf
diff --git a/crates/ra_ide/src/display/short_label.rs b/crates/ra_ide/src/display/short_label.rs
index d37260e96..5588130a1 100644
--- a/crates/ra_ide/src/display/short_label.rs
+++ b/crates/ra_ide/src/display/short_label.rs
@@ -9,7 +9,7 @@ pub(crate) trait ShortLabel {
9 9
10impl ShortLabel for ast::FnDef { 10impl ShortLabel for ast::FnDef {
11 fn short_label(&self) -> Option<String> { 11 fn short_label(&self) -> Option<String> {
12 Some(crate::display::function_label(self)) 12 Some(crate::display::function_declaration(self))
13 } 13 }
14} 14}
15 15
diff --git a/crates/ra_ide/src/display/structure.rs b/crates/ra_ide/src/display/structure.rs
deleted file mode 100644
index 1f6a3febf..000000000
--- a/crates/ra_ide/src/display/structure.rs
+++ /dev/null
@@ -1,441 +0,0 @@
1use ra_syntax::{
2 ast::{self, AttrsOwner, NameOwner, TypeAscriptionOwner, TypeParamsOwner},
3 match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, WalkEvent,
4};
5
6#[derive(Debug, Clone)]
7pub struct StructureNode {
8 pub parent: Option<usize>,
9 pub label: String,
10 pub navigation_range: TextRange,
11 pub node_range: TextRange,
12 pub kind: SyntaxKind,
13 pub detail: Option<String>,
14 pub deprecated: bool,
15}
16
17// Feature: File Structure
18//
19// Provides a tree of the symbols defined in the file. Can be used to
20//
21// * fuzzy search symbol in a file (super useful)
22// * draw breadcrumbs to describe the context around the cursor
23// * draw outline of the file
24//
25// |===
26// | Editor | Shortcut
27//
28// | VS Code | kbd:[Ctrl+Shift+O]
29// |===
30pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
31 let mut res = Vec::new();
32 let mut stack = Vec::new();
33
34 for event in file.syntax().preorder() {
35 match event {
36 WalkEvent::Enter(node) => {
37 if let Some(mut symbol) = structure_node(&node) {
38 symbol.parent = stack.last().copied();
39 stack.push(res.len());
40 res.push(symbol);
41 }
42 }
43 WalkEvent::Leave(node) => {
44 if structure_node(&node).is_some() {
45 stack.pop().unwrap();
46 }
47 }
48 }
49 }
50 res
51}
52
53fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
54 fn decl<N: NameOwner + AttrsOwner>(node: N) -> Option<StructureNode> {
55 decl_with_detail(node, None)
56 }
57
58 fn decl_with_ascription<N: NameOwner + AttrsOwner + TypeAscriptionOwner>(
59 node: N,
60 ) -> Option<StructureNode> {
61 let ty = node.ascribed_type();
62 decl_with_type_ref(node, ty)
63 }
64
65 fn decl_with_type_ref<N: NameOwner + AttrsOwner>(
66 node: N,
67 type_ref: Option<ast::TypeRef>,
68 ) -> Option<StructureNode> {
69 let detail = type_ref.map(|type_ref| {
70 let mut detail = String::new();
71 collapse_ws(type_ref.syntax(), &mut detail);
72 detail
73 });
74 decl_with_detail(node, detail)
75 }
76
77 fn decl_with_detail<N: NameOwner + AttrsOwner>(
78 node: N,
79 detail: Option<String>,
80 ) -> Option<StructureNode> {
81 let name = node.name()?;
82
83 Some(StructureNode {
84 parent: None,
85 label: name.text().to_string(),
86 navigation_range: name.syntax().text_range(),
87 node_range: node.syntax().text_range(),
88 kind: node.syntax().kind(),
89 detail,
90 deprecated: node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated"),
91 })
92 }
93
94 fn collapse_ws(node: &SyntaxNode, output: &mut String) {
95 let mut can_insert_ws = false;
96 node.text().for_each_chunk(|chunk| {
97 for line in chunk.lines() {
98 let line = line.trim();
99 if line.is_empty() {
100 if can_insert_ws {
101 output.push(' ');
102 can_insert_ws = false;
103 }
104 } else {
105 output.push_str(line);
106 can_insert_ws = true;
107 }
108 }
109 })
110 }
111
112 match_ast! {
113 match node {
114 ast::FnDef(it) => {
115 let mut detail = String::from("fn");
116 if let Some(type_param_list) = it.type_param_list() {
117 collapse_ws(type_param_list.syntax(), &mut detail);
118 }
119 if let Some(param_list) = it.param_list() {
120 collapse_ws(param_list.syntax(), &mut detail);
121 }
122 if let Some(ret_type) = it.ret_type() {
123 detail.push_str(" ");
124 collapse_ws(ret_type.syntax(), &mut detail);
125 }
126
127 decl_with_detail(it, Some(detail))
128 },
129 ast::StructDef(it) => decl(it),
130 ast::UnionDef(it) => decl(it),
131 ast::EnumDef(it) => decl(it),
132 ast::EnumVariant(it) => decl(it),
133 ast::TraitDef(it) => decl(it),
134 ast::Module(it) => decl(it),
135 ast::TypeAliasDef(it) => {
136 let ty = it.type_ref();
137 decl_with_type_ref(it, ty)
138 },
139 ast::RecordFieldDef(it) => decl_with_ascription(it),
140 ast::ConstDef(it) => decl_with_ascription(it),
141 ast::StaticDef(it) => decl_with_ascription(it),
142 ast::ImplDef(it) => {
143 let target_type = it.target_type()?;
144 let target_trait = it.target_trait();
145 let label = match target_trait {
146 None => format!("impl {}", target_type.syntax().text()),
147 Some(t) => {
148 format!("impl {} for {}", t.syntax().text(), target_type.syntax().text(),)
149 }
150 };
151
152 let node = StructureNode {
153 parent: None,
154 label,
155 navigation_range: target_type.syntax().text_range(),
156 node_range: it.syntax().text_range(),
157 kind: it.syntax().kind(),
158 detail: None,
159 deprecated: false,
160 };
161 Some(node)
162 },
163 ast::MacroCall(it) => {
164 match it.path().and_then(|it| it.segment()).and_then(|it| it.name_ref()) {
165 Some(path_segment) if path_segment.text() == "macro_rules"
166 => decl(it),
167 _ => None,
168 }
169 },
170 _ => None,
171 }
172 }
173}
174
175#[cfg(test)]
176mod tests {
177 use expect::{expect, Expect};
178
179 use super::*;
180
181 fn check(ra_fixture: &str, expect: Expect) {
182 let file = SourceFile::parse(ra_fixture).ok().unwrap();
183 let structure = file_structure(&file);
184 expect.assert_debug_eq(&structure)
185 }
186
187 #[test]
188 fn test_file_structure() {
189 check(
190 r#"
191struct Foo {
192 x: i32
193}
194
195mod m {
196 fn bar1() {}
197 fn bar2<T>(t: T) -> T {}
198 fn bar3<A,
199 B>(a: A,
200 b: B) -> Vec<
201 u32
202 > {}
203}
204
205enum E { X, Y(i32) }
206type T = ();
207static S: i32 = 92;
208const C: i32 = 92;
209
210impl E {}
211
212impl fmt::Debug for E {}
213
214macro_rules! mc {
215 () => {}
216}
217
218#[macro_export]
219macro_rules! mcexp {
220 () => {}
221}
222
223/// Doc comment
224macro_rules! mcexp {
225 () => {}
226}
227
228#[deprecated]
229fn obsolete() {}
230
231#[deprecated(note = "for awhile")]
232fn very_obsolete() {}
233"#,
234 expect![[r#"
235 [
236 StructureNode {
237 parent: None,
238 label: "Foo",
239 navigation_range: 8..11,
240 node_range: 1..26,
241 kind: STRUCT_DEF,
242 detail: None,
243 deprecated: false,
244 },
245 StructureNode {
246 parent: Some(
247 0,
248 ),
249 label: "x",
250 navigation_range: 18..19,
251 node_range: 18..24,
252 kind: RECORD_FIELD_DEF,
253 detail: Some(
254 "i32",
255 ),
256 deprecated: false,
257 },
258 StructureNode {
259 parent: None,
260 label: "m",
261 navigation_range: 32..33,
262 node_range: 28..158,
263 kind: MODULE,
264 detail: None,
265 deprecated: false,
266 },
267 StructureNode {
268 parent: Some(
269 2,
270 ),
271 label: "bar1",
272 navigation_range: 43..47,
273 node_range: 40..52,
274 kind: FN_DEF,
275 detail: Some(
276 "fn()",
277 ),
278 deprecated: false,
279 },
280 StructureNode {
281 parent: Some(
282 2,
283 ),
284 label: "bar2",
285 navigation_range: 60..64,
286 node_range: 57..81,
287 kind: FN_DEF,
288 detail: Some(
289 "fn<T>(t: T) -> T",
290 ),
291 deprecated: false,
292 },
293 StructureNode {
294 parent: Some(
295 2,
296 ),
297 label: "bar3",
298 navigation_range: 89..93,
299 node_range: 86..156,
300 kind: FN_DEF,
301 detail: Some(
302 "fn<A, B>(a: A, b: B) -> Vec< u32 >",
303 ),
304 deprecated: false,
305 },
306 StructureNode {
307 parent: None,
308 label: "E",
309 navigation_range: 165..166,
310 node_range: 160..180,
311 kind: ENUM_DEF,
312 detail: None,
313 deprecated: false,
314 },
315 StructureNode {
316 parent: Some(
317 6,
318 ),
319 label: "X",
320 navigation_range: 169..170,
321 node_range: 169..170,
322 kind: ENUM_VARIANT,
323 detail: None,
324 deprecated: false,
325 },
326 StructureNode {
327 parent: Some(
328 6,
329 ),
330 label: "Y",
331 navigation_range: 172..173,
332 node_range: 172..178,
333 kind: ENUM_VARIANT,
334 detail: None,
335 deprecated: false,
336 },
337 StructureNode {
338 parent: None,
339 label: "T",
340 navigation_range: 186..187,
341 node_range: 181..193,
342 kind: TYPE_ALIAS_DEF,
343 detail: Some(
344 "()",
345 ),
346 deprecated: false,
347 },
348 StructureNode {
349 parent: None,
350 label: "S",
351 navigation_range: 201..202,
352 node_range: 194..213,
353 kind: STATIC_DEF,
354 detail: Some(
355 "i32",
356 ),
357 deprecated: false,
358 },
359 StructureNode {
360 parent: None,
361 label: "C",
362 navigation_range: 220..221,
363 node_range: 214..232,
364 kind: CONST_DEF,
365 detail: Some(
366 "i32",
367 ),
368 deprecated: false,
369 },
370 StructureNode {
371 parent: None,
372 label: "impl E",
373 navigation_range: 239..240,
374 node_range: 234..243,
375 kind: IMPL_DEF,
376 detail: None,
377 deprecated: false,
378 },
379 StructureNode {
380 parent: None,
381 label: "impl fmt::Debug for E",
382 navigation_range: 265..266,
383 node_range: 245..269,
384 kind: IMPL_DEF,
385 detail: None,
386 deprecated: false,
387 },
388 StructureNode {
389 parent: None,
390 label: "mc",
391 navigation_range: 284..286,
392 node_range: 271..303,
393 kind: MACRO_CALL,
394 detail: None,
395 deprecated: false,
396 },
397 StructureNode {
398 parent: None,
399 label: "mcexp",
400 navigation_range: 334..339,
401 node_range: 305..356,
402 kind: MACRO_CALL,
403 detail: None,
404 deprecated: false,
405 },
406 StructureNode {
407 parent: None,
408 label: "mcexp",
409 navigation_range: 387..392,
410 node_range: 358..409,
411 kind: MACRO_CALL,
412 detail: None,
413 deprecated: false,
414 },
415 StructureNode {
416 parent: None,
417 label: "obsolete",
418 navigation_range: 428..436,
419 node_range: 411..441,
420 kind: FN_DEF,
421 detail: Some(
422 "fn()",
423 ),
424 deprecated: true,
425 },
426 StructureNode {
427 parent: None,
428 label: "very_obsolete",
429 navigation_range: 481..494,
430 node_range: 443..499,
431 kind: FN_DEF,
432 detail: Some(
433 "fn()",
434 ),
435 deprecated: true,
436 },
437 ]
438 "#]],
439 );
440 }
441}