diff options
author | Paul Daniel Faria <[email protected]> | 2020-09-06 19:34:01 +0100 |
---|---|---|
committer | Paul Daniel Faria <[email protected]> | 2020-09-06 19:34:01 +0100 |
commit | a1a7b07ad33b7dcadedc2af26c3a5f8ef3daca27 (patch) | |
tree | c41abbdb6dd82b04a232533e824a6b395ccbd3da /crates/ide | |
parent | 7af947a032bd2e6f6df6b903b40f142cd7b8d9e0 (diff) |
Fix handling of consuming self, refactor shared logic into a single function
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/src/syntax_highlighting.rs | 62 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/test_data/highlighting.html | 2 |
2 files changed, 34 insertions, 30 deletions
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 4fa9e638a..d9fc25d88 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs | |||
@@ -4,7 +4,7 @@ mod injection; | |||
4 | #[cfg(test)] | 4 | #[cfg(test)] |
5 | mod tests; | 5 | mod tests; |
6 | 6 | ||
7 | use hir::{Name, Semantics, VariantDef}; | 7 | use hir::{Local, Name, Semantics, VariantDef}; |
8 | use ide_db::{ | 8 | use ide_db::{ |
9 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, | 9 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, |
10 | RootDatabase, | 10 | RootDatabase, |
@@ -14,7 +14,7 @@ use syntax::{ | |||
14 | ast::{self, HasFormatSpecifier}, | 14 | ast::{self, HasFormatSpecifier}, |
15 | AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, | 15 | AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, |
16 | SyntaxKind::{self, *}, | 16 | SyntaxKind::{self, *}, |
17 | SyntaxNode, TextRange, WalkEvent, T, | 17 | SyntaxNode, SyntaxToken, TextRange, WalkEvent, T, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | use crate::FileId; | 20 | use crate::FileId; |
@@ -455,7 +455,7 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { | |||
455 | } | 455 | } |
456 | 456 | ||
457 | /// Returns true if the parent nodes of `node` all match the `SyntaxKind`s in `kinds` exactly. | 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 { | 458 | fn parents_match(mut node: NodeOrToken<SyntaxNode, SyntaxToken>, mut kinds: &[SyntaxKind]) -> bool { |
459 | while let (Some(parent), [kind, rest @ ..]) = (&node.parent(), kinds) { | 459 | while let (Some(parent), [kind, rest @ ..]) = (&node.parent(), kinds) { |
460 | if parent.kind() != *kind { | 460 | if parent.kind() != *kind { |
461 | return false; | 461 | return false; |
@@ -463,7 +463,7 @@ fn parents_match(mut node: SyntaxNode, mut kinds: &[SyntaxKind]) -> bool { | |||
463 | 463 | ||
464 | // FIXME: Would be nice to get parent out of the match, but binding by-move and by-value | 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. | 465 | // in the same pattern is unstable: rust-lang/rust#68354. |
466 | node = node.parent().unwrap(); | 466 | node = node.parent().unwrap().into(); |
467 | kinds = rest; | 467 | kinds = rest; |
468 | } | 468 | } |
469 | 469 | ||
@@ -471,6 +471,15 @@ fn parents_match(mut node: SyntaxNode, mut kinds: &[SyntaxKind]) -> bool { | |||
471 | kinds.len() == 0 | 471 | kinds.len() == 0 |
472 | } | 472 | } |
473 | 473 | ||
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 | |||
474 | fn highlight_element( | 483 | fn highlight_element( |
475 | sema: &Semantics<RootDatabase>, | 484 | sema: &Semantics<RootDatabase>, |
476 | bindings_shadow_count: &mut FxHashMap<Name, u32>, | 485 | bindings_shadow_count: &mut FxHashMap<Name, u32>, |
@@ -539,23 +548,9 @@ fn highlight_element( | |||
539 | 548 | ||
540 | let mut h = highlight_def(db, def); | 549 | let mut h = highlight_def(db, def); |
541 | 550 | ||
542 | // When lvalues are passed as arguments and they're not Copy, then mark | 551 | if let Definition::Local(local) = &def { |
543 | // them as Consuming. | 552 | if is_consumed_lvalue(name_ref.syntax().clone().into(), local, db) { |
544 | if parents_match( | 553 | h |= HighlightModifier::Consuming; |
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 | } | 554 | } |
560 | } | 555 | } |
561 | 556 | ||
@@ -682,21 +677,30 @@ fn highlight_element( | |||
682 | .and_then(ast::SelfParam::cast) | 677 | .and_then(ast::SelfParam::cast) |
683 | .and_then(|p| p.mut_token()) | 678 | .and_then(|p| p.mut_token()) |
684 | .is_some(); | 679 | .is_some(); |
685 | // closure to enforce lazyness | 680 | let self_path = &element |
686 | let self_path = || { | 681 | .parent() |
687 | sema.resolve_path(&element.parent()?.parent().and_then(ast::Path::cast)?) | 682 | .as_ref() |
688 | }; | 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(); | ||
689 | if self_param_is_mut | 687 | if self_param_is_mut |
690 | || matches!(self_path(), | 688 | || matches!(self_path, |
691 | Some(hir::PathResolution::Local(local)) | 689 | Some(hir::PathResolution::Local(local)) |
692 | if local.is_self(db) | 690 | if local.is_self(db) |
693 | && (local.is_mut(db) || local.ty(db).is_mutable_reference()) | 691 | && (local.is_mut(db) || local.ty(db).is_mutable_reference()) |
694 | ) | 692 | ) |
695 | { | 693 | { |
696 | HighlightTag::SelfKeyword | HighlightModifier::Mutable | 694 | h |= HighlightModifier::Mutable |
697 | } else { | 695 | } |
698 | HighlightTag::SelfKeyword.into() | 696 | |
697 | if let Some(hir::PathResolution::Local(local)) = self_path { | ||
698 | if is_consumed_lvalue(element, &local, db) { | ||
699 | h |= HighlightModifier::Consuming; | ||
700 | } | ||
699 | } | 701 | } |
702 | |||
703 | h | ||
700 | } | 704 | } |
701 | T![ref] => element | 705 | T![ref] => element |
702 | .parent() | 706 | .parent() |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index cade46348..cde42024c 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html | |||
@@ -62,7 +62,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
62 | 62 | ||
63 | <span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span> | 63 | <span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span> |
64 | <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">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span> | 64 | <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">-></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> |
66 | <span class="punctuation">}</span> | 66 | <span class="punctuation">}</span> |
67 | 67 | ||
68 | <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> | 68 | <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> |