diff options
-rw-r--r-- | crates/ide/src/references.rs | 115 | ||||
-rw-r--r-- | crates/ide_db/src/search.rs | 15 |
2 files changed, 130 insertions, 0 deletions
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 7395b81bd..66f0f7950 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs | |||
@@ -97,6 +97,9 @@ pub(crate) fn find_all_refs( | |||
97 | get_struct_def_name_for_struct_literal_search(&sema, &syntax, position) | 97 | get_struct_def_name_for_struct_literal_search(&sema, &syntax, position) |
98 | { | 98 | { |
99 | (Some(name), ReferenceKind::StructLiteral) | 99 | (Some(name), ReferenceKind::StructLiteral) |
100 | } else if let Some(name) = get_enum_def_name_for_struct_literal_search(&sema, &syntax, position) | ||
101 | { | ||
102 | (Some(name), ReferenceKind::EnumLiteral) | ||
100 | } else { | 103 | } else { |
101 | ( | 104 | ( |
102 | sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, position.offset), | 105 | sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, position.offset), |
@@ -198,6 +201,33 @@ fn get_struct_def_name_for_struct_literal_search( | |||
198 | None | 201 | None |
199 | } | 202 | } |
200 | 203 | ||
204 | fn get_enum_def_name_for_struct_literal_search( | ||
205 | sema: &Semantics<RootDatabase>, | ||
206 | syntax: &SyntaxNode, | ||
207 | position: FilePosition, | ||
208 | ) -> Option<ast::Name> { | ||
209 | if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) { | ||
210 | if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN { | ||
211 | return None; | ||
212 | } | ||
213 | if let Some(name) = | ||
214 | sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, left.text_range().start()) | ||
215 | { | ||
216 | return name.syntax().ancestors().find_map(ast::Enum::cast).and_then(|l| l.name()); | ||
217 | } | ||
218 | if sema | ||
219 | .find_node_at_offset_with_descend::<ast::GenericParamList>( | ||
220 | &syntax, | ||
221 | left.text_range().start(), | ||
222 | ) | ||
223 | .is_some() | ||
224 | { | ||
225 | return left.ancestors().find_map(ast::Enum::cast).and_then(|l| l.name()); | ||
226 | } | ||
227 | } | ||
228 | None | ||
229 | } | ||
230 | |||
201 | fn try_find_self_references( | 231 | fn try_find_self_references( |
202 | syntax: &SyntaxNode, | 232 | syntax: &SyntaxNode, |
203 | position: FilePosition, | 233 | position: FilePosition, |
@@ -357,6 +387,91 @@ fn main() { | |||
357 | } | 387 | } |
358 | 388 | ||
359 | #[test] | 389 | #[test] |
390 | fn test_enum_after_space() { | ||
391 | check( | ||
392 | r#" | ||
393 | enum Foo <|>{ | ||
394 | A, | ||
395 | B, | ||
396 | } | ||
397 | fn main() { | ||
398 | let f: Foo; | ||
399 | f = Foo::A; | ||
400 | } | ||
401 | "#, | ||
402 | expect![[r#" | ||
403 | Foo ENUM FileId(0) 0..26 5..8 Other | ||
404 | |||
405 | FileId(0) 63..66 EnumLiteral | ||
406 | "#]], | ||
407 | ); | ||
408 | } | ||
409 | |||
410 | #[test] | ||
411 | fn test_enum_before_space() { | ||
412 | check( | ||
413 | r#" | ||
414 | enum Foo<|> { | ||
415 | A, | ||
416 | B, | ||
417 | } | ||
418 | fn main() { | ||
419 | let f: Foo; | ||
420 | f = Foo::A; | ||
421 | } | ||
422 | "#, | ||
423 | expect![[r#" | ||
424 | Foo ENUM FileId(0) 0..26 5..8 Other | ||
425 | |||
426 | FileId(0) 50..53 Other | ||
427 | FileId(0) 63..66 EnumLiteral | ||
428 | "#]], | ||
429 | ); | ||
430 | } | ||
431 | |||
432 | #[test] | ||
433 | fn test_enum_with_generic_type() { | ||
434 | check( | ||
435 | r#" | ||
436 | enum Foo<T> <|>{ | ||
437 | A(T), | ||
438 | B, | ||
439 | } | ||
440 | fn main() { | ||
441 | let f: Foo<i8>; | ||
442 | f = Foo::A(1); | ||
443 | } | ||
444 | "#, | ||
445 | expect![[r#" | ||
446 | Foo ENUM FileId(0) 0..32 5..8 Other | ||
447 | |||
448 | FileId(0) 73..76 EnumLiteral | ||
449 | "#]], | ||
450 | ); | ||
451 | } | ||
452 | |||
453 | #[test] | ||
454 | fn test_enum_for_tuple() { | ||
455 | check( | ||
456 | r#" | ||
457 | enum Foo<|>{ | ||
458 | A(i8), | ||
459 | B(i8), | ||
460 | } | ||
461 | fn main() { | ||
462 | let f: Foo; | ||
463 | f = Foo::A(1); | ||
464 | } | ||
465 | "#, | ||
466 | expect![[r#" | ||
467 | Foo ENUM FileId(0) 0..33 5..8 Other | ||
468 | |||
469 | FileId(0) 70..73 EnumLiteral | ||
470 | "#]], | ||
471 | ); | ||
472 | } | ||
473 | |||
474 | #[test] | ||
360 | fn test_find_all_refs_for_local() { | 475 | fn test_find_all_refs_for_local() { |
361 | check( | 476 | check( |
362 | r#" | 477 | r#" |
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 607185ca9..3936c7390 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs | |||
@@ -32,6 +32,7 @@ pub enum ReferenceKind { | |||
32 | StructLiteral, | 32 | StructLiteral, |
33 | RecordFieldExprOrPat, | 33 | RecordFieldExprOrPat, |
34 | SelfKw, | 34 | SelfKw, |
35 | EnumLiteral, | ||
35 | Other, | 36 | Other, |
36 | } | 37 | } |
37 | 38 | ||
@@ -284,6 +285,8 @@ impl<'a> FindUsages<'a> { | |||
284 | ReferenceKind::RecordFieldExprOrPat | 285 | ReferenceKind::RecordFieldExprOrPat |
285 | } else if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) { | 286 | } else if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) { |
286 | ReferenceKind::StructLiteral | 287 | ReferenceKind::StructLiteral |
288 | } else if is_enum_lit_name_ref(&name_ref) { | ||
289 | ReferenceKind::EnumLiteral | ||
287 | } else { | 290 | } else { |
288 | ReferenceKind::Other | 291 | ReferenceKind::Other |
289 | }; | 292 | }; |
@@ -402,3 +405,15 @@ fn is_record_field_expr_or_pat(name_ref: &ast::NameRef) -> bool { | |||
402 | false | 405 | false |
403 | } | 406 | } |
404 | } | 407 | } |
408 | |||
409 | fn is_enum_lit_name_ref(name_ref: &ast::NameRef) -> bool { | ||
410 | name_ref | ||
411 | .syntax() | ||
412 | .ancestors() | ||
413 | .find_map(ast::PathExpr::cast) | ||
414 | .and_then(|p| p.path()) | ||
415 | .and_then(|p| p.qualifier()) | ||
416 | .and_then(|p| p.segment()) | ||
417 | .map(|p| p.name_ref().as_ref() == Some(name_ref)) | ||
418 | .unwrap_or(false) | ||
419 | } | ||