From cbc6f94573d7f4601b739e001de5d5f71ec9b552 Mon Sep 17 00:00:00 2001 From: Wesley Norris Date: Sat, 9 Nov 2019 10:56:36 -0500 Subject: [PATCH 01/16] Add add_new assist Adds a new assist to autogenerate a new fn based on the selected struct, excluding tuple structs and unions. The fn will inherit the same visibility as the struct and the assist will attempt to reuse any existing impl blocks that exist at the same level of struct. --- crates/ra_assists/src/assists/add_new.rs | 379 +++++++++++++++++++ crates/ra_assists/src/doc_tests/generated.rs | 22 ++ crates/ra_assists/src/lib.rs | 2 + docs/user/assists.md | 21 + 4 files changed, 424 insertions(+) create mode 100644 crates/ra_assists/src/assists/add_new.rs diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs new file mode 100644 index 0000000000..a8839cfba3 --- /dev/null +++ b/crates/ra_assists/src/assists/add_new.rs @@ -0,0 +1,379 @@ +use format_buf::format; +use hir::{db::HirDatabase, FromSource}; +use join_to_string::join; +use ra_syntax::{ + ast::{ + self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner, + }, + TextUnit, T, +}; +use std::fmt::Write; + +use crate::{Assist, AssistCtx, AssistId}; + +// Assist: add_new +// +// Adds a new inherent impl for a type. +// +// ``` +// struct Ctx { +// data: T,<|> +// } +// ``` +// -> +// ``` +// struct Ctx { +// data: T, +// } +// +// impl Ctx { +// fn new(data: T) -> Self { Self { data } } +// } +// +// ``` +pub(crate) fn add_new(ctx: AssistCtx) -> Option { + let strukt = ctx.find_node_at_offset::()?; + + // We want to only apply this to non-union structs with named fields + let field_list = match (strukt.kind(), strukt.is_union()) { + (StructKind::Named(named), false) => named, + _ => return None, + }; + + // Return early if we've found an existing new fn + let impl_block = find_struct_impl(&ctx, &strukt)?; + + ctx.add_assist(AssistId("add_new"), "add new fn", |edit| { + edit.target(strukt.syntax().text_range()); + + let mut buf = String::with_capacity(512); + + if impl_block.is_some() { + buf.push('\n'); + } + + let vis = strukt.visibility().map(|v| format!("{} ", v.syntax())); + let vis = vis.as_ref().map(String::as_str).unwrap_or(""); + write!(&mut buf, " {}fn new(", vis).unwrap(); + + join(field_list.fields().map(|f| { + format!( + "{}: {}", + f.name().unwrap().syntax().text(), + f.ascribed_type().unwrap().syntax().text() + ) + })) + .separator(", ") + .to_buf(&mut buf); + + buf.push_str(") -> Self { Self {"); + + join(field_list.fields().map(|f| f.name().unwrap().syntax().text())) + .separator(", ") + .surround_with(" ", " ") + .to_buf(&mut buf); + + buf.push_str("} }"); + + let (start_offset, end_offset) = if let Some(impl_block) = impl_block { + buf.push('\n'); + let start = impl_block + .syntax() + .descendants_with_tokens() + .find(|t| t.kind() == T!['{']) + .unwrap() + .text_range() + .end(); + + (start, TextUnit::from_usize(1)) + } else { + buf = generate_impl_text(&strukt, &buf); + let start = strukt.syntax().text_range().end(); + + (start, TextUnit::from_usize(3)) + }; + + edit.set_cursor(start_offset + TextUnit::of_str(&buf) - end_offset); + edit.insert(start_offset, buf); + }) +} + +// Generates the surrounding `impl Type { }` including type and lifetime +// parameters +fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String { + let type_params = strukt.type_param_list(); + let mut buf = String::with_capacity(code.len()); + buf.push_str("\n\nimpl"); + if let Some(type_params) = &type_params { + format!(buf, "{}", type_params.syntax()); + } + buf.push_str(" "); + buf.push_str(strukt.name().unwrap().text().as_str()); + if let Some(type_params) = type_params { + let lifetime_params = type_params + .lifetime_params() + .filter_map(|it| it.lifetime_token()) + .map(|it| it.text().clone()); + let type_params = + type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); + join(lifetime_params.chain(type_params)).surround_with("<", ">").to_buf(&mut buf); + } + + format!(&mut buf, " {{\n{}\n}}\n", code); + + buf +} + +// Uses a syntax-driven approach to find any impl blocks for the struct that +// exist within the module/file +// +// Returns `None` if we've found an existing `new` fn +// +// FIXME: change the new fn checking to a more semantic approach when that's more +// viable (e.g. we process proc macros, etc) +fn find_struct_impl( + ctx: &AssistCtx, + strukt: &ast::StructDef, +) -> Option> { + let db = ctx.db; + let module = strukt.syntax().ancestors().find(|node| { + ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind()) + })?; + + let struct_ty = { + let src = hir::Source { file_id: ctx.frange.file_id.into(), ast: strukt.clone() }; + hir::Struct::from_source(db, src).unwrap().ty(db) + }; + + let mut found_new_fn = false; + + let block = module.descendants().filter_map(ast::ImplBlock::cast).find(|impl_blk| { + if found_new_fn { + return false; + } + + let src = hir::Source { file_id: ctx.frange.file_id.into(), ast: impl_blk.clone() }; + let blk = hir::ImplBlock::from_source(db, src).unwrap(); + + let same_ty = blk.target_ty(db) == struct_ty; + let not_trait_impl = blk.target_trait(db).is_none(); + + found_new_fn = has_new_fn(impl_blk); + + same_ty && not_trait_impl + }); + + if found_new_fn { + None + } else { + Some(block) + } +} + +fn has_new_fn(imp: &ast::ImplBlock) -> bool { + if let Some(il) = imp.item_list() { + for item in il.impl_items() { + if let ast::ImplItem::FnDef(f) = item { + if f.name().unwrap().text().eq_ignore_ascii_case("new") { + return true; + } + } + } + } + + false +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; + + #[test] + #[rustfmt::skip] + fn test_add_new() { + // Check output of generation + check_assist( + add_new, +"struct Foo {<|>}", +"struct Foo {} + +impl Foo { + fn new() -> Self { Self { } }<|> +} +", + ); + check_assist( + add_new, +"struct Foo {<|>}", +"struct Foo {} + +impl Foo { + fn new() -> Self { Self { } }<|> +} +", + ); + check_assist( + add_new, +"struct Foo<'a, T: Foo<'a>> {<|>}", +"struct Foo<'a, T: Foo<'a>> {} + +impl<'a, T: Foo<'a>> Foo<'a, T> { + fn new() -> Self { Self { } }<|> +} +", + ); + check_assist( + add_new, +"struct Foo { baz: String <|>}", +"struct Foo { baz: String } + +impl Foo { + fn new(baz: String) -> Self { Self { baz } }<|> +} +", + ); + check_assist( + add_new, +"struct Foo { baz: String, qux: Vec <|>}", +"struct Foo { baz: String, qux: Vec } + +impl Foo { + fn new(baz: String, qux: Vec) -> Self { Self { baz, qux } }<|> +} +", + ); + + // Check that visibility modifiers don't get brought in for fields + check_assist( + add_new, +"struct Foo { pub baz: String, pub qux: Vec <|>}", +"struct Foo { pub baz: String, pub qux: Vec } + +impl Foo { + fn new(baz: String, qux: Vec) -> Self { Self { baz, qux } }<|> +} +", + ); + + // Check that it reuses existing impls + check_assist( + add_new, +"struct Foo {<|>} + +impl Foo {} +", +"struct Foo {} + +impl Foo { + fn new() -> Self { Self { } }<|> +} +", + ); + check_assist( + add_new, +"struct Foo {<|>} + +impl Foo { + fn qux(&self) {} +} +", +"struct Foo {} + +impl Foo { + fn new() -> Self { Self { } }<|> + + fn qux(&self) {} +} +", + ); + + check_assist( + add_new, +"struct Foo {<|>} + +impl Foo { + fn qux(&self) {} + fn baz() -> i32 { + 5 + } +} +", +"struct Foo {} + +impl Foo { + fn new() -> Self { Self { } }<|> + + fn qux(&self) {} + fn baz() -> i32 { + 5 + } +} +", + ); + + // Check visibility of new fn based on struct + check_assist( + add_new, +"pub struct Foo {<|>}", +"pub struct Foo {} + +impl Foo { + pub fn new() -> Self { Self { } }<|> +} +", + ); + check_assist( + add_new, +"pub(crate) struct Foo {<|>}", +"pub(crate) struct Foo {} + +impl Foo { + pub(crate) fn new() -> Self { Self { } }<|> +} +", + ); + } + + #[test] + fn add_new_not_applicable_if_fn_exists() { + check_assist_not_applicable( + add_new, + " +struct Foo {<|>} + +impl Foo { + fn new() -> Self { + Self + } +}", + ); + + check_assist_not_applicable( + add_new, + " +struct Foo {<|>} + +impl Foo { + fn New() -> Self { + Self + } +}", + ); + } + + #[test] + fn add_new_target() { + check_assist_target( + add_new, + " +struct SomeThingIrrelevant; +/// Has a lifetime parameter +struct Foo<'a, T: Foo<'a>> {<|>} +struct EvenMoreIrrelevant; +", + "/// Has a lifetime parameter +struct Foo<'a, T: Foo<'a>> {}", + ); + } +} diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 1bee76f59a..176761efb9 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs @@ -156,6 +156,28 @@ fn process(map: HashMap) {} ) } +#[test] +fn doctest_add_new() { + check( + "add_new", + r#####" +struct Ctx { + data: T,<|> +} +"#####, + r#####" +struct Ctx { + data: T, +} + +impl Ctx { + fn new(data: T) -> Self { Self { data } } +} + +"#####, + ) +} + #[test] fn doctest_apply_demorgan() { check( diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 39c1c283f4..f2f0dacbf7 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -95,6 +95,7 @@ mod assists { mod add_derive; mod add_explicit_type; mod add_impl; + mod add_new; mod apply_demorgan; mod flip_comma; mod flip_binexpr; @@ -119,6 +120,7 @@ mod assists { add_derive::add_derive, add_explicit_type::add_explicit_type, add_impl::add_impl, + add_new::add_new, apply_demorgan::apply_demorgan, change_visibility::change_visibility, fill_match_arms::fill_match_arms, diff --git a/docs/user/assists.md b/docs/user/assists.md index 303353e742..8da7578e2f 100644 --- a/docs/user/assists.md +++ b/docs/user/assists.md @@ -150,6 +150,27 @@ use std::collections::HashMap; fn process(map: HashMap) {} ``` +## `add_new` + +Adds a new inherent impl for a type. + +```rust +// BEFORE +struct Ctx { + data: T,┃ +} + +// AFTER +struct Ctx { + data: T, +} + +impl Ctx { + fn new(data: T) -> Self { Self { data } } +} + +``` + ## `apply_demorgan` Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). From f299e50e6c029124eb26a9abcdc86e19504b7f02 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Thu, 14 Nov 2019 17:30:59 -0500 Subject: [PATCH 02/16] Remove snapshots since we no long commit them --- .gitattributes | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 183e9b5211..bb3cd61512 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1 @@ crates/ra_syntax/test_data/** -text eof=LF -crates/ra_ide_api/src/snapshots/** -text eof=LF From 1e3b1cc7eb42ed006304d24f3c8b24ff71b4dced Mon Sep 17 00:00:00 2001 From: kjeremy Date: Thu, 14 Nov 2019 17:06:44 -0500 Subject: [PATCH 03/16] Set text to autodetect and use LF --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index bb3cd61512..e749e1dc98 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ +* text=auto eol=lf crates/ra_syntax/test_data/** -text eof=LF From 50825a41d8661e4a93f92c81913c675a48247037 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Thu, 14 Nov 2019 17:09:47 -0500 Subject: [PATCH 04/16] Renormalize line endings --- crates/ra_prof/Cargo.toml | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/crates/ra_prof/Cargo.toml b/crates/ra_prof/Cargo.toml index bb241258cf..751bcdeb8a 100644 --- a/crates/ra_prof/Cargo.toml +++ b/crates/ra_prof/Cargo.toml @@ -1,19 +1,19 @@ -[package] -edition = "2018" -name = "ra_prof" -version = "0.1.0" -authors = ["rust-analyzer developers"] -publish = false - -[dependencies] -once_cell = "1.0.1" -itertools = "0.8.0" -backtrace = "0.3.28" - -[target.'cfg(not(target_env = "msvc"))'.dependencies] -jemallocator = { version = "0.3.2", optional = true } -jemalloc-ctl = { version = "0.3.2", optional = true } - -[features] -jemalloc = [ "jemallocator", "jemalloc-ctl" ] -cpu_profiler = [] +[package] +edition = "2018" +name = "ra_prof" +version = "0.1.0" +authors = ["rust-analyzer developers"] +publish = false + +[dependencies] +once_cell = "1.0.1" +itertools = "0.8.0" +backtrace = "0.3.28" + +[target.'cfg(not(target_env = "msvc"))'.dependencies] +jemallocator = { version = "0.3.2", optional = true } +jemalloc-ctl = { version = "0.3.2", optional = true } + +[features] +jemalloc = [ "jemallocator", "jemalloc-ctl" ] +cpu_profiler = [] From 89647f93c499f2db186e8d216e3d279c0ae9fb70 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Thu, 14 Nov 2019 22:48:35 -0500 Subject: [PATCH 05/16] Cleanup hover Take advantage of classify_name --- crates/ra_ide_api/src/hover.rs | 204 +++++++++++++++------------------ 1 file changed, 93 insertions(+), 111 deletions(-) diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 086e6dec3a..07d511fb31 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -5,7 +5,7 @@ use ra_db::SourceDatabase; use ra_syntax::{ algo::{ancestors_at_offset, find_covering_element, find_node_at_offset}, ast::{self, DocCommentsOwner}, - match_ast, AstNode, + AstNode, }; use crate::{ @@ -14,7 +14,7 @@ use crate::{ description_from_symbol, docs_from_symbol, macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, }, - references::{classify_name_ref, NameKind::*}, + references::{classify_name, classify_name_ref, NameKind, NameKind::*}, FilePosition, FileRange, RangeInfo, }; @@ -92,65 +92,88 @@ fn hover_text(docs: Option, desc: Option) -> Option { } } +fn hover_text_from_name_kind( + db: &RootDatabase, + name_kind: NameKind, + no_fallback: &mut bool, +) -> Option { + return match name_kind { + Macro(it) => { + let src = it.source(db); + hover_text(src.ast.doc_comment_text(), Some(macro_label(&src.ast))) + } + Field(it) => { + let src = it.source(db); + match src.ast { + hir::FieldSource::Named(it) => hover_text(it.doc_comment_text(), it.short_label()), + _ => None, + } + } + AssocItem(it) => match it { + hir::AssocItem::Function(it) => from_def_source(db, it), + hir::AssocItem::Const(it) => from_def_source(db, it), + hir::AssocItem::TypeAlias(it) => from_def_source(db, it), + }, + Def(it) => match it { + hir::ModuleDef::Module(it) => match it.definition_source(db).ast { + hir::ModuleSource::Module(it) => { + hover_text(it.doc_comment_text(), it.short_label()) + } + _ => None, + }, + hir::ModuleDef::Function(it) => from_def_source(db, it), + hir::ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it), + hir::ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it), + hir::ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it), + hir::ModuleDef::EnumVariant(it) => from_def_source(db, it), + hir::ModuleDef::Const(it) => from_def_source(db, it), + hir::ModuleDef::Static(it) => from_def_source(db, it), + hir::ModuleDef::Trait(it) => from_def_source(db, it), + hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), + hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), + }, + SelfType(ty) => match ty.as_adt() { + Some((adt_def, _)) => match adt_def { + hir::Adt::Struct(it) => from_def_source(db, it), + hir::Adt::Union(it) => from_def_source(db, it), + hir::Adt::Enum(it) => from_def_source(db, it), + }, + _ => None, + }, + Local(_) => { + // Hover for these shows type names + *no_fallback = true; + None + } + GenericParam(_) => { + // FIXME: Hover for generic param + None + } + }; + + fn from_def_source(db: &RootDatabase, def: D) -> Option + where + D: HasSource, + A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, + { + let src = def.source(db); + hover_text(src.ast.doc_comment_text(), src.ast.short_label()) + } +} + pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option> { let parse = db.parse(position.file_id); let file = parse.tree(); + let mut res = HoverResult::new(); - let mut range = None; - if let Some(name_ref) = find_node_at_offset::(file.syntax(), position.offset) { + let mut range = if let Some(name_ref) = + find_node_at_offset::(file.syntax(), position.offset) + { let mut no_fallback = false; - let name_kind = classify_name_ref(db, position.file_id, &name_ref).map(|d| d.kind); - match name_kind { - Some(Macro(it)) => { - let src = it.source(db); - res.extend(hover_text(src.ast.doc_comment_text(), Some(macro_label(&src.ast)))); - } - Some(Field(it)) => { - let src = it.source(db); - if let hir::FieldSource::Named(it) = src.ast { - res.extend(hover_text(it.doc_comment_text(), it.short_label())); - } - } - Some(AssocItem(it)) => res.extend(match it { - hir::AssocItem::Function(it) => from_def_source(db, it), - hir::AssocItem::Const(it) => from_def_source(db, it), - hir::AssocItem::TypeAlias(it) => from_def_source(db, it), - }), - Some(Def(it)) => match it { - hir::ModuleDef::Module(it) => { - if let hir::ModuleSource::Module(it) = it.definition_source(db).ast { - res.extend(hover_text(it.doc_comment_text(), it.short_label())) - } - } - hir::ModuleDef::Function(it) => res.extend(from_def_source(db, it)), - hir::ModuleDef::Adt(Adt::Struct(it)) => res.extend(from_def_source(db, it)), - hir::ModuleDef::Adt(Adt::Union(it)) => res.extend(from_def_source(db, it)), - hir::ModuleDef::Adt(Adt::Enum(it)) => res.extend(from_def_source(db, it)), - hir::ModuleDef::EnumVariant(it) => res.extend(from_def_source(db, it)), - hir::ModuleDef::Const(it) => res.extend(from_def_source(db, it)), - hir::ModuleDef::Static(it) => res.extend(from_def_source(db, it)), - hir::ModuleDef::Trait(it) => res.extend(from_def_source(db, it)), - hir::ModuleDef::TypeAlias(it) => res.extend(from_def_source(db, it)), - hir::ModuleDef::BuiltinType(it) => res.extend(Some(it.to_string())), - }, - Some(SelfType(ty)) => { - if let Some((adt_def, _)) = ty.as_adt() { - res.extend(match adt_def { - hir::Adt::Struct(it) => from_def_source(db, it), - hir::Adt::Union(it) => from_def_source(db, it), - hir::Adt::Enum(it) => from_def_source(db, it), - }) - } - } - Some(Local(_)) => { - // Hover for these shows type names - no_fallback = true; - } - Some(GenericParam(_)) => { - // FIXME: Hover for generic param - } - None => {} + if let Some(name_kind) = classify_name_ref(db, position.file_id, &name_ref).map(|d| d.kind) + { + res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback)) } if res.is_empty() && !no_fallback { @@ -164,55 +187,24 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option(file.syntax(), position.offset) { - if let Some(parent) = name.syntax().parent() { - let text = match_ast! { - match parent { - ast::StructDef(it) => { - hover_text(it.doc_comment_text(), it.short_label()) - }, - ast::EnumDef(it) => { - hover_text(it.doc_comment_text(), it.short_label()) - }, - ast::EnumVariant(it) => { - hover_text(it.doc_comment_text(), it.short_label()) - }, - ast::FnDef(it) => { - hover_text(it.doc_comment_text(), it.short_label()) - }, - ast::TypeAliasDef(it) => { - hover_text(it.doc_comment_text(), it.short_label()) - }, - ast::ConstDef(it) => { - hover_text(it.doc_comment_text(), it.short_label()) - }, - ast::StaticDef(it) => { - hover_text(it.doc_comment_text(), it.short_label()) - }, - ast::TraitDef(it) => { - hover_text(it.doc_comment_text(), it.short_label()) - }, - ast::RecordFieldDef(it) => { - hover_text(it.doc_comment_text(), it.short_label()) - }, - ast::Module(it) => { - hover_text(it.doc_comment_text(), it.short_label()) - }, - ast::MacroCall(it) => { - hover_text(it.doc_comment_text(), None) - }, - _ => None, - } - }; - res.extend(text); + if let Some(name_kind) = classify_name(db, position.file_id, &name).map(|d| d.kind) { + let mut _b: bool = true; + res.extend(hover_text_from_name_kind(db, name_kind, &mut _b)); } - if !res.is_empty() && range.is_none() { - range = Some(name.syntax().text_range()); + if !res.is_empty() { + Some(name.syntax().text_range()) + } else { + None } - } + } else { + None + }; if range.is_none() { let node = ancestors_at_offset(file.syntax(), position.offset).find(|n| { @@ -221,23 +213,13 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option(db: &RootDatabase, def: D) -> Option - where - D: HasSource, - A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, - { - let src = def.source(db); - hover_text(src.ast.doc_comment_text(), src.ast.short_label()) - } + Some(RangeInfo::new(range, res)) } pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option { From 9c7a2aef30cb35347af646dea5a5611af1224676 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 10:26:31 +0300 Subject: [PATCH 06/16] Refactor Module::from_source to properly descend from root file --- crates/ra_hir/src/code_model.rs | 2 +- crates/ra_hir/src/from_source.rs | 68 +++++++++++++++++--------------- crates/ra_hir_def/src/nameres.rs | 7 ++++ 3 files changed, 44 insertions(+), 33 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 962d5a8c15..dd43271f4c 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -157,7 +157,7 @@ impl Module { } /// Finds a child module with the specified name. - pub fn child(self, db: &impl HirDatabase, name: &Name) -> Option { + pub fn child(self, db: &impl DefDatabase, name: &Name) -> Option { let def_map = db.crate_def_map(self.id.krate); let child_id = def_map[self.id.module_id].children.get(name)?; Some(self.with_module_id(*child_id)) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 9793af8587..7e5523c54a 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,6 +1,6 @@ //! FIXME: write short doc here -use hir_def::{StructId, StructOrUnionId, UnionId}; +use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId}; use hir_expand::name::AsName; use ra_syntax::{ ast::{self, AstNode, NameOwner}, @@ -10,9 +10,9 @@ use ra_syntax::{ use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, ids::{AstItemDef, LocationCtx}, - AstId, Const, Crate, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, - ImplBlock, Local, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, - Union, VariantDef, + Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, ImplBlock, + Local, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, + VariantDef, }; pub trait FromSource: Sized { @@ -152,44 +152,48 @@ impl Local { } impl Module { - pub fn from_declaration(db: &impl HirDatabase, src: Source) -> Option { - let src_parent = Source { - file_id: src.file_id, - ast: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), - }; - let parent_module = Module::from_definition(db, src_parent)?; + pub fn from_declaration(db: &impl DefDatabase, src: Source) -> Option { + let parent_declaration = src.ast.syntax().ancestors().skip(1).find_map(ast::Module::cast); + + let parent_module = match parent_declaration { + Some(parent_declaration) => { + let src_parent = Source { file_id: src.file_id, ast: parent_declaration }; + Module::from_declaration(db, src_parent) + } + _ => { + let src_parent = Source { + file_id: src.file_id, + ast: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), + }; + Module::from_definition(db, src_parent) + } + }?; + let child_name = src.ast.name()?; parent_module.child(db, &child_name.as_name()) } - pub fn from_definition( - db: &(impl DefDatabase + AstDatabase), - src: Source, - ) -> Option { - let decl_id = match src.ast { + pub fn from_definition(db: &impl DefDatabase, src: Source) -> Option { + match src.ast { ModuleSource::Module(ref module) => { assert!(!module.has_semi()); - let ast_id_map = db.ast_id_map(src.file_id); - let item_id = AstId::new(src.file_id, ast_id_map.ast_id(module)); - Some(item_id) + return Module::from_declaration( + db, + Source { file_id: src.file_id, ast: module.clone() }, + ); } - ModuleSource::SourceFile(_) => None, + ModuleSource::SourceFile(_) => (), }; - db.relevant_crates(src.file_id.original_file(db)).iter().find_map(|&crate_id| { - let def_map = db.crate_def_map(crate_id); + let original_file = src.file_id.original_file(db); - let (module_id, _module_data) = - def_map.modules.iter().find(|(_module_id, module_data)| { - if decl_id.is_some() { - module_data.declaration == decl_id - } else { - module_data.definition.map(|it| it.into()) == Some(src.file_id) - } - })?; - - Some(Module::new(Crate { crate_id }, module_id)) - }) + let (krate, module_id) = + db.relevant_crates(original_file).iter().find_map(|&crate_id| { + let crate_def_map = db.crate_def_map(crate_id); + let local_module_id = crate_def_map.modules_for_file(original_file).next()?; + Some((crate_id, local_module_id)) + })?; + Some(Module { id: ModuleId { krate, module_id } }) } } diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index d3ecabb9be..1331fbe307 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -258,6 +258,13 @@ impl CrateDefMap { let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); (res.resolved_def, res.segment_index) } + + pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator + '_ { + self.modules + .iter() + .filter(move |(_id, data)| data.definition == Some(file_id)) + .map(|(id, _data)| id) + } } mod diagnostics { From a28907af8ca93077601053cf168ac2429855c394 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 10:42:54 +0300 Subject: [PATCH 07/16] Privatize modules --- crates/ra_hir/src/test_db.rs | 2 +- crates/ra_hir_def/src/nameres.rs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir/src/test_db.rs b/crates/ra_hir/src/test_db.rs index 5237b303af..1caa2e8759 100644 --- a/crates/ra_hir/src/test_db.rs +++ b/crates/ra_hir/src/test_db.rs @@ -81,7 +81,7 @@ impl TestDB { let crate_graph = self.crate_graph(); for krate in crate_graph.iter().next() { let crate_def_map = self.crate_def_map(krate); - for (module_id, _) in crate_def_map.modules.iter() { + for module_id in crate_def_map.modules() { let module_id = ModuleId { krate, module_id }; let module = crate::Module::from(module_id); module.diagnostics( diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 1331fbe307..5fc5921500 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -87,7 +87,7 @@ pub struct CrateDefMap { prelude: Option, extern_prelude: FxHashMap, root: CrateModuleId, - pub modules: Arena, + modules: Arena, /// Some macros are not well-behavior, which leads to infinite loop /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } @@ -259,6 +259,10 @@ impl CrateDefMap { (res.resolved_def, res.segment_index) } + pub fn modules(&self) -> impl Iterator + '_ { + self.modules.iter().map(|(id, _data)| id) + } + pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator + '_ { self.modules .iter() From b80fa14a850db78b1f45de95b0edde1a65da4625 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 12:00:36 +0300 Subject: [PATCH 08/16] Use Local more --- crates/ra_hir/src/expr.rs | 2 +- crates/ra_hir/src/resolve.rs | 17 ++++++++++------- crates/ra_hir/src/source_binder.rs | 8 -------- .../ra_ide_api/src/completion/presentation.rs | 14 ++++++-------- 4 files changed, 17 insertions(+), 24 deletions(-) diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 9262325f23..899e0fa04a 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -38,7 +38,7 @@ pub(crate) fn resolver_for_scope( let scopes = owner.expr_scopes(db); let scope_chain = scopes.scope_chain(scope_id).collect::>(); for scope in scope_chain.into_iter().rev() { - r = r.push_expr_scope(Arc::clone(&scopes), scope); + r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); } r } diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 2f3e12eb83..b922fe20fa 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -16,8 +16,8 @@ use crate::{ expr::{ExprScopes, PatId, ScopeId}, generics::GenericParams, impl_block::ImplBlock, - Adt, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, PerNs, Static, Struct, Trait, - TypeAlias, + Adt, Const, DefWithBody, Enum, EnumVariant, Function, Local, MacroDef, ModuleDef, PerNs, + Static, Struct, Trait, TypeAlias, }; #[derive(Debug, Clone, Default)] @@ -34,6 +34,7 @@ pub(crate) struct ModuleItemMap { #[derive(Debug, Clone)] pub(crate) struct ExprScope { + owner: DefWithBody, expr_scopes: Arc, scope_id: ScopeId, } @@ -399,10 +400,11 @@ impl Resolver { pub(crate) fn push_expr_scope( self, + owner: DefWithBody, expr_scopes: Arc, scope_id: ScopeId, ) -> Resolver { - self.push_scope(Scope::ExprScope(ExprScope { expr_scopes, scope_id })) + self.push_scope(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id })) } } @@ -413,7 +415,7 @@ pub enum ScopeDef { GenericParam(u32), ImplSelfType(ImplBlock), AdtSelfType(Adt), - LocalBinding(PatId), + Local(Local), Unknown, } @@ -467,9 +469,10 @@ impl Scope { Scope::AdtScope(i) => { f(name::SELF_TYPE, ScopeDef::AdtSelfType(*i)); } - Scope::ExprScope(e) => { - e.expr_scopes.entries(e.scope_id).iter().for_each(|e| { - f(e.name().clone(), ScopeDef::LocalBinding(e.pat())); + Scope::ExprScope(scope) => { + scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { + let local = Local { parent: scope.owner, pat_id: e.pat() }; + f(e.name().clone(), ScopeDef::Local(local)); }); } } diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index ca40e3b544..59046edcc4 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -195,14 +195,6 @@ impl SourceAnalyzer { Some(self.infer.as_ref()?[pat_id].clone()) } - pub fn type_of_pat_by_id( - &self, - _db: &impl HirDatabase, - pat_id: expr::PatId, - ) -> Option { - Some(self.infer.as_ref()?[pat_id].clone()) - } - pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option { let expr_id = self.expr_id(&call.clone().into())?; self.infer.as_ref()?.method_resolution(expr_id) diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index d861303b75..c343cece64 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs @@ -68,7 +68,7 @@ impl Completions { ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::TypeAlias, ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, ScopeDef::GenericParam(..) => CompletionItemKind::TypeParam, - ScopeDef::LocalBinding(..) => CompletionItemKind::Binding, + ScopeDef::Local(..) => CompletionItemKind::Binding, // (does this need its own kind?) ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => CompletionItemKind::TypeParam, ScopeDef::MacroDef(mac) => { @@ -96,13 +96,11 @@ impl Completions { let mut completion_item = CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone()); - if let ScopeDef::LocalBinding(pat_id) = resolution { - let ty = ctx - .analyzer - .type_of_pat_by_id(ctx.db, pat_id.clone()) - .filter(|t| t != &Ty::Unknown) - .map(|t| t.display(ctx.db).to_string()); - completion_item = completion_item.set_detail(ty); + if let ScopeDef::Local(local) = resolution { + let ty = local.ty(ctx.db); + if ty != Ty::Unknown { + completion_item = completion_item.detail(ty.display(ctx.db).to_string()); + } }; // If not an import, add parenthesis automatically. From 487fc448c3fae2f494f0e5a9e208aa012cfb6309 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 12:24:30 +0300 Subject: [PATCH 09/16] Reduce visibility --- crates/ra_hir/src/resolve.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index b922fe20fa..2fb9131087 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -54,7 +54,7 @@ pub(crate) enum Scope { } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum TypeNs { +pub(crate) enum TypeNs { SelfType(ImplBlock), GenericParam(u32), Adt(Adt), @@ -69,13 +69,13 @@ pub enum TypeNs { } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum ResolveValueResult { +pub(crate) enum ResolveValueResult { ValueNs(ValueNs), Partial(TypeNs, usize), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum ValueNs { +pub(crate) enum ValueNs { LocalBinding(PatId), Function(Function), Const(Const), From 3564fbb7f5fc7fc91530c441a6dacce88762fcc9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 12:56:24 +0300 Subject: [PATCH 10/16] Auto-upgrade some insta snapshots --- crates/ra_hir/src/ty/tests.rs | 54 +- .../ra_ide_api/src/completion/complete_dot.rs | 94 +- .../src/completion/complete_fn_param.rs | 54 +- .../src/completion/complete_keyword.rs | 960 +++++++++--------- .../complete_macro_in_item_position.rs | 95 +- .../src/completion/complete_path.rs | 332 +++--- .../src/completion/complete_pattern.rs | 60 +- .../src/completion/complete_postfix.rs | 298 +++--- .../src/completion/complete_record_literal.rs | 102 +- .../src/completion/complete_record_pattern.rs | 56 +- .../src/completion/complete_scope.rs | 56 +- .../src/completion/complete_snippet.rs | 74 +- .../ra_ide_api/src/completion/presentation.rs | 146 +-- crates/ra_ide_api/src/diagnostics.rs | 44 +- crates/ra_ide_api/src/display/structure.rs | 372 +++---- crates/ra_ide_api/src/inlay_hints.rs | 314 +++--- crates/ra_ide_api/src/runnables.rs | 128 +-- 17 files changed, 1643 insertions(+), 1596 deletions(-) diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 8863c36087..fe9346c783 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -254,7 +254,6 @@ fn test(a: u32, b: isize, c: !, d: &str) { 1.0f32; }"#), @r###" - [9; 10) 'a': u32 [17; 18) 'b': isize [27; 28) 'c': ! @@ -317,7 +316,6 @@ fn test() { } "#), @r###" - [15; 20) '{ 1 }': u32 [17; 18) '1': u32 [48; 53) '{ 1 }': u32 @@ -354,7 +352,7 @@ fn test() { [66; 74) 'S::foo()': i32 [80; 88) '::foo': fn foo() -> i32 [80; 90) '::foo()': i32 -"### + "### ); } @@ -409,7 +407,6 @@ fn test() { } "#), @r###" - [72; 154) '{ ...a.c; }': () [82; 83) 'c': C [86; 87) 'C': C(usize) -> C @@ -443,7 +440,6 @@ fn test() { E::V2; }"#), @r###" - [48; 82) '{ E:...:V2; }': () [52; 70) 'E::V1 ...d: 1 }': E [67; 68) '1': u32 @@ -471,7 +467,6 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { } "#), @r###" - [9; 10) 'a': &u32 [18; 19) 'b': &mut u32 [31; 32) 'c': *const u32 @@ -524,7 +519,6 @@ fn test() { } "##), @r###" - [11; 221) '{ ...o"#; }': () [17; 21) '5i32': i32 [27; 31) '5f32': f32 @@ -568,7 +562,6 @@ fn test(x: SomeType) { } "#), @r###" - [27; 28) 'x': SomeType [40; 272) '{ ...lo"; }': () [50; 51) 'b': bool @@ -632,7 +625,6 @@ fn test() -> &mut &f64 { } "#), @r###" - [14; 15) 'x': u32 [22; 24) '{}': () [78; 231) '{ ...t &c }': &mut &f64 @@ -679,7 +671,6 @@ impl S { } "#), @r###" - [34; 38) 'self': &S [40; 61) '{ ... }': () [50; 54) 'self': &S @@ -719,7 +710,6 @@ fn test() -> bool { } "#), @r###" - [6; 7) 'x': bool [22; 34) '{ 0i32 }': i32 [28; 32) '0i32': i32 @@ -802,7 +792,6 @@ fn test2(a1: *const A, a2: *mut A) { } "#), @r###" - [44; 45) 'a': A [50; 213) '{ ...5.b; }': () [60; 62) 'a1': A @@ -970,7 +959,7 @@ fn test(a: A) { [374; 375) 'B': B>(T) -> B [374; 378) 'B(a)': B> [376; 377) 'a': A -"### + "### ); } @@ -983,7 +972,6 @@ fn test() { } "#), @r###" - [11; 37) '{ l... {}; }': () [20; 21) 'x': () [24; 34) 'if true {}': () @@ -1105,7 +1093,6 @@ fn test(a: A) { } "#), @r###" - [32; 36) 'self': A [38; 39) 'x': u32 [53; 55) '{}': () @@ -1142,7 +1129,6 @@ fn test() { } "#), @r###" - [40; 44) 'self': &str [53; 55) '{}': () [69; 89) '{ ...o(); }': () @@ -1166,7 +1152,6 @@ fn test(x: &str, y: isize) { } "#), @r###" - [9; 10) 'x': &str [18; 19) 'y': isize [28; 170) '{ ...d"); }': () @@ -1367,7 +1352,6 @@ fn test() { } "#), @r###" - [28; 79) '{ ...(1); }': () [38; 42) 'A(n)': A [40; 41) 'n': &i32 @@ -1396,7 +1380,6 @@ fn test() { } "#), @r###" - [11; 57) '{ ...= v; }': () [21; 22) 'v': &(i32, &i32) [25; 33) '&(1, &2)': &(i32, &i32) @@ -1441,7 +1424,6 @@ fn test() { } "#), @r###" - [68; 289) '{ ... d; }': () [78; 79) 'e': E [82; 95) 'E::A { x: 3 }': E @@ -1488,7 +1470,6 @@ fn test(a1: A, i: i32) { } "#), @r###" - [36; 38) 'a1': A [48; 49) 'i': i32 [56; 147) '{ ...3.x; }': () @@ -1569,7 +1550,6 @@ fn test(a1: A, o: Option) { } "#), @r###" - [79; 81) 'a1': A [91; 92) 'o': Option [107; 244) '{ ... }; }': () @@ -1604,7 +1584,6 @@ fn test() { } "#), @r###" - [10; 11) 't': T [21; 26) '{ t }': T [23; 24) 't': T @@ -1652,7 +1631,6 @@ fn test() -> i128 { } "#), @r###" - [74; 78) 'self': A [85; 107) '{ ... }': X [95; 99) 'self': A @@ -1706,7 +1684,6 @@ fn test(o: Option) { } "#), @r###" - [78; 82) 'self': &Option [98; 100) '{}': () [111; 112) 'o': Option @@ -1744,7 +1721,6 @@ fn test() -> i128 { } "#), @r###" - [53; 57) 'self': A [65; 87) '{ ... }': T2 [75; 79) 'self': A @@ -1921,7 +1897,6 @@ fn test() { } "#), @r###" - [56; 64) '{ A {} }': A [58; 62) 'A {}': A [126; 132) '{ 99 }': u32 @@ -1961,7 +1936,6 @@ fn test() { } "#), @r###" - [64; 67) 'val': T [82; 109) '{ ... }': Gen [92; 103) 'Gen { val }': Gen @@ -2129,7 +2103,6 @@ fn test(x: X) { } "#), @r###" - [20; 21) 'x': X [26; 47) '{ ...eld; }': () [32; 33) 'x': X @@ -2151,7 +2124,6 @@ fn test() { } "#), @r###" - [11; 89) '{ ... } }': () [17; 21) 'X {}': {unknown} [27; 87) 'match ... }': () @@ -2174,7 +2146,6 @@ fn quux() { } "#), @r###" - [11; 41) '{ ...+ y; }': () [21; 22) 'y': i32 [25; 27) '92': i32 @@ -2300,7 +2271,6 @@ fn write() { } "#), @r###" - [54; 139) '{ ... } }': () [60; 137) 'match ... }': () [66; 83) 'someth...nknown': Maybe<{unknown}> @@ -2322,7 +2292,6 @@ fn test_line_buffer() { } "#), @r###" - [23; 53) '{ ...n']; }': () [29; 50) '&[0, b...b'\n']': &[u8;_] [30; 50) '[0, b'...b'\n']': [u8;_] @@ -2446,7 +2415,6 @@ fn test(query_response: Canonical>) { } "#), @r###" - [92; 106) 'query_response': Canonical> [137; 167) '{ ...lue; }': () [143; 164) '&query....value': &QueryResponse @@ -2472,7 +2440,6 @@ pub fn main_loop() { } "#), @r###" - [144; 146) '{}': () [169; 198) '{ ...t(); }': () [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet @@ -2518,7 +2485,6 @@ fn test() { } "#), @r###" - [49; 50) '0': u32 [80; 83) '101': u32 [95; 213) '{ ...NST; }': () @@ -2549,7 +2515,6 @@ fn test() { } "#), @r###" - [29; 32) '101': u32 [70; 73) '101': u32 [85; 280) '{ ...MUT; }': () @@ -2588,7 +2553,6 @@ fn test() { } "#), @r###" - [31; 35) 'self': &Self [110; 114) 'self': &Self [170; 228) '{ ...i128 }': () @@ -2636,7 +2600,6 @@ mod bar_test { } "#), @r###" - [63; 67) 'self': &Self [169; 173) 'self': &Self [300; 337) '{ ... }': () @@ -2664,7 +2627,6 @@ fn test() { } "#), @r###" - [33; 37) 'self': &Self [92; 111) '{ ...d(); }': () [98; 99) 'S': S @@ -2694,7 +2656,6 @@ fn test() { } "#), @r###" - [43; 47) 'self': &Self [82; 86) 'self': &Self [210; 361) '{ ..., i8 }': () @@ -2725,7 +2686,6 @@ fn test() { } "#), @r###" - [33; 37) 'self': &Self [102; 127) '{ ...d(); }': () [108; 109) 'S': S(T) -> S @@ -3130,7 +3090,6 @@ fn test>() { } "#), @r###" - [67; 100) '{ ...own; }': () [77; 78) 'y': {unknown} [90; 97) 'unknown': {unknown} @@ -3146,7 +3105,6 @@ const A: u32 = 1 + 1; static B: u64 = { let x = 1; x }; "#), @r###" - [16; 17) '1': u32 [16; 21) '1 + 1': u32 [20; 21) '1': u32 @@ -3170,7 +3128,6 @@ fn test() -> u64 { } "#), @r###" - [38; 87) '{ ... a.1 }': u64 [48; 49) 'a': S [52; 53) 'S': S(i32, u64) -> S @@ -3225,7 +3182,6 @@ fn indexing_arrays() { assert_snapshot!( infer("fn main() { &mut [9][2]; }"), @r###" - [10; 26) '{ &mut...[2]; }': () [12; 23) '&mut [9][2]': &mut {unknown} [17; 20) '[9]': [i32;_] @@ -4822,9 +4778,9 @@ fn main() { } "#), @r###" - ![0; 1) '6': i32 - [64; 88) '{ ...!(); }': () - [74; 75) 'x': i32 + ![0; 1) '6': i32 + [64; 88) '{ ...!(); }': () + [74; 75) 'x': i32 "### ); } diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index b4df6ee2ad..4e2c497e1d 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -88,16 +88,16 @@ mod tests { ", ), @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "the_field", - ⋮ source_range: [94; 94), - ⋮ delete: [94; 94), - ⋮ insert: "the_field", - ⋮ kind: Field, - ⋮ detail: "u32", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "the_field", + source_range: [94; 94), + delete: [94; 94), + insert: "the_field", + kind: Field, + detail: "u32", + }, + ] "### ); } @@ -349,24 +349,24 @@ mod tests { ", ), @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "0", - ⋮ source_range: [75; 75), - ⋮ delete: [75; 75), - ⋮ insert: "0", - ⋮ kind: Field, - ⋮ detail: "i32", - ⋮ }, - ⋮ CompletionItem { - ⋮ label: "1", - ⋮ source_range: [75; 75), - ⋮ delete: [75; 75), - ⋮ insert: "1", - ⋮ kind: Field, - ⋮ detail: "f64", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "0", + source_range: [75; 75), + delete: [75; 75), + insert: "0", + kind: Field, + detail: "i32", + }, + CompletionItem { + label: "1", + source_range: [75; 75), + delete: [75; 75), + insert: "1", + kind: Field, + detail: "f64", + }, + ] "### ); } @@ -419,16 +419,16 @@ mod tests { ", ), @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "the_field", - ⋮ source_range: [106; 106), - ⋮ delete: [106; 106), - ⋮ insert: "the_field", - ⋮ kind: Field, - ⋮ detail: "u32", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "the_field", + source_range: [106; 106), + delete: [106; 106), + insert: "the_field", + kind: Field, + detail: "u32", + }, + ] "### ); } @@ -452,15 +452,15 @@ mod tests { } "###, CompletionKind::Keyword), @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "await", - ⋮ source_range: [74; 74), - ⋮ delete: [74; 74), - ⋮ insert: "await", - ⋮ detail: "expr.await", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "await", + source_range: [74; 74), + delete: [74; 74), + insert: "await", + detail: "expr.await", + }, + ] "### ) } diff --git a/crates/ra_ide_api/src/completion/complete_fn_param.rs b/crates/ra_ide_api/src/completion/complete_fn_param.rs index 3e936e3ecb..5024587065 100644 --- a/crates/ra_ide_api/src/completion/complete_fn_param.rs +++ b/crates/ra_ide_api/src/completion/complete_fn_param.rs @@ -70,15 +70,15 @@ mod tests { ", ), @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "file_id: FileId", - ⋮ source_range: [110; 114), - ⋮ delete: [110; 114), - ⋮ insert: "file_id: FileId", - ⋮ lookup: "file_id", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "file_id: FileId", + source_range: [110; 114), + delete: [110; 114), + insert: "file_id: FileId", + lookup: "file_id", + }, + ] "### ); } @@ -94,15 +94,15 @@ mod tests { ", ), @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "file_id: FileId", - ⋮ source_range: [110; 114), - ⋮ delete: [110; 114), - ⋮ insert: "file_id: FileId", - ⋮ lookup: "file_id", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "file_id: FileId", + source_range: [110; 114), + delete: [110; 114), + insert: "file_id: FileId", + lookup: "file_id", + }, + ] "### ); } @@ -121,15 +121,15 @@ mod tests { ", ), @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "file_id: FileId", - ⋮ source_range: [289; 293), - ⋮ delete: [289; 293), - ⋮ insert: "file_id: FileId", - ⋮ lookup: "file_id", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "file_id: FileId", + source_range: [289; 293), + delete: [289; 293), + insert: "file_id: FileId", + lookup: "file_id", + }, + ] "### ); } diff --git a/crates/ra_ide_api/src/completion/complete_keyword.rs b/crates/ra_ide_api/src/completion/complete_keyword.rs index 48c688a08a..eb7cd9ac20 100644 --- a/crates/ra_ide_api/src/completion/complete_keyword.rs +++ b/crates/ra_ide_api/src/completion/complete_keyword.rs @@ -131,29 +131,31 @@ mod tests { use <|> ", ), - @r###"[ - CompletionItem { - label: "crate", - source_range: [21; 21), - delete: [21; 21), - insert: "crate::", - kind: Keyword, - }, - CompletionItem { - label: "self", - source_range: [21; 21), - delete: [21; 21), - insert: "self", - kind: Keyword, - }, - CompletionItem { - label: "super", - source_range: [21; 21), - delete: [21; 21), - insert: "super::", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "crate", + source_range: [21; 21), + delete: [21; 21), + insert: "crate::", + kind: Keyword, + }, + CompletionItem { + label: "self", + source_range: [21; 21), + delete: [21; 21), + insert: "self", + kind: Keyword, + }, + CompletionItem { + label: "super", + source_range: [21; 21), + delete: [21; 21), + insert: "super::", + kind: Keyword, + }, + ] + "### ); assert_debug_snapshot!( @@ -162,22 +164,24 @@ mod tests { use a::<|> ", ), - @r###"[ - CompletionItem { - label: "self", - source_range: [24; 24), - delete: [24; 24), - insert: "self", - kind: Keyword, - }, - CompletionItem { - label: "super", - source_range: [24; 24), - delete: [24; 24), - insert: "super::", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "self", + source_range: [24; 24), + delete: [24; 24), + insert: "self", + kind: Keyword, + }, + CompletionItem { + label: "super", + source_range: [24; 24), + delete: [24; 24), + insert: "super::", + kind: Keyword, + }, + ] + "### ); assert_debug_snapshot!( @@ -186,22 +190,24 @@ mod tests { use a::{b, <|>} ", ), - @r###"[ - CompletionItem { - label: "self", - source_range: [28; 28), - delete: [28; 28), - insert: "self", - kind: Keyword, - }, - CompletionItem { - label: "super", - source_range: [28; 28), - delete: [28; 28), - insert: "super::", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "self", + source_range: [28; 28), + delete: [28; 28), + insert: "self", + kind: Keyword, + }, + CompletionItem { + label: "super", + source_range: [28; 28), + delete: [28; 28), + insert: "super::", + kind: Keyword, + }, + ] + "### ); } @@ -215,43 +221,45 @@ mod tests { } ", ), - @r###"[ - CompletionItem { - label: "if", - source_range: [49; 49), - delete: [49; 49), - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: [49; 49), - delete: [49; 49), - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: [49; 49), - delete: [49; 49), - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: [49; 49), - delete: [49; 49), - insert: "return;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: [49; 49), - delete: [49; 49), - insert: "while $0 {}", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "if", + source_range: [49; 49), + delete: [49; 49), + insert: "if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "loop", + source_range: [49; 49), + delete: [49; 49), + insert: "loop {$0}", + kind: Keyword, + }, + CompletionItem { + label: "match", + source_range: [49; 49), + delete: [49; 49), + insert: "match $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "return", + source_range: [49; 49), + delete: [49; 49), + insert: "return;", + kind: Keyword, + }, + CompletionItem { + label: "while", + source_range: [49; 49), + delete: [49; 49), + insert: "while $0 {}", + kind: Keyword, + }, + ] + "### ); } @@ -267,57 +275,59 @@ mod tests { } ", ), - @r###"[ - CompletionItem { - label: "else", - source_range: [108; 108), - delete: [108; 108), - insert: "else {$0}", - kind: Keyword, - }, - CompletionItem { - label: "else if", - source_range: [108; 108), - delete: [108; 108), - insert: "else if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "if", - source_range: [108; 108), - delete: [108; 108), - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: [108; 108), - delete: [108; 108), - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: [108; 108), - delete: [108; 108), - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: [108; 108), - delete: [108; 108), - insert: "return;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: [108; 108), - delete: [108; 108), - insert: "while $0 {}", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "else", + source_range: [108; 108), + delete: [108; 108), + insert: "else {$0}", + kind: Keyword, + }, + CompletionItem { + label: "else if", + source_range: [108; 108), + delete: [108; 108), + insert: "else if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "if", + source_range: [108; 108), + delete: [108; 108), + insert: "if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "loop", + source_range: [108; 108), + delete: [108; 108), + insert: "loop {$0}", + kind: Keyword, + }, + CompletionItem { + label: "match", + source_range: [108; 108), + delete: [108; 108), + insert: "match $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "return", + source_range: [108; 108), + delete: [108; 108), + insert: "return;", + kind: Keyword, + }, + CompletionItem { + label: "while", + source_range: [108; 108), + delete: [108; 108), + insert: "while $0 {}", + kind: Keyword, + }, + ] + "### ); } @@ -332,43 +342,45 @@ mod tests { } ", ), - @r###"[ - CompletionItem { - label: "if", - source_range: [56; 56), - delete: [56; 56), - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: [56; 56), - delete: [56; 56), - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: [56; 56), - delete: [56; 56), - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: [56; 56), - delete: [56; 56), - insert: "return $0;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: [56; 56), - delete: [56; 56), - insert: "while $0 {}", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "if", + source_range: [56; 56), + delete: [56; 56), + insert: "if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "loop", + source_range: [56; 56), + delete: [56; 56), + insert: "loop {$0}", + kind: Keyword, + }, + CompletionItem { + label: "match", + source_range: [56; 56), + delete: [56; 56), + insert: "match $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "return", + source_range: [56; 56), + delete: [56; 56), + insert: "return $0;", + kind: Keyword, + }, + CompletionItem { + label: "while", + source_range: [56; 56), + delete: [56; 56), + insert: "while $0 {}", + kind: Keyword, + }, + ] + "### ); assert_debug_snapshot!( do_keyword_completion( @@ -379,43 +391,45 @@ mod tests { } ", ), - @r###"[ - CompletionItem { - label: "if", - source_range: [49; 49), - delete: [49; 49), - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: [49; 49), - delete: [49; 49), - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: [49; 49), - delete: [49; 49), - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: [49; 49), - delete: [49; 49), - insert: "return;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: [49; 49), - delete: [49; 49), - insert: "while $0 {}", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "if", + source_range: [49; 49), + delete: [49; 49), + insert: "if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "loop", + source_range: [49; 49), + delete: [49; 49), + insert: "loop {$0}", + kind: Keyword, + }, + CompletionItem { + label: "match", + source_range: [49; 49), + delete: [49; 49), + insert: "match $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "return", + source_range: [49; 49), + delete: [49; 49), + insert: "return;", + kind: Keyword, + }, + CompletionItem { + label: "while", + source_range: [49; 49), + delete: [49; 49), + insert: "while $0 {}", + kind: Keyword, + }, + ] + "### ); } @@ -431,43 +445,45 @@ mod tests { } ", ), - @r###"[ - CompletionItem { - label: "if", - source_range: [97; 97), - delete: [97; 97), - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: [97; 97), - delete: [97; 97), - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: [97; 97), - delete: [97; 97), - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: [97; 97), - delete: [97; 97), - insert: "return $0", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: [97; 97), - delete: [97; 97), - insert: "while $0 {}", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "if", + source_range: [97; 97), + delete: [97; 97), + insert: "if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "loop", + source_range: [97; 97), + delete: [97; 97), + insert: "loop {$0}", + kind: Keyword, + }, + CompletionItem { + label: "match", + source_range: [97; 97), + delete: [97; 97), + insert: "match $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "return", + source_range: [97; 97), + delete: [97; 97), + insert: "return $0", + kind: Keyword, + }, + CompletionItem { + label: "while", + source_range: [97; 97), + delete: [97; 97), + insert: "while $0 {}", + kind: Keyword, + }, + ] + "### ); } @@ -483,43 +499,45 @@ mod tests { } ", ), - @r###"[ - CompletionItem { - label: "if", - source_range: [95; 95), - delete: [95; 95), - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: [95; 95), - delete: [95; 95), - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: [95; 95), - delete: [95; 95), - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: [95; 95), - delete: [95; 95), - insert: "return $0;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: [95; 95), - delete: [95; 95), - insert: "while $0 {}", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "if", + source_range: [95; 95), + delete: [95; 95), + insert: "if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "loop", + source_range: [95; 95), + delete: [95; 95), + insert: "loop {$0}", + kind: Keyword, + }, + CompletionItem { + label: "match", + source_range: [95; 95), + delete: [95; 95), + insert: "match $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "return", + source_range: [95; 95), + delete: [95; 95), + insert: "return $0;", + kind: Keyword, + }, + CompletionItem { + label: "while", + source_range: [95; 95), + delete: [95; 95), + insert: "while $0 {}", + kind: Keyword, + }, + ] + "### ); assert_debug_snapshot!( do_keyword_completion( @@ -533,43 +551,45 @@ mod tests { } ", ), - @r###"[ - CompletionItem { - label: "if", - source_range: [95; 95), - delete: [95; 95), - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: [95; 95), - delete: [95; 95), - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: [95; 95), - delete: [95; 95), - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: [95; 95), - delete: [95; 95), - insert: "return $0;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: [95; 95), - delete: [95; 95), - insert: "while $0 {}", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "if", + source_range: [95; 95), + delete: [95; 95), + insert: "if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "loop", + source_range: [95; 95), + delete: [95; 95), + insert: "loop {$0}", + kind: Keyword, + }, + CompletionItem { + label: "match", + source_range: [95; 95), + delete: [95; 95), + insert: "match $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "return", + source_range: [95; 95), + delete: [95; 95), + insert: "return $0;", + kind: Keyword, + }, + CompletionItem { + label: "while", + source_range: [95; 95), + delete: [95; 95), + insert: "while $0 {}", + kind: Keyword, + }, + ] + "### ); } @@ -583,57 +603,59 @@ mod tests { } ", ), - @r###"[ - CompletionItem { - label: "break", - source_range: [63; 63), - delete: [63; 63), - insert: "break;", - kind: Keyword, - }, - CompletionItem { - label: "continue", - source_range: [63; 63), - delete: [63; 63), - insert: "continue;", - kind: Keyword, - }, - CompletionItem { - label: "if", - source_range: [63; 63), - delete: [63; 63), - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: [63; 63), - delete: [63; 63), - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: [63; 63), - delete: [63; 63), - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: [63; 63), - delete: [63; 63), - insert: "return $0;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: [63; 63), - delete: [63; 63), - insert: "while $0 {}", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "break", + source_range: [63; 63), + delete: [63; 63), + insert: "break;", + kind: Keyword, + }, + CompletionItem { + label: "continue", + source_range: [63; 63), + delete: [63; 63), + insert: "continue;", + kind: Keyword, + }, + CompletionItem { + label: "if", + source_range: [63; 63), + delete: [63; 63), + insert: "if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "loop", + source_range: [63; 63), + delete: [63; 63), + insert: "loop {$0}", + kind: Keyword, + }, + CompletionItem { + label: "match", + source_range: [63; 63), + delete: [63; 63), + insert: "match $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "return", + source_range: [63; 63), + delete: [63; 63), + insert: "return $0;", + kind: Keyword, + }, + CompletionItem { + label: "while", + source_range: [63; 63), + delete: [63; 63), + insert: "while $0 {}", + kind: Keyword, + }, + ] + "### ); // No completion: lambda isolates control flow @@ -645,43 +667,45 @@ mod tests { } ", ), - @r###"[ - CompletionItem { - label: "if", - source_range: [68; 68), - delete: [68; 68), - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: [68; 68), - delete: [68; 68), - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: [68; 68), - delete: [68; 68), - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: [68; 68), - delete: [68; 68), - insert: "return $0;", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: [68; 68), - delete: [68; 68), - insert: "while $0 {}", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "if", + source_range: [68; 68), + delete: [68; 68), + insert: "if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "loop", + source_range: [68; 68), + delete: [68; 68), + insert: "loop {$0}", + kind: Keyword, + }, + CompletionItem { + label: "match", + source_range: [68; 68), + delete: [68; 68), + insert: "match $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "return", + source_range: [68; 68), + delete: [68; 68), + insert: "return $0;", + kind: Keyword, + }, + CompletionItem { + label: "while", + source_range: [68; 68), + delete: [68; 68), + insert: "while $0 {}", + kind: Keyword, + }, + ] + "### ); } @@ -699,57 +723,59 @@ mod tests { } ", ), - @r###"[ - CompletionItem { - label: "break", - source_range: [122; 124), - delete: [122; 124), - insert: "break", - kind: Keyword, - }, - CompletionItem { - label: "continue", - source_range: [122; 124), - delete: [122; 124), - insert: "continue", - kind: Keyword, - }, - CompletionItem { - label: "if", - source_range: [122; 124), - delete: [122; 124), - insert: "if $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "loop", - source_range: [122; 124), - delete: [122; 124), - insert: "loop {$0}", - kind: Keyword, - }, - CompletionItem { - label: "match", - source_range: [122; 124), - delete: [122; 124), - insert: "match $0 {}", - kind: Keyword, - }, - CompletionItem { - label: "return", - source_range: [122; 124), - delete: [122; 124), - insert: "return", - kind: Keyword, - }, - CompletionItem { - label: "while", - source_range: [122; 124), - delete: [122; 124), - insert: "while $0 {}", - kind: Keyword, - }, -]"### + @r###" + [ + CompletionItem { + label: "break", + source_range: [122; 124), + delete: [122; 124), + insert: "break", + kind: Keyword, + }, + CompletionItem { + label: "continue", + source_range: [122; 124), + delete: [122; 124), + insert: "continue", + kind: Keyword, + }, + CompletionItem { + label: "if", + source_range: [122; 124), + delete: [122; 124), + insert: "if $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "loop", + source_range: [122; 124), + delete: [122; 124), + insert: "loop {$0}", + kind: Keyword, + }, + CompletionItem { + label: "match", + source_range: [122; 124), + delete: [122; 124), + insert: "match $0 {}", + kind: Keyword, + }, + CompletionItem { + label: "return", + source_range: [122; 124), + delete: [122; 124), + insert: "return", + kind: Keyword, + }, + CompletionItem { + label: "while", + source_range: [122; 124), + delete: [122; 124), + insert: "while $0 {}", + kind: Keyword, + }, + ] + "### ) } } diff --git a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs b/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs index 09f743c660..faadd1e3f4 100644 --- a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs +++ b/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs @@ -37,16 +37,18 @@ mod tests { <|> " ), - @r##"[ - CompletionItem { - label: "foo!", - source_range: [46; 46), - delete: [46; 46), - insert: "foo!($0)", - kind: Macro, - detail: "macro_rules! foo", - }, -]"## + @r###" + [ + CompletionItem { + label: "foo!", + source_range: [46; 46), + delete: [46; 46), + insert: "foo!($0)", + kind: Macro, + detail: "macro_rules! foo", + }, + ] + "### ); } @@ -75,19 +77,21 @@ mod tests { <|> " ), - @r##"[ - CompletionItem { - label: "vec!", - source_range: [280; 280), - delete: [280; 280), - insert: "vec![$0]", - kind: Macro, - detail: "macro_rules! vec", - documentation: Documentation( - "Creates a [`Vec`] containing the arguments.\n\n- Create a [`Vec`] containing a given list of elements:\n\n```\nlet v = vec![1, 2, 3];\nassert_eq!(v[0], 1);\nassert_eq!(v[1], 2);\nassert_eq!(v[2], 3);\n```", - ), - }, -]"## + @r###" + [ + CompletionItem { + label: "vec!", + source_range: [280; 280), + delete: [280; 280), + insert: "vec![$0]", + kind: Macro, + detail: "macro_rules! vec", + documentation: Documentation( + "Creates a [`Vec`] containing the arguments.\n\n- Create a [`Vec`] containing a given list of elements:\n\n```\nlet v = vec![1, 2, 3];\nassert_eq!(v[0], 1);\nassert_eq!(v[1], 2);\nassert_eq!(v[2], 3);\n```", + ), + }, + ] + "### ); } @@ -110,28 +114,29 @@ mod tests { } " ), - @r###"[ - CompletionItem { - label: "foo!", - source_range: [163; 163), - delete: [163; 163), - insert: "foo! {$0}", - kind: Macro, - detail: "macro_rules! foo", - documentation: Documentation( - "Foo\n\nNot call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`.\nCall as `let _=foo! { hello world };`", - ), - }, - CompletionItem { - label: "main()", - source_range: [163; 163), - delete: [163; 163), - insert: "main()$0", - kind: Function, - lookup: "main", - detail: "fn main()", - }, -] + @r###" + [ + CompletionItem { + label: "foo!", + source_range: [163; 163), + delete: [163; 163), + insert: "foo! {$0}", + kind: Macro, + detail: "macro_rules! foo", + documentation: Documentation( + "Foo\n\nNot call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`.\nCall as `let _=foo! { hello world };`", + ), + }, + CompletionItem { + label: "main()", + source_range: [163; 163), + delete: [163; 163), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] "### ); } diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 09ca401794..5d974cf6d5 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -152,18 +152,20 @@ mod tests { } " ), - @r###"[ - CompletionItem { - label: "my", - source_range: [27; 29), - delete: [27; 29), - insert: "my", - kind: Module, - documentation: Documentation( - "Some simple\ndocs describing `mod my`.", - ), - }, -]"### + @r###" + [ + CompletionItem { + label: "my", + source_range: [27; 29), + delete: [27; 29), + insert: "my", + kind: Module, + documentation: Documentation( + "Some simple\ndocs describing `mod my`.", + ), + }, + ] + "### ); } @@ -179,15 +181,17 @@ mod tests { } " ), - @r###"[ - CompletionItem { - label: "Bar", - source_range: [30; 30), - delete: [30; 30), - insert: "Bar", - kind: Struct, - }, -]"### + @r###" + [ + CompletionItem { + label: "Bar", + source_range: [30; 30), + delete: [30; 30), + insert: "Bar", + kind: Struct, + }, + ] + "### ); } @@ -203,22 +207,24 @@ mod tests { use crate::Sp<|> " ), - @r###"[ - CompletionItem { - label: "Spam", - source_range: [11; 13), - delete: [11; 13), - insert: "Spam", - kind: Struct, - }, - CompletionItem { - label: "foo", - source_range: [11; 13), - delete: [11; 13), - insert: "foo", - kind: Module, - }, -]"### + @r###" + [ + CompletionItem { + label: "Spam", + source_range: [11; 13), + delete: [11; 13), + insert: "Spam", + kind: Struct, + }, + CompletionItem { + label: "foo", + source_range: [11; 13), + delete: [11; 13), + insert: "foo", + kind: Module, + }, + ] + "### ); } @@ -234,22 +240,24 @@ mod tests { use crate::{Sp<|>}; " ), - @r###"[ - CompletionItem { - label: "Spam", - source_range: [12; 14), - delete: [12; 14), - insert: "Spam", - kind: Struct, - }, - CompletionItem { - label: "foo", - source_range: [12; 14), - delete: [12; 14), - insert: "foo", - kind: Module, - }, -]"### + @r###" + [ + CompletionItem { + label: "Spam", + source_range: [12; 14), + delete: [12; 14), + insert: "Spam", + kind: Struct, + }, + CompletionItem { + label: "foo", + source_range: [12; 14), + delete: [12; 14), + insert: "foo", + kind: Module, + }, + ] + "### ); } @@ -269,15 +277,17 @@ mod tests { use crate::{bar::{baz::Sp<|>}}; " ), - @r###"[ - CompletionItem { - label: "Spam", - source_range: [23; 25), - delete: [23; 25), - insert: "Spam", - kind: Struct, - }, -]"### + @r###" + [ + CompletionItem { + label: "Spam", + source_range: [23; 25), + delete: [23; 25), + insert: "Spam", + kind: Struct, + }, + ] + "### ); } @@ -297,30 +307,32 @@ mod tests { fn foo() { let _ = E::<|> } " ), - @r###"[ - CompletionItem { - label: "Bar", - source_range: [116; 116), - delete: [116; 116), - insert: "Bar", - kind: EnumVariant, - detail: "(i32)", - documentation: Documentation( - "Bar Variant with i32", - ), - }, - CompletionItem { - label: "Foo", - source_range: [116; 116), - delete: [116; 116), - insert: "Foo", - kind: EnumVariant, - detail: "()", - documentation: Documentation( - "Foo Variant", - ), - }, -]"### + @r###" + [ + CompletionItem { + label: "Bar", + source_range: [116; 116), + delete: [116; 116), + insert: "Bar", + kind: EnumVariant, + detail: "(i32)", + documentation: Documentation( + "Bar Variant with i32", + ), + }, + CompletionItem { + label: "Foo", + source_range: [116; 116), + delete: [116; 116), + insert: "Foo", + kind: EnumVariant, + detail: "()", + documentation: Documentation( + "Foo Variant", + ), + }, + ] + "### ); } @@ -343,41 +355,43 @@ mod tests { fn foo() { let _ = E::<|> } " ), - @r###"[ - CompletionItem { - label: "Bar", - source_range: [180; 180), - delete: [180; 180), - insert: "Bar", - kind: EnumVariant, - detail: "(i32, u32)", - documentation: Documentation( - "Bar Variant with i32 and u32", - ), - }, - CompletionItem { - label: "Foo", - source_range: [180; 180), - delete: [180; 180), - insert: "Foo", - kind: EnumVariant, - detail: "()", - documentation: Documentation( - "Foo Variant (empty)", - ), - }, - CompletionItem { - label: "S", - source_range: [180; 180), - delete: [180; 180), - insert: "S", - kind: EnumVariant, - detail: "(S)", - documentation: Documentation( - "", - ), - }, -]"### + @r###" + [ + CompletionItem { + label: "Bar", + source_range: [180; 180), + delete: [180; 180), + insert: "Bar", + kind: EnumVariant, + detail: "(i32, u32)", + documentation: Documentation( + "Bar Variant with i32 and u32", + ), + }, + CompletionItem { + label: "Foo", + source_range: [180; 180), + delete: [180; 180), + insert: "Foo", + kind: EnumVariant, + detail: "()", + documentation: Documentation( + "Foo Variant (empty)", + ), + }, + CompletionItem { + label: "S", + source_range: [180; 180), + delete: [180; 180), + insert: "S", + kind: EnumVariant, + detail: "(S)", + documentation: Documentation( + "", + ), + }, + ] + "### ); } @@ -434,19 +448,21 @@ mod tests { fn foo() { let _ = S::<|> } " ), - @r###"[ - CompletionItem { - label: "C", - source_range: [107; 107), - delete: [107; 107), - insert: "C", - kind: Const, - detail: "const C: i32 = 42;", - documentation: Documentation( - "An associated const", - ), - }, -]"### + @r###" + [ + CompletionItem { + label: "C", + source_range: [107; 107), + delete: [107; 107), + insert: "C", + kind: Const, + detail: "const C: i32 = 42;", + documentation: Documentation( + "An associated const", + ), + }, + ] + "### ); } @@ -467,19 +483,21 @@ mod tests { fn foo() { let _ = S::<|> } " ), - @r###"[ - CompletionItem { - label: "T", - source_range: [101; 101), - delete: [101; 101), - insert: "T", - kind: TypeAlias, - detail: "type T = i32;", - documentation: Documentation( - "An associated type", - ), - }, -]"### + @r###" + [ + CompletionItem { + label: "T", + source_range: [101; 101), + delete: [101; 101), + insert: "T", + kind: TypeAlias, + detail: "type T = i32;", + documentation: Documentation( + "An associated type", + ), + }, + ] + "### ); } @@ -569,15 +587,17 @@ mod tests { } " ), - @r###"[ - CompletionItem { - label: "bar", - source_range: [9; 9), - delete: [9; 9), - insert: "bar", - kind: Module, - }, -]"### + @r###" + [ + CompletionItem { + label: "bar", + source_range: [9; 9), + delete: [9; 9), + insert: "bar", + kind: Module, + }, + ] + "### ); } diff --git a/crates/ra_ide_api/src/completion/complete_pattern.rs b/crates/ra_ide_api/src/completion/complete_pattern.rs index 513ad6e5f0..fd03b1c405 100644 --- a/crates/ra_ide_api/src/completion/complete_pattern.rs +++ b/crates/ra_ide_api/src/completion/complete_pattern.rs @@ -54,36 +54,36 @@ mod tests { ", ); assert_debug_snapshot!(completions, @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "E", - ⋮ source_range: [246; 246), - ⋮ delete: [246; 246), - ⋮ insert: "E", - ⋮ kind: Enum, - ⋮ }, - ⋮ CompletionItem { - ⋮ label: "X", - ⋮ source_range: [246; 246), - ⋮ delete: [246; 246), - ⋮ insert: "X", - ⋮ kind: EnumVariant, - ⋮ }, - ⋮ CompletionItem { - ⋮ label: "Z", - ⋮ source_range: [246; 246), - ⋮ delete: [246; 246), - ⋮ insert: "Z", - ⋮ kind: Const, - ⋮ }, - ⋮ CompletionItem { - ⋮ label: "m", - ⋮ source_range: [246; 246), - ⋮ delete: [246; 246), - ⋮ insert: "m", - ⋮ kind: Module, - ⋮ }, - ⋮] + [ + CompletionItem { + label: "E", + source_range: [246; 246), + delete: [246; 246), + insert: "E", + kind: Enum, + }, + CompletionItem { + label: "X", + source_range: [246; 246), + delete: [246; 246), + insert: "X", + kind: EnumVariant, + }, + CompletionItem { + label: "Z", + source_range: [246; 246), + delete: [246; 246), + insert: "Z", + kind: Const, + }, + CompletionItem { + label: "m", + source_range: [246; 246), + delete: [246; 246), + insert: "m", + kind: Module, + }, + ] "###); } } diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs index 99fed8689d..17b75cf7eb 100644 --- a/crates/ra_ide_api/src/completion/complete_postfix.rs +++ b/crates/ra_ide_api/src/completion/complete_postfix.rs @@ -104,64 +104,66 @@ mod tests { } "#, ), - @r###"[ - CompletionItem { - label: "box", - source_range: [89; 89), - delete: [85; 89), - insert: "Box::new(bar)", - detail: "Box::new(expr)", - }, - CompletionItem { - label: "dbg", - source_range: [89; 89), - delete: [85; 89), - insert: "dbg!(bar)", - detail: "dbg!(expr)", - }, - CompletionItem { - label: "if", - source_range: [89; 89), - delete: [85; 89), - insert: "if bar {$0}", - detail: "if expr {}", - }, - CompletionItem { - label: "match", - source_range: [89; 89), - delete: [85; 89), - insert: "match bar {\n ${1:_} => {$0\\},\n}", - detail: "match expr {}", - }, - CompletionItem { - label: "not", - source_range: [89; 89), - delete: [85; 89), - insert: "!bar", - detail: "!expr", - }, - CompletionItem { - label: "ref", - source_range: [89; 89), - delete: [85; 89), - insert: "&bar", - detail: "&expr", - }, - CompletionItem { - label: "refm", - source_range: [89; 89), - delete: [85; 89), - insert: "&mut bar", - detail: "&mut expr", - }, - CompletionItem { - label: "while", - source_range: [89; 89), - delete: [85; 89), - insert: "while bar {\n$0\n}", - detail: "while expr {}", - }, -]"### + @r###" + [ + CompletionItem { + label: "box", + source_range: [89; 89), + delete: [85; 89), + insert: "Box::new(bar)", + detail: "Box::new(expr)", + }, + CompletionItem { + label: "dbg", + source_range: [89; 89), + delete: [85; 89), + insert: "dbg!(bar)", + detail: "dbg!(expr)", + }, + CompletionItem { + label: "if", + source_range: [89; 89), + delete: [85; 89), + insert: "if bar {$0}", + detail: "if expr {}", + }, + CompletionItem { + label: "match", + source_range: [89; 89), + delete: [85; 89), + insert: "match bar {\n ${1:_} => {$0\\},\n}", + detail: "match expr {}", + }, + CompletionItem { + label: "not", + source_range: [89; 89), + delete: [85; 89), + insert: "!bar", + detail: "!expr", + }, + CompletionItem { + label: "ref", + source_range: [89; 89), + delete: [85; 89), + insert: "&bar", + detail: "&expr", + }, + CompletionItem { + label: "refm", + source_range: [89; 89), + delete: [85; 89), + insert: "&mut bar", + detail: "&mut expr", + }, + CompletionItem { + label: "while", + source_range: [89; 89), + delete: [85; 89), + insert: "while bar {\n$0\n}", + detail: "while expr {}", + }, + ] + "### ); } @@ -176,50 +178,52 @@ mod tests { } "#, ), - @r###"[ - CompletionItem { - label: "box", - source_range: [91; 91), - delete: [87; 91), - insert: "Box::new(bar)", - detail: "Box::new(expr)", - }, - CompletionItem { - label: "dbg", - source_range: [91; 91), - delete: [87; 91), - insert: "dbg!(bar)", - detail: "dbg!(expr)", - }, - CompletionItem { - label: "match", - source_range: [91; 91), - delete: [87; 91), - insert: "match bar {\n ${1:_} => {$0\\},\n}", - detail: "match expr {}", - }, - CompletionItem { - label: "not", - source_range: [91; 91), - delete: [87; 91), - insert: "!bar", - detail: "!expr", - }, - CompletionItem { - label: "ref", - source_range: [91; 91), - delete: [87; 91), - insert: "&bar", - detail: "&expr", - }, - CompletionItem { - label: "refm", - source_range: [91; 91), - delete: [87; 91), - insert: "&mut bar", - detail: "&mut expr", - }, -]"### + @r###" + [ + CompletionItem { + label: "box", + source_range: [91; 91), + delete: [87; 91), + insert: "Box::new(bar)", + detail: "Box::new(expr)", + }, + CompletionItem { + label: "dbg", + source_range: [91; 91), + delete: [87; 91), + insert: "dbg!(bar)", + detail: "dbg!(expr)", + }, + CompletionItem { + label: "match", + source_range: [91; 91), + delete: [87; 91), + insert: "match bar {\n ${1:_} => {$0\\},\n}", + detail: "match expr {}", + }, + CompletionItem { + label: "not", + source_range: [91; 91), + delete: [87; 91), + insert: "!bar", + detail: "!expr", + }, + CompletionItem { + label: "ref", + source_range: [91; 91), + delete: [87; 91), + insert: "&bar", + detail: "&expr", + }, + CompletionItem { + label: "refm", + source_range: [91; 91), + delete: [87; 91), + insert: "&mut bar", + detail: "&mut expr", + }, + ] + "### ); } @@ -233,50 +237,52 @@ mod tests { } "#, ), - @r###"[ - CompletionItem { - label: "box", - source_range: [52; 52), - delete: [49; 52), - insert: "Box::new(42)", - detail: "Box::new(expr)", - }, - CompletionItem { - label: "dbg", - source_range: [52; 52), - delete: [49; 52), - insert: "dbg!(42)", - detail: "dbg!(expr)", - }, - CompletionItem { - label: "match", - source_range: [52; 52), - delete: [49; 52), - insert: "match 42 {\n ${1:_} => {$0\\},\n}", - detail: "match expr {}", - }, - CompletionItem { - label: "not", - source_range: [52; 52), - delete: [49; 52), - insert: "!42", - detail: "!expr", - }, - CompletionItem { - label: "ref", - source_range: [52; 52), - delete: [49; 52), - insert: "&42", - detail: "&expr", - }, - CompletionItem { - label: "refm", - source_range: [52; 52), - delete: [49; 52), - insert: "&mut 42", - detail: "&mut expr", - }, -]"### + @r###" + [ + CompletionItem { + label: "box", + source_range: [52; 52), + delete: [49; 52), + insert: "Box::new(42)", + detail: "Box::new(expr)", + }, + CompletionItem { + label: "dbg", + source_range: [52; 52), + delete: [49; 52), + insert: "dbg!(42)", + detail: "dbg!(expr)", + }, + CompletionItem { + label: "match", + source_range: [52; 52), + delete: [49; 52), + insert: "match 42 {\n ${1:_} => {$0\\},\n}", + detail: "match expr {}", + }, + CompletionItem { + label: "not", + source_range: [52; 52), + delete: [49; 52), + insert: "!42", + detail: "!expr", + }, + CompletionItem { + label: "ref", + source_range: [52; 52), + delete: [49; 52), + insert: "&42", + detail: "&expr", + }, + CompletionItem { + label: "refm", + source_range: [52; 52), + delete: [49; 52), + insert: "&mut 42", + detail: "&mut expr", + }, + ] + "### ); } } diff --git a/crates/ra_ide_api/src/completion/complete_record_literal.rs b/crates/ra_ide_api/src/completion/complete_record_literal.rs index 0295b81013..45a4a97382 100644 --- a/crates/ra_ide_api/src/completion/complete_record_literal.rs +++ b/crates/ra_ide_api/src/completion/complete_record_literal.rs @@ -45,17 +45,17 @@ mod tests { ", ); assert_debug_snapshot!(completions, @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "the_field", - ⋮ source_range: [142; 145), - ⋮ delete: [142; 145), - ⋮ insert: "the_field", - ⋮ kind: Field, - ⋮ detail: "u32", - ⋮ deprecated: true, - ⋮ }, - ⋮] + [ + CompletionItem { + label: "the_field", + source_range: [142; 145), + delete: [142; 145), + insert: "the_field", + kind: Field, + detail: "u32", + deprecated: true, + }, + ] "###); } @@ -70,16 +70,16 @@ mod tests { ", ); assert_debug_snapshot!(completions, @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "the_field", - ⋮ source_range: [83; 86), - ⋮ delete: [83; 86), - ⋮ insert: "the_field", - ⋮ kind: Field, - ⋮ detail: "u32", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "the_field", + source_range: [83; 86), + delete: [83; 86), + insert: "the_field", + kind: Field, + detail: "u32", + }, + ] "###); } @@ -96,16 +96,16 @@ mod tests { ", ); assert_debug_snapshot!(completions, @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "a", - ⋮ source_range: [119; 119), - ⋮ delete: [119; 119), - ⋮ insert: "a", - ⋮ kind: Field, - ⋮ detail: "u32", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "a", + source_range: [119; 119), + delete: [119; 119), + insert: "a", + kind: Field, + detail: "u32", + }, + ] "###); } @@ -122,16 +122,16 @@ mod tests { ", ); assert_debug_snapshot!(completions, @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "b", - ⋮ source_range: [119; 119), - ⋮ delete: [119; 119), - ⋮ insert: "b", - ⋮ kind: Field, - ⋮ detail: "u32", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "b", + source_range: [119; 119), + delete: [119; 119), + insert: "b", + kind: Field, + detail: "u32", + }, + ] "###); } @@ -147,16 +147,16 @@ mod tests { ", ); assert_debug_snapshot!(completions, @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "a", - ⋮ source_range: [93; 93), - ⋮ delete: [93; 93), - ⋮ insert: "a", - ⋮ kind: Field, - ⋮ detail: "u32", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "a", + source_range: [93; 93), + delete: [93; 93), + insert: "a", + kind: Field, + detail: "u32", + }, + ] "###); } } diff --git a/crates/ra_ide_api/src/completion/complete_record_pattern.rs b/crates/ra_ide_api/src/completion/complete_record_pattern.rs index d20fa796c7..aa0fd6d24f 100644 --- a/crates/ra_ide_api/src/completion/complete_record_pattern.rs +++ b/crates/ra_ide_api/src/completion/complete_record_pattern.rs @@ -44,16 +44,16 @@ mod tests { ", ); assert_debug_snapshot!(completions, @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "foo", - ⋮ source_range: [117; 118), - ⋮ delete: [117; 118), - ⋮ insert: "foo", - ⋮ kind: Field, - ⋮ detail: "u32", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "foo", + source_range: [117; 118), + delete: [117; 118), + insert: "foo", + kind: Field, + detail: "u32", + }, + ] "###); } @@ -73,24 +73,24 @@ mod tests { ", ); assert_debug_snapshot!(completions, @r###" - ⋮[ - ⋮ CompletionItem { - ⋮ label: "bar", - ⋮ source_range: [161; 161), - ⋮ delete: [161; 161), - ⋮ insert: "bar", - ⋮ kind: Field, - ⋮ detail: "()", - ⋮ }, - ⋮ CompletionItem { - ⋮ label: "foo", - ⋮ source_range: [161; 161), - ⋮ delete: [161; 161), - ⋮ insert: "foo", - ⋮ kind: Field, - ⋮ detail: "u32", - ⋮ }, - ⋮] + [ + CompletionItem { + label: "bar", + source_range: [161; 161), + delete: [161; 161), + insert: "bar", + kind: Field, + detail: "()", + }, + CompletionItem { + label: "foo", + source_range: [161; 161), + delete: [161; 161), + insert: "foo", + kind: Field, + detail: "u32", + }, + ] "###); } } diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 3e205efd12..8c57c907d9 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs @@ -409,15 +409,17 @@ mod tests { // nothing here " ), - @r#"[ - CompletionItem { - label: "other_crate", - source_range: [4; 4), - delete: [4; 4), - insert: "other_crate", - kind: Module, - }, -]"# + @r###" + [ + CompletionItem { + label: "other_crate", + source_range: [4; 4), + delete: [4; 4), + insert: "other_crate", + kind: Module, + }, + ] + "### ); } @@ -530,23 +532,25 @@ mod tests { fn completes_self_in_methods() { assert_debug_snapshot!( do_reference_completion(r"impl S { fn foo(&self) { <|> } }"), - @r#"[ - CompletionItem { - label: "Self", - source_range: [25; 25), - delete: [25; 25), - insert: "Self", - kind: TypeParam, - }, - CompletionItem { - label: "self", - source_range: [25; 25), - delete: [25; 25), - insert: "self", - kind: Binding, - detail: "&{unknown}", - }, -]"# + @r###" + [ + CompletionItem { + label: "Self", + source_range: [25; 25), + delete: [25; 25), + insert: "Self", + kind: TypeParam, + }, + CompletionItem { + label: "self", + source_range: [25; 25), + delete: [25; 25), + insert: "self", + kind: Binding, + detail: "&{unknown}", + }, + ] + "### ); } diff --git a/crates/ra_ide_api/src/completion/complete_snippet.rs b/crates/ra_ide_api/src/completion/complete_snippet.rs index 2df79b6c3f..1f2988b36b 100644 --- a/crates/ra_ide_api/src/completion/complete_snippet.rs +++ b/crates/ra_ide_api/src/completion/complete_snippet.rs @@ -52,22 +52,24 @@ mod tests { fn completes_snippets_in_expressions() { assert_debug_snapshot!( do_snippet_completion(r"fn foo(x: i32) { <|> }"), - @r#"[ - CompletionItem { - label: "pd", - source_range: [17; 17), - delete: [17; 17), - insert: "eprintln!(\"$0 = {:?}\", $0);", - kind: Snippet, - }, - CompletionItem { - label: "ppd", - source_range: [17; 17), - delete: [17; 17), - insert: "eprintln!(\"$0 = {:#?}\", $0);", - kind: Snippet, - }, -]"# + @r###" + [ + CompletionItem { + label: "pd", + source_range: [17; 17), + delete: [17; 17), + insert: "eprintln!(\"$0 = {:?}\", $0);", + kind: Snippet, + }, + CompletionItem { + label: "ppd", + source_range: [17; 17), + delete: [17; 17), + insert: "eprintln!(\"$0 = {:#?}\", $0);", + kind: Snippet, + }, + ] + "### ); } @@ -75,11 +77,11 @@ mod tests { fn should_not_complete_snippets_in_path() { assert_debug_snapshot!( do_snippet_completion(r"fn foo(x: i32) { ::foo<|> }"), - @r#"[]"# + @"[]" ); assert_debug_snapshot!( do_snippet_completion(r"fn foo(x: i32) { ::<|> }"), - @r#"[]"# + @"[]" ); } @@ -94,23 +96,25 @@ mod tests { } " ), - @r###"[ - CompletionItem { - label: "Test function", - source_range: [78; 78), - delete: [78; 78), - insert: "#[test]\nfn ${1:feature}() {\n $0\n}", - kind: Snippet, - lookup: "tfn", - }, - CompletionItem { - label: "pub(crate)", - source_range: [78; 78), - delete: [78; 78), - insert: "pub(crate) $0", - kind: Snippet, - }, -]"### + @r###" + [ + CompletionItem { + label: "Test function", + source_range: [78; 78), + delete: [78; 78), + insert: "#[test]\nfn ${1:feature}() {\n $0\n}", + kind: Snippet, + lookup: "tfn", + }, + CompletionItem { + label: "pub(crate)", + source_range: [78; 78), + delete: [78; 78), + insert: "pub(crate) $0", + kind: Snippet, + }, + ] + "### ); } } diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index c343cece64..501b7da4e7 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs @@ -323,38 +323,38 @@ mod tests { "#, ), @r###" - [ - CompletionItem { - label: "main()", - source_range: [203; 206), - delete: [203; 206), - insert: "main()$0", - kind: Function, - lookup: "main", - detail: "fn main()", - }, - CompletionItem { - label: "something_deprecated()", - source_range: [203; 206), - delete: [203; 206), - insert: "something_deprecated()$0", - kind: Function, - lookup: "something_deprecated", - detail: "fn something_deprecated()", - deprecated: true, - }, - CompletionItem { - label: "something_else_deprecated()", - source_range: [203; 206), - delete: [203; 206), - insert: "something_else_deprecated()$0", - kind: Function, - lookup: "something_else_deprecated", - detail: "fn something_else_deprecated()", - deprecated: true, - }, - ] - "### + [ + CompletionItem { + label: "main()", + source_range: [203; 206), + delete: [203; 206), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + CompletionItem { + label: "something_deprecated()", + source_range: [203; 206), + delete: [203; 206), + insert: "something_deprecated()$0", + kind: Function, + lookup: "something_deprecated", + detail: "fn something_deprecated()", + deprecated: true, + }, + CompletionItem { + label: "something_else_deprecated()", + source_range: [203; 206), + delete: [203; 206), + insert: "something_else_deprecated()$0", + kind: Function, + lookup: "something_else_deprecated", + detail: "fn something_else_deprecated()", + deprecated: true, + }, + ] + "### ); } @@ -459,16 +459,18 @@ mod tests { use crate::m::f<|>; " ), - @r#"[ - CompletionItem { - label: "foo", - source_range: [40; 41), - delete: [40; 41), - insert: "foo", - kind: Function, - detail: "pub fn foo()", - }, -]"# + @r###" + [ + CompletionItem { + label: "foo", + source_range: [40; 41), + delete: [40; 41), + insert: "foo", + kind: Function, + detail: "pub fn foo()", + }, + ] + "### ); } @@ -484,24 +486,26 @@ mod tests { } " ), - @r#"[ - CompletionItem { - label: "frobnicate", - source_range: [35; 39), - delete: [35; 39), - insert: "frobnicate", - kind: Function, - detail: "fn frobnicate()", - }, - CompletionItem { - label: "main", - source_range: [35; 39), - delete: [35; 39), - insert: "main", - kind: Function, - detail: "fn main()", - }, -]"# + @r###" + [ + CompletionItem { + label: "frobnicate", + source_range: [35; 39), + delete: [35; 39), + insert: "frobnicate", + kind: Function, + detail: "fn frobnicate()", + }, + CompletionItem { + label: "main", + source_range: [35; 39), + delete: [35; 39), + insert: "main", + kind: Function, + detail: "fn main()", + }, + ] + "### ); assert_debug_snapshot!( do_reference_completion( @@ -514,16 +518,18 @@ mod tests { } " ), - @r#"[ - CompletionItem { - label: "new", - source_range: [67; 69), - delete: [67; 69), - insert: "new", - kind: Function, - detail: "fn new() -> Foo", - }, -]"# + @r###" + [ + CompletionItem { + label: "new", + source_range: [67; 69), + delete: [67; 69), + insert: "new", + kind: Function, + detail: "fn new() -> Foo", + }, + ] + "### ); } diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs index 2890a3d2b5..e52ffefb36 100644 --- a/crates/ra_ide_api/src/diagnostics.rs +++ b/crates/ra_ide_api/src/diagnostics.rs @@ -526,28 +526,28 @@ mod tests { let (analysis, file_id) = single_file("mod foo;"); let diagnostics = analysis.diagnostics(file_id).unwrap(); assert_debug_snapshot!(diagnostics, @r###" - ⋮[ - ⋮ Diagnostic { - ⋮ message: "unresolved module", - ⋮ range: [0; 8), - ⋮ fix: Some( - ⋮ SourceChange { - ⋮ label: "create module", - ⋮ source_file_edits: [], - ⋮ file_system_edits: [ - ⋮ CreateFile { - ⋮ source_root: SourceRootId( - ⋮ 0, - ⋮ ), - ⋮ path: "foo.rs", - ⋮ }, - ⋮ ], - ⋮ cursor_position: None, - ⋮ }, - ⋮ ), - ⋮ severity: Error, - ⋮ }, - ⋮] + [ + Diagnostic { + message: "unresolved module", + range: [0; 8), + fix: Some( + SourceChange { + label: "create module", + source_file_edits: [], + file_system_edits: [ + CreateFile { + source_root: SourceRootId( + 0, + ), + path: "foo.rs", + }, + ], + cursor_position: None, + }, + ), + severity: Error, + }, + ] "###); } diff --git a/crates/ra_ide_api/src/display/structure.rs b/crates/ra_ide_api/src/display/structure.rs index ddd8b7b203..a80d65ac71 100644 --- a/crates/ra_ide_api/src/display/structure.rs +++ b/crates/ra_ide_api/src/display/structure.rs @@ -209,191 +209,193 @@ fn very_obsolete() {} .unwrap(); let structure = file_structure(&file); assert_debug_snapshot!(structure, - @r#"[ - StructureNode { - parent: None, - label: "Foo", - navigation_range: [8; 11), - node_range: [1; 26), - kind: STRUCT_DEF, - detail: None, - deprecated: false, - }, - StructureNode { - parent: Some( - 0, - ), - label: "x", - navigation_range: [18; 19), - node_range: [18; 24), - kind: RECORD_FIELD_DEF, - detail: Some( - "i32", - ), - deprecated: false, - }, - StructureNode { - parent: None, - label: "m", - navigation_range: [32; 33), - node_range: [28; 158), - kind: MODULE, - detail: None, - deprecated: false, - }, - StructureNode { - parent: Some( - 2, - ), - label: "bar1", - navigation_range: [43; 47), - node_range: [40; 52), - kind: FN_DEF, - detail: Some( - "fn()", - ), - deprecated: false, - }, - StructureNode { - parent: Some( - 2, - ), - label: "bar2", - navigation_range: [60; 64), - node_range: [57; 81), - kind: FN_DEF, - detail: Some( - "fn(t: T) -> T", - ), - deprecated: false, - }, - StructureNode { - parent: Some( - 2, - ), - label: "bar3", - navigation_range: [89; 93), - node_range: [86; 156), - kind: FN_DEF, - detail: Some( - "fn(a: A, b: B) -> Vec< u32 >", - ), - deprecated: false, - }, - StructureNode { - parent: None, - label: "E", - navigation_range: [165; 166), - node_range: [160; 180), - kind: ENUM_DEF, - detail: None, - deprecated: false, - }, - StructureNode { - parent: Some( - 6, - ), - label: "X", - navigation_range: [169; 170), - node_range: [169; 170), - kind: ENUM_VARIANT, - detail: None, - deprecated: false, - }, - StructureNode { - parent: Some( - 6, - ), - label: "Y", - navigation_range: [172; 173), - node_range: [172; 178), - kind: ENUM_VARIANT, - detail: None, - deprecated: false, - }, - StructureNode { - parent: None, - label: "T", - navigation_range: [186; 187), - node_range: [181; 193), - kind: TYPE_ALIAS_DEF, - detail: Some( - "()", - ), - deprecated: false, - }, - StructureNode { - parent: None, - label: "S", - navigation_range: [201; 202), - node_range: [194; 213), - kind: STATIC_DEF, - detail: Some( - "i32", - ), - deprecated: false, - }, - StructureNode { - parent: None, - label: "C", - navigation_range: [220; 221), - node_range: [214; 232), - kind: CONST_DEF, - detail: Some( - "i32", - ), - deprecated: false, - }, - StructureNode { - parent: None, - label: "impl E", - navigation_range: [239; 240), - node_range: [234; 243), - kind: IMPL_BLOCK, - detail: None, - deprecated: false, - }, - StructureNode { - parent: None, - label: "impl fmt::Debug for E", - navigation_range: [265; 266), - node_range: [245; 269), - kind: IMPL_BLOCK, - detail: None, - deprecated: false, - }, - StructureNode { - parent: None, - label: "mc", - navigation_range: [284; 286), - node_range: [271; 303), - kind: MACRO_CALL, - detail: None, - deprecated: false, - }, - StructureNode { - parent: None, - label: "obsolete", - navigation_range: [322; 330), - node_range: [305; 335), - kind: FN_DEF, - detail: Some( - "fn()", - ), - deprecated: true, - }, - StructureNode { - parent: None, - label: "very_obsolete", - navigation_range: [375; 388), - node_range: [337; 393), - kind: FN_DEF, - detail: Some( - "fn()", - ), - deprecated: true, - }, -]"# + @r###" + [ + StructureNode { + parent: None, + label: "Foo", + navigation_range: [8; 11), + node_range: [1; 26), + kind: STRUCT_DEF, + detail: None, + deprecated: false, + }, + StructureNode { + parent: Some( + 0, + ), + label: "x", + navigation_range: [18; 19), + node_range: [18; 24), + kind: RECORD_FIELD_DEF, + detail: Some( + "i32", + ), + deprecated: false, + }, + StructureNode { + parent: None, + label: "m", + navigation_range: [32; 33), + node_range: [28; 158), + kind: MODULE, + detail: None, + deprecated: false, + }, + StructureNode { + parent: Some( + 2, + ), + label: "bar1", + navigation_range: [43; 47), + node_range: [40; 52), + kind: FN_DEF, + detail: Some( + "fn()", + ), + deprecated: false, + }, + StructureNode { + parent: Some( + 2, + ), + label: "bar2", + navigation_range: [60; 64), + node_range: [57; 81), + kind: FN_DEF, + detail: Some( + "fn(t: T) -> T", + ), + deprecated: false, + }, + StructureNode { + parent: Some( + 2, + ), + label: "bar3", + navigation_range: [89; 93), + node_range: [86; 156), + kind: FN_DEF, + detail: Some( + "fn(a: A, b: B) -> Vec< u32 >", + ), + deprecated: false, + }, + StructureNode { + parent: None, + label: "E", + navigation_range: [165; 166), + node_range: [160; 180), + kind: ENUM_DEF, + detail: None, + deprecated: false, + }, + StructureNode { + parent: Some( + 6, + ), + label: "X", + navigation_range: [169; 170), + node_range: [169; 170), + kind: ENUM_VARIANT, + detail: None, + deprecated: false, + }, + StructureNode { + parent: Some( + 6, + ), + label: "Y", + navigation_range: [172; 173), + node_range: [172; 178), + kind: ENUM_VARIANT, + detail: None, + deprecated: false, + }, + StructureNode { + parent: None, + label: "T", + navigation_range: [186; 187), + node_range: [181; 193), + kind: TYPE_ALIAS_DEF, + detail: Some( + "()", + ), + deprecated: false, + }, + StructureNode { + parent: None, + label: "S", + navigation_range: [201; 202), + node_range: [194; 213), + kind: STATIC_DEF, + detail: Some( + "i32", + ), + deprecated: false, + }, + StructureNode { + parent: None, + label: "C", + navigation_range: [220; 221), + node_range: [214; 232), + kind: CONST_DEF, + detail: Some( + "i32", + ), + deprecated: false, + }, + StructureNode { + parent: None, + label: "impl E", + navigation_range: [239; 240), + node_range: [234; 243), + kind: IMPL_BLOCK, + detail: None, + deprecated: false, + }, + StructureNode { + parent: None, + label: "impl fmt::Debug for E", + navigation_range: [265; 266), + node_range: [245; 269), + kind: IMPL_BLOCK, + detail: None, + deprecated: false, + }, + StructureNode { + parent: None, + label: "mc", + navigation_range: [284; 286), + node_range: [271; 303), + kind: MACRO_CALL, + detail: None, + deprecated: false, + }, + StructureNode { + parent: None, + label: "obsolete", + navigation_range: [322; 330), + node_range: [305; 335), + kind: FN_DEF, + detail: Some( + "fn()", + ), + deprecated: true, + }, + StructureNode { + parent: None, + label: "very_obsolete", + navigation_range: [375; 388), + node_range: [337; 393), + kind: FN_DEF, + detail: Some( + "fn()", + ), + deprecated: true, + }, + ] + "### ); } } diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs index f1c0dc1642..2ff10b89a8 100644 --- a/crates/ra_ide_api/src/inlay_hints.rs +++ b/crates/ra_ide_api/src/inlay_hints.rs @@ -214,58 +214,60 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r#"[ - InlayHint { - range: [193; 197), - kind: TypeHint, - label: "i32", - }, - InlayHint { - range: [236; 244), - kind: TypeHint, - label: "i32", - }, - InlayHint { - range: [275; 279), - kind: TypeHint, - label: "&str", - }, - InlayHint { - range: [539; 543), - kind: TypeHint, - label: "(i32, char)", - }, - InlayHint { - range: [566; 567), - kind: TypeHint, - label: "i32", - }, - InlayHint { - range: [570; 571), - kind: TypeHint, - label: "i32", - }, - InlayHint { - range: [573; 574), - kind: TypeHint, - label: "i32", - }, - InlayHint { - range: [584; 585), - kind: TypeHint, - label: "i32", - }, - InlayHint { - range: [577; 578), - kind: TypeHint, - label: "f64", - }, - InlayHint { - range: [580; 581), - kind: TypeHint, - label: "f64", - }, -]"# + assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + [ + InlayHint { + range: [193; 197), + kind: TypeHint, + label: "i32", + }, + InlayHint { + range: [236; 244), + kind: TypeHint, + label: "i32", + }, + InlayHint { + range: [275; 279), + kind: TypeHint, + label: "&str", + }, + InlayHint { + range: [539; 543), + kind: TypeHint, + label: "(i32, char)", + }, + InlayHint { + range: [566; 567), + kind: TypeHint, + label: "i32", + }, + InlayHint { + range: [570; 571), + kind: TypeHint, + label: "i32", + }, + InlayHint { + range: [573; 574), + kind: TypeHint, + label: "i32", + }, + InlayHint { + range: [584; 585), + kind: TypeHint, + label: "i32", + }, + InlayHint { + range: [577; 578), + kind: TypeHint, + label: "f64", + }, + InlayHint { + range: [580; 581), + kind: TypeHint, + label: "f64", + }, + ] + "### ); } @@ -281,18 +283,20 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r#"[ - InlayHint { - range: [21; 30), - kind: TypeHint, - label: "i32", - }, - InlayHint { - range: [57; 66), - kind: TypeHint, - label: "i32", - }, -]"# + assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + [ + InlayHint { + range: [21; 30), + kind: TypeHint, + label: "i32", + }, + InlayHint { + range: [57; 66), + kind: TypeHint, + label: "i32", + }, + ] + "### ); } @@ -308,18 +312,20 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r#"[ - InlayHint { - range: [21; 30), - kind: TypeHint, - label: "i32", - }, - InlayHint { - range: [44; 53), - kind: TypeHint, - label: "i32", - }, -]"# + assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + [ + InlayHint { + range: [21; 30), + kind: TypeHint, + label: "i32", + }, + InlayHint { + range: [44; 53), + kind: TypeHint, + label: "i32", + }, + ] + "### ); } @@ -354,33 +360,35 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r#"[ - InlayHint { - range: [166; 170), - kind: TypeHint, - label: "CustomOption", - }, - InlayHint { - range: [334; 338), - kind: TypeHint, - label: "&Test", - }, - InlayHint { - range: [389; 390), - kind: TypeHint, - label: "&CustomOption", - }, - InlayHint { - range: [392; 393), - kind: TypeHint, - label: "&u8", - }, - InlayHint { - range: [531; 532), - kind: TypeHint, - label: "&u32", - }, -]"# + assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + [ + InlayHint { + range: [166; 170), + kind: TypeHint, + label: "CustomOption", + }, + InlayHint { + range: [334; 338), + kind: TypeHint, + label: "&Test", + }, + InlayHint { + range: [389; 390), + kind: TypeHint, + label: "&CustomOption", + }, + InlayHint { + range: [392; 393), + kind: TypeHint, + label: "&u8", + }, + InlayHint { + range: [531; 532), + kind: TypeHint, + label: "&u32", + }, + ] + "### ); } @@ -416,33 +424,33 @@ fn main() { ); assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" - ⋮[ - ⋮ InlayHint { - ⋮ range: [166; 170), - ⋮ kind: TypeHint, - ⋮ label: "CustomOption", - ⋮ }, - ⋮ InlayHint { - ⋮ range: [343; 347), - ⋮ kind: TypeHint, - ⋮ label: "&Test", - ⋮ }, - ⋮ InlayHint { - ⋮ range: [401; 402), - ⋮ kind: TypeHint, - ⋮ label: "&CustomOption", - ⋮ }, - ⋮ InlayHint { - ⋮ range: [404; 405), - ⋮ kind: TypeHint, - ⋮ label: "&u8", - ⋮ }, - ⋮ InlayHint { - ⋮ range: [549; 550), - ⋮ kind: TypeHint, - ⋮ label: "&u32", - ⋮ }, - ⋮] + [ + InlayHint { + range: [166; 170), + kind: TypeHint, + label: "CustomOption", + }, + InlayHint { + range: [343; 347), + kind: TypeHint, + label: "&Test", + }, + InlayHint { + range: [401; 402), + kind: TypeHint, + label: "&CustomOption", + }, + InlayHint { + range: [404; 405), + kind: TypeHint, + label: "&u8", + }, + InlayHint { + range: [549; 550), + kind: TypeHint, + label: "&u32", + }, + ] "### ); } @@ -478,28 +486,30 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r#"[ - InlayHint { - range: [311; 315), - kind: TypeHint, - label: "Test", - }, - InlayHint { - range: [358; 359), - kind: TypeHint, - label: "CustomOption", - }, - InlayHint { - range: [361; 362), - kind: TypeHint, - label: "u8", - }, - InlayHint { - range: [484; 485), - kind: TypeHint, - label: "u32", - }, -]"# + assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + [ + InlayHint { + range: [311; 315), + kind: TypeHint, + label: "Test", + }, + InlayHint { + range: [358; 359), + kind: TypeHint, + label: "CustomOption", + }, + InlayHint { + range: [361; 362), + kind: TypeHint, + label: "u8", + }, + InlayHint { + range: [484; 485), + kind: TypeHint, + label: "u32", + }, + ] + "### ); } } diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs index 1b5c8deea0..366ac80486 100644 --- a/crates/ra_ide_api/src/runnables.rs +++ b/crates/ra_ide_api/src/runnables.rs @@ -97,24 +97,26 @@ mod tests { ); let runnables = analysis.runnables(pos.file_id).unwrap(); assert_debug_snapshot!(&runnables, - @r#"[ - Runnable { - range: [1; 21), - kind: Bin, - }, - Runnable { - range: [22; 46), - kind: Test { - name: "test_foo", - }, - }, - Runnable { - range: [47; 81), - kind: Test { - name: "test_foo", - }, - }, -]"# + @r###" + [ + Runnable { + range: [1; 21), + kind: Bin, + }, + Runnable { + range: [22; 46), + kind: Test { + name: "test_foo", + }, + }, + Runnable { + range: [47; 81), + kind: Test { + name: "test_foo", + }, + }, + ] + "### ); } @@ -132,20 +134,22 @@ mod tests { ); let runnables = analysis.runnables(pos.file_id).unwrap(); assert_debug_snapshot!(&runnables, - @r#"[ - Runnable { - range: [1; 59), - kind: TestMod { - path: "test_mod", - }, - }, - Runnable { - range: [28; 57), - kind: Test { - name: "test_foo1", - }, - }, -]"# + @r###" + [ + Runnable { + range: [1; 59), + kind: TestMod { + path: "test_mod", + }, + }, + Runnable { + range: [28; 57), + kind: Test { + name: "test_foo1", + }, + }, + ] + "### ); } @@ -165,20 +169,22 @@ mod tests { ); let runnables = analysis.runnables(pos.file_id).unwrap(); assert_debug_snapshot!(&runnables, - @r#"[ - Runnable { - range: [23; 85), - kind: TestMod { - path: "foo::test_mod", - }, - }, - Runnable { - range: [46; 79), - kind: Test { - name: "test_foo1", - }, - }, -]"# + @r###" + [ + Runnable { + range: [23; 85), + kind: TestMod { + path: "foo::test_mod", + }, + }, + Runnable { + range: [46; 79), + kind: Test { + name: "test_foo1", + }, + }, + ] + "### ); } @@ -200,20 +206,22 @@ mod tests { ); let runnables = analysis.runnables(pos.file_id).unwrap(); assert_debug_snapshot!(&runnables, - @r#"[ - Runnable { - range: [41; 115), - kind: TestMod { - path: "foo::bar::test_mod", - }, - }, - Runnable { - range: [68; 105), - kind: Test { - name: "test_foo1", - }, - }, -]"# + @r###" + [ + Runnable { + range: [41; 115), + kind: TestMod { + path: "foo::bar::test_mod", + }, + }, + Runnable { + range: [68; 105), + kind: Test { + name: "test_foo1", + }, + }, + ] + "### ); } From 5766ceab0629acc4464dcc57d00d9cc5c12f1c6b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 13:16:16 +0300 Subject: [PATCH 11/16] Add convenience method for testing --- crates/ra_db/src/fixture.rs | 12 ++++++++++-- crates/ra_hir_def/src/nameres/collector.rs | 2 +- crates/ra_hir_def/src/nameres/tests/incremental.rs | 6 +++--- .../ra_hir_def/src/nameres/tests/mod_resolution.rs | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs index ee883b6154..ade187629b 100644 --- a/crates/ra_db/src/fixture.rs +++ b/crates/ra_db/src/fixture.rs @@ -8,8 +8,8 @@ use rustc_hash::FxHashMap; use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; use crate::{ - CrateGraph, Edition, FileId, FilePosition, RelativePathBuf, SourceDatabaseExt, SourceRoot, - SourceRootId, + CrateGraph, CrateId, Edition, FileId, FilePosition, RelativePathBuf, SourceDatabaseExt, + SourceRoot, SourceRootId, }; pub const WORKSPACE: SourceRootId = SourceRootId(0); @@ -33,6 +33,14 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static { let pos = with_files(&mut db, fixture); (db, pos.unwrap()) } + + fn test_crate(&self) -> CrateId { + let crate_graph = self.crate_graph(); + let mut it = crate_graph.iter(); + let res = it.next().unwrap(); + assert!(it.next().is_none()); + res + } } impl WithFixture for DB {} diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 37d0f30936..83eef821f7 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -798,7 +798,7 @@ mod tests { fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap { let (db, _file_id) = TestDB::with_single_file(&code); - let krate = db.crate_graph().iter().next().unwrap(); + let krate = db.test_crate(); let def_map = { let edition = db.crate_graph().edition(krate); diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs index 80dcec62f0..903a227719 100644 --- a/crates/ra_hir_def/src/nameres/tests/incremental.rs +++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs @@ -1,12 +1,12 @@ use std::sync::Arc; -use ra_db::{SourceDatabase, SourceDatabaseExt}; +use ra_db::SourceDatabaseExt; use super::*; fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) { let (mut db, pos) = TestDB::with_position(initial); - let krate = db.crate_graph().iter().next().unwrap(); + let krate = db.test_crate(); { let events = db.log_executed(|| { db.crate_def_map(krate); @@ -111,7 +111,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { m!(X); ", ); - let krate = db.crate_graph().iter().next().unwrap(); + let krate = db.test_crate(); { let events = db.log_executed(|| { let crate_def_map = db.crate_def_map(krate); diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs index dee364a142..eb7b85c07c 100644 --- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs @@ -656,7 +656,7 @@ fn unresolved_module_diagnostics() { //- /foo.rs ", ); - let krate = db.crate_graph().iter().next().unwrap(); + let krate = db.test_crate(); let crate_def_map = db.crate_def_map(krate); From 9167da66acff22b4fe68d7bbe60c25ab0b56ad72 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 14:15:04 +0300 Subject: [PATCH 12/16] Reduce visibility --- crates/ra_hir/src/source_binder.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 59046edcc4..c1ecf18b96 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -285,7 +285,7 @@ impl SourceAnalyzer { self.resolve_hir_path(db, &hir_path) } - pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option { + fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option { let mut shadowed = FxHashSet::default(); let name = name_ref.as_name(); let source_map = self.body_source_map.as_ref()?; @@ -309,9 +309,9 @@ impl SourceAnalyzer { self.resolver.process_all_names(db, f) } + // FIXME: we only use this in `inline_local_variable` assist, ideally, we + // should switch to general reference search infra there. pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { - // FIXME: at least, this should work with any DefWithBody, but ideally - // this should be hir-based altogether let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); let ptr = Either::A(AstPtr::new(&ast::Pat::from(pat.clone()))); fn_def From 2f6c0c314b749e25431f3fd6caaac5d3270751b6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 14:47:26 +0300 Subject: [PATCH 13/16] Move scope tests to hir_def --- crates/ra_hir/src/expr.rs | 189 ------------------ crates/ra_hir/src/source_binder.rs | 24 +-- crates/ra_hir_def/src/body/scope.rs | 219 +++++++++++++++++++++ crates/ra_hir_def/src/nameres.rs | 9 +- crates/ra_hir_def/src/nameres/collector.rs | 3 +- 5 files changed, 233 insertions(+), 211 deletions(-) diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 899e0fa04a..e4598eec07 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -42,192 +42,3 @@ pub(crate) fn resolver_for_scope( } r } - -#[cfg(test)] -mod tests { - use hir_expand::Source; - use ra_db::{fixture::WithFixture, SourceDatabase}; - use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; - use test_utils::{assert_eq_text, extract_offset}; - - use crate::{source_binder::SourceAnalyzer, test_db::TestDB}; - - fn do_check(code: &str, expected: &[&str]) { - let (off, code) = extract_offset(code); - let code = { - let mut buf = String::new(); - let off = u32::from(off) as usize; - buf.push_str(&code[..off]); - buf.push_str("marker"); - buf.push_str(&code[off..]); - buf - }; - - let (db, file_id) = TestDB::with_single_file(&code); - - let file = db.parse(file_id).ok().unwrap(); - let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); - let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); - - let scopes = analyzer.scopes(); - let expr_id = analyzer - .body_source_map() - .node_expr(Source { file_id: file_id.into(), ast: &marker.into() }) - .unwrap(); - let scope = scopes.scope_for(expr_id); - - let actual = scopes - .scope_chain(scope) - .flat_map(|scope| scopes.entries(scope)) - .map(|it| it.name().to_string()) - .collect::>() - .join("\n"); - let expected = expected.join("\n"); - assert_eq_text!(&expected, &actual); - } - - #[test] - fn test_lambda_scope() { - do_check( - r" - fn quux(foo: i32) { - let f = |bar, baz: i32| { - <|> - }; - }", - &["bar", "baz", "foo"], - ); - } - - #[test] - fn test_call_scope() { - do_check( - r" - fn quux() { - f(|x| <|> ); - }", - &["x"], - ); - } - - #[test] - fn test_method_call_scope() { - do_check( - r" - fn quux() { - z.f(|x| <|> ); - }", - &["x"], - ); - } - - #[test] - fn test_loop_scope() { - do_check( - r" - fn quux() { - loop { - let x = (); - <|> - }; - }", - &["x"], - ); - } - - #[test] - fn test_match() { - do_check( - r" - fn quux() { - match () { - Some(x) => { - <|> - } - }; - }", - &["x"], - ); - } - - #[test] - fn test_shadow_variable() { - do_check( - r" - fn foo(x: String) { - let x : &str = &x<|>; - }", - &["x"], - ); - } - - fn do_check_local_name(code: &str, expected_offset: u32) { - let (off, code) = extract_offset(code); - - let (db, file_id) = TestDB::with_single_file(&code); - let file = db.parse(file_id).ok().unwrap(); - let expected_name = find_node_at_offset::(file.syntax(), expected_offset.into()) - .expect("failed to find a name at the target offset"); - let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); - let analyzer = SourceAnalyzer::new(&db, file_id, name_ref.syntax(), None); - - let local_name_entry = analyzer.resolve_local_name(&name_ref).unwrap(); - let local_name = - local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); - assert_eq!(local_name.range(), expected_name.syntax().text_range()); - } - - #[test] - fn test_resolve_local_name() { - do_check_local_name( - r#" - fn foo(x: i32, y: u32) { - { - let z = x * 2; - } - { - let t = x<|> * 3; - } - }"#, - 21, - ); - } - - #[test] - fn test_resolve_local_name_declaration() { - do_check_local_name( - r#" - fn foo(x: String) { - let x : &str = &x<|>; - }"#, - 21, - ); - } - - #[test] - fn test_resolve_local_name_shadow() { - do_check_local_name( - r" - fn foo(x: String) { - let x : &str = &x; - x<|> - } - ", - 53, - ); - } - - #[test] - fn ref_patterns_contribute_bindings() { - do_check_local_name( - r" - fn foo() { - if let Some(&from) = bar() { - from<|>; - } - } - ", - 53, - ); - } -} diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index c1ecf18b96..662d3f8808 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -19,7 +19,6 @@ use ra_syntax::{ SyntaxKind::*, SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, }; -use rustc_hash::FxHashSet; use crate::{ db::HirDatabase, @@ -286,22 +285,14 @@ impl SourceAnalyzer { } fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option { - let mut shadowed = FxHashSet::default(); let name = name_ref.as_name(); let source_map = self.body_source_map.as_ref()?; let scopes = self.scopes.as_ref()?; - let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax()); - let ret = scopes - .scope_chain(scope) - .flat_map(|scope| scopes.entries(scope).iter()) - .filter(|entry| shadowed.insert(entry.name())) - .filter(|entry| entry.name() == &name) - .nth(0); - ret.and_then(|entry| { - Some(ScopeEntryWithSyntax { - name: entry.name().clone(), - ptr: source_map.pat_syntax(entry.pat())?.ast, - }) + let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax())?; + let entry = scopes.resolve_name_in_scope(scope, &name)?; + Some(ScopeEntryWithSyntax { + name: entry.name().clone(), + ptr: source_map.pat_syntax(entry.pat())?.ast, }) } @@ -413,11 +404,6 @@ impl SourceAnalyzer { pub(crate) fn inference_result(&self) -> Arc { self.infer.clone().unwrap() } - - #[cfg(test)] - pub(crate) fn scopes(&self) -> Arc { - self.scopes.clone().unwrap() - } } fn scope_for( diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 09a39e721e..10cb87d37b 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs @@ -67,6 +67,11 @@ impl ExprScopes { std::iter::successors(scope, move |&scope| self.scopes[scope].parent) } + pub fn resolve_name_in_scope(&self, scope: ScopeId, name: &Name) -> Option<&ScopeEntry> { + self.scope_chain(Some(scope)) + .find_map(|scope| self.entries(scope).iter().find(|it| it.name == *name)) + } + pub fn scope_for(&self, expr: ExprId) -> Option { self.scope_by_expr.get(&expr).copied() } @@ -163,3 +168,217 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope e => e.walk_child_exprs(|e| compute_expr_scopes(e, body, scopes, scope)), }; } + +#[cfg(test)] +mod tests { + use hir_expand::{name::AsName, Source}; + use ra_db::{fixture::WithFixture, FileId, SourceDatabase}; + use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; + use test_utils::{assert_eq_text, extract_offset}; + + use crate::{db::DefDatabase2, test_db::TestDB, FunctionId, ModuleDefId}; + + fn find_function(db: &TestDB, file_id: FileId) -> FunctionId { + let krate = db.test_crate(); + let crate_def_map = db.crate_def_map(krate); + + let module = crate_def_map.modules_for_file(file_id).next().unwrap(); + let (_, res) = crate_def_map[module].scope.entries().next().unwrap(); + match res.def.take_values().unwrap() { + ModuleDefId::FunctionId(it) => it, + _ => panic!(), + } + } + + fn do_check(code: &str, expected: &[&str]) { + let (off, code) = extract_offset(code); + let code = { + let mut buf = String::new(); + let off = u32::from(off) as usize; + buf.push_str(&code[..off]); + buf.push_str("marker"); + buf.push_str(&code[off..]); + buf + }; + + let (db, file_id) = TestDB::with_single_file(&code); + + let file_syntax = db.parse(file_id).syntax_node(); + let marker: ast::PathExpr = find_node_at_offset(&file_syntax, off).unwrap(); + let function = find_function(&db, file_id); + + let scopes = db.expr_scopes(function.into()); + let (_body, source_map) = db.body_with_source_map(function.into()); + + let expr_id = + source_map.node_expr(Source { file_id: file_id.into(), ast: &marker.into() }).unwrap(); + let scope = scopes.scope_for(expr_id); + + let actual = scopes + .scope_chain(scope) + .flat_map(|scope| scopes.entries(scope)) + .map(|it| it.name().to_string()) + .collect::>() + .join("\n"); + let expected = expected.join("\n"); + assert_eq_text!(&expected, &actual); + } + + #[test] + fn test_lambda_scope() { + do_check( + r" + fn quux(foo: i32) { + let f = |bar, baz: i32| { + <|> + }; + }", + &["bar", "baz", "foo"], + ); + } + + #[test] + fn test_call_scope() { + do_check( + r" + fn quux() { + f(|x| <|> ); + }", + &["x"], + ); + } + + #[test] + fn test_method_call_scope() { + do_check( + r" + fn quux() { + z.f(|x| <|> ); + }", + &["x"], + ); + } + + #[test] + fn test_loop_scope() { + do_check( + r" + fn quux() { + loop { + let x = (); + <|> + }; + }", + &["x"], + ); + } + + #[test] + fn test_match() { + do_check( + r" + fn quux() { + match () { + Some(x) => { + <|> + } + }; + }", + &["x"], + ); + } + + #[test] + fn test_shadow_variable() { + do_check( + r" + fn foo(x: String) { + let x : &str = &x<|>; + }", + &["x"], + ); + } + + fn do_check_local_name(code: &str, expected_offset: u32) { + let (off, code) = extract_offset(code); + + let (db, file_id) = TestDB::with_single_file(&code); + + let file = db.parse(file_id).ok().unwrap(); + let expected_name = find_node_at_offset::(file.syntax(), expected_offset.into()) + .expect("failed to find a name at the target offset"); + let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); + + let function = find_function(&db, file_id); + + let scopes = db.expr_scopes(function.into()); + let (_body, source_map) = db.body_with_source_map(function.into()); + + let expr_scope = { + let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap(); + let expr_id = + source_map.node_expr(Source { file_id: file_id.into(), ast: &expr_ast }).unwrap(); + scopes.scope_for(expr_id).unwrap() + }; + + let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap(); + let pat_src = source_map.pat_syntax(resolved.pat()).unwrap(); + + let local_name = pat_src.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); + assert_eq!(local_name.range(), expected_name.syntax().text_range()); + } + + #[test] + fn test_resolve_local_name() { + do_check_local_name( + r#" + fn foo(x: i32, y: u32) { + { + let z = x * 2; + } + { + let t = x<|> * 3; + } + }"#, + 21, + ); + } + + #[test] + fn test_resolve_local_name_declaration() { + do_check_local_name( + r#" + fn foo(x: String) { + let x : &str = &x<|>; + }"#, + 21, + ); + } + + #[test] + fn test_resolve_local_name_shadow() { + do_check_local_name( + r" + fn foo(x: String) { + let x : &str = &x; + x<|> + } + ", + 53, + ); + } + + #[test] + fn ref_patterns_contribute_bindings() { + do_check_local_name( + r" + fn foo() { + if let Some(&from) = bar() { + from<|>; + } + } + ", + 53, + ); + } +} diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 5fc5921500..21d5f62e04 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -58,7 +58,7 @@ mod tests; use std::sync::Arc; -use hir_expand::{diagnostics::DiagnosticSink, name::Name, MacroDefId}; +use hir_expand::{ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, MacroDefId}; use once_cell::sync::Lazy; use ra_arena::Arena; use ra_db::{CrateId, Edition, FileId}; @@ -73,7 +73,7 @@ use crate::{ diagnostics::DefDiagnostic, path_resolution::ResolveMode, per_ns::PerNs, raw::ImportId, }, path::Path, - AstId, CrateModuleId, ModuleDefId, ModuleId, TraitId, + AstId, CrateModuleId, FunctionId, ModuleDefId, ModuleId, TraitId, }; /// Contains all top-level defs from a macro-expanded crate @@ -124,6 +124,11 @@ pub struct ModuleData { pub definition: Option, } +#[derive(Default, Debug, PartialEq, Eq, Clone)] +pub(crate) struct Declarations { + fns: FxHashMap, FunctionId>, +} + #[derive(Debug, Default, PartialEq, Eq, Clone)] pub struct ModuleScope { pub items: FxHashMap, diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 83eef821f7..5c899aff35 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -664,7 +664,8 @@ where let name = def.name.clone(); let def: PerNs = match def.kind { raw::DefKind::Function(ast_id) => { - PerNs::values(FunctionId::from_ast_id(ctx, ast_id).into()) + let f = FunctionId::from_ast_id(ctx, ast_id); + PerNs::values(f.into()) } raw::DefKind::Struct(ast_id) => { let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); From c3f84960aa99529a3afc8f28c16e657fb071db5f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 14:53:09 +0300 Subject: [PATCH 14/16] Flatten expr module --- crates/ra_hir/src/code_model.rs | 2 +- crates/ra_hir/src/expr.rs | 132 +++++++++++++++++++++++++- crates/ra_hir/src/expr/validation.rs | 137 --------------------------- 3 files changed, 130 insertions(+), 141 deletions(-) delete mode 100644 crates/ra_hir/src/expr/validation.rs diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index dd43271f4c..078bd86090 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -23,7 +23,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; use crate::{ adt::VariantDef, db::{AstDatabase, DefDatabase, HirDatabase}, - expr::{validation::ExprValidator, BindingAnnotation, Body, BodySourceMap, Pat, PatId}, + expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, generics::{GenericDef, HasGenericParams}, ids::{ AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index e4598eec07..e3733779e9 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -1,12 +1,19 @@ //! FIXME: write short doc here -pub(crate) mod validation; - use std::sync::Arc; +use hir_def::path::known; +use hir_expand::diagnostics::DiagnosticSink; +use ra_syntax::ast; use ra_syntax::AstPtr; +use rustc_hash::FxHashSet; -use crate::{db::HirDatabase, DefWithBody, HasBody, Resolver}; +use crate::{ + db::HirDatabase, + diagnostics::{MissingFields, MissingOkInTailExpr}, + ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, + Adt, DefWithBody, Function, HasBody, Name, Path, Resolver, +}; pub use hir_def::{ body::{ @@ -42,3 +49,122 @@ pub(crate) fn resolver_for_scope( } r } + +pub(crate) struct ExprValidator<'a, 'b: 'a> { + func: Function, + infer: Arc, + sink: &'a mut DiagnosticSink<'b>, +} + +impl<'a, 'b> ExprValidator<'a, 'b> { + pub(crate) fn new( + func: Function, + infer: Arc, + sink: &'a mut DiagnosticSink<'b>, + ) -> ExprValidator<'a, 'b> { + ExprValidator { func, infer, sink } + } + + pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) { + let body = self.func.body(db); + + for e in body.exprs() { + if let (id, Expr::RecordLit { path, fields, spread }) = e { + self.validate_record_literal(id, path, fields, *spread, db); + } + } + + let body_expr = &body[body.body_expr()]; + if let Expr::Block { statements: _, tail: Some(t) } = body_expr { + self.validate_results_in_tail_expr(body.body_expr(), *t, db); + } + } + + fn validate_record_literal( + &mut self, + id: ExprId, + _path: &Option, + fields: &[RecordLitField], + spread: Option, + db: &impl HirDatabase, + ) { + if spread.is_some() { + return; + } + + let struct_def = match self.infer[id].as_adt() { + Some((Adt::Struct(s), _)) => s, + _ => return, + }; + + let lit_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); + let missed_fields: Vec = struct_def + .fields(db) + .iter() + .filter_map(|f| { + let name = f.name(db); + if lit_fields.contains(&name) { + None + } else { + Some(name) + } + }) + .collect(); + if missed_fields.is_empty() { + return; + } + let source_map = self.func.body_source_map(db); + + if let Some(source_ptr) = source_map.expr_syntax(id) { + if let Some(expr) = source_ptr.ast.a() { + let root = source_ptr.file_syntax(db); + if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { + if let Some(field_list) = record_lit.record_field_list() { + self.sink.push(MissingFields { + file: source_ptr.file_id, + field_list: AstPtr::new(&field_list), + missed_fields, + }) + } + } + } + } + } + + fn validate_results_in_tail_expr( + &mut self, + body_id: ExprId, + id: ExprId, + db: &impl HirDatabase, + ) { + // the mismatch will be on the whole block currently + let mismatch = match self.infer.type_mismatch_for_expr(body_id) { + Some(m) => m, + None => return, + }; + + let std_result_path = known::std_result_result(); + + let resolver = self.func.resolver(db); + let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { + Some(it) => it, + _ => return, + }; + + let std_result_ctor = TypeCtor::Adt(Adt::Enum(std_result_enum)); + let params = match &mismatch.expected { + Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters, + _ => return, + }; + + if params.len() == 2 && ¶ms[0] == &mismatch.actual { + let source_map = self.func.body_source_map(db); + + if let Some(source_ptr) = source_map.expr_syntax(id) { + if let Some(expr) = source_ptr.ast.a() { + self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); + } + } + } + } +} diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs deleted file mode 100644 index 3054f1dced..0000000000 --- a/crates/ra_hir/src/expr/validation.rs +++ /dev/null @@ -1,137 +0,0 @@ -//! FIXME: write short doc here - -use std::sync::Arc; - -use hir_def::path::known; -use hir_expand::diagnostics::DiagnosticSink; -use ra_syntax::ast; -use rustc_hash::FxHashSet; - -use crate::{ - db::HirDatabase, - diagnostics::{MissingFields, MissingOkInTailExpr}, - expr::AstPtr, - ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, - Adt, Function, Name, Path, -}; - -use super::{Expr, ExprId, RecordLitField}; - -pub(crate) struct ExprValidator<'a, 'b: 'a> { - func: Function, - infer: Arc, - sink: &'a mut DiagnosticSink<'b>, -} - -impl<'a, 'b> ExprValidator<'a, 'b> { - pub(crate) fn new( - func: Function, - infer: Arc, - sink: &'a mut DiagnosticSink<'b>, - ) -> ExprValidator<'a, 'b> { - ExprValidator { func, infer, sink } - } - - pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) { - let body = self.func.body(db); - - for e in body.exprs() { - if let (id, Expr::RecordLit { path, fields, spread }) = e { - self.validate_record_literal(id, path, fields, *spread, db); - } - } - - let body_expr = &body[body.body_expr()]; - if let Expr::Block { statements: _, tail: Some(t) } = body_expr { - self.validate_results_in_tail_expr(body.body_expr(), *t, db); - } - } - - fn validate_record_literal( - &mut self, - id: ExprId, - _path: &Option, - fields: &[RecordLitField], - spread: Option, - db: &impl HirDatabase, - ) { - if spread.is_some() { - return; - } - - let struct_def = match self.infer[id].as_adt() { - Some((Adt::Struct(s), _)) => s, - _ => return, - }; - - let lit_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); - let missed_fields: Vec = struct_def - .fields(db) - .iter() - .filter_map(|f| { - let name = f.name(db); - if lit_fields.contains(&name) { - None - } else { - Some(name) - } - }) - .collect(); - if missed_fields.is_empty() { - return; - } - let source_map = self.func.body_source_map(db); - - if let Some(source_ptr) = source_map.expr_syntax(id) { - if let Some(expr) = source_ptr.ast.a() { - let root = source_ptr.file_syntax(db); - if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { - if let Some(field_list) = record_lit.record_field_list() { - self.sink.push(MissingFields { - file: source_ptr.file_id, - field_list: AstPtr::new(&field_list), - missed_fields, - }) - } - } - } - } - } - - fn validate_results_in_tail_expr( - &mut self, - body_id: ExprId, - id: ExprId, - db: &impl HirDatabase, - ) { - // the mismatch will be on the whole block currently - let mismatch = match self.infer.type_mismatch_for_expr(body_id) { - Some(m) => m, - None => return, - }; - - let std_result_path = known::std_result_result(); - - let resolver = self.func.resolver(db); - let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { - Some(it) => it, - _ => return, - }; - - let std_result_ctor = TypeCtor::Adt(Adt::Enum(std_result_enum)); - let params = match &mismatch.expected { - Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters, - _ => return, - }; - - if params.len() == 2 && ¶ms[0] == &mismatch.actual { - let source_map = self.func.body_source_map(db); - - if let Some(source_ptr) = source_map.expr_syntax(id) { - if let Some(expr) = source_ptr.ast.a() { - self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); - } - } - } - } -} From 5476c4faa34ae2ec8f736ec21e3965ed8e33c225 Mon Sep 17 00:00:00 2001 From: memoryruins Date: Fri, 15 Nov 2019 06:45:58 -0500 Subject: [PATCH 15/16] Update smallvec dep to 1.0 --- Cargo.lock | 8 +++++++- crates/ra_mbe/Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1dedf97721..d7ec266c0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1135,7 +1135,7 @@ dependencies = [ "ra_syntax 0.1.0", "ra_tt 0.1.0", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", ] @@ -1603,6 +1603,11 @@ dependencies = [ "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "smallvec" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "smol_str" version = "0.1.15" @@ -2007,6 +2012,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" "checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" "checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a" "checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" diff --git a/crates/ra_mbe/Cargo.toml b/crates/ra_mbe/Cargo.toml index e8ef2457bb..b02e45ee39 100644 --- a/crates/ra_mbe/Cargo.toml +++ b/crates/ra_mbe/Cargo.toml @@ -9,7 +9,7 @@ ra_syntax = { path = "../ra_syntax" } ra_parser = { path = "../ra_parser" } tt = { path = "../ra_tt", package = "ra_tt" } rustc-hash = "1.0.0" -smallvec = "0.6.9" +smallvec = "1.0.0" log = "0.4.5" [dev-dependencies] From a5f57f98ca4c0afb1c292da6676a1273ce95f0e0 Mon Sep 17 00:00:00 2001 From: memoryruins Date: Fri, 15 Nov 2019 06:53:11 -0500 Subject: [PATCH 16/16] Heed the advice of rustc's into_iter() warning --- crates/ra_hir_expand/src/quote.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/ra_hir_expand/src/quote.rs b/crates/ra_hir_expand/src/quote.rs index 9cd17f0e35..35133d2164 100644 --- a/crates/ra_hir_expand/src/quote.rs +++ b/crates/ra_hir_expand/src/quote.rs @@ -241,10 +241,8 @@ mod tests { // } let struct_name = mk_ident("Foo"); let fields = [mk_ident("name"), mk_ident("id")]; - let fields = fields - .into_iter() - .map(|it| quote!(#it: self.#it.clone(), ).token_trees.clone()) - .flatten(); + let fields = + fields.iter().map(|it| quote!(#it: self.#it.clone(), ).token_trees.clone()).flatten(); let list = tt::Subtree { delimiter: tt::Delimiter::Brace, token_trees: fields.collect() };