diff options
Diffstat (limited to 'crates/ide/src/syntax_highlighting.rs')
-rw-r--r-- | crates/ide/src/syntax_highlighting.rs | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 25d6f7abd..4fa9e638a 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs | |||
@@ -13,8 +13,8 @@ use rustc_hash::FxHashMap; | |||
13 | use syntax::{ | 13 | use syntax::{ |
14 | ast::{self, HasFormatSpecifier}, | 14 | ast::{self, HasFormatSpecifier}, |
15 | AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, | 15 | AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, |
16 | SyntaxKind::*, | 16 | SyntaxKind::{self, *}, |
17 | TextRange, WalkEvent, T, | 17 | SyntaxNode, TextRange, WalkEvent, T, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | use crate::FileId; | 20 | use crate::FileId; |
@@ -454,6 +454,23 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { | |||
454 | Some(TextRange::new(range_start, range_end)) | 454 | Some(TextRange::new(range_start, range_end)) |
455 | } | 455 | } |
456 | 456 | ||
457 | /// Returns true if the parent nodes of `node` all match the `SyntaxKind`s in `kinds` exactly. | ||
458 | fn parents_match(mut node: SyntaxNode, mut kinds: &[SyntaxKind]) -> bool { | ||
459 | while let (Some(parent), [kind, rest @ ..]) = (&node.parent(), kinds) { | ||
460 | if parent.kind() != *kind { | ||
461 | return false; | ||
462 | } | ||
463 | |||
464 | // FIXME: Would be nice to get parent out of the match, but binding by-move and by-value | ||
465 | // in the same pattern is unstable: rust-lang/rust#68354. | ||
466 | node = node.parent().unwrap(); | ||
467 | kinds = rest; | ||
468 | } | ||
469 | |||
470 | // Only true if we matched all expected kinds | ||
471 | kinds.len() == 0 | ||
472 | } | ||
473 | |||
457 | fn highlight_element( | 474 | fn highlight_element( |
458 | sema: &Semantics<RootDatabase>, | 475 | sema: &Semantics<RootDatabase>, |
459 | bindings_shadow_count: &mut FxHashMap<Name, u32>, | 476 | bindings_shadow_count: &mut FxHashMap<Name, u32>, |
@@ -522,6 +539,26 @@ fn highlight_element( | |||
522 | 539 | ||
523 | let mut h = highlight_def(db, def); | 540 | let mut h = highlight_def(db, def); |
524 | 541 | ||
542 | // When lvalues are passed as arguments and they're not Copy, then mark | ||
543 | // them as Consuming. | ||
544 | if parents_match( | ||
545 | name_ref.syntax().clone(), | ||
546 | &[PATH_SEGMENT, PATH, PATH_EXPR, ARG_LIST], | ||
547 | ) { | ||
548 | let lvalue_ty = if let Definition::Local(local) = &def { | ||
549 | Some(local.ty(db)) | ||
550 | } else if let Definition::SelfType(impl_def) = &def { | ||
551 | Some(impl_def.target_ty(db)) | ||
552 | } else { | ||
553 | None | ||
554 | }; | ||
555 | if let Some(lvalue_ty) = lvalue_ty { | ||
556 | if !lvalue_ty.is_copy(db) { | ||
557 | h |= HighlightModifier::Consuming; | ||
558 | } | ||
559 | } | ||
560 | } | ||
561 | |||
525 | if let Some(parent) = name_ref.syntax().parent() { | 562 | if let Some(parent) = name_ref.syntax().parent() { |
526 | if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) { | 563 | if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) { |
527 | if let Definition::Field(field) = def { | 564 | if let Definition::Field(field) = def { |