diff options
Diffstat (limited to 'crates/ide/src/references.rs')
-rw-r--r-- | crates/ide/src/references.rs | 686 |
1 files changed, 415 insertions, 271 deletions
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index df9c31aef..fef70533d 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs | |||
@@ -11,171 +11,120 @@ | |||
11 | 11 | ||
12 | pub(crate) mod rename; | 12 | pub(crate) mod rename; |
13 | 13 | ||
14 | use either::Either; | 14 | use hir::{PathResolution, Semantics}; |
15 | use hir::Semantics; | ||
16 | use ide_db::{ | 15 | use ide_db::{ |
17 | base_db::FileId, | 16 | base_db::FileId, |
18 | defs::{Definition, NameClass, NameRefClass}, | 17 | defs::{Definition, NameClass, NameRefClass}, |
19 | search::{FileReference, ReferenceAccess, ReferenceKind, SearchScope, UsageSearchResult}, | 18 | search::{ReferenceAccess, SearchScope}, |
20 | RootDatabase, | 19 | RootDatabase, |
21 | }; | 20 | }; |
21 | use rustc_hash::FxHashMap; | ||
22 | use syntax::{ | 22 | use syntax::{ |
23 | algo::find_node_at_offset, | 23 | algo::find_node_at_offset, |
24 | ast::{self, NameOwner}, | 24 | ast::{self, NameOwner}, |
25 | AstNode, SyntaxNode, TextRange, TokenAtOffset, T, | 25 | match_ast, AstNode, SyntaxNode, TextRange, T, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo}; | 28 | use crate::{display::TryToNav, FilePosition, NavigationTarget}; |
29 | 29 | ||
30 | #[derive(Debug, Clone)] | 30 | #[derive(Debug, Clone)] |
31 | pub struct ReferenceSearchResult { | 31 | pub struct ReferenceSearchResult { |
32 | declaration: Declaration, | 32 | pub declaration: Declaration, |
33 | references: UsageSearchResult, | 33 | pub references: FxHashMap<FileId, Vec<(TextRange, Option<ReferenceAccess>)>>, |
34 | } | 34 | } |
35 | 35 | ||
36 | #[derive(Debug, Clone)] | 36 | #[derive(Debug, Clone)] |
37 | pub struct Declaration { | 37 | pub struct Declaration { |
38 | pub nav: NavigationTarget, | 38 | pub nav: NavigationTarget, |
39 | pub kind: ReferenceKind, | ||
40 | pub access: Option<ReferenceAccess>, | 39 | pub access: Option<ReferenceAccess>, |
41 | } | 40 | } |
42 | 41 | ||
43 | impl ReferenceSearchResult { | 42 | // Feature: Find All References |
44 | pub fn declaration(&self) -> &Declaration { | 43 | // |
45 | &self.declaration | 44 | // Shows all references of the item at the cursor location |
46 | } | 45 | // |
47 | 46 | // |=== | |
48 | pub fn decl_target(&self) -> &NavigationTarget { | 47 | // | Editor | Shortcut |
49 | &self.declaration.nav | 48 | // |
50 | } | 49 | // | VS Code | kbd:[Shift+Alt+F12] |
51 | 50 | // |=== | |
52 | pub fn references(&self) -> &UsageSearchResult { | ||
53 | &self.references | ||
54 | } | ||
55 | |||
56 | pub fn references_with_declaration(mut self) -> UsageSearchResult { | ||
57 | let decl_ref = FileReference { | ||
58 | range: self.declaration.nav.focus_or_full_range(), | ||
59 | kind: self.declaration.kind, | ||
60 | access: self.declaration.access, | ||
61 | }; | ||
62 | let file_id = self.declaration.nav.file_id; | ||
63 | self.references.references.entry(file_id).or_default().push(decl_ref); | ||
64 | self.references | ||
65 | } | ||
66 | |||
67 | /// Total number of references | ||
68 | /// At least 1 since all valid references should | ||
69 | /// Have a declaration | ||
70 | pub fn len(&self) -> usize { | ||
71 | self.references.len() + 1 | ||
72 | } | ||
73 | } | ||
74 | |||
75 | // allow turning ReferenceSearchResult into an iterator | ||
76 | // over References | ||
77 | impl IntoIterator for ReferenceSearchResult { | ||
78 | type Item = (FileId, Vec<FileReference>); | ||
79 | type IntoIter = std::collections::hash_map::IntoIter<FileId, Vec<FileReference>>; | ||
80 | |||
81 | fn into_iter(self) -> Self::IntoIter { | ||
82 | self.references_with_declaration().into_iter() | ||
83 | } | ||
84 | } | ||
85 | |||
86 | pub(crate) fn find_all_refs( | 51 | pub(crate) fn find_all_refs( |
87 | sema: &Semantics<RootDatabase>, | 52 | sema: &Semantics<RootDatabase>, |
88 | position: FilePosition, | 53 | position: FilePosition, |
89 | search_scope: Option<SearchScope>, | 54 | search_scope: Option<SearchScope>, |
90 | ) -> Option<RangeInfo<ReferenceSearchResult>> { | 55 | ) -> Option<ReferenceSearchResult> { |
91 | let _p = profile::span("find_all_refs"); | 56 | let _p = profile::span("find_all_refs"); |
92 | let syntax = sema.parse(position.file_id).syntax().clone(); | 57 | let syntax = sema.parse(position.file_id).syntax().clone(); |
93 | 58 | ||
94 | let (opt_name, search_kind) = if let Some(name) = | 59 | let (def, is_literal_search) = |
95 | get_struct_def_name_for_struct_literal_search(&sema, &syntax, position) | 60 | if let Some(name) = get_name_of_item_declaration(&syntax, position) { |
96 | { | 61 | (NameClass::classify(sema, &name)?.referenced_or_defined(sema.db), true) |
97 | (Some(name), ReferenceKind::StructLiteral) | 62 | } else { |
98 | } else if let Some(name) = get_enum_def_name_for_struct_literal_search(&sema, &syntax, position) | 63 | (find_def(&sema, &syntax, position)?, false) |
99 | { | 64 | }; |
100 | (Some(name), ReferenceKind::EnumLiteral) | ||
101 | } else { | ||
102 | ( | ||
103 | sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, position.offset), | ||
104 | ReferenceKind::Other, | ||
105 | ) | ||
106 | }; | ||
107 | |||
108 | let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; | ||
109 | 65 | ||
110 | let mut usages = def.usages(sema).set_scope(search_scope).all(); | 66 | let mut usages = def.usages(sema).set_scope(search_scope).all(); |
111 | usages | 67 | if is_literal_search { |
112 | .references | 68 | // filter for constructor-literals |
113 | .values_mut() | 69 | let refs = usages.references.values_mut(); |
114 | .for_each(|it| it.retain(|r| search_kind == ReferenceKind::Other || search_kind == r.kind)); | 70 | match def { |
115 | usages.references.retain(|_, it| !it.is_empty()); | 71 | Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(enum_))) => { |
116 | 72 | refs.for_each(|it| { | |
117 | let nav = def.try_to_nav(sema.db)?; | 73 | it.retain(|reference| { |
118 | let decl_range = nav.focus_or_full_range(); | 74 | reference |
119 | 75 | .name | |
120 | let mut kind = ReferenceKind::Other; | 76 | .as_name_ref() |
121 | if let Definition::Local(local) = def { | 77 | .map_or(false, |name_ref| is_enum_lit_name_ref(sema, enum_, name_ref)) |
122 | match local.source(sema.db).value { | 78 | }) |
123 | Either::Left(pat) => { | 79 | }); |
124 | if matches!( | 80 | usages.references.retain(|_, it| !it.is_empty()); |
125 | pat.syntax().parent().and_then(ast::RecordPatField::cast), | ||
126 | Some(pat_field) if pat_field.name_ref().is_none() | ||
127 | ) { | ||
128 | kind = ReferenceKind::FieldShorthandForLocal; | ||
129 | } | ||
130 | } | 81 | } |
131 | Either::Right(_) => kind = ReferenceKind::SelfParam, | 82 | Definition::ModuleDef(hir::ModuleDef::Adt(_)) |
83 | | Definition::ModuleDef(hir::ModuleDef::Variant(_)) => { | ||
84 | refs.for_each(|it| { | ||
85 | it.retain(|reference| { | ||
86 | reference.name.as_name_ref().map_or(false, is_lit_name_ref) | ||
87 | }) | ||
88 | }); | ||
89 | usages.references.retain(|_, it| !it.is_empty()); | ||
90 | } | ||
91 | _ => {} | ||
132 | } | 92 | } |
133 | } else if matches!( | 93 | } |
134 | def, | 94 | let nav = def.try_to_nav(sema.db)?; |
135 | Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_) | 95 | let decl_range = nav.focus_or_full_range(); |
136 | ) { | ||
137 | kind = ReferenceKind::Lifetime; | ||
138 | }; | ||
139 | 96 | ||
140 | let declaration = Declaration { nav, kind, access: decl_access(&def, &syntax, decl_range) }; | 97 | let declaration = Declaration { nav, access: decl_access(&def, &syntax, decl_range) }; |
98 | let references = usages | ||
99 | .into_iter() | ||
100 | .map(|(file_id, refs)| { | ||
101 | (file_id, refs.into_iter().map(|file_ref| (file_ref.range, file_ref.access)).collect()) | ||
102 | }) | ||
103 | .collect(); | ||
141 | 104 | ||
142 | Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references: usages })) | 105 | Some(ReferenceSearchResult { declaration, references }) |
143 | } | 106 | } |
144 | 107 | ||
145 | fn find_name( | 108 | fn find_def( |
146 | sema: &Semantics<RootDatabase>, | 109 | sema: &Semantics<RootDatabase>, |
147 | syntax: &SyntaxNode, | 110 | syntax: &SyntaxNode, |
148 | position: FilePosition, | 111 | position: FilePosition, |
149 | opt_name: Option<ast::Name>, | 112 | ) -> Option<Definition> { |
150 | ) -> Option<RangeInfo<Definition>> { | 113 | let def = match sema.find_node_at_offset_with_descend(syntax, position.offset)? { |
151 | if let Some(name) = opt_name { | 114 | ast::NameLike::NameRef(name_ref) => { |
152 | let def = NameClass::classify(sema, &name)?.referenced_or_defined(sema.db); | 115 | NameRefClass::classify(sema, &name_ref)?.referenced(sema.db) |
153 | let FileRange { range, .. } = sema.original_range(name.syntax()); | ||
154 | return Some(RangeInfo::new(range, def)); | ||
155 | } | ||
156 | |||
157 | let (FileRange { range, .. }, def) = if let Some(lifetime) = | ||
158 | sema.find_node_at_offset_with_descend::<ast::Lifetime>(&syntax, position.offset) | ||
159 | { | ||
160 | if let Some(def) = NameRefClass::classify_lifetime(sema, &lifetime) | ||
161 | .map(|class| NameRefClass::referenced(class, sema.db)) | ||
162 | { | ||
163 | (sema.original_range(lifetime.syntax()), def) | ||
164 | } else { | ||
165 | ( | ||
166 | sema.original_range(lifetime.syntax()), | ||
167 | NameClass::classify_lifetime(sema, &lifetime)?.referenced_or_defined(sema.db), | ||
168 | ) | ||
169 | } | 116 | } |
170 | } else { | 117 | ast::NameLike::Name(name) => { |
171 | let name_ref = | 118 | NameClass::classify(sema, &name)?.referenced_or_defined(sema.db) |
172 | sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?; | 119 | } |
173 | ( | 120 | ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime) |
174 | sema.original_range(name_ref.syntax()), | 121 | .map(|class| class.referenced(sema.db)) |
175 | NameRefClass::classify(sema, &name_ref)?.referenced(sema.db), | 122 | .or_else(|| { |
176 | ) | 123 | NameClass::classify_lifetime(sema, &lifetime) |
124 | .map(|class| class.referenced_or_defined(sema.db)) | ||
125 | })?, | ||
177 | }; | 126 | }; |
178 | Some(RangeInfo::new(range, def)) | 127 | Some(def) |
179 | } | 128 | } |
180 | 129 | ||
181 | fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Option<ReferenceAccess> { | 130 | fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Option<ReferenceAccess> { |
@@ -197,58 +146,85 @@ fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Optio | |||
197 | None | 146 | None |
198 | } | 147 | } |
199 | 148 | ||
200 | fn get_struct_def_name_for_struct_literal_search( | 149 | fn get_name_of_item_declaration(syntax: &SyntaxNode, position: FilePosition) -> Option<ast::Name> { |
201 | sema: &Semantics<RootDatabase>, | 150 | let token = syntax.token_at_offset(position.offset).right_biased()?; |
202 | syntax: &SyntaxNode, | 151 | let kind = token.kind(); |
203 | position: FilePosition, | 152 | if kind == T![;] { |
204 | ) -> Option<ast::Name> { | 153 | ast::Struct::cast(token.parent()) |
205 | if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) { | 154 | .filter(|struct_| struct_.field_list().is_none()) |
206 | if right.kind() != T!['{'] && right.kind() != T!['('] { | 155 | .and_then(|struct_| struct_.name()) |
207 | return None; | 156 | } else if kind == T!['{'] { |
208 | } | 157 | match_ast! { |
209 | if let Some(name) = | 158 | match (token.parent()) { |
210 | sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, left.text_range().start()) | 159 | ast::RecordFieldList(rfl) => match_ast! { |
211 | { | 160 | match (rfl.syntax().parent()?) { |
212 | return name.syntax().ancestors().find_map(ast::Struct::cast).and_then(|l| l.name()); | 161 | ast::Variant(it) => it.name(), |
162 | ast::Struct(it) => it.name(), | ||
163 | ast::Union(it) => it.name(), | ||
164 | _ => None, | ||
165 | } | ||
166 | }, | ||
167 | ast::VariantList(vl) => ast::Enum::cast(vl.syntax().parent()?)?.name(), | ||
168 | _ => None, | ||
169 | } | ||
213 | } | 170 | } |
214 | if sema | 171 | } else if kind == T!['('] { |
215 | .find_node_at_offset_with_descend::<ast::GenericParamList>( | 172 | let tfl = ast::TupleFieldList::cast(token.parent())?; |
216 | &syntax, | 173 | match_ast! { |
217 | left.text_range().start(), | 174 | match (tfl.syntax().parent()?) { |
218 | ) | 175 | ast::Variant(it) => it.name(), |
219 | .is_some() | 176 | ast::Struct(it) => it.name(), |
220 | { | 177 | _ => None, |
221 | return left.ancestors().find_map(ast::Struct::cast).and_then(|l| l.name()); | 178 | } |
222 | } | 179 | } |
180 | } else { | ||
181 | None | ||
223 | } | 182 | } |
224 | None | ||
225 | } | 183 | } |
226 | 184 | ||
227 | fn get_enum_def_name_for_struct_literal_search( | 185 | fn is_enum_lit_name_ref( |
228 | sema: &Semantics<RootDatabase>, | 186 | sema: &Semantics<RootDatabase>, |
229 | syntax: &SyntaxNode, | 187 | enum_: hir::Enum, |
230 | position: FilePosition, | 188 | name_ref: &ast::NameRef, |
231 | ) -> Option<ast::Name> { | 189 | ) -> bool { |
232 | if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) { | 190 | let path_is_variant_of_enum = |path: ast::Path| { |
233 | if right.kind() != T!['{'] && right.kind() != T!['('] { | 191 | matches!( |
234 | return None; | 192 | sema.resolve_path(&path), |
235 | } | 193 | Some(PathResolution::Def(hir::ModuleDef::Variant(variant))) |
236 | if let Some(name) = | 194 | if variant.parent_enum(sema.db) == enum_ |
237 | sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, left.text_range().start()) | 195 | ) |
238 | { | 196 | }; |
239 | return name.syntax().ancestors().find_map(ast::Enum::cast).and_then(|l| l.name()); | 197 | name_ref |
240 | } | 198 | .syntax() |
241 | if sema | 199 | .ancestors() |
242 | .find_node_at_offset_with_descend::<ast::GenericParamList>( | 200 | .find_map(|ancestor| { |
243 | &syntax, | 201 | match_ast! { |
244 | left.text_range().start(), | 202 | match ancestor { |
245 | ) | 203 | ast::PathExpr(path_expr) => path_expr.path().map(path_is_variant_of_enum), |
246 | .is_some() | 204 | ast::RecordExpr(record_expr) => record_expr.path().map(path_is_variant_of_enum), |
247 | { | 205 | _ => None, |
248 | return left.ancestors().find_map(ast::Enum::cast).and_then(|l| l.name()); | 206 | } |
207 | } | ||
208 | }) | ||
209 | .unwrap_or(false) | ||
210 | } | ||
211 | |||
212 | fn path_ends_with(path: Option<ast::Path>, name_ref: &ast::NameRef) -> bool { | ||
213 | path.and_then(|path| path.segment()) | ||
214 | .and_then(|segment| segment.name_ref()) | ||
215 | .map_or(false, |segment| segment == *name_ref) | ||
216 | } | ||
217 | |||
218 | fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool { | ||
219 | name_ref.syntax().ancestors().find_map(|ancestor| { | ||
220 | match_ast! { | ||
221 | match ancestor { | ||
222 | ast::PathExpr(path_expr) => Some(path_ends_with(path_expr.path(), name_ref)), | ||
223 | ast::RecordExpr(record_expr) => Some(path_ends_with(record_expr.path(), name_ref)), | ||
224 | _ => None, | ||
225 | } | ||
249 | } | 226 | } |
250 | } | 227 | }).unwrap_or(false) |
251 | None | ||
252 | } | 228 | } |
253 | 229 | ||
254 | #[cfg(test)] | 230 | #[cfg(test)] |
@@ -275,9 +251,9 @@ fn main() { | |||
275 | } | 251 | } |
276 | "#, | 252 | "#, |
277 | expect![[r#" | 253 | expect![[r#" |
278 | Foo Struct FileId(0) 0..26 7..10 Other | 254 | Foo Struct FileId(0) 0..26 7..10 |
279 | 255 | ||
280 | FileId(0) 101..104 StructLiteral | 256 | FileId(0) 101..104 |
281 | "#]], | 257 | "#]], |
282 | ); | 258 | ); |
283 | } | 259 | } |
@@ -293,10 +269,10 @@ struct Foo$0 {} | |||
293 | } | 269 | } |
294 | "#, | 270 | "#, |
295 | expect![[r#" | 271 | expect![[r#" |
296 | Foo Struct FileId(0) 0..13 7..10 Other | 272 | Foo Struct FileId(0) 0..13 7..10 |
297 | 273 | ||
298 | FileId(0) 41..44 Other | 274 | FileId(0) 41..44 |
299 | FileId(0) 54..57 StructLiteral | 275 | FileId(0) 54..57 |
300 | "#]], | 276 | "#]], |
301 | ); | 277 | ); |
302 | } | 278 | } |
@@ -312,9 +288,9 @@ struct Foo<T> $0{} | |||
312 | } | 288 | } |
313 | "#, | 289 | "#, |
314 | expect![[r#" | 290 | expect![[r#" |
315 | Foo Struct FileId(0) 0..16 7..10 Other | 291 | Foo Struct FileId(0) 0..16 7..10 |
316 | 292 | ||
317 | FileId(0) 64..67 StructLiteral | 293 | FileId(0) 64..67 |
318 | "#]], | 294 | "#]], |
319 | ); | 295 | ); |
320 | } | 296 | } |
@@ -331,9 +307,30 @@ fn main() { | |||
331 | } | 307 | } |
332 | "#, | 308 | "#, |
333 | expect![[r#" | 309 | expect![[r#" |
334 | Foo Struct FileId(0) 0..16 7..10 Other | 310 | Foo Struct FileId(0) 0..16 7..10 |
311 | |||
312 | FileId(0) 54..57 | ||
313 | "#]], | ||
314 | ); | ||
315 | } | ||
316 | |||
317 | #[test] | ||
318 | fn test_struct_literal_for_union() { | ||
319 | check( | ||
320 | r#" | ||
321 | union Foo $0{ | ||
322 | x: u32 | ||
323 | } | ||
324 | |||
325 | fn main() { | ||
326 | let f: Foo; | ||
327 | f = Foo { x: 1 }; | ||
328 | } | ||
329 | "#, | ||
330 | expect![[r#" | ||
331 | Foo Union FileId(0) 0..24 6..9 | ||
335 | 332 | ||
336 | FileId(0) 54..57 StructLiteral | 333 | FileId(0) 62..65 |
337 | "#]], | 334 | "#]], |
338 | ); | 335 | ); |
339 | } | 336 | } |
@@ -344,17 +341,65 @@ fn main() { | |||
344 | r#" | 341 | r#" |
345 | enum Foo $0{ | 342 | enum Foo $0{ |
346 | A, | 343 | A, |
347 | B, | 344 | B(), |
345 | C{}, | ||
348 | } | 346 | } |
349 | fn main() { | 347 | fn main() { |
350 | let f: Foo; | 348 | let f: Foo; |
351 | f = Foo::A; | 349 | f = Foo::A; |
350 | f = Foo::B(); | ||
351 | f = Foo::C{}; | ||
352 | } | ||
353 | "#, | ||
354 | expect![[r#" | ||
355 | Foo Enum FileId(0) 0..37 5..8 | ||
356 | |||
357 | FileId(0) 74..77 | ||
358 | FileId(0) 90..93 | ||
359 | FileId(0) 108..111 | ||
360 | "#]], | ||
361 | ); | ||
362 | } | ||
363 | |||
364 | #[test] | ||
365 | fn test_variant_record_after_space() { | ||
366 | check( | ||
367 | r#" | ||
368 | enum Foo { | ||
369 | A $0{ n: i32 }, | ||
370 | B, | ||
371 | } | ||
372 | fn main() { | ||
373 | let f: Foo; | ||
374 | f = Foo::B; | ||
375 | f = Foo::A { n: 92 }; | ||
352 | } | 376 | } |
353 | "#, | 377 | "#, |
354 | expect![[r#" | 378 | expect![[r#" |
355 | Foo Enum FileId(0) 0..26 5..8 Other | 379 | A Variant FileId(0) 15..27 15..16 |
356 | 380 | ||
357 | FileId(0) 63..66 EnumLiteral | 381 | FileId(0) 95..96 |
382 | "#]], | ||
383 | ); | ||
384 | } | ||
385 | #[test] | ||
386 | fn test_variant_tuple_before_paren() { | ||
387 | check( | ||
388 | r#" | ||
389 | enum Foo { | ||
390 | A$0(i32), | ||
391 | B, | ||
392 | } | ||
393 | fn main() { | ||
394 | let f: Foo; | ||
395 | f = Foo::B; | ||
396 | f = Foo::A(92); | ||
397 | } | ||
398 | "#, | ||
399 | expect![[r#" | ||
400 | A Variant FileId(0) 15..21 15..16 | ||
401 | |||
402 | FileId(0) 89..90 | ||
358 | "#]], | 403 | "#]], |
359 | ); | 404 | ); |
360 | } | 405 | } |
@@ -373,10 +418,10 @@ fn main() { | |||
373 | } | 418 | } |
374 | "#, | 419 | "#, |
375 | expect![[r#" | 420 | expect![[r#" |
376 | Foo Enum FileId(0) 0..26 5..8 Other | 421 | Foo Enum FileId(0) 0..26 5..8 |
377 | 422 | ||
378 | FileId(0) 50..53 Other | 423 | FileId(0) 50..53 |
379 | FileId(0) 63..66 EnumLiteral | 424 | FileId(0) 63..66 |
380 | "#]], | 425 | "#]], |
381 | ); | 426 | ); |
382 | } | 427 | } |
@@ -395,9 +440,9 @@ fn main() { | |||
395 | } | 440 | } |
396 | "#, | 441 | "#, |
397 | expect![[r#" | 442 | expect![[r#" |
398 | Foo Enum FileId(0) 0..32 5..8 Other | 443 | Foo Enum FileId(0) 0..32 5..8 |
399 | 444 | ||
400 | FileId(0) 73..76 EnumLiteral | 445 | FileId(0) 73..76 |
401 | "#]], | 446 | "#]], |
402 | ); | 447 | ); |
403 | } | 448 | } |
@@ -416,9 +461,9 @@ fn main() { | |||
416 | } | 461 | } |
417 | "#, | 462 | "#, |
418 | expect![[r#" | 463 | expect![[r#" |
419 | Foo Enum FileId(0) 0..33 5..8 Other | 464 | Foo Enum FileId(0) 0..33 5..8 |
420 | 465 | ||
421 | FileId(0) 70..73 EnumLiteral | 466 | FileId(0) 70..73 |
422 | "#]], | 467 | "#]], |
423 | ); | 468 | ); |
424 | } | 469 | } |
@@ -439,12 +484,12 @@ fn main() { | |||
439 | i = 5; | 484 | i = 5; |
440 | }"#, | 485 | }"#, |
441 | expect![[r#" | 486 | expect![[r#" |
442 | i Local FileId(0) 20..25 24..25 Other Write | 487 | i Local FileId(0) 20..25 24..25 Write |
443 | 488 | ||
444 | FileId(0) 50..51 Other Write | 489 | FileId(0) 50..51 Write |
445 | FileId(0) 54..55 Other Read | 490 | FileId(0) 54..55 Read |
446 | FileId(0) 76..77 Other Write | 491 | FileId(0) 76..77 Write |
447 | FileId(0) 94..95 Other Write | 492 | FileId(0) 94..95 Write |
448 | "#]], | 493 | "#]], |
449 | ); | 494 | ); |
450 | } | 495 | } |
@@ -463,10 +508,10 @@ fn bar() { | |||
463 | } | 508 | } |
464 | "#, | 509 | "#, |
465 | expect![[r#" | 510 | expect![[r#" |
466 | spam Local FileId(0) 19..23 19..23 Other | 511 | spam Local FileId(0) 19..23 19..23 |
467 | 512 | ||
468 | FileId(0) 34..38 Other Read | 513 | FileId(0) 34..38 Read |
469 | FileId(0) 41..45 Other Read | 514 | FileId(0) 41..45 Read |
470 | "#]], | 515 | "#]], |
471 | ); | 516 | ); |
472 | } | 517 | } |
@@ -478,9 +523,9 @@ fn bar() { | |||
478 | fn foo(i : u32) -> u32 { i$0 } | 523 | fn foo(i : u32) -> u32 { i$0 } |
479 | "#, | 524 | "#, |
480 | expect![[r#" | 525 | expect![[r#" |
481 | i ValueParam FileId(0) 7..8 7..8 Other | 526 | i ValueParam FileId(0) 7..8 7..8 |
482 | 527 | ||
483 | FileId(0) 25..26 Other Read | 528 | FileId(0) 25..26 Read |
484 | "#]], | 529 | "#]], |
485 | ); | 530 | ); |
486 | } | 531 | } |
@@ -492,9 +537,9 @@ fn foo(i : u32) -> u32 { i$0 } | |||
492 | fn foo(i$0 : u32) -> u32 { i } | 537 | fn foo(i$0 : u32) -> u32 { i } |
493 | "#, | 538 | "#, |
494 | expect![[r#" | 539 | expect![[r#" |
495 | i ValueParam FileId(0) 7..8 7..8 Other | 540 | i ValueParam FileId(0) 7..8 7..8 |
496 | 541 | ||
497 | FileId(0) 25..26 Other Read | 542 | FileId(0) 25..26 Read |
498 | "#]], | 543 | "#]], |
499 | ); | 544 | ); |
500 | } | 545 | } |
@@ -513,9 +558,9 @@ fn main(s: Foo) { | |||
513 | } | 558 | } |
514 | "#, | 559 | "#, |
515 | expect![[r#" | 560 | expect![[r#" |
516 | spam Field FileId(0) 17..30 21..25 Other | 561 | spam Field FileId(0) 17..30 21..25 |
517 | 562 | ||
518 | FileId(0) 67..71 Other Read | 563 | FileId(0) 67..71 Read |
519 | "#]], | 564 | "#]], |
520 | ); | 565 | ); |
521 | } | 566 | } |
@@ -530,7 +575,7 @@ impl Foo { | |||
530 | } | 575 | } |
531 | "#, | 576 | "#, |
532 | expect![[r#" | 577 | expect![[r#" |
533 | f Function FileId(0) 27..43 30..31 Other | 578 | f Function FileId(0) 27..43 30..31 |
534 | 579 | ||
535 | "#]], | 580 | "#]], |
536 | ); | 581 | ); |
@@ -547,7 +592,7 @@ enum Foo { | |||
547 | } | 592 | } |
548 | "#, | 593 | "#, |
549 | expect![[r#" | 594 | expect![[r#" |
550 | B Variant FileId(0) 22..23 22..23 Other | 595 | B Variant FileId(0) 22..23 22..23 |
551 | 596 | ||
552 | "#]], | 597 | "#]], |
553 | ); | 598 | ); |
@@ -564,7 +609,7 @@ enum Foo { | |||
564 | } | 609 | } |
565 | "#, | 610 | "#, |
566 | expect![[r#" | 611 | expect![[r#" |
567 | field Field FileId(0) 26..35 26..31 Other | 612 | field Field FileId(0) 26..35 26..31 |
568 | 613 | ||
569 | "#]], | 614 | "#]], |
570 | ); | 615 | ); |
@@ -605,10 +650,10 @@ fn f() { | |||
605 | } | 650 | } |
606 | "#, | 651 | "#, |
607 | expect![[r#" | 652 | expect![[r#" |
608 | Foo Struct FileId(1) 17..51 28..31 Other | 653 | Foo Struct FileId(1) 17..51 28..31 |
609 | 654 | ||
610 | FileId(0) 53..56 StructLiteral | 655 | FileId(0) 53..56 |
611 | FileId(2) 79..82 StructLiteral | 656 | FileId(2) 79..82 |
612 | "#]], | 657 | "#]], |
613 | ); | 658 | ); |
614 | } | 659 | } |
@@ -635,9 +680,9 @@ pub struct Foo { | |||
635 | } | 680 | } |
636 | "#, | 681 | "#, |
637 | expect![[r#" | 682 | expect![[r#" |
638 | foo Module FileId(1) 0..35 Other | 683 | foo Module FileId(1) 0..35 |
639 | 684 | ||
640 | FileId(0) 14..17 Other | 685 | FileId(0) 14..17 |
641 | "#]], | 686 | "#]], |
642 | ); | 687 | ); |
643 | } | 688 | } |
@@ -663,10 +708,10 @@ pub(super) struct Foo$0 { | |||
663 | } | 708 | } |
664 | "#, | 709 | "#, |
665 | expect![[r#" | 710 | expect![[r#" |
666 | Foo Struct FileId(2) 0..41 18..21 Other | 711 | Foo Struct FileId(2) 0..41 18..21 |
667 | 712 | ||
668 | FileId(1) 20..23 Other | 713 | FileId(1) 20..23 |
669 | FileId(1) 47..50 StructLiteral | 714 | FileId(1) 47..50 |
670 | "#]], | 715 | "#]], |
671 | ); | 716 | ); |
672 | } | 717 | } |
@@ -691,10 +736,10 @@ pub(super) struct Foo$0 { | |||
691 | code, | 736 | code, |
692 | None, | 737 | None, |
693 | expect![[r#" | 738 | expect![[r#" |
694 | quux Function FileId(0) 19..35 26..30 Other | 739 | quux Function FileId(0) 19..35 26..30 |
695 | 740 | ||
696 | FileId(1) 16..20 StructLiteral | 741 | FileId(1) 16..20 |
697 | FileId(2) 16..20 StructLiteral | 742 | FileId(2) 16..20 |
698 | "#]], | 743 | "#]], |
699 | ); | 744 | ); |
700 | 745 | ||
@@ -702,9 +747,9 @@ pub(super) struct Foo$0 { | |||
702 | code, | 747 | code, |
703 | Some(SearchScope::single_file(FileId(2))), | 748 | Some(SearchScope::single_file(FileId(2))), |
704 | expect![[r#" | 749 | expect![[r#" |
705 | quux Function FileId(0) 19..35 26..30 Other | 750 | quux Function FileId(0) 19..35 26..30 |
706 | 751 | ||
707 | FileId(2) 16..20 StructLiteral | 752 | FileId(2) 16..20 |
708 | "#]], | 753 | "#]], |
709 | ); | 754 | ); |
710 | } | 755 | } |
@@ -722,10 +767,10 @@ fn foo() { | |||
722 | } | 767 | } |
723 | "#, | 768 | "#, |
724 | expect![[r#" | 769 | expect![[r#" |
725 | m1 Macro FileId(0) 0..46 29..31 Other | 770 | m1 Macro FileId(0) 0..46 29..31 |
726 | 771 | ||
727 | FileId(0) 63..65 StructLiteral | 772 | FileId(0) 63..65 |
728 | FileId(0) 73..75 StructLiteral | 773 | FileId(0) 73..75 |
729 | "#]], | 774 | "#]], |
730 | ); | 775 | ); |
731 | } | 776 | } |
@@ -740,10 +785,10 @@ fn foo() { | |||
740 | } | 785 | } |
741 | "#, | 786 | "#, |
742 | expect![[r#" | 787 | expect![[r#" |
743 | i Local FileId(0) 19..24 23..24 Other Write | 788 | i Local FileId(0) 19..24 23..24 Write |
744 | 789 | ||
745 | FileId(0) 34..35 Other Write | 790 | FileId(0) 34..35 Write |
746 | FileId(0) 38..39 Other Read | 791 | FileId(0) 38..39 Read |
747 | "#]], | 792 | "#]], |
748 | ); | 793 | ); |
749 | } | 794 | } |
@@ -762,10 +807,10 @@ fn foo() { | |||
762 | } | 807 | } |
763 | "#, | 808 | "#, |
764 | expect![[r#" | 809 | expect![[r#" |
765 | f Field FileId(0) 15..21 15..16 Other | 810 | f Field FileId(0) 15..21 15..16 |
766 | 811 | ||
767 | FileId(0) 55..56 RecordFieldExprOrPat Read | 812 | FileId(0) 55..56 Read |
768 | FileId(0) 68..69 Other Write | 813 | FileId(0) 68..69 Write |
769 | "#]], | 814 | "#]], |
770 | ); | 815 | ); |
771 | } | 816 | } |
@@ -780,9 +825,9 @@ fn foo() { | |||
780 | } | 825 | } |
781 | "#, | 826 | "#, |
782 | expect![[r#" | 827 | expect![[r#" |
783 | i Local FileId(0) 19..20 19..20 Other | 828 | i Local FileId(0) 19..20 19..20 |
784 | 829 | ||
785 | FileId(0) 26..27 Other Write | 830 | FileId(0) 26..27 Write |
786 | "#]], | 831 | "#]], |
787 | ); | 832 | ); |
788 | } | 833 | } |
@@ -804,9 +849,9 @@ fn main() { | |||
804 | } | 849 | } |
805 | "#, | 850 | "#, |
806 | expect![[r#" | 851 | expect![[r#" |
807 | new Function FileId(0) 54..81 61..64 Other | 852 | new Function FileId(0) 54..81 61..64 |
808 | 853 | ||
809 | FileId(0) 126..129 StructLiteral | 854 | FileId(0) 126..129 |
810 | "#]], | 855 | "#]], |
811 | ); | 856 | ); |
812 | } | 857 | } |
@@ -826,10 +871,10 @@ use crate::f; | |||
826 | fn g() { f(); } | 871 | fn g() { f(); } |
827 | "#, | 872 | "#, |
828 | expect![[r#" | 873 | expect![[r#" |
829 | f Function FileId(0) 22..31 25..26 Other | 874 | f Function FileId(0) 22..31 25..26 |
830 | 875 | ||
831 | FileId(1) 11..12 Other | 876 | FileId(1) 11..12 |
832 | FileId(1) 24..25 StructLiteral | 877 | FileId(1) 24..25 |
833 | "#]], | 878 | "#]], |
834 | ); | 879 | ); |
835 | } | 880 | } |
@@ -849,9 +894,9 @@ fn f(s: S) { | |||
849 | } | 894 | } |
850 | "#, | 895 | "#, |
851 | expect![[r#" | 896 | expect![[r#" |
852 | field Field FileId(0) 15..24 15..20 Other | 897 | field Field FileId(0) 15..24 15..20 |
853 | 898 | ||
854 | FileId(0) 68..73 FieldShorthandForField Read | 899 | FileId(0) 68..73 Read |
855 | "#]], | 900 | "#]], |
856 | ); | 901 | ); |
857 | } | 902 | } |
@@ -873,9 +918,9 @@ fn f(e: En) { | |||
873 | } | 918 | } |
874 | "#, | 919 | "#, |
875 | expect![[r#" | 920 | expect![[r#" |
876 | field Field FileId(0) 32..41 32..37 Other | 921 | field Field FileId(0) 32..41 32..37 |
877 | 922 | ||
878 | FileId(0) 102..107 FieldShorthandForField Read | 923 | FileId(0) 102..107 Read |
879 | "#]], | 924 | "#]], |
880 | ); | 925 | ); |
881 | } | 926 | } |
@@ -897,9 +942,9 @@ fn f() -> m::En { | |||
897 | } | 942 | } |
898 | "#, | 943 | "#, |
899 | expect![[r#" | 944 | expect![[r#" |
900 | field Field FileId(0) 56..65 56..61 Other | 945 | field Field FileId(0) 56..65 56..61 |
901 | 946 | ||
902 | FileId(0) 125..130 RecordFieldExprOrPat Read | 947 | FileId(0) 125..130 Read |
903 | "#]], | 948 | "#]], |
904 | ); | 949 | ); |
905 | } | 950 | } |
@@ -922,10 +967,10 @@ impl Foo { | |||
922 | } | 967 | } |
923 | "#, | 968 | "#, |
924 | expect![[r#" | 969 | expect![[r#" |
925 | self SelfParam FileId(0) 47..51 47..51 SelfParam | 970 | self SelfParam FileId(0) 47..51 47..51 |
926 | 971 | ||
927 | FileId(0) 71..75 Other Read | 972 | FileId(0) 71..75 Read |
928 | FileId(0) 152..156 Other Read | 973 | FileId(0) 152..156 Read |
929 | "#]], | 974 | "#]], |
930 | ); | 975 | ); |
931 | } | 976 | } |
@@ -943,9 +988,9 @@ impl Foo { | |||
943 | } | 988 | } |
944 | "#, | 989 | "#, |
945 | expect![[r#" | 990 | expect![[r#" |
946 | self SelfParam FileId(0) 47..51 47..51 SelfParam | 991 | self SelfParam FileId(0) 47..51 47..51 |
947 | 992 | ||
948 | FileId(0) 63..67 Other Read | 993 | FileId(0) 63..67 Read |
949 | "#]], | 994 | "#]], |
950 | ); | 995 | ); |
951 | } | 996 | } |
@@ -961,7 +1006,7 @@ impl Foo { | |||
961 | let mut actual = String::new(); | 1006 | let mut actual = String::new(); |
962 | { | 1007 | { |
963 | let decl = refs.declaration; | 1008 | let decl = refs.declaration; |
964 | format_to!(actual, "{} {:?}", decl.nav.debug_render(), decl.kind); | 1009 | format_to!(actual, "{}", decl.nav.debug_render()); |
965 | if let Some(access) = decl.access { | 1010 | if let Some(access) = decl.access { |
966 | format_to!(actual, " {:?}", access) | 1011 | format_to!(actual, " {:?}", access) |
967 | } | 1012 | } |
@@ -969,9 +1014,9 @@ impl Foo { | |||
969 | } | 1014 | } |
970 | 1015 | ||
971 | for (file_id, references) in refs.references { | 1016 | for (file_id, references) in refs.references { |
972 | for r in references { | 1017 | for (range, access) in references { |
973 | format_to!(actual, "{:?} {:?} {:?}", file_id, r.range, r.kind); | 1018 | format_to!(actual, "{:?} {:?}", file_id, range); |
974 | if let Some(access) = r.access { | 1019 | if let Some(access) = access { |
975 | format_to!(actual, " {:?}", access); | 1020 | format_to!(actual, " {:?}", access); |
976 | } | 1021 | } |
977 | actual += "\n"; | 1022 | actual += "\n"; |
@@ -992,13 +1037,13 @@ fn foo<'a, 'b: 'a>(x: &'a$0 ()) -> &'a () where &'a (): Foo<'a> { | |||
992 | } | 1037 | } |
993 | "#, | 1038 | "#, |
994 | expect![[r#" | 1039 | expect![[r#" |
995 | 'a LifetimeParam FileId(0) 55..57 55..57 Lifetime | 1040 | 'a LifetimeParam FileId(0) 55..57 55..57 |
996 | 1041 | ||
997 | FileId(0) 63..65 Lifetime | 1042 | FileId(0) 63..65 |
998 | FileId(0) 71..73 Lifetime | 1043 | FileId(0) 71..73 |
999 | FileId(0) 82..84 Lifetime | 1044 | FileId(0) 82..84 |
1000 | FileId(0) 95..97 Lifetime | 1045 | FileId(0) 95..97 |
1001 | FileId(0) 106..108 Lifetime | 1046 | FileId(0) 106..108 |
1002 | "#]], | 1047 | "#]], |
1003 | ); | 1048 | ); |
1004 | } | 1049 | } |
@@ -1010,10 +1055,10 @@ fn foo<'a, 'b: 'a>(x: &'a$0 ()) -> &'a () where &'a (): Foo<'a> { | |||
1010 | type Foo<'a, T> where T: 'a$0 = &'a T; | 1055 | type Foo<'a, T> where T: 'a$0 = &'a T; |
1011 | "#, | 1056 | "#, |
1012 | expect![[r#" | 1057 | expect![[r#" |
1013 | 'a LifetimeParam FileId(0) 9..11 9..11 Lifetime | 1058 | 'a LifetimeParam FileId(0) 9..11 9..11 |
1014 | 1059 | ||
1015 | FileId(0) 25..27 Lifetime | 1060 | FileId(0) 25..27 |
1016 | FileId(0) 31..33 Lifetime | 1061 | FileId(0) 31..33 |
1017 | "#]], | 1062 | "#]], |
1018 | ); | 1063 | ); |
1019 | } | 1064 | } |
@@ -1032,11 +1077,11 @@ impl<'a> Foo<'a> for &'a () { | |||
1032 | } | 1077 | } |
1033 | "#, | 1078 | "#, |
1034 | expect![[r#" | 1079 | expect![[r#" |
1035 | 'a LifetimeParam FileId(0) 47..49 47..49 Lifetime | 1080 | 'a LifetimeParam FileId(0) 47..49 47..49 |
1036 | 1081 | ||
1037 | FileId(0) 55..57 Lifetime | 1082 | FileId(0) 55..57 |
1038 | FileId(0) 64..66 Lifetime | 1083 | FileId(0) 64..66 |
1039 | FileId(0) 89..91 Lifetime | 1084 | FileId(0) 89..91 |
1040 | "#]], | 1085 | "#]], |
1041 | ); | 1086 | ); |
1042 | } | 1087 | } |
@@ -1052,9 +1097,9 @@ fn main() { | |||
1052 | } | 1097 | } |
1053 | "#, | 1098 | "#, |
1054 | expect![[r#" | 1099 | expect![[r#" |
1055 | a Local FileId(0) 59..60 59..60 Other | 1100 | a Local FileId(0) 59..60 59..60 |
1056 | 1101 | ||
1057 | FileId(0) 80..81 Other Read | 1102 | FileId(0) 80..81 Read |
1058 | "#]], | 1103 | "#]], |
1059 | ); | 1104 | ); |
1060 | } | 1105 | } |
@@ -1070,9 +1115,9 @@ fn main() { | |||
1070 | } | 1115 | } |
1071 | "#, | 1116 | "#, |
1072 | expect![[r#" | 1117 | expect![[r#" |
1073 | a Local FileId(0) 59..60 59..60 Other | 1118 | a Local FileId(0) 59..60 59..60 |
1074 | 1119 | ||
1075 | FileId(0) 80..81 Other Read | 1120 | FileId(0) 80..81 Read |
1076 | "#]], | 1121 | "#]], |
1077 | ); | 1122 | ); |
1078 | } | 1123 | } |
@@ -1091,10 +1136,10 @@ fn foo<'a>() -> &'a () { | |||
1091 | } | 1136 | } |
1092 | "#, | 1137 | "#, |
1093 | expect![[r#" | 1138 | expect![[r#" |
1094 | 'a Label FileId(0) 29..32 29..31 Lifetime | 1139 | 'a Label FileId(0) 29..32 29..31 |
1095 | 1140 | ||
1096 | FileId(0) 80..82 Lifetime | 1141 | FileId(0) 80..82 |
1097 | FileId(0) 108..110 Lifetime | 1142 | FileId(0) 108..110 |
1098 | "#]], | 1143 | "#]], |
1099 | ); | 1144 | ); |
1100 | } | 1145 | } |
@@ -1108,9 +1153,108 @@ fn foo<const FOO$0: usize>() -> usize { | |||
1108 | } | 1153 | } |
1109 | "#, | 1154 | "#, |
1110 | expect![[r#" | 1155 | expect![[r#" |
1111 | FOO ConstParam FileId(0) 7..23 13..16 Other | 1156 | FOO ConstParam FileId(0) 7..23 13..16 |
1157 | |||
1158 | FileId(0) 42..45 | ||
1159 | "#]], | ||
1160 | ); | ||
1161 | } | ||
1162 | |||
1163 | #[test] | ||
1164 | fn test_find_self_ty_in_trait_def() { | ||
1165 | check( | ||
1166 | r#" | ||
1167 | trait Foo { | ||
1168 | fn f() -> Self$0; | ||
1169 | } | ||
1170 | "#, | ||
1171 | expect![[r#" | ||
1172 | Self TypeParam FileId(0) 6..9 6..9 | ||
1173 | |||
1174 | FileId(0) 26..30 | ||
1175 | "#]], | ||
1176 | ); | ||
1177 | } | ||
1178 | |||
1179 | #[test] | ||
1180 | fn test_self_variant_with_payload() { | ||
1181 | check( | ||
1182 | r#" | ||
1183 | enum Foo { Bar() } | ||
1184 | |||
1185 | impl Foo { | ||
1186 | fn foo(self) { | ||
1187 | match self { | ||
1188 | Self::Bar$0() => (), | ||
1189 | } | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1193 | "#, | ||
1194 | expect![[r#" | ||
1195 | Bar Variant FileId(0) 11..16 11..14 | ||
1196 | |||
1197 | FileId(0) 89..92 | ||
1198 | "#]], | ||
1199 | ); | ||
1200 | } | ||
1201 | |||
1202 | #[test] | ||
1203 | fn test_attr_differs_from_fn_with_same_name() { | ||
1204 | check( | ||
1205 | r#" | ||
1206 | #[test] | ||
1207 | fn test$0() { | ||
1208 | test(); | ||
1209 | } | ||
1210 | "#, | ||
1211 | expect![[r#" | ||
1212 | test Function FileId(0) 0..33 11..15 | ||
1213 | |||
1214 | FileId(0) 24..28 | ||
1215 | "#]], | ||
1216 | ); | ||
1217 | } | ||
1218 | |||
1219 | #[test] | ||
1220 | fn test_attr_matches_proc_macro_fn() { | ||
1221 | check( | ||
1222 | r#" | ||
1223 | #[proc_macro_attribute] | ||
1224 | fn my_proc_macro() {} | ||
1225 | |||
1226 | #[my_proc_macro$0] | ||
1227 | fn test() {} | ||
1228 | "#, | ||
1229 | expect![[r#" | ||
1230 | my_proc_macro Function FileId(0) 0..45 27..40 | ||
1231 | |||
1232 | FileId(0) 49..62 | ||
1233 | "#]], | ||
1234 | ); | ||
1235 | } | ||
1236 | |||
1237 | #[test] | ||
1238 | fn test_const_in_pattern() { | ||
1239 | check( | ||
1240 | r#" | ||
1241 | const A$0: i32 = 42; | ||
1242 | |||
1243 | fn main() { | ||
1244 | match A { | ||
1245 | A => (), | ||
1246 | _ => (), | ||
1247 | } | ||
1248 | if let A = A {} | ||
1249 | } | ||
1250 | "#, | ||
1251 | expect![[r#" | ||
1252 | A Const FileId(0) 0..18 6..7 | ||
1112 | 1253 | ||
1113 | FileId(0) 42..45 Other | 1254 | FileId(0) 42..43 |
1255 | FileId(0) 54..55 | ||
1256 | FileId(0) 97..98 | ||
1257 | FileId(0) 101..102 | ||
1114 | "#]], | 1258 | "#]], |
1115 | ); | 1259 | ); |
1116 | } | 1260 | } |