diff options
Diffstat (limited to 'crates/hir_def/src/item_tree/tests.rs')
-rw-r--r-- | crates/hir_def/src/item_tree/tests.rs | 439 |
1 files changed, 0 insertions, 439 deletions
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs deleted file mode 100644 index 4b354c4c1..000000000 --- a/crates/hir_def/src/item_tree/tests.rs +++ /dev/null | |||
@@ -1,439 +0,0 @@ | |||
1 | use base_db::fixture::WithFixture; | ||
2 | use expect_test::{expect, Expect}; | ||
3 | use hir_expand::{db::AstDatabase, HirFileId, InFile}; | ||
4 | use rustc_hash::FxHashSet; | ||
5 | use std::sync::Arc; | ||
6 | use stdx::format_to; | ||
7 | use syntax::{ast, AstNode}; | ||
8 | |||
9 | use crate::{db::DefDatabase, test_db::TestDB}; | ||
10 | |||
11 | use super::{ItemTree, ModItem, ModKind}; | ||
12 | |||
13 | fn test_inner_items(ra_fixture: &str) { | ||
14 | let (db, file_id) = TestDB::with_single_file(ra_fixture); | ||
15 | let file_id = HirFileId::from(file_id); | ||
16 | let tree = db.item_tree(file_id); | ||
17 | let root = db.parse_or_expand(file_id).unwrap(); | ||
18 | let ast_id_map = db.ast_id_map(file_id); | ||
19 | |||
20 | // Traverse the item tree and collect all module/impl/trait-level items as AST nodes. | ||
21 | let mut outer_items = FxHashSet::default(); | ||
22 | let mut worklist = tree.top_level_items().to_vec(); | ||
23 | while let Some(item) = worklist.pop() { | ||
24 | let node: ast::Item = match item { | ||
25 | ModItem::Import(it) => tree.source(&db, InFile::new(file_id, it)).into(), | ||
26 | ModItem::ExternCrate(it) => tree.source(&db, InFile::new(file_id, it)).into(), | ||
27 | ModItem::Function(it) => tree.source(&db, InFile::new(file_id, it)).into(), | ||
28 | ModItem::Struct(it) => tree.source(&db, InFile::new(file_id, it)).into(), | ||
29 | ModItem::Union(it) => tree.source(&db, InFile::new(file_id, it)).into(), | ||
30 | ModItem::Enum(it) => tree.source(&db, InFile::new(file_id, it)).into(), | ||
31 | ModItem::Const(it) => tree.source(&db, InFile::new(file_id, it)).into(), | ||
32 | ModItem::Static(it) => tree.source(&db, InFile::new(file_id, it)).into(), | ||
33 | ModItem::TypeAlias(it) => tree.source(&db, InFile::new(file_id, it)).into(), | ||
34 | ModItem::Mod(it) => { | ||
35 | if let ModKind::Inline { items } = &tree[it].kind { | ||
36 | worklist.extend(&**items); | ||
37 | } | ||
38 | tree.source(&db, InFile::new(file_id, it)).into() | ||
39 | } | ||
40 | ModItem::Trait(it) => { | ||
41 | worklist.extend(tree[it].items.iter().map(|item| ModItem::from(*item))); | ||
42 | tree.source(&db, InFile::new(file_id, it)).into() | ||
43 | } | ||
44 | ModItem::Impl(it) => { | ||
45 | worklist.extend(tree[it].items.iter().map(|item| ModItem::from(*item))); | ||
46 | tree.source(&db, InFile::new(file_id, it)).into() | ||
47 | } | ||
48 | ModItem::MacroCall(_) => continue, | ||
49 | }; | ||
50 | |||
51 | outer_items.insert(node); | ||
52 | } | ||
53 | |||
54 | // Now descend the root node and check that all `ast::ModuleItem`s are either recorded above, or | ||
55 | // registered as inner items. | ||
56 | for item in root.descendants().skip(1).filter_map(ast::Item::cast) { | ||
57 | if outer_items.contains(&item) { | ||
58 | continue; | ||
59 | } | ||
60 | |||
61 | let ast_id = ast_id_map.ast_id(&item); | ||
62 | assert!(!tree.inner_items(ast_id).is_empty()); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | fn item_tree(ra_fixture: &str) -> Arc<ItemTree> { | ||
67 | let (db, file_id) = TestDB::with_single_file(ra_fixture); | ||
68 | db.item_tree(file_id.into()) | ||
69 | } | ||
70 | |||
71 | fn print_item_tree(ra_fixture: &str) -> String { | ||
72 | let tree = item_tree(ra_fixture); | ||
73 | let mut out = String::new(); | ||
74 | |||
75 | format_to!(out, "inner attrs: {:?}\n\n", tree.top_level_attrs()); | ||
76 | format_to!(out, "top-level items:\n"); | ||
77 | for item in tree.top_level_items() { | ||
78 | fmt_mod_item(&mut out, &tree, *item); | ||
79 | format_to!(out, "\n"); | ||
80 | } | ||
81 | |||
82 | if !tree.inner_items.is_empty() { | ||
83 | format_to!(out, "\ninner items:\n\n"); | ||
84 | for (ast_id, items) in &tree.inner_items { | ||
85 | format_to!(out, "for AST {:?}:\n", ast_id); | ||
86 | for inner in items { | ||
87 | fmt_mod_item(&mut out, &tree, *inner); | ||
88 | format_to!(out, "\n\n"); | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
93 | out | ||
94 | } | ||
95 | |||
96 | fn fmt_mod_item(out: &mut String, tree: &ItemTree, item: ModItem) { | ||
97 | let attrs = tree.attrs(item.into()); | ||
98 | if !attrs.is_empty() { | ||
99 | format_to!(out, "#[{:?}]\n", attrs); | ||
100 | } | ||
101 | |||
102 | let mut children = String::new(); | ||
103 | match item { | ||
104 | ModItem::ExternCrate(it) => { | ||
105 | format_to!(out, "{:?}", tree[it]); | ||
106 | } | ||
107 | ModItem::Import(it) => { | ||
108 | format_to!(out, "{:?}", tree[it]); | ||
109 | } | ||
110 | ModItem::Function(it) => { | ||
111 | format_to!(out, "{:?}", tree[it]); | ||
112 | } | ||
113 | ModItem::Struct(it) => { | ||
114 | format_to!(out, "{:?}", tree[it]); | ||
115 | } | ||
116 | ModItem::Union(it) => { | ||
117 | format_to!(out, "{:?}", tree[it]); | ||
118 | } | ||
119 | ModItem::Enum(it) => { | ||
120 | format_to!(out, "{:?}", tree[it]); | ||
121 | } | ||
122 | ModItem::Const(it) => { | ||
123 | format_to!(out, "{:?}", tree[it]); | ||
124 | } | ||
125 | ModItem::Static(it) => { | ||
126 | format_to!(out, "{:?}", tree[it]); | ||
127 | } | ||
128 | ModItem::Trait(it) => { | ||
129 | format_to!(out, "{:?}", tree[it]); | ||
130 | for item in &*tree[it].items { | ||
131 | fmt_mod_item(&mut children, tree, ModItem::from(*item)); | ||
132 | format_to!(children, "\n"); | ||
133 | } | ||
134 | } | ||
135 | ModItem::Impl(it) => { | ||
136 | format_to!(out, "{:?}", tree[it]); | ||
137 | for item in &*tree[it].items { | ||
138 | fmt_mod_item(&mut children, tree, ModItem::from(*item)); | ||
139 | format_to!(children, "\n"); | ||
140 | } | ||
141 | } | ||
142 | ModItem::TypeAlias(it) => { | ||
143 | format_to!(out, "{:?}", tree[it]); | ||
144 | } | ||
145 | ModItem::Mod(it) => { | ||
146 | format_to!(out, "{:?}", tree[it]); | ||
147 | match &tree[it].kind { | ||
148 | ModKind::Inline { items } => { | ||
149 | for item in &**items { | ||
150 | fmt_mod_item(&mut children, tree, *item); | ||
151 | format_to!(children, "\n"); | ||
152 | } | ||
153 | } | ||
154 | ModKind::Outline {} => {} | ||
155 | } | ||
156 | } | ||
157 | ModItem::MacroCall(it) => { | ||
158 | format_to!(out, "{:?}", tree[it]); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | for line in children.lines() { | ||
163 | format_to!(out, "\n> {}", line); | ||
164 | } | ||
165 | } | ||
166 | |||
167 | fn check(ra_fixture: &str, expect: Expect) { | ||
168 | let actual = print_item_tree(ra_fixture); | ||
169 | expect.assert_eq(&actual); | ||
170 | } | ||
171 | |||
172 | #[test] | ||
173 | fn smoke() { | ||
174 | check( | ||
175 | r" | ||
176 | #![attr] | ||
177 | |||
178 | #[attr_on_use] | ||
179 | use {a, b::*}; | ||
180 | |||
181 | #[ext_crate] | ||
182 | extern crate krate; | ||
183 | |||
184 | #[on_trait] | ||
185 | trait Tr<U> { | ||
186 | #[assoc_ty] | ||
187 | type AssocTy: Tr<()>; | ||
188 | |||
189 | #[assoc_const] | ||
190 | const CONST: u8; | ||
191 | |||
192 | #[assoc_method] | ||
193 | fn method(&self); | ||
194 | |||
195 | #[assoc_dfl_method] | ||
196 | fn dfl_method(&mut self) {} | ||
197 | } | ||
198 | |||
199 | #[struct0] | ||
200 | struct Struct0<T = ()>; | ||
201 | |||
202 | #[struct1] | ||
203 | struct Struct1<T>(#[struct1fld] u8); | ||
204 | |||
205 | #[struct2] | ||
206 | struct Struct2<T> { | ||
207 | #[struct2fld] | ||
208 | fld: (T, ), | ||
209 | } | ||
210 | |||
211 | #[en] | ||
212 | enum En { | ||
213 | #[enum_variant] | ||
214 | Variant { | ||
215 | #[enum_field] | ||
216 | field: u8, | ||
217 | }, | ||
218 | } | ||
219 | |||
220 | #[un] | ||
221 | union Un { | ||
222 | #[union_fld] | ||
223 | fld: u16, | ||
224 | } | ||
225 | ", | ||
226 | expect![[r##" | ||
227 | inner attrs: Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr"))] }, input: None }]) } | ||
228 | |||
229 | top-level items: | ||
230 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_on_use"))] }, input: None }]) }] | ||
231 | Import { path: ModPath { kind: Plain, segments: [Name(Text("a"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: false, is_prelude: false, ast_id: FileAstId::<syntax::ast::generated::nodes::Use>(0), index: 0 } | ||
232 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_on_use"))] }, input: None }]) }] | ||
233 | Import { path: ModPath { kind: Plain, segments: [Name(Text("b"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: true, is_prelude: false, ast_id: FileAstId::<syntax::ast::generated::nodes::Use>(0), index: 1 } | ||
234 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("ext_crate"))] }, input: None }]) }] | ||
235 | ExternCrate { name: Name(Text("krate")), alias: None, visibility: RawVisibilityId("pub(self)"), is_macro_use: false, ast_id: FileAstId::<syntax::ast::generated::nodes::ExternCrate>(1) } | ||
236 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_trait"))] }, input: None }]) }] | ||
237 | Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [TypeAlias(Idx::<TypeAlias>(0)), Const(Idx::<Const>(0)), Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<syntax::ast::generated::nodes::Trait>(2) } | ||
238 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_ty"))] }, input: None }]) }] | ||
239 | > TypeAlias { name: Name(Text("AssocTy")), visibility: RawVisibilityId("pub(self)"), bounds: [Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Tr"))] }, generic_args: [Some(GenericArgs { args: [Type(Tuple([]))], has_self_type: false, bindings: [] })] })], generic_params: GenericParamsId(4294967295), type_ref: None, is_extern: false, ast_id: FileAstId::<syntax::ast::generated::nodes::TypeAlias>(8) } | ||
240 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_const"))] }, input: None }]) }] | ||
241 | > Const { name: Some(Name(Text("CONST"))), visibility: RawVisibilityId("pub(self)"), type_ref: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u8"))] }, generic_args: [None] }), ast_id: FileAstId::<syntax::ast::generated::nodes::Const>(9) } | ||
242 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_method"))] }, input: None }]) }] | ||
243 | > Function { name: Name(Text("method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, has_body: false, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Shared)], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(10) } | ||
244 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_dfl_method"))] }, input: None }]) }] | ||
245 | > Function { name: Name(Text("dfl_method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, has_body: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Mut)], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(11) } | ||
246 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct0"))] }, input: None }]) }] | ||
247 | Struct { name: Name(Text("Struct0")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), fields: Unit, ast_id: FileAstId::<syntax::ast::generated::nodes::Struct>(3), kind: Unit } | ||
248 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct1"))] }, input: None }]) }] | ||
249 | Struct { name: Name(Text("Struct1")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(2), fields: Tuple(IdRange::<hir_def::item_tree::Field>(0..1)), ast_id: FileAstId::<syntax::ast::generated::nodes::Struct>(4), kind: Tuple } | ||
250 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct2"))] }, input: None }]) }] | ||
251 | Struct { name: Name(Text("Struct2")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(3), fields: Record(IdRange::<hir_def::item_tree::Field>(1..2)), ast_id: FileAstId::<syntax::ast::generated::nodes::Struct>(5), kind: Record } | ||
252 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("en"))] }, input: None }]) }] | ||
253 | Enum { name: Name(Text("En")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), variants: IdRange::<hir_def::item_tree::Variant>(0..1), ast_id: FileAstId::<syntax::ast::generated::nodes::Enum>(6) } | ||
254 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("un"))] }, input: None }]) }] | ||
255 | Union { name: Name(Text("Un")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), fields: Record(IdRange::<hir_def::item_tree::Field>(3..4)), ast_id: FileAstId::<syntax::ast::generated::nodes::Union>(7) } | ||
256 | "##]], | ||
257 | ); | ||
258 | } | ||
259 | |||
260 | #[test] | ||
261 | fn simple_inner_items() { | ||
262 | check( | ||
263 | r" | ||
264 | impl<T:A> D for Response<T> { | ||
265 | fn foo() { | ||
266 | end(); | ||
267 | fn end<W: Write>() { | ||
268 | let _x: T = loop {}; | ||
269 | } | ||
270 | } | ||
271 | } | ||
272 | ", | ||
273 | expect![[r#" | ||
274 | inner attrs: Attrs { entries: None } | ||
275 | |||
276 | top-level items: | ||
277 | Impl { generic_params: GenericParamsId(0), target_trait: Some(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("D"))] }, generic_args: [None] })), target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Response"))] }, generic_args: [Some(GenericArgs { args: [Type(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("T"))] }, generic_args: [None] }))], has_self_type: false, bindings: [] })] }), is_negative: false, items: [Function(Idx::<Function>(1))], ast_id: FileAstId::<syntax::ast::generated::nodes::Impl>(0) } | ||
278 | > Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, has_body: true, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(1) } | ||
279 | |||
280 | inner items: | ||
281 | |||
282 | for AST FileAstId::<syntax::ast::generated::nodes::Item>(2): | ||
283 | Function { name: Name(Text("end")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), has_self_param: false, has_body: true, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(2) } | ||
284 | |||
285 | "#]], | ||
286 | ); | ||
287 | } | ||
288 | |||
289 | #[test] | ||
290 | fn extern_attrs() { | ||
291 | check( | ||
292 | r#" | ||
293 | #[block_attr] | ||
294 | extern "C" { | ||
295 | #[attr_a] | ||
296 | fn a() {} | ||
297 | #[attr_b] | ||
298 | fn b() {} | ||
299 | } | ||
300 | "#, | ||
301 | expect![[r##" | ||
302 | inner attrs: Attrs { entries: None } | ||
303 | |||
304 | top-level items: | ||
305 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }] | ||
306 | Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, has_body: true, is_unsafe: true, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(1) } | ||
307 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }] | ||
308 | Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, has_body: true, is_unsafe: true, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(2) } | ||
309 | "##]], | ||
310 | ); | ||
311 | } | ||
312 | |||
313 | #[test] | ||
314 | fn trait_attrs() { | ||
315 | check( | ||
316 | r#" | ||
317 | #[trait_attr] | ||
318 | trait Tr { | ||
319 | #[attr_a] | ||
320 | fn a() {} | ||
321 | #[attr_b] | ||
322 | fn b() {} | ||
323 | } | ||
324 | "#, | ||
325 | expect![[r##" | ||
326 | inner attrs: Attrs { entries: None } | ||
327 | |||
328 | top-level items: | ||
329 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("trait_attr"))] }, input: None }]) }] | ||
330 | Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<syntax::ast::generated::nodes::Trait>(0) } | ||
331 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }] | ||
332 | > Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, has_body: true, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(1) } | ||
333 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }] | ||
334 | > Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, has_body: true, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(2) } | ||
335 | "##]], | ||
336 | ); | ||
337 | } | ||
338 | |||
339 | #[test] | ||
340 | fn impl_attrs() { | ||
341 | check( | ||
342 | r#" | ||
343 | #[impl_attr] | ||
344 | impl Ty { | ||
345 | #[attr_a] | ||
346 | fn a() {} | ||
347 | #[attr_b] | ||
348 | fn b() {} | ||
349 | } | ||
350 | "#, | ||
351 | expect![[r##" | ||
352 | inner attrs: Attrs { entries: None } | ||
353 | |||
354 | top-level items: | ||
355 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("impl_attr"))] }, input: None }]) }] | ||
356 | Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Ty"))] }, generic_args: [None] }), is_negative: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<syntax::ast::generated::nodes::Impl>(0) } | ||
357 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }] | ||
358 | > Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, has_body: true, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(1) } | ||
359 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }] | ||
360 | > Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, has_body: true, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(2) } | ||
361 | "##]], | ||
362 | ); | ||
363 | } | ||
364 | |||
365 | #[test] | ||
366 | fn cursed_inner_items() { | ||
367 | test_inner_items( | ||
368 | r" | ||
369 | struct S<T: Trait = [u8; { fn f() {} 0 }]>(T); | ||
370 | |||
371 | enum En { | ||
372 | Var1 { | ||
373 | t: [(); { trait Inner {} 0 }], | ||
374 | }, | ||
375 | |||
376 | Var2([u16; { enum Inner {} 0 }]), | ||
377 | } | ||
378 | |||
379 | type Ty = [En; { struct Inner; 0 }]; | ||
380 | |||
381 | impl En { | ||
382 | fn assoc() { | ||
383 | trait InnerTrait<T = [u8; { fn f() {} }]> {} | ||
384 | struct InnerStruct<T = [u8; { fn f() {} }]> {} | ||
385 | impl<T = [u8; { fn f() {} }]> InnerTrait for InnerStruct {} | ||
386 | } | ||
387 | } | ||
388 | |||
389 | trait Tr<T = [u8; { fn f() {} }]> { | ||
390 | type AssocTy = [u8; { fn f() {} }]; | ||
391 | |||
392 | const AssocConst: [u8; { fn f() {} }]; | ||
393 | } | ||
394 | ", | ||
395 | ); | ||
396 | } | ||
397 | |||
398 | #[test] | ||
399 | fn inner_item_attrs() { | ||
400 | check( | ||
401 | r" | ||
402 | fn foo() { | ||
403 | #[on_inner] | ||
404 | fn inner() {} | ||
405 | } | ||
406 | ", | ||
407 | expect![[r##" | ||
408 | inner attrs: Attrs { entries: None } | ||
409 | |||
410 | top-level items: | ||
411 | Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, has_body: true, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(0) } | ||
412 | |||
413 | inner items: | ||
414 | |||
415 | for AST FileAstId::<syntax::ast::generated::nodes::Item>(1): | ||
416 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_inner"))] }, input: None }]) }] | ||
417 | Function { name: Name(Text("inner")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, has_body: true, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<syntax::ast::generated::nodes::Fn>(1) } | ||
418 | |||
419 | "##]], | ||
420 | ); | ||
421 | } | ||
422 | |||
423 | #[test] | ||
424 | fn assoc_item_macros() { | ||
425 | check( | ||
426 | r" | ||
427 | impl S { | ||
428 | items!(); | ||
429 | } | ||
430 | ", | ||
431 | expect![[r#" | ||
432 | inner attrs: Attrs { entries: None } | ||
433 | |||
434 | top-level items: | ||
435 | Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("S"))] }, generic_args: [None] }), is_negative: false, items: [MacroCall(Idx::<MacroCall>(0))], ast_id: FileAstId::<syntax::ast::generated::nodes::Impl>(0) } | ||
436 | > MacroCall { name: None, path: ModPath { kind: Plain, segments: [Name(Text("items"))] }, is_export: false, is_local_inner: false, is_builtin: false, ast_id: FileAstId::<syntax::ast::generated::nodes::MacroCall>(1) } | ||
437 | "#]], | ||
438 | ); | ||
439 | } | ||