Skip to content

Commit a1a7b07

Browse files
committed
Fix handling of consuming self, refactor shared logic into a single function
1 parent 7af947a commit a1a7b07

File tree

2 files changed

+34
-30
lines changed

2 files changed

+34
-30
lines changed

crates/ide/src/syntax_highlighting.rs

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod injection;
44
#[cfg(test)]
55
mod tests;
66

7-
use hir::{Name, Semantics, VariantDef};
7+
use hir::{Local, Name, Semantics, VariantDef};
88
use ide_db::{
99
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
1010
RootDatabase,
@@ -14,7 +14,7 @@ use syntax::{
1414
ast::{self, HasFormatSpecifier},
1515
AstNode, AstToken, Direction, NodeOrToken, SyntaxElement,
1616
SyntaxKind::{self, *},
17-
SyntaxNode, TextRange, WalkEvent, T,
17+
SyntaxNode, SyntaxToken, TextRange, WalkEvent, T,
1818
};
1919

2020
use crate::FileId;
@@ -455,22 +455,31 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> {
455455
}
456456

457457
/// 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 {
458+
fn parents_match(mut node: NodeOrToken<SyntaxNode, SyntaxToken>, mut kinds: &[SyntaxKind]) -> bool {
459459
while let (Some(parent), [kind, rest @ ..]) = (&node.parent(), kinds) {
460460
if parent.kind() != *kind {
461461
return false;
462462
}
463463

464464
// FIXME: Would be nice to get parent out of the match, but binding by-move and by-value
465465
// in the same pattern is unstable: rust-lang/rust#68354.
466-
node = node.parent().unwrap();
466+
node = node.parent().unwrap().into();
467467
kinds = rest;
468468
}
469469

470470
// Only true if we matched all expected kinds
471471
kinds.len() == 0
472472
}
473473

474+
fn is_consumed_lvalue(
475+
node: NodeOrToken<SyntaxNode, SyntaxToken>,
476+
local: &Local,
477+
db: &RootDatabase,
478+
) -> bool {
479+
// When lvalues are passed as arguments and they're not Copy, then mark them as Consuming.
480+
parents_match(node, &[PATH_SEGMENT, PATH, PATH_EXPR, ARG_LIST]) && !local.ty(db).is_copy(db)
481+
}
482+
474483
fn highlight_element(
475484
sema: &Semantics<RootDatabase>,
476485
bindings_shadow_count: &mut FxHashMap<Name, u32>,
@@ -539,23 +548,9 @@ fn highlight_element(
539548

540549
let mut h = highlight_def(db, def);
541550

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-
}
551+
if let Definition::Local(local) = &def {
552+
if is_consumed_lvalue(name_ref.syntax().clone().into(), local, db) {
553+
h |= HighlightModifier::Consuming;
559554
}
560555
}
561556

@@ -682,21 +677,30 @@ fn highlight_element(
682677
.and_then(ast::SelfParam::cast)
683678
.and_then(|p| p.mut_token())
684679
.is_some();
685-
// closure to enforce lazyness
686-
let self_path = || {
687-
sema.resolve_path(&element.parent()?.parent().and_then(ast::Path::cast)?)
688-
};
680+
let self_path = &element
681+
.parent()
682+
.as_ref()
683+
.and_then(SyntaxNode::parent)
684+
.and_then(ast::Path::cast)
685+
.and_then(|p| sema.resolve_path(&p));
686+
let mut h = HighlightTag::SelfKeyword.into();
689687
if self_param_is_mut
690-
|| matches!(self_path(),
688+
|| matches!(self_path,
691689
Some(hir::PathResolution::Local(local))
692690
if local.is_self(db)
693691
&& (local.is_mut(db) || local.ty(db).is_mutable_reference())
694692
)
695693
{
696-
HighlightTag::SelfKeyword | HighlightModifier::Mutable
697-
} else {
698-
HighlightTag::SelfKeyword.into()
694+
h |= HighlightModifier::Mutable
695+
}
696+
697+
if let Some(hir::PathResolution::Local(local)) = self_path {
698+
if is_consumed_lvalue(element, &local, db) {
699+
h |= HighlightModifier::Consuming;
700+
}
699701
}
702+
703+
h
700704
}
701705
T![ref] => element
702706
.parent()

crates/ide/src/syntax_highlighting/test_data/highlighting.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262

6363
<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
6464
<span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">Foo</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
65-
<span class="value_param">f</span><span class="punctuation">.</span><span class="function consuming">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">)</span>
65+
<span class="value_param">f</span><span class="punctuation">.</span><span class="function consuming">baz</span><span class="punctuation">(</span><span class="self_keyword consuming">self</span><span class="punctuation">)</span>
6666
<span class="punctuation">}</span>
6767

6868
<span class="keyword">fn</span> <span class="function declaration">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>

0 commit comments

Comments
 (0)