mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 01:17:27 +00:00
9567: remove unneded special case r=matklad a=matklad bors r+ 🤖 9568: feat: add 'for' postfix completion r=lnicola a=mahdi-frms ![Peek 2021-07-11 16-45](https://user-images.githubusercontent.com/62165556/125194692-a0aaf780-e267-11eb-952a-81de7955d9a1.gif) adds #9561 used ```ele``` as identifier for each element in the iteration Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com> Co-authored-by: mahdi-frms <mahdif1380@outlook.com>
This commit is contained in:
commit
87621de2b9
17 changed files with 92 additions and 53 deletions
|
@ -112,8 +112,8 @@ pub(crate) fn external_docs(
|
|||
let node = token.parent()?;
|
||||
let definition = match_ast! {
|
||||
match node {
|
||||
ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db))?,
|
||||
ast::Name(name) => NameClass::classify(&sema, &name).map(|d| d.referenced_or_defined(sema.db))?,
|
||||
ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced())?,
|
||||
ast::Name(name) => NameClass::classify(&sema, &name).map(|d| d.referenced_or_defined())?,
|
||||
_ => return None,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -25,10 +25,10 @@ pub(crate) fn goto_declaration(
|
|||
match parent {
|
||||
ast::NameRef(name_ref) => {
|
||||
let name_kind = NameRefClass::classify(&sema, &name_ref)?;
|
||||
name_kind.referenced(sema.db)
|
||||
name_kind.referenced()
|
||||
},
|
||||
ast::Name(name) => {
|
||||
NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db)
|
||||
NameClass::classify(&sema, &name)?.referenced_or_defined()
|
||||
},
|
||||
_ => return None,
|
||||
}
|
||||
|
|
|
@ -60,12 +60,12 @@ pub(crate) fn goto_definition(
|
|||
reference_definition(&sema, Either::Right(&name_ref))
|
||||
},
|
||||
ast::Name(name) => {
|
||||
let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db);
|
||||
let def = NameClass::classify(&sema, &name)?.referenced_or_defined();
|
||||
try_find_trait_item_definition(sema.db, &def)
|
||||
.or_else(|| def.try_to_nav(sema.db))
|
||||
},
|
||||
ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, <) {
|
||||
let def = name_class.referenced_or_defined(sema.db);
|
||||
let def = name_class.referenced_or_defined();
|
||||
def.try_to_nav(sema.db)
|
||||
} else {
|
||||
reference_definition(&sema, Either::Left(<))
|
||||
|
@ -140,7 +140,7 @@ pub(crate) fn reference_definition(
|
|||
|lifetime| NameRefClass::classify_lifetime(sema, lifetime),
|
||||
|name_ref| NameRefClass::classify(sema, name_ref),
|
||||
)?;
|
||||
let def = name_kind.referenced(sema.db);
|
||||
let def = name_kind.referenced();
|
||||
def.try_to_nav(sema.db)
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,10 @@ pub(crate) fn goto_implementation(
|
|||
let node = sema.find_node_at_offset_with_descend(&syntax, position.offset)?;
|
||||
let def = match &node {
|
||||
ast::NameLike::Name(name) => {
|
||||
NameClass::classify(&sema, name).map(|class| class.referenced_or_defined(sema.db))
|
||||
NameClass::classify(&sema, name).map(|class| class.referenced_or_defined())
|
||||
}
|
||||
ast::NameLike::NameRef(name_ref) => {
|
||||
NameRefClass::classify(&sema, name_ref).map(|class| class.referenced(sema.db))
|
||||
NameRefClass::classify(&sema, name_ref).map(|class| class.referenced())
|
||||
}
|
||||
ast::NameLike::Lifetime(_) => None,
|
||||
}?;
|
||||
|
|
|
@ -98,14 +98,14 @@ pub(crate) fn hover(
|
|||
// field pattern shorthands to their definition
|
||||
ast::Name(name) => NameClass::classify(&sema, &name).and_then(|class| match class {
|
||||
NameClass::ConstReference(def) => Some(def),
|
||||
def => def.defined(db),
|
||||
def => def.defined(),
|
||||
}),
|
||||
ast::NameRef(name_ref) => {
|
||||
NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(db))
|
||||
NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced())
|
||||
},
|
||||
ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime).map_or_else(
|
||||
|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(db)),
|
||||
|d| d.defined(db),
|
||||
|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced()),
|
||||
|d| d.defined(),
|
||||
),
|
||||
|
||||
_ => {
|
||||
|
|
|
@ -58,7 +58,7 @@ pub(crate) fn find_all_refs(
|
|||
|
||||
let (def, is_literal_search) =
|
||||
if let Some(name) = get_name_of_item_declaration(&syntax, position) {
|
||||
(NameClass::classify(sema, &name)?.referenced_or_defined(sema.db), true)
|
||||
(NameClass::classify(sema, &name)?.referenced_or_defined(), true)
|
||||
} else {
|
||||
(find_def(sema, &syntax, position.offset)?, false)
|
||||
};
|
||||
|
@ -116,17 +116,13 @@ pub(crate) fn find_def(
|
|||
offset: TextSize,
|
||||
) -> Option<Definition> {
|
||||
let def = match sema.find_node_at_offset_with_descend(syntax, offset)? {
|
||||
ast::NameLike::NameRef(name_ref) => {
|
||||
NameRefClass::classify(sema, &name_ref)?.referenced(sema.db)
|
||||
}
|
||||
ast::NameLike::Name(name) => {
|
||||
NameClass::classify(sema, &name)?.referenced_or_defined(sema.db)
|
||||
}
|
||||
ast::NameLike::NameRef(name_ref) => NameRefClass::classify(sema, &name_ref)?.referenced(),
|
||||
ast::NameLike::Name(name) => NameClass::classify(sema, &name)?.referenced_or_defined(),
|
||||
ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
|
||||
.map(|class| class.referenced(sema.db))
|
||||
.map(|class| class.referenced())
|
||||
.or_else(|| {
|
||||
NameClass::classify_lifetime(sema, &lifetime)
|
||||
.map(|class| class.referenced_or_defined(sema.db))
|
||||
.map(|class| class.referenced_or_defined())
|
||||
})?,
|
||||
};
|
||||
Some(def)
|
||||
|
|
|
@ -108,11 +108,11 @@ fn find_definition(
|
|||
bail!("Renaming aliases is currently unsupported")
|
||||
}
|
||||
ast::NameLike::Name(name) => {
|
||||
NameClass::classify(sema, &name).map(|class| class.referenced_or_defined(sema.db))
|
||||
NameClass::classify(sema, &name).map(|class| class.referenced_or_defined())
|
||||
}
|
||||
ast::NameLike::NameRef(name_ref) => {
|
||||
if let Some(def) =
|
||||
NameRefClass::classify(sema, &name_ref).map(|class| class.referenced(sema.db))
|
||||
NameRefClass::classify(sema, &name_ref).map(|class| class.referenced())
|
||||
{
|
||||
// if the name differs from the definitions name it has to be an alias
|
||||
if def.name(sema.db).map_or(false, |it| it.to_string() != name_ref.text()) {
|
||||
|
@ -124,10 +124,9 @@ fn find_definition(
|
|||
}
|
||||
}
|
||||
ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
|
||||
.map(|class| NameRefClass::referenced(class, sema.db))
|
||||
.map(|class| class.referenced())
|
||||
.or_else(|| {
|
||||
NameClass::classify_lifetime(sema, &lifetime)
|
||||
.map(|it| it.referenced_or_defined(sema.db))
|
||||
NameClass::classify_lifetime(sema, &lifetime).map(|it| it.referenced_or_defined())
|
||||
}),
|
||||
}
|
||||
.ok_or_else(|| format_err!("No references found at position"))?;
|
||||
|
|
|
@ -46,7 +46,6 @@ pub(super) fn element(
|
|||
};
|
||||
|
||||
match name_kind {
|
||||
Some(NameClass::ExternCrate(_)) => SymbolKind::Module.into(),
|
||||
Some(NameClass::Definition(def)) => {
|
||||
let mut h = highlight_def(db, krate, def) | HlMod::Definition;
|
||||
if let Definition::ModuleDef(hir::ModuleDef::Trait(trait_)) = &def {
|
||||
|
@ -111,7 +110,6 @@ pub(super) fn element(
|
|||
}
|
||||
};
|
||||
let h = match name_class {
|
||||
NameRefClass::ExternCrate(_) => SymbolKind::Module.into(),
|
||||
NameRefClass::Definition(def) => {
|
||||
if let Definition::Local(local) = &def {
|
||||
if let Some(name) = local.name(db) {
|
||||
|
|
|
@ -38,6 +38,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
|||
|
||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||
</style>
|
||||
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module">std</span><span class="semicolon">;</span>
|
||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module">alloc</span> <span class="keyword">as</span> <span class="module">abc</span><span class="semicolon">;</span>
|
||||
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module library">std</span><span class="semicolon">;</span>
|
||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module library">alloc</span> <span class="keyword">as</span> <span class="module declaration library">abc</span><span class="semicolon">;</span>
|
||||
</code></pre>
|
|
@ -41,7 +41,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
|
|||
let name_ref = ast::NameRef::cast(ident.parent()?)?;
|
||||
let def = match NameRefClass::classify(&ctx.sema, &name_ref)? {
|
||||
NameRefClass::Definition(def) => def,
|
||||
NameRefClass::ExternCrate(_) | NameRefClass::FieldShorthand { .. } => return None,
|
||||
NameRefClass::FieldShorthand { .. } => return None,
|
||||
};
|
||||
let fun = match def {
|
||||
Definition::ModuleDef(hir::ModuleDef::Function(it)) => it,
|
||||
|
|
|
@ -638,7 +638,7 @@ fn vars_used_in_body(ctx: &AssistContext, body: &FunctionBody) -> Vec<Local> {
|
|||
body.descendants()
|
||||
.filter_map(ast::NameRef::cast)
|
||||
.filter_map(|name_ref| NameRefClass::classify(&ctx.sema, &name_ref))
|
||||
.map(|name_kind| name_kind.referenced(ctx.db()))
|
||||
.map(|name_kind| name_kind.referenced())
|
||||
.filter_map(|definition| match definition {
|
||||
Definition::Local(local) => Some(local),
|
||||
_ => None,
|
||||
|
|
|
@ -310,6 +310,36 @@ use super::foo;
|
|||
fn bar() {
|
||||
let _ = foo(1);
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_method_param() {
|
||||
// FIXME: This is completely wrong:
|
||||
// * method call expressions are not handled
|
||||
// * assoc function syntax removes the wrong argument.
|
||||
check_assist(
|
||||
remove_unused_param,
|
||||
r#"
|
||||
struct S;
|
||||
impl S { fn f(&self, $0_unused: i32) {} }
|
||||
fn main() {
|
||||
S.f(92);
|
||||
S.f();
|
||||
S.f(92, 92);
|
||||
S::f(&S, 92);
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct S;
|
||||
impl S { fn f(&self) {} }
|
||||
fn main() {
|
||||
S.f(92);
|
||||
S.f();
|
||||
S.f(92, 92);
|
||||
S::f(92);
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
mod format_like;
|
||||
|
||||
use ide_db::{helpers::SnippetCap, ty_filter::TryEnum};
|
||||
use ide_db::{
|
||||
helpers::{FamousDefs, SnippetCap},
|
||||
ty_filter::TryEnum,
|
||||
};
|
||||
use syntax::{
|
||||
ast::{self, AstNode, AstToken},
|
||||
SyntaxKind::{BLOCK_EXPR, EXPR_STMT},
|
||||
|
@ -110,6 +113,18 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
|
|||
.add_to(acc);
|
||||
postfix_snippet(ctx, cap, dot_receiver, "not", "!expr", &format!("!{}", receiver_text))
|
||||
.add_to(acc);
|
||||
} else if let Some(trait_) = FamousDefs(&ctx.sema, ctx.krate).core_iter_IntoIterator() {
|
||||
if receiver_ty.impls_trait(ctx.db, trait_, &[]) {
|
||||
postfix_snippet(
|
||||
ctx,
|
||||
cap,
|
||||
dot_receiver,
|
||||
"for",
|
||||
"for ele in expr {}",
|
||||
&format!("for ele in {} {{\n $0\n}}", receiver_text),
|
||||
)
|
||||
.add_to(acc);
|
||||
}
|
||||
}
|
||||
|
||||
postfix_snippet(ctx, cap, dot_receiver, "ref", "&expr", &format!("&{}", receiver_text))
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
|
||||
|
||||
use hir::{
|
||||
db::HirDatabase, Crate, Field, GenericParam, HasVisibility, Impl, Label, Local, MacroDef,
|
||||
Module, ModuleDef, Name, PathResolution, Semantics, Visibility,
|
||||
Field, GenericParam, HasVisibility, Impl, Label, Local, MacroDef, Module, ModuleDef, Name,
|
||||
PathResolution, Semantics, Visibility,
|
||||
};
|
||||
use syntax::{
|
||||
ast::{self, AstNode, PathSegmentKind},
|
||||
|
@ -101,14 +101,13 @@ impl Definition {
|
|||
/// scope. That is, that, by just looking at the syntactical category, we can
|
||||
/// unambiguously define the semantic category.
|
||||
///
|
||||
/// Sadly, that's not 100% true, there are special cases. To make sure that call
|
||||
/// the code handles all the special cases correctly via exhaustive matching, we
|
||||
/// Sadly, that's not 100% true, there are special cases. To make sure that
|
||||
/// callers handle all the special cases correctly via exhaustive matching, we
|
||||
/// add a [`NameClass`] enum which lists all of them!
|
||||
///
|
||||
/// A model special case is `None` constant in pattern.
|
||||
#[derive(Debug)]
|
||||
pub enum NameClass {
|
||||
ExternCrate(Crate),
|
||||
Definition(Definition),
|
||||
/// `None` in `if let None = Some(82) {}`.
|
||||
/// Syntactically, it is a name, but semantically it is a reference.
|
||||
|
@ -124,9 +123,8 @@ pub enum NameClass {
|
|||
|
||||
impl NameClass {
|
||||
/// `Definition` defined by this name.
|
||||
pub fn defined(self, db: &dyn HirDatabase) -> Option<Definition> {
|
||||
pub fn defined(self) -> Option<Definition> {
|
||||
let res = match self {
|
||||
NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()),
|
||||
NameClass::Definition(it) => it,
|
||||
NameClass::ConstReference(_) => return None,
|
||||
NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
|
||||
|
@ -137,9 +135,8 @@ impl NameClass {
|
|||
}
|
||||
|
||||
/// `Definition` referenced or defined by this name.
|
||||
pub fn referenced_or_defined(self, db: &dyn HirDatabase) -> Definition {
|
||||
pub fn referenced_or_defined(self) -> Definition {
|
||||
match self {
|
||||
NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()),
|
||||
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||
NameClass::PatFieldShorthand { local_def: _, field_ref } => field_ref,
|
||||
}
|
||||
|
@ -186,11 +183,12 @@ impl NameClass {
|
|||
})
|
||||
.and_then(|name_ref| NameRefClass::classify(sema, &name_ref))?;
|
||||
|
||||
Some(NameClass::Definition(name_ref_class.referenced(sema.db)))
|
||||
Some(NameClass::Definition(name_ref_class.referenced()))
|
||||
} else {
|
||||
let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?;
|
||||
let resolved = sema.resolve_extern_crate(&extern_crate)?;
|
||||
Some(NameClass::ExternCrate(resolved))
|
||||
let krate = sema.resolve_extern_crate(&extern_crate)?;
|
||||
let root_module = krate.root_module(sema.db);
|
||||
Some(NameClass::Definition(Definition::ModuleDef(root_module.into())))
|
||||
}
|
||||
},
|
||||
ast::IdentPat(it) => {
|
||||
|
@ -303,16 +301,14 @@ impl NameClass {
|
|||
/// reference to point to two different defs.
|
||||
#[derive(Debug)]
|
||||
pub enum NameRefClass {
|
||||
ExternCrate(Crate),
|
||||
Definition(Definition),
|
||||
FieldShorthand { local_ref: Local, field_ref: Definition },
|
||||
}
|
||||
|
||||
impl NameRefClass {
|
||||
/// `Definition`, which this name refers to.
|
||||
pub fn referenced(self, db: &dyn HirDatabase) -> Definition {
|
||||
pub fn referenced(self) -> Definition {
|
||||
match self {
|
||||
NameRefClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()),
|
||||
NameRefClass::Definition(def) => def,
|
||||
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
||||
// FIXME: this is inherently ambiguous -- this name refers to
|
||||
|
@ -428,8 +424,9 @@ impl NameRefClass {
|
|||
}
|
||||
|
||||
let extern_crate = ast::ExternCrate::cast(parent)?;
|
||||
let resolved = sema.resolve_extern_crate(&extern_crate)?;
|
||||
Some(NameRefClass::ExternCrate(resolved))
|
||||
let krate = sema.resolve_extern_crate(&extern_crate)?;
|
||||
let root_module = krate.root_module(sema.db);
|
||||
Some(NameRefClass::Definition(Definition::ModuleDef(root_module.into())))
|
||||
}
|
||||
|
||||
pub fn classify_lifetime(
|
||||
|
|
|
@ -134,6 +134,10 @@ impl FamousDefs<'_, '_> {
|
|||
self.find_trait("core:iter:traits:iterator:Iterator")
|
||||
}
|
||||
|
||||
pub fn core_iter_IntoIterator(&self) -> Option<Trait> {
|
||||
self.find_trait("core:iter:traits:collect:IntoIterator")
|
||||
}
|
||||
|
||||
pub fn core_iter(&self) -> Option<Module> {
|
||||
self.find_module("core:iter")
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ fn get_name_definition(
|
|||
candidate_node
|
||||
};
|
||||
let name = ast::Name::cast(candidate_name_node)?;
|
||||
NameClass::classify(sema, &name)?.defined(sema.db)
|
||||
NameClass::classify(sema, &name)?.defined()
|
||||
}
|
||||
|
||||
fn is_assoc_item(item: ItemInNs, db: &RootDatabase) -> bool {
|
||||
|
|
|
@ -29,7 +29,7 @@ pub(crate) fn incorrect_case(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCas
|
|||
fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Option<Vec<Assist>> {
|
||||
let root = ctx.sema.db.parse_or_expand(d.file)?;
|
||||
let name_node = d.ident.to_node(&root);
|
||||
let def = NameClass::classify(&ctx.sema, &name_node)?.defined(ctx.sema.db)?;
|
||||
let def = NameClass::classify(&ctx.sema, &name_node)?.defined()?;
|
||||
|
||||
let name_node = InFile::new(d.file, name_node.syntax());
|
||||
let frange = name_node.original_file_range(ctx.sema.db);
|
||||
|
|
Loading…
Reference in a new issue