mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
Fix handling of consuming self, refactor shared logic into a single function
This commit is contained in:
parent
7af947a032
commit
a1a7b07ad3
2 changed files with 34 additions and 30 deletions
|
@ -4,7 +4,7 @@ mod injection;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use hir::{Name, Semantics, VariantDef};
|
use hir::{Local, Name, Semantics, VariantDef};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
|
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
|
||||||
RootDatabase,
|
RootDatabase,
|
||||||
|
@ -14,7 +14,7 @@ use syntax::{
|
||||||
ast::{self, HasFormatSpecifier},
|
ast::{self, HasFormatSpecifier},
|
||||||
AstNode, AstToken, Direction, NodeOrToken, SyntaxElement,
|
AstNode, AstToken, Direction, NodeOrToken, SyntaxElement,
|
||||||
SyntaxKind::{self, *},
|
SyntaxKind::{self, *},
|
||||||
SyntaxNode, TextRange, WalkEvent, T,
|
SyntaxNode, SyntaxToken, TextRange, WalkEvent, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::FileId;
|
use crate::FileId;
|
||||||
|
@ -455,7 +455,7 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the parent nodes of `node` all match the `SyntaxKind`s in `kinds` exactly.
|
/// Returns true if the parent nodes of `node` all match the `SyntaxKind`s in `kinds` exactly.
|
||||||
fn parents_match(mut node: SyntaxNode, mut kinds: &[SyntaxKind]) -> bool {
|
fn parents_match(mut node: NodeOrToken<SyntaxNode, SyntaxToken>, mut kinds: &[SyntaxKind]) -> bool {
|
||||||
while let (Some(parent), [kind, rest @ ..]) = (&node.parent(), kinds) {
|
while let (Some(parent), [kind, rest @ ..]) = (&node.parent(), kinds) {
|
||||||
if parent.kind() != *kind {
|
if parent.kind() != *kind {
|
||||||
return false;
|
return false;
|
||||||
|
@ -463,7 +463,7 @@ fn parents_match(mut node: SyntaxNode, mut kinds: &[SyntaxKind]) -> bool {
|
||||||
|
|
||||||
// FIXME: Would be nice to get parent out of the match, but binding by-move and by-value
|
// FIXME: Would be nice to get parent out of the match, but binding by-move and by-value
|
||||||
// in the same pattern is unstable: rust-lang/rust#68354.
|
// in the same pattern is unstable: rust-lang/rust#68354.
|
||||||
node = node.parent().unwrap();
|
node = node.parent().unwrap().into();
|
||||||
kinds = rest;
|
kinds = rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,6 +471,15 @@ fn parents_match(mut node: SyntaxNode, mut kinds: &[SyntaxKind]) -> bool {
|
||||||
kinds.len() == 0
|
kinds.len() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_consumed_lvalue(
|
||||||
|
node: NodeOrToken<SyntaxNode, SyntaxToken>,
|
||||||
|
local: &Local,
|
||||||
|
db: &RootDatabase,
|
||||||
|
) -> bool {
|
||||||
|
// When lvalues are passed as arguments and they're not Copy, then mark them as Consuming.
|
||||||
|
parents_match(node, &[PATH_SEGMENT, PATH, PATH_EXPR, ARG_LIST]) && !local.ty(db).is_copy(db)
|
||||||
|
}
|
||||||
|
|
||||||
fn highlight_element(
|
fn highlight_element(
|
||||||
sema: &Semantics<RootDatabase>,
|
sema: &Semantics<RootDatabase>,
|
||||||
bindings_shadow_count: &mut FxHashMap<Name, u32>,
|
bindings_shadow_count: &mut FxHashMap<Name, u32>,
|
||||||
|
@ -539,25 +548,11 @@ fn highlight_element(
|
||||||
|
|
||||||
let mut h = highlight_def(db, def);
|
let mut h = highlight_def(db, def);
|
||||||
|
|
||||||
// When lvalues are passed as arguments and they're not Copy, then mark
|
if let Definition::Local(local) = &def {
|
||||||
// them as Consuming.
|
if is_consumed_lvalue(name_ref.syntax().clone().into(), local, db) {
|
||||||
if parents_match(
|
|
||||||
name_ref.syntax().clone(),
|
|
||||||
&[PATH_SEGMENT, PATH, PATH_EXPR, ARG_LIST],
|
|
||||||
) {
|
|
||||||
let lvalue_ty = if let Definition::Local(local) = &def {
|
|
||||||
Some(local.ty(db))
|
|
||||||
} else if let Definition::SelfType(impl_def) = &def {
|
|
||||||
Some(impl_def.target_ty(db))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
if let Some(lvalue_ty) = lvalue_ty {
|
|
||||||
if !lvalue_ty.is_copy(db) {
|
|
||||||
h |= HighlightModifier::Consuming;
|
h |= HighlightModifier::Consuming;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(parent) = name_ref.syntax().parent() {
|
if let Some(parent) = name_ref.syntax().parent() {
|
||||||
if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) {
|
if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) {
|
||||||
|
@ -682,21 +677,30 @@ fn highlight_element(
|
||||||
.and_then(ast::SelfParam::cast)
|
.and_then(ast::SelfParam::cast)
|
||||||
.and_then(|p| p.mut_token())
|
.and_then(|p| p.mut_token())
|
||||||
.is_some();
|
.is_some();
|
||||||
// closure to enforce lazyness
|
let self_path = &element
|
||||||
let self_path = || {
|
.parent()
|
||||||
sema.resolve_path(&element.parent()?.parent().and_then(ast::Path::cast)?)
|
.as_ref()
|
||||||
};
|
.and_then(SyntaxNode::parent)
|
||||||
|
.and_then(ast::Path::cast)
|
||||||
|
.and_then(|p| sema.resolve_path(&p));
|
||||||
|
let mut h = HighlightTag::SelfKeyword.into();
|
||||||
if self_param_is_mut
|
if self_param_is_mut
|
||||||
|| matches!(self_path(),
|
|| matches!(self_path,
|
||||||
Some(hir::PathResolution::Local(local))
|
Some(hir::PathResolution::Local(local))
|
||||||
if local.is_self(db)
|
if local.is_self(db)
|
||||||
&& (local.is_mut(db) || local.ty(db).is_mutable_reference())
|
&& (local.is_mut(db) || local.ty(db).is_mutable_reference())
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
HighlightTag::SelfKeyword | HighlightModifier::Mutable
|
h |= HighlightModifier::Mutable
|
||||||
} else {
|
|
||||||
HighlightTag::SelfKeyword.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(hir::PathResolution::Local(local)) = self_path {
|
||||||
|
if is_consumed_lvalue(element, &local, db) {
|
||||||
|
h |= HighlightModifier::Consuming;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h
|
||||||
}
|
}
|
||||||
T![ref] => element
|
T![ref] => element
|
||||||
.parent()
|
.parent()
|
||||||
|
|
|
@ -62,7 +62,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
|
|
||||||
<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
|
<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
|
||||||
<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>
|
<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>
|
||||||
<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>
|
<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>
|
||||||
<span class="punctuation">}</span>
|
<span class="punctuation">}</span>
|
||||||
|
|
||||||
<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>
|
<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>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue