aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/syntax_highlighting.rs
diff options
context:
space:
mode:
authorPaul Daniel Faria <[email protected]>2020-09-06 17:26:53 +0100
committerPaul Daniel Faria <[email protected]>2020-09-06 17:26:53 +0100
commit7af947a032bd2e6f6df6b903b40f142cd7b8d9e0 (patch)
treea3a07fc4d44f56339d70f2094cf3cc3ce96c20f3 /crates/ide/src/syntax_highlighting.rs
parent0275b08d1521606fa733f76fe5d5707717456fb4 (diff)
Add consuming modifier to lvalues that are passed by value and not Copy
Diffstat (limited to 'crates/ide/src/syntax_highlighting.rs')
-rw-r--r--crates/ide/src/syntax_highlighting.rs41
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;
13use syntax::{ 13use 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
20use crate::FileId; 20use 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.
458fn 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
457fn highlight_element( 474fn 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 {